Merge "mw.language.convertPlural: Check if matching form exists"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 4 Dec 2013 08:34:43 +0000 (08:34 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 4 Dec 2013 08:34:43 +0000 (08:34 +0000)
1112 files changed:
.gitignore
CREDITS
FAQ
HISTORY
RELEASE-NOTES-1.22
RELEASE-NOTES-1.23 [new file with mode: 0644]
cache/.htaccess [changed mode: 0755->0644]
composer-example.json [new file with mode: 0644]
composer.json [deleted file]
docs/README
docs/hooks.txt
docs/maintenance.txt
docs/memcached.txt
extensions/README
img_auth.php
includes/Action.php
includes/ArrayUtils.php [deleted file]
includes/Article.php
includes/AuthPlugin.php
includes/AutoLoader.php
includes/Block.php
includes/CallableUpdate.php [deleted file]
includes/Cdb.php [deleted file]
includes/Cdb_PHP.php [deleted file]
includes/ChangeTags.php
includes/Collation.php
includes/ConfEditor.php [deleted file]
includes/Cookie.php
includes/DataUpdate.php [deleted file]
includes/DefaultSettings.php
includes/DeferredUpdates.php [deleted file]
includes/DeprecatedGlobal.php
includes/EditPage.php
includes/Exception.php
includes/Export.php
includes/FormOptions.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/HTMLForm.php
includes/HashRing.php [deleted file]
includes/HistoryBlob.php
includes/Hooks.php
includes/Html.php
includes/HtmlFormatter.php
includes/HttpFunctions.php
includes/IP.php [deleted file]
includes/ImagePage.php
includes/Init.php
includes/LinkFilter.php
includes/Linker.php
includes/LinksUpdate.php [deleted file]
includes/MWCryptRand.php [deleted file]
includes/MWFunction.php [deleted file]
includes/MappedIterator.php [deleted file]
includes/Message.php
includes/Metadata.php
includes/MimeMagic.php
includes/Namespace.php
includes/OutputPage.php
includes/PHPVersionError.php
includes/PageQueryPage.php
includes/Pager.php
includes/Preferences.php
includes/ProtectionForm.php
includes/ProxyTools.php
includes/Revision.php
includes/Sanitizer.php
includes/ScopedCallback.php [deleted file]
includes/ScopedPHPTimeout.php [deleted file]
includes/Setup.php
includes/SiteStats.php
includes/Skin.php
includes/SkinTemplate.php
includes/SpecialPage.php
includes/SpecialPageFactory.php
includes/SqlDataUpdate.php [deleted file]
includes/Status.php
includes/StreamFile.php
includes/StringUtils.php [deleted file]
includes/Timestamp.php
includes/Title.php
includes/UIDGenerator.php [deleted file]
includes/User.php
includes/UserMailer.php
includes/ViewCountUpdate.php [deleted file]
includes/WatchedItem.php
includes/WebRequest.php
includes/Wiki.php
includes/WikiFilePage.php
includes/WikiPage.php
includes/Xml.php
includes/XmlTypeCheck.php [deleted file]
includes/ZipDirectoryReader.php [deleted file]
includes/actions/CachedAction.php
includes/actions/CreditsAction.php
includes/actions/DeleteAction.php
includes/actions/EditAction.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/MarkpatrolledAction.php
includes/actions/ProtectAction.php
includes/actions/RawAction.php
includes/actions/RenderAction.php
includes/actions/RevertAction.php
includes/actions/RevisiondeleteAction.php
includes/actions/RollbackAction.php
includes/actions/ViewAction.php
includes/actions/WatchAction.php
includes/api/ApiBase.php
includes/api/ApiBlock.php
includes/api/ApiComparePages.php
includes/api/ApiCreateAccount.php
includes/api/ApiDelete.php
includes/api/ApiEditPage.php
includes/api/ApiEmailUser.php
includes/api/ApiFeedContributions.php
includes/api/ApiFeedWatchlist.php
includes/api/ApiFileRevert.php
includes/api/ApiFormatBase.php
includes/api/ApiFormatJson.php
includes/api/ApiFormatRaw.php
includes/api/ApiFormatWddx.php
includes/api/ApiFormatXml.php
includes/api/ApiHelp.php
includes/api/ApiImageRotate.php
includes/api/ApiImport.php
includes/api/ApiLogin.php
includes/api/ApiMain.php
includes/api/ApiModuleManager.php
includes/api/ApiMove.php
includes/api/ApiOpenSearch.php
includes/api/ApiOptions.php
includes/api/ApiPageSet.php
includes/api/ApiParamInfo.php
includes/api/ApiParse.php
includes/api/ApiPatrol.php
includes/api/ApiProtect.php
includes/api/ApiPurge.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllCategories.php
includes/api/ApiQueryAllImages.php
includes/api/ApiQueryAllLinks.php
includes/api/ApiQueryAllMessages.php
includes/api/ApiQueryAllPages.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryBlocks.php
includes/api/ApiQueryCategories.php
includes/api/ApiQueryCategoryInfo.php
includes/api/ApiQueryCategoryMembers.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryDuplicateFiles.php
includes/api/ApiQueryExtLinksUsage.php
includes/api/ApiQueryExternalLinks.php
includes/api/ApiQueryFileRepoInfo.php
includes/api/ApiQueryFilearchive.php
includes/api/ApiQueryIWBacklinks.php
includes/api/ApiQueryIWLinks.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryImages.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryLangBacklinks.php
includes/api/ApiQueryLangLinks.php
includes/api/ApiQueryLinks.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryORM.php
includes/api/ApiQueryPagePropNames.php
includes/api/ApiQueryPageProps.php
includes/api/ApiQueryPagesWithProp.php
includes/api/ApiQueryProtectedTitles.php
includes/api/ApiQueryQueryPage.php
includes/api/ApiQueryRandom.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQuerySearch.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryTags.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiQueryUsers.php
includes/api/ApiQueryWatchlist.php
includes/api/ApiQueryWatchlistRaw.php
includes/api/ApiResult.php
includes/api/ApiRollback.php
includes/api/ApiRsd.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiTokens.php
includes/api/ApiUnblock.php
includes/api/ApiUndelete.php
includes/api/ApiUpload.php
includes/api/ApiUserrights.php
includes/api/ApiWatch.php
includes/cache/BacklinkCache.php
includes/cache/CacheDependency.php
includes/cache/FileCacheBase.php
includes/cache/GenderCache.php
includes/cache/HTMLCacheUpdate.php [deleted file]
includes/cache/HTMLFileCache.php
includes/cache/LinkBatch.php
includes/cache/LinkCache.php
includes/cache/LocalisationCache.php
includes/cache/MapCacheLRU.php [new file with mode: 0644]
includes/cache/MessageCache.php
includes/cache/ProcessCacheLRU.php
includes/cache/ResourceFileCache.php
includes/cache/SquidUpdate.php [deleted file]
includes/cache/UserCache.php
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/changes/RCCacheEntry.php
includes/changes/RecentChange.php
includes/clientpool/RedisConnectionPool.php
includes/content/AbstractContent.php
includes/content/Content.php
includes/content/ContentHandler.php
includes/content/CssContentHandler.php
includes/content/JavaScriptContentHandler.php
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/TextContentHandler.php
includes/content/WikitextContent.php
includes/content/WikitextContentHandler.php
includes/context/ContextSource.php
includes/context/DerivativeContext.php
includes/context/RequestContext.php
includes/dao/DBAccessBase.php
includes/db/ChronologyProtector.php
includes/db/CloneDatabase.php
includes/db/Database.php
includes/db/DatabaseError.php
includes/db/DatabaseMssql.php
includes/db/DatabaseMysql.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabaseMysqli.php
includes/db/DatabaseOracle.php
includes/db/DatabasePostgres.php
includes/db/DatabaseSqlite.php
includes/db/DatabaseUtility.php
includes/db/IORMRow.php
includes/db/IORMTable.php
includes/db/LBFactory.php
includes/db/LBFactory_Multi.php
includes/db/LoadBalancer.php
includes/db/LoadMonitor.php
includes/db/ORMIterator.php
includes/db/ORMResult.php
includes/db/ORMRow.php
includes/db/ORMTable.php
includes/debug/Debug.php
includes/deferred/CallableUpdate.php [new file with mode: 0644]
includes/deferred/DataUpdate.php [new file with mode: 0644]
includes/deferred/DeferredUpdates.php [new file with mode: 0644]
includes/deferred/HTMLCacheUpdate.php [new file with mode: 0644]
includes/deferred/LinksUpdate.php [new file with mode: 0644]
includes/deferred/SearchUpdate.php [new file with mode: 0644]
includes/deferred/SiteStatsUpdate.php [new file with mode: 0644]
includes/deferred/SqlDataUpdate.php [new file with mode: 0644]
includes/deferred/SquidUpdate.php [new file with mode: 0644]
includes/deferred/ViewCountUpdate.php [new file with mode: 0644]
includes/diff/ArrayDiffFormatter.php [new file with mode: 0644]
includes/diff/DairikiDiff.php
includes/diff/DiffFormatter.php [new file with mode: 0644]
includes/diff/DifferenceEngine.php
includes/diff/TableDiffFormatter.php [new file with mode: 0644]
includes/diff/UnifiedDiffFormatter.php [new file with mode: 0644]
includes/diff/WikiDiff3.php
includes/externalstore/ExternalStore.php
includes/externalstore/ExternalStoreDB.php
includes/externalstore/ExternalStoreMedium.php
includes/externalstore/ExternalStoreMwstore.php
includes/filebackend/FSFile.php
includes/filebackend/FSFileBackend.php
includes/filebackend/FileBackend.php
includes/filebackend/FileBackendGroup.php
includes/filebackend/FileBackendMultiWrite.php
includes/filebackend/FileBackendStore.php
includes/filebackend/FileOp.php
includes/filebackend/FileOpBatch.php
includes/filebackend/SwiftFileBackend.php
includes/filebackend/TempFSFile.php
includes/filebackend/filejournal/DBFileJournal.php
includes/filebackend/filejournal/FileJournal.php
includes/filebackend/lockmanager/DBLockManager.php
includes/filebackend/lockmanager/FSLockManager.php
includes/filebackend/lockmanager/LSLockManager.php
includes/filebackend/lockmanager/LockManager.php
includes/filebackend/lockmanager/LockManagerGroup.php
includes/filebackend/lockmanager/MemcLockManager.php
includes/filebackend/lockmanager/QuorumLockManager.php
includes/filebackend/lockmanager/RedisLockManager.php
includes/filebackend/lockmanager/ScopedLock.php
includes/filerepo/FSRepo.php
includes/filerepo/FileRepo.php
includes/filerepo/FileRepoStatus.php
includes/filerepo/ForeignAPIRepo.php
includes/filerepo/ForeignDBRepo.php
includes/filerepo/ForeignDBViaLBRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/NullRepo.php
includes/filerepo/RepoGroup.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/ForeignAPIFile.php
includes/filerepo/file/ForeignDBFile.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/filerepo/file/UnregisteredLocalFile.php
includes/gallery/ImageGalleryBase.php
includes/gallery/NolinesImageGallery.php
includes/gallery/PackedImageGallery.php
includes/gallery/PackedOverlayImageGallery.php
includes/gallery/TraditionalImageGallery.php
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.i18n.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/MysqlInstaller.php
includes/installer/MysqlUpdater.php
includes/installer/OracleInstaller.php
includes/installer/OracleUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerOutput.php
includes/installer/WebInstallerPage.php
includes/interwiki/Interwiki.php
includes/job/Job.php
includes/job/JobQueue.php
includes/job/JobQueueDB.php
includes/job/JobQueueFederated.php
includes/job/JobQueueGroup.php
includes/job/JobQueueRedis.php
includes/job/aggregator/JobQueueAggregator.php
includes/job/aggregator/JobQueueAggregatorMemc.php
includes/job/aggregator/JobQueueAggregatorRedis.php
includes/job/jobs/AssembleUploadChunksJob.php
includes/job/jobs/DoubleRedirectJob.php
includes/job/jobs/DuplicateJob.php
includes/job/jobs/EmaillingJob.php
includes/job/jobs/EnotifNotifyJob.php
includes/job/jobs/HTMLCacheUpdateJob.php
includes/job/jobs/NullJob.php
includes/job/jobs/PublishStashedFileJob.php
includes/job/jobs/RefreshLinksJob.php
includes/job/jobs/RefreshLinksJob2.php [new file with mode: 0644]
includes/job/jobs/UploadFromUrlJob.php
includes/job/utils/BacklinkJobUtils.php [new file with mode: 0644]
includes/json/FormatJson.php
includes/libs/CSSMin.php
includes/libs/ScopedPHPTimeout.php [new file with mode: 0644]
includes/libs/XmlTypeCheck.php [new file with mode: 0644]
includes/limit.sh
includes/logging/DeleteLogFormatter.php
includes/logging/LogEntry.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/logging/LogPage.php
includes/logging/LogPager.php
includes/logging/MoveLogFormatter.php
includes/logging/NewUsersLogFormatter.php
includes/logging/PatrolLog.php
includes/logging/PatrolLogFormatter.php
includes/logging/RightsLogFormatter.php
includes/media/Bitmap.php
includes/media/BitmapMetadataHandler.php
includes/media/Exif.php
includes/media/ExifBitmap.php
includes/media/FormatMetadata.php
includes/media/GIF.php
includes/media/GIFMetadataExtractor.php
includes/media/IPTC.php
includes/media/ImageHandler.php
includes/media/MediaHandler.php
includes/media/PNG.php
includes/media/SVG.php
includes/media/SVGMetadataExtractor.php
includes/media/XCF.php
includes/media/XMP.php
includes/media/XMPInfo.php
includes/normal/UtfNormalTest.php
includes/objectcache/MemcachedClient.php
includes/objectcache/RedisBagOStuff.php
includes/objectcache/SqlBagOStuff.php
includes/parser/CacheTime.php
includes/parser/CoreParserFunctions.php
includes/parser/LinkHolderArray.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/parser/Tidy.php
includes/profiler/Profiler.php
includes/profiler/ProfilerSimpleUDP.php
includes/rcfeed/JSONRCFeedFormatter.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderUserGroupsModule.php
includes/resourceloader/ResourceLoaderUserModule.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/revisiondelete/RevisionDeleter.php
includes/search/SearchUpdate.php [deleted file]
includes/specials/SpecialAllpages.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialConfirmemail.php
includes/specials/SpecialContributions.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialExpandTemplates.php [new file with mode: 0644]
includes/specials/SpecialImport.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListfiles.php
includes/specials/SpecialListredirects.php
includes/specials/SpecialLog.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRecentchangeslinked.php
includes/specials/SpecialResetTokens.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialSearch.php
includes/specials/SpecialSpecialpages.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUploadStash.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialWatchlist.php
includes/templates/NoLocalSettings.php
includes/templates/Usercreate.php
includes/templates/Userlogin.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/upload/UploadFromStash.php
includes/upload/UploadStash.php
includes/utils/ArrayUtils.php [new file with mode: 0644]
includes/utils/Cdb.php [new file with mode: 0644]
includes/utils/CdbDBA.php [new file with mode: 0644]
includes/utils/CdbPHP.php [new file with mode: 0644]
includes/utils/ConfEditor.php [new file with mode: 0644]
includes/utils/HashRing.php [new file with mode: 0644]
includes/utils/IP.php [new file with mode: 0644]
includes/utils/MWCryptRand.php [new file with mode: 0644]
includes/utils/MWFunction.php [new file with mode: 0644]
includes/utils/MappedIterator.php [new file with mode: 0644]
includes/utils/README [new file with mode: 0644]
includes/utils/ScopedCallback.php [new file with mode: 0644]
includes/utils/StringUtils.php [new file with mode: 0644]
includes/utils/UIDGenerator.php [new file with mode: 0644]
includes/utils/ZipDirectoryReader.php [new file with mode: 0644]
index.php
languages/Language.php
languages/LanguageConverter.php
languages/Names.php
languages/classes/LanguageBe_tarask.php
languages/classes/LanguageBs.php
languages/classes/LanguageDsb.php
languages/classes/LanguageGv.php
languages/classes/LanguageHr.php
languages/classes/LanguageHsb.php
languages/classes/LanguageKk_cyrl.php
languages/classes/LanguageKsh.php
languages/classes/LanguageOs.php
languages/classes/LanguageRu.php
languages/classes/LanguageSr.php
languages/classes/LanguageSr_ec.php
languages/classes/LanguageSr_el.php
languages/classes/LanguageTr.php
languages/classes/LanguageTyv.php
languages/classes/LanguageUk.php
languages/messages/MessagesAce.php
languages/messages/MessagesAeb.php
languages/messages/MessagesAf.php
languages/messages/MessagesAk.php
languages/messages/MessagesAln.php
languages/messages/MessagesAm.php
languages/messages/MessagesAn.php
languages/messages/MessagesAng.php
languages/messages/MessagesAr.php
languages/messages/MessagesArc.php
languages/messages/MessagesArn.php
languages/messages/MessagesAry.php
languages/messages/MessagesArz.php
languages/messages/MessagesAs.php
languages/messages/MessagesAst.php
languages/messages/MessagesAvk.php
languages/messages/MessagesAz.php
languages/messages/MessagesAzb.php
languages/messages/MessagesBa.php
languages/messages/MessagesBar.php
languages/messages/MessagesBcc.php
languages/messages/MessagesBcl.php
languages/messages/MessagesBe.php
languages/messages/MessagesBe_tarask.php
languages/messages/MessagesBg.php
languages/messages/MessagesBho.php
languages/messages/MessagesBjn.php
languages/messages/MessagesBn.php
languages/messages/MessagesBo.php
languages/messages/MessagesBpy.php
languages/messages/MessagesBr.php
languages/messages/MessagesBs.php
languages/messages/MessagesCa.php
languages/messages/MessagesCdo.php
languages/messages/MessagesCe.php
languages/messages/MessagesCeb.php
languages/messages/MessagesCh.php
languages/messages/MessagesCkb.php
languages/messages/MessagesCps.php
languages/messages/MessagesCrh_cyrl.php
languages/messages/MessagesCrh_latn.php
languages/messages/MessagesCs.php
languages/messages/MessagesCsb.php
languages/messages/MessagesCu.php
languages/messages/MessagesCv.php
languages/messages/MessagesCy.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesDsb.php
languages/messages/MessagesDtp.php
languages/messages/MessagesDv.php
languages/messages/MessagesEl.php
languages/messages/MessagesEn.php
languages/messages/MessagesEo.php
languages/messages/MessagesEs.php
languages/messages/MessagesEt.php
languages/messages/MessagesEu.php
languages/messages/MessagesExt.php
languages/messages/MessagesFa.php
languages/messages/MessagesFi.php
languages/messages/MessagesFo.php
languages/messages/MessagesFr.php
languages/messages/MessagesFrp.php
languages/messages/MessagesFrr.php
languages/messages/MessagesFur.php
languages/messages/MessagesFy.php
languages/messages/MessagesGa.php
languages/messages/MessagesGag.php
languages/messages/MessagesGan_hans.php
languages/messages/MessagesGan_hant.php
languages/messages/MessagesGd.php
languages/messages/MessagesGl.php
languages/messages/MessagesGom_latn.php [new file with mode: 0644]
languages/messages/MessagesGrc.php
languages/messages/MessagesGsw.php
languages/messages/MessagesGu.php
languages/messages/MessagesGv.php
languages/messages/MessagesHak.php
languages/messages/MessagesHaw.php
languages/messages/MessagesHe.php
languages/messages/MessagesHi.php
languages/messages/MessagesHif_latn.php
languages/messages/MessagesHil.php
languages/messages/MessagesHr.php
languages/messages/MessagesHsb.php
languages/messages/MessagesHt.php
languages/messages/MessagesHu.php
languages/messages/MessagesHy.php
languages/messages/MessagesIa.php
languages/messages/MessagesId.php
languages/messages/MessagesIe.php
languages/messages/MessagesIg.php
languages/messages/MessagesIlo.php
languages/messages/MessagesInh.php
languages/messages/MessagesIo.php
languages/messages/MessagesIs.php
languages/messages/MessagesIt.php
languages/messages/MessagesJa.php
languages/messages/MessagesJam.php
languages/messages/MessagesJv.php
languages/messages/MessagesKa.php
languages/messages/MessagesKaa.php
languages/messages/MessagesKab.php
languages/messages/MessagesKbd_cyrl.php
languages/messages/MessagesKhw.php
languages/messages/MessagesKiu.php
languages/messages/MessagesKk_arab.php
languages/messages/MessagesKk_cyrl.php
languages/messages/MessagesKk_latn.php
languages/messages/MessagesKm.php
languages/messages/MessagesKn.php
languages/messages/MessagesKo.php
languages/messages/MessagesKoi.php
languages/messages/MessagesKrc.php
languages/messages/MessagesKsh.php
languages/messages/MessagesKu_latn.php
languages/messages/MessagesKw.php
languages/messages/MessagesKy.php
languages/messages/MessagesLa.php
languages/messages/MessagesLad.php
languages/messages/MessagesLb.php
languages/messages/MessagesLez.php
languages/messages/MessagesLfn.php
languages/messages/MessagesLg.php
languages/messages/MessagesLi.php
languages/messages/MessagesLij.php
languages/messages/MessagesLiv.php
languages/messages/MessagesLmo.php
languages/messages/MessagesLo.php
languages/messages/MessagesLoz.php
languages/messages/MessagesLrc.php [new file with mode: 0644]
languages/messages/MessagesLt.php
languages/messages/MessagesLtg.php
languages/messages/MessagesLus.php
languages/messages/MessagesLv.php
languages/messages/MessagesLzh.php
languages/messages/MessagesMai.php
languages/messages/MessagesMap_bms.php
languages/messages/MessagesMdf.php
languages/messages/MessagesMg.php
languages/messages/MessagesMhr.php
languages/messages/MessagesMin.php
languages/messages/MessagesMk.php
languages/messages/MessagesMl.php
languages/messages/MessagesMn.php
languages/messages/MessagesMr.php
languages/messages/MessagesMs.php
languages/messages/MessagesMt.php
languages/messages/MessagesMwl.php
languages/messages/MessagesMy.php
languages/messages/MessagesMyv.php
languages/messages/MessagesMzn.php
languages/messages/MessagesNah.php
languages/messages/MessagesNan.php
languages/messages/MessagesNap.php
languages/messages/MessagesNb.php
languages/messages/MessagesNds.php
languages/messages/MessagesNds_nl.php
languages/messages/MessagesNe.php
languages/messages/MessagesNl.php
languages/messages/MessagesNn.php
languages/messages/MessagesNso.php
languages/messages/MessagesOc.php
languages/messages/MessagesOr.php
languages/messages/MessagesOs.php
languages/messages/MessagesPa.php
languages/messages/MessagesPam.php
languages/messages/MessagesPcd.php
languages/messages/MessagesPdc.php
languages/messages/MessagesPfl.php
languages/messages/MessagesPl.php
languages/messages/MessagesPms.php
languages/messages/MessagesPnb.php
languages/messages/MessagesPnt.php
languages/messages/MessagesPrg.php
languages/messages/MessagesPs.php
languages/messages/MessagesPt.php
languages/messages/MessagesPt_br.php
languages/messages/MessagesQqq.php
languages/messages/MessagesQu.php
languages/messages/MessagesQug.php
languages/messages/MessagesRm.php
languages/messages/MessagesRo.php
languages/messages/MessagesRoa_tara.php
languages/messages/MessagesRu.php
languages/messages/MessagesRue.php
languages/messages/MessagesSa.php
languages/messages/MessagesSah.php
languages/messages/MessagesSat.php
languages/messages/MessagesSc.php
languages/messages/MessagesScn.php
languages/messages/MessagesSco.php
languages/messages/MessagesSd.php
languages/messages/MessagesSdc.php
languages/messages/MessagesSe.php
languages/messages/MessagesSei.php
languages/messages/MessagesSgs.php
languages/messages/MessagesSh.php
languages/messages/MessagesShi.php
languages/messages/MessagesSi.php
languages/messages/MessagesSk.php
languages/messages/MessagesSl.php
languages/messages/MessagesSli.php
languages/messages/MessagesSo.php
languages/messages/MessagesSq.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesSr_el.php
languages/messages/MessagesSrn.php
languages/messages/MessagesStq.php
languages/messages/MessagesSu.php
languages/messages/MessagesSv.php
languages/messages/MessagesSw.php
languages/messages/MessagesSzl.php
languages/messages/MessagesTa.php
languages/messages/MessagesTcy.php
languages/messages/MessagesTe.php
languages/messages/MessagesTet.php
languages/messages/MessagesTg_cyrl.php
languages/messages/MessagesTg_latn.php
languages/messages/MessagesTh.php
languages/messages/MessagesTk.php
languages/messages/MessagesTl.php
languages/messages/MessagesTly.php
languages/messages/MessagesTo.php
languages/messages/MessagesTpi.php
languages/messages/MessagesTr.php
languages/messages/MessagesTru.php
languages/messages/MessagesTs.php
languages/messages/MessagesTt_cyrl.php
languages/messages/MessagesTt_latn.php
languages/messages/MessagesTyv.php
languages/messages/MessagesUdm.php
languages/messages/MessagesUg_arab.php
languages/messages/MessagesUk.php
languages/messages/MessagesUr.php
languages/messages/MessagesUz.php
languages/messages/MessagesVec.php
languages/messages/MessagesVep.php
languages/messages/MessagesVi.php
languages/messages/MessagesVmf.php
languages/messages/MessagesVo.php
languages/messages/MessagesVot.php
languages/messages/MessagesVro.php
languages/messages/MessagesWa.php
languages/messages/MessagesWar.php
languages/messages/MessagesWo.php
languages/messages/MessagesWuu.php
languages/messages/MessagesXal.php
languages/messages/MessagesXmf.php
languages/messages/MessagesYi.php
languages/messages/MessagesYo.php
languages/messages/MessagesYue.php
languages/messages/MessagesZea.php
languages/messages/MessagesZh_hans.php
languages/messages/MessagesZh_hant.php
languages/messages/MessagesZh_tw.php
languages/utils/CLDRPluralRuleEvaluator.php
maintenance/Maintenance.php
maintenance/archives/patch-rc_source.sql [new file with mode: 0644]
maintenance/archives/patch-val_ip.sql [deleted file]
maintenance/archives/patch-validate.sql [deleted file]
maintenance/backup.inc
maintenance/backupTextPass.inc
maintenance/benchmarks/bench_wfIsWindows.php
maintenance/cdb.php
maintenance/cleanupUploadStash.php
maintenance/copyFileBackend.php
maintenance/dictionary/mediawiki.dic
maintenance/doMaintenance.php
maintenance/dumpIterator.php
maintenance/dumpTextPass.php
maintenance/dumpUploads.php
maintenance/eval.php
maintenance/findHooks.php
maintenance/fuzz-tester.php [deleted file]
maintenance/generateSitemap.php
maintenance/importTextFile.php
maintenance/jsduck/categories.json
maintenance/jsduck/config.json
maintenance/jsduck/external.js
maintenance/language/StatOutputs.php
maintenance/language/checkDupeMessages.php
maintenance/language/checkLanguage.inc
maintenance/language/countMessages.php
maintenance/language/generateCollationData.php
maintenance/language/generateNormalizerData.php
maintenance/language/langmemusage.php
maintenance/language/languages.inc
maintenance/language/messageTypes.inc
maintenance/language/messages.inc
maintenance/language/rebuildLanguage.php
maintenance/language/transstat.php
maintenance/language/validate.php
maintenance/language/writeMessagesArray.inc
maintenance/language/zhtable/trad2simp_supp_unset.manual [deleted file]
maintenance/locking/LockServerDaemon.php
maintenance/mctest.php
maintenance/mergeMessageFileList.php
maintenance/moveBatch.php
maintenance/mssql/tables.sql
maintenance/mwjsduck-gen
maintenance/nextJobDB.php
maintenance/oracle/archives/patch_16_17_schema_changes.sql
maintenance/oracle/tables.sql
maintenance/parse.php
maintenance/populateRecentChangesSource.php [new file with mode: 0644]
maintenance/populateRevisionLength.php
maintenance/postgres/mediawiki_mysql2postgres.pl
maintenance/postgres/tables.sql
maintenance/pruneFileCache.php
maintenance/purgeChangedFiles.php
maintenance/reassignEdits.php
maintenance/rebuildImages.php
maintenance/rebuildLocalisationCache.php
maintenance/rebuildrecentchanges.php
maintenance/refreshImageMetadata.php
maintenance/runBatchedQuery.php
maintenance/runScript.php [new file with mode: 0644]
maintenance/showCacheStats.php
maintenance/sqlite/archives/initial-indexes.sql
maintenance/storage/checkStorage.php
maintenance/storage/compressOld.php
maintenance/storage/fixBug20757.php
maintenance/storage/testCompression.php
maintenance/storage/trackBlobs.php
maintenance/tables.sql
maintenance/update.php
maintenance/updateCollation.php
maintenance/userDupes.inc
maintenance/userOptions.inc
maintenance/userOptions.php
resources/Resources.php
resources/jquery/jquery.makeCollapsible.css
resources/jquery/jquery.makeCollapsible.js
resources/jquery/jquery.placeholder.js
resources/jquery/jquery.spinner.js
resources/mediawiki.action/mediawiki.action.edit.js
resources/mediawiki.page/mediawiki.page.image.pagination.js
resources/mediawiki.page/mediawiki.page.watch.ajax.js
resources/mediawiki.special/mediawiki.special.changeemail.js
resources/mediawiki.special/mediawiki.special.changeslist.css
resources/mediawiki.special/mediawiki.special.createAccount.js
resources/mediawiki.special/mediawiki.special.preferences.css
resources/mediawiki.special/mediawiki.special.userLogin.css
resources/mediawiki.special/mediawiki.special.vforms.css
resources/mediawiki.ui/components/default/buttons.less [new file with mode: 0644]
resources/mediawiki.ui/components/default/forms.less [new file with mode: 0644]
resources/mediawiki.ui/components/utilities.less [new file with mode: 0644]
resources/mediawiki.ui/components/vector/buttons.less [new file with mode: 0644]
resources/mediawiki.ui/components/vector/containers.less [new file with mode: 0644]
resources/mediawiki.ui/components/vector/forms.less [new file with mode: 0644]
resources/mediawiki.ui/default.less [new file with mode: 0644]
resources/mediawiki.ui/mediawiki.ui.default.css [deleted file]
resources/mediawiki.ui/mediawiki.ui.vector.css [deleted file]
resources/mediawiki.ui/mixins/effects.less [new file with mode: 0644]
resources/mediawiki.ui/mixins/forms.less [new file with mode: 0644]
resources/mediawiki.ui/mixins/type.less [new file with mode: 0644]
resources/mediawiki.ui/mixins/utilities.less [new file with mode: 0644]
resources/mediawiki.ui/settings/colors.less [new file with mode: 0644]
resources/mediawiki.ui/settings/typography.less [new file with mode: 0644]
resources/mediawiki.ui/sourcefiles/Makefile [deleted file]
resources/mediawiki.ui/sourcefiles/config.rb [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/_default.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/_utilities.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/_vector.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/default/_buttons.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/default/_forms.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/vector/_buttons.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/vector/_containers.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/components/vector/_forms.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.default.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.vector.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mixins/_all.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mixins/_effects.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mixins/_forms.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mixins/_type.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/mixins/_utilities.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/settings/_all.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/settings/_colors.scss [deleted file]
resources/mediawiki.ui/sourcefiles/scss/settings/_typography.scss [deleted file]
resources/mediawiki.ui/vector.less [new file with mode: 0644]
resources/mediawiki/mediawiki.Title.js
resources/mediawiki/mediawiki.hlist.css [new file with mode: 0644]
resources/mediawiki/mediawiki.hlist.js [new file with mode: 0644]
resources/mediawiki/mediawiki.inspect.js
resources/mediawiki/mediawiki.jqueryMsg.js
resources/mediawiki/mediawiki.js
resources/mediawiki/mediawiki.user.js
resources/mediawiki/mediawiki.util.js
skins/.gitignore [new file with mode: 0644]
skins/CologneBlue.php
skins/MonoBook.php
skins/common/IEFixes.js
skins/common/commonElements.css
skins/common/commonPrint.css
skins/common/images/feed-icon.svg [new file with mode: 0644]
skins/common/protect.js
skins/common/shared.css
skins/common/upload.js
skins/common/wikibits.js
skins/modern/print.css
skins/vector/beta/variables.less
skins/vector/collapsibleNav.js
skins/vector/collapsibleTabs.js
skins/vector/images/preferences-break.png [deleted file]
skins/vector/images/preferences-fade.png [deleted file]
skins/vector/images/preferences/break.png [new file with mode: 0644]
skins/vector/images/preferences/fade.png [new file with mode: 0644]
skins/vector/screen.less
skins/vector/special.preferences.less [new file with mode: 0644]
skins/vector/styles-beta.less
skins/vector/styles.less
skins/vector/variables.less
tests/TestsAutoLoader.php
tests/parser/parserTest.inc
tests/parser/parserTests.txt
tests/phpunit/MediaWikiPHPUnitCommand.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/data/autoloader/TestAutoloadedCamlClass.php [new file with mode: 0644]
tests/phpunit/data/autoloader/TestAutoloadedClass.php [new file with mode: 0644]
tests/phpunit/data/autoloader/TestAutoloadedLocalClass.php [new file with mode: 0644]
tests/phpunit/data/autoloader/TestAutoloadedSerializedClass.php [new file with mode: 0644]
tests/phpunit/data/cssmin/green.gif [new file with mode: 0644]
tests/phpunit/data/cssmin/large.png [new file with mode: 0644]
tests/phpunit/data/cssmin/red.gif [new file with mode: 0644]
tests/phpunit/data/db/sqlite/tables-1.13.sql
tests/phpunit/data/media/README
tests/phpunit/data/media/Tux.svg [new file with mode: 0644]
tests/phpunit/data/xmp/gps.result.php
tests/phpunit/includes/ArticleTablesTest.php
tests/phpunit/includes/ArticleTest.php
tests/phpunit/includes/BlockTest.php
tests/phpunit/includes/CdbTest.php [deleted file]
tests/phpunit/includes/CollationTest.php
tests/phpunit/includes/DiffHistoryBlobTest.php
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/ExceptionTest.php [new file with mode: 0644]
tests/phpunit/includes/ExternalStoreTest.php
tests/phpunit/includes/ExtraParserTest.php
tests/phpunit/includes/FallbackTest.php [new file with mode: 0644]
tests/phpunit/includes/FauxRequestTest.php
tests/phpunit/includes/FauxResponseTest.php
tests/phpunit/includes/FormOptionsInitializationTest.php
tests/phpunit/includes/FormOptionsTest.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/GlobalFunctions/GlobalWithDBTest.php
tests/phpunit/includes/GlobalFunctions/wfAssembleUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php
tests/phpunit/includes/GlobalFunctions/wfBaseConvertTest.php
tests/phpunit/includes/GlobalFunctions/wfBaseNameTest.php
tests/phpunit/includes/GlobalFunctions/wfExpandUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfGetCallerTest.php
tests/phpunit/includes/GlobalFunctions/wfParseUrlTest.php
tests/phpunit/includes/GlobalFunctions/wfRemoveDotSegmentsTest.php
tests/phpunit/includes/GlobalFunctions/wfShorthandToIntegerTest.php
tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php
tests/phpunit/includes/GlobalFunctions/wfUrlencodeTest.php
tests/phpunit/includes/HTMLCheckMatrixTest.php
tests/phpunit/includes/HashRingTest.php [deleted file]
tests/phpunit/includes/HooksTest.php
tests/phpunit/includes/HtmlFormatterTest.php
tests/phpunit/includes/HtmlTest.php
tests/phpunit/includes/HttpTest.php
tests/phpunit/includes/IPTest.php [deleted file]
tests/phpunit/includes/LanguageConverterTest.php
tests/phpunit/includes/LicensesTest.php
tests/phpunit/includes/LinkFilterTest.php [new file with mode: 0644]
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/LinksUpdateTest.php
tests/phpunit/includes/LocalFileTest.php
tests/phpunit/includes/LocalisationCacheTest.php
tests/phpunit/includes/MWExceptionHandlerTest.php [new file with mode: 0644]
tests/phpunit/includes/MWFunctionTest.php
tests/phpunit/includes/MWNamespaceTest.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/PathRouterTest.php
tests/phpunit/includes/PreferencesTest.php
tests/phpunit/includes/RecentChangeTest.php [deleted file]
tests/phpunit/includes/ResourceLoaderModuleTest.php [new file with mode: 0644]
tests/phpunit/includes/RevisionStorageTest.php
tests/phpunit/includes/RevisionStorageTest_ContentHandlerUseDB.php
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/SampleTest.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/SpecialPageTest.php [new file with mode: 0644]
tests/phpunit/includes/StatusTest.php [new file with mode: 0644]
tests/phpunit/includes/StringUtilsTest.php [deleted file]
tests/phpunit/includes/TemplateCategoriesTest.php
tests/phpunit/includes/TitleMethodsTest.php
tests/phpunit/includes/TitlePermissionTest.php
tests/phpunit/includes/UIDGeneratorTest.php [deleted file]
tests/phpunit/includes/UserMailerTest.php [new file with mode: 0644]
tests/phpunit/includes/WebRequestTest.php
tests/phpunit/includes/WikiPageTest.php
tests/phpunit/includes/XmlJsTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/ZipDirectoryReaderTest.php [deleted file]
tests/phpunit/includes/api/ApiAccountCreationTest.php [deleted file]
tests/phpunit/includes/api/ApiBaseTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiBlockTest.php
tests/phpunit/includes/api/ApiCreateAccountTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiLoginTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiMainTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiOptionsTest.php
tests/phpunit/includes/api/ApiParseTest.php
tests/phpunit/includes/api/ApiPurgeTest.php
tests/phpunit/includes/api/ApiTest.php [deleted file]
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/api/ApiTestCaseUpload.php
tests/phpunit/includes/api/ApiTestContext.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiTokensTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiUnblockTest.php [new file with mode: 0644]
tests/phpunit/includes/api/ApiUploadTest.php
tests/phpunit/includes/api/ApiWatchTest.php
tests/phpunit/includes/api/MockApi.php [new file with mode: 0644]
tests/phpunit/includes/api/PrefixUniquenessTest.php
tests/phpunit/includes/api/RandomImageGenerator.php
tests/phpunit/includes/api/UserWrapper.php [new file with mode: 0644]
tests/phpunit/includes/api/format/ApiFormatJsonTest.php [new file with mode: 0644]
tests/phpunit/includes/api/format/ApiFormatPhpTest.php
tests/phpunit/includes/api/format/ApiFormatTestBase.php
tests/phpunit/includes/api/format/ApiFormatWddxTest.php [new file with mode: 0644]
tests/phpunit/includes/api/query/ApiQueryBasicTest.php
tests/phpunit/includes/api/query/ApiQueryContinue2Test.php
tests/phpunit/includes/api/query/ApiQueryContinueTest.php
tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
tests/phpunit/includes/api/query/ApiQueryRevisionsTest.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/api/query/ApiQueryTestBase.php
tests/phpunit/includes/cache/GenderCacheTest.php
tests/phpunit/includes/cache/MessageCacheTest.php
tests/phpunit/includes/cache/ProcessCacheLRUTest.php
tests/phpunit/includes/changes/RecentChangeTest.php [new file with mode: 0644]
tests/phpunit/includes/content/ContentHandlerTest.php
tests/phpunit/includes/content/WikitextContentHandlerTest.php
tests/phpunit/includes/content/WikitextContentTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/db/DatabaseSQLTest.php
tests/phpunit/includes/db/DatabaseSqliteTest.php
tests/phpunit/includes/db/DatabaseTest.php
tests/phpunit/includes/db/ORMTableTest.php
tests/phpunit/includes/db/TestORMRowTest.php
tests/phpunit/includes/debug/MWDebugTest.php
tests/phpunit/includes/diff/DifferenceEngineTest.php [new file with mode: 0644]
tests/phpunit/includes/filerepo/FileRepoTest.php
tests/phpunit/includes/installer/InstallDocFormatterTest.php
tests/phpunit/includes/installer/OracleInstallerTest.php
tests/phpunit/includes/jobqueue/JobQueueTest.php
tests/phpunit/includes/jobqueue/RefreshLinksPartitionTest.php [new file with mode: 0644]
tests/phpunit/includes/json/FormatJsonTest.php
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/libs/GenericArrayObjectTest.php
tests/phpunit/includes/libs/IEUrlExtensionTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/logging/LogFormatterTest.php [changed mode: 0755->0644]
tests/phpunit/includes/logging/LogTests.i18n.php [changed mode: 0755->0644]
tests/phpunit/includes/media/BitmapMetadataHandlerTest.php
tests/phpunit/includes/media/BitmapScalingTest.php
tests/phpunit/includes/media/ExifBitmapTest.php
tests/phpunit/includes/media/ExifRotationTest.php
tests/phpunit/includes/media/ExifTest.php
tests/phpunit/includes/media/FakeDimensionFile.php [new file with mode: 0644]
tests/phpunit/includes/media/FormatMetadataTest.php
tests/phpunit/includes/media/GIFMetadataExtractorTest.php
tests/phpunit/includes/media/GIFTest.php
tests/phpunit/includes/media/IPTCTest.php
tests/phpunit/includes/media/JpegMetadataExtractorTest.php
tests/phpunit/includes/media/JpegTest.php
tests/phpunit/includes/media/MediaHandlerTest.php
tests/phpunit/includes/media/PNGMetadataExtractorTest.php
tests/phpunit/includes/media/PNGTest.php
tests/phpunit/includes/media/SVGMetadataExtractorTest.php
tests/phpunit/includes/media/SVGTest.php [new file with mode: 0644]
tests/phpunit/includes/media/TiffTest.php
tests/phpunit/includes/media/XMPTest.php
tests/phpunit/includes/media/XMPValidateTest.php
tests/phpunit/includes/normal/CleanUpTest.php
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/includes/parser/PreprocessorTest.php
tests/phpunit/includes/parser/TagHooksTest.php
tests/phpunit/includes/parser/TidyTest.php [new file with mode: 0644]
tests/phpunit/includes/search/SearchEngineTest.php
tests/phpunit/includes/search/SearchUpdateTest.php
tests/phpunit/includes/specials/QueryAllSpecialPagesTest.php
tests/phpunit/includes/specials/SpecialPreferencesTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php
tests/phpunit/includes/specials/SpecialSearchTest.php
tests/phpunit/includes/upload/UploadBaseTest.php
tests/phpunit/includes/upload/UploadFromUrlTest.php
tests/phpunit/includes/upload/UploadStashTest.php
tests/phpunit/includes/utils/CdbTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/HashRingTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/IPTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/StringUtilsTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/UIDGeneratorTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/ZipDirectoryReaderTest.php [new file with mode: 0644]
tests/phpunit/languages/LanguageBe_taraskTest.php
tests/phpunit/languages/LanguageRuTest.php
tests/phpunit/languages/LanguageSrTest.php
tests/phpunit/languages/LanguageTest.php
tests/phpunit/languages/LanguageTrTest.php
tests/phpunit/languages/LanguageUkTest.php
tests/phpunit/languages/LanguageUzTest.php
tests/phpunit/languages/utils/CLDRPluralRuleEvaluatorTest.php
tests/phpunit/maintenance/DumpTestCase.php
tests/phpunit/maintenance/MaintenanceTest.php
tests/phpunit/maintenance/backupPrefetchTest.php
tests/phpunit/maintenance/backupTextPassTest.php
tests/phpunit/maintenance/backup_LogTest.php
tests/phpunit/maintenance/backup_PageTest.php
tests/phpunit/maintenance/fetchTextTest.php
tests/phpunit/maintenance/getSlaveServerTest.php
tests/phpunit/mocks/media/MockBitmapHandler.php
tests/phpunit/mocks/media/MockImageHandler.php [new file with mode: 0644]
tests/phpunit/mocks/media/MockSvgHandler.php [new file with mode: 0644]
tests/phpunit/phpunit.php
tests/phpunit/skins/SideBarTest.php
tests/phpunit/structure/AutoLoaderTest.php
tests/phpunit/structure/ResourcesTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/jquery/jquery.placeholder.test.js [new file with mode: 0644]
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
tests/testHelpers.inc
thumb.php

index 9c0c3b6..76d220a 100644 (file)
@@ -62,3 +62,5 @@ Thumbs.db
 /favicon.ico
 /static*
 /tags
+/.htaccess
+/.htpasswd
diff --git a/CREDITS b/CREDITS
index 7927c3d..01505b0 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1,4 +1,4 @@
-MediaWiki 1.22 is a collaborative project released under the
+MediaWiki 1.23 is a collaborative project released under the
 GNU General Public License v2. We would like to recognize the
 following names for their contribution to the product.
 
@@ -22,6 +22,7 @@ following names for their contribution to the product.
 * church of emacs
 * Daniel Friesen
 * Daniel Kinzler
+* Daniel Renfro
 * Danny B.
 * David McCabe
 * Derk-Jan Hartman
diff --git a/FAQ b/FAQ
index 0aedb7e..cfacf14 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -1,2 +1,2 @@
 The MediaWiki FAQ can be found at:
-http://www.mediawiki.org/wiki/Manual:FAQ
+https://www.mediawiki.org/wiki/Manual:FAQ
diff --git a/HISTORY b/HISTORY
index 45eab2e..88cc906 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -1,4 +1,4 @@
-Change notes from older releases. For current info see RELEASE-NOTES-1.22.
+Change notes from older releases. For current info see RELEASE-NOTES-1.23.
 
 == MediaWiki 1.21 ==
 
index d6a75ba..333696b 100644 (file)
@@ -64,8 +64,11 @@ production.
 * (bug 54597) $wgBlockOpenProxies, $wgProxyPorts, $wgProxyScriptPath, and
   $wgProxyMemcExpiry have been removed, along with the open proxy scanner
   script they were added for.
+* Default value of $wgMaxShellMemory has been tripled (it's now 300 MB).
 
 === New features in 1.22 ===
+* You can now install extensions using Composer.
+  See https://www.mediawiki.org/wiki/Composer
 * (bug 44525) mediawiki.jqueryMsg can now parse (whitelisted) HTML elements and attributes.
 * (bug 33454) Language::sprintfDate now has a timezone parameter, and supports
   the "eIOPTZ" formatting characters.
@@ -226,8 +229,6 @@ production.
 * Add deferrable update support for callback/closure.
 * Add TitleMove hook before page renames.
 * Revision deletion backend code is moved out of SpecialRevisiondelete
-* Add a variable (wgRedactedFunctionArguments) to redact the values sent as certain function
-  parameters from exception stack traces.
 * Added {{REVISIONSIZE}} variable to get the current size of a revision.
 * Add support for the LESS stylesheet language to ResourceLoader. LESS is a
   stylesheet language that compiles into CSS. ResourceLoader file modules may
@@ -254,10 +255,19 @@ production.
 * The 'UnwatchArticle' and 'WatchArticle' hooks now support a Status object
   instead of just a boolean return value to abort the hook.
 * Added a hook, SpecialWatchlistGetNonRevisionTypes, to allow extensions
-  with custom recentchanges entries to hook into the Watchlist without 
+  with custom recentchanges entries to hook into the Watchlist without
   clobbering each other.
+* A hidden, empty input field was added to the edit form, and any edit that fills
+  it in will be rejected. This prevents against the simplest form of spambots.
+  Previously in the "SimpleAntiSpam" extension by Ryan Schmidt.
+* populateRevisionLength.php maintenance script updated to also populate
+  archive.ar_len field.
+* (bug 43571) DatabaseMySQLBase learned to list views, optionally filtered by a
+  prefix. Also fixed PHPUnit test suite when using a MySQL backend containing
+  views.
 
 === Bug fixes in 1.22 ===
+* (bug 47271) $wgContentHandlerUseDB should be set to false during the upgrade
 * Disable Special:PasswordReset when $wgEnableEmail is false. Previously one
   could still navigate to the page by entering the URL directly.
 * (bug 47138) Fixed a fatal error when a blocked user tries to automatically
@@ -343,6 +353,8 @@ production.
 * (bug 45288) Support mysqli PHP extension
 * (bug 55818) BREAKING CHANGE: Removed undocumented 'Debug' hook in wfDebug.
   This resolves an infinite loop when using $wgDebugFunctionEntry = true.
+* (bug 56707) Correct tooltip of "Next n results" on query special pages.
+* (bug 56770) mw.util.addPortletLink: Check length before access array index.
 
 === API changes in 1.22 ===
 * (bug 25553) The JSON output formatter now leaves forward slashes unescaped
@@ -512,6 +524,16 @@ changes to languages because of Bugzilla reports.
   to addModules() and made protected.
 * Methods WatchAction::doWatch and WatchAction::doUnwatch now return a Status
   object instead of a boolean.
+* Information boxes (CSS classes errorbox, warningbox, successbox) have been
+  made more subtle.
+* BREAKING CHANGE: The module 'mediawiki.legacy.IEFixes' has been removed as it was
+  unused. The file skins/common/IEFixes.js remains but is only used by wikibits.
+  The file never contained any re-usable components. To use it in a skin, load
+  'mediawiki.legacy.wikibits' (which IEFixes depends on) and that will import
+  IEFixes automatically if user agent conditions are met.
+* Code specific to the Math extension was marked as deprecated.
+* mediawiki.util: mw.util.wikiGetlink has been renamed to getUrl. (The old name
+  still works, but is deprecated.)
 
 == Compatibility ==
 
diff --git a/RELEASE-NOTES-1.23 b/RELEASE-NOTES-1.23
new file mode 100644 (file)
index 0000000..4697b4d
--- /dev/null
@@ -0,0 +1,159 @@
+Security reminder: MediaWiki does not require PHP's register_globals. If you
+have it on, turn it '''off''' if you can.
+
+== MediaWiki 1.23 ==
+
+THIS IS NOT A RELEASE YET
+
+MediaWiki 1.23 is an alpha-quality branch and is not recommended for use in
+production.
+
+=== Configuration changes in 1.23 ===
+* $wgDebugLogGroups values may be set to an associative array with a
+  'destination' key specifying the log destination. The array may also contain
+  a 'sample' key with a positive integer value N indicating that the log group
+  should be sampled by dispatching one in every N messages on average. The
+  sampling is random.
+* In addition to the current exception log format, MediaWiki now serializes
+  exception metadata to JSON and logs it to the 'exception-json' log group.
+  This makes MediaWiki easier to integrate with log aggregation and analysis
+  tools.
+* $wgSquidServersNoPurge now supports the use of Classless Inter-Domain
+  Routing (CIDR) notation to specify contiguous blocks of IPv4 and/or IPv6
+  addresses that should be trusted to provide X-Forwarded-For headers.
+
+=== New features in 1.23 ===
+* ResourceLoader can utilize the Web Storage API to cache modules client-side.
+  Compared to the browser cache, caching in Web Storage allows ResourceLoader
+  to be more granular about evicting stale modules from the cache while
+  retaining the ability to retrieve multiple modules in a single HTTP request.
+  This capability can be enabled by setting $wgResourceLoaderStorageEnabled to
+  true. This feature is currently considered experimental and should only be
+  enabled with care.
+* (bug 6092) Add expensive parser functions {{REVISIONID:}}, {{REVISIONUSER:}}
+  and {{REVISIONTIMESTAMP:}} (with friends).
+* Add "wgRelevantUserName" to mw.config containing the current
+  Skin::getRelevantUser value.
+* (bug 56033) Add content model to the page information.
+* Added Article::MissingArticleConditions hook to give extensions a chance to
+  hide their (unrelated) log entries.
+* Added $wgOpenSearchDefaultLimit defining the default number of entries to show
+  on action=opensearch API call.
+* For namespaces with $wgNamespaceProtection (including the MediaWiki
+  namespace), the "protect" tab will be shown only if there are restriction
+  levels available that would restrict editing beyond what
+  $wgNamespaceProtection already applies. The protection form will offer only
+  those protection levels.
+
+=== Bug fixes in 1.23 ===
+* (bug 41759) The "updated since last visit" markers (on history pages, recent
+  changes and watchlist) and the talk page message indicator are now correctly
+  updated when the user is viewing old revisions of pages, instead of always
+  acting as if the latest revision was being viewed.
+* (bug 56443) Special:ConfirmEmail no longer shows a "Mail a confirmation code"
+  when the email address is already confirmed. Also, consistently use
+  "confirmed", rather than "authenticated", when messaging whether or not the
+  user has confirmed an email address.
+* (bug 56912) Show correct link color on cached result of Special:DeadendPages.
+* Classes TitleListDependency and TitleDependency have been removed, as they
+  have been found unused in core and extensions for a long time.
+* (bug 57098) SpecialPasswordReset now obeys returnto parameter
+* (bug 37812) ResourceLoader will notice when a module's definition changes and
+  recompile it accordingly.
+
+=== API changes in 1.23 ===
+* (bug 54884) action=parse&prop=categories now indicates hidden and missing
+  categories.
+* action=query&meta=filerepoinfo now returns additional information for each
+  repo.
+* EditPage::spamPage() was deprecated since 1.17 and has been removed.
+* action=parse&prop=languageshtml was deprecated in 1.18 and will be removed in
+  MediaWiki 1.24.
+
+=== Languages updated in 1.23===
+
+MediaWiki supports over 350 languages. Many localisations are updated
+regularly. Below only new and removed languages are listed, as well as
+changes to languages because of Bugzilla reports.
+
+* Support was added for Northern Luri (lrc)
+
+=== Other changes in 1.23 ===
+* The rc_type field in the recentchanges table has been superseded by a new
+  rc_source field.  The rc_source field is a string representation of the
+  change type where rc_type was a numeric constant.  This field is not yet
+  queried but will be in a future point release of 1.22.
+** Utilize update.php to create and populate this new field.  On larger wiki's
+   which do not wish to update recentchanges table in one large update please
+   review the sql and comments in maintenance/archives/patch-rc_source.sql.
+** The rc_type field of recentchanges will be deprecated in a future point
+   release.
+* The global variable $wgArticle has been removed after a lengthy deprecation.
+* The global functions addButton and insertTags (for mw.toolbar.addButton and
+  mw.toolbar.insertTags) now emits mw.log.warn when accessed.
+* User::getPageRenderingHash() was deprecated since 1.17 and has been removed.
+* The ExpandTemplates extension has been moved into MediaWiki core.
+
+== Compatibility ==
+
+MediaWiki 1.23 requires PHP 5.3.2 or later.
+
+MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
+support for them is somewhat less mature. There is experimental support for
+Oracle.
+
+The supported versions are:
+
+* MySQL 5.0.2 or later
+* PostgreSQL 8.3 or later
+* SQLite 3.3.7 or later
+* Oracle 9.0.1 or later
+
+== Upgrading ==
+
+1.23 has several database changes since 1.22, and will not work without schema
+updates. Note that due to changes to some very large tables like the revision
+table, the schema update may take quite long (minutes on a medium sized site,
+many hours on a large site).
+
+If upgrading from before 1.11, and you are using a wiki as a commons
+repository, make sure that it is updated as well. Otherwise, errors may arise
+due to database schema changes.
+
+If upgrading from before 1.7, you may want to run refreshLinks.php to ensure
+new database fields are filled with data.
+
+If you are upgrading from MediaWiki 1.4.x or earlier, you should upgrade to
+1.5 first. The upgrade script maintenance/upgrade1_5.php has been removed
+with MediaWiki 1.21.
+
+Don't forget to always back up your database before upgrading!
+
+See the file UPGRADE for more detailed upgrade instructions.
+
+For notes on 1.21.x and older releases, see HISTORY.
+
+== Online documentation ==
+
+Documentation for both end-users and site administrators is available on
+MediaWiki.org, and is covered under the GNU Free Documentation License (except
+for pages that explicitly state that their contents are in the public domain):
+
+       https://www.mediawiki.org/wiki/Documentation
+
+== Mailing list ==
+
+A mailing list is available for MediaWiki user support and discussion:
+
+       https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
+
+A low-traffic announcements-only list is also available:
+
+       https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce
+
+It's highly recommended that you sign up for one of these lists if you're
+going to run a public MediaWiki, so you can be notified of security fixes.
+
+== IRC help ==
+
+There's usually someone online in #mediawiki on irc.freenode.net.
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/composer-example.json b/composer-example.json
new file mode 100644 (file)
index 0000000..6c4d37f
--- /dev/null
@@ -0,0 +1,11 @@
+{
+       "require": {
+               "php": ">=5.3.2"
+       },
+       "suggest": {
+               "ext-fileinfo": "*",
+               "ext-mbstring": "*",
+               "ext-wikidiff2": "*",
+               "ext-apc": "*"
+       }
+}
diff --git a/composer.json b/composer.json
deleted file mode 100644 (file)
index ded3365..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-       "name": "mediawiki/core",
-       "description": "Free software wiki application developed by the Wikimedia Foundation and others",
-       "keywords": ["mediawiki", "wiki"],
-       "homepage": "https://www.mediawiki.org/",
-       "authors": [
-               {
-                       "name": "MediaWiki Community",
-                       "homepage": "https://www.mediawiki.org/wiki/Special:Version/Credits"
-               }
-       ],
-       "license": "GPL-2.0",
-       "support": {
-               "issues": "https://bugzilla.wikimedia.org/",
-               "irc": "irc://irc.freenode.net/mediawiki",
-               "wiki": "https://www.mediawiki.org/"
-       },
-       "require": {
-               "php": ">=5.3.2"
-       },
-       "require-dev": {
-               "phpunit/phpunit": "*"
-       },
-       "suggest": {
-               "ext-fileinfo": "*",
-               "ext-mbstring": "*",
-               "ext-wikidiff2": "*",
-               "ext-apc": "*"
-       }
-}
index 6917076..5bc8bfc 100644 (file)
@@ -1,16 +1,19 @@
-[July 22nd 2008]
+/docs Directory README
+======================
 
 The 'docs' directory contain various text files that should help you understand
 the most important parts of the code of MediaWiki. More in-depth documentation
-can be found at http://www.mediawiki.org/wiki/Manual:Code.
+can be found at:
+  https://www.mediawiki.org/wiki/Manual:Code
 
 API documentation is automatically generated and updated daily at:
-  http://svn.wikimedia.org/doc/
+  https://doc.wikimedia.org/mediawiki-core/master/php/html/
 
 You can get a fresh version using 'make doc' or mwdocgen.php in the
 ../maintenance/ directory.
 
 
-For end user / administrators, most of the documentation is located online at:
-  http://www.mediawiki.org/wiki/Help:Contents
-  http://www.mediawiki.org/wiki/Manual:Contents
+For end users, most of the documentation is located online at:
+  https://www.mediawiki.org/wiki/Help:Contents
+Documentation for MediaWiki site administrators is at:
+  https://www.mediawiki.org/wiki/Manual:Contents
index 5aaf596..15387f8 100644 (file)
@@ -461,6 +461,13 @@ types.
 &$tokenTypes: supported token types in format 'type' => callback function
 used to retrieve this type of tokens.
 
+'Article::MissingArticleConditions': Before fetching deletion & move log entries
+to display a message of a non-existing page being deleted/moved, give extensions
+a chance to hide their (unrelated) log entries.
+&$conds: Array of query conditions (all of which have to be met; conditions will
+AND in the final query)
+$logTypes: Array of log types being queried
+
 'ArticleAfterFetchContent': After fetching content of an article from the
 database. DEPRECATED, use ArticleAfterFetchContentObject instead.
 $article: the article (object) being loaded from the database
@@ -765,7 +772,7 @@ $output: OutputPage object in use
 'CanIPUseHTTPS': Determine whether the client at a given source IP is likely
 to be able to access the wiki via HTTPS.
 $ip: The IP address in human-readable form
-&$canDo: This reference should be set to false if the client may not be able 
+&$canDo: This reference should be set to false if the client may not be able
 to use HTTPS
 
 'CanonicalNamespaces': For extensions adding their own namespaces or altering
@@ -891,7 +898,7 @@ $oldid: oldid (int) being viewed
 'DoEditSectionLink': Override the HTML generated for section edit links
 $skin: Skin object rendering the UI
 $title: Title object for the title being linked to (may not be the same as
-  $wgTitle, if the section is included from a template)
+  the page title, if the section is included from a template)
 $section: The designation of the section being pointed to, to be included in
   the link, like "&section=$section"
 $tooltip: The default tooltip.  Escape before using.
@@ -1157,6 +1164,16 @@ $title: Title object that we need to get a sortkey for
 underscore) magic words. Called by MagicWord.
 &$doubleUnderscoreIDs: array of strings
 
+'GetExtendedMetadata': Get extended file metadata for the API
+&$combinedMeta: Array of the form: 'MetadataPropName' => array(
+'value' => prop value, 'source' => 'name of hook' ).
+$file: File object of file in question
+$context: RequestContext (including language to use)
+$single: Only extract the current language; if false, the prop value should
+be in the metadata multi-language array format:
+mediawiki.org/wiki/Manual:File_metadata_handling#Multi-language_array_format
+&$maxCacheTime: how long the results can be cached
+
 'GetFullURL': Modify fully-qualified URLs used in redirects/export/offsite data.
 $title: Title object of page
 $url: string value as output (out parameter, can modify)
@@ -1203,6 +1220,9 @@ without any fancy queries or variants.
 $title: Title object of page
 &$url: string value as output (out parameter, can modify)
 
+'GetLogTypesOnUser': Add log types where the target is a userpage
+&$types: Array of log types
+
 'GetMetadataVersion': Modify the image metadata version currently in use. This
 is used when requesting image metadata from a ForeignApiRepo. Media handlers
 that need to have versioned metadata should add an element to the end of the
@@ -1349,7 +1369,7 @@ $context: IContextSource object
 &$pageInfo: Array of information
 
 'InitializeArticleMaybeRedirect': MediaWiki check to see if title is a redirect.
-$title: Title object ($wgTitle)
+$title: Title object for the current page
 $request: WebRequest
 $ignoreRedirect: boolean to skip redirect check
 $target: Title/string of redirect target
@@ -1524,6 +1544,11 @@ $cache: The LocalisationCache object
 $code: language code
 &$alldata: The localisation data from core and extensions
 
+'LocalisationChecksBlacklist': When fetching the blacklist of
+localisation checks.
+&$blacklist: array of checks to blacklist. See the bottom of
+  maintenance/language/checkLanguage.inc for the format of this variable.
+
 'LogEventsListShowLogExtract': Called before the string is added to OutputPage.
 Returning false will prevent the string from being added to the OutputPage.
 &$s: html string to show for the log extract
@@ -1598,8 +1623,8 @@ $wcOnlySysopsCanPatrol: config setting indicating whether the user must be a
 something completely different, after the basic globals have been set up, but
 before ordinary actions take place.
 $output: $wgOut
-$article: $wgArticle
-$title: $wgTitle
+$article: Article on which the action will be performed
+$title: Title on which the action will be performed
 $user: $wgUser
 $request: $wgRequest
 $mediaWiki: The $mediawiki object
@@ -1751,7 +1776,7 @@ $baseRevId: the rev ID (or false) this edit was based on
 $article: the article that the history is loading for
 $context: RequestContext object
 
-'PageHistoryLineEnding' : Right before the end <li> is added to a history line.
+'PageHistoryLineEnding': Right before the end <li> is added to a history line.
 $row: the revision row for this line
 $s: the string representing this parsed line
 $classes: array containing the <li> element classes
@@ -1837,7 +1862,7 @@ needs formatting. If nothing handles this hook, the default is to use "$key" to
 get the label, and "$key-value" or "$key-value-text"/"$key-value-html" to
 format the value.
 $key: Key for the limit report item (string)
-$value: Value of the limit report item
+&$value: Value of the limit report item
 &$report: String onto which to append the data
 $isHTML: If true, $report is an HTML table with two columns; if false, it's
        text intended for display in a monospaced font.
@@ -1845,7 +1870,8 @@ $localize: If false, $report should be output in English.
 
 'ParserLimitReportPrepare': Called at the end of Parser:parse() when the parser will
 include comments about size of the text parsed. Hooks should use
-$output->setLimitReportData() to populate data.
+$output->setLimitReportData() to populate data. Functions for this hook should
+not use $wgLang; do that in ParserLimitReportFormat instead.
 $parser: Parser object
 $output: ParserOutput object
 
@@ -1883,6 +1909,7 @@ that tests continue to run properly.
 my talk page, my contributions" etc).
 &$personal_urls: Array of link specifiers (see SkinTemplate.php)
 &$title: Title object representing the current page
+$skin: Skin object providing context (e.g. to check if the user is logged in, etc.)
 
 'PingLimiter': Allows extensions to override the results of User::pingLimiter().
 &$user : User performing the action
@@ -2221,7 +2248,7 @@ $special: the special page object
   name/URL parameters. Each key maps to an associative array with a 'msg'
   (message key) and a 'default' value.
 
-'SpecialPage_initList': Called when setting up SpecialPage::$mList, use this
+'SpecialPage_initList': Called when setting up SpecialPageFactory::$list, use this
 hook to remove a core special page.
 $list: list (array) of core special pages
 
@@ -2366,7 +2393,7 @@ $special: the special page object
 $values: array of variables with watchlist options
 
 'SpecialWatchlistGetNonRevisionTypes': Called when building sql query for
-SpecialWatchlist. Allows extensions to register custom values they have 
+SpecialWatchlist. Allows extensions to register custom values they have
 inserted to rc_type so they can be returned as part of the watchlist.
 &$nonRevisionTypes: array of values in the rc_type field of recentchanges table
 
@@ -2579,6 +2606,7 @@ $user: User (object) whose permission is being checked
 'UserClearNewTalkNotification': Called when clearing the "You have new
 messages!" message, return false to not delete it.
 $user: User (object) that will clear the message
+$oldid: ID of the talk page revision being viewed (0 means the most recent one)
 
 'UserComparePasswords': Called when checking passwords, return false to
 override the default password checks.
@@ -2743,6 +2771,12 @@ $userId: User id of the current user
 $userText: User name of the current user
 &$items: Array of user tool links as HTML fragments
 
+'ValidateExtendedMetadataCache': Called to validate the cached metadata in
+FormatMetadata::getExtendedMeta (return false means cache will be
+invalidated and GetExtendedMetadata hook called again).
+$timestamp: The timestamp metadata was generated
+$file: The file the metadata is for
+
 'WantedPages::getQueryInfo': Called in WantedPagesPage::getQueryInfo(), can be
 used to alter the SQL query which gets the list of wanted pages.
 &$wantedPages: WantedPagesPage object
@@ -2826,4 +2860,4 @@ data. Can be used to post-process the results.
   of values).
 
 More hooks might be available but undocumented, you can execute
-'php maintenance/findHooks.php' to find hidden ones.
+"php maintenance/findHooks.php" to find hidden ones.
index 87a32a8..87071f2 100644 (file)
@@ -54,4 +54,4 @@ require_once RUN_MAINTENANCE_IF_MAIN;
 That's it. In the execute() method, you have access to all of the normal
 MediaWiki functions, so you can get a DB connection, use the cache, etc.
 For full docs on the Maintenance class, see the auto-generated docs at
-http://svn.wikimedia.org/doc/classMaintenance.html
+https://doc.wikimedia.org/mediawiki-core/master/php/html/classMaintenance.html
index f54a4e7..16c5760 100644 (file)
@@ -78,7 +78,7 @@ usage evenly), make its entry a subarray:
 == PHP client for memcached ==
 
 MediaWiki uses a fork of Ryan T. Dean's pure-PHP memcached client.
-The newer PECL module is not yet supported.
+It also supports the PECL PHP extension for memcached.
 
 MediaWiki uses three object for object caching:
 * $wgMemc, controlled by $wgMainCacheType
@@ -91,7 +91,7 @@ database. If the cache daemon can't be contacted, it should also
 disable itself fairly smoothly.
 
 By default, $wgMemc is used but when it is $parserMemc or $messageMemc
-this is mentionned below.
+this is mentioned below.
 
 == Keys used ==
 
index e815062..b665001 100644 (file)
@@ -2,20 +2,22 @@ Extensions (such as the hieroglyphic module WikiHiero) are distributed
 separately. Drop them into this extensions directory and enable as
 per the extension's directions.
 
+You can find a list of extensions and documentation on the MediaWiki website:
+    https://www.mediawiki.org/wiki/Category:Extensions
+
+
 If you are a developer, you want to fetch the extension tree in another
 directory and make a symbolic link:
 
  mediawiki/extensions$ ln -s ../../extensions-trunk/FooBarExt
 
-The extensions are available through Git:
+Most extensions are available through Git:
     https://gerrit.wikimedia.org/r/#/admin/projects/
+    https://git.wikimedia.org/project/mediawiki
 
-or Subversion:
+Old extensions are on Subversion:
     https://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/
 
-You can find documentation and additional extensions on MediaWiki website:
-    https://www.mediawiki.org/wiki/Category:Extensions
-
 
 Please note that under POSIX systems (Linux...), parent of a symbolic path
 refers to the link source, NOT to the target! You should check the env
index c8759ec..2d2db9a 100644 (file)
@@ -52,7 +52,7 @@ wfImageAuthMain();
 wfLogProfilingData();
 
 function wfImageAuthMain() {
-       global $wgImgAuthPublicTest, $wgRequest;
+       global $wgImgAuthPublicTest, $wgImgAuthUrlPathMap, $wgRequest;
 
        // See if this is a public Wiki (no protections).
        if ( $wgImgAuthPublicTest
@@ -77,14 +77,32 @@ function wfImageAuthMain() {
 
        // Check for bug 28235: QUERY_STRING overriding the correct extension
        $whitelist = array();
-       $dotPos = strrpos( $path, '.' );
-       if ( $dotPos !== false ) {
-               $whitelist[] = substr( $path, $dotPos + 1 );
+       $extension = FileBackend::extensionFromPath( $path );
+       if ( $extension != '' ) {
+               $whitelist[] = $extension;
        }
        if ( !$wgRequest->checkUrlExtension( $whitelist ) ) {
                return;
        }
 
+       // Various extensions may have their own backends that need access.
+       // Check if there is a special backend and storage base path for this file.
+       foreach ( $wgImgAuthUrlPathMap as $prefix => $storageDir ) {
+               $prefix = rtrim( $prefix, '/' ) . '/'; // implicit trailing slash
+               if ( strpos( $path, $prefix ) === 0 ) {
+                       $be = FileBackendGroup::singleton()->backendFromPath( $storageDir );
+                       $filename = $storageDir . substr( $path, strlen( $prefix ) ); // strip prefix
+                       if ( $be->fileExists( array( 'src' => $filename ) ) ) {
+                               wfDebugLog( 'img_auth', "Streaming `" . $filename . "`." );
+                               $be->streamFile( array( 'src' => $filename ),
+                                       array( 'Cache-Control: private', 'Vary: Cookie' ) );
+                       } else {
+                               wfForbidden( 'img-auth-accessdenied', 'img-auth-nofile', $filename );
+                       }
+                       return;
+               }
+       }
+
        // Get the local file repository
        $repo = RepoGroup::singleton()->getRepo( 'local' );
 
@@ -145,6 +163,7 @@ function wfForbidden( $msg1, $msg2 ) {
        $args = func_get_args();
        array_shift( $args );
        array_shift( $args );
+       $args = ( isset( $args[0] ) && is_array( $args[0] ) ) ? $args[0] : $args;
 
        $msgHdr = wfMessage( $msg1 )->escaped();
        $detailMsgKey = $wgImgAuthDetails ? $msg2 : 'badaccess-group0';
index 4b6e446..72be46f 100644 (file)
@@ -167,7 +167,7 @@ abstract class Action {
        final public function getContext() {
                if ( $this->context instanceof IContextSource ) {
                        return $this->context;
-               } else if ( $this->page instanceof Article ) {
+               } elseif ( $this->page instanceof Article ) {
                        // NOTE: $this->page can be a WikiPage, which does not have a context.
                        wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' );
                        return $this->page->getContext();
diff --git a/includes/ArrayUtils.php b/includes/ArrayUtils.php
deleted file mode 100644 (file)
index 985271f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-
-class ArrayUtils {
-       /**
-        * Sort the given array in a pseudo-random order which depends only on the
-        * given key and each element value. This is typically used for load
-        * balancing between servers each with a local cache.
-        *
-        * Keys are preserved. The input array is modified in place.
-        *
-        * Note: Benchmarking on PHP 5.3 and 5.4 indicates that for small
-        * strings, md5() is only 10% slower than hash('joaat',...) etc.,
-        * since the function call overhead dominates. So there's not much
-        * justification for breaking compatibility with installations
-        * compiled with ./configure --disable-hash.
-        *
-        * @param $array The array to sort
-        * @param $key The string key
-        * @param $separator A separator used to delimit the array elements and the
-        *     key. This can be chosen to provide backwards compatibility with
-        *     various consistent hash implementations that existed before this
-        *     function was introduced.
-        */
-       public static function consistentHashSort( &$array, $key, $separator = "\000" ) {
-               $hashes = array();
-               foreach ( $array as $elt ) {
-                       $hashes[$elt] = md5( $elt . $separator . $key );
-               }
-               uasort( $array, function ( $a, $b ) use ( $hashes ) {
-                       return strcmp( $hashes[$a], $hashes[$b] );
-               } );
-       }
-
-       /**
-        * Given an array of non-normalised probabilities, this function will select
-        * an element and return the appropriate key
-        *
-        * @param $weights array
-        *
-        * @return bool|int|string
-        */
-       public static function pickRandom( $weights ) {
-               if ( !is_array( $weights ) || count( $weights ) == 0 ) {
-                       return false;
-               }
-
-               $sum = array_sum( $weights );
-               if ( $sum == 0 ) {
-                       # No loads on any of them
-                       # In previous versions, this triggered an unweighted random selection,
-                       # but this feature has been removed as of April 2006 to allow for strict
-                       # separation of query groups.
-                       return false;
-               }
-               $max = mt_getrandmax();
-               $rand = mt_rand( 0, $max ) / $max * $sum;
-
-               $sum = 0;
-               foreach ( $weights as $i => $w ) {
-                       $sum += $w;
-                       # Do not return keys if they have 0 weight.
-                       # Note that the "all 0 weight" case is handed above
-                       if ( $w > 0 && $sum >= $rand ) {
-                               break;
-                       }
-               }
-               return $i;
-       }
-}
index 0b18221..821c32e 100644 (file)
@@ -586,7 +586,7 @@ class Article implements Page {
                                wfDebug( __METHOD__ . ": done file cache\n" );
                                # tell wgOut that output is taken care of
                                $outputPage->disable();
-                               $this->mPage->doViewUpdates( $user );
+                               $this->mPage->doViewUpdates( $user, $oldid );
                                wfProfileOut( __METHOD__ );
 
                                return;
@@ -765,7 +765,7 @@ class Article implements Page {
                $outputPage->setFollowPolicy( $policy['follow'] );
 
                $this->showViewFooter();
-               $this->mPage->doViewUpdates( $user );
+               $this->mPage->doViewUpdates( $user, $oldid );
 
                $outputPage->addModules( 'mediawiki.action.view.postEdit' );
 
@@ -815,10 +815,10 @@ class Article implements Page {
                $this->mRevIdFetched = $de->mNewid;
                $de->showDiffPage( $diffOnly );
 
-               if ( $diff == 0 || $diff == $this->mPage->getLatest() ) {
-                       # Run view updates for current revision only
-                       $this->mPage->doViewUpdates( $user );
-               }
+               // Run view updates for the newer revision being diffed (and shown below the diff if not $diffOnly)
+               list( $old, $new ) = $de->mapDiffPrevNext( $oldid, $diff );
+               // New can be false, convert it to 0 - this conveniently means the latest revision
+               $this->mPage->doViewUpdates( $user, (int)$new );
        }
 
        /**
@@ -1201,10 +1201,15 @@ class Article implements Page {
 
                wfRunHooks( 'ShowMissingArticle', array( $this ) );
 
+               // Give extensions a chance to hide their (unrelated) log entries
+               $logTypes = array( 'delete', 'move' );
+               $conds = array( "log_action != 'revision'" );
+               wfRunHooks( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
+
                # Show delete and move logs
-               LogEventsList::showLogExtract( $outputPage, array( 'delete', 'move' ), $this->getTitle(), '',
+               LogEventsList::showLogExtract( $outputPage, $logTypes, $this->getTitle(), '',
                        array( 'lim' => 10,
-                               'conds' => array( "log_action != 'revision'" ),
+                               'conds' => $conds,
                                'showIfEmpty' => false,
                                'msgKey' => array( 'moveddeleted-notice' ) )
                );
@@ -1238,7 +1243,8 @@ class Article implements Page {
                } elseif ( $this->getTitle()->quickUserCan( 'create', $this->getContext()->getUser() )
                        && $this->getTitle()->quickUserCan( 'edit', $this->getContext()->getUser() )
                ) {
-                       $text = wfMessage( 'noarticletext' )->plain();
+                       $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon';
+                       $text = wfMessage( $message )->plain();
                } else {
                        $text = wfMessage( 'noarticletext-nopermission' )->plain();
                }
@@ -1546,8 +1552,8 @@ class Article implements Page {
                }
 
                if ( $request->wasPosted() && $user->matchEditToken( $request->getVal( 'wpEditToken' ),
-                       array( 'delete', $this->getTitle()->getPrefixedText() ) ) )
-               {
+                       array( 'delete', $this->getTitle()->getPrefixedText() ) )
+               {
                        # Flag to hide all contents of the archived revisions
                        $suppress = $request->getVal( 'wpSuppress' ) && $user->isAllowed( 'suppressrevision' );
 
index 84cf3d5..c7b0c97 100644 (file)
@@ -34,7 +34,6 @@
  * someone logs in who can be authenticated externally.
  */
 class AuthPlugin {
-
        /**
         * @var string
         */
@@ -46,7 +45,7 @@ class AuthPlugin {
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
-        * @param string $username username.
+        * @param string $username Username.
         * @return bool
         */
        public function userExists( $username ) {
@@ -60,8 +59,8 @@ class AuthPlugin {
         * you might need to munge it (for instance, for lowercase initial
         * letters).
         *
-        * @param string $username username.
-        * @param string $password user password.
+        * @param string $username Username.
+        * @param string $password User password.
         * @return bool
         */
        public function authenticate( $username, $password ) {
@@ -72,7 +71,7 @@ class AuthPlugin {
        /**
         * Modify options in the login template.
         *
-        * @param $template UserLoginTemplate object.
+        * @param UserLoginTemplate $template
         * @param string $type 'signup' or 'login'. Added in 1.16.
         */
        public function modifyUITemplate( &$template, &$type ) {
@@ -83,7 +82,7 @@ class AuthPlugin {
        /**
         * Set the domain this plugin is supposed to use when authenticating.
         *
-        * @param string $domain authentication domain.
+        * @param string $domain Authentication domain.
         */
        public function setDomain( $domain ) {
                $this->domain = $domain;
@@ -105,7 +104,7 @@ class AuthPlugin {
        /**
         * Check to see if the specific domain is a valid domain.
         *
-        * @param string $domain authentication domain.
+        * @param string $domain Authentication domain.
         * @return bool
         */
        public function validDomain( $domain ) {
@@ -121,7 +120,7 @@ class AuthPlugin {
         * The User object is passed by reference so it can be modified; don't
         * forget the & on your function declaration.
         *
-        * @param $user User object
+        * @param User $user
         * @return bool
         */
        public function updateUser( &$user ) {
@@ -140,7 +139,7 @@ class AuthPlugin {
         *
         * This is just a question, and shouldn't perform any actions.
         *
-        * @return Boolean
+        * @return bool
         */
        public function autoCreate() {
                return false;
@@ -151,9 +150,9 @@ class AuthPlugin {
         * and use the same keys. 'Realname' 'Emailaddress' and 'Nickname'
         * all reference this.
         *
-        * @param $prop string
+        * @param string $prop
         *
-        * @return Boolean
+        * @return bool
         */
        public function allowPropChange( $prop = '' ) {
                if ( $prop == 'realname' && is_callable( array( $this, 'allowRealNameChange' ) ) ) {
@@ -193,8 +192,8 @@ class AuthPlugin {
         *
         * Return true if successful.
         *
-        * @param $user User object.
-        * @param string $password password.
+        * @param User $user
+        * @param string $password Password.
         * @return bool
         */
        public function setPassword( $user, $password ) {
@@ -216,10 +215,10 @@ class AuthPlugin {
         * Update user groups in the external authentication database.
         * Return true if successful.
         *
-        * @param $user User object.
-        * @param $addgroups Groups to add.
-        * @param $delgroups Groups to remove.
-        * @return Boolean
+        * @param User $user
+        * @param array $addgroups Groups to add.
+        * @param array $delgroups Groups to remove.
+        * @return bool
         */
        public function updateExternalDBGroups( $user, $addgroups, $delgroups = array() ) {
                return true;
@@ -228,7 +227,7 @@ class AuthPlugin {
        /**
         * Check to see if external accounts can be created.
         * Return true if external accounts can be created.
-        * @return Boolean
+        * @return bool
         */
        public function canCreateAccounts() {
                return false;
@@ -238,11 +237,11 @@ class AuthPlugin {
         * Add a user to the external authentication database.
         * Return true if successful.
         *
-        * @param $user User: only the name should be assumed valid at this point
-        * @param $password String
-        * @param $email String
-        * @param $realname String
-        * @return Boolean
+        * @param User $user Only the name should be assumed valid at this point
+        * @param string $password
+        * @param string $email
+        * @param string $realname
+        * @return bool
         */
        public function addUser( $user, $password, $email = '', $realname = '' ) {
                return true;
@@ -254,7 +253,7 @@ class AuthPlugin {
         *
         * This is just a question, and shouldn't perform any actions.
         *
-        * @return Boolean
+        * @return bool
         */
        public function strict() {
                return false;
@@ -264,8 +263,8 @@ class AuthPlugin {
         * Check if a user should authenticate locally if the global authentication fails.
         * If either this or strict() returns true, local authentication is not used.
         *
-        * @param string $username username.
-        * @return Boolean
+        * @param string $username Username.
+        * @return bool
         */
        public function strictUserAuth( $username ) {
                return false;
@@ -279,8 +278,8 @@ class AuthPlugin {
         * The User object is passed by reference so it can be modified; don't
         * forget the & on your function declaration.
         *
-        * @param $user User object.
-        * @param $autocreate Boolean: True if user is being autocreated on login
+        * @param User $user
+        * @param bool $autocreate True if user is being autocreated on login
         */
        public function initUser( &$user, $autocreate = false ) {
                # Override this to do something.
@@ -289,7 +288,7 @@ class AuthPlugin {
        /**
         * If you want to munge the case of an account name before the final
         * check, now is your chance.
-        * @param $username string
+        * @param string $username
         * @return string
         */
        public function getCanonicalName( $username ) {
@@ -299,7 +298,7 @@ class AuthPlugin {
        /**
         * Get an instance of a User object
         *
-        * @param $user User
+        * @param User $user
         *
         * @return AuthPluginUser
         */
index 0706fe3..6ee62e0 100644 (file)
@@ -33,7 +33,6 @@ $wgAutoloadLocalClasses = array(
        'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
        'AjaxResponse' => 'includes/AjaxResponse.php',
        'AlphabeticPager' => 'includes/Pager.php',
-       'ArrayUtils' => 'includes/ArrayUtils.php',
        'Article' => 'includes/Article.php',
        'AtomFeed' => 'includes/Feed.php',
        'AuthPlugin' => 'includes/AuthPlugin.php',
@@ -47,31 +46,17 @@ $wgAutoloadLocalClasses = array(
        'Categoryfinder' => 'includes/Categoryfinder.php',
        'CategoryPage' => 'includes/CategoryPage.php',
        'CategoryViewer' => 'includes/CategoryViewer.php',
-       'CdbFunctions' => 'includes/Cdb_PHP.php',
-       'CdbReader' => 'includes/Cdb.php',
-       'CdbReader_DBA' => 'includes/Cdb.php',
-       'CdbReader_PHP' => 'includes/Cdb_PHP.php',
-       'CdbWriter' => 'includes/Cdb.php',
-       'CdbWriter_DBA' => 'includes/Cdb.php',
-       'CdbWriter_PHP' => 'includes/Cdb_PHP.php',
        'ChangesFeed' => 'includes/ChangesFeed.php',
        'ChangeTags' => 'includes/ChangeTags.php',
        'ChannelFeed' => 'includes/Feed.php',
        'Collation' => 'includes/Collation.php',
        'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
-       'ConfEditor' => 'includes/ConfEditor.php',
-       'ConfEditorParseError' => 'includes/ConfEditor.php',
-       'ConfEditorToken' => 'includes/ConfEditor.php',
        'Cookie' => 'includes/Cookie.php',
        'CookieJar' => 'includes/Cookie.php',
        'CurlHttpRequest' => 'includes/HttpFunctions.php',
-       'DeferrableUpdate' => 'includes/DeferredUpdates.php',
-       'DeferredUpdates' => 'includes/DeferredUpdates.php',
-       'MWCallableUpdate' => 'includes/CallableUpdate.php',
        'DeprecatedGlobal' => 'includes/DeprecatedGlobal.php',
        'DerivativeRequest' => 'includes/WebRequest.php',
        'DiffHistoryBlob' => 'includes/HistoryBlob.php',
-       'DoubleReplacer' => 'includes/StringUtils.php',
        'DummyLinker' => 'includes/Linker.php',
        'Dump7ZipOutput' => 'includes/Export.php',
        'DumpBZip2Output' => 'includes/Export.php',
@@ -87,7 +72,6 @@ $wgAutoloadLocalClasses = array(
        'EditPage' => 'includes/EditPage.php',
        'EmailNotification' => 'includes/UserMailer.php',
        'ErrorPageError' => 'includes/Exception.php',
-       'ExplodeIterator' => 'includes/StringUtils.php',
        'FakeTitle' => 'includes/FakeTitle.php',
        'Fallback' => 'includes/Fallback.php',
        'FatalError' => 'includes/Exception.php',
@@ -102,8 +86,6 @@ $wgAutoloadLocalClasses = array(
        'FormOptions' => 'includes/FormOptions.php',
        'FormSpecialPage' => 'includes/SpecialPage.php',
        'GitInfo' => 'includes/GitInfo.php',
-       'HashRing' => 'includes/HashRing.php',
-       'HashtableReplacer' => 'includes/StringUtils.php',
        'HistoryBlob' => 'includes/HistoryBlob.php',
        'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
        'HistoryBlobStub' => 'includes/HistoryBlob.php',
@@ -145,33 +127,27 @@ $wgAutoloadLocalClasses = array(
        'IncludableSpecialPage' => 'includes/SpecialPage.php',
        'IndexPager' => 'includes/Pager.php',
        'Interwiki' => 'includes/interwiki/Interwiki.php',
-       'IP' => 'includes/IP.php',
        'LCStore' => 'includes/cache/LocalisationCache.php',
-       'LCStore_Accel' => 'includes/cache/LocalisationCache.php',
-       'LCStore_CDB' => 'includes/cache/LocalisationCache.php',
-       'LCStore_DB' => 'includes/cache/LocalisationCache.php',
-       'LCStore_Null' => 'includes/cache/LocalisationCache.php',
+       'LCStoreAccel' => 'includes/cache/LocalisationCache.php',
+       'LCStoreCDB' => 'includes/cache/LocalisationCache.php',
+       'LCStoreDB' => 'includes/cache/LocalisationCache.php',
+       'LCStoreNull' => 'includes/cache/LocalisationCache.php',
        'License' => 'includes/Licenses.php',
        'Licenses' => 'includes/Licenses.php',
        'Linker' => 'includes/Linker.php',
        'LinkFilter' => 'includes/LinkFilter.php',
-       'LinksUpdate' => 'includes/LinksUpdate.php',
-       'LinksDeletionUpdate' => 'includes/LinksUpdate.php',
        'LocalisationCache' => 'includes/cache/LocalisationCache.php',
-       'LocalisationCache_BulkLoad' => 'includes/cache/LocalisationCache.php',
+       'LocalisationCacheBulkLoad' => 'includes/cache/LocalisationCache.php',
        'MagicWord' => 'includes/MagicWord.php',
        'MagicWordArray' => 'includes/MagicWord.php',
        'MailAddress' => 'includes/UserMailer.php',
-       'MappedIterator' => 'includes/MappedIterator.php',
        'MediaWiki' => 'includes/Wiki.php',
        'MediaWiki_I18N' => 'includes/SkinTemplate.php',
        'Message' => 'includes/Message.php',
        'MessageBlobStore' => 'includes/MessageBlobStore.php',
        'MimeMagic' => 'includes/MimeMagic.php',
-       'MWCryptRand' => 'includes/MWCryptRand.php',
        'MWException' => 'includes/Exception.php',
        'MWExceptionHandler' => 'includes/Exception.php',
-       'MWFunction' => 'includes/MWFunction.php',
        'MWHookException' => 'includes/Hooks.php',
        'MWHttpRequest' => 'includes/HttpFunctions.php',
        'MWInit' => 'includes/Init.php',
@@ -201,9 +177,6 @@ $wgAutoloadLocalClasses = array(
        'ReadOnlyError' => 'includes/Exception.php',
        'RedirectSpecialArticle' => 'includes/SpecialPage.php',
        'RedirectSpecialPage' => 'includes/SpecialPage.php',
-       'RegexlikeReplacer' => 'includes/StringUtils.php',
-       'ReplacementArray' => 'includes/StringUtils.php',
-       'Replacer' => 'includes/StringUtils.php',
        'ReverseChronologicalPager' => 'includes/Pager.php',
        'RevisionItem' => 'includes/RevisionList.php',
        'RevisionItemBase' => 'includes/RevisionList.php',
@@ -212,14 +185,9 @@ $wgAutoloadLocalClasses = array(
        'RevisionList' => 'includes/RevisionList.php',
        'RSSFeed' => 'includes/Feed.php',
        'Sanitizer' => 'includes/Sanitizer.php',
-       'DataUpdate' => 'includes/DataUpdate.php',
-       'SqlDataUpdate' => 'includes/SqlDataUpdate.php',
-       'ScopedCallback' => 'includes/ScopedCallback.php',
-       'ScopedPHPTimeout' => 'includes/ScopedPHPTimeout.php',
        'SiteConfiguration' => 'includes/SiteConfiguration.php',
        'SiteStats' => 'includes/SiteStats.php',
        'SiteStatsInit' => 'includes/SiteStats.php',
-       'SiteStatsUpdate' => 'includes/SiteStats.php',
        'Skin' => 'includes/Skin.php',
        'SkinTemplate' => 'includes/SkinTemplate.php',
        'SpecialCreateAccount' => 'includes/SpecialPage.php',
@@ -238,7 +206,6 @@ $wgAutoloadLocalClasses = array(
        'StatCounter' => 'includes/StatCounter.php',
        'Status' => 'includes/Status.php',
        'StreamFile' => 'includes/StreamFile.php',
-       'StringUtils' => 'includes/StringUtils.php',
        'StubContLang' => 'includes/StubObject.php',
        'StubObject' => 'includes/StubObject.php',
        'StubUserLang' => 'includes/StubObject.php',
@@ -249,7 +216,6 @@ $wgAutoloadLocalClasses = array(
        'TitleArray' => 'includes/TitleArray.php',
        'TitleArrayFromResult' => 'includes/TitleArray.php',
        'ThrottledError' => 'includes/Exception.php',
-       'UIDGenerator' => 'includes/UIDGenerator.php',
        'UnlistedSpecialPage' => 'includes/SpecialPage.php',
        'UploadSourceAdapter' => 'includes/Import.php',
        'UppercaseCollation' => 'includes/Collation.php',
@@ -261,7 +227,6 @@ $wgAutoloadLocalClasses = array(
        'UserCache' => 'includes/cache/UserCache.php',
        'UserMailer' => 'includes/UserMailer.php',
        'UserRightsProxy' => 'includes/UserRightsProxy.php',
-       'ViewCountUpdate' => 'includes/ViewCountUpdate.php',
        'WantedQueryPage' => 'includes/QueryPage.php',
        'WatchedItem' => 'includes/WatchedItem.php',
        'WebRequest' => 'includes/WebRequest.php',
@@ -283,25 +248,7 @@ $wgAutoloadLocalClasses = array(
        'XmlJsCode' => 'includes/Xml.php',
        'XMLReader2' => 'includes/Import.php',
        'XmlSelect' => 'includes/Xml.php',
-       'XmlTypeCheck' => 'includes/XmlTypeCheck.php',
        'ZhClient' => 'includes/ZhClient.php',
-       'ZipDirectoryReader' => 'includes/ZipDirectoryReader.php',
-       'ZipDirectoryReaderError' => 'includes/ZipDirectoryReader.php',
-
-       # content handler
-       'AbstractContent' => 'includes/content/AbstractContent.php',
-       'ContentHandler' => 'includes/content/ContentHandler.php',
-       'Content' => 'includes/content/Content.php',
-       'CssContentHandler' => 'includes/content/CssContentHandler.php',
-       'CssContent' => 'includes/content/CssContent.php',
-       'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
-       'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
-       'MessageContent' => 'includes/content/MessageContent.php',
-       'MWContentSerializationException' => 'includes/content/ContentHandler.php',
-       'TextContentHandler' => 'includes/content/TextContentHandler.php',
-       'TextContent' => 'includes/content/TextContent.php',
-       'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
-       'WikitextContent' => 'includes/content/WikitextContent.php',
 
        # includes/actions
        'CachedAction' => 'includes/actions/CachedAction.php',
@@ -440,17 +387,14 @@ $wgAutoloadLocalClasses = array(
        'FileDependency' => 'includes/cache/CacheDependency.php',
        'GenderCache' => 'includes/cache/GenderCache.php',
        'GlobalDependency' => 'includes/cache/CacheDependency.php',
-       'HTMLCacheUpdate' => 'includes/cache/HTMLCacheUpdate.php',
        'HTMLFileCache' => 'includes/cache/HTMLFileCache.php',
        'LinkBatch' => 'includes/cache/LinkBatch.php',
        'LinkCache' => 'includes/cache/LinkCache.php',
+       'MapCacheLRU' => 'includes/cache/MapCacheLRU.php',
        'MessageCache' => 'includes/cache/MessageCache.php',
        'ObjectFileCache' => 'includes/cache/ObjectFileCache.php',
        'ProcessCacheLRU' => 'includes/cache/ProcessCacheLRU.php',
        'ResourceFileCache' => 'includes/cache/ResourceFileCache.php',
-       'SquidUpdate' => 'includes/cache/SquidUpdate.php',
-       'TitleDependency' => 'includes/cache/CacheDependency.php',
-       'TitleListDependency' => 'includes/cache/CacheDependency.php',
 
        # includes/changes
        'ChangesList' => 'includes/changes/ChangesList.php',
@@ -463,6 +407,21 @@ $wgAutoloadLocalClasses = array(
        'RedisConnectionPool' => 'includes/clientpool/RedisConnectionPool.php',
        'RedisConnRef' => 'includes/clientpool/RedisConnectionPool.php',
 
+       # includes/content
+       'AbstractContent' => 'includes/content/AbstractContent.php',
+       'ContentHandler' => 'includes/content/ContentHandler.php',
+       'Content' => 'includes/content/Content.php',
+       'CssContentHandler' => 'includes/content/CssContentHandler.php',
+       'CssContent' => 'includes/content/CssContent.php',
+       'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+       'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
+       'MessageContent' => 'includes/content/MessageContent.php',
+       'MWContentSerializationException' => 'includes/content/ContentHandler.php',
+       'TextContentHandler' => 'includes/content/TextContentHandler.php',
+       'TextContent' => 'includes/content/TextContent.php',
+       'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
+       'WikitextContent' => 'includes/content/WikitextContent.php',
+
        # includes/context
        'ContextSource' => 'includes/context/ContextSource.php',
        'DerivativeContext' => 'includes/context/DerivativeContext.php',
@@ -530,22 +489,36 @@ $wgAutoloadLocalClasses = array(
        # includes/debug
        'MWDebug' => 'includes/debug/Debug.php',
 
+       # includes/deferred
+       'DataUpdate' => 'includes/deferred/DataUpdate.php',
+       'DeferrableUpdate' => 'includes/deferred/DeferredUpdates.php',
+       'DeferredUpdates' => 'includes/deferred/DeferredUpdates.php',
+       'HTMLCacheUpdate' => 'includes/deferred/HTMLCacheUpdate.php',
+       'LinksDeletionUpdate' => 'includes/deferred/LinksUpdate.php',
+       'LinksUpdate' => 'includes/deferred/LinksUpdate.php',
+       'MWCallableUpdate' => 'includes/deferred/CallableUpdate.php',
+       'SearchUpdate' => 'includes/deferred/SearchUpdate.php',
+       'SiteStatsUpdate' => 'includes/deferred/SiteStatsUpdate.php',
+       'SqlDataUpdate' => 'includes/deferred/SqlDataUpdate.php',
+       'SquidUpdate' => 'includes/deferred/SquidUpdate.php',
+       'ViewCountUpdate' => 'includes/deferred/ViewCountUpdate.php',
+
        # includes/diff
-       '_DiffEngine' => 'includes/diff/DairikiDiff.php',
-       '_DiffOp' => 'includes/diff/DairikiDiff.php',
-       '_DiffOp_Add' => 'includes/diff/DairikiDiff.php',
-       '_DiffOp_Change' => 'includes/diff/DairikiDiff.php',
-       '_DiffOp_Copy' => 'includes/diff/DairikiDiff.php',
-       '_DiffOp_Delete' => 'includes/diff/DairikiDiff.php',
-       '_HWLDF_WordAccumulator' => 'includes/diff/DairikiDiff.php',
-       'ArrayDiffFormatter' => 'includes/diff/DairikiDiff.php',
+       'DiffEngine' => 'includes/diff/DairikiDiff.php',
+       'DiffOp' => 'includes/diff/DairikiDiff.php',
+       'DiffOpAdd' => 'includes/diff/DairikiDiff.php',
+       'DiffOpChange' => 'includes/diff/DairikiDiff.php',
+       'DiffOpCopy' => 'includes/diff/DairikiDiff.php',
+       'DiffOpDelete' => 'includes/diff/DairikiDiff.php',
+       'HWLDFWordAccumulator' => 'includes/diff/DairikiDiff.php',
+       'ArrayDiffFormatter' => 'includes/diff/ArrayDiffFormatter.php',
        'Diff' => 'includes/diff/DairikiDiff.php',
        'DifferenceEngine' => 'includes/diff/DifferenceEngine.php',
-       'DiffFormatter' => 'includes/diff/DairikiDiff.php',
+       'DiffFormatter' => 'includes/diff/DiffFormatter.php',
        'MappedDiff' => 'includes/diff/DairikiDiff.php',
        'RangeDifference' => 'includes/diff/WikiDiff3.php',
-       'TableDiffFormatter' => 'includes/diff/DairikiDiff.php',
-       'UnifiedDiffFormatter' => 'includes/diff/DairikiDiff.php',
+       'TableDiffFormatter' => 'includes/diff/TableDiffFormatter.php',
+       'UnifiedDiffFormatter' => 'includes/diff/UnifiedDiffFormatter.php',
        'WikiDiff3' => 'includes/diff/WikiDiff3.php',
        'WordLevelDiff' => 'includes/diff/DairikiDiff.php',
 
@@ -685,11 +658,14 @@ $wgAutoloadLocalClasses = array(
        'HTMLCacheUpdateJob' => 'includes/job/jobs/HTMLCacheUpdateJob.php',
        'NullJob' => 'includes/job/jobs/NullJob.php',
        'RefreshLinksJob' => 'includes/job/jobs/RefreshLinksJob.php',
-       'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob.php',
+       'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob2.php',
        'UploadFromUrlJob' => 'includes/job/jobs/UploadFromUrlJob.php',
        'AssembleUploadChunksJob' => 'includes/job/jobs/AssembleUploadChunksJob.php',
        'PublishStashedFileJob' => 'includes/job/jobs/PublishStashedFileJob.php',
 
+       # includes/job/utils
+       'BacklinkJobUtils' => 'includes/job/utils/BacklinkJobUtils.php',
+
        # includes/json
        'FormatJson' => 'includes/json/FormatJson.php',
 
@@ -708,6 +684,8 @@ $wgAutoloadLocalClasses = array(
        'JSParser' => 'includes/libs/jsminplus.php',
        'JSToken' => 'includes/libs/jsminplus.php',
        'JSTokenizer' => 'includes/libs/jsminplus.php',
+       'ScopedPHPTimeout' => 'includes/libs/ScopedPHPTimeout.php',
+       'XmlTypeCheck' => 'includes/libs/XmlTypeCheck.php',
 
        # includes/libs/lessphp
        'lessc' => 'includes/libs/lessc.inc.php',
@@ -867,12 +845,14 @@ $wgAutoloadLocalClasses = array(
        'ResourceLoaderNoscriptModule' => 'includes/resourceloader/ResourceLoaderNoscriptModule.php',
        'ResourceLoaderSiteModule' => 'includes/resourceloader/ResourceLoaderSiteModule.php',
        'ResourceLoaderStartUpModule' => 'includes/resourceloader/ResourceLoaderStartUpModule.php',
-       'ResourceLoaderUserCSSPrefsModule' => 'includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php',
+       'ResourceLoaderUserCSSPrefsModule' =>
+               'includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php',
        'ResourceLoaderUserGroupsModule' => 'includes/resourceloader/ResourceLoaderUserGroupsModule.php',
        'ResourceLoaderUserModule' => 'includes/resourceloader/ResourceLoaderUserModule.php',
        'ResourceLoaderUserOptionsModule' => 'includes/resourceloader/ResourceLoaderUserOptionsModule.php',
        'ResourceLoaderUserTokensModule' => 'includes/resourceloader/ResourceLoaderUserTokensModule.php',
-       'ResourceLoaderLanguageDataModule' => 'includes/resourceloader/ResourceLoaderLanguageDataModule.php',
+       'ResourceLoaderLanguageDataModule' =>
+               'includes/resourceloader/ResourceLoaderLanguageDataModule.php',
        'ResourceLoaderWikiModule' => 'includes/resourceloader/ResourceLoaderWikiModule.php',
 
        # includes/revisiondelete
@@ -909,7 +889,6 @@ $wgAutoloadLocalClasses = array(
        'SearchResultSet' => 'includes/search/SearchEngine.php',
        'SearchResultTooMany' => 'includes/search/SearchEngine.php',
        'SearchSqlite' => 'includes/search/SearchSqlite.php',
-       'SearchUpdate' => 'includes/search/SearchUpdate.php',
        'SqliteSearchResultSet' => 'includes/search/SearchSqlite.php',
        'SqlSearchResultSet' => 'includes/search/SearchEngine.php',
 
@@ -983,6 +962,7 @@ $wgAutoloadLocalClasses = array(
        'SpecialContributions' => 'includes/specials/SpecialContributions.php',
        'SpecialEditWatchlist' => 'includes/specials/SpecialEditWatchlist.php',
        'SpecialEmailUser' => 'includes/specials/SpecialEmailuser.php',
+       'SpecialExpandTemplates' => 'includes/specials/SpecialExpandTemplates.php',
        'SpecialExport' => 'includes/specials/SpecialExport.php',
        'SpecialFilepath' => 'includes/specials/SpecialFilepath.php',
        'SpecialImport' => 'includes/specials/SpecialImport.php',
@@ -1067,6 +1047,36 @@ $wgAutoloadLocalClasses = array(
        'UploadStashWrongOwnerException' => 'includes/upload/UploadStash.php',
        'UploadStashNoSuchKeyException' => 'includes/upload/UploadStash.php',
 
+       # includes/utils
+       'ArrayUtils' => 'includes/utils/ArrayUtils.php',
+       'CdbException' => 'includes/utils/Cdb.php',
+       'CdbFunctions' => 'includes/utils/CdbPHP.php',
+       'CdbReader' => 'includes/utils/Cdb.php',
+       'CdbReaderDBA' => 'includes/utils/CdbDBA.php',
+       'CdbReaderPHP' => 'includes/utils/CdbPHP.php',
+       'CdbWriter' => 'includes/utils/Cdb.php',
+       'CdbWriterDBA' => 'includes/utils/CdbDBA.php',
+       'CdbWriterPHP' => 'includes/utils/CdbPHP.php',
+       'ConfEditor' => 'includes/utils/ConfEditor.php',
+       'ConfEditorParseError' => 'includes/utils/ConfEditor.php',
+       'ConfEditorToken' => 'includes/utils/ConfEditor.php',
+       'DoubleReplacer' => 'includes/utils/StringUtils.php',
+       'ExplodeIterator' => 'includes/utils/StringUtils.php',
+       'HashRing' => 'includes/utils/HashRing.php',
+       'HashtableReplacer' => 'includes/utils/StringUtils.php',
+       'IP' => 'includes/utils/IP.php',
+       'MWCryptRand' => 'includes/utils/MWCryptRand.php',
+       'MWFunction' => 'includes/utils/MWFunction.php',
+       'MappedIterator' => 'includes/utils/MappedIterator.php',
+       'RegexlikeReplacer' => 'includes/utils/StringUtils.php',
+       'ReplacementArray' => 'includes/utils/StringUtils.php',
+       'Replacer' => 'includes/utils/StringUtils.php',
+       'ScopedCallback' => 'includes/utils/ScopedCallback.php',
+       'StringUtils' => 'includes/utils/StringUtils.php',
+       'UIDGenerator' => 'includes/utils/UIDGenerator.php',
+       'ZipDirectoryReader' => 'includes/utils/ZipDirectoryReader.php',
+       'ZipDirectoryReaderError' => 'includes/utils/ZipDirectoryReader.php',
+
        # languages
        'ConverterRule' => 'languages/LanguageConverter.php',
        'FakeConverter' => 'languages/Language.php',
@@ -1108,13 +1118,13 @@ $wgAutoloadLocalClasses = array(
        'UserDupes' => 'maintenance/userDupes.inc',
 
        # maintenance/language
-       'csvStatsOutput' => 'maintenance/language/StatOutputs.php',
-       'extensionLanguages' => 'maintenance/language/languages.inc',
-       'languages' => 'maintenance/language/languages.inc',
+       'CsvStatsOutput' => 'maintenance/language/StatOutputs.php',
+       'ExtensionLanguages' => 'maintenance/language/languages.inc',
+       'Languages' => 'maintenance/language/languages.inc',
        'MessageWriter' => 'maintenance/language/writeMessagesArray.inc',
-       'statsOutput' => 'maintenance/language/StatOutputs.php',
-       'textStatsOutput' => 'maintenance/language/StatOutputs.php',
-       'wikiStatsOutput' => 'maintenance/language/StatOutputs.php',
+       'StatsOutput' => 'maintenance/language/StatOutputs.php',
+       'TextStatsOutput' => 'maintenance/language/StatOutputs.php',
+       'WikiStatsOutput' => 'maintenance/language/StatOutputs.php',
 
        # maintenance/term
        'AnsiTermColorer' => 'maintenance/term/MWTerm.php',
@@ -1136,6 +1146,8 @@ $wgAutoloadLocalClasses = array(
 );
 
 class AutoLoader {
+       static protected $autoloadLocalClassesLower = null;
+
        /**
         * autoload - take a class name and attempt to load it
         *
@@ -1145,7 +1157,8 @@ class AutoLoader {
         * as well.
         */
        static function autoload( $className ) {
-               global $wgAutoloadClasses, $wgAutoloadLocalClasses;
+               global $wgAutoloadClasses, $wgAutoloadLocalClasses,
+                       $wgAutoloadAttemptLowercase;
 
                // Workaround for PHP bug <https://bugs.php.net/bug.php?id=49143> (5.3.2. is broken, it's
                // fixed in 5.3.6). Strip leading backslashes from class names. When namespaces are used,
@@ -1156,30 +1169,42 @@ class AutoLoader {
                // do not strip the leading backlash in this case, causing autoloading to fail.
                $className = ltrim( $className, '\\' );
 
+               $filename = false;
+
                if ( isset( $wgAutoloadLocalClasses[$className] ) ) {
                        $filename = $wgAutoloadLocalClasses[$className];
                } elseif ( isset( $wgAutoloadClasses[$className] ) ) {
                        $filename = $wgAutoloadClasses[$className];
-               } else {
-                       # Try a different capitalisation
-                       # The case can sometimes be wrong when unserializing PHP 4 objects
-                       $filename = false;
+               } elseif ( $wgAutoloadAttemptLowercase ) {
+                       /*
+                        * Try a different capitalisation.
+                        *
+                        * PHP 4 objects are always serialized with the classname coerced to lowercase,
+                        * and we are plagued with several legacy uses created by MediaWiki < 1.5, see
+                        * https://wikitech.wikimedia.org/wiki/Text_storage_data
+                        */
                        $lowerClass = strtolower( $className );
 
-                       foreach ( $wgAutoloadLocalClasses as $class2 => $file2 ) {
-                               if ( strtolower( $class2 ) == $lowerClass ) {
-                                       $filename = $file2;
-                               }
+                       if ( self::$autoloadLocalClassesLower === null ) {
+                               self::$autoloadLocalClassesLower = array_change_key_case( $wgAutoloadLocalClasses, CASE_LOWER );
                        }
 
-                       if ( !$filename ) {
+                       if ( isset( self::$autoloadLocalClassesLower[$lowerClass] ) ) {
                                if ( function_exists( 'wfDebug' ) ) {
-                                       wfDebug( "Class {$className} not found; skipped loading\n" );
+                                       wfDebug( "Class {$className} was loaded using incorrect case.\n" );
                                }
+                               $filename = self::$autoloadLocalClassesLower[$lowerClass];
+                       }
+               }
 
-                               # Give up
-                               return false;
+               if ( !$filename ) {
+                       if ( function_exists( 'wfDebug' ) ) {
+                               # FIXME: This is not very polite.  Assume we do not manage the class.
+                               wfDebug( "Class {$className} not found; skipped loading\n" );
                        }
+
+                       # Give up
+                       return false;
                }
 
                # Make an absolute path, this improves performance by avoiding some stat calls
@@ -1204,6 +1229,14 @@ class AutoLoader {
        static function loadClass( $class ) {
                return class_exists( $class );
        }
+
+       /**
+        * Method to clear the protected class property $autoloadLocalClassesLower.
+        * Used in tests.
+        */
+       static function resetAutoloadLocalClassesLower() {
+               self::$autoloadLocalClassesLower = null;
+       }
 }
 
 spl_autoload_register( array( 'AutoLoader', 'autoload' ) );
index 34b89e7..8673a3d 100644 (file)
@@ -63,8 +63,8 @@ class Block {
         */
        function __construct( $address = '', $user = 0, $by = 0, $reason = '',
                $timestamp = 0, $auto = 0, $expiry = '', $anonOnly = 0, $createAccount = 0, $enableAutoblock = 0,
-               $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = '' )
-       {
+               $hideName = 0, $blockEmail = 0, $allowUsertalk = 0, $byText = ''
+       {
                if ( $timestamp === 0 ) {
                        $timestamp = wfTimestampNow();
                }
@@ -1083,7 +1083,6 @@ class Block {
                return null;
        }
 
-
        /**
         * Get all blocks that match any IP from an array of IP addresses
         *
diff --git a/includes/CallableUpdate.php b/includes/CallableUpdate.php
deleted file mode 100644 (file)
index 6eb5541..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * Deferrable Update for closure/callback
- */
-class MWCallableUpdate implements DeferrableUpdate {
-
-       /**
-        * @var closure/callabck
-        */
-       private $callback;
-
-       /**
-        * @param callable $callback
-        */
-       public function __construct( $callback ) {
-               if ( !is_callable( $callback ) ) {
-                       throw new MWException( 'Not a valid callback/closure!' );
-               }
-               $this->callback = $callback;
-       }
-
-       /**
-        * Run the update
-        */
-       public function doUpdate() {
-               call_user_func( $this->callback );
-       }
-
-}
diff --git a/includes/Cdb.php b/includes/Cdb.php
deleted file mode 100644 (file)
index 81c0afe..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-<?php
-/**
- * Native CDB file reader and writer.
- *
- * 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
- */
-
-/**
- * Read from a CDB file.
- * Native and pure PHP implementations are provided.
- * http://cr.yp.to/cdb.html
- */
-abstract class CdbReader {
-       /**
-        * Open a file and return a subclass instance
-        *
-        * @param $fileName string
-        *
-        * @return CdbReader
-        */
-       public static function open( $fileName ) {
-               if ( self::haveExtension() ) {
-                       return new CdbReader_DBA( $fileName );
-               } else {
-                       wfDebug( "Warning: no dba extension found, using emulation.\n" );
-                       return new CdbReader_PHP( $fileName );
-               }
-       }
-
-       /**
-        * Returns true if the native extension is available
-        *
-        * @return bool
-        */
-       public static function haveExtension() {
-               if ( !function_exists( 'dba_handlers' ) ) {
-                       return false;
-               }
-               $handlers = dba_handlers();
-               if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
-                       return false;
-               }
-               return true;
-       }
-
-       /**
-        * Construct the object and open the file
-        */
-       abstract function __construct( $fileName );
-
-       /**
-        * Close the file. Optional, you can just let the variable go out of scope.
-        */
-       abstract function close();
-
-       /**
-        * Get a value with a given key. Only string values are supported.
-        *
-        * @param $key string
-        */
-       abstract public function get( $key );
-}
-
-/**
- * Write to a CDB file.
- * Native and pure PHP implementations are provided.
- */
-abstract class CdbWriter {
-       /**
-        * Open a writer and return a subclass instance.
-        * The user must have write access to the directory, for temporary file creation.
-        *
-        * @param $fileName string
-        *
-        * @return CdbWriter_DBA|CdbWriter_PHP
-        */
-       public static function open( $fileName ) {
-               if ( CdbReader::haveExtension() ) {
-                       return new CdbWriter_DBA( $fileName );
-               } else {
-                       wfDebug( "Warning: no dba extension found, using emulation.\n" );
-                       return new CdbWriter_PHP( $fileName );
-               }
-       }
-
-       /**
-        * Create the object and open the file
-        *
-        * @param $fileName string
-        */
-       abstract function __construct( $fileName );
-
-       /**
-        * Set a key to a given value. The value will be converted to string.
-        * @param $key string
-        * @param $value string
-        */
-       abstract public function set( $key, $value );
-
-       /**
-        * Close the writer object. You should call this function before the object
-        * goes out of scope, to write out the final hashtables.
-        */
-       abstract public function close();
-}
-
-/**
- * Reader class which uses the DBA extension
- */
-class CdbReader_DBA {
-       var $handle;
-
-       function __construct( $fileName ) {
-               $this->handle = dba_open( $fileName, 'r-', 'cdb' );
-               if ( !$this->handle ) {
-                       throw new MWException( 'Unable to open CDB file "' . $fileName . '"' );
-               }
-       }
-
-       function close() {
-               if ( isset( $this->handle ) ) {
-                       dba_close( $this->handle );
-               }
-               unset( $this->handle );
-       }
-
-       function get( $key ) {
-               return dba_fetch( $key, $this->handle );
-       }
-}
-
-/**
- * Writer class which uses the DBA extension
- */
-class CdbWriter_DBA {
-       var $handle, $realFileName, $tmpFileName;
-
-       function __construct( $fileName ) {
-               $this->realFileName = $fileName;
-               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
-               $this->handle = dba_open( $this->tmpFileName, 'n', 'cdb_make' );
-               if ( !$this->handle ) {
-                       throw new MWException( 'Unable to open CDB file for write "' . $fileName . '"' );
-               }
-       }
-
-       function set( $key, $value ) {
-               return dba_insert( $key, $value, $this->handle );
-       }
-
-       function close() {
-               if ( isset( $this->handle ) ) {
-                       dba_close( $this->handle );
-               }
-               if ( wfIsWindows() ) {
-                       unlink( $this->realFileName );
-               }
-               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
-                       throw new MWException( 'Unable to move the new CDB file into place.' );
-               }
-               unset( $this->handle );
-       }
-
-       function __destruct() {
-               if ( isset( $this->handle ) ) {
-                       $this->close();
-               }
-       }
-}
diff --git a/includes/Cdb_PHP.php b/includes/Cdb_PHP.php
deleted file mode 100644 (file)
index a38b9a8..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-<?php
-/**
- * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
- * appears in PHP 5.3. Changes are:
- *    * Error returns replaced with exceptions
- *    * Exception thrown if sizes or offsets are between 2GB and 4GB
- *    * Some variables renamed
- *
- * 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
- */
-
-/**
- * Common functions for readers and writers
- */
-class CdbFunctions {
-       /**
-        * Take a modulo of a signed integer as if it were an unsigned integer.
-        * $b must be less than 0x40000000 and greater than 0
-        *
-        * @param $a
-        * @param $b
-        *
-        * @return int
-        */
-       public static function unsignedMod( $a, $b ) {
-               if ( $a & 0x80000000 ) {
-                       $m = ( $a & 0x7fffffff ) % $b + 2 * ( 0x40000000 % $b );
-                       return $m % $b;
-               } else {
-                       return $a % $b;
-               }
-       }
-
-       /**
-        * Shift a signed integer right as if it were unsigned
-        * @param $a
-        * @param $b
-        * @return int
-        */
-       public static function unsignedShiftRight( $a, $b ) {
-               if ( $b == 0 ) {
-                       return $a;
-               }
-               if ( $a & 0x80000000 ) {
-                       return ( ( $a & 0x7fffffff ) >> $b ) | ( 0x40000000 >> ( $b - 1 ) );
-               } else {
-                       return $a >> $b;
-               }
-       }
-
-       /**
-        * The CDB hash function.
-        *
-        * @param $s string
-        *
-        * @return
-        */
-       public static function hash( $s ) {
-               $h = 5381;
-               for ( $i = 0; $i < strlen( $s ); $i++ ) {
-                       $h5 = ( $h << 5 ) & 0xffffffff;
-                       // Do a 32-bit sum
-                       // Inlined here for speed
-                       $sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff );
-                       $h =
-                               (
-                                       ( $sum & 0x40000000 ? 1 : 0 )
-                                       + ( $h & 0x80000000 ? 2 : 0 )
-                                       + ( $h & 0x40000000 ? 1 : 0 )
-                                       + ( $h5 & 0x80000000 ? 2 : 0 )
-                                       + ( $h5 & 0x40000000 ? 1 : 0 )
-                               ) << 30
-                               | ( $sum & 0x3fffffff );
-                       $h ^= ord( $s[$i] );
-                       $h &= 0xffffffff;
-               }
-               return $h;
-       }
-}
-
-/**
- * CDB reader class
- */
-class CdbReader_PHP extends CdbReader {
-       /** The filename */
-       var $fileName;
-
-       /** The file handle */
-       var $handle;
-
-       /* number of hash slots searched under this key */
-       var $loop;
-
-       /* initialized if loop is nonzero */
-       var $khash;
-
-       /* initialized if loop is nonzero */
-       var $kpos;
-
-       /* initialized if loop is nonzero */
-       var $hpos;
-
-       /* initialized if loop is nonzero */
-       var $hslots;
-
-       /* initialized if findNext() returns true */
-       var $dpos;
-
-       /* initialized if cdb_findnext() returns 1 */
-       var $dlen;
-
-       /**
-        * @param $fileName string
-        * @throws MWException
-        */
-       function __construct( $fileName ) {
-               $this->fileName = $fileName;
-               $this->handle = fopen( $fileName, 'rb' );
-               if ( !$this->handle ) {
-                       throw new MWException( 'Unable to open CDB file "' . $this->fileName . '".' );
-               }
-               $this->findStart();
-       }
-
-       function close() {
-               if ( isset( $this->handle ) ) {
-                       fclose( $this->handle );
-               }
-               unset( $this->handle );
-       }
-
-       /**
-        * @param $key
-        * @return bool|string
-        */
-       public function get( $key ) {
-               // strval is required
-               if ( $this->find( strval( $key ) ) ) {
-                       return $this->read( $this->dlen, $this->dpos );
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * @param $key
-        * @param $pos
-        * @return bool
-        */
-       protected function match( $key, $pos ) {
-               $buf = $this->read( strlen( $key ), $pos );
-               return $buf === $key;
-       }
-
-       protected function findStart() {
-               $this->loop = 0;
-       }
-
-       /**
-        * @throws MWException
-        * @param $length
-        * @param $pos
-        * @return string
-        */
-       protected function read( $length, $pos ) {
-               if ( fseek( $this->handle, $pos ) == -1 ) {
-                       // This can easily happen if the internal pointers are incorrect
-                       throw new MWException(
-                               'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
-               }
-
-               if ( $length == 0 ) {
-                       return '';
-               }
-
-               $buf = fread( $this->handle, $length );
-               if ( $buf === false || strlen( $buf ) !== $length ) {
-                       throw new MWException(
-                               'Read from CDB file failed, file "' . $this->fileName . '" may be corrupted.' );
-               }
-               return $buf;
-       }
-
-       /**
-        * Unpack an unsigned integer and throw an exception if it needs more than 31 bits
-        * @param $s
-        * @throws MWException
-        * @return mixed
-        */
-       protected function unpack31( $s ) {
-               $data = unpack( 'V', $s );
-               if ( $data[1] > 0x7fffffff ) {
-                       throw new MWException(
-                               'Error in CDB file "' . $this->fileName . '", integer too big.' );
-               }
-               return $data[1];
-       }
-
-       /**
-        * Unpack a 32-bit signed integer
-        * @param $s
-        * @return int
-        */
-       protected function unpackSigned( $s ) {
-               $data = unpack( 'va/vb', $s );
-               return $data['a'] | ( $data['b'] << 16 );
-       }
-
-       /**
-        * @param $key
-        * @return bool
-        */
-       protected function findNext( $key ) {
-               if ( !$this->loop ) {
-                       $u = CdbFunctions::hash( $key );
-                       $buf = $this->read( 8, ( $u << 3 ) & 2047 );
-                       $this->hslots = $this->unpack31( substr( $buf, 4 ) );
-                       if ( !$this->hslots ) {
-                               return false;
-                       }
-                       $this->hpos = $this->unpack31( substr( $buf, 0, 4 ) );
-                       $this->khash = $u;
-                       $u = CdbFunctions::unsignedShiftRight( $u, 8 );
-                       $u = CdbFunctions::unsignedMod( $u, $this->hslots );
-                       $u <<= 3;
-                       $this->kpos = $this->hpos + $u;
-               }
-
-               while ( $this->loop < $this->hslots ) {
-                       $buf = $this->read( 8, $this->kpos );
-                       $pos = $this->unpack31( substr( $buf, 4 ) );
-                       if ( !$pos ) {
-                               return false;
-                       }
-                       $this->loop += 1;
-                       $this->kpos += 8;
-                       if ( $this->kpos == $this->hpos + ( $this->hslots << 3 ) ) {
-                               $this->kpos = $this->hpos;
-                       }
-                       $u = $this->unpackSigned( substr( $buf, 0, 4 ) );
-                       if ( $u === $this->khash ) {
-                               $buf = $this->read( 8, $pos );
-                               $keyLen = $this->unpack31( substr( $buf, 0, 4 ) );
-                               if ( $keyLen == strlen( $key ) && $this->match( $key, $pos + 8 ) ) {
-                                       // Found
-                                       $this->dlen = $this->unpack31( substr( $buf, 4 ) );
-                                       $this->dpos = $pos + 8 + $keyLen;
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * @param $key
-        * @return bool
-        */
-       protected function find( $key ) {
-               $this->findStart();
-               return $this->findNext( $key );
-       }
-}
-
-/**
- * CDB writer class
- */
-class CdbWriter_PHP extends CdbWriter {
-       var $handle, $realFileName, $tmpFileName;
-
-       var $hplist;
-       var $numentries, $pos;
-
-       /**
-        * @param $fileName string
-        */
-       function __construct( $fileName ) {
-               $this->realFileName = $fileName;
-               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
-               $this->handle = fopen( $this->tmpFileName, 'wb' );
-               if ( !$this->handle ) {
-                       $this->throwException(
-                               'Unable to open CDB file "' . $this->tmpFileName . '" for write.' );
-               }
-               $this->hplist = array();
-               $this->numentries = 0;
-               $this->pos = 2048; // leaving space for the pointer array, 256 * 8
-               if ( fseek( $this->handle, $this->pos ) == -1 ) {
-                       $this->throwException( 'fseek failed in file "' . $this->tmpFileName . '".' );
-               }
-       }
-
-       function __destruct() {
-               if ( isset( $this->handle ) ) {
-                       $this->close();
-               }
-       }
-
-       /**
-        * @param $key
-        * @param $value
-        * @return
-        */
-       public function set( $key, $value ) {
-               if ( strval( $key ) === '' ) {
-                       // DBA cross-check hack
-                       return;
-               }
-               $this->addbegin( strlen( $key ), strlen( $value ) );
-               $this->write( $key );
-               $this->write( $value );
-               $this->addend( strlen( $key ), strlen( $value ), CdbFunctions::hash( $key ) );
-       }
-
-       /**
-        * @throws MWException
-        */
-       public function close() {
-               $this->finish();
-               if ( isset( $this->handle ) ) {
-                       fclose( $this->handle );
-               }
-               if ( wfIsWindows() && file_exists( $this->realFileName ) ) {
-                       unlink( $this->realFileName );
-               }
-               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
-                       $this->throwException( 'Unable to move the new CDB file into place.' );
-               }
-               unset( $this->handle );
-       }
-
-       /**
-        * @throws MWException
-        * @param $buf
-        */
-       protected function write( $buf ) {
-               $len = fwrite( $this->handle, $buf );
-               if ( $len !== strlen( $buf ) ) {
-                       $this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
-               }
-       }
-
-       /**
-        * @throws MWException
-        * @param $len
-        */
-       protected function posplus( $len ) {
-               $newpos = $this->pos + $len;
-               if ( $newpos > 0x7fffffff ) {
-                       $this->throwException(
-                               'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
-               }
-               $this->pos = $newpos;
-       }
-
-       /**
-        * @param $keylen
-        * @param $datalen
-        * @param $h
-        */
-       protected function addend( $keylen, $datalen, $h ) {
-               $this->hplist[] = array(
-                       'h' => $h,
-                       'p' => $this->pos
-               );
-
-               $this->numentries++;
-               $this->posplus( 8 );
-               $this->posplus( $keylen );
-               $this->posplus( $datalen );
-       }
-
-       /**
-        * @throws MWException
-        * @param $keylen
-        * @param $datalen
-        */
-       protected function addbegin( $keylen, $datalen ) {
-               if ( $keylen > 0x7fffffff ) {
-                       $this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
-               }
-               if ( $datalen > 0x7fffffff ) {
-                       $this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
-               }
-               $buf = pack( 'VV', $keylen, $datalen );
-               $this->write( $buf );
-       }
-
-       /**
-        * @throws MWException
-        */
-       protected function finish() {
-               // Hack for DBA cross-check
-               $this->hplist = array_reverse( $this->hplist );
-
-               // Calculate the number of items that will be in each hashtable
-               $counts = array_fill( 0, 256, 0 );
-               foreach ( $this->hplist as $item ) {
-                       ++ $counts[255 & $item['h']];
-               }
-
-               // Fill in $starts with the *end* indexes
-               $starts = array();
-               $pos = 0;
-               for ( $i = 0; $i < 256; ++$i ) {
-                       $pos += $counts[$i];
-                       $starts[$i] = $pos;
-               }
-
-               // Excessively clever and indulgent code to simultaneously fill $packedTables
-               // with the packed hashtables, and adjust the elements of $starts
-               // to actually point to the starts instead of the ends.
-               $packedTables = array_fill( 0, $this->numentries, false );
-               foreach ( $this->hplist as $item ) {
-                       $packedTables[--$starts[255 & $item['h']]] = $item;
-               }
-
-               $final = '';
-               for ( $i = 0; $i < 256; ++$i ) {
-                       $count = $counts[$i];
-
-                       // The size of the hashtable will be double the item count.
-                       // The rest of the slots will be empty.
-                       $len = $count + $count;
-                       $final .= pack( 'VV', $this->pos, $len );
-
-                       $hashtable = array();
-                       for ( $u = 0; $u < $len; ++$u ) {
-                               $hashtable[$u] = array( 'h' => 0, 'p' => 0 );
-                       }
-
-                       // Fill the hashtable, using the next empty slot if the hashed slot
-                       // is taken.
-                       for ( $u = 0; $u < $count; ++$u ) {
-                               $hp = $packedTables[$starts[$i] + $u];
-                               $where = CdbFunctions::unsignedMod(
-                                       CdbFunctions::unsignedShiftRight( $hp['h'], 8 ), $len );
-                               while ( $hashtable[$where]['p'] ) {
-                                       if ( ++$where == $len ) {
-                                               $where = 0;
-                                       }
-                               }
-                               $hashtable[$where] = $hp;
-                       }
-
-                       // Write the hashtable
-                       for ( $u = 0; $u < $len; ++$u ) {
-                               $buf = pack( 'vvV',
-                                       $hashtable[$u]['h'] & 0xffff,
-                                       CdbFunctions::unsignedShiftRight( $hashtable[$u]['h'], 16 ),
-                                       $hashtable[$u]['p'] );
-                               $this->write( $buf );
-                               $this->posplus( 8 );
-                       }
-               }
-
-               // Write the pointer array at the start of the file
-               rewind( $this->handle );
-               if ( ftell( $this->handle ) != 0 ) {
-                       $this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
-               }
-               $this->write( $final );
-       }
-
-       /**
-        * Clean up the temp file and throw an exception
-        *
-        * @param $msg string
-        * @throws MWException
-        */
-       protected function throwException( $msg ) {
-               if ( $this->handle ) {
-                       fclose( $this->handle );
-                       unlink( $this->tmpFileName );
-               }
-               throw new MWException( $msg );
-       }
-}
index 3fc27f9..53f2955 100644 (file)
@@ -184,29 +184,27 @@ class ChangeTags {
 
                // Figure out which conditions can be done.
                if ( in_array( 'recentchanges', $tables ) ) {
-                       $join_cond = 'rc_id';
+                       $join_cond = 'ct_rc_id=rc_id';
                } elseif ( in_array( 'logging', $tables ) ) {
-                       $join_cond = 'log_id';
+                       $join_cond = 'ct_log_id=log_id';
                } elseif ( in_array( 'revision', $tables ) ) {
-                       $join_cond = 'rev_id';
+                       $join_cond = 'ct_rev_id=rev_id';
+               } elseif ( in_array( 'archive', $tables ) ) {
+                       $join_cond = 'ct_rev_id=ar_rev_id';
                } else {
                        throw new MWException( 'Unable to determine appropriate JOIN condition for tagging.' );
                }
 
-               // JOIN on tag_summary
-               $tables[] = 'tag_summary';
-               $join_conds['tag_summary'] = array( 'LEFT JOIN', "ts_$join_cond=$join_cond" );
-               $fields[] = 'ts_tags';
+               $fields['ts_tags'] = wfGetDB( DB_SLAVE )->buildGroupConcatField(
+                       ',', 'change_tag', 'ct_tag', $join_cond
+               );
 
                if ( $wgUseTagFilter && $filter_tag ) {
                        // Somebody wants to filter on a tag.
                        // Add an INNER JOIN on change_tag
 
-                       // FORCE INDEX -- change_tags will almost ALWAYS be the correct query plan.
-                       $options['USE INDEX'] = array( 'change_tag' => 'change_tag_tag_id' );
-                       unset( $options['FORCE INDEX'] );
                        $tables[] = 'change_tag';
-                       $join_conds['change_tag'] = array( 'INNER JOIN', "ct_$join_cond=$join_cond" );
+                       $join_conds['change_tag'] = array( 'INNER JOIN', $join_cond );
                        $conds['ct_tag'] = $filter_tag;
                }
        }
@@ -232,7 +230,7 @@ class ChangeTags {
                }
 
                $data = array( Html::rawElement( 'label', array( 'for' => 'tagfilter' ), wfMessage( 'tag-filter' )->parse() ),
-                       Xml::input( 'tagfilter', 20, $selected, array( 'class' => 'mw-tagfilter-input' ) ) );
+                       Xml::input( 'tagfilter', 20, $selected, array( 'class' => 'mw-tagfilter-input', 'id' => 'tagfilter' ) ) );
 
                if ( !$fullForm ) {
                        return $data;
index b0252c7..ac2187c 100644 (file)
@@ -319,9 +319,7 @@ class IcuCollation extends Collation {
 
                // Check for CJK
                $firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
-               if ( ord( $firstChar ) > 0x7f
-                       && self::isCjk( utf8ToCodepoint( $firstChar ) ) )
-               {
+               if ( ord( $firstChar ) > 0x7f && self::isCjk( utf8ToCodepoint( $firstChar ) ) ) {
                        return $firstChar;
                }
 
diff --git a/includes/ConfEditor.php b/includes/ConfEditor.php
deleted file mode 100644 (file)
index 67cb87d..0000000
+++ /dev/null
@@ -1,1109 +0,0 @@
-<?php
-/**
- * Configuration file editor.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * This is a state machine style parser with two internal stacks:
- *   * A next state stack, which determines the state the machine will progress to next
- *   * A path stack, which keeps track of the logical location in the file.
- *
- * Reference grammar:
- *
- * file = T_OPEN_TAG *statement
- * statement = T_VARIABLE "=" expression ";"
- * expression = array / scalar / T_VARIABLE
- * array = T_ARRAY "(" [ element *( "," element ) [ "," ] ] ")"
- * element = assoc-element / expression
- * assoc-element = scalar T_DOUBLE_ARROW expression
- * scalar = T_LNUMBER / T_DNUMBER / T_STRING / T_CONSTANT_ENCAPSED_STRING
- */
-class ConfEditor {
-       /** The text to parse */
-       var $text;
-
-       /** The token array from token_get_all() */
-       var $tokens;
-
-       /** The current position in the token array */
-       var $pos;
-
-       /** The current 1-based line number */
-       var $lineNum;
-
-       /** The current 1-based column number */
-       var $colNum;
-
-       /** The current 0-based byte number */
-       var $byteNum;
-
-       /** The current ConfEditorToken object */
-       var $currentToken;
-
-       /** The previous ConfEditorToken object */
-       var $prevToken;
-
-       /**
-        * The state machine stack. This is an array of strings where the topmost
-        * element will be popped off and become the next parser state.
-        */
-       var $stateStack;
-
-       /**
-        * The path stack is a stack of associative arrays with the following elements:
-        *    name              The name of top level of the path
-        *    level             The level (number of elements) of the path
-        *    startByte         The byte offset of the start of the path
-        *    startToken        The token offset of the start
-        *    endByte           The byte offset of thee
-        *    endToken          The token offset of the end, plus one
-        *    valueStartToken   The start token offset of the value part
-        *    valueStartByte    The start byte offset of the value part
-        *    valueEndToken     The end token offset of the value part, plus one
-        *    valueEndByte      The end byte offset of the value part, plus one
-        *    nextArrayIndex    The next numeric array index at this level
-        *    hasComma          True if the array element ends with a comma
-        *    arrowByte         The byte offset of the "=>", or false if there isn't one
-        */
-       var $pathStack;
-
-       /**
-        * The elements of the top of the pathStack for every path encountered, indexed
-        * by slash-separated path.
-        */
-       var $pathInfo;
-
-       /**
-        * Next serial number for whitespace placeholder paths (\@extra-N)
-        */
-       var $serial;
-
-       /**
-        * Editor state. This consists of the internal copy/insert operations which
-        * are applied to the source string to obtain the destination string.
-        */
-       var $edits;
-
-       /**
-        * Simple entry point for command-line testing
-        *
-        * @param $text string
-        *
-        * @return string
-        */
-       static function test( $text ) {
-               try {
-                       $ce = new self( $text );
-                       $ce->parse();
-               } catch ( ConfEditorParseError $e ) {
-                       return $e->getMessage() . "\n" . $e->highlight( $text );
-               }
-               return "OK";
-       }
-
-       /**
-        * Construct a new parser
-        */
-       public function __construct( $text ) {
-               $this->text = $text;
-       }
-
-       /**
-        * Edit the text. Returns the edited text.
-        * @param array $ops of operations.
-        *
-        * Operations are given as an associative array, with members:
-        *    type:     One of delete, set, append or insert (required)
-        *    path:     The path to operate on (required)
-        *    key:      The array key to insert/append, with PHP quotes
-        *    value:    The value, with PHP quotes
-        *
-        * delete
-        *    Deletes an array element or statement with the specified path.
-        *    e.g.
-        *        array('type' => 'delete', 'path' => '$foo/bar/baz' )
-        *    is equivalent to the runtime PHP code:
-        *        unset( $foo['bar']['baz'] );
-        *
-        * set
-        *    Sets the value of an array element. If the element doesn't exist, it
-        *    is appended to the array. If it does exist, the value is set, with
-        *    comments and indenting preserved.
-        *
-        * append
-        *    Appends a new element to the end of the array. Adds a trailing comma.
-        *    e.g.
-        *        array( 'type' => 'append', 'path', '$foo/bar',
-        *            'key' => 'baz', 'value' => "'x'" )
-        *    is like the PHP code:
-        *        $foo['bar']['baz'] = 'x';
-        *
-        * insert
-        *    Insert a new element at the start of the array.
-        *
-        * @throws MWException
-        * @return string
-        */
-       public function edit( $ops ) {
-               $this->parse();
-
-               $this->edits = array(
-                       array( 'copy', 0, strlen( $this->text ) )
-               );
-               foreach ( $ops as $op ) {
-                       $type = $op['type'];
-                       $path = $op['path'];
-                       $value = isset( $op['value'] ) ? $op['value'] : null;
-                       $key = isset( $op['key'] ) ? $op['key'] : null;
-
-                       switch ( $type ) {
-                       case 'delete':
-                               list( $start, $end ) = $this->findDeletionRegion( $path );
-                               $this->replaceSourceRegion( $start, $end, false );
-                               break;
-                       case 'set':
-                               if ( isset( $this->pathInfo[$path] ) ) {
-                                       list( $start, $end ) = $this->findValueRegion( $path );
-                                       $encValue = $value; // var_export( $value, true );
-                                       $this->replaceSourceRegion( $start, $end, $encValue );
-                                       break;
-                               }
-                               // No existing path, fall through to append
-                               $slashPos = strrpos( $path, '/' );
-                               $key = var_export( substr( $path, $slashPos + 1 ), true );
-                               $path = substr( $path, 0, $slashPos );
-                               // Fall through
-                       case 'append':
-                               // Find the last array element
-                               $lastEltPath = $this->findLastArrayElement( $path );
-                               if ( $lastEltPath === false ) {
-                                       throw new MWException( "Can't find any element of array \"$path\"" );
-                               }
-                               $lastEltInfo = $this->pathInfo[$lastEltPath];
-
-                               // Has it got a comma already?
-                               if ( strpos( $lastEltPath, '@extra' ) === false && !$lastEltInfo['hasComma'] ) {
-                                       // No comma, insert one after the value region
-                                       list( , $end ) = $this->findValueRegion( $lastEltPath );
-                                       $this->replaceSourceRegion( $end - 1, $end - 1, ',' );
-                               }
-
-                               // Make the text to insert
-                               list( $start, $end ) = $this->findDeletionRegion( $lastEltPath );
-
-                               if ( $key === null ) {
-                                       list( $indent, ) = $this->getIndent( $start );
-                                       $textToInsert = "$indent$value,";
-                               } else {
-                                       list( $indent, $arrowIndent ) =
-                                               $this->getIndent( $start, $key, $lastEltInfo['arrowByte'] );
-                                       $textToInsert = "$indent$key$arrowIndent=> $value,";
-                               }
-                               $textToInsert .= ( $indent === false ? ' ' : "\n" );
-
-                               // Insert the item
-                               $this->replaceSourceRegion( $end, $end, $textToInsert );
-                               break;
-                       case 'insert':
-                               // Find first array element
-                               $firstEltPath = $this->findFirstArrayElement( $path );
-                               if ( $firstEltPath === false ) {
-                                       throw new MWException( "Can't find array element of \"$path\"" );
-                               }
-                               list( $start, ) = $this->findDeletionRegion( $firstEltPath );
-                               $info = $this->pathInfo[$firstEltPath];
-
-                               // Make the text to insert
-                               if ( $key === null ) {
-                                       list( $indent, ) = $this->getIndent( $start );
-                                       $textToInsert = "$indent$value,";
-                               } else {
-                                       list( $indent, $arrowIndent ) =
-                                               $this->getIndent( $start, $key, $info['arrowByte'] );
-                                       $textToInsert = "$indent$key$arrowIndent=> $value,";
-                               }
-                               $textToInsert .= ( $indent === false ? ' ' : "\n" );
-
-                               // Insert the item
-                               $this->replaceSourceRegion( $start, $start, $textToInsert );
-                               break;
-                       default:
-                               throw new MWException( "Unrecognised operation: \"$type\"" );
-                       }
-               }
-
-               // Do the edits
-               $out = '';
-               foreach ( $this->edits as $edit ) {
-                       if ( $edit[0] == 'copy' ) {
-                               $out .= substr( $this->text, $edit[1], $edit[2] - $edit[1] );
-                       } else { // if ( $edit[0] == 'insert' )
-                               $out .= $edit[1];
-                       }
-               }
-
-               // Do a second parse as a sanity check
-               $this->text = $out;
-               try {
-                       $this->parse();
-               } catch ( ConfEditorParseError $e ) {
-                       throw new MWException(
-                               "Sorry, ConfEditor broke the file during editing and it won't parse anymore: " .
-                               $e->getMessage() );
-               }
-               return $out;
-       }
-
-       /**
-        * Get the variables defined in the text
-        * @return array( varname => value )
-        */
-       function getVars() {
-               $vars = array();
-               $this->parse();
-               foreach ( $this->pathInfo as $path => $data ) {
-                       if ( $path[0] != '$' ) {
-                               continue;
-                       }
-                       $trimmedPath = substr( $path, 1 );
-                       $name = $data['name'];
-                       if ( $name[0] == '@' ) {
-                               continue;
-                       }
-                       if ( $name[0] == '$' ) {
-                               $name = substr( $name, 1 );
-                       }
-                       $parentPath = substr( $trimmedPath, 0,
-                               strlen( $trimmedPath ) - strlen( $name ) );
-                       if ( substr( $parentPath, -1 ) == '/' ) {
-                               $parentPath = substr( $parentPath, 0, -1 );
-                       }
-
-                       $value = substr( $this->text, $data['valueStartByte'],
-                               $data['valueEndByte'] - $data['valueStartByte']
-                       );
-                       $this->setVar( $vars, $parentPath, $name,
-                               $this->parseScalar( $value ) );
-               }
-               return $vars;
-       }
-
-       /**
-        * Set a value in an array, unless it's set already. For instance,
-        * setVar( $arr, 'foo/bar', 'baz', 3 ); will set
-        * $arr['foo']['bar']['baz'] = 3;
-        * @param $array array
-        * @param string $path slash-delimited path
-        * @param $key mixed Key
-        * @param $value mixed Value
-        */
-       function setVar( &$array, $path, $key, $value ) {
-               $pathArr = explode( '/', $path );
-               $target =& $array;
-               if ( $path !== '' ) {
-                       foreach ( $pathArr as $p ) {
-                               if ( !isset( $target[$p] ) ) {
-                                       $target[$p] = array();
-                               }
-                               $target =& $target[$p];
-                       }
-               }
-               if ( !isset( $target[$key] ) ) {
-                       $target[$key] = $value;
-               }
-       }
-
-       /**
-        * Parse a scalar value in PHP
-        * @return mixed Parsed value
-        */
-       function parseScalar( $str ) {
-               if ( $str !== '' && $str[0] == '\'' ) {
-                       // Single-quoted string
-                       // @todo FIXME: trim() call is due to mystery bug where whitespace gets
-                       // appended to the token; without it we ended up reading in the
-                       // extra quote on the end!
-                       return strtr( substr( trim( $str ), 1, -1 ),
-                               array( '\\\'' => '\'', '\\\\' => '\\' ) );
-               }
-               if ( $str !== '' && $str[0] == '"' ) {
-                       // Double-quoted string
-                       // @todo FIXME: trim() call is due to mystery bug where whitespace gets
-                       // appended to the token; without it we ended up reading in the
-                       // extra quote on the end!
-                       return stripcslashes( substr( trim( $str ), 1, -1 ) );
-               }
-               if ( substr( $str, 0, 4 ) == 'true' ) {
-                       return true;
-               }
-               if ( substr( $str, 0, 5 ) == 'false' ) {
-                       return false;
-               }
-               if ( substr( $str, 0, 4 ) == 'null' ) {
-                       return null;
-               }
-               // Must be some kind of numeric value, so let PHP's weak typing
-               // be useful for a change
-               return $str;
-       }
-
-       /**
-        * Replace the byte offset region of the source with $newText.
-        * Works by adding elements to the $this->edits array.
-        */
-       function replaceSourceRegion( $start, $end, $newText = false ) {
-               // Split all copy operations with a source corresponding to the region
-               // in question.
-               $newEdits = array();
-               foreach ( $this->edits as $edit ) {
-                       if ( $edit[0] !== 'copy' ) {
-                               $newEdits[] = $edit;
-                               continue;
-                       }
-                       $copyStart = $edit[1];
-                       $copyEnd = $edit[2];
-                       if ( $start >= $copyEnd || $end <= $copyStart ) {
-                               // Outside this region
-                               $newEdits[] = $edit;
-                               continue;
-                       }
-                       if ( ( $start < $copyStart && $end > $copyStart )
-                               || ( $start < $copyEnd && $end > $copyEnd )
-                       ) {
-                               throw new MWException( "Overlapping regions found, can't do the edit" );
-                       }
-                       // Split the copy
-                       $newEdits[] = array( 'copy', $copyStart, $start );
-                       if ( $newText !== false ) {
-                               $newEdits[] = array( 'insert', $newText );
-                       }
-                       $newEdits[] = array( 'copy', $end, $copyEnd );
-               }
-               $this->edits = $newEdits;
-       }
-
-       /**
-        * Finds the source byte region which you would want to delete, if $pathName
-        * was to be deleted. Includes the leading spaces and tabs, the trailing line
-        * break, and any comments in between.
-        * @param $pathName
-        * @throws MWException
-        * @return array
-        */
-       function findDeletionRegion( $pathName ) {
-               if ( !isset( $this->pathInfo[$pathName] ) ) {
-                       throw new MWException( "Can't find path \"$pathName\"" );
-               }
-               $path = $this->pathInfo[$pathName];
-               // Find the start
-               $this->firstToken();
-               while ( $this->pos != $path['startToken'] ) {
-                       $this->nextToken();
-               }
-               $regionStart = $path['startByte'];
-               for ( $offset = -1; $offset >= -$this->pos; $offset-- ) {
-                       $token = $this->getTokenAhead( $offset );
-                       if ( !$token->isSkip() ) {
-                               // If there is other content on the same line, don't move the start point
-                               // back, because that will cause the regions to overlap.
-                               $regionStart = $path['startByte'];
-                               break;
-                       }
-                       $lfPos = strrpos( $token->text, "\n" );
-                       if ( $lfPos === false ) {
-                               $regionStart -= strlen( $token->text );
-                       } else {
-                               // The line start does not include the LF
-                               $regionStart -= strlen( $token->text ) - $lfPos - 1;
-                               break;
-                       }
-               }
-               // Find the end
-               while ( $this->pos != $path['endToken'] ) {
-                       $this->nextToken();
-               }
-               $regionEnd = $path['endByte']; // past the end
-               for ( $offset = 0; $offset < count( $this->tokens ) - $this->pos; $offset++ ) {
-                       $token = $this->getTokenAhead( $offset );
-                       if ( !$token->isSkip() ) {
-                               break;
-                       }
-                       $lfPos = strpos( $token->text, "\n" );
-                       if ( $lfPos === false ) {
-                               $regionEnd += strlen( $token->text );
-                       } else {
-                               // This should point past the LF
-                               $regionEnd += $lfPos + 1;
-                               break;
-                       }
-               }
-               return array( $regionStart, $regionEnd );
-       }
-
-       /**
-        * Find the byte region in the source corresponding to the value part.
-        * This includes the quotes, but does not include the trailing comma
-        * or semicolon.
-        *
-        * The end position is the past-the-end (end + 1) value as per convention.
-        * @param $pathName
-        * @throws MWException
-        * @return array
-        */
-       function findValueRegion( $pathName ) {
-               if ( !isset( $this->pathInfo[$pathName] ) ) {
-                       throw new MWException( "Can't find path \"$pathName\"" );
-               }
-               $path = $this->pathInfo[$pathName];
-               if ( $path['valueStartByte'] === false || $path['valueEndByte'] === false ) {
-                       throw new MWException( "Can't find value region for path \"$pathName\"" );
-               }
-               return array( $path['valueStartByte'], $path['valueEndByte'] );
-       }
-
-       /**
-        * Find the path name of the last element in the array.
-        * If the array is empty, this will return the \@extra interstitial element.
-        * If the specified path is not found or is not an array, it will return false.
-        * @return bool|int|string
-        */
-       function findLastArrayElement( $path ) {
-               // Try for a real element
-               $lastEltPath = false;
-               foreach ( $this->pathInfo as $candidatePath => $info ) {
-                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
-                       $part2 = substr( $candidatePath, strlen( $path ) + 1, 1 );
-                       if ( $part2 == '@' ) {
-                               // Do nothing
-                       } elseif ( $part1 == "$path/" ) {
-                               $lastEltPath = $candidatePath;
-                       } elseif ( $lastEltPath !== false ) {
-                               break;
-                       }
-               }
-               if ( $lastEltPath !== false ) {
-                       return $lastEltPath;
-               }
-
-               // Try for an interstitial element
-               $extraPath = false;
-               foreach ( $this->pathInfo as $candidatePath => $info ) {
-                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
-                       if ( $part1 == "$path/" ) {
-                               $extraPath = $candidatePath;
-                       } elseif ( $extraPath !== false ) {
-                               break;
-                       }
-               }
-               return $extraPath;
-       }
-
-       /**
-        * Find the path name of first element in the array.
-        * If the array is empty, this will return the \@extra interstitial element.
-        * If the specified path is not found or is not an array, it will return false.
-        * @return bool|int|string
-        */
-       function findFirstArrayElement( $path ) {
-               // Try for an ordinary element
-               foreach ( $this->pathInfo as $candidatePath => $info ) {
-                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
-                       $part2 = substr( $candidatePath, strlen( $path ) + 1, 1 );
-                       if ( $part1 == "$path/" && $part2 != '@' ) {
-                               return $candidatePath;
-                       }
-               }
-
-               // Try for an interstitial element
-               foreach ( $this->pathInfo as $candidatePath => $info ) {
-                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
-                       if ( $part1 == "$path/" ) {
-                               return $candidatePath;
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Get the indent string which sits after a given start position.
-        * Returns false if the position is not at the start of the line.
-        * @return array
-        */
-       function getIndent( $pos, $key = false, $arrowPos = false ) {
-               $arrowIndent = ' ';
-               if ( $pos == 0 || $this->text[$pos - 1] == "\n" ) {
-                       $indentLength = strspn( $this->text, " \t", $pos );
-                       $indent = substr( $this->text, $pos, $indentLength );
-               } else {
-                       $indent = false;
-               }
-               if ( $indent !== false && $arrowPos !== false ) {
-                       $arrowIndentLength = $arrowPos - $pos - $indentLength - strlen( $key );
-                       if ( $arrowIndentLength > 0 ) {
-                               $arrowIndent = str_repeat( ' ', $arrowIndentLength );
-                       }
-               }
-               return array( $indent, $arrowIndent );
-       }
-
-       /**
-        * Run the parser on the text. Throws an exception if the string does not
-        * match our defined subset of PHP syntax.
-        */
-       public function parse() {
-               $this->initParse();
-               $this->pushState( 'file' );
-               $this->pushPath( '@extra-' . ( $this->serial++ ) );
-               $token = $this->firstToken();
-
-               while ( !$token->isEnd() ) {
-                       $state = $this->popState();
-                       if ( !$state ) {
-                               $this->error( 'internal error: empty state stack' );
-                       }
-
-                       switch ( $state ) {
-                       case 'file':
-                               $this->expect( T_OPEN_TAG );
-                               $token = $this->skipSpace();
-                               if ( $token->isEnd() ) {
-                                       break 2;
-                               }
-                               $this->pushState( 'statement', 'file 2' );
-                               break;
-                       case 'file 2':
-                               $token = $this->skipSpace();
-                               if ( $token->isEnd() ) {
-                                       break 2;
-                               }
-                               $this->pushState( 'statement', 'file 2' );
-                               break;
-                       case 'statement':
-                               $token = $this->skipSpace();
-                               if ( !$this->validatePath( $token->text ) ) {
-                                       $this->error( "Invalid variable name \"{$token->text}\"" );
-                               }
-                               $this->nextPath( $token->text );
-                               $this->expect( T_VARIABLE );
-                               $this->skipSpace();
-                               $arrayAssign = false;
-                               if ( $this->currentToken()->type == '[' ) {
-                                       $this->nextToken();
-                                       $token = $this->skipSpace();
-                                       if ( !$token->isScalar() ) {
-                                               $this->error( "expected a string or number for the array key" );
-                                       }
-                                       if ( $token->type == T_CONSTANT_ENCAPSED_STRING ) {
-                                               $text = $this->parseScalar( $token->text );
-                                       } else {
-                                               $text = $token->text;
-                                       }
-                                       if ( !$this->validatePath( $text ) ) {
-                                               $this->error( "Invalid associative array name \"$text\"" );
-                                       }
-                                       $this->pushPath( $text );
-                                       $this->nextToken();
-                                       $this->skipSpace();
-                                       $this->expect( ']' );
-                                       $this->skipSpace();
-                                       $arrayAssign = true;
-                               }
-                               $this->expect( '=' );
-                               $this->skipSpace();
-                               $this->startPathValue();
-                               if ( $arrayAssign ) {
-                                       $this->pushState( 'expression', 'array assign end' );
-                               } else {
-                                       $this->pushState( 'expression', 'statement end' );
-                               }
-                               break;
-                       case 'array assign end':
-                       case 'statement end':
-                               $this->endPathValue();
-                               if ( $state == 'array assign end' ) {
-                                       $this->popPath();
-                               }
-                               $this->skipSpace();
-                               $this->expect( ';' );
-                               $this->nextPath( '@extra-' . ( $this->serial++ ) );
-                               break;
-                       case 'expression':
-                               $token = $this->skipSpace();
-                               if ( $token->type == T_ARRAY ) {
-                                       $this->pushState( 'array' );
-                               } elseif ( $token->isScalar() ) {
-                                       $this->nextToken();
-                               } elseif ( $token->type == T_VARIABLE ) {
-                                       $this->nextToken();
-                               } else {
-                                       $this->error( "expected simple expression" );
-                               }
-                               break;
-                       case 'array':
-                               $this->skipSpace();
-                               $this->expect( T_ARRAY );
-                               $this->skipSpace();
-                               $this->expect( '(' );
-                               $this->skipSpace();
-                               $this->pushPath( '@extra-' . ( $this->serial++ ) );
-                               if ( $this->isAhead( ')' ) ) {
-                                       // Empty array
-                                       $this->pushState( 'array end' );
-                               } else {
-                                       $this->pushState( 'element', 'array end' );
-                               }
-                               break;
-                       case 'array end':
-                               $this->skipSpace();
-                               $this->popPath();
-                               $this->expect( ')' );
-                               break;
-                       case 'element':
-                               $token = $this->skipSpace();
-                               // Look ahead to find the double arrow
-                               if ( $token->isScalar() && $this->isAhead( T_DOUBLE_ARROW, 1 ) ) {
-                                       // Found associative element
-                                       $this->pushState( 'assoc-element', 'element end' );
-                               } else {
-                                       // Not associative
-                                       $this->nextPath( '@next' );
-                                       $this->startPathValue();
-                                       $this->pushState( 'expression', 'element end' );
-                               }
-                               break;
-                       case 'element end':
-                               $token = $this->skipSpace();
-                               if ( $token->type == ',' ) {
-                                       $this->endPathValue();
-                                       $this->markComma();
-                                       $this->nextToken();
-                                       $this->nextPath( '@extra-' . ( $this->serial++ ) );
-                                       // Look ahead to find ending bracket
-                                       if ( $this->isAhead( ")" ) ) {
-                                               // Found ending bracket, no continuation
-                                               $this->skipSpace();
-                                       } else {
-                                               // No ending bracket, continue to next element
-                                               $this->pushState( 'element' );
-                                       }
-                               } elseif ( $token->type == ')' ) {
-                                       // End array
-                                       $this->endPathValue();
-                               } else {
-                                       $this->error( "expected the next array element or the end of the array" );
-                               }
-                               break;
-                       case 'assoc-element':
-                               $token = $this->skipSpace();
-                               if ( !$token->isScalar() ) {
-                                       $this->error( "expected a string or number for the array key" );
-                               }
-                               if ( $token->type == T_CONSTANT_ENCAPSED_STRING ) {
-                                       $text = $this->parseScalar( $token->text );
-                               } else {
-                                       $text = $token->text;
-                               }
-                               if ( !$this->validatePath( $text ) ) {
-                                       $this->error( "Invalid associative array name \"$text\"" );
-                               }
-                               $this->nextPath( $text );
-                               $this->nextToken();
-                               $this->skipSpace();
-                               $this->markArrow();
-                               $this->expect( T_DOUBLE_ARROW );
-                               $this->skipSpace();
-                               $this->startPathValue();
-                               $this->pushState( 'expression' );
-                               break;
-                       }
-               }
-               if ( count( $this->stateStack ) ) {
-                       $this->error( 'unexpected end of file' );
-               }
-               $this->popPath();
-       }
-
-       /**
-        * Initialise a parse.
-        */
-       protected function initParse() {
-               $this->tokens = token_get_all( $this->text );
-               $this->stateStack = array();
-               $this->pathStack = array();
-               $this->firstToken();
-               $this->pathInfo = array();
-               $this->serial = 1;
-       }
-
-       /**
-        * Set the parse position. Do not call this except from firstToken() and
-        * nextToken(), there is more to update than just the position.
-        */
-       protected function setPos( $pos ) {
-               $this->pos = $pos;
-               if ( $this->pos >= count( $this->tokens ) ) {
-                       $this->currentToken = ConfEditorToken::newEnd();
-               } else {
-                       $this->currentToken = $this->newTokenObj( $this->tokens[$this->pos] );
-               }
-               return $this->currentToken;
-       }
-
-       /**
-        * Create a ConfEditorToken from an element of token_get_all()
-        * @return ConfEditorToken
-        */
-       function newTokenObj( $internalToken ) {
-               if ( is_array( $internalToken ) ) {
-                       return new ConfEditorToken( $internalToken[0], $internalToken[1] );
-               } else {
-                       return new ConfEditorToken( $internalToken, $internalToken );
-               }
-       }
-
-       /**
-        * Reset the parse position
-        */
-       function firstToken() {
-               $this->setPos( 0 );
-               $this->prevToken = ConfEditorToken::newEnd();
-               $this->lineNum = 1;
-               $this->colNum = 1;
-               $this->byteNum = 0;
-               return $this->currentToken;
-       }
-
-       /**
-        * Get the current token
-        */
-       function currentToken() {
-               return $this->currentToken;
-       }
-
-       /**
-        * Advance the current position and return the resulting next token
-        */
-       function nextToken() {
-               if ( $this->currentToken ) {
-                       $text = $this->currentToken->text;
-                       $lfCount = substr_count( $text, "\n" );
-                       if ( $lfCount ) {
-                               $this->lineNum += $lfCount;
-                               $this->colNum = strlen( $text ) - strrpos( $text, "\n" );
-                       } else {
-                               $this->colNum += strlen( $text );
-                       }
-                       $this->byteNum += strlen( $text );
-               }
-               $this->prevToken = $this->currentToken;
-               $this->setPos( $this->pos + 1 );
-               return $this->currentToken;
-       }
-
-       /**
-        * Get the token $offset steps ahead of the current position.
-        * $offset may be negative, to get tokens behind the current position.
-        * @return ConfEditorToken
-        */
-       function getTokenAhead( $offset ) {
-               $pos = $this->pos + $offset;
-               if ( $pos >= count( $this->tokens ) || $pos < 0 ) {
-                       return ConfEditorToken::newEnd();
-               } else {
-                       return $this->newTokenObj( $this->tokens[$pos] );
-               }
-       }
-
-       /**
-        * Advances the current position past any whitespace or comments
-        */
-       function skipSpace() {
-               while ( $this->currentToken && $this->currentToken->isSkip() ) {
-                       $this->nextToken();
-               }
-               return $this->currentToken;
-       }
-
-       /**
-        * Throws an error if the current token is not of the given type, and
-        * then advances to the next position.
-        */
-       function expect( $type ) {
-               if ( $this->currentToken && $this->currentToken->type == $type ) {
-                       return $this->nextToken();
-               } else {
-                       $this->error( "expected " . $this->getTypeName( $type ) .
-                               ", got " . $this->getTypeName( $this->currentToken->type ) );
-               }
-       }
-
-       /**
-        * Push a state or two on to the state stack.
-        */
-       function pushState( $nextState, $stateAfterThat = null ) {
-               if ( $stateAfterThat !== null ) {
-                       $this->stateStack[] = $stateAfterThat;
-               }
-               $this->stateStack[] = $nextState;
-       }
-
-       /**
-        * Pop a state from the state stack.
-        * @return mixed
-        */
-       function popState() {
-               return array_pop( $this->stateStack );
-       }
-
-       /**
-        * Returns true if the user input path is valid.
-        * This exists to allow "/" and "@" to be reserved for string path keys
-        * @return bool
-        */
-       function validatePath( $path ) {
-               return strpos( $path, '/' ) === false && substr( $path, 0, 1 ) != '@';
-       }
-
-       /**
-        * Internal function to update some things at the end of a path region. Do
-        * not call except from popPath() or nextPath().
-        */
-       function endPath() {
-               $key = '';
-               foreach ( $this->pathStack as $pathInfo ) {
-                       if ( $key !== '' ) {
-                               $key .= '/';
-                       }
-                       $key .= $pathInfo['name'];
-               }
-               $pathInfo['endByte'] = $this->byteNum;
-               $pathInfo['endToken'] = $this->pos;
-               $this->pathInfo[$key] = $pathInfo;
-       }
-
-       /**
-        * Go up to a new path level, for example at the start of an array.
-        */
-       function pushPath( $path ) {
-               $this->pathStack[] = array(
-                       'name' => $path,
-                       'level' => count( $this->pathStack ) + 1,
-                       'startByte' => $this->byteNum,
-                       'startToken' => $this->pos,
-                       'valueStartToken' => false,
-                       'valueStartByte' => false,
-                       'valueEndToken' => false,
-                       'valueEndByte' => false,
-                       'nextArrayIndex' => 0,
-                       'hasComma' => false,
-                       'arrowByte' => false
-               );
-       }
-
-       /**
-        * Go down a path level, for example at the end of an array.
-        */
-       function popPath() {
-               $this->endPath();
-               array_pop( $this->pathStack );
-       }
-
-       /**
-        * Go to the next path on the same level. This ends the current path and
-        * starts a new one. If $path is \@next, the new path is set to the next
-        * numeric array element.
-        */
-       function nextPath( $path ) {
-               $this->endPath();
-               $i = count( $this->pathStack ) - 1;
-               if ( $path == '@next' ) {
-                       $nextArrayIndex =& $this->pathStack[$i]['nextArrayIndex'];
-                       $this->pathStack[$i]['name'] = $nextArrayIndex;
-                       $nextArrayIndex++;
-               } else {
-                       $this->pathStack[$i]['name'] = $path;
-               }
-               $this->pathStack[$i] =
-                       array(
-                               'startByte' => $this->byteNum,
-                               'startToken' => $this->pos,
-                               'valueStartToken' => false,
-                               'valueStartByte' => false,
-                               'valueEndToken' => false,
-                               'valueEndByte' => false,
-                               'hasComma' => false,
-                               'arrowByte' => false,
-                       ) + $this->pathStack[$i];
-       }
-
-       /**
-        * Mark the start of the value part of a path.
-        */
-       function startPathValue() {
-               $path =& $this->pathStack[count( $this->pathStack ) - 1];
-               $path['valueStartToken'] = $this->pos;
-               $path['valueStartByte'] = $this->byteNum;
-       }
-
-       /**
-        * Mark the end of the value part of a path.
-        */
-       function endPathValue() {
-               $path =& $this->pathStack[count( $this->pathStack ) - 1];
-               $path['valueEndToken'] = $this->pos;
-               $path['valueEndByte'] = $this->byteNum;
-       }
-
-       /**
-        * Mark the comma separator in an array element
-        */
-       function markComma() {
-               $path =& $this->pathStack[count( $this->pathStack ) - 1];
-               $path['hasComma'] = true;
-       }
-
-       /**
-        * Mark the arrow separator in an associative array element
-        */
-       function markArrow() {
-               $path =& $this->pathStack[count( $this->pathStack ) - 1];
-               $path['arrowByte'] = $this->byteNum;
-       }
-
-       /**
-        * Generate a parse error
-        */
-       function error( $msg ) {
-               throw new ConfEditorParseError( $this, $msg );
-       }
-
-       /**
-        * Get a readable name for the given token type.
-        * @return string
-        */
-       function getTypeName( $type ) {
-               if ( is_int( $type ) ) {
-                       return token_name( $type );
-               } else {
-                       return "\"$type\"";
-               }
-       }
-
-       /**
-        * Looks ahead to see if the given type is the next token type, starting
-        * from the current position plus the given offset. Skips any intervening
-        * whitespace.
-        * @return bool
-        */
-       function isAhead( $type, $offset = 0 ) {
-               $ahead = $offset;
-               $token = $this->getTokenAhead( $offset );
-               while ( !$token->isEnd() ) {
-                       if ( $token->isSkip() ) {
-                               $ahead++;
-                               $token = $this->getTokenAhead( $ahead );
-                               continue;
-                       } elseif ( $token->type == $type ) {
-                               // Found the type
-                               return true;
-                       } else {
-                               // Not found
-                               return false;
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Get the previous token object
-        */
-       function prevToken() {
-               return $this->prevToken;
-       }
-
-       /**
-        * Echo a reasonably readable representation of the tokenizer array.
-        */
-       function dumpTokens() {
-               $out = '';
-               foreach ( $this->tokens as $token ) {
-                       $obj = $this->newTokenObj( $token );
-                       $out .= sprintf( "%-28s %s\n",
-                               $this->getTypeName( $obj->type ),
-                               addcslashes( $obj->text, "\0..\37" ) );
-               }
-               echo "<pre>" . htmlspecialchars( $out ) . "</pre>";
-       }
-}
-
-/**
- * Exception class for parse errors
- */
-class ConfEditorParseError extends MWException {
-       var $lineNum, $colNum;
-       function __construct( $editor, $msg ) {
-               $this->lineNum = $editor->lineNum;
-               $this->colNum = $editor->colNum;
-               parent::__construct( "Parse error on line {$editor->lineNum} " .
-                       "col {$editor->colNum}: $msg" );
-       }
-
-       function highlight( $text ) {
-               $lines = StringUtils::explode( "\n", $text );
-               foreach ( $lines as $lineNum => $line ) {
-                       if ( $lineNum == $this->lineNum - 1 ) {
-                               return "$line\n" . str_repeat( ' ', $this->colNum - 1 ) . "^\n";
-                       }
-               }
-               return '';
-       }
-
-}
-
-/**
- * Class to wrap a token from the tokenizer.
- */
-class ConfEditorToken {
-       var $type, $text;
-
-       static $scalarTypes = array( T_LNUMBER, T_DNUMBER, T_STRING, T_CONSTANT_ENCAPSED_STRING );
-       static $skipTypes = array( T_WHITESPACE, T_COMMENT, T_DOC_COMMENT );
-
-       static function newEnd() {
-               return new self( 'END', '' );
-       }
-
-       function __construct( $type, $text ) {
-               $this->type = $type;
-               $this->text = $text;
-       }
-
-       function isSkip() {
-               return in_array( $this->type, self::$skipTypes );
-       }
-
-       function isScalar() {
-               return in_array( $this->type, self::$scalarTypes );
-       }
-
-       function isEnd() {
-               return $this->type == 'END';
-       }
-}
index ecf4667..e0a11a2 100644 (file)
@@ -131,8 +131,14 @@ class Cookie {
                        }
 
                        if ( substr( $domain, 0, 1 ) == '.'
-                               && substr_compare( $originDomain, $domain, -strlen( $domain ),
-                                                                  strlen( $domain ), true ) != 0 ) {
+                               && substr_compare(
+                                       $originDomain,
+                                       $domain,
+                                       -strlen( $domain ),
+                                       strlen( $domain ),
+                                       true
+                               ) != 0
+                       ) {
                                return false;
                        }
                }
@@ -167,8 +173,15 @@ class Cookie {
                if ( $domain == $this->domain
                        || ( strlen( $domain ) > strlen( $this->domain )
                                && substr( $this->domain, 0, 1 ) == '.'
-                               && substr_compare( $domain, $this->domain, -strlen( $this->domain ),
-                                                                       strlen( $this->domain ), true ) == 0 ) ) {
+                               && substr_compare(
+                                       $domain,
+                                       $this->domain,
+                                       -strlen( $this->domain ),
+                                       strlen( $this->domain ),
+                                       true
+                               ) == 0
+                       )
+               ) {
                        return true;
                }
 
diff --git a/includes/DataUpdate.php b/includes/DataUpdate.php
deleted file mode 100644 (file)
index 7b9ac28..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/**
- * Base code for update jobs that do something with some secondary
- * data extracted from article.
- *
- * 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
- */
-
-/**
- * Abstract base class for update jobs that do something with some secondary
- * data extracted from article.
- *
- * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
- *        a transaction will automatically be wrapped around the update. If need be,
- *        subclasses can override the beginTransaction() and commitTransaction() methods.
- */
-abstract class DataUpdate implements DeferrableUpdate {
-
-       /**
-        * Constructor
-        */
-       public function __construct() {
-               # noop
-       }
-
-       /**
-        * Begin an appropriate transaction, if any.
-        * This default implementation does nothing.
-        */
-       public function beginTransaction() {
-               //noop
-       }
-
-       /**
-        * Commit the transaction started via beginTransaction, if any.
-        * This default implementation does nothing.
-        */
-       public function commitTransaction() {
-               //noop
-       }
-
-       /**
-        * Abort / roll back the transaction started via beginTransaction, if any.
-        * This default implementation does nothing.
-        */
-       public function rollbackTransaction() {
-               //noop
-       }
-
-       /**
-        * Convenience method, calls doUpdate() on every DataUpdate in the array.
-        *
-        * This methods supports transactions logic by first calling beginTransaction()
-        * on all updates in the array, then calling doUpdate() on each, and, if all goes well,
-        * then calling commitTransaction() on each update. If an error occurs,
-        * rollbackTransaction() will be called on any update object that had beginTransaction()
-        * called but not yet commitTransaction().
-        *
-        * This allows for limited transactional logic across multiple backends for storing
-        * secondary data.
-        *
-        * @param array $updates a list of DataUpdate instances
-        * @throws Exception|null
-        */
-       public static function runUpdates( $updates ) {
-               if ( empty( $updates ) ) {
-                       return; # nothing to do
-               }
-
-               $open_transactions = array();
-               $exception = null;
-
-               /**
-                * @var $update DataUpdate
-                * @var $trans DataUpdate
-                */
-
-               try {
-                       // begin transactions
-                       foreach ( $updates as $update ) {
-                               $update->beginTransaction();
-                               $open_transactions[] = $update;
-                       }
-
-                       // do work
-                       foreach ( $updates as $update ) {
-                               $update->doUpdate();
-                       }
-
-                       // commit transactions
-                       while ( count( $open_transactions ) > 0 ) {
-                               $trans = array_pop( $open_transactions );
-                               $trans->commitTransaction();
-                       }
-               } catch ( Exception $ex ) {
-                       $exception = $ex;
-                       wfDebug( "Caught exception, will rethrow after rollback: " . $ex->getMessage() );
-               }
-
-               // rollback remaining transactions
-               while ( count( $open_transactions ) > 0 ) {
-                       $trans = array_pop( $open_transactions );
-                       $trans->rollbackTransaction();
-               }
-
-               if ( $exception ) {
-                       throw $exception; // rethrow after cleanup
-               }
-       }
-
-}
index 6b76b03..e9e4545 100644 (file)
@@ -63,7 +63,7 @@ $wgConf = new SiteConfiguration;
  * MediaWiki version number
  * @since 1.2
  */
-$wgVersion = '1.22alpha';
+$wgVersion = '1.23alpha';
 
 /**
  * Name of the site. It must be changed in LocalSettings.php
@@ -361,6 +361,22 @@ $wgImgAuthDetails = false;
  */
 $wgImgAuthPublicTest = true;
 
+/**
+ * Map of relative URL directories to match to internal mwstore:// base storage paths.
+ * For img_auth.php requests, everything after "img_auth.php/" is checked to see
+ * if starts with any of the prefixes defined here. The prefixes should not overlap.
+ * The prefix that matches has a corresponding storage path, which the rest of the URL
+ * is assumed to be relative to. The file at that path (or a 404) is send to the client.
+ *
+ * Example:
+ * $wgImgAuthUrlPathMap['/timeline/'] = 'mwstore://local-fs/timeline-render/';
+ * The above maps ".../img_auth.php/timeline/X" to "mwstore://local-fs/timeline-render/".
+ * The name "local-fs" should correspond by name to an entry in $wgFileBackends.
+ *
+ * @see $wgFileBackends
+ */
+$wgImgAuthUrlPathMap = array();
+
 /**
  * File repository structures
  *
@@ -1608,7 +1624,12 @@ $wgSharedTables = array( 'user', 'user_properties' );
  *   - user:        DB user
  *   - password:    DB password
  *   - type:        "mysql" or "postgres"
- *   - load:        ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0
+ *
+ *   - load:        Ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0.
+ *                  If this is zero for any given server, no normal query traffic will be
+ *                  sent to it. It will be excluded from lag checks in maintenance scripts.
+ *                  The only way it can receive traffic is if groupLoads is used.
+ *
  *   - groupLoads:  array of load ratios, the key is the query group name. A query may belong
  *                  to several groups, the most specific group defined here is used.
  *
@@ -1793,7 +1814,7 @@ $wgCompressRevisions = false;
  *
  * CAUTION: Access to database might lead to code execution
  */
-$wgExternalStores = false;
+$wgExternalStores = array();
 
 /**
  * An array of external MySQL servers.
@@ -2129,7 +2150,7 @@ $wgStyleVersion = '303';
 /**
  * This will cache static pages for non-logged-in users to reduce
  * database traffic on public sites.
- * Must set $wgShowIPinHeader = false
+ * Automatically sets $wgShowIPinHeader = false
  * ResourceLoader requests to default language and skins are cached
  * as well as single module requests.
  */
@@ -2285,7 +2306,9 @@ $wgSquidServers = array();
 
 /**
  * As above, except these servers aren't purged on page changes; use to set a
- * list of trusted proxies, etc.
+ * list of trusted proxies, etc. Supports both individual IP addresses and
+ * CIDR blocks.
+ * @since 1.23 Supports CIDR ranges
  */
 $wgSquidServersNoPurge = array();
 
@@ -3322,6 +3345,22 @@ $wgResourceLoaderLESSImportPaths = array(
        "$IP/resources/mediawiki.less/",
 );
 
+/**
+ * Whether ResourceLoader should attempt to persist modules in localStorage on
+ * browsers that support the Web Storage API.
+ *
+ * @since 1.23 - Client-side module persistence is experimental. Exercise care.
+ */
+$wgResourceLoaderStorageEnabled = false;
+
+/**
+ * Cache version for client-side ResourceLoader module storage. You can trigger
+ * invalidation of the contents of the module store by incrementing this value.
+ *
+ * @since 1.23
+ */
+$wgResourceLoaderStorageVersion = 1;
+
 /** @} */ # End of resource loader settings }
 
 /*************************************************************************//**
@@ -3788,13 +3827,16 @@ $wgNoFollowNsExceptions = array();
  * (or any subdomains) will not be set to rel="nofollow" regardless of the
  * value of $wgNoFollowLinks.  For instance:
  *
- * $wgNoFollowDomainExceptions = array( 'en.wikipedia.org', 'wiktionary.org' );
+ * $wgNoFollowDomainExceptions = array( 'en.wikipedia.org', 'wiktionary.org',
+ * 'mediawiki.org' );
  *
  * This would add rel="nofollow" to links to de.wikipedia.org, but not
  * en.wikipedia.org, wiktionary.org, en.wiktionary.org, us.en.wikipedia.org,
  * etc.
+ *
+ * Defaults to mediawiki.org for the links included in the software by default.
  */
-$wgNoFollowDomainExceptions = array();
+$wgNoFollowDomainExceptions = array( 'mediawiki.org' );
 
 /**
  * Allow DISPLAYTITLE to change title display
@@ -4879,10 +4921,29 @@ $wgDebugDBTransactions = false;
 $wgDebugDumpSql = false;
 
 /**
- * Set to an array of log group keys to filenames.
+ * Map of string log group names to log destinations.
+ *
  * If set, wfDebugLog() output for that group will go to that file instead
  * of the regular $wgDebugLogFile. Useful for enabling selective logging
  * in production.
+ *
+ * Log destinations may be string values specifying a filename or URI, or they
+ * may be filename or an associative array mapping 'destination' to the desired
+ * filename. The associative array may also contain a 'sample' key with an
+ * integer value, specifying a sampling factor.
+ *
+ * @par Example:
+ * @code
+ * $wgDebugLogGroups['redis'] = '/var/log/mediawiki/redis.log';
+ * @endcode
+ *
+ * @par Advanced example:
+ * @code
+ * $wgDebugLogGroups['memcached'] = (
+ *     'destination' => '/var/log/mediawiki/memcached.log',
+ *     'sample' => 1000,  // log 1 message out of every 1,000.
+ * );
+ * @endcode
  */
 $wgDebugLogGroups = array();
 
@@ -4924,37 +4985,6 @@ $wgShowSQLErrors = false;
  */
 $wgShowExceptionDetails = false;
 
-/**
- * Array of functions which need parameters redacted from stack traces shown to
- * clients and logged. Keys are in the format '[class::]function', and the
- * values should be either an integer or an array of integers. These are the
- * indexes of the parameters which need to be kept secret.
- * @since 1.22
- */
-$wgRedactedFunctionArguments = array(
-       'AuthPlugin::setPassword' => 1,
-       'AuthPlugin::authenticate' => 1,
-       'AuthPlugin::addUser' => 1,
-
-       'DatabaseBase::__construct' => 2,
-       'DatabaseBase::open' => 2,
-
-       'SpecialChangeEmail::attemptChange' => 1,
-       'SpecialChangePassword::attemptReset' => 0,
-
-       'User::setPassword' => 0,
-       'User::setInternalPassword' => 0,
-       'User::checkPassword' => 0,
-       'User::setNewpassword' => 0,
-       'User::comparePasswords' => array( 0, 1 ),
-       'User::checkTemporaryPassword' => 0,
-       'User::setToken' => 0,
-       'User::crypt' => 0,
-       'User::oldCrypt' => 0,
-       'User::getPasswordValidity' => 0,
-       'User::isValidPassword' => 0,
-);
-
 /**
  * If true, show a backtrace for database errors
  */
@@ -5026,7 +5056,8 @@ $wgProfilePerHost = false;
  * Host for UDP profiler.
  *
  * The host should be running a daemon which can be obtained from MediaWiki
- * Subversion at: http://svn.wikimedia.org/svnroot/mediawiki/trunk/udpprofile
+ * Git at:
+ * http://git.wikimedia.org/tree/operations%2Fsoftware.git/master/udpprofile
  */
 $wgUDPProfilerHost = '127.0.0.1';
 
@@ -5229,6 +5260,12 @@ $wgOpenSearchTemplate = false;
  */
 $wgEnableOpenSearchSuggest = true;
 
+/**
+ * Integer defining default number of entries to show on
+ * OpenSearch call.
+ */
+$wgOpenSearchDefaultLimit = 10;
+
 /**
  * Expiry time for search suggestion responses
  */
@@ -5953,6 +5990,13 @@ $wgSpecialPages = array();
  */
 $wgAutoloadClasses = array();
 
+/**
+ * Switch controlling legacy case-insensitive classloading.
+ * Do not disable if your wiki must support data created by PHP4, or by
+ * MediaWiki 1.4 or earlier.
+ */
+$wgAutoloadAttemptLowercase = true;
+
 /**
  * An array of extension types and inside that their names, versions, authors,
  * urls, descriptions and pointers to localized description msgs. Note that
@@ -6029,7 +6073,7 @@ $wgHooks = array();
  */
 $wgJobClasses = array(
        'refreshLinks' => 'RefreshLinksJob',
-       'refreshLinks2' => 'RefreshLinksJob2',
+       'refreshLinks2' => 'RefreshLinksJob2', // b/c
        'htmlCacheUpdate' => 'HTMLCacheUpdateJob',
        'sendMail' => 'EmaillingJob',
        'enotifNotify' => 'EnotifNotifyJob',
@@ -6514,6 +6558,7 @@ $wgDebugAPI = false;
  * @todo Describe each of the variables, group them and add examples
  */
 $wgAPIModules = array();
+$wgAPIFormatModules = array();
 $wgAPIMetaModules = array();
 $wgAPIPropModules = array();
 $wgAPIListModules = array();
@@ -6629,7 +6674,7 @@ $wgCrossSiteAJAXdomainExceptions = array();
 /**
  * Maximum amount of virtual memory available to shell processes under linux, in KB.
  */
-$wgMaxShellMemory = 102400;
+$wgMaxShellMemory = 307200;
 
 /**
  * Maximum file size created by shell processes under linux, in KB
diff --git a/includes/DeferredUpdates.php b/includes/DeferredUpdates.php
deleted file mode 100644 (file)
index a321414..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-/**
- * Interface and manager for deferred updates.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Interface that deferrable updates should implement. Basically required so we
- * can validate input on DeferredUpdates::addUpdate()
- *
- * @since 1.19
- */
-interface DeferrableUpdate {
-       /**
-        * Perform the actual work
-        */
-       function doUpdate();
-}
-
-/**
- * Class for managing the deferred updates.
- *
- * @since 1.19
- */
-class DeferredUpdates {
-       /**
-        * Store of updates to be deferred until the end of the request.
-        */
-       private static $updates = array();
-
-       /**
-        * Add an update to the deferred list
-        * @param $update DeferrableUpdate Some object that implements doUpdate()
-        */
-       public static function addUpdate( DeferrableUpdate $update ) {
-               array_push( self::$updates, $update );
-       }
-
-       /**
-        * HTMLCacheUpdates are the most common deferred update people use. This
-        * is a shortcut method for that.
-        * @see HTMLCacheUpdate::__construct()
-        * @param $title
-        * @param $table
-        */
-       public static function addHTMLCacheUpdate( $title, $table ) {
-               self::addUpdate( new HTMLCacheUpdate( $title, $table ) );
-       }
-
-       /**
-        * Add a callable update.  In a lot of cases, we just need a callback/closure,
-        * defining a new DeferrableUpdate object is not necessary
-        * @see MWCallableUpdate::__construct()
-        * @param callable $callable
-        */
-       public static function addCallableUpdate( $callable ) {
-               self::addUpdate( new MWCallableUpdate( $callable ) );
-       }
-
-       /**
-        * Do any deferred updates and clear the list
-        *
-        * @param string $commit set to 'commit' to commit after every update to
-        *                prevent lock contention
-        */
-       public static function doUpdates( $commit = '' ) {
-               global $wgDeferredUpdateList;
-
-               wfProfileIn( __METHOD__ );
-
-               $updates = array_merge( $wgDeferredUpdateList, self::$updates );
-
-               // No need to get master connections in case of empty updates array
-               if ( !count( $updates ) ) {
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               $doCommit = $commit == 'commit';
-               if ( $doCommit ) {
-                       $dbw = wfGetDB( DB_MASTER );
-               }
-
-               foreach ( $updates as $update ) {
-                       try {
-                               $update->doUpdate();
-
-                               if ( $doCommit && $dbw->trxLevel() ) {
-                                       $dbw->commit( __METHOD__, 'flush' );
-                               }
-                       } catch ( MWException $e ) {
-                               // We don't want exceptions thrown during deferred updates to
-                               // be reported to the user since the output is already sent.
-                               // Instead we just log them.
-                               if ( !$e instanceof ErrorPageError ) {
-                                       wfDebugLog( 'exception', $e->getLogMessage() );
-                               }
-                       }
-               }
-
-               self::clearPendingUpdates();
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Clear all pending updates without performing them. Generally, you don't
-        * want or need to call this. Unit tests need it though.
-        */
-       public static function clearPendingUpdates() {
-               global $wgDeferredUpdateList;
-               $wgDeferredUpdateList = self::$updates = array();
-       }
-}
index d48bd0b..8a63786 100644 (file)
@@ -23,7 +23,6 @@
 /**
  * Class to allow throwing wfDeprecated warnings
  * when people use globals that we do not want them to.
- * (For example like $wgArticle)
  */
 
 class DeprecatedGlobal extends StubObject {
index d7b2b5e..f86cae4 100644 (file)
@@ -457,9 +457,9 @@ class EditPage {
                # Ignore some permissions errors when a user is just previewing/viewing diffs
                $remove = array();
                foreach ( $permErrors as $error ) {
-                       if ( ( $this->preview || $this->diff ) &&
-                               ( $error[0] == 'blockedtext' || $error[0] == 'autoblockedtext' ) )
-                       {
+                       if ( ( $this->preview || $this->diff )
+                               && ( $error[0] == 'blockedtext' || $error[0] == 'autoblockedtext' )
+                       {
                                $remove[] = $error;
                        }
                }
@@ -567,10 +567,10 @@ class EditPage {
                } elseif ( ( $wgRequest->getVal( 'preload' ) !== null || $this->mTitle->exists() ) && $wgUser->getOption( 'previewonfirst' ) ) {
                        // Standard preference behavior
                        return true;
-               } elseif ( !$this->mTitle->exists() &&
-                       isset( $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] ) &&
-                       $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] )
-               {
+               } elseif ( !$this->mTitle->exists()
+                       && isset( $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] )
+                       && $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()]
+               {
                        // Categories are special
                        return true;
                } else {
@@ -728,9 +728,9 @@ class EditPage {
                        $this->watchthis = $request->getCheck( 'wpWatchthis' );
 
                        # Don't force edit summaries when a user is editing their own user or talk page
-                       if ( ( $this->mTitle->mNamespace == NS_USER || $this->mTitle->mNamespace == NS_USER_TALK ) &&
-                               $this->mTitle->getText() == $wgUser->getName() )
-                       {
+                       if ( ( $this->mTitle->mNamespace == NS_USER || $this->mTitle->mNamespace == NS_USER_TALK )
+                               && $this->mTitle->getText() == $wgUser->getName()
+                       {
                                $this->allowBlankSummary = true;
                        } else {
                                $this->allowBlankSummary = $request->getBool( 'wpIgnoreBlankSummary' ) || !$wgUser->getOption( 'forceeditsummary' );
@@ -1204,13 +1204,29 @@ class EditPage {
         * @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
         * @return bool false if output is done, true if the rest of the form should be displayed
         */
-       function attemptSave() {
-               global $wgUser, $wgOut;
+       public function attemptSave() {
+               global $wgUser;
 
                $resultDetails = false;
                # Allow bots to exempt some edits from bot flagging
                $bot = $wgUser->isAllowed( 'bot' ) && $this->bot;
                $status = $this->internalAttemptSave( $resultDetails, $bot );
+
+               return $this->handleStatus( $status, $resultDetails );
+       }
+
+       /**
+        * Handle status, such as after attempt save
+        *
+        * @param Status $status
+        * @param array|bool $resultDetails
+        *
+        * @throws ErrorPageError
+        * return bool false, if output is done, true if rest of the form should be displayed
+        */
+       private function handleStatus( Status $status, $resultDetails ) {
+               global $wgUser, $wgOut;
+
                // FIXME: once the interface for internalAttemptSave() is made nicer, this should use the message in $status
                if ( $status->value == self::AS_SUCCESS_UPDATE || $status->value == self::AS_SUCCESS_NEW_ARTICLE ) {
                        $this->didSave = true;
@@ -1381,6 +1397,24 @@ class EditPage {
                        return $status;
                }
 
+               $spam = $wgRequest->getText( 'wpAntispam' );
+               if ( $spam !== '' ) {
+                       wfDebugLog(
+                               'SimpleAntiSpam',
+                               $wgUser->getName() .
+                               ' editing "' .
+                               $this->mTitle->getPrefixedText() .
+                               '" submitted bogus field "' .
+                               $spam .
+                               '"'
+                       );
+                       $status->fatal( 'spamprotectionmatch', false );
+                       $status->value = self::AS_SPAM_ERROR;
+                       wfProfileOut( __METHOD__ . '-checks' );
+                       wfProfileOut( __METHOD__ );
+                       return $status;
+               }
+
                try {
                        # Construct Content object
                        $textbox_content = $this->toEditContent( $this->textbox1 );
@@ -1758,9 +1792,9 @@ class EditPage {
                        // Show the edit conflict page for certain recognized errors from doEdit(),
                        // but don't show it for errors from extension hooks
                        $errors = $doEditStatus->getErrorsArray();
-                       if ( in_array( $errors[0][0], array( 'edit-gone-missing', 'edit-conflict',
-                               'edit-already-exists' ) ) )
-                       {
+                       if ( in_array( $errors[0][0],
+                                       array( 'edit-gone-missing', 'edit-conflict', 'edit-already-exists' ) )
+                       {
                                $this->isConflict = true;
                                // Destroys data doEdit() put in $status->value but who cares
                                $doEditStatus->value = self::AS_END;
@@ -2190,6 +2224,14 @@ class EditPage {
                        call_user_func_array( $formCallback, array( &$wgOut ) );
                }
 
+               // Add an empty field to trip up spambots
+               $wgOut->addHTML(
+                       Xml::openElement( 'div', array( 'id' => 'antispam-container', 'style' => 'display: none;' ) )
+                       . Html::rawElement( 'label', array( 'for' => 'wpAntiSpam' ), wfMessage( 'simpleantispam-label' )->parse() )
+                       . Xml::element( 'input', array( 'type' => 'text', 'name' => 'wpAntispam', 'id' => 'wpAntispam', 'value' => '' ) )
+                       . Xml::closeElement( 'div' )
+               );
+
                wfRunHooks( 'EditPage::showEditForm:fields', array( &$this, &$wgOut ) );
 
                // Put these up at the top to ensure they aren't lost on early form submission
@@ -2434,7 +2476,9 @@ class EditPage {
                        }
                }
 
-               if ( $this->mTitle->getNamespace() != NS_MEDIAWIKI && $this->mTitle->isProtected( 'edit' ) ) {
+               if ( $this->mTitle->isProtected( 'edit' ) &&
+                       MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) !== array( '' )
+               ) {
                        # Is the title semi-protected?
                        if ( $this->mTitle->isSemiProtected() ) {
                                $noticeMsg = 'semiprotectedpagewarning';
@@ -2636,7 +2680,9 @@ HTML
                        $attribs = array( 'style' => 'display:none;' );
                } else {
                        $classes = array(); // Textarea CSS
-                       if ( $this->mTitle->getNamespace() != NS_MEDIAWIKI && $this->mTitle->isProtected( 'edit' ) ) {
+                       if ( $this->mTitle->isProtected( 'edit' ) &&
+                               MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) !== array( '' )
+                       ) {
                                # Is the title semi-protected?
                                if ( $this->mTitle->isSemiProtected() ) {
                                        $classes[] = 'mw-textarea-sprotected';
@@ -2911,7 +2957,7 @@ HTML
 
                foreach ( $output->getLimitReportData() as $key => $value ) {
                        if ( wfRunHooks( 'ParserLimitReportFormat',
-                               array( $key, $value, &$limitReport, true, true )
+                               array( $key, &$value, &$limitReport, true, true )
                        ) ) {
                                $keyMsg = wfMessage( $key );
                                $valueMsg = wfMessage( array( "$key-value-html", "$key-value" ) );
@@ -3129,6 +3175,10 @@ HTML
                                return $previewHTML;
                        }
 
+                       # provide a anchor link to the editform
+                       $continueEditing = '<span class="mw-continue-editing">' .
+                               '[[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' .
+                               wfMessage( 'continue-editing' )->text() . ']]</span>';
                        if ( $this->mTriedSave && !$this->mTokenOk ) {
                                if ( $this->mTokenOkExceptSuffix ) {
                                        $note = wfMessage( 'token_suffix_mismatch' )->plain();
@@ -3139,8 +3189,7 @@ HTML
                        } elseif ( $this->incompleteForm ) {
                                $note = wfMessage( 'edit_form_incomplete' )->plain();
                        } else {
-                               $note = wfMessage( 'previewnote' )->plain() .
-                                       ' [[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . wfMessage( 'continue-editing' )->text() . ']]';
+                               $note = wfMessage( 'previewnote' )->plain() . ' ' . $continueEditing;
                        }
 
                        $parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
@@ -3169,7 +3218,9 @@ HTML
                                # Used messages to make sure grep find them:
                                # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
                                if ( $level && $format ) {
-                                       $note = "<div id='mw-{$level}{$format}preview'>" . wfMessage( "{$level}{$format}preview" )->text() . "</div>";
+                                       $note = "<div id='mw-{$level}{$format}preview'>" .
+                                               wfMessage( "{$level}{$format}preview" )->text() .
+                                               ' ' . $continueEditing . "</div>";
                                }
                        }
 
@@ -3596,29 +3647,6 @@ HTML
                $wgOut->returnToMain( false, $this->mTitle );
        }
 
-       /**
-        * Produce the stock "your edit contains spam" page
-        *
-        * @param string|bool $match Text which triggered one or more filters
-        * @deprecated since 1.17 Use method spamPageWithContent() instead
-        */
-       static function spamPage( $match = false ) {
-               wfDeprecated( __METHOD__, '1.17' );
-
-               global $wgOut, $wgTitle;
-
-               $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) );
-
-               $wgOut->addHTML( '<div id="spamprotected">' );
-               $wgOut->addWikiMsg( 'spamprotectiontext' );
-               if ( $match ) {
-                       $wgOut->addWikiMsg( 'spamprotectionmatch', wfEscapeWikiText( $match ) );
-               }
-               $wgOut->addHTML( '</div>' );
-
-               $wgOut->returnToMain( false, $wgTitle );
-       }
-
        /**
         * Show "your edit contains spam" page with your diff and text
         *
index fba857f..4548345 100644 (file)
@@ -30,7 +30,6 @@
  * @ingroup Exception
  */
 class MWException extends Exception {
-
        /**
         * Should the exception use $wgOut to output the error?
         *
@@ -43,6 +42,16 @@ class MWException extends Exception {
                        !empty( $GLOBALS['wgTitle'] );
        }
 
+       /**
+        * Whether to log this exception in the exception debug log.
+        *
+        * @since 1.23
+        * @return boolean
+        */
+       function isLoggable() {
+               return true;
+       }
+
        /**
         * Can the extension use the Message class/wfMessage to get i18n-ed messages?
         *
@@ -74,7 +83,9 @@ class MWException extends Exception {
                        return null; // Just silently ignore
                }
 
-               if ( !array_key_exists( $name, $wgExceptionHooks ) || !is_array( $wgExceptionHooks[$name] ) ) {
+               if ( !array_key_exists( $name, $wgExceptionHooks ) ||
+                       !is_array( $wgExceptionHooks[$name] )
+               ) {
                        return null;
                }
 
@@ -82,7 +93,11 @@ class MWException extends Exception {
                $callargs = array_merge( array( $this ), $args );
 
                foreach ( $hooks as $hook ) {
-                       if ( is_string( $hook ) || ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) ) { // 'function' or array( 'class', hook' )
+                       if (
+                               is_string( $hook ) ||
+                               ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) )
+                       ) {
+                               // 'function' or array( 'class', hook' )
                                $result = call_user_func_array( $hook, $callargs );
                        } else {
                                $result = null;
@@ -125,8 +140,8 @@ class MWException extends Exception {
                global $wgShowExceptionDetails;
 
                if ( $wgShowExceptionDetails ) {
-                       return '<p>' . nl2br( htmlspecialchars( $this->getMessage() ) ) .
-                               '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( MWExceptionHandler::formatRedactedTrace( $this ) ) ) .
+                       return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
+                               '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
                                "</p>\n";
                } else {
                        return "<div class=\"errorbox\">" .
@@ -150,8 +165,8 @@ class MWException extends Exception {
                global $wgShowExceptionDetails;
 
                if ( $wgShowExceptionDetails ) {
-                       return $this->getMessage() .
-                               "\nBacktrace:\n" . MWExceptionHandler::formatRedactedTrace( $this ) . "\n";
+                       return MWExceptionHandler::getLogMessage( $this ) .
+                               "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
                } else {
                        return "Set \$wgShowExceptionDetails = true; " .
                                "in LocalSettings.php to show detailed debugging information.\n";
@@ -164,7 +179,8 @@ class MWException extends Exception {
         * @return string
         */
        function getPageTitle() {
-               return $this->msg( 'internalerror', "Internal error" );
+               global $wgSitename;
+               return $this->msg( 'pagetitle', "$1 - $wgSitename", $this->msg( 'internalerror', 'Internal error' ) );
        }
 
        /**
@@ -209,13 +225,14 @@ class MWException extends Exception {
 
                        $wgOut->output();
                } else {
-                       header( "Content-Type: text/html; charset=utf-8" );
-                       echo "<!doctype html>\n" .
+                       header( 'Content-Type: text/html; charset=utf-8' );
+                       echo "<!DOCTYPE html>\n" .
                                '<html><head>' .
                                '<title>' . htmlspecialchars( $this->getPageTitle() ) . '</title>' .
+                               '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
                                "</head><body>\n";
 
-                       $hookResult = $this->runHooks( get_class( $this ) . "Raw" );
+                       $hookResult = $this->runHooks( get_class( $this ) . 'Raw' );
                        if ( $hookResult ) {
                                echo $hookResult;
                        } else {
@@ -242,8 +259,8 @@ class MWException extends Exception {
                } elseif ( self::isCommandLine() ) {
                        MWExceptionHandler::printError( $this->getText() );
                } else {
-                       header( "HTTP/1.1 500 MediaWiki exception" );
-                       header( "Status: 500 MediaWiki exception", true );
+                       header( 'HTTP/1.1 500 MediaWiki exception' );
+                       header( 'Status: 500 MediaWiki exception', true );
                        header( "Content-Type: $wgMimeType; charset=utf-8", true );
 
                        $this->reportHTML();
@@ -480,11 +497,11 @@ class UserBlockedError extends ErrorPageError {
 class UserNotLoggedIn extends ErrorPageError {
 
        /**
-        * @param $reasonMsg A message key containing the reason for the error.
+        * @param string $reasonMsg A message key containing the reason for the error.
         *        Optional, default: 'exception-nologin-text'
-        * @param $titleMsg A message key to set the page title.
+        * @param string $titleMsg A message key to set the page title.
         *        Optional, default: 'exception-nologin'
-        * @param $params Parameters to wfMessage().
+        * @param array $params Parameters to wfMessage().
         *        Optional, default: null
         */
        public function __construct(
@@ -601,8 +618,10 @@ class MWExceptionHandler {
                                $message = "MediaWiki internal error.\n\n";
 
                                if ( $wgShowExceptionDetails ) {
-                                       $message .= 'Original exception: ' . self::formatRedactedTrace( $e ) . "\n\n" .
-                                               'Exception caught inside exception handler: ' . $e2->__toString();
+                                       $message .= 'Original exception: ' . self::getLogMessage( $e ) .
+                                               "\nBacktrace:\n" . self::getRedactedTraceAsString( $e ) .
+                                               "\n\nException caught inside exception handler: " . self::getLogMessage( $e2 ) .
+                                               "\nBacktrace:\n" . self::getRedactedTraceAsString( $e2 );
                                } else {
                                        $message .= "Exception caught inside exception handler.\n\n" .
                                                "Set \$wgShowExceptionDetails = true; at the bottom of LocalSettings.php " .
@@ -618,10 +637,12 @@ class MWExceptionHandler {
                                }
                        }
                } else {
-                       $message = "Unexpected non-MediaWiki exception encountered, of type \"" . get_class( $e ) . "\"";
+                       $message = "Unexpected non-MediaWiki exception encountered, of type \"" .
+                               get_class( $e ) . "\"";
 
                        if ( $wgShowExceptionDetails ) {
-                               $message .= "\nexception '" . get_class( $e ) . "' in " . $e->getFile() . ":" . $e->getLine() . "\nStack trace:\n" . self::formatRedactedTrace( $e ) . "\n";
+                               $message .= "\n" . MWExceptionHandler::getLogMessage( $e ) . "\nBacktrace:\n" .
+                                       self::getRedactedTraceAsString( $e ) . "\n";
                        }
 
                        if ( $cmdLine ) {
@@ -639,8 +660,9 @@ class MWExceptionHandler {
         * @param string $message Failure text
         */
        public static function printError( $message ) {
-               # NOTE: STDERR may not be available, especially if php-cgi is used from the command line (bug #15602).
-               #      Try to produce meaningful output anyway. Using echo may corrupt output to STDOUT though.
+               # NOTE: STDERR may not be available, especially if php-cgi is used from the
+               # command line (bug #15602). Try to produce meaningful output anyway. Using
+               # echo may corrupt output to STDOUT though.
                if ( defined( 'STDERR' ) ) {
                        fwrite( STDERR, $message );
                } else {
@@ -678,64 +700,67 @@ class MWExceptionHandler {
        }
 
        /**
-        * Get the stack trace from the exception as a string, redacting certain function arguments in the process
-        * @param Exception $e The exception
-        * @return string The stack trace as a string
+        * Generate a string representation of an exception's stack trace
+        *
+        * Like Exception::getTraceAsString, but replaces argument values with
+        * argument type or class name.
+        *
+        * @param Exception $e
+        * @return string
         */
-       public static function formatRedactedTrace( Exception $e ) {
-               global $wgRedactedFunctionArguments;
-               $finalExceptionText = '';
+       public static function getRedactedTraceAsString( Exception $e ) {
+               $text = '';
 
-               foreach ( $e->getTrace() as $i => $call ) {
-                       $checkFor = array();
-                       if ( isset( $call['class'] ) ) {
-                               $checkFor[] = $call['class'] . '::' . $call['function'];
-                               foreach ( class_parents( $call['class'] ) as $parent ) {
-                                       $checkFor[] = $parent . '::' . $call['function'];
-                               }
-                       } else {
-                               $checkFor[] = $call['function'];
-                       }
-
-                       foreach ( $checkFor as $check ) {
-                               if ( isset( $wgRedactedFunctionArguments[$check] ) ) {
-                                       foreach ( (array)$wgRedactedFunctionArguments[$check] as $argNo ) {
-                                               $call['args'][$argNo] = 'REDACTED';
-                                       }
-                               }
-                       }
-
-                       if ( isset( $call['file'] ) && isset( $call['line'] ) ) {
-                               $finalExceptionText .= "#{$i} {$call['file']}({$call['line']}): ";
+               foreach ( self::getRedactedTrace( $e ) as $level => $frame ) {
+                       if ( isset( $frame['file'] ) && isset( $frame['line'] ) ) {
+                               $text .= "#{$level} {$frame['file']}({$frame['line']}): ";
                        } else {
                                // 'file' and 'line' are unset for calls via call_user_func (bug 55634)
                                // This matches behaviour of Exception::getTraceAsString to instead
                                // display "[internal function]".
-                               $finalExceptionText .= "#{$i} [internal function]: ";
+                               $text .= "#{$level} [internal function]: ";
                        }
 
-                       if ( isset( $call['class'] ) ) {
-                               $finalExceptionText .= $call['class'] . $call['type'] . $call['function'];
+                       if ( isset( $frame['class'] ) ) {
+                               $text .= $frame['class'] . $frame['type'] . $frame['function'];
                        } else {
-                               $finalExceptionText .= $call['function'];
+                               $text .= $frame['function'];
                        }
-                       $args = array();
-                       if ( isset( $call['args'] ) ) {
-                               foreach ( $call['args'] as $arg ) {
-                                       if ( is_object( $arg ) ) {
-                                               $args[] = 'Object(' . get_class( $arg ) . ')';
-                                       } elseif( is_array( $arg ) ) {
-                                               $args[] = 'Array';
-                                       } else {
-                                               $args[] = var_export( $arg, true );
-                                       }
-                               }
+
+                       if ( isset( $frame['args'] ) ) {
+                               $text .= '(' . implode( ', ', $frame['args'] ) . ")\n";
+                       } else {
+                               $text .= "()\n";
                        }
-                       $finalExceptionText .=  '(' . implode( ', ', $args ) . ")\n";
                }
-               return $finalExceptionText . '#' . ( $i + 1 ) . ' {main}';
+
+               $level = $level + 1;
+               $text .= "#{$level} {main}";
+
+               return $text;
        }
 
+       /**
+        * Return a copy of an exception's backtrace as an array.
+        *
+        * Like Exception::getTrace, but replaces each element in each frame's
+        * argument array with the name of its class (if the element is an object)
+        * or its type (if the element is a PHP primitive).
+        *
+        * @since 1.22
+        * @param Exception $e
+        * @return array
+        */
+       public static function getRedactedTrace( Exception $e ) {
+               return array_map( function ( $frame ) {
+                       if ( isset( $frame['args'] ) ) {
+                               $frame['args'] = array_map( function ( $arg ) {
+                                       return is_object( $arg ) ? get_class( $arg ) : gettype( $arg );
+                               }, $frame['args'] );
+                       }
+                       return $frame;
+               }, $e->getTrace() );
+       }
 
        /**
         * Get the ID for this error.
@@ -754,6 +779,21 @@ class MWExceptionHandler {
                return $e->_mwLogId;
        }
 
+       /**
+        * If the exception occurred in the course of responding to a request,
+        * returns the requested URL. Otherwise, returns false.
+        *
+        * @since 1.23
+        * @return string|bool
+        */
+       public static function getURL() {
+               global $wgRequest;
+               if ( !isset( $wgRequest ) || $wgRequest instanceof FauxRequest ) {
+                       return false;
+               }
+               return $wgRequest->getRequestURL();
+       }
+
        /**
         * Return the requested URL and point to file and line number from which the
         * exception occurred.
@@ -763,23 +803,88 @@ class MWExceptionHandler {
         * @return string
         */
        public static function getLogMessage( Exception $e ) {
-               global $wgRequest;
-
                $id = self::getLogId( $e );
                $file = $e->getFile();
                $line = $e->getLine();
                $message = $e->getMessage();
+               $url = self::getURL() ?: '[no req]';
 
-               if ( isset( $wgRequest ) && !$wgRequest instanceof FauxRequest ) {
-                       $url = $wgRequest->getRequestURL();
-                       if ( !$url ) {
-                               $url = '[no URL]';
-                       }
-               } else {
-                       $url = '[no req]';
+               return "[$id] $url   Exception from line $line of $file: $message";
+       }
+
+       /**
+        * Serialize an Exception object to JSON.
+        *
+        * The JSON object will have keys 'id', 'file', 'line', 'message', and
+        * 'url'. These keys map to string values, with the exception of 'line',
+        * which is a number, and 'url', which may be either a string URL or or
+        * null if the exception did not occur in the context of serving a web
+        * request.
+        *
+        * If $wgLogExceptionBacktrace is true, it will also have a 'backtrace'
+        * key, mapped to the array return value of Exception::getTrace, but with
+        * each element in each frame's "args" array (if set) replaced with the
+        * argument's class name (if the argument is an object) or type name (if
+        * the argument is a PHP primitive).
+        *
+        * @par Sample JSON record ($wgLogExceptionBacktrace = false):
+        * @code
+        *  {
+        *    "id": "c41fb419",
+        *    "file": "/var/www/mediawiki/includes/cache/MessageCache.php",
+        *    "line": 704,
+        *    "message": "Non-string key given",
+        *    "url": "/wiki/Main_Page"
+        *  }
+        * @endcode
+        *
+        * @par Sample JSON record ($wgLogExceptionBacktrace = true):
+        * @code
+        *  {
+        *    "id": "dc457938",
+        *    "file": "/vagrant/mediawiki/includes/cache/MessageCache.php",
+        *    "line": 704,
+        *    "message": "Non-string key given",
+        *    "url": "/wiki/Main_Page",
+        *    "backtrace": [{
+        *      "file": "/vagrant/mediawiki/extensions/VisualEditor/VisualEditor.hooks.php",
+        *      "line": 80,
+        *      "function": "get",
+        *      "class": "MessageCache",
+        *      "type": "->",
+        *      "args": ["array"]
+        *    }]
+        *  }
+        * @endcode
+        *
+        * @since 1.23
+        * @param Exception $e
+        * @param bool $pretty Add non-significant whitespace to improve readability (default: false).
+        * @param int $escaping Bitfield consisting of FormatJson::.*_OK class constants.
+        * @return string|bool: JSON string if successful; false upon failure
+        */
+       public static function jsonSerializeException( Exception $e, $pretty = false, $escaping = 0 ) {
+               global $wgLogExceptionBacktrace;
+
+               $exceptionData = array(
+                       'id' => self::getLogId( $e ),
+                       'file' => $e->getFile(),
+                       'line' => $e->getLine(),
+                       'message' => $e->getMessage(),
+               );
+
+               // Because MediaWiki is first and foremost a web application, we set a
+               // 'url' key unconditionally, but set it to null if the exception does
+               // not occur in the context of a web request, as a way of making that
+               // fact visible and explicit.
+               $exceptionData['url'] = self::getURL() ?: null;
+
+               if ( $wgLogExceptionBacktrace ) {
+                       // Argument values may not be serializable, so redact them.
+                       $exceptionData['backtrace'] = self::getRedactedTrace( $e );
                }
 
-               return "[$id] $url   Exception from line $line of $file: $message";
+               return FormatJson::encode( $exceptionData, $pretty, $escaping );
        }
 
        /**
@@ -794,14 +899,20 @@ class MWExceptionHandler {
        public static function logException( Exception $e ) {
                global $wgLogExceptionBacktrace;
 
-               $log = self::getLogMessage( $e );
-               if ( $log ) {
+               if ( !( $e instanceof MWException ) || $e->isLoggable() ) {
+                       $log = self::getLogMessage( $e );
                        if ( $wgLogExceptionBacktrace ) {
-                               wfDebugLog( 'exception', $log . "\n" . self::formatRedactedTrace( $e ) . "\n" );
+                               wfDebugLog( 'exception', $log . "\n" . $e->getTraceAsString() . "\n" );
                        } else {
                                wfDebugLog( 'exception', $log );
                        }
+
+                       $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
+                       if ( $json !== false ) {
+                               wfDebugLog( 'exception-json', $json, false );
+                       }
                }
+
        }
 
 }
index 98de4c0..b4a507d 100644 (file)
@@ -503,7 +503,8 @@ class XmlDumpWriter {
                        'xmlns'              => "http://www.mediawiki.org/xml/export-$ver/",
                        'xmlns:xsi'          => "http://www.w3.org/2001/XMLSchema-instance",
                        'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
-                                               "http://www.mediawiki.org/xml/export-$ver.xsd", #TODO: how do we get a new version up there?
+                               #TODO: how do we get a new version up there?
+                               "http://www.mediawiki.org/xml/export-$ver.xsd",
                        'version'            => $ver,
                        'xml:lang'           => $wgLanguageCode ),
                        null ) .
@@ -604,7 +605,7 @@ class XmlDumpWriter {
                if ( $row->page_is_redirect ) {
                        $page = WikiPage::factory( $title );
                        $redirect = $page->getRedirectTarget();
-                       if ( $redirect instanceOf Title && $redirect->isValidRedirectTarget() ) {
+                       if ( $redirect instanceof Title && $redirect->isValidRedirectTarget() ) {
                                $out .= '    ' . Xml::element( 'redirect', array( 'title' => self::canonicalTitle( $redirect ) ) ) . "\n";
                        }
                }
index 54822e3..cd6e207 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright © 2008, Niklas Laxström
  * Copyright © 2011, Antoine Musso
+ * Copyright © 2013, Bartosz Dziewoński
  *
  * 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
@@ -42,6 +43,9 @@ class FormOptions implements ArrayAccess {
        const STRING = 0;
        /** Integer type, maps guessType() to WebRequest::getInt() */
        const INT = 1;
+       /** Float type, maps guessType() to WebRequest::getFloat()
+         * @since 1.23 */
+       const FLOAT = 4;
        /** Boolean type, maps guessType() to WebRequest::getBool() */
        const BOOL = 2;
        /** Integer type or null, maps to WebRequest::getIntOrNull()
@@ -112,6 +116,8 @@ class FormOptions implements ArrayAccess {
                        return self::BOOL;
                } elseif ( is_int( $data ) ) {
                        return self::INT;
+               } elseif ( is_float( $data ) ) {
+                       return self::FLOAT;
                } elseif ( is_string( $data ) ) {
                        return self::STRING;
                } else {
@@ -234,19 +240,29 @@ class FormOptions implements ArrayAccess {
        }
 
        /**
-        * Validate and set an option integer value
-        * The value will be altered to fit in the range.
+        * @see validateBounds()
+        */
+       public function validateIntBounds( $name, $min, $max ) {
+               $this->validateBounds( $name, $min, $max );
+       }
+
+       /**
+        * Constrain a numeric value for a given option to a given range. The value will be altered to fit
+        * in the range.
         *
-        * @param string $name option name
-        * @param int $min minimum value
-        * @param int $max maximum value
+        * @since 1.23
+        *
+        * @param string $name Option name
+        * @param int|float $min Minimum value
+        * @param int|float $max Maximum value
         * @throws MWException If option is not of type INT
         */
-       public function validateIntBounds( $name, $min, $max ) {
+       public function validateBounds( $name, $min, $max ) {
                $this->validateName( $name, true );
+               $type = $this->options[$name]['type'];
 
-               if ( $this->options[$name]['type'] !== self::INT ) {
-                       throw new MWException( "Option $name is not of type int" );
+               if ( $type !== self::INT && $type !== self::FLOAT ) {
+                       throw new MWException( "Option $name is not of type INT or FLOAT" );
                }
 
                $value = $this->getValueReal( $this->options[$name] );
@@ -333,6 +349,9 @@ class FormOptions implements ArrayAccess {
                                case self::INT:
                                        $value = $r->getInt( $name, $default );
                                        break;
+                               case self::FLOAT:
+                                       $value = $r->getFloat( $name, $default );
+                                       break;
                                case self::STRING:
                                        $value = $r->getText( $name, $default );
                                        break;
index f49f9be..e0bd5cd 100644 (file)
@@ -143,8 +143,7 @@ class GitInfo {
                } else {
                        return (int)$commitDate;
                }
-
-        }
+       }
 
        /**
         * Return the name of the current branch, or HEAD if not found
index 77c09e5..819b076 100644 (file)
@@ -81,7 +81,6 @@ if ( !function_exists( 'mb_strpos' ) ) {
        function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
                return Fallback::mb_strpos( $haystack, $needle, $offset, $encoding );
        }
-
 }
 
 if ( !function_exists( 'mb_strrpos' ) ) {
@@ -283,8 +282,8 @@ function wfRandom() {
        # The maximum random value is "only" 2^31-1, so get two random
        # values to reduce the chance of dupes
        $max = mt_getrandmax() + 1;
-       $rand = number_format( ( mt_rand() * $max + mt_rand() )
-               / $max / $max, 12, '.', '' );
+       $rand = number_format( ( mt_rand() * $max + mt_rand() ) / $max / $max, 12, '.', '' );
+
        return $rand;
 }
 
@@ -330,6 +329,7 @@ function wfRandomString( $length = 32 ) {
  */
 function wfUrlencode( $s ) {
        static $needle;
+
        if ( is_null( $s ) ) {
                $needle = null;
                return '';
@@ -337,7 +337,9 @@ function wfUrlencode( $s ) {
 
        if ( is_null( $needle ) ) {
                $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
-               if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) || ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false ) ) {
+               if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
+                       ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
+               ) {
                        $needle[] = '%3A';
                }
        }
@@ -470,15 +472,17 @@ function wfAppendQuery( $url, $query ) {
 }
 
 /**
- * Expand a potentially local URL to a fully-qualified URL.  Assumes $wgServer
+ * Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer
  * is correct.
  *
  * The meaning of the PROTO_* constants is as follows:
  * PROTO_HTTP: Output a URL starting with http://
  * PROTO_HTTPS: Output a URL starting with https://
  * PROTO_RELATIVE: Output a URL starting with // (protocol-relative URL)
- * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending on which protocol was used for the current incoming request
- * PROTO_CANONICAL: For URLs without a domain, like /w/index.php , use $wgCanonicalServer. For protocol-relative URLs, use the protocol of $wgCanonicalServer
+ * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending
+ *    on which protocol was used for the current incoming request
+ * PROTO_CANONICAL: For URLs without a domain, like /w/index.php , use $wgCanonicalServer.
+ *    For protocol-relative URLs, use the protocol of $wgCanonicalServer
  * PROTO_INTERNAL: Like PROTO_CANONICAL, but uses $wgInternalServer instead of $wgCanonicalServer
  *
  * @todo this won't work with current-path-relative URLs
@@ -486,23 +490,22 @@ function wfAppendQuery( $url, $query ) {
  *
  * @param string $url either fully-qualified or a local path + query
  * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the
- *                             protocol to use if $url or $wgServer is
- *                             protocol-relative
+ *    protocol to use if $url or $wgServer is protocol-relative
  * @return string Fully-qualified URL, current-path-relative URL or false if
- *                no valid URL can be constructed
+ *    no valid URL can be constructed
  */
 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
-       global $wgServer, $wgCanonicalServer, $wgInternalServer;
-       $serverUrl = $wgServer;
+       global $wgServer, $wgCanonicalServer, $wgInternalServer, $wgRequest;
        if ( $defaultProto === PROTO_CANONICAL ) {
                $serverUrl = $wgCanonicalServer;
-       }
-       // Make $wgInternalServer fall back to $wgServer if not set
-       if ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
+       } elseif ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
+               // Make $wgInternalServer fall back to $wgServer if not set
                $serverUrl = $wgInternalServer;
-       }
-       if ( $defaultProto === PROTO_CURRENT ) {
-               $defaultProto = WebRequest::detectProtocol() . '://';
+       } else {
+               $serverUrl = $wgServer;
+               if ( $defaultProto === PROTO_CURRENT ) {
+                       $defaultProto = $wgRequest->getProtocol() . '://';
+               }
        }
 
        // Analyze $serverUrl to obtain its protocol
@@ -513,8 +516,9 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
                if ( $serverHasProto ) {
                        $defaultProto = $bits['scheme'] . '://';
                } else {
-                       // $wgCanonicalServer or $wgInternalServer doesn't have a protocol. This really isn't supposed to happen
-                       // Fall back to HTTP in this ridiculous case
+                       // $wgCanonicalServer or $wgInternalServer doesn't have a protocol.
+                       // This really isn't supposed to happen. Fall back to HTTP in this
+                       // ridiculous case.
                        $defaultProto = PROTO_HTTP;
                }
        }
@@ -524,7 +528,8 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
        if ( substr( $url, 0, 2 ) == '//' ) {
                $url = $defaultProtoWithoutSlashes . $url;
        } elseif ( substr( $url, 0, 1 ) == '/' ) {
-               // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone
+               // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
+               // otherwise leave it alone.
                $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url;
        }
 
@@ -739,9 +744,10 @@ function wfUrlProtocolsWithoutProtRel() {
 /**
  * parse_url() work-alike, but non-broken.  Differences:
  *
- * 1) Does not raise warnings on bad URLs (just returns false)
- * 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly
- * 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2))
+ * 1) Does not raise warnings on bad URLs (just returns false).
+ * 2) Handles protocols that don't use :// (e.g., mailto: and news:, as well as
+ *    protocol-relative URLs) correctly.
+ * 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2)).
  *
  * @param string $url a URL to parse
  * @return Array: bits of the URL in an associative array, per PHP docs
@@ -749,8 +755,9 @@ function wfUrlProtocolsWithoutProtRel() {
 function wfParseUrl( $url ) {
        global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
 
-       // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest
-       // way to handle them is to just prepend 'http:' and strip the protocol out later
+       // Protocol-relative URLs are handled really badly by parse_url(). It's so
+       // bad that the easiest way to handle them is to just prepend 'http:' and
+       // strip the protocol out later.
        $wasRelative = substr( $url, 0, 2 ) == '//';
        if ( $wasRelative ) {
                $url = "http:$url";
@@ -816,7 +823,11 @@ function wfParseUrl( $url ) {
  * @return string
  */
 function wfExpandIRI( $url ) {
-       return preg_replace_callback( '/((?:%[89A-F][0-9A-F])+)/i', 'wfExpandIRI_callback', wfExpandUrl( $url ) );
+       return preg_replace_callback(
+               '/((?:%[89A-F][0-9A-F])+)/i',
+               'wfExpandIRI_callback',
+               wfExpandUrl( $url )
+       );
 }
 
 /**
@@ -954,8 +965,8 @@ function wfIsDebugRawPage() {
                || (
                        isset( $_SERVER['SCRIPT_NAME'] )
                        && substr( $_SERVER['SCRIPT_NAME'], -8 ) == 'load.php'
-               ) )
-       {
+               )
+       {
                $cache = true;
        } else {
                $cache = false;
@@ -997,7 +1008,12 @@ function wfDebugMem( $exact = false ) {
 
 /**
  * Send a line to a supplementary debug log file, if configured, or main debug log if not.
- * $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log.
+ * To configure a supplementary log file, set $wgDebugLogGroups[$logGroup] to a string
+ * filename or an associative array mapping 'destination' to the desired filename. The
+ * associative array may also contain a 'sample' key with an integer value, specifying
+ * a sampling factor.
+ *
+ * @since 1.23 support for sampling log messages via $wgDebugLogGroups.
  *
  * @param $logGroup String
  * @param $text String
@@ -1007,14 +1023,28 @@ function wfDebugMem( $exact = false ) {
 function wfDebugLog( $logGroup, $text, $public = true ) {
        global $wgDebugLogGroups;
        $text = trim( $text ) . "\n";
-       if ( isset( $wgDebugLogGroups[$logGroup] ) ) {
-               $time = wfTimestamp( TS_DB );
-               $wiki = wfWikiID();
-               $host = wfHostname();
-               wfErrorLog( "$time $host $wiki: $text", $wgDebugLogGroups[$logGroup] );
-       } elseif ( $public === true ) {
-               wfDebug( "[$logGroup] $text", false );
+
+       if ( !isset( $wgDebugLogGroups[$logGroup] ) ) {
+               if ( $public === true ) {
+                       wfDebug( "[$logGroup] $text", false );
+               }
+               return;
        }
+
+       $logConfig = $wgDebugLogGroups[$logGroup];
+       if ( is_array( $logConfig ) ) {
+               if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
+                       return;
+               }
+               $destination = $logConfig['destination'];
+       } else {
+               $destination = strval( $logConfig );
+       }
+
+       $time = wfTimestamp( TS_DB );
+       $wiki = wfWikiID();
+       $host = wfHostname();
+       wfErrorLog( "$time $host $wiki: $text", $destination );
 }
 
 /**
@@ -1053,7 +1083,8 @@ function wfLogDBError( $text ) {
  * Throws a warning that $function is deprecated
  *
  * @param $function String
- * @param string|bool $version Version of MediaWiki that the function was deprecated in (Added in 1.19).
+ * @param string|bool $version Version of MediaWiki that the function
+ *    was deprecated in (Added in 1.19).
  * @param string|bool $component Added in 1.19.
  * @param $callerOffset integer: How far up the call stack is the original
  *    caller. 2 = function that called the function that called
@@ -1432,9 +1463,9 @@ function wfMsgForContent( $key ) {
        $args = func_get_args();
        array_shift( $args );
        $forcontent = true;
-       if ( is_array( $wgForceUIMsgAsContentMsg ) &&
-               in_array( $key, $wgForceUIMsgAsContentMsg ) )
-       {
+       if ( is_array( $wgForceUIMsgAsContentMsg )
+               && in_array( $key, $wgForceUIMsgAsContentMsg )
+       {
                $forcontent = false;
        }
        return wfMsgReal( $key, $args, true, $forcontent );
@@ -1455,9 +1486,9 @@ function wfMsgForContentNoTrans( $key ) {
        $args = func_get_args();
        array_shift( $args );
        $forcontent = true;
-       if ( is_array( $wgForceUIMsgAsContentMsg ) &&
-               in_array( $key, $wgForceUIMsgAsContentMsg ) )
-       {
+       if ( is_array( $wgForceUIMsgAsContentMsg )
+               && in_array( $key, $wgForceUIMsgAsContentMsg )
+       {
                $forcontent = false;
        }
        return wfMsgReal( $key, $args, true, $forcontent, false );
@@ -1962,11 +1993,11 @@ function wfClientAcceptsGzip( $force = false ) {
                        # @todo FIXME: We may want to blacklist some broken browsers
                        $m = array();
                        if ( preg_match(
-                               '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
-                               $_SERVER['HTTP_ACCEPT_ENCODING'],
-                               $m )
-                       )
-                       {
+                                       '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
+                                       $_SERVER['HTTP_ACCEPT_ENCODING'],
+                                       $m
+                               )
+                       {
                                if ( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) {
                                        $result = false;
                                        return $result;
@@ -2325,7 +2356,15 @@ function wfSuppressWarnings( $end = false ) {
                }
        } else {
                if ( !$suppressCount ) {
-                       $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT ) );
+                       $originalLevel = error_reporting( E_ALL & ~(
+                               E_WARNING |
+                               E_NOTICE |
+                               E_USER_WARNING |
+                               E_USER_NOTICE |
+                               E_DEPRECATED |
+                               E_USER_DEPRECATED |
+                               E_STRICT
+                       ) );
                }
                ++$suppressCount;
        }
@@ -2450,12 +2489,12 @@ function wfIsWindows() {
 }
 
 /**
- * Check if we are running under HipHop
+ * Check if we are running under HHVM
  *
  * @return Bool
  */
-function wfIsHipHop() {
-       return defined( 'HPHP_VERSION' );
+function wfIsHHVM() {
+       return defined( 'HHVM_VERSION' );
 }
 
 /**
@@ -2656,12 +2695,14 @@ function wfEscapeShellArg() {
 
                if ( wfIsWindows() ) {
                        // Escaping for an MSVC-style command line parser and CMD.EXE
+                       // @codingStandardsIgnoreStart For long URLs
                        // Refs:
                        //  * http://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html
                        //  * http://technet.microsoft.com/en-us/library/cc723564.aspx
                        //  * Bug #13518
                        //  * CR r63214
                        // Double the backslashes before any double quotes. Escape the double quotes.
+                       // @codingStandardsIgnoreEnd
                        $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE );
                        $arg = '';
                        $iteration = 0;
@@ -2710,9 +2751,9 @@ function wfShellExecDisabled() {
                        $functions = explode( ',', ini_get( 'disable_functions' ) );
                        $functions = array_map( 'trim', $functions );
                        $functions = array_map( 'strtolower', $functions );
-                       if ( in_array( 'passthru', $functions ) ) {
-                               wfDebug( "passthru is in disabled_functions\n" );
-                               $disabled = 'passthru';
+                       if ( in_array( 'proc_open', $functions ) ) {
+                               wfDebug( "proc_open is in disabled_functions\n" );
+                               $disabled = 'disabled';
                        }
                }
        }
@@ -2724,16 +2765,21 @@ function wfShellExecDisabled() {
  * configuration if supported.
  * @param string $cmd Command line, properly escaped for shell.
  * @param &$retval null|Mixed optional, will receive the program's exit code.
- *                 (non-zero is usually failure)
+ *                 (non-zero is usually failure). If there is an error from
+ *                 read, select, or proc_open(), this will be set to -1.
  * @param array $environ optional environment variables which should be
  *                 added to the executed command environment.
  * @param array $limits optional array with limits(filesize, memory, time, walltime)
- *                 this overwrites the global wgShellMax* limits.
- * @param array $options Array of options. Only one is "duplicateStderr" => true, which
- *                 Which duplicates stderr to stdout, including errors from limit.sh
+ *                 this overwrites the global wgMaxShell* limits.
+ * @param array $options Array of options:
+ *    - duplicateStderr: Set this to true to duplicate stderr to stdout,
+ *      including errors from limit.sh
+ *
  * @return string collected stdout as a string
  */
-function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array(), $options = array() ) {
+function wfShellExec( $cmd, &$retval = null, $environ = array(),
+       $limits = array(), $options = array()
+) {
        global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
                $wgMaxShellWallClockTime, $wgShellCgroup;
 
@@ -2742,7 +2788,7 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array
                $retval = 1;
                return $disabled == 'safemode' ?
                        'Unable to run external programs in safe mode.' :
-                       'Unable to run external programs, passthru() is disabled.';
+                       'Unable to run external programs, proc_open() is disabled.';
        }
 
        $includeStderr = isset( $options['duplicateStderr'] ) && $options['duplicateStderr'];
@@ -2768,6 +2814,7 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array
        }
        $cmd = $envcmd . $cmd;
 
+       $useLogPipe = false;
        if ( php_uname( 's' ) == 'Linux' ) {
                $time = intval ( isset( $limits['time'] ) ? $limits['time'] : $wgMaxShellTime );
                if ( isset( $limits['walltime'] ) ) {
@@ -2789,8 +2836,10 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array
                                        'MW_CGROUP=' . escapeshellarg( $wgShellCgroup ) . '; ' .
                                        "MW_MEM_LIMIT=$mem; " .
                                        "MW_FILE_SIZE_LIMIT=$filesize; " .
-                                       "MW_WALL_CLOCK_LIMIT=$wallTime"
+                                       "MW_WALL_CLOCK_LIMIT=$wallTime; " .
+                                       "MW_USE_LOG_PIPE=yes"
                                );
+                       $useLogPipe = true;
                } elseif ( $includeStderr ) {
                        $cmd .= ' 2>&1';
                }
@@ -2799,19 +2848,144 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array
        }
        wfDebug( "wfShellExec: $cmd\n" );
 
-       // Default to an unusual value that shouldn't happen naturally,
-       // so in the unlikely event of a weird php bug, it would be
-       // more obvious what happened.
-       $retval = 200;
-       ob_start();
-       passthru( $cmd, $retval );
-       $output = ob_get_contents();
-       ob_end_clean();
+       $desc = array(
+               0 => array( 'file', 'php://stdin', 'r' ),
+               1 => array( 'pipe', 'w' ),
+               2 => array( 'file', 'php://stderr', 'w' ) );
+       if ( $useLogPipe ) {
+               $desc[3] = array( 'pipe', 'w' );
+       }
 
-       if ( $retval == 127 ) {
-               wfDebugLog( 'exec', "Possibly missing executable file: $cmd\n" );
+       # TODO/FIXME: This is a bad hack to workaround an HHVM bug that prevents
+       # proc_open() from opening stdin/stdout, so use /dev/null *for now*
+       # See bug 56597 / https://github.com/facebook/hhvm/issues/1247 for more info
+       if ( wfIsHHVM() ) {
+               $desc[0] = array( 'file', '/dev/null', 'r' );
+               $desc[2] = array( 'file', '/dev/null', 'w' );
        }
-       return $output;
+
+       $pipes = null;
+       $proc = proc_open( $cmd, $desc, $pipes );
+       if ( !$proc ) {
+               wfDebugLog( 'exec', "proc_open() failed: $cmd\n" );
+               $retval = -1;
+               return '';
+       }
+       $outBuffer = $logBuffer = '';
+       $emptyArray = array();
+       $status = false;
+       $logMsg = false;
+
+       // According to the documentation, it is possible for stream_select()
+       // to fail due to EINTR. I haven't managed to induce this in testing
+       // despite sending various signals. If it did happen, the error
+       // message would take the form:
+       //
+       // stream_select(): unable to select [4]: Interrupted system call (max_fd=5)
+       //
+       // where [4] is the value of the macro EINTR and "Interrupted system
+       // call" is string which according to the Linux manual is "possibly"
+       // localised according to LC_MESSAGES.
+       $eintr = defined( 'SOCKET_EINTR' ) ? SOCKET_EINTR : 4;
+       $eintrMessage = "stream_select(): unable to select [$eintr]";
+
+       // Build a table mapping resource IDs to pipe FDs to work around a
+       // PHP 5.3 issue in which stream_select() does not preserve array keys
+       // <https://bugs.php.net/bug.php?id=53427>.
+       $fds = array();
+       foreach ( $pipes as $fd => $pipe ) {
+               $fds[(int)$pipe] = $fd;
+       }
+
+       while ( true ) {
+               $status = proc_get_status( $proc );
+               if ( !$status['running'] ) {
+                       break;
+               }
+               $status = false;
+
+               $readyPipes = $pipes;
+
+               // Clear last error
+               @trigger_error( '' );
+               if ( @stream_select( $readyPipes, $emptyArray, $emptyArray, null ) === false ) {
+                       $error = error_get_last();
+                       if ( strncmp( $error['message'], $eintrMessage, strlen( $eintrMessage ) ) == 0 ) {
+                               continue;
+                       } else {
+                               trigger_error( $error['message'], E_USER_WARNING );
+                               $logMsg = $error['message'];
+                               break;
+                       }
+               }
+               foreach ( $readyPipes as $pipe ) {
+                       $block = fread( $pipe, 65536 );
+                       $fd = $fds[(int)$pipe];
+                       if ( $block === '' ) {
+                               // End of file
+                               fclose( $pipes[$fd] );
+                               unset( $pipes[$fd] );
+                               if ( !$pipes ) {
+                                       break 2;
+                               }
+                       } elseif ( $block === false ) {
+                               // Read error
+                               $logMsg = "Error reading from pipe";
+                               break 2;
+                       } elseif ( $fd == 1 ) {
+                               // From stdout
+                               $outBuffer .= $block;
+                       } elseif ( $fd == 3 ) {
+                               // From log FD
+                               $logBuffer .= $block;
+                               if ( strpos( $block, "\n" ) !== false ) {
+                                       $lines = explode( "\n", $logBuffer );
+                                       $logBuffer = array_pop( $lines );
+                                       foreach ( $lines as $line ) {
+                                               wfDebugLog( 'exec', $line );
+                                       }
+                               }
+                       }
+               }
+       }
+
+       foreach ( $pipes as $pipe ) {
+               fclose( $pipe );
+       }
+
+       // Use the status previously collected if possible, since proc_get_status()
+       // just calls waitpid() which will not return anything useful the second time.
+       if ( $status === false ) {
+               $status = proc_get_status( $proc );
+       }
+
+       if ( $logMsg !== false ) {
+               // Read/select error
+               $retval = -1;
+               proc_close( $proc );
+       } elseif ( $status['signaled'] ) {
+               $logMsg = "Exited with signal {$status['termsig']}";
+               $retval = 128 + $status['termsig'];
+               proc_close( $proc );
+       } else {
+               if ( $status['running'] ) {
+                       $retval = proc_close( $proc );
+               } else {
+                       $retval = $status['exitcode'];
+                       proc_close( $proc );
+               }
+               if ( $retval == 127 ) {
+                       $logMsg = "Possibly missing executable file";
+               } elseif ( $retval >= 129 && $retval <= 192 ) {
+                       $logMsg = "Probably exited with signal " . ( $retval - 128 );
+               }
+       }
+
+       if ( $logMsg !== false ) {
+               wfDebugLog( 'exec', "$logMsg: $cmd\n" );
+       }
+
+       return $outBuffer;
 }
 
 /**
@@ -3065,6 +3239,14 @@ function wfUsePHP( $req_ver ) {
  * This is useful for extensions which due to their nature are not kept in sync
  * with releases
  *
+ * Note: Due to the behavior of PHP's version_compare() which is used in this
+ * fuction, if you want to allow the 'wmf' development versions add a 'c' (or
+ * any single letter other than 'a', 'b' or 'p') as a post-fix to your
+ * targeted version number. For example if you wanted to allow any variation
+ * of 1.22 use `wfUseMW( '1.22c' )`. Using an 'a' or 'b' instead of 'c' will
+ * not result in the same comparison due to the internal logic of
+ * version_compare().
+ *
  * @see perldoc -f use
  *
  * @param $req_ver Mixed: the version to check, can be a string, an integer, or
@@ -3092,9 +3274,12 @@ function wfUseMW( $req_ver ) {
  * @return String
  */
 function wfBaseName( $path, $suffix = '' ) {
-       $encSuffix = ( $suffix == '' )
-               ? ''
-               : ( '(?:' . preg_quote( $suffix, '#' ) . ')?' );
+       if ( $suffix == '' ) {
+               $encSuffix = '';
+       } else {
+               $encSuffix = '(?:' . preg_quote( $suffix, '#' ) . ')?';
+       }
+
        $matches = array();
        if ( preg_match( "#([^/\\\\]*?){$encSuffix}[/\\\\]*$#", $path, $matches ) ) {
                return $matches[1];
@@ -3148,18 +3333,6 @@ function wfRelativePath( $path, $from ) {
        return implode( DIRECTORY_SEPARATOR, $pieces );
 }
 
-/**
- * Do any deferred updates and clear the list
- *
- * @deprecated since 1.19
- * @see DeferredUpdates::doUpdate()
- * @param $commit string
- */
-function wfDoUpdates( $commit = '' ) {
-       wfDeprecated( __METHOD__, '1.19' );
-       DeferredUpdates::doUpdates( $commit );
-}
-
 /**
  * Convert an arbitrarily-long digit string from one numeric base
  * to another, optionally zero-padding to a minimum column width.
@@ -3175,7 +3348,9 @@ function wfDoUpdates( $commit = '' ) {
  * @param string $engine Either "gmp", "bcmath", or "php"
  * @return string|bool The output number as a string, or false on error
  */
-function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true, $engine = 'auto' ) {
+function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
+       $lowercase = true, $engine = 'auto'
+) {
        $input = (string)$input;
        if (
                $sourceBase < 2 ||
@@ -3185,7 +3360,10 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = t
                $sourceBase != (int)$sourceBase ||
                $destBase != (int)$destBase ||
                $pad != (int)$pad ||
-               !preg_match( "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i", $input )
+               !preg_match(
+                       "/^[" . substr( '0123456789abcdefghijklmnopqrstuvwxyz', 0, $sourceBase ) . "]+$/i",
+                       $input
+               )
        ) {
                return false;
        }
@@ -3261,19 +3439,6 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = t
        return str_pad( $result, $pad, '0', STR_PAD_LEFT );
 }
 
-/**
- * Create an object with a given name and an array of construct parameters
- *
- * @param $name String
- * @param array $p parameters
- * @return object
- * @deprecated since 1.18, warnings in 1.18, removal in 1.20
- */
-function wfCreateObject( $name, $p ) {
-       wfDeprecated( __FUNCTION__, '1.18' );
-       return MWFunction::newObj( $name, $p );
-}
-
 /**
  * @return bool
  */
@@ -3319,9 +3484,11 @@ function wfFixSessionID() {
        // We treat it as disabled if it doesn't have an entropy length of at least 32
        $entropyEnabled = wfCheckEntropy();
 
-       // If built-in entropy is not enabled or not sufficient override php's built in session id generation code
+       // If built-in entropy is not enabled or not sufficient override PHP's
+       // built in session id generation code
        if ( !$entropyEnabled ) {
-               wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, overriding session id generation using our cryptrand source.\n" );
+               wfDebug( __METHOD__ . ": PHP's built in entropy is disabled or not sufficient, " .
+                       "overriding session id generation using our cryptrand source.\n" );
                session_id( MWCryptRand::generateHex( 32 ) );
        }
 }
@@ -3346,7 +3513,6 @@ function wfResetSessionID() {
        wfRunHooks( 'ResetSessionID', array( $oldSessionId, $newSessionId ) );
 }
 
-
 /**
  * Initialise php session
  *
@@ -3627,9 +3793,7 @@ function wfBoolToStr( $value ) {
  * @return string
  */
 function wfGetNull() {
-       return wfIsWindows()
-               ? 'NUL'
-               : '/dev/null';
+       return wfIsWindows() ? 'NUL' : '/dev/null';
 }
 
 /**
@@ -3639,14 +3803,17 @@ function wfGetNull() {
  * in maintenance scripts, to avoid causing too much lag.  Of course, this is
  * a no-op if there are no slaves.
  *
- * @param $maxLag Integer (deprecated)
- * @param $wiki mixed Wiki identifier accepted by wfGetLB
- * @param $cluster string cluster name accepted by LBFactory
+ * @param int|bool $maxLag (deprecated)
+ * @param mixed $wiki Wiki identifier accepted by wfGetLB
+ * @param string|bool $cluster Cluster name accepted by LBFactory. Default: false.
  */
 function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
-       $lb = ( $cluster !== false )
-               ? wfGetLBFactory()->getExternalLB( $cluster )
-               : wfGetLB( $wiki );
+       if ( $cluster !== false ) {
+               $lb = wfGetLBFactory()->getExternalLB( $cluster );
+       } else {
+               $lb = wfGetLB( $wiki );
+       }
+
        // bug 27975 - Don't try to wait for slaves if there are none
        // Prevents permission error when getting master position
        if ( $lb->getServerCount() > 1 ) {
@@ -3660,21 +3827,6 @@ function wfWaitForSlaves( $maxLag = false, $wiki = false, $cluster = false ) {
        }
 }
 
-/**
- * Used to be used for outputting text in the installer/updater
- * @deprecated since 1.18, warnings in 1.18, remove in 1.20
- */
-function wfOut( $s ) {
-       wfDeprecated( __FUNCTION__, '1.18' );
-       global $wgCommandLineMode;
-       if ( $wgCommandLineMode ) {
-               echo $s;
-       } else {
-               echo htmlspecialchars( $s );
-       }
-       flush();
-}
-
 /**
  * Count down from $n to zero on the terminal, with a one-second pause
  * between showing each number. For use in command-line scripts.
@@ -3701,8 +3853,10 @@ function wfCountDown( $n ) {
  *              characters before hashing.
  * @return string
  * @codeCoverageIgnore
- * @deprecated since 1.20; Please use MWCryptRand for security purposes and wfRandomString for pseudo-random strings
- * @warning This method is NOT secure. Additionally it has many callers that use it for pseudo-random purposes.
+ * @deprecated since 1.20; Please use MWCryptRand for security purposes and
+ * wfRandomString for pseudo-random strings
+ * @warning This method is NOT secure. Additionally it has many callers that
+ * use it for pseudo-random purposes.
  */
 function wfGenerateToken( $salt = '' ) {
        wfDeprecated( __METHOD__, '1.20' );
index d260862..385663a 100644 (file)
@@ -655,8 +655,7 @@ class HTMLForm extends ContextSource {
                        . $this->getBody()
                        . $this->getHiddenFields()
                        . $this->getButtons()
-                       . $this->mFooter
-               ;
+                       . $this->mFooter;
 
                $html = $this->wrapForm( $html );
 
@@ -745,7 +744,7 @@ class HTMLForm extends ContextSource {
                        $attribs['class'] = array( 'mw-htmlform-submit' );
 
                        if ( $this->isVForm() ) {
-                               // mw-ui-block is necessary because the buttons aren't necessarily in an 
+                               // mw-ui-block is necessary because the buttons aren't necessarily in an
                                // immediate child div of the vform.
                                array_push( $attribs['class'], 'mw-ui-button', 'mw-ui-big', 'mw-ui-primary', 'mw-ui-block' );
                        }
@@ -1034,7 +1033,7 @@ class HTMLForm extends ContextSource {
                $subsectionHtml = '';
                $hasLabel = false;
 
-               switch( $displayFormat ) {
+               switch ( $displayFormat ) {
                        case 'table':
                                $getFieldHtmlMethod = 'getTableRow';
                                break;
diff --git a/includes/HashRing.php b/includes/HashRing.php
deleted file mode 100644 (file)
index 930f8c0..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-/**
- * Convenience class for weighted consistent hash rings.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Convenience class for weighted consistent hash rings
- *
- * @since 1.22
- */
-class HashRing {
-       /** @var Array (location => weight) */
-       protected $sourceMap = array();
-       /** @var Array (location => (start, end)) */
-       protected $ring = array();
-
-       const RING_SIZE = 268435456; // 2^28
-
-       /**
-        * @param array $map (location => weight)
-        */
-       public function __construct( array $map ) {
-               $map = array_filter( $map, function( $w ) { return $w > 0; } );
-               if ( !count( $map ) ) {
-                       throw new MWException( "Ring is empty or all weights are zero." );
-               }
-               $this->sourceMap = $map;
-               // Sort the locations based on the hash of their names
-               $hashes = array();
-               foreach ( $map as $location => $weight ) {
-                       $hashes[$location] = sha1( $location );
-               }
-               uksort( $map, function ( $a, $b ) use ( $hashes ) {
-                       return strcmp( $hashes[$a], $hashes[$b] );
-               } );
-               // Fit the map to weight-proportionate one with a space of size RING_SIZE
-               $sum = array_sum( $map );
-               $standardMap = array();
-               foreach ( $map as $location => $weight ) {
-                       $standardMap[$location] = (int)floor( $weight / $sum * self::RING_SIZE );
-               }
-               // Build a ring of RING_SIZE spots, with each location at a spot in location hash order
-               $index = 0;
-               foreach ( $standardMap as $location => $weight ) {
-                       // Location covers half-closed interval [$index,$index + $weight)
-                       $this->ring[$location] = array( $index, $index + $weight );
-                       $index += $weight;
-               }
-               // Make sure the last location covers what is left
-               end( $this->ring );
-               $this->ring[key( $this->ring )][1] = self::RING_SIZE;
-       }
-
-       /**
-        * Get the location of an item on the ring
-        *
-        * @param string $item
-        * @return string Location
-        */
-       public function getLocation( $item ) {
-               $locations = $this->getLocations( $item, 1 );
-               return $locations[0];
-       }
-
-       /**
-        * Get the location of an item on the ring, as well as the next clockwise locations
-        *
-        * @param string $item
-        * @param integer $limit Maximum number of locations to return
-        * @return array List of locations
-        */
-       public function getLocations( $item, $limit ) {
-               $locations = array();
-               $primaryLocation = null;
-               $spot = hexdec( substr( sha1( $item ), 0, 7 ) ); // first 28 bits
-               foreach ( $this->ring as $location => $range ) {
-                       if ( count( $locations ) >= $limit ) {
-                               break;
-                       }
-                       // The $primaryLocation is the location the item spot is in.
-                       // After that is reached, keep appending the next locations.
-                       if ( ( $range[0] <= $spot && $spot < $range[1] ) || $primaryLocation !== null ) {
-                               if ( $primaryLocation === null ) {
-                                       $primaryLocation = $location;
-                               }
-                               $locations[] = $location;
-                       }
-               }
-               // If more locations are requested, wrap-around and keep adding them
-               reset( $this->ring );
-               while ( count( $locations ) < $limit ) {
-                       list( $location, ) = each( $this->ring );
-                       if ( $location === $primaryLocation ) {
-                               break; // don't go in circles
-                       }
-                       $locations[] = $location;
-               }
-               return $locations;
-       }
-
-       /**
-        * Get the map of locations to weight (ignores 0-weight items)
-        *
-        * @return array
-        */
-       public function getLocationWeights() {
-               return $this->sourceMap;
-       }
-
-       /**
-        * Get a new hash ring with a location removed from the ring
-        *
-        * @param string $location
-        * @return HashRing|bool Returns false if no non-zero weighted spots are left
-        */
-       public function newWithoutLocation( $location ) {
-               $map = $this->sourceMap;
-               unset( $map[$location] );
-               if ( count( $map ) ) {
-                       return new self( $map );
-               }
-               return false;
-       }
-}
index 31aa0f8..9c50895 100644 (file)
@@ -290,7 +290,7 @@ class HistoryBlobStub {
  * of megabytes of data during the conversion downtime.
  *
  * Serialized HistoryBlobCurStub objects will be inserted into the text table
- * on conversion if $wgFastSchemaUpgrades is set to true.
+ * on conversion if $wgLegacySchemaConversion is set to true.
  */
 class HistoryBlobCurStub {
        var $mCurId;
index 396e360..db47d31 100644 (file)
@@ -199,6 +199,9 @@ class Hooks {
                                $retval = call_user_func_array( $callback, $hook_args );
                        } catch ( MWHookException $e ) {
                                $badhookmsg = $e->getMessage();
+                       } catch ( Exception $e ) {
+                               restore_error_handler();
+                               throw $e;
                        }
                        restore_error_handler();
                        wfProfileOut( $func );
index 932f753..0eb6474 100644 (file)
@@ -449,8 +449,8 @@ class Html {
                        // numbers to be entered in 'type="number"' fields, allow
                        // the special case 'step="any"'.
 
-                       if ( in_array( $key, array( 'max', 'min', 'pattern', 'required' ) ) ||
-                                $key === 'step' && $value !== 'any' ) {
+                       if ( in_array( $key, array( 'max', 'min', 'pattern', 'required' ) )
+                               || $key === 'step' && $value !== 'any' ) {
                                continue;
                        }
 
@@ -664,7 +664,7 @@ class Html {
        }
 
        /**
-        * Convenience function to produce an "<input>" element.
+        * Convenience function to produce a <textarea> element.
         *
         * This supports leaving out the cols= and rows= which Xml requires and are
         * required by HTML4/XHTML but not required by HTML5.
index 248a76f..c06fbbc 100644 (file)
@@ -306,14 +306,10 @@ class HtmlFormatter {
                } elseif ( strpos( $selector, '#' ) === 0 ) {
                        $type = 'ID';
                        $rawName = substr( $selector, 1 );
-               } elseif ( strpos( $selector, '.' ) !== 0 &&
-                       strpos( $selector, '.' ) !== false )
-               {
+               } elseif ( strpos( $selector, '.' ) !== 0 && strpos( $selector, '.' ) !== false ) {
                        $type = 'TAG_CLASS';
                        $rawName = $selector;
-               } elseif ( strpos( $selector, '[' ) === false
-                       && strpos( $selector, ']' ) === false )
-               {
+               } elseif ( strpos( $selector, '[' ) === false && strpos( $selector, ']' ) === false ) {
                        $type = 'TAG';
                        $rawName = $selector;
                } else {
index 78c2ac7..da08aa2 100644 (file)
@@ -842,8 +842,8 @@ class PhpHttpRequest extends MWHttpRequest {
                        $this->postData = wfArrayToCgi( $this->postData );
                }
 
-               if ( $this->parsedUrl['scheme'] != 'http' &&
-                        $this->parsedUrl['scheme'] != 'https' ) {
+               if ( $this->parsedUrl['scheme'] != 'http'
+                       && $this->parsedUrl['scheme'] != 'https' ) {
                        $this->status->fatal( 'http-invalid-scheme', $this->parsedUrl['scheme'] );
                }
 
diff --git a/includes/IP.php b/includes/IP.php
deleted file mode 100644 (file)
index 73834a5..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-<?php
-/**
- * Functions and constants to play with IP addresses and ranges
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Antoine Musso "<hashar at free dot fr>", Aaron Schulz
- */
-
-// Some regex definition to "play" with IP address and IP address blocks
-
-// An IPv4 address is made of 4 bytes from x00 to xFF which is d0 to d255
-define( 'RE_IP_BYTE', '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])' );
-define( 'RE_IP_ADD', RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE );
-// An IPv4 block is an IP address and a prefix (d1 to d32)
-define( 'RE_IP_PREFIX', '(3[0-2]|[12]?\d)' );
-define( 'RE_IP_BLOCK', RE_IP_ADD . '\/' . RE_IP_PREFIX );
-
-// An IPv6 address is made up of 8 words (each x0000 to xFFFF).
-// However, the "::" abbreviation can be used on consecutive x0000 words.
-define( 'RE_IPV6_WORD', '([0-9A-Fa-f]{1,4})' );
-define( 'RE_IPV6_PREFIX', '(12[0-8]|1[01][0-9]|[1-9]?\d)' );
-define( 'RE_IPV6_ADD',
-       '(?:' . // starts with "::" (including "::")
-               ':(?::|(?::' . RE_IPV6_WORD . '){1,7})' .
-       '|' . // ends with "::" (except "::")
-               RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){0,6}::' .
-       '|' . // contains one "::" in the middle (the ^ makes the test fail if none found)
-               RE_IPV6_WORD . '(?::((?(-1)|:))?' . RE_IPV6_WORD . '){1,6}(?(-2)|^)' .
-       '|' . // contains no "::"
-               RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){7}' .
-       ')'
-);
-// An IPv6 block is an IP address and a prefix (d1 to d128)
-define( 'RE_IPV6_BLOCK', RE_IPV6_ADD . '\/' . RE_IPV6_PREFIX );
-// For IPv6 canonicalization (NOT for strict validation; these are quite lax!)
-define( 'RE_IPV6_GAP', ':(?:0+:)*(?::(?:0+:)*)?' );
-define( 'RE_IPV6_V4_PREFIX', '0*' . RE_IPV6_GAP . '(?:ffff:)?' );
-
-// This might be useful for regexps used elsewhere, matches any IPv6 or IPv6 address or network
-define( 'IP_ADDRESS_STRING',
-       '(?:' .
-               RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?' . // IPv4
-       '|' .
-               RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?' . // IPv6
-       ')'
-);
-
-/**
- * A collection of public static functions to play with IP address
- * and IP blocks.
- */
-class IP {
-       /**
-        * Determine if a string is as valid IP address or network (CIDR prefix).
-        * SIIT IPv4-translated addresses are rejected.
-        * Note: canonicalize() tries to convert translated addresses to IPv4.
-        *
-        * @param string $ip possible IP address
-        * @return Boolean
-        */
-       public static function isIPAddress( $ip ) {
-               return (bool)preg_match( '/^' . IP_ADDRESS_STRING . '$/', $ip );
-       }
-
-       /**
-        * Given a string, determine if it as valid IP in IPv6 only.
-        * Note: Unlike isValid(), this looks for networks too.
-        *
-        * @param string $ip possible IP address
-        * @return Boolean
-        */
-       public static function isIPv6( $ip ) {
-               return (bool)preg_match( '/^' . RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?$/', $ip );
-       }
-
-       /**
-        * Given a string, determine if it as valid IP in IPv4 only.
-        * Note: Unlike isValid(), this looks for networks too.
-        *
-        * @param string $ip possible IP address
-        * @return Boolean
-        */
-       public static function isIPv4( $ip ) {
-               return (bool)preg_match( '/^' . RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?$/', $ip );
-       }
-
-       /**
-        * Validate an IP address. Ranges are NOT considered valid.
-        * SIIT IPv4-translated addresses are rejected.
-        * Note: canonicalize() tries to convert translated addresses to IPv4.
-        *
-        * @param $ip String
-        * @return Boolean: True if it is valid.
-        */
-       public static function isValid( $ip ) {
-               return ( preg_match( '/^' . RE_IP_ADD . '$/', $ip )
-                       || preg_match( '/^' . RE_IPV6_ADD . '$/', $ip ) );
-       }
-
-       /**
-        * Validate an IP Block (valid address WITH a valid prefix).
-        * SIIT IPv4-translated addresses are rejected.
-        * Note: canonicalize() tries to convert translated addresses to IPv4.
-        *
-        * @param $ipblock String
-        * @return Boolean: True if it is valid.
-        */
-       public static function isValidBlock( $ipblock ) {
-               return ( preg_match( '/^' . RE_IPV6_BLOCK . '$/', $ipblock )
-                       || preg_match( '/^' . RE_IP_BLOCK . '$/', $ipblock ) );
-       }
-
-       /**
-        * Convert an IP into a verbose, uppercase, normalized form.
-        * IPv6 addresses in octet notation are expanded to 8 words.
-        * IPv4 addresses are just trimmed.
-        *
-        * @param string $ip IP address in quad or octet form (CIDR or not).
-        * @return String
-        */
-       public static function sanitizeIP( $ip ) {
-               $ip = trim( $ip );
-               if ( $ip === '' ) {
-                       return null;
-               }
-               if ( self::isIPv4( $ip ) || !self::isIPv6( $ip ) ) {
-                       return $ip; // nothing else to do for IPv4 addresses or invalid ones
-               }
-               // Remove any whitespaces, convert to upper case
-               $ip = strtoupper( $ip );
-               // Expand zero abbreviations
-               $abbrevPos = strpos( $ip, '::' );
-               if ( $abbrevPos !== false ) {
-                       // We know this is valid IPv6. Find the last index of the
-                       // address before any CIDR number (e.g. "a:b:c::/24").
-                       $CIDRStart = strpos( $ip, "/" );
-                       $addressEnd = ( $CIDRStart !== false )
-                               ? $CIDRStart - 1
-                               : strlen( $ip ) - 1;
-                       // If the '::' is at the beginning...
-                       if ( $abbrevPos == 0 ) {
-                               $repeat = '0:';
-                               $extra = ( $ip == '::' ) ? '0' : ''; // for the address '::'
-                               $pad = 9; // 7+2 (due to '::')
-                       // If the '::' is at the end...
-                       } elseif ( $abbrevPos == ( $addressEnd - 1 ) ) {
-                               $repeat = ':0';
-                               $extra = '';
-                               $pad = 9; // 7+2 (due to '::')
-                       // If the '::' is in the middle...
-                       } else {
-                               $repeat = ':0';
-                               $extra = ':';
-                               $pad = 8; // 6+2 (due to '::')
-                       }
-                       $ip = str_replace( '::',
-                               str_repeat( $repeat, $pad - substr_count( $ip, ':' ) ) . $extra,
-                               $ip
-                       );
-               }
-               // Remove leading zeros from each bloc as needed
-               $ip = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip );
-               return $ip;
-       }
-
-       /**
-        * Prettify an IP for display to end users.
-        * This will make it more compact and lower-case.
-        *
-        * @param $ip string
-        * @return string
-        */
-       public static function prettifyIP( $ip ) {
-               $ip = self::sanitizeIP( $ip ); // normalize (removes '::')
-               if ( self::isIPv6( $ip ) ) {
-                       // Split IP into an address and a CIDR
-                       if ( strpos( $ip, '/' ) !== false ) {
-                               list( $ip, $cidr ) = explode( '/', $ip, 2 );
-                       } else {
-                               list( $ip, $cidr ) = array( $ip, '' );
-                       }
-                       // Get the largest slice of words with multiple zeros
-                       $offset = 0;
-                       $longest = $longestPos = false;
-                       while ( preg_match(
-                               '!(?:^|:)0(?::0)+(?:$|:)!', $ip, $m, PREG_OFFSET_CAPTURE, $offset
-                       ) ) {
-                               list( $match, $pos ) = $m[0]; // full match
-                               if ( strlen( $match ) > strlen( $longest ) ) {
-                                       $longest = $match;
-                                       $longestPos = $pos;
-                               }
-                               $offset = ( $pos + strlen( $match ) ); // advance
-                       }
-                       if ( $longest !== false ) {
-                               // Replace this portion of the string with the '::' abbreviation
-                               $ip = substr_replace( $ip, '::', $longestPos, strlen( $longest ) );
-                       }
-                       // Add any CIDR back on
-                       if ( $cidr !== '' ) {
-                               $ip = "{$ip}/{$cidr}";
-                       }
-                       // Convert to lower case to make it more readable
-                       $ip = strtolower( $ip );
-               }
-               return $ip;
-       }
-
-       /**
-        * Given a host/port string, like one might find in the host part of a URL
-        * per RFC 2732, split the hostname part and the port part and return an
-        * array with an element for each. If there is no port part, the array will
-        * have false in place of the port. If the string was invalid in some way,
-        * false is returned.
-        *
-        * This was easy with IPv4 and was generally done in an ad-hoc way, but
-        * with IPv6 it's somewhat more complicated due to the need to parse the
-        * square brackets and colons.
-        *
-        * A bare IPv6 address is accepted despite the lack of square brackets.
-        *
-        * @param string $both The string with the host and port
-        * @return array
-        */
-       public static function splitHostAndPort( $both ) {
-               if ( substr( $both, 0, 1 ) === '[' ) {
-                       if ( preg_match( '/^\[(' . RE_IPV6_ADD . ')\](?::(?P<port>\d+))?$/', $both, $m ) ) {
-                               if ( isset( $m['port'] ) ) {
-                                       return array( $m[1], intval( $m['port'] ) );
-                               } else {
-                                       return array( $m[1], false );
-                               }
-                       } else {
-                               // Square bracket found but no IPv6
-                               return false;
-                       }
-               }
-               $numColons = substr_count( $both, ':' );
-               if ( $numColons >= 2 ) {
-                       // Is it a bare IPv6 address?
-                       if ( preg_match( '/^' . RE_IPV6_ADD . '$/', $both ) ) {
-                               return array( $both, false );
-                       } else {
-                               // Not valid IPv6, but too many colons for anything else
-                               return false;
-                       }
-               }
-               if ( $numColons >= 1 ) {
-                       // Host:port?
-                       $bits = explode( ':', $both );
-                       if ( preg_match( '/^\d+/', $bits[1] ) ) {
-                               return array( $bits[0], intval( $bits[1] ) );
-                       } else {
-                               // Not a valid port
-                               return false;
-                       }
-               }
-               // Plain hostname
-               return array( $both, false );
-       }
-
-       /**
-        * Given a host name and a port, combine them into host/port string like
-        * you might find in a URL. If the host contains a colon, wrap it in square
-        * brackets like in RFC 2732. If the port matches the default port, omit
-        * the port specification
-        *
-        * @param $host string
-        * @param $port int
-        * @param $defaultPort bool|int
-        * @return string
-        */
-       public static function combineHostAndPort( $host, $port, $defaultPort = false ) {
-               if ( strpos( $host, ':' ) !== false ) {
-                       $host = "[$host]";
-               }
-               if ( $defaultPort !== false && $port == $defaultPort ) {
-                       return $host;
-               } else {
-                       return "$host:$port";
-               }
-       }
-
-       /**
-        * Given an unsigned integer, returns an IPv6 address in octet notation
-        *
-        * @param $ip_int String: IP address.
-        * @return String
-        */
-       public static function toOctet( $ip_int ) {
-               return self::hexToOctet( wfBaseConvert( $ip_int, 10, 16, 32, false ) );
-       }
-
-       /**
-        * Convert an IPv4 or IPv6 hexadecimal representation back to readable format
-        *
-        * @param string $hex number, with "v6-" prefix if it is IPv6
-        * @return String: quad-dotted (IPv4) or octet notation (IPv6)
-        */
-       public static function formatHex( $hex ) {
-               if ( substr( $hex, 0, 3 ) == 'v6-' ) { // IPv6
-                       return self::hexToOctet( substr( $hex, 3 ) );
-               } else { // IPv4
-                       return self::hexToQuad( $hex );
-               }
-       }
-
-       /**
-        * Converts a hexadecimal number to an IPv6 address in octet notation
-        *
-        * @param $ip_hex String: pure hex (no v6- prefix)
-        * @return String (of format a:b:c:d:e:f:g:h)
-        */
-       public static function hexToOctet( $ip_hex ) {
-               // Pad hex to 32 chars (128 bits)
-               $ip_hex = str_pad( strtoupper( $ip_hex ), 32, '0', STR_PAD_LEFT );
-               // Separate into 8 words
-               $ip_oct = substr( $ip_hex, 0, 4 );
-               for ( $n = 1; $n < 8; $n++ ) {
-                       $ip_oct .= ':' . substr( $ip_hex, 4 * $n, 4 );
-               }
-               // NO leading zeroes
-               $ip_oct = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip_oct );
-               return $ip_oct;
-       }
-
-       /**
-        * Converts a hexadecimal number to an IPv4 address in quad-dotted notation
-        *
-        * @param $ip_hex String: pure hex
-        * @return String (of format a.b.c.d)
-        */
-       public static function hexToQuad( $ip_hex ) {
-               // Pad hex to 8 chars (32 bits)
-               $ip_hex = str_pad( strtoupper( $ip_hex ), 8, '0', STR_PAD_LEFT );
-               // Separate into four quads
-               $s = '';
-               for ( $i = 0; $i < 4; $i++ ) {
-                       if ( $s !== '' ) {
-                               $s .= '.';
-                       }
-                       $s .= base_convert( substr( $ip_hex, $i * 2, 2 ), 16, 10 );
-               }
-               return $s;
-       }
-
-       /**
-        * Determine if an IP address really is an IP address, and if it is public,
-        * i.e. not RFC 1918 or similar
-        * Comes from ProxyTools.php
-        *
-        * @param $ip String
-        * @return Boolean
-        */
-       public static function isPublic( $ip ) {
-               if ( self::isIPv6( $ip ) ) {
-                       return self::isPublic6( $ip );
-               }
-               $n = self::toUnsigned( $ip );
-               if ( !$n ) {
-                       return false;
-               }
-
-               // ip2long accepts incomplete addresses, as well as some addresses
-               // followed by garbage characters. Check that it's really valid.
-               if ( $ip != long2ip( $n ) ) {
-                       return false;
-               }
-
-               static $privateRanges = false;
-               if ( !$privateRanges ) {
-                       $privateRanges = array(
-                               array( '10.0.0.0', '10.255.255.255' ), # RFC 1918 (private)
-                               array( '172.16.0.0', '172.31.255.255' ), # RFC 1918 (private)
-                               array( '192.168.0.0', '192.168.255.255' ), # RFC 1918 (private)
-                               array( '0.0.0.0', '0.255.255.255' ), # this network
-                               array( '127.0.0.0', '127.255.255.255' ), # loopback
-                       );
-               }
-
-               foreach ( $privateRanges as $r ) {
-                       $start = self::toUnsigned( $r[0] );
-                       $end = self::toUnsigned( $r[1] );
-                       if ( $n >= $start && $n <= $end ) {
-                               return false;
-                       }
-               }
-               return true;
-       }
-
-       /**
-        * Determine if an IPv6 address really is an IP address, and if it is public,
-        * i.e. not RFC 4193 or similar
-        *
-        * @param $ip String
-        * @return Boolean
-        */
-       private static function isPublic6( $ip ) {
-               static $privateRanges = false;
-               if ( !$privateRanges ) {
-                       $privateRanges = array(
-                               array( 'fc00::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ), # RFC 4193 (local)
-                               array( '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1' ), # loopback
-                       );
-               }
-               $n = self::toHex( $ip );
-               foreach ( $privateRanges as $r ) {
-                       $start = self::toHex( $r[0] );
-                       $end = self::toHex( $r[1] );
-                       if ( $n >= $start && $n <= $end ) {
-                               return false;
-                       }
-               }
-               return true;
-       }
-
-       /**
-        * Return a zero-padded upper case hexadecimal representation of an IP address.
-        *
-        * Hexadecimal addresses are used because they can easily be extended to
-        * IPv6 support. To separate the ranges, the return value from this
-        * function for an IPv6 address will be prefixed with "v6-", a non-
-        * hexadecimal string which sorts after the IPv4 addresses.
-        *
-        * @param string $ip quad dotted/octet IP address.
-        * @return String
-        */
-       public static function toHex( $ip ) {
-               if ( self::isIPv6( $ip ) ) {
-                       $n = 'v6-' . self::IPv6ToRawHex( $ip );
-               } else {
-                       $n = self::toUnsigned( $ip );
-                       if ( $n !== false ) {
-                               $n = wfBaseConvert( $n, 10, 16, 8, false );
-                       }
-               }
-               return $n;
-       }
-
-       /**
-        * Given an IPv6 address in octet notation, returns a pure hex string.
-        *
-        * @param string $ip octet ipv6 IP address.
-        * @return String: pure hex (uppercase)
-        */
-       private static function IPv6ToRawHex( $ip ) {
-               $ip = self::sanitizeIP( $ip );
-               if ( !$ip ) {
-                       return null;
-               }
-               $r_ip = '';
-               foreach ( explode( ':', $ip ) as $v ) {
-                       $r_ip .= str_pad( $v, 4, 0, STR_PAD_LEFT );
-               }
-               return $r_ip;
-       }
-
-       /**
-        * Given an IP address in dotted-quad/octet notation, returns an unsigned integer.
-        * Like ip2long() except that it actually works and has a consistent error return value.
-        * Comes from ProxyTools.php
-        *
-        * @param string $ip quad dotted IP address.
-        * @return Mixed: string/int/false
-        */
-       public static function toUnsigned( $ip ) {
-               if ( self::isIPv6( $ip ) ) {
-                       $n = self::toUnsigned6( $ip );
-               } else {
-                       $n = ip2long( $ip );
-                       if ( $n < 0 ) {
-                               $n += pow( 2, 32 );
-                               # On 32-bit platforms (and on Windows), 2^32 does not fit into an int,
-                               # so $n becomes a float. We convert it to string instead.
-                               if ( is_float( $n ) ) {
-                                       $n = (string)$n;
-                               }
-                       }
-               }
-               return $n;
-       }
-
-       /**
-        * @param $ip
-        * @return String
-        */
-       private static function toUnsigned6( $ip ) {
-               return wfBaseConvert( self::IPv6ToRawHex( $ip ), 16, 10 );
-       }
-
-       /**
-        * Convert a network specification in CIDR notation
-        * to an integer network and a number of bits
-        *
-        * @param string $range IP with CIDR prefix
-        * @return array(int or string, int)
-        */
-       public static function parseCIDR( $range ) {
-               if ( self::isIPv6( $range ) ) {
-                       return self::parseCIDR6( $range );
-               }
-               $parts = explode( '/', $range, 2 );
-               if ( count( $parts ) != 2 ) {
-                       return array( false, false );
-               }
-               list( $network, $bits ) = $parts;
-               $network = ip2long( $network );
-               if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 32 ) {
-                       if ( $bits == 0 ) {
-                               $network = 0;
-                       } else {
-                               $network &= ~( ( 1 << ( 32 - $bits ) ) - 1 );
-                       }
-                       # Convert to unsigned
-                       if ( $network < 0 ) {
-                               $network += pow( 2, 32 );
-                       }
-               } else {
-                       $network = false;
-                       $bits = false;
-               }
-               return array( $network, $bits );
-       }
-
-       /**
-        * Given a string range in a number of formats,
-        * return the start and end of the range in hexadecimal.
-        *
-        * Formats are:
-        *     1.2.3.4/24          CIDR
-        *     1.2.3.4 - 1.2.3.5   Explicit range
-        *     1.2.3.4             Single IP
-        *
-        *     2001:0db8:85a3::7344/96                                   CIDR
-        *     2001:0db8:85a3::7344 - 2001:0db8:85a3::7344   Explicit range
-        *     2001:0db8:85a3::7344                                      Single IP
-        * @param string $range IP range
-        * @return array(string, string)
-        */
-       public static function parseRange( $range ) {
-               // CIDR notation
-               if ( strpos( $range, '/' ) !== false ) {
-                       if ( self::isIPv6( $range ) ) {
-                               return self::parseRange6( $range );
-                       }
-                       list( $network, $bits ) = self::parseCIDR( $range );
-                       if ( $network === false ) {
-                               $start = $end = false;
-                       } else {
-                               $start = sprintf( '%08X', $network );
-                               $end = sprintf( '%08X', $network + pow( 2, ( 32 - $bits ) ) - 1 );
-                       }
-               // Explicit range
-               } elseif ( strpos( $range, '-' ) !== false ) {
-                       list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
-                       if ( self::isIPv6( $start ) && self::isIPv6( $end ) ) {
-                               return self::parseRange6( $range );
-                       }
-                       if ( self::isIPv4( $start ) && self::isIPv4( $end ) ) {
-                               $start = self::toUnsigned( $start );
-                               $end = self::toUnsigned( $end );
-                               if ( $start > $end ) {
-                                       $start = $end = false;
-                               } else {
-                                       $start = sprintf( '%08X', $start );
-                                       $end = sprintf( '%08X', $end );
-                               }
-                       } else {
-                               $start = $end = false;
-                       }
-               } else {
-                       # Single IP
-                       $start = $end = self::toHex( $range );
-               }
-               if ( $start === false || $end === false ) {
-                       return array( false, false );
-               } else {
-                       return array( $start, $end );
-               }
-       }
-
-       /**
-        * Convert a network specification in IPv6 CIDR notation to an
-        * integer network and a number of bits
-        *
-        * @param $range
-        *
-        * @return array(string, int)
-        */
-       private static function parseCIDR6( $range ) {
-               # Explode into <expanded IP,range>
-               $parts = explode( '/', IP::sanitizeIP( $range ), 2 );
-               if ( count( $parts ) != 2 ) {
-                       return array( false, false );
-               }
-               list( $network, $bits ) = $parts;
-               $network = self::IPv6ToRawHex( $network );
-               if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 128 ) {
-                       if ( $bits == 0 ) {
-                               $network = "0";
-                       } else {
-                               # Native 32 bit functions WONT work here!!!
-                               # Convert to a padded binary number
-                               $network = wfBaseConvert( $network, 16, 2, 128 );
-                               # Truncate the last (128-$bits) bits and replace them with zeros
-                               $network = str_pad( substr( $network, 0, $bits ), 128, 0, STR_PAD_RIGHT );
-                               # Convert back to an integer
-                               $network = wfBaseConvert( $network, 2, 10 );
-                       }
-               } else {
-                       $network = false;
-                       $bits = false;
-               }
-               return array( $network, (int)$bits );
-       }
-
-       /**
-        * Given a string range in a number of formats, return the
-        * start and end of the range in hexadecimal. For IPv6.
-        *
-        * Formats are:
-        *     2001:0db8:85a3::7344/96                                   CIDR
-        *     2001:0db8:85a3::7344 - 2001:0db8:85a3::7344   Explicit range
-        *     2001:0db8:85a3::7344/96                                   Single IP
-        *
-        * @param $range
-        *
-        * @return array(string, string)
-        */
-       private static function parseRange6( $range ) {
-               # Expand any IPv6 IP
-               $range = IP::sanitizeIP( $range );
-               // CIDR notation...
-               if ( strpos( $range, '/' ) !== false ) {
-                       list( $network, $bits ) = self::parseCIDR6( $range );
-                       if ( $network === false ) {
-                               $start = $end = false;
-                       } else {
-                               $start = wfBaseConvert( $network, 10, 16, 32, false );
-                               # Turn network to binary (again)
-                               $end = wfBaseConvert( $network, 10, 2, 128 );
-                               # Truncate the last (128-$bits) bits and replace them with ones
-                               $end = str_pad( substr( $end, 0, $bits ), 128, 1, STR_PAD_RIGHT );
-                               # Convert to hex
-                               $end = wfBaseConvert( $end, 2, 16, 32, false );
-                               # see toHex() comment
-                               $start = "v6-$start";
-                               $end = "v6-$end";
-                       }
-               // Explicit range notation...
-               } elseif ( strpos( $range, '-' ) !== false ) {
-                       list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
-                       $start = self::toUnsigned6( $start );
-                       $end = self::toUnsigned6( $end );
-                       if ( $start > $end ) {
-                               $start = $end = false;
-                       } else {
-                               $start = wfBaseConvert( $start, 10, 16, 32, false );
-                               $end = wfBaseConvert( $end, 10, 16, 32, false );
-                       }
-                       # see toHex() comment
-                       $start = "v6-$start";
-                       $end = "v6-$end";
-               } else {
-                       # Single IP
-                       $start = $end = self::toHex( $range );
-               }
-               if ( $start === false || $end === false ) {
-                       return array( false, false );
-               } else {
-                       return array( $start, $end );
-               }
-       }
-
-       /**
-        * Determine if a given IPv4/IPv6 address is in a given CIDR network
-        *
-        * @param string $addr the address to check against the given range.
-        * @param string $range the range to check the given address against.
-        * @return Boolean: whether or not the given address is in the given range.
-        */
-       public static function isInRange( $addr, $range ) {
-               $hexIP = self::toHex( $addr );
-               list( $start, $end ) = self::parseRange( $range );
-               return ( strcmp( $hexIP, $start ) >= 0 &&
-                       strcmp( $hexIP, $end ) <= 0 );
-       }
-
-       /**
-        * Convert some unusual representations of IPv4 addresses to their
-        * canonical dotted quad representation.
-        *
-        * This currently only checks a few IPV4-to-IPv6 related cases.  More
-        * unusual representations may be added later.
-        *
-        * @param string $addr something that might be an IP address
-        * @return String: valid dotted quad IPv4 address or null
-        */
-       public static function canonicalize( $addr ) {
-               // remove zone info (bug 35738)
-               $addr = preg_replace( '/\%.*/', '', $addr );
-
-               if ( self::isValid( $addr ) ) {
-                       return $addr;
-               }
-               // Turn mapped addresses from ::ce:ffff:1.2.3.4 to 1.2.3.4
-               if ( strpos( $addr, ':' ) !== false && strpos( $addr, '.' ) !== false ) {
-                       $addr = substr( $addr, strrpos( $addr, ':' ) + 1 );
-                       if ( self::isIPv4( $addr ) ) {
-                               return $addr;
-                       }
-               }
-               // IPv6 loopback address
-               $m = array();
-               if ( preg_match( '/^0*' . RE_IPV6_GAP . '1$/', $addr, $m ) ) {
-                       return '127.0.0.1';
-               }
-               // IPv4-mapped and IPv4-compatible IPv6 addresses
-               if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . '(' . RE_IP_ADD . ')$/i', $addr, $m ) ) {
-                       return $m[1];
-               }
-               if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . RE_IPV6_WORD .
-                       ':' . RE_IPV6_WORD . '$/i', $addr, $m ) )
-               {
-                       return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
-               }
-
-               return null; // give up
-       }
-
-       /**
-        * Gets rid of unneeded numbers in quad-dotted/octet IP strings
-        * For example, 127.111.113.151/24 -> 127.111.113.0/24
-        * @param string $range IP address to normalize
-        * @return string
-        */
-       public static function sanitizeRange( $range ) {
-               list( /*...*/, $bits ) = self::parseCIDR( $range );
-               list( $start, /*...*/ ) = self::parseRange( $range );
-               $start = self::formatHex( $start );
-               if ( $bits === false ) {
-                       return $start; // wasn't actually a range
-               }
-               return "$start/$bits";
-       }
-}
index 7ea06b0..b2a53cd 100644 (file)
@@ -128,7 +128,7 @@ class ImagePage extends Article {
                                $out->setPageTitle( $this->getTitle()->getPrefixedText() );
                                $out->addHTML( $this->viewRedirect( Title::makeTitle( NS_FILE, $this->mPage->getFile()->getName() ),
                                        /* $appendSubtitle */ true, /* $forceKnown */ true ) );
-                               $this->mPage->doViewUpdates( $this->getContext()->getUser() );
+                               $this->mPage->doViewUpdates( $this->getContext()->getUser(), $this->getOldID() );
                                return;
                        }
                }
@@ -165,7 +165,7 @@ class ImagePage extends Article {
                        # Just need to set the right headers
                        $out->setArticleFlag( true );
                        $out->setPageTitle( $this->getTitle()->getPrefixedText() );
-                       $this->mPage->doViewUpdates( $this->getContext()->getUser() );
+                       $this->mPage->doViewUpdates( $this->getContext()->getUser(), $this->getOldID() );
                }
 
                # Show shared description, if needed
@@ -350,23 +350,42 @@ class ImagePage extends Article {
                                        $linktext = wfMessage( 'show-big-image' )->escaped();
                                        if ( $this->displayImg->getRepo()->canTransformVia404() ) {
                                                $thumbSizes = $wgImageLimits;
+                                               // Also include the full sized resolution in the list, so
+                                               // that users know they can get it. This will link to the
+                                               // original file asset if mustRender() === false. In the case
+                                               // that we mustRender, some users have indicated that they would
+                                               // find it useful to have the full size image in the rendered
+                                               // image format.
+                                               $thumbSizes[] = array( $width_orig, $height_orig );
                                        } else {
                                                # Creating thumb links triggers thumbnail generation.
                                                # Just generate the thumb for the current users prefs.
                                                $thumbSizes = array( $this->getImageLimitsFromOption( $user, 'thumbsize' ) );
+                                               if ( !$this->displayImg->mustRender() ) {
+                                                       // We can safely include a link to the "full-size" preview,
+                                                       // without actually rendering.
+                                                       $thumbSizes[] = array( $width_orig, $height_orig );
+                                               }
                                        }
                                        # Generate thumbnails or thumbnail links as needed...
                                        $otherSizes = array();
                                        foreach ( $thumbSizes as $size ) {
-                                               if ( $size[0] < $width_orig && $size[1] < $height_orig
-                                                       && $size[0] != $width && $size[1] != $height )
-                                               {
+                                               // We include a thumbnail size in the list, if it is
+                                               // less than or equal to the original size of the image
+                                               // asset ($width_orig/$height_orig). We also exclude
+                                               // the current thumbnail's size ($width/$height)
+                                               // since that is added to the message separately, so
+                                               // it can be denoted as the current size being shown.
+                                               if ( $size[0] <= $width_orig && $size[1] <= $height_orig
+                                                       && $size[0] != $width && $size[1] != $height
+                                               ) {
                                                        $sizeLink = $this->makeSizeLink( $params, $size[0], $size[1] );
                                                        if ( $sizeLink ) {
                                                                $otherSizes[] = $sizeLink;
                                                        }
                                                }
                                        }
+                                       $otherSizes = array_unique( $otherSizes );
                                        $msgsmall = '';
                                        $sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
                                        if ( $sizeLinkBigImagePreview ) {
@@ -396,6 +415,7 @@ class ImagePage extends Article {
                                $params['width'] = $width;
                                $params['height'] = $height;
                                $thumbnail = $this->displayImg->transform( $params );
+                               Linker::processResponsiveImages( $this->displayImg, $thumbnail, $params );
 
                                $anchorclose = Html::rawElement( 'div', array( 'class' => 'mw-filepage-resolutioninfo' ), $msgsmall );
 
@@ -600,7 +620,7 @@ EOT
                $this->loadFile();
 
                $descUrl = $this->mPage->getFile()->getDescriptionUrl();
-               $descText = $this->mPage->getFile()->getDescriptionText();
+               $descText = $this->mPage->getFile()->getDescriptionText( $this->getContext()->getLanguage() );
 
                /* Add canonical to head if there is no local page for this shared file */
                if ( $descUrl && $this->mPage->getID() == 0 ) {
@@ -1183,8 +1203,8 @@ class ImageHistoryList extends ContextSource {
                $lang = $this->getLanguage();
                $user = $this->getUser();
                if ( $file->allowInlineDisplay() && $file->userCan( File::DELETED_FILE, $user )
-                       && !$file->isDeleted( File::DELETED_FILE ) )
-               {
+                       && !$file->isDeleted( File::DELETED_FILE )
+               {
                        $params = array(
                                'width' => '120',
                                'height' => '120',
index 64431f0..dd5e2d7 100644 (file)
@@ -48,7 +48,7 @@ class MWInit {
         * @return bool
         */
        static function isHipHop() {
-               return defined( 'HPHP_VERSION' );
+               return wfIsHHVM();
        }
 
        /**
index d552c69..48d5cd8 100644 (file)
@@ -84,16 +84,28 @@ class LinkFilter {
         *
         * Asterisks in any other location are considered invalid.
         *
-        * @param string $filterEntry domainparts
-        * @param $prot        String: protocol
+        * This function does the same as wfMakeUrlIndexes(), except it also takes care
+        * of adding wildcards
+        *
+        * @param String $filterEntry domainparts
+        * @param String $protocol protocol (default http://)
         * @return Array to be passed to DatabaseBase::buildLike() or false on error
         */
-       public static function makeLikeArray( $filterEntry, $prot = 'http://' ) {
+       public static function makeLikeArray( $filterEntry, $protocol = 'http://' ) {
                $db = wfGetDB( DB_MASTER );
-               if ( substr( $filterEntry, 0, 2 ) == '*.' ) {
+
+               $target = $protocol . $filterEntry;
+               $bits = wfParseUrl( $target );
+
+               if ( $bits == false ) {
+                       // Unknown protocol?
+                       return false;
+               }
+
+               if ( substr( $bits['host'], 0, 2 ) == '*.' ) {
                        $subdomains = true;
-                       $filterEntry = substr( $filterEntry, 2 );
-                       if ( $filterEntry == '' ) {
+                       $bits['host'] = substr( $bits['host'], 2 );
+                       if ( $bits['host'] == '' ) {
                                // We don't want to make a clause that will match everything,
                                // that could be dangerous
                                return false;
@@ -101,52 +113,63 @@ class LinkFilter {
                } else {
                        $subdomains = false;
                }
-               // No stray asterisks, that could cause confusion
-               // It's not simple or efficient to handle it properly so we don't
-               // handle it at all.
-               if ( strpos( $filterEntry, '*' ) !== false ) {
-                       return false;
-               }
-               $slash = strpos( $filterEntry, '/' );
-               if ( $slash !== false ) {
-                       $path = substr( $filterEntry, $slash );
-                       $host = substr( $filterEntry, 0, $slash );
-               } else {
-                       $path = '/';
-                       $host = $filterEntry;
-               }
+
                // Reverse the labels in the hostname, convert to lower case
                // For emails reverse domainpart only
-               if ( $prot == 'mailto:' && strpos( $host, '@' ) ) {
+               if ( $bits['scheme'] === 'mailto' && strpos( $bits['host'], '@' ) ) {
                        // complete email address
-                       $mailparts = explode( '@', $host );
+                       $mailparts = explode( '@', $bits['host'] );
                        $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) );
-                       $host = $domainpart . '@' . $mailparts[0];
-                       $like = array( "$prot$host", $db->anyString() );
-               } elseif ( $prot == 'mailto:' ) {
-                       // domainpart of email address only. do not add '.'
-                       $host = strtolower( implode( '.', array_reverse( explode( '.', $host ) ) ) );
-                       $like = array( "$prot$host", $db->anyString() );
+                       $bits['host'] = $domainpart . '@' . $mailparts[0];
+               } elseif ( $bits['scheme'] === 'mailto' ) {
+                       // domainpart of email address only, do not add '.'
+                       $bits['host'] = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) );
                } else {
-                       $host = strtolower( implode( '.', array_reverse( explode( '.', $host ) ) ) );
-                       if ( substr( $host, -1, 1 ) !== '.' ) {
-                               $host .= '.';
+                       $bits['host'] = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) );
+                       if ( substr( $bits['host'], -1, 1 ) !== '.' ) {
+                               $bits['host'] .= '.';
                        }
-                       $like = array( "$prot$host" );
+               }
 
-                       if ( $subdomains ) {
-                               $like[] = $db->anyString();
-                       }
-                       if ( !$subdomains || $path !== '/' ) {
-                               $like[] = $path;
-                               $like[] = $db->anyString();
+               $like[] = $bits['scheme'] . $bits['delimiter'] . $bits['host'];
+
+               if ( $subdomains ) {
+                       $like[] = $db->anyString();
+               }
+
+               if ( isset( $bits['port'] ) ) {
+                       $like[] = ':' . $bits['port'];
+               }
+               if ( isset( $bits['path'] ) ) {
+                       $like[] = $bits['path'];
+               } elseif ( !$subdomains ) {
+                       $like[] = '/';
+               }
+               if ( isset( $bits['query'] ) ) {
+                       $like[] = '?' . $bits['query'];
+               }
+               if ( isset( $bits['fragment'] ) ) {
+                       $like[] = '#' . $bits['fragment'];
+               }
+
+               // Check for stray asterisks: asterisk only allowed at the start of the domain
+               foreach ( $like as $likepart ) {
+                       if ( !( $likepart instanceof LikeMatch ) && strpos( $likepart, '*' ) !== false ) {
+                               return false;
                        }
                }
+
+               if ( !( $like[count( $like ) - 1] instanceof LikeMatch ) ) {
+                       // Add wildcard at the end if there isn't one already
+                       $like[] = $db->anyString();
+               }
+
                return $like;
        }
 
        /**
-        * Filters an array returned by makeLikeArray(), removing everything past first pattern placeholder.
+        * Filters an array returned by makeLikeArray(), removing everything past first
+        * pattern placeholder.
         *
         * @param array $arr array to filter
         * @return array filtered array
index 23ece75..7c6bbc6 100644 (file)
@@ -264,8 +264,8 @@ class Linker {
         */
        public static function linkKnown(
                $target, $html = null, $customAttribs = array(),
-               $query = array(), $options = array( 'known', 'noclasses' ) )
-       {
+               $query = array(), $options = array( 'known', 'noclasses' )
+       {
                return self::link( $target, $html, $customAttribs, $query, $options );
        }
 
@@ -562,8 +562,8 @@ class Linker {
         * @return String: HTML for an image, with links, wrappers, etc.
         */
        public static function makeImageLink( /*Parser*/ $parser, Title $title, $file, $frameParams = array(),
-               $handlerParams = array(), $time = false, $query = "", $widthOption = null )
-       {
+               $handlerParams = array(), $time = false, $query = "", $widthOption = null
+       {
                $res = null;
                $dummy = new DummyLinker;
                if ( !wfRunHooks( 'ImageBeforeProduceHTML', array( &$dummy, &$title,
@@ -681,8 +681,7 @@ class Linker {
                                'valign' => isset( $fp['valign'] ) ? $fp['valign'] : false,
                                'img-class' => $fp['class'] );
                        if ( isset( $fp['border'] ) ) {
-                               // TODO: BUG? Both values are identical
-                               $params['img-class'] .= ( $params['img-class'] !== '' ) ? ' thumbborder' : 'thumbborder';
+                               $params['img-class'] .= ( $params['img-class'] !== '' ? ' ' : '' ) . 'thumbborder';
                        }
                        $params = self::getImageLinkMTOParams( $fp, $query, $parser ) + $params;
 
@@ -750,8 +749,8 @@ class Linker {
         * @return mixed
         */
        public static function makeThumbLinkObj( Title $title, $file, $label = '', $alt,
-               $align = 'right', $params = array(), $framed = false, $manualthumb = "" )
-       {
+               $align = 'right', $params = array(), $framed = false, $manualthumb = ""
+       {
                $frameParams = array(
                        'alt' => $alt,
                        'caption' => $label,
@@ -776,8 +775,8 @@ class Linker {
         * @return mixed
         */
        public static function makeThumbLink2( Title $title, $file, $frameParams = array(),
-               $handlerParams = array(), $time = false, $query = "" )
-       {
+               $handlerParams = array(), $time = false, $query = ""
+       {
                global $wgStylePath, $wgContLang;
                $exists = $file && $file->exists();
 
@@ -850,10 +849,10 @@ class Linker {
                if ( $page ) {
                        $url = wfAppendQuery( $url, array( 'page' => $page ) );
                }
-               if ( $manualthumb &&
-                    !isset( $fp['link-title'] ) &&
-                    !isset( $fp['link-url'] ) &&
-                    !isset( $fp['no-link'] ) ) {
+               if ( $manualthumb
+                       && !isset( $fp['link-title'] )
+                       && !isset( $fp['link-url'] )
+                       && !isset( $fp['no-link'] ) ) {
                        $fp['link-url'] = $url;
                }
 
@@ -871,7 +870,7 @@ class Linker {
                        $params = array(
                                'alt' => $fp['alt'],
                                'title' => $fp['title'],
-                               'img-class' => ( isset( $fp['class'] ) && $fp['class'] !== '' ) ? $fp['class'] . ' thumbimage' : 'thumbimage'
+                               'img-class' => ( isset( $fp['class'] ) && $fp['class'] !== '' ? $fp['class'] . ' ' : '' ) . 'thumbimage'
                        );
                        $params = self::getImageLinkMTOParams( $fp, $query ) + $params;
                        $s .= $thumb->toHtml( $params );
@@ -902,7 +901,7 @@ class Linker {
         * @param MediaOutput $thumb
         * @param array $hp image parameters
         */
-       protected static function processResponsiveImages( $file, $thumb, $hp ) {
+       public static function processResponsiveImages( $file, $thumb, $hp ) {
                global $wgResponsiveImages;
                if ( $wgResponsiveImages ) {
                        $hp15 = $hp;
@@ -1471,8 +1470,8 @@ class Linker {
                        $target = Title::newFromText( $linkTarget );
                        if ( $target ) {
                                if ( $target->getText() == '' && $target->getInterwiki() === ''
-                                       && !self::$commentLocal && self::$commentContextTitle )
-                               {
+                                       && !self::$commentLocal && self::$commentContextTitle
+                               {
                                        $newTarget = clone ( self::$commentContextTitle );
                                        $newTarget->setFragment( '#' . $target->getFragment() );
                                        $target = $newTarget;
@@ -2116,9 +2115,10 @@ class Linker {
                        $accesskey = self::accesskey( $name );
                        if ( $accesskey !== false ) {
                                if ( $tooltip === false || $tooltip === '' ) {
-                                       $tooltip = "[$accesskey]";
+                                       $tooltip = wfMessage( 'brackets', $accesskey )->escaped();
                                } else {
-                                       $tooltip .= " [$accesskey]";
+                                       $tooltip .= wfMessage( 'word-separator' )->escaped();
+                                       $tooltip .= wfMessage( 'brackets', $accesskey )->escaped();
                                }
                        }
                }
diff --git a/includes/LinksUpdate.php b/includes/LinksUpdate.php
deleted file mode 100644 (file)
index fdd0e3c..0000000
+++ /dev/null
@@ -1,892 +0,0 @@
-<?php
-/**
- * Updater for link tracking tables after a page edit.
- *
- * 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
- */
-
-/**
- * See docs/deferred.txt
- *
- * @todo document (e.g. one-sentence top-level class description).
- */
-class LinksUpdate extends SqlDataUpdate {
-
-       // @todo make members protected, but make sure extensions don't break
-
-       public $mId,         //!< Page ID of the article linked from
-               $mTitle,         //!< Title object of the article linked from
-               $mParserOutput,  //!< Parser output
-               $mLinks,         //!< Map of title strings to IDs for the links in the document
-               $mImages,        //!< DB keys of the images used, in the array key only
-               $mTemplates,     //!< Map of title strings to IDs for the template references, including broken ones
-               $mExternals,     //!< URLs of external links, array key only
-               $mCategories,    //!< Map of category names to sort keys
-               $mInterlangs,    //!< Map of language codes to titles
-               $mProperties,    //!< Map of arbitrary name to value
-               $mDb,            //!< Database connection reference
-               $mOptions,       //!< SELECT options to be used (array)
-               $mRecursive;     //!< Whether to queue jobs for recursive updates
-
-       /**
-        * @var null|array Added links if calculated.
-        */
-       private $linkInsertions = null;
-
-       /**
-        * @var null|array Deleted links if calculated.
-        */
-       private $linkDeletions = null;
-
-       /**
-        * Constructor
-        *
-        * @param $title Title of the page we're updating
-        * @param $parserOutput ParserOutput: output from a full parse of this page
-        * @param $recursive Boolean: queue jobs for recursive updates?
-        * @throws MWException
-        */
-       function __construct( $title, $parserOutput, $recursive = true ) {
-               parent::__construct( false ); // no implicit transaction
-
-               if ( !( $title instanceof Title ) ) {
-                       throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
-                               "Please see Article::editUpdates() for an invocation example.\n" );
-               }
-
-               if ( !( $parserOutput instanceof ParserOutput ) ) {
-                       throw new MWException( "The calling convention to LinksUpdate::__construct() has changed. " .
-                               "Please see WikiPage::doEditUpdates() for an invocation example.\n" );
-               }
-
-               $this->mTitle = $title;
-               $this->mId = $title->getArticleID();
-
-               if ( !$this->mId ) {
-                       throw new MWException( "The Title object did not provide an article ID. Perhaps the page doesn't exist?" );
-               }
-
-               $this->mParserOutput = $parserOutput;
-
-               $this->mLinks = $parserOutput->getLinks();
-               $this->mImages = $parserOutput->getImages();
-               $this->mTemplates = $parserOutput->getTemplates();
-               $this->mExternals = $parserOutput->getExternalLinks();
-               $this->mCategories = $parserOutput->getCategories();
-               $this->mProperties = $parserOutput->getProperties();
-               $this->mInterwikis = $parserOutput->getInterwikiLinks();
-
-               # Convert the format of the interlanguage links
-               # I didn't want to change it in the ParserOutput, because that array is passed all
-               # the way back to the skin, so either a skin API break would be required, or an
-               # inefficient back-conversion.
-               $ill = $parserOutput->getLanguageLinks();
-               $this->mInterlangs = array();
-               foreach ( $ill as $link ) {
-                       list( $key, $title ) = explode( ':', $link, 2 );
-                       $this->mInterlangs[$key] = $title;
-               }
-
-               foreach ( $this->mCategories as &$sortkey ) {
-                       # If the sortkey is longer then 255 bytes,
-                       # it truncated by DB, and then doesn't get
-                       # matched when comparing existing vs current
-                       # categories, causing bug 25254.
-                       # Also. substr behaves weird when given "".
-                       if ( $sortkey !== '' ) {
-                               $sortkey = substr( $sortkey, 0, 255 );
-                       }
-               }
-
-               $this->mRecursive = $recursive;
-
-               wfRunHooks( 'LinksUpdateConstructed', array( &$this ) );
-       }
-
-       /**
-        * Update link tables with outgoing links from an updated article
-        */
-       public function doUpdate() {
-               wfRunHooks( 'LinksUpdate', array( &$this ) );
-               $this->doIncrementalUpdate();
-               wfRunHooks( 'LinksUpdateComplete', array( &$this ) );
-       }
-
-       protected function doIncrementalUpdate() {
-               wfProfileIn( __METHOD__ );
-
-               # Page links
-               $existing = $this->getExistingLinks();
-               $this->linkDeletions = $this->getLinkDeletions( $existing );
-               $this->linkInsertions = $this->getLinkInsertions( $existing );
-               $this->incrTableUpdate( 'pagelinks', 'pl', $this->linkDeletions, $this->linkInsertions );
-
-               # Image links
-               $existing = $this->getExistingImages();
-
-               $imageDeletes = $this->getImageDeletions( $existing );
-               $this->incrTableUpdate( 'imagelinks', 'il', $imageDeletes,
-                       $this->getImageInsertions( $existing ) );
-
-               # Invalidate all image description pages which had links added or removed
-               $imageUpdates = $imageDeletes + array_diff_key( $this->mImages, $existing );
-               $this->invalidateImageDescriptions( $imageUpdates );
-
-               # External links
-               $existing = $this->getExistingExternals();
-               $this->incrTableUpdate( 'externallinks', 'el', $this->getExternalDeletions( $existing ),
-                       $this->getExternalInsertions( $existing ) );
-
-               # Language links
-               $existing = $this->getExistingInterlangs();
-               $this->incrTableUpdate( 'langlinks', 'll', $this->getInterlangDeletions( $existing ),
-                       $this->getInterlangInsertions( $existing ) );
-
-               # Inline interwiki links
-               $existing = $this->getExistingInterwikis();
-               $this->incrTableUpdate( 'iwlinks', 'iwl', $this->getInterwikiDeletions( $existing ),
-                       $this->getInterwikiInsertions( $existing ) );
-
-               # Template links
-               $existing = $this->getExistingTemplates();
-               $this->incrTableUpdate( 'templatelinks', 'tl', $this->getTemplateDeletions( $existing ),
-                       $this->getTemplateInsertions( $existing ) );
-
-               # Category links
-               $existing = $this->getExistingCategories();
-
-               $categoryDeletes = $this->getCategoryDeletions( $existing );
-
-               $this->incrTableUpdate( 'categorylinks', 'cl', $categoryDeletes,
-                       $this->getCategoryInsertions( $existing ) );
-
-               # Invalidate all categories which were added, deleted or changed (set symmetric difference)
-               $categoryInserts = array_diff_assoc( $this->mCategories, $existing );
-               $categoryUpdates = $categoryInserts + $categoryDeletes;
-               $this->invalidateCategories( $categoryUpdates );
-               $this->updateCategoryCounts( $categoryInserts, $categoryDeletes );
-
-               # Page properties
-               $existing = $this->getExistingProperties();
-
-               $propertiesDeletes = $this->getPropertyDeletions( $existing );
-
-               $this->incrTableUpdate( 'page_props', 'pp', $propertiesDeletes,
-                       $this->getPropertyInsertions( $existing ) );
-
-               # Invalidate the necessary pages
-               $changed = $propertiesDeletes + array_diff_assoc( $this->mProperties, $existing );
-               $this->invalidateProperties( $changed );
-
-               # Refresh links of all pages including this page
-               # This will be in a separate transaction
-               if ( $this->mRecursive ) {
-                       $this->queueRecursiveJobs();
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Queue recursive jobs for this page
-        *
-        * Which means do LinksUpdate on all templates
-        * that include the current page, using the job queue.
-        */
-       function queueRecursiveJobs() {
-               self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
-       }
-
-       /**
-        * Queue a RefreshLinks job for any table.
-        *
-        * @param Title $title Title to do job for
-        * @param String $table Table to use (e.g. 'templatelinks')
-        */
-       public static function queueRecursiveJobsForTable( Title $title, $table ) {
-               wfProfileIn( __METHOD__ );
-               if ( $title->getBacklinkCache()->hasLinks( $table ) ) {
-                       $job = new RefreshLinksJob2(
-                               $title,
-                               array(
-                                       'table' => $table,
-                               ) + Job::newRootJobParams( // "overall" refresh links job info
-                                       "refreshlinks:{$table}:{$title->getPrefixedText()}"
-                               )
-                       );
-                       JobQueueGroup::singleton()->push( $job );
-                       JobQueueGroup::singleton()->deduplicateRootJob( $job );
-               }
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * @param $cats
-        */
-       function invalidateCategories( $cats ) {
-               $this->invalidatePages( NS_CATEGORY, array_keys( $cats ) );
-       }
-
-       /**
-        * Update all the appropriate counts in the category table.
-        * @param array $added associative array of category name => sort key
-        * @param array $deleted associative array of category name => sort key
-        */
-       function updateCategoryCounts( $added, $deleted ) {
-               $a = WikiPage::factory( $this->mTitle );
-               $a->updateCategoryCounts(
-                       array_keys( $added ), array_keys( $deleted )
-               );
-       }
-
-       /**
-        * @param $images
-        */
-       function invalidateImageDescriptions( $images ) {
-               $this->invalidatePages( NS_FILE, array_keys( $images ) );
-       }
-
-       /**
-        * Update a table by doing a delete query then an insert query
-        * @param $table
-        * @param $prefix
-        * @param $deletions
-        * @param $insertions
-        */
-       function incrTableUpdate( $table, $prefix, $deletions, $insertions ) {
-               if ( $table == 'page_props' ) {
-                       $fromField = 'pp_page';
-               } else {
-                       $fromField = "{$prefix}_from";
-               }
-               $where = array( $fromField => $this->mId );
-               if ( $table == 'pagelinks' || $table == 'templatelinks' || $table == 'iwlinks' ) {
-                       if ( $table == 'iwlinks' ) {
-                               $baseKey = 'iwl_prefix';
-                       } else {
-                               $baseKey = "{$prefix}_namespace";
-                       }
-                       $clause = $this->mDb->makeWhereFrom2d( $deletions, $baseKey, "{$prefix}_title" );
-                       if ( $clause ) {
-                               $where[] = $clause;
-                       } else {
-                               $where = false;
-                       }
-               } else {
-                       if ( $table == 'langlinks' ) {
-                               $toField = 'll_lang';
-                       } elseif ( $table == 'page_props' ) {
-                               $toField = 'pp_propname';
-                       } else {
-                               $toField = $prefix . '_to';
-                       }
-                       if ( count( $deletions ) ) {
-                               $where[] = "$toField IN (" . $this->mDb->makeList( array_keys( $deletions ) ) . ')';
-                       } else {
-                               $where = false;
-                       }
-               }
-               if ( $where ) {
-                       $this->mDb->delete( $table, $where, __METHOD__ );
-               }
-               if ( count( $insertions ) ) {
-                       $this->mDb->insert( $table, $insertions, __METHOD__, 'IGNORE' );
-                       wfRunHooks( 'LinksUpdateAfterInsert', array( $this, $table, $insertions ) );
-               }
-       }
-
-       /**
-        * Get an array of pagelinks insertions for passing to the DB
-        * Skips the titles specified by the 2-D array $existing
-        * @param $existing array
-        * @return array
-        */
-       private function getLinkInsertions( $existing = array() ) {
-               $arr = array();
-               foreach ( $this->mLinks as $ns => $dbkeys ) {
-                       $diffs = isset( $existing[$ns] )
-                               ? array_diff_key( $dbkeys, $existing[$ns] )
-                               : $dbkeys;
-                       foreach ( $diffs as $dbk => $id ) {
-                               $arr[] = array(
-                                       'pl_from' => $this->mId,
-                                       'pl_namespace' => $ns,
-                                       'pl_title' => $dbk
-                               );
-                       }
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of template insertions. Like getLinkInsertions()
-        * @param $existing array
-        * @return array
-        */
-       private function getTemplateInsertions( $existing = array() ) {
-               $arr = array();
-               foreach ( $this->mTemplates as $ns => $dbkeys ) {
-                       $diffs = isset( $existing[$ns] ) ? array_diff_key( $dbkeys, $existing[$ns] ) : $dbkeys;
-                       foreach ( $diffs as $dbk => $id ) {
-                               $arr[] = array(
-                                       'tl_from' => $this->mId,
-                                       'tl_namespace' => $ns,
-                                       'tl_title' => $dbk
-                               );
-                       }
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of image insertions
-        * Skips the names specified in $existing
-        * @param $existing array
-        * @return array
-        */
-       private function getImageInsertions( $existing = array() ) {
-               $arr = array();
-               $diffs = array_diff_key( $this->mImages, $existing );
-               foreach ( $diffs as $iname => $dummy ) {
-                       $arr[] = array(
-                               'il_from' => $this->mId,
-                               'il_to' => $iname
-                       );
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of externallinks insertions. Skips the names specified in $existing
-        * @param $existing array
-        * @return array
-        */
-       private function getExternalInsertions( $existing = array() ) {
-               $arr = array();
-               $diffs = array_diff_key( $this->mExternals, $existing );
-               foreach ( $diffs as $url => $dummy ) {
-                       foreach ( wfMakeUrlIndexes( $url ) as $index ) {
-                               $arr[] = array(
-                                       'el_from' => $this->mId,
-                                       'el_to' => $url,
-                                       'el_index' => $index,
-                               );
-                       }
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of category insertions
-        *
-        * @param array $existing mapping existing category names to sort keys. If both
-        * match a link in $this, the link will be omitted from the output
-        *
-        * @return array
-        */
-       private function getCategoryInsertions( $existing = array() ) {
-               global $wgContLang, $wgCategoryCollation;
-               $diffs = array_diff_assoc( $this->mCategories, $existing );
-               $arr = array();
-               foreach ( $diffs as $name => $prefix ) {
-                       $nt = Title::makeTitleSafe( NS_CATEGORY, $name );
-                       $wgContLang->findVariantLink( $name, $nt, true );
-
-                       if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
-                               $type = 'subcat';
-                       } elseif ( $this->mTitle->getNamespace() == NS_FILE ) {
-                               $type = 'file';
-                       } else {
-                               $type = 'page';
-                       }
-
-                       # Treat custom sortkeys as a prefix, so that if multiple
-                       # things are forced to sort as '*' or something, they'll
-                       # sort properly in the category rather than in page_id
-                       # order or such.
-                       $sortkey = Collation::singleton()->getSortKey(
-                               $this->mTitle->getCategorySortkey( $prefix ) );
-
-                       $arr[] = array(
-                               'cl_from' => $this->mId,
-                               'cl_to' => $name,
-                               'cl_sortkey' => $sortkey,
-                               'cl_timestamp' => $this->mDb->timestamp(),
-                               'cl_sortkey_prefix' => $prefix,
-                               'cl_collation' => $wgCategoryCollation,
-                               'cl_type' => $type,
-                       );
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of interlanguage link insertions
-        *
-        * @param array $existing mapping existing language codes to titles
-        *
-        * @return array
-        */
-       private function getInterlangInsertions( $existing = array() ) {
-               $diffs = array_diff_assoc( $this->mInterlangs, $existing );
-               $arr = array();
-               foreach ( $diffs as $lang => $title ) {
-                       $arr[] = array(
-                               'll_from' => $this->mId,
-                               'll_lang' => $lang,
-                               'll_title' => $title
-                       );
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of page property insertions
-        * @param $existing array
-        * @return array
-        */
-       function getPropertyInsertions( $existing = array() ) {
-               $diffs = array_diff_assoc( $this->mProperties, $existing );
-               $arr = array();
-               foreach ( $diffs as $name => $value ) {
-                       $arr[] = array(
-                               'pp_page' => $this->mId,
-                               'pp_propname' => $name,
-                               'pp_value' => $value,
-                       );
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of interwiki insertions for passing to the DB
-        * Skips the titles specified by the 2-D array $existing
-        * @param $existing array
-        * @return array
-        */
-       private function getInterwikiInsertions( $existing = array() ) {
-               $arr = array();
-               foreach ( $this->mInterwikis as $prefix => $dbkeys ) {
-                       $diffs = isset( $existing[$prefix] ) ? array_diff_key( $dbkeys, $existing[$prefix] ) : $dbkeys;
-                       foreach ( $diffs as $dbk => $id ) {
-                               $arr[] = array(
-                                       'iwl_from' => $this->mId,
-                                       'iwl_prefix' => $prefix,
-                                       'iwl_title' => $dbk
-                               );
-                       }
-               }
-               return $arr;
-       }
-
-       /**
-        * Given an array of existing links, returns those links which are not in $this
-        * and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getLinkDeletions( $existing ) {
-               $del = array();
-               foreach ( $existing as $ns => $dbkeys ) {
-                       if ( isset( $this->mLinks[$ns] ) ) {
-                               $del[$ns] = array_diff_key( $existing[$ns], $this->mLinks[$ns] );
-                       } else {
-                               $del[$ns] = $existing[$ns];
-                       }
-               }
-               return $del;
-       }
-
-       /**
-        * Given an array of existing templates, returns those templates which are not in $this
-        * and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getTemplateDeletions( $existing ) {
-               $del = array();
-               foreach ( $existing as $ns => $dbkeys ) {
-                       if ( isset( $this->mTemplates[$ns] ) ) {
-                               $del[$ns] = array_diff_key( $existing[$ns], $this->mTemplates[$ns] );
-                       } else {
-                               $del[$ns] = $existing[$ns];
-                       }
-               }
-               return $del;
-       }
-
-       /**
-        * Given an array of existing images, returns those images which are not in $this
-        * and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getImageDeletions( $existing ) {
-               return array_diff_key( $existing, $this->mImages );
-       }
-
-       /**
-        * Given an array of existing external links, returns those links which are not
-        * in $this and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getExternalDeletions( $existing ) {
-               return array_diff_key( $existing, $this->mExternals );
-       }
-
-       /**
-        * Given an array of existing categories, returns those categories which are not in $this
-        * and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getCategoryDeletions( $existing ) {
-               return array_diff_assoc( $existing, $this->mCategories );
-       }
-
-       /**
-        * Given an array of existing interlanguage links, returns those links which are not
-        * in $this and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getInterlangDeletions( $existing ) {
-               return array_diff_assoc( $existing, $this->mInterlangs );
-       }
-
-       /**
-        * Get array of properties which should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       function getPropertyDeletions( $existing ) {
-               return array_diff_assoc( $existing, $this->mProperties );
-       }
-
-       /**
-        * Given an array of existing interwiki links, returns those links which are not in $this
-        * and thus should be deleted.
-        * @param $existing array
-        * @return array
-        */
-       private function getInterwikiDeletions( $existing ) {
-               $del = array();
-               foreach ( $existing as $prefix => $dbkeys ) {
-                       if ( isset( $this->mInterwikis[$prefix] ) ) {
-                               $del[$prefix] = array_diff_key( $existing[$prefix], $this->mInterwikis[$prefix] );
-                       } else {
-                               $del[$prefix] = $existing[$prefix];
-                       }
-               }
-               return $del;
-       }
-
-       /**
-        * Get an array of existing links, as a 2-D array
-        *
-        * @return array
-        */
-       private function getExistingLinks() {
-               $res = $this->mDb->select( 'pagelinks', array( 'pl_namespace', 'pl_title' ),
-                       array( 'pl_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       if ( !isset( $arr[$row->pl_namespace] ) ) {
-                               $arr[$row->pl_namespace] = array();
-                       }
-                       $arr[$row->pl_namespace][$row->pl_title] = 1;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing templates, as a 2-D array
-        *
-        * @return array
-        */
-       private function getExistingTemplates() {
-               $res = $this->mDb->select( 'templatelinks', array( 'tl_namespace', 'tl_title' ),
-                       array( 'tl_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       if ( !isset( $arr[$row->tl_namespace] ) ) {
-                               $arr[$row->tl_namespace] = array();
-                       }
-                       $arr[$row->tl_namespace][$row->tl_title] = 1;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing images, image names in the keys
-        *
-        * @return array
-        */
-       private function getExistingImages() {
-               $res = $this->mDb->select( 'imagelinks', array( 'il_to' ),
-                       array( 'il_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       $arr[$row->il_to] = 1;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing external links, URLs in the keys
-        *
-        * @return array
-        */
-       private function getExistingExternals() {
-               $res = $this->mDb->select( 'externallinks', array( 'el_to' ),
-                       array( 'el_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       $arr[$row->el_to] = 1;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing categories, with the name in the key and sort key in the value.
-        *
-        * @return array
-        */
-       private function getExistingCategories() {
-               $res = $this->mDb->select( 'categorylinks', array( 'cl_to', 'cl_sortkey_prefix' ),
-                       array( 'cl_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       $arr[$row->cl_to] = $row->cl_sortkey_prefix;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing interlanguage links, with the language code in the key and the
-        * title in the value.
-        *
-        * @return array
-        */
-       private function getExistingInterlangs() {
-               $res = $this->mDb->select( 'langlinks', array( 'll_lang', 'll_title' ),
-                       array( 'll_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       $arr[$row->ll_lang] = $row->ll_title;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing inline interwiki links, as a 2-D array
-        * @return array (prefix => array(dbkey => 1))
-        */
-       protected function getExistingInterwikis() {
-               $res = $this->mDb->select( 'iwlinks', array( 'iwl_prefix', 'iwl_title' ),
-                       array( 'iwl_from' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       if ( !isset( $arr[$row->iwl_prefix] ) ) {
-                               $arr[$row->iwl_prefix] = array();
-                       }
-                       $arr[$row->iwl_prefix][$row->iwl_title] = 1;
-               }
-               return $arr;
-       }
-
-       /**
-        * Get an array of existing categories, with the name in the key and sort key in the value.
-        *
-        * @return array
-        */
-       private function getExistingProperties() {
-               $res = $this->mDb->select( 'page_props', array( 'pp_propname', 'pp_value' ),
-                       array( 'pp_page' => $this->mId ), __METHOD__, $this->mOptions );
-               $arr = array();
-               foreach ( $res as $row ) {
-                       $arr[$row->pp_propname] = $row->pp_value;
-               }
-               return $arr;
-       }
-
-       /**
-        * Return the title object of the page being updated
-        * @return Title
-        */
-       public function getTitle() {
-               return $this->mTitle;
-       }
-
-       /**
-        * Returns parser output
-        * @since 1.19
-        * @return ParserOutput
-        */
-       public function getParserOutput() {
-               return $this->mParserOutput;
-       }
-
-       /**
-        * Return the list of images used as generated by the parser
-        * @return array
-        */
-       public function getImages() {
-               return $this->mImages;
-       }
-
-       /**
-        * Invalidate any necessary link lists related to page property changes
-        * @param $changed
-        */
-       private function invalidateProperties( $changed ) {
-               global $wgPagePropLinkInvalidations;
-
-               foreach ( $changed as $name => $value ) {
-                       if ( isset( $wgPagePropLinkInvalidations[$name] ) ) {
-                               $inv = $wgPagePropLinkInvalidations[$name];
-                               if ( !is_array( $inv ) ) {
-                                       $inv = array( $inv );
-                               }
-                               foreach ( $inv as $table ) {
-                                       $update = new HTMLCacheUpdate( $this->mTitle, $table );
-                                       $update->doUpdate();
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Fetch page links added by this LinksUpdate.  Only available after the update is complete.
-        * @since 1.22
-        * @return null|array of Titles
-        */
-       public function getAddedLinks() {
-               if ( $this->linkInsertions === null ) {
-                       return null;
-               }
-               $result = array();
-               foreach ( $this->linkInsertions as $insertion ) {
-                       $result[] = Title::makeTitle( $insertion[ 'pl_namespace' ], $insertion[ 'pl_title' ] );
-               }
-               return $result;
-       }
-
-       /**
-        * Fetch page links removed by this LinksUpdate.  Only available after the update is complete.
-        * @since 1.22
-        * @return null|array of Titles
-        */
-       public function getRemovedLinks() {
-               if ( $this->linkDeletions === null ) {
-                       return null;
-               }
-               $result = array();
-               foreach ( $this->linkDeletions as $ns => $titles ) {
-                       foreach ( $titles as $title => $unused ) {
-                               $result[] = Title::makeTitle( $ns, $title );
-                       }
-               }
-               return $result;
-       }
-}
-
-/**
- * Update object handling the cleanup of links tables after a page was deleted.
- **/
-class LinksDeletionUpdate extends SqlDataUpdate {
-
-       protected $mPage;     //!< WikiPage the wikipage that was deleted
-
-       /**
-        * Constructor
-        *
-        * @param $page WikiPage Page we are updating
-        * @throws MWException
-        */
-       function __construct( WikiPage $page ) {
-               parent::__construct( false ); // no implicit transaction
-
-               $this->mPage = $page;
-
-               if ( !$page->exists() ) {
-                       throw new MWException( "Page ID not known, perhaps the page doesn't exist?" );
-               }
-       }
-
-       /**
-        * Do some database updates after deletion
-        */
-       public function doUpdate() {
-               $title = $this->mPage->getTitle();
-               $id = $this->mPage->getId();
-
-               # Delete restrictions for it
-               $this->mDb->delete( 'page_restrictions', array( 'pr_page' => $id ), __METHOD__ );
-
-               # Fix category table counts
-               $cats = array();
-               $res = $this->mDb->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
-
-               foreach ( $res as $row ) {
-                       $cats[] = $row->cl_to;
-               }
-
-               $this->mPage->updateCategoryCounts( array(), $cats );
-
-               # If using cascading deletes, we can skip some explicit deletes
-               if ( !$this->mDb->cascadingDeletes() ) {
-                       # Delete outgoing links
-                       $this->mDb->delete( 'pagelinks', array( 'pl_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'imagelinks', array( 'il_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'categorylinks', array( 'cl_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'templatelinks', array( 'tl_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'externallinks', array( 'el_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'langlinks', array( 'll_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'iwlinks', array( 'iwl_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'redirect', array( 'rd_from' => $id ), __METHOD__ );
-                       $this->mDb->delete( 'page_props', array( 'pp_page' => $id ), __METHOD__ );
-               }
-
-               # If using cleanup triggers, we can skip some manual deletes
-               if ( !$this->mDb->cleanupTriggers() ) {
-                       # Clean up recentchanges entries...
-                       $this->mDb->delete( 'recentchanges',
-                               array( 'rc_type != ' . RC_LOG,
-                                       'rc_namespace' => $title->getNamespace(),
-                                       'rc_title' => $title->getDBkey() ),
-                               __METHOD__ );
-                       $this->mDb->delete( 'recentchanges',
-                               array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
-                               __METHOD__ );
-               }
-       }
-
-       /**
-        * Update all the appropriate counts in the category table.
-        * @param array $added associative array of category name => sort key
-        * @param array $deleted associative array of category name => sort key
-        */
-       function updateCategoryCounts( $added, $deleted ) {
-               $a = WikiPage::factory( $this->mTitle );
-               $a->updateCategoryCounts(
-                       array_keys( $added ), array_keys( $deleted )
-               );
-       }
-}
diff --git a/includes/MWCryptRand.php b/includes/MWCryptRand.php
deleted file mode 100644 (file)
index bac018e..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-<?php
-/**
- * A cryptographic random generator class used for generating secret keys
- *
- * This is based in part on Drupal code as well as what we used in our own code
- * prior to introduction of this class.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @author Daniel Friesen
- * @file
- */
-
-class MWCryptRand {
-
-       /**
-        * Minimum number of iterations we want to make in our drift calculations.
-        */
-       const MIN_ITERATIONS = 1000;
-
-       /**
-        * Number of milliseconds we want to spend generating each separate byte
-        * of the final generated bytes.
-        * This is used in combination with the hash length to determine the duration
-        * we should spend doing drift calculations.
-        */
-       const MSEC_PER_BYTE = 0.5;
-
-       /**
-        * Singleton instance for public use
-        */
-       protected static $singleton = null;
-
-       /**
-        * The hash algorithm being used
-        */
-       protected $algo = null;
-
-       /**
-        * The number of bytes outputted by the hash algorithm
-        */
-       protected $hashLength = null;
-
-       /**
-        * A boolean indicating whether the previous random generation was done using
-        * cryptographically strong random number generator or not.
-        */
-       protected $strong = null;
-
-       /**
-        * Initialize an initial random state based off of whatever we can find
-        */
-       protected function initialRandomState() {
-               // $_SERVER contains a variety of unstable user and system specific information
-               // It'll vary a little with each page, and vary even more with separate users
-               // It'll also vary slightly across different machines
-               $state = serialize( $_SERVER );
-
-               // To try vary the system information of the state a bit more
-               // by including the system's hostname into the state
-               $state .= wfHostname();
-
-               // Try to gather a little entropy from the different php rand sources
-               $state .= rand() . uniqid( mt_rand(), true );
-
-               // Include some information about the filesystem's current state in the random state
-               $files = array();
-
-               // We know this file is here so grab some info about ourselves
-               $files[] = __FILE__;
-
-               // We must also have a parent folder, and with the usual file structure, a grandparent
-               $files[] = __DIR__;
-               $files[] = dirname( __DIR__ );
-
-               // The config file is likely the most often edited file we know should be around
-               // so include its stat info into the state.
-               // The constant with its location will almost always be defined, as WebStart.php defines
-               // MW_CONFIG_FILE to $IP/LocalSettings.php unless being configured with MW_CONFIG_CALLBACK (eg. the installer)
-               if ( defined( 'MW_CONFIG_FILE' ) ) {
-                       $files[] = MW_CONFIG_FILE;
-               }
-
-               foreach ( $files as $file ) {
-                       wfSuppressWarnings();
-                       $stat = stat( $file );
-                       wfRestoreWarnings();
-                       if ( $stat ) {
-                               // stat() duplicates data into numeric and string keys so kill off all the numeric ones
-                               foreach ( $stat as $k => $v ) {
-                                       if ( is_numeric( $k ) ) {
-                                               unset( $k );
-                                       }
-                               }
-                               // The absolute filename itself will differ from install to install so don't leave it out
-                               if ( ( $path = realpath( $file ) ) !== false ) {
-                                       $state .= $path;
-                               } else {
-                                       $state .= $file;
-                               }
-                               $state .= implode( '', $stat );
-                       } else {
-                               // The fact that the file isn't there is worth at least a
-                               // minuscule amount of entropy.
-                               $state .= '0';
-                       }
-               }
-
-               // Try and make this a little more unstable by including the varying process
-               // id of the php process we are running inside of if we are able to access it
-               if ( function_exists( 'getmypid' ) ) {
-                       $state .= getmypid();
-               }
-
-               // If available try to increase the instability of the data by throwing in
-               // the precise amount of memory that we happen to be using at the moment.
-               if ( function_exists( 'memory_get_usage' ) ) {
-                       $state .= memory_get_usage( true );
-               }
-
-               // It's mostly worthless but throw the wiki's id into the data for a little more variance
-               $state .= wfWikiID();
-
-               // If we have a secret key or proxy key set then throw it into the state as well
-               global $wgSecretKey, $wgProxyKey;
-               if ( $wgSecretKey ) {
-                       $state .= $wgSecretKey;
-               } elseif ( $wgProxyKey ) {
-                       $state .= $wgProxyKey;
-               }
-
-               return $state;
-       }
-
-       /**
-        * Randomly hash data while mixing in clock drift data for randomness
-        *
-        * @param string $data The data to randomly hash.
-        * @return String The hashed bytes
-        * @author Tim Starling
-        */
-       protected function driftHash( $data ) {
-               // Minimum number of iterations (to avoid slow operations causing the loop to gather little entropy)
-               $minIterations = self::MIN_ITERATIONS;
-               // Duration of time to spend doing calculations (in seconds)
-               $duration = ( self::MSEC_PER_BYTE / 1000 ) * $this->hashLength();
-               // Create a buffer to use to trigger memory operations
-               $bufLength = 10000000;
-               $buffer = str_repeat( ' ', $bufLength );
-               $bufPos = 0;
-
-               // Iterate for $duration seconds or at least $minIterations number of iterations
-               $iterations = 0;
-               $startTime = microtime( true );
-               $currentTime = $startTime;
-               while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
-                       // Trigger some memory writing to trigger some bus activity
-                       // This may create variance in the time between iterations
-                       $bufPos = ( $bufPos + 13 ) % $bufLength;
-                       $buffer[$bufPos] = ' ';
-                       // Add the drift between this iteration and the last in as entropy
-                       $nextTime = microtime( true );
-                       $delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
-                       $data .= $delta;
-                       // Every 100 iterations hash the data and entropy
-                       if ( $iterations % 100 === 0 ) {
-                               $data = sha1( $data );
-                       }
-                       $currentTime = $nextTime;
-                       $iterations++;
-               }
-               $timeTaken = $currentTime - $startTime;
-               $data = $this->hash( $data );
-
-               wfDebug( __METHOD__ . ": Clock drift calculation " .
-                       "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
-                       "iterations=$iterations, " .
-                       "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" );
-               return $data;
-       }
-
-       /**
-        * Return a rolling random state initially build using data from unstable sources
-        * @return string A new weak random state
-        */
-       protected function randomState() {
-               static $state = null;
-               if ( is_null( $state ) ) {
-                       // Initialize the state with whatever unstable data we can find
-                       // It's important that this data is hashed right afterwards to prevent
-                       // it from being leaked into the output stream
-                       $state = $this->hash( $this->initialRandomState() );
-               }
-               // Generate a new random state based on the initial random state or previous
-               // random state by combining it with clock drift
-               $state = $this->driftHash( $state );
-               return $state;
-       }
-
-       /**
-        * Decide on the best acceptable hash algorithm we have available for hash()
-        * @throws MWException
-        * @return String A hash algorithm
-        */
-       protected function hashAlgo() {
-               if ( !is_null( $this->algo ) ) {
-                       return $this->algo;
-               }
-
-               $algos = hash_algos();
-               $preference = array( 'whirlpool', 'sha256', 'sha1', 'md5' );
-
-               foreach ( $preference as $algorithm ) {
-                       if ( in_array( $algorithm, $algos ) ) {
-                               $this->algo = $algorithm;
-                               wfDebug( __METHOD__ . ": Using the {$this->algo} hash algorithm.\n" );
-                               return $this->algo;
-                       }
-               }
-
-               // We only reach here if no acceptable hash is found in the list, this should
-               // be a technical impossibility since most of php's hash list is fixed and
-               // some of the ones we list are available as their own native functions
-               // But since we already require at least 5.2 and hash() was default in
-               // 5.1.2 we don't bother falling back to methods like sha1 and md5.
-               throw new MWException( "Could not find an acceptable hashing function in hash_algos()" );
-       }
-
-       /**
-        * Return the byte-length output of the hash algorithm we are
-        * using in self::hash and self::hmac.
-        *
-        * @return int Number of bytes the hash outputs
-        */
-       protected function hashLength() {
-               if ( is_null( $this->hashLength ) ) {
-                       $this->hashLength = strlen( $this->hash( '' ) );
-               }
-               return $this->hashLength;
-       }
-
-       /**
-        * Generate an acceptably unstable one-way-hash of some text
-        * making use of the best hash algorithm that we have available.
-        *
-        * @param $data string
-        * @return String A raw hash of the data
-        */
-       protected function hash( $data ) {
-               return hash( $this->hashAlgo(), $data, true );
-       }
-
-       /**
-        * Generate an acceptably unstable one-way-hmac of some text
-        * making use of the best hash algorithm that we have available.
-        *
-        * @param $data string
-        * @param $key string
-        * @return String A raw hash of the data
-        */
-       protected function hmac( $data, $key ) {
-               return hash_hmac( $this->hashAlgo(), $data, $key, true );
-       }
-
-       /**
-        * @see self::wasStrong()
-        */
-       public function realWasStrong() {
-               if ( is_null( $this->strong ) ) {
-                       throw new MWException( __METHOD__ . ' called before generation of random data' );
-               }
-               return $this->strong;
-       }
-
-       /**
-        * @see self::generate()
-        */
-       public function realGenerate( $bytes, $forceStrong = false ) {
-               wfProfileIn( __METHOD__ );
-
-               wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " . wfGetAllCallers( 5 ) . "\n" );
-
-               $bytes = floor( $bytes );
-               static $buffer = '';
-               if ( is_null( $this->strong ) ) {
-                       // Set strength to false initially until we know what source data is coming from
-                       $this->strong = true;
-               }
-
-               if ( strlen( $buffer ) < $bytes ) {
-                       // If available make use of mcrypt_create_iv URANDOM source to generate randomness
-                       // On unix-like systems this reads from /dev/urandom but does it without any buffering
-                       // and bypasses openbasedir restrictions, so it's preferable to reading directly
-                       // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
-                       // entropy so this is also preferable to just trying to read urandom because it may work
-                       // on Windows systems as well.
-                       if ( function_exists( 'mcrypt_create_iv' ) ) {
-                               wfProfileIn( __METHOD__ . '-mcrypt' );
-                               $rem = $bytes - strlen( $buffer );
-                               $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
-                               if ( $iv === false ) {
-                                       wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
-                               } else {
-                                       $buffer .= $iv;
-                                       wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) . " bytes of randomness.\n" );
-                               }
-                               wfProfileOut( __METHOD__ . '-mcrypt' );
-                       }
-               }
-
-               if ( strlen( $buffer ) < $bytes ) {
-                       // If available make use of openssl's random_pseudo_bytes method to attempt to generate randomness.
-                       // However don't do this on Windows with PHP < 5.3.4 due to a bug:
-                       // http://stackoverflow.com/questions/1940168/openssl-random-pseudo-bytes-is-slow-php
-                       // http://git.php.net/?p=php-src.git;a=commitdiff;h=cd62a70863c261b07f6dadedad9464f7e213cad5
-                       if ( function_exists( 'openssl_random_pseudo_bytes' )
-                               && ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
-                       ) {
-                               wfProfileIn( __METHOD__ . '-openssl' );
-                               $rem = $bytes - strlen( $buffer );
-                               $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
-                               if ( $openssl_bytes === false ) {
-                                       wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes returned false.\n" );
-                               } else {
-                                       $buffer .= $openssl_bytes;
-                                       wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes generated " . strlen( $openssl_bytes ) . " bytes of " . ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" );
-                               }
-                               if ( strlen( $buffer ) >= $bytes ) {
-                                       // openssl tells us if the random source was strong, if some of our data was generated
-                                       // using it use it's say on whether the randomness is strong
-                                       $this->strong = !!$openssl_strong;
-                               }
-                               wfProfileOut( __METHOD__ . '-openssl' );
-                       }
-               }
-
-               // Only read from urandom if we can control the buffer size or were passed forceStrong
-               if ( strlen( $buffer ) < $bytes && ( function_exists( 'stream_set_read_buffer' ) || $forceStrong ) ) {
-                       wfProfileIn( __METHOD__ . '-fopen-urandom' );
-                       $rem = $bytes - strlen( $buffer );
-                       if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
-                               wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom without control over the buffer size.\n" );
-                       }
-                       // /dev/urandom is generally considered the best possible commonly
-                       // available random source, and is available on most *nix systems.
-                       wfSuppressWarnings();
-                       $urandom = fopen( "/dev/urandom", "rb" );
-                       wfRestoreWarnings();
-
-                       // Attempt to read all our random data from urandom
-                       // php's fread always does buffered reads based on the stream's chunk_size
-                       // so in reality it will usually read more than the amount of data we're
-                       // asked for and not storing that risks depleting the system's random pool.
-                       // If stream_set_read_buffer is available set the chunk_size to the amount
-                       // of data we need. Otherwise read 8k, php's default chunk_size.
-                       if ( $urandom ) {
-                               // php's default chunk_size is 8k
-                               $chunk_size = 1024 * 8;
-                               if ( function_exists( 'stream_set_read_buffer' ) ) {
-                                       // If possible set the chunk_size to the amount of data we need
-                                       stream_set_read_buffer( $urandom, $rem );
-                                       $chunk_size = $rem;
-                               }
-                               $random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
-                               $buffer .= $random_bytes;
-                               fclose( $urandom );
-                               wfDebug( __METHOD__ . ": /dev/urandom generated " . strlen( $random_bytes ) . " bytes of randomness.\n" );
-                               if ( strlen( $buffer ) >= $bytes ) {
-                                       // urandom is always strong, set to true if all our data was generated using it
-                                       $this->strong = true;
-                               }
-                       } else {
-                               wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
-                       }
-                       wfProfileOut( __METHOD__ . '-fopen-urandom' );
-               }
-
-               // If we cannot use or generate enough data from a secure source
-               // use this loop to generate a good set of pseudo random data.
-               // This works by initializing a random state using a pile of unstable data
-               // and continually shoving it through a hash along with a variable salt.
-               // We hash the random state with more salt to avoid the state from leaking
-               // out and being used to predict the /randomness/ that follows.
-               if ( strlen( $buffer ) < $bytes ) {
-                       wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
-               }
-               while ( strlen( $buffer ) < $bytes ) {
-                       wfProfileIn( __METHOD__ . '-fallback' );
-                       $buffer .= $this->hmac( $this->randomState(), mt_rand() );
-                       // This code is never really cryptographically strong, if we use it
-                       // at all, then set strong to false.
-                       $this->strong = false;
-                       wfProfileOut( __METHOD__ . '-fallback' );
-               }
-
-               // Once the buffer has been filled up with enough random data to fulfill
-               // the request shift off enough data to handle the request and leave the
-               // unused portion left inside the buffer for the next request for random data
-               $generated = substr( $buffer, 0, $bytes );
-               $buffer = substr( $buffer, $bytes );
-
-               wfDebug( __METHOD__ . ": " . strlen( $buffer ) . " bytes of randomness leftover in the buffer.\n" );
-
-               wfProfileOut( __METHOD__ );
-               return $generated;
-       }
-
-       /**
-        * @see self::generateHex()
-        */
-       public function realGenerateHex( $chars, $forceStrong = false ) {
-               // hex strings are 2x the length of raw binary so we divide the length in half
-               // odd numbers will result in a .5 that leads the generate() being 1 character
-               // short, so we use ceil() to ensure that we always have enough bytes
-               $bytes = ceil( $chars / 2 );
-               // Generate the data and then convert it to a hex string
-               $hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
-               // A bit of paranoia here, the caller asked for a specific length of string
-               // here, and it's possible (eg when given an odd number) that we may actually
-               // have at least 1 char more than they asked for. Just in case they made this
-               // call intending to insert it into a database that does truncation we don't
-               // want to give them too much and end up with their database and their live
-               // code having two different values because part of what we gave them is truncated
-               // hence, we strip out any run of characters longer than what we were asked for.
-               return substr( $hex, 0, $chars );
-       }
-
-       /** Publicly exposed static methods **/
-
-       /**
-        * Return a singleton instance of MWCryptRand
-        * @return MWCryptRand
-        */
-       protected static function singleton() {
-               if ( is_null( self::$singleton ) ) {
-                       self::$singleton = new self;
-               }
-               return self::$singleton;
-       }
-
-       /**
-        * Return a boolean indicating whether or not the source used for cryptographic
-        * random bytes generation in the previously run generate* call
-        * was cryptographically strong.
-        *
-        * @return bool Returns true if the source was strong, false if not.
-        */
-       public static function wasStrong() {
-               return self::singleton()->realWasStrong();
-       }
-
-       /**
-        * Generate a run of (ideally) cryptographically random data and return
-        * it in raw binary form.
-        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
-        * was cryptographically strong.
-        *
-        * @param int $bytes the number of bytes of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
-        * @return String Raw binary random data
-        */
-       public static function generate( $bytes, $forceStrong = false ) {
-               return self::singleton()->realGenerate( $bytes, $forceStrong );
-       }
-
-       /**
-        * Generate a run of (ideally) cryptographically random data and return
-        * it in hexadecimal string format.
-        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
-        * was cryptographically strong.
-        *
-        * @param int $chars the number of hex chars of random data to generate
-        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
-        *                          strong sources of entropy even if reading from them may steal
-        *                          more entropy from the system than optimal.
-        * @return String Hexadecimal random data
-        */
-       public static function generateHex( $chars, $forceStrong = false ) {
-               return self::singleton()->realGenerateHex( $chars, $forceStrong );
-       }
-
-}
diff --git a/includes/MWFunction.php b/includes/MWFunction.php
deleted file mode 100644 (file)
index 6d11d17..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-/**
- * Helper methods to call functions and instance objects.
- *
- * 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
- */
-
-class MWFunction {
-
-       /**
-        * @deprecated since 1.22; use call_user_func()
-        * @param $callback
-        * @return mixed
-        */
-       public static function call( $callback ) {
-               wfDeprecated( __METHOD__, '1.22' );
-               $args = func_get_args();
-               return call_user_func_array( 'call_user_func', $args );
-       }
-
-       /**
-        * @deprecated since 1.22; use call_user_func_array()
-        * @param $callback
-        * @param $argsarams
-        * @return mixed
-        */
-       public static function callArray( $callback, $argsarams ) {
-               wfDeprecated( __METHOD__, '1.22' );
-               return call_user_func_array( $callback, $argsarams );
-       }
-
-       /**
-        * @param $class
-        * @param $args array
-        * @return object
-        */
-       public static function newObj( $class, $args = array() ) {
-               if ( !count( $args ) ) {
-                       return new $class;
-               }
-
-               $ref = new ReflectionClass( $class );
-               return $ref->newInstanceArgs( $args );
-       }
-
-}
diff --git a/includes/MappedIterator.php b/includes/MappedIterator.php
deleted file mode 100644 (file)
index 70d2032..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-/**
- * Convenience class for generating iterators from iterators.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Convenience class for generating iterators from iterators.
- *
- * @since 1.21
- */
-class MappedIterator extends FilterIterator {
-       /** @var callable */
-       protected $vCallback;
-       /** @var callable */
-       protected $aCallback;
-       /** @var array */
-       protected $cache = array();
-
-       protected $rewound = false; // boolean; whether rewind() has been called
-
-       /**
-        * Build an new iterator from a base iterator by having the former wrap the
-        * later, returning the result of "value" callback for each current() invocation.
-        * The callback takes the result of current() on the base iterator as an argument.
-        * The keys of the base iterator are reused verbatim.
-        *
-        * An "accept" callback can also be provided which will be called for each value in
-        * the base iterator (post-callback) and will return true if that value should be
-        * included in iteration of the MappedIterator (otherwise it will be filtered out).
-        *
-        * @param Iterator|Array $iter
-        * @param callable $vCallback Value transformation callback
-        * @param array $options Options map (includes "accept") (since 1.22)
-        * @throws MWException
-        */
-       public function __construct( $iter, $vCallback, array $options = array() ) {
-               if ( is_array( $iter ) ) {
-                       $baseIterator = new ArrayIterator( $iter );
-               } elseif ( $iter instanceof Iterator ) {
-                       $baseIterator = $iter;
-               } else {
-                       throw new MWException( "Invalid base iterator provided." );
-               }
-               parent::__construct( $baseIterator );
-               $this->vCallback = $vCallback;
-               $this->aCallback = isset( $options['accept'] ) ? $options['accept'] : null;
-       }
-
-       public function next() {
-               $this->cache = array();
-               parent::next();
-       }
-
-       public function rewind() {
-               $this->rewound = true;
-               $this->cache = array();
-               parent::rewind();
-       }
-
-       public function accept() {
-               $value = call_user_func( $this->vCallback, $this->getInnerIterator()->current() );
-               $ok = ( $this->aCallback ) ? call_user_func( $this->aCallback, $value ) : true;
-               if ( $ok ) {
-                       $this->cache['current'] = $value;
-               }
-               return $ok;
-       }
-
-       public function key() {
-               $this->init();
-               return parent::key();
-       }
-
-       public function valid() {
-               $this->init();
-               return parent::valid();
-       }
-
-       public function current() {
-               $this->init();
-               if ( parent::valid() ) {
-                       return $this->cache['current'];
-               } else {
-                       return null; // out of range
-               }
-       }
-
-       /**
-        * Obviate the usual need for rewind() before using a FilterIterator in a manual loop
-        */
-       protected function init() {
-               if ( !$this->rewound ) {
-                       $this->rewind();
-               }
-       }
-}
index 208f96e..57c6264 100644 (file)
@@ -799,7 +799,7 @@ class Message {
         * @return Tuple(type, value)
         */
        protected function extractParam( $param ) {
-               if ( is_array( $param ) ){
+               if ( is_array( $param ) ) {
                        if ( isset( $param['raw'] ) ) {
                                return array( 'after', $param['raw'] );
                        } elseif ( isset( $param['num'] ) ) {
@@ -823,6 +823,11 @@ class Message {
                                );
                                return array( 'before', '[INVALID]' );
                        }
+               } elseif ( $param instanceof Message ) {
+                       // Message objects should not be before parameters because
+                       // then they'll get double escaped. If the message needs to be
+                       // escaped, it'll happen right here when we call toString().
+                       return array( 'after', $param->toString() );
                } else {
                        return array( 'before', $param );
                }
index 37df489..ea89f52 100644 (file)
@@ -28,10 +28,10 @@ abstract class RdfMetaData {
 
        /**
         * Constructor
-        * @param $article Article object
+        * @param Page $page
         */
-       public function __construct( Page $article ) {
-               $this->mArticle = $article;
+       public function __construct( Page $page ) {
+               $this->mArticle = $page;
        }
 
        abstract public function show();
@@ -40,7 +40,10 @@ abstract class RdfMetaData {
                global $wgOut, $wgRequest;
 
                $httpaccept = isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : null;
-               $rdftype = wfNegotiateType( wfAcceptToPrefs( $httpaccept ), wfAcceptToPrefs( self::RDF_TYPE_PREFS ) );
+               $rdftype = wfNegotiateType(
+                       wfAcceptToPrefs( $httpaccept ),
+                       wfAcceptToPrefs( self::RDF_TYPE_PREFS )
+               );
 
                if ( !$rdftype ) {
                        throw new HttpError( 406, wfMessage( 'notacceptable' ) );
@@ -103,8 +106,8 @@ abstract class RdfMetaData {
        }
 
        /**
-        * @param $name string
-        * @param $title Title
+        * @param string $name
+        * @param Title $title
         */
        protected function page( $name, $title ) {
                $this->url( $name, $title->getFullURL() );
index 8220e92..f5c28ab 100644 (file)
@@ -167,7 +167,7 @@ class MimeMagic {
 
        /** The singleton instance
         */
-       private static $instance;
+       private static $instance = null;
 
        /** Initializes the MimeMagic object. This is called by MimeMagic::singleton().
         *
@@ -336,7 +336,7 @@ class MimeMagic {
         * Get an instance of this class
         * @return MimeMagic
         */
-       public static function &singleton() {
+       public static function singleton() {
                if ( self::$instance === null ) {
                        self::$instance = new MimeMagic;
                }
index 5c8e63b..ce585ce 100644 (file)
@@ -433,4 +433,74 @@ class MWNamespace {
                        ? $wgNamespaceContentModels[$index]
                        : null;
        }
+
+       /**
+        * Determine which restriction levels it makes sense to use in a namespace,
+        * optionally filtered by a user's rights.
+        *
+        * @since 1.23
+        * @param int $index Index to check
+        * @param User $user User to check
+        * @return array
+        */
+       public static function getRestrictionLevels( $index, User $user = null ) {
+               global $wgNamespaceProtection, $wgRestrictionLevels;
+
+               if ( !isset( $wgNamespaceProtection[$index] ) ) {
+                       // All levels are valid if there's no namespace restriction.
+                       // But still filter by user, if necessary
+                       $levels = $wgRestrictionLevels;
+                       if ( $user ) {
+                               $levels = array_values( array_filter( $levels, function ( $level ) use ( $user ) {
+                                       $right = $level;
+                                       if ( $right == 'sysop' ) {
+                                               $right = 'editprotected'; // BC
+                                       }
+                                       if ( $right == 'autoconfirmed' ) {
+                                               $right = 'editsemiprotected'; // BC
+                                       }
+                                       return ( $right == '' || $user->isAllowed( $right ) );
+                               } ) );
+                       }
+                       return $levels;
+               }
+
+               // First, get the list of groups that can edit this namespace.
+               $namespaceGroups = array();
+               $combine = 'array_merge';
+               foreach ( (array)$wgNamespaceProtection[$index] as $right ) {
+                       if ( $right == 'sysop' ) {
+                               $right = 'editprotected'; // BC
+                       }
+                       if ( $right == 'autoconfirmed' ) {
+                               $right = 'editsemiprotected'; // BC
+                       }
+                       if ( $right != '' ) {
+                               $namespaceGroups = call_user_func( $combine, $namespaceGroups,
+                                       User::getGroupsWithPermission( $right ) );
+                               $combine = 'array_intersect';
+                       }
+               }
+
+               // Now, keep only those restriction levels where there is at least one
+               // group that can edit the namespace but would be blocked by the
+               // restriction.
+               $usableLevels = array( '' );
+               foreach ( $wgRestrictionLevels as $level ) {
+                       $right = $level;
+                       if ( $right == 'sysop' ) {
+                               $right = 'editprotected'; // BC
+                       }
+                       if ( $right == 'autoconfirmed' ) {
+                               $right = 'editsemiprotected'; // BC
+                       }
+                       if ( $right != '' && ( !$user || $user->isAllowed( $right ) ) &&
+                               array_diff( $namespaceGroups, User::getGroupsWithPermission( $right ) )
+                       ) {
+                               $usableLevels[] = $level;
+                       }
+               }
+
+               return $usableLevels;
+       }
 }
index 6a1ce19..a0d7e30 100644 (file)
@@ -255,6 +255,11 @@ class OutputPage extends ContextSource {
         */
        private $mTarget = null;
 
+       /**
+        * @var bool: Whether output should contain table of contents
+        */
+       private $mEnableTOC = true;
+
        /**
         * Constructor for OutputPage. This should not be called directly.
         * Instead a new RequestContext should be created and it will implicitly create
@@ -442,8 +447,8 @@ class OutputPage extends ContextSource {
                        if ( $module instanceof ResourceLoaderModule
                                && $module->getOrigin() <= $this->getAllowedModules( $type )
                                && ( is_null( $position ) || $module->getPosition() == $position )
-                               && ( !$this->mTarget || in_array( $this->mTarget, $module->getTargets() ) ) )
-                       {
+                               && ( !$this->mTarget || in_array( $this->mTarget, $module->getTargets() ) )
+                       {
                                $filteredModules[] = $val;
                        }
                }
@@ -886,7 +891,10 @@ class OutputPage extends ContextSource {
                $this->mPagetitle = $nameWithTags;
 
                # change "<i>foo&amp;bar</i>" to "foo&bar"
-               $this->setHTMLTitle( $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) ) );
+               $this->setHTMLTitle(
+                       $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) )
+                               ->inContentLanguage()
+               );
        }
 
        /**
@@ -1606,6 +1614,7 @@ class OutputPage extends ContextSource {
         */
        function addParserOutput( &$parserOutput ) {
                $this->addParserOutputNoText( $parserOutput );
+               $parserOutput->setTOCEnabled( $this->mEnableTOC );
                $text = $parserOutput->getText();
                wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
                $this->addHTML( $text );
@@ -1617,10 +1626,7 @@ class OutputPage extends ContextSource {
         * @param $template QuickTemplate
         */
        public function addTemplate( &$template ) {
-               ob_start();
-               $template->execute();
-               $this->addHTML( ob_get_contents() );
-               ob_end_clean();
+               $this->addHTML( $template->getHTML() );
        }
 
        /**
@@ -2485,7 +2491,7 @@ $templates
                $ret = Html::htmlHeader( array( 'lang' => $this->getLanguage()->getHtmlCode(), 'dir' => $userdir, 'class' => 'client-nojs' ) );
 
                if ( $this->getHTMLTitle() == '' ) {
-                       $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() ) );
+                       $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
                }
 
                $openHead = Html::openElement( 'head' );
@@ -2974,9 +2980,11 @@ $templates
                $ns = $title->getNamespace();
                $canonicalNamespace = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $title->getNsText();
 
+               $sk = $this->getSkin();
                // Get the relevant title so that AJAX features can use the correct page name
                // when making API requests from certain special pages (bug 34972).
-               $relevantTitle = $this->getSkin()->getRelevantTitle();
+               $relevantTitle = $sk->getRelevantTitle();
+               $relevantUser = $sk->getRelevantUser();
 
                if ( $ns == NS_SPECIAL ) {
                        list( $canonicalSpecialPageName, /*...*/ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
@@ -3053,6 +3061,9 @@ $templates
                if ( $this->mRedirectedFrom ) {
                        $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
                }
+               if ( $relevantUser ) {
+                       $vars['wgRelevantUserName'] = $relevantUser->getName();
+               }
 
                // Allow extensions to add their custom variables to the mw.config map.
                // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
@@ -3648,4 +3659,20 @@ $templates
                return array();
        }
 
+       /**
+        * Enables/disables TOC, doesn't override __NOTOC__
+        * @param bool $flag
+        * @since 1.22
+        */
+       public function enableTOC( $flag = true ) {
+               $this->mEnableTOC = $flag;
+       }
+
+       /**
+        * @return bool
+        * @since 1.22
+        */
+       public function isTOCEnabled() {
+               return $this->mEnableTOC;
+       }
 }
index 02d3546..e6d6ebf 100644 (file)
@@ -38,7 +38,7 @@
  * version are hardcoded here
  */
 function wfPHPVersionError( $type ) {
-       $mwVersion = '1.22';
+       $mwVersion = '1.23';
        $minimumVersionPHP = '5.3.2';
 
        $phpVersion = phpversion();
index 61a535d..02a883a 100644 (file)
  * @ingroup SpecialPage
  */
 abstract class PageQueryPage extends QueryPage {
+       /**
+        * Run a LinkBatch to pre-cache LinkCache information,
+        * like page existence and information for stub color and redirect hints.
+        * This should be done for live data and cached data.
+        *
+        * @param $db DatabaseBase connection
+        * @param ResultWrapper $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 );
+       }
+
        /**
         * Format the result as a simple link to the page
         *
@@ -41,7 +63,7 @@ abstract class PageQueryPage extends QueryPage {
 
                if ( $title instanceof Title ) {
                        $text = $wgContLang->convert( $title->getPrefixedText() );
-                       return Linker::linkKnown( $title, htmlspecialchars( $text ) );
+                       return Linker::link( $title, htmlspecialchars( $text ) );
                } else {
                        return Html::element( 'span', array( 'class' => 'mw-invalidtitle' ),
                                Linker::getInvalidTitleDescription( $this->getContext(), $row->namespace, $row->title ) );
index 4a14c7e..28d2839 100644 (file)
@@ -267,6 +267,15 @@ abstract class IndexPager extends ContextSource implements Pager {
                }
        }
 
+       /**
+        * Get the current limit
+        *
+        * @return int
+        */
+       function getLimit() {
+               return $this->mLimit;
+       }
+
        /**
         * Set whether a row matching exactly the offset should be also included
         * in the result or not. By default this is not the case, but when the
index c9caf4f..d498770 100644 (file)
@@ -682,8 +682,8 @@ class Preferences {
                        $minDiff = $tz[1];
                        $tzSetting = sprintf( '%+03d:%02d', floor( $minDiff / 60 ), abs( $minDiff ) % 60 );
                } elseif ( count( $tz ) > 1 && $tz[0] == 'ZoneInfo' &&
-                       !in_array( $tzOffset, HTMLFormField::flattenOptions( $tzOptions ) ) )
-               {
+                       !in_array( $tzOffset, HTMLFormField::flattenOptions( $tzOptions ) )
+               {
                        # Timezone offset can vary with DST
                        $userTZ = timezone_open( $tz[2] );
                        if ( $userTZ !== false ) {
index f10317a..d6cc8a3 100644 (file)
@@ -83,8 +83,8 @@ class ProtectionForm {
         */
        function loadData() {
                global $wgRequest, $wgUser;
-               global $wgRestrictionLevels;
 
+               $levels = MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace(), $wgUser );
                $this->mCascade = $this->mTitle->areRestrictionsCascading();
 
                $this->mReason = $wgRequest->getText( 'mwProtect-reason' );
@@ -132,21 +132,7 @@ class ProtectionForm {
                        }
 
                        $val = $wgRequest->getVal( "mwProtect-level-$action" );
-                       if ( isset( $val ) && in_array( $val, $wgRestrictionLevels ) ) {
-                               // Prevent users from setting levels that they cannot later unset
-                               if ( $val == 'sysop' ) {
-                                       // Special case, rewrite sysop to editprotected
-                                       if ( !$wgUser->isAllowed( 'editprotected' ) ) {
-                                               continue;
-                                       }
-                               } elseif ( $val == 'autoconfirmed' ) {
-                                       // Special case, rewrite autoconfirmed to editsemiprotected
-                                       if ( !$wgUser->isAllowed( 'editsemiprotected' ) ) {
-                                               continue;
-                                       }
-                               } elseif ( !$wgUser->isAllowed( $val ) ) {
-                                       continue;
-                               }
+                       if ( isset( $val ) && in_array( $val, $levels ) ) {
                                $this->mRestrictions[$action] = $val;
                        }
                }
@@ -189,7 +175,7 @@ class ProtectionForm {
        function execute() {
                global $wgRequest, $wgOut;
 
-               if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+               if ( MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) === array( '' ) ) {
                        throw new ErrorPageError( 'protect-badnamespace-title', 'protect-badnamespace-text' );
                }
 
@@ -556,28 +542,13 @@ class ProtectionForm {
         * @return String: HTML fragment
         */
        function buildSelector( $action, $selected ) {
-               global $wgRestrictionLevels, $wgUser;
-
-               $levels = array();
-               foreach ( $wgRestrictionLevels as $key ) {
-                       //don't let them choose levels above their own (aka so they can still unprotect and edit the page). but only when the form isn't disabled
-                       if ( $key == 'sysop' ) {
-                               //special case, rewrite sysop to editprotected
-                               if ( !$wgUser->isAllowed( 'editprotected' ) && !$this->disabled ) {
-                                       continue;
-                               }
-                       } elseif ( $key == 'autoconfirmed' ) {
-                               //special case, rewrite autoconfirmed to editsemiprotected
-                               if ( !$wgUser->isAllowed( 'editsemiprotected' ) && !$this->disabled ) {
-                                       continue;
-                               }
-                       } else {
-                               if ( !$wgUser->isAllowed( $key ) && !$this->disabled ) {
-                                       continue;
-                               }
-                       }
-                       $levels[] = $key;
-               }
+               global $wgUser;
+
+               // If the form is disabled, display all relevant levels. Otherwise,
+               // just show the ones this user can use.
+               $levels = MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace(),
+                       $this->disabled ? null : $wgUser
+               );
 
                $id = 'mwProtect-level-' . $action;
                $attribs = array(
index bf1c405..a0f9e5f 100644 (file)
@@ -77,10 +77,24 @@ function wfIsTrustedProxy( $ip ) {
  * Checks if an IP matches a proxy we've configured.
  * @param $ip String
  * @return bool
+ * @since 1.23 Supports CIDR ranges in $wgSquidServersNoPurge
  */
 function wfIsConfiguredProxy( $ip ) {
        global $wgSquidServers, $wgSquidServersNoPurge;
-       $trusted = in_array( $ip, $wgSquidServers ) ||
-               in_array( $ip, $wgSquidServersNoPurge );
+
+       // quick check of known proxy servers
+       $trusted = in_array( $ip, $wgSquidServers )
+               || in_array( $ip, $wgSquidServersNoPurge );
+
+       if ( !$trusted ) {
+               // slightly slower check to see if the ip is listed directly or in a CIDR
+               // block in $wgSquidServersNoPurge
+               foreach ( $wgSquidServersNoPurge as $block ) {
+                       if ( strpos( $block, '/' ) !== false && IP::isInRange( $ip, $block ) ) {
+                               $trusted = true;
+                               break;
+                       }
+               }
+       }
        return $trusted;
 }
index 233eac0..6ab3df4 100644 (file)
@@ -433,6 +433,36 @@ class Revision implements IDBAccessObject {
                return $fields;
        }
 
+       /**
+        * Return the list of revision fields that should be selected to create
+        * a new revision from an archive row.
+        * @return array
+        */
+       public static function selectArchiveFields() {
+               global $wgContentHandlerUseDB;
+               $fields = array(
+                       'ar_id',
+                       'ar_page_id',
+                       'ar_rev_id',
+                       'ar_text_id',
+                       'ar_timestamp',
+                       'ar_comment',
+                       'ar_user_text',
+                       'ar_user',
+                       'ar_minor_edit',
+                       'ar_deleted',
+                       'ar_len',
+                       'ar_parent_id',
+                       'ar_sha1',
+               );
+
+               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
@@ -1281,8 +1311,8 @@ class Revision implements IDBAccessObject {
 
                global $wgLegacyEncoding;
                if ( $text !== false && $wgLegacyEncoding
-                       && !in_array( 'utf-8', $flags ) && !in_array( 'utf8', $flags ) )
-               {
+                       && !in_array( 'utf-8', $flags ) && !in_array( 'utf8', $flags )
+               {
                        # Old revisions kept around in a legacy encoding?
                        # Upconvert on demand.
                        # ("utf8" checked for compatibility with some broken
@@ -1423,14 +1453,14 @@ class Revision implements IDBAccessObject {
                                $t = $title->getPrefixedDBkey();
 
                                throw new MWException( "Can't save non-default content model with \$wgContentHandlerUseDB disabled: "
-                                                                               . "model is $model , default for $t is $defaultModel" );
+                                       . "model is $model, default for $t is $defaultModel" );
                        }
 
                        if ( $this->getContentFormat() != $defaultFormat ) {
                                $t = $title->getPrefixedDBkey();
 
                                throw new MWException( "Can't use non-default content format with \$wgContentHandlerUseDB disabled: "
-                                                                               . "format is $format, default for $t is $defaultFormat" );
+                                       . "format is $format, default for $t is $defaultFormat" );
                        }
                }
 
index 499d821..3384af0 100644 (file)
@@ -865,6 +865,27 @@ class Sanitizer {
                $value = preg_replace_callback( $decodeRegex,
                        array( __CLASS__, 'cssDecodeCallback' ), $value );
 
+               // Normalize Halfwidth and Fullwidth Unicode block that IE6 might treat as ascii
+               $value = preg_replace_callback(
+                       '/[!-z]/u', // U+FF01 to U+FF5A
+                       function ( $matches ) {
+                               $cp = utf8ToCodepoint( $matches[0] );
+                               if ( $cp === false ) {
+                                       return '';
+                               }
+                               return chr( $cp - 65248 ); // ASCII range \x21-\x7A
+                       },
+                       $value
+               );
+
+               // Convert more characters IE6 might treat as ascii
+               // U+0280, U+0274, U+207F, U+029F, U+026A, U+207D, U+208D
+               $value = str_replace(
+                       array( 'ʀ', 'ɴ', 'ⁿ', 'ʟ', 'ɪ', '⁽', '₍' ),
+                       array( 'r', 'n', 'n', 'l', 'i', '(', '(' ),
+                       $value
+               );
+
                // Let the value through if it's nothing but a single comment, to
                // allow other functions which may reject it to pass some error
                // message through.
@@ -885,8 +906,24 @@ class Sanitizer {
                        }
                }
 
+               // S followed by repeat, iteration, or prolonged sound marks,
+               // which IE will treat as "ss"
+               $value = preg_replace(
+                       '/s(?:
+                               \xE3\x80\xB1 | # U+3031
+                               \xE3\x82\x9D | # U+309D
+                               \xE3\x83\xBC | # U+30FC
+                               \xE3\x83\xBD | # U+30FD
+                               \xEF\xB9\xBC | # U+FE7C
+                               \xEF\xB9\xBD | # U+FE7D
+                               \xEF\xBD\xB0   # U+FF70
+                       )/ix',
+                       'ss',
+                       $value
+               );
+
                // Reject problematic keywords and control characters
-               if ( preg_match( '/[\000-\010\016-\037\177]/', $value ) ) {
+               if ( preg_match( '/[\000-\010\013\016-\037\177]/', $value ) ) {
                        return '/* invalid control char */';
                } elseif ( preg_match( '! expression | filter\s*: | accelerator\s*: | url\s*\( | image\s*\( | image-set\s*\( !ix', $value ) ) {
                        return '/* insecure input */';
@@ -1484,7 +1521,7 @@ class Sanitizer {
                }
 
                $block = array_merge( $common, array( 'align' ) );
-               $tablealign = array( 'align', 'char', 'charoff', 'valign' );
+               $tablealign = array( 'align', 'valign' );
                $tablecell = array(
                        'abbr',
                        'axis',
@@ -1504,7 +1541,7 @@ class Sanitizer {
                        # 7.5.4
                        'div'        => $block,
                        'center'     => $common, # deprecated
-                       'span'       => $block, # ??
+                       'span'       => $common,
 
                        # 7.5.5
                        'h1'         => $block,
@@ -1518,7 +1555,7 @@ class Sanitizer {
                        # address
 
                        # 8.2.4
-                       # bdo
+                       'bdo'        => $common,
 
                        # 9.2.1
                        'em'         => $common,
@@ -1534,7 +1571,7 @@ class Sanitizer {
 
                        # 9.2.2
                        'blockquote' => array_merge( $common, array( 'cite' ) ),
-                       # q
+                       'q'          => array_merge( $common, array( 'cite' ) ),
 
                        # 9.2.3
                        'sub'        => $common,
@@ -1544,10 +1581,10 @@ class Sanitizer {
                        'p'          => $block,
 
                        # 9.3.2
-                       'br'         => array( 'id', 'class', 'title', 'style', 'clear' ),
+                       'br'         => array_merge( $common, array( 'clear' ) ),
 
                        # http://www.whatwg.org/html/text-level-semantics.html#the-wbr-element
-                       'wbr'        => array( 'id', 'class', 'title', 'style' ),
+                       'wbr'        => $common,
 
                        # 9.3.4
                        'pre'        => array_merge( $common, array( 'width' ) ),
@@ -1574,16 +1611,16 @@ class Sanitizer {
                                                                ) ),
 
                        # 11.2.2
-                       'caption'    => array_merge( $common, array( 'align' ) ),
+                       'caption'    => $block,
 
                        # 11.2.3
-                       'thead'      => array_merge( $common, $tablealign ),
-                       'tfoot'      => array_merge( $common, $tablealign ),
-                       'tbody'      => array_merge( $common, $tablealign ),
+                       'thead'      => $common,
+                       'tfoot'      => $common,
+                       'tbody'      => $common,
 
                        # 11.2.4
-                       'colgroup'   => array_merge( $common, array( 'span', 'width' ), $tablealign ),
-                       'col'        => array_merge( $common, array( 'span', 'width' ), $tablealign ),
+                       'colgroup'   => array_merge( $common, array( 'span' ) ),
+                       'col'        => array_merge( $common, array( 'span' ) ),
 
                        # 11.2.5
                        'tr'         => array_merge( $common, array( 'bgcolor' ), $tablealign ),
@@ -1618,7 +1655,7 @@ class Sanitizer {
                        # basefont
 
                        # 15.3
-                       'hr'         => array_merge( $common, array( 'noshade', 'size', 'width' ) ),
+                       'hr'         => array_merge( $common, array( 'width' ) ),
 
                        # HTML Ruby annotation text module, simple ruby only.
                        # http://www.whatwg.org/html/text-level-semantics.html#the-ruby-element
diff --git a/includes/ScopedCallback.php b/includes/ScopedCallback.php
deleted file mode 100644 (file)
index ef22e0a..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/**
- * This file deals with RAII style scoped callbacks.
- *
- * 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
- */
-
-/**
- * Class for asserting that a callback happens when an dummy object leaves scope
- *
- * @since 1.21
- */
-class ScopedCallback {
-       /** @var callable */
-       protected $callback;
-
-       /**
-        * @param callable $callback
-        * @throws MWException
-        */
-       public function __construct( $callback ) {
-               if ( !is_callable( $callback ) ) {
-                       throw new MWException( "Provided callback is not valid." );
-               }
-               $this->callback = $callback;
-       }
-
-       /**
-        * Trigger a scoped callback and destroy it.
-        * This is the same is just setting it to null.
-        *
-        * @param ScopedCallback $sc
-        */
-       public static function consume( ScopedCallback &$sc = null ) {
-               $sc = null;
-       }
-
-       /**
-        * Destroy a scoped callback without triggering it
-        *
-        * @param ScopedCallback $sc
-        */
-       public static function cancel( ScopedCallback &$sc = null ) {
-               if ( $sc ) {
-                       $sc->callback = null;
-               }
-               $sc = null;
-       }
-
-       /**
-        * Trigger the callback when this leaves scope
-        */
-       function __destruct() {
-               if ( $this->callback !== null ) {
-                       call_user_func( $this->callback );
-               }
-       }
-}
diff --git a/includes/ScopedPHPTimeout.php b/includes/ScopedPHPTimeout.php
deleted file mode 100644 (file)
index d1493c3..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-<?php
-/**
- * Expansion of the PHP execution time limit feature for a function call.
- *
- * 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
- */
-
-/**
- * Class to expand PHP execution time for a function call.
- * Use this when performing changes that should not be interrupted.
- *
- * On construction, set_time_limit() is called and set to $seconds.
- * If the client aborts the connection, PHP will continue to run.
- * When the object goes out of scope, the timer is restarted, with
- * the original time limit minus the time the object existed.
- */
-class ScopedPHPTimeout {
-       protected $startTime; // float; seconds
-       protected $oldTimeout; // integer; seconds
-       protected $oldIgnoreAbort; // boolean
-
-       protected static $stackDepth = 0; // integer
-       protected static $totalCalls = 0; // integer
-       protected static $totalElapsed = 0; // float; seconds
-
-       /* Prevent callers in infinite loops from running forever */
-       const MAX_TOTAL_CALLS = 1000000;
-       const MAX_TOTAL_TIME = 300; // seconds
-
-       /**
-        * @param $seconds integer
-        */
-       public function __construct( $seconds ) {
-               if ( ini_get( 'max_execution_time' ) > 0 ) { // CLI uses 0
-                       if ( self::$totalCalls >= self::MAX_TOTAL_CALLS ) {
-                               trigger_error( "Maximum invocations of " . __CLASS__ . " exceeded." );
-                       } elseif ( self::$totalElapsed >= self::MAX_TOTAL_TIME ) {
-                               trigger_error( "Time limit within invocations of " . __CLASS__ . " exceeded." );
-                       } elseif ( self::$stackDepth > 0 ) { // recursion guard
-                               trigger_error( "Resursive invocation of " . __CLASS__ . " attempted." );
-                       } else {
-                               $this->oldIgnoreAbort = ignore_user_abort( true );
-                               $this->oldTimeout = ini_set( 'max_execution_time', $seconds );
-                               $this->startTime = microtime( true );
-                               ++self::$stackDepth;
-                               ++self::$totalCalls; // proof against < 1us scopes
-                       }
-               }
-       }
-
-       /**
-        * Restore the original timeout.
-        * This does not account for the timer value on __construct().
-        */
-       public function __destruct() {
-               if ( $this->oldTimeout ) {
-                       $elapsed = microtime( true ) - $this->startTime;
-                       // Note: a limit of 0 is treated as "forever"
-                       set_time_limit( max( 1, $this->oldTimeout - (int)$elapsed ) );
-                       // If each scoped timeout is for less than one second, we end up
-                       // restoring the original timeout without any decrease in value.
-                       // Thus web scripts in an infinite loop can run forever unless we
-                       // take some measures to prevent this. Track total time and calls.
-                       self::$totalElapsed += $elapsed;
-                       --self::$stackDepth;
-                       ignore_user_abort( $this->oldIgnoreAbort );
-               }
-       }
-}
index 2e083d8..f75ee29 100644 (file)
@@ -102,10 +102,10 @@ if ( isset( $wgFileStore['deleted']['directory'] ) ) {
        $wgDeletedDirectory = $wgFileStore['deleted']['directory'];
 }
 
-if ( isset( $wgFooterIcons['copyright'] ) &&
-       isset( $wgFooterIcons['copyright']['copyright'] ) &&
-       $wgFooterIcons['copyright']['copyright'] === array() )
-{
+if ( isset( $wgFooterIcons['copyright'] )
+       && isset( $wgFooterIcons['copyright']['copyright'] )
+       && $wgFooterIcons['copyright']['copyright'] === array()
+{
        if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) {
                $wgFooterIcons['copyright']['copyright'] = $wgCopyrightIcon;
        } elseif ( $wgRightsIcon || $wgRightsText ) {
@@ -119,10 +119,10 @@ if ( isset( $wgFooterIcons['copyright'] ) &&
        }
 }
 
-if ( isset( $wgFooterIcons['poweredby'] ) &&
-       isset( $wgFooterIcons['poweredby']['mediawiki'] ) &&
-       $wgFooterIcons['poweredby']['mediawiki']['src'] === null )
-{
+if ( isset( $wgFooterIcons['poweredby'] )
+       && isset( $wgFooterIcons['poweredby']['mediawiki'] )
+       && $wgFooterIcons['poweredby']['mediawiki']['src'] === null
+{
        $wgFooterIcons['poweredby']['mediawiki']['src'] = "$wgStylePath/common/images/poweredby_mediawiki_88x31.png";
 }
 
@@ -293,7 +293,6 @@ if ( $wgMetaNamespace === false ) {
        $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
 }
 
-
 // Default value is either the suhosin limit or -1 for unlimited
 if ( $wgResourceLoaderMaxQueryLength === false ) {
        $maxValueLength = ini_get( 'suhosin.get.max_value_length' );
index 355993c..0df6d90 100644 (file)
@@ -251,231 +251,6 @@ class SiteStats {
        }
 }
 
-/**
- * Class for handling updates to the site_stats table
- */
-class SiteStatsUpdate implements DeferrableUpdate {
-       protected $views = 0;
-       protected $edits = 0;
-       protected $pages = 0;
-       protected $articles = 0;
-       protected $users = 0;
-       protected $images = 0;
-
-       // @todo deprecate this constructor
-       function __construct( $views, $edits, $good, $pages = 0, $users = 0 ) {
-               $this->views = $views;
-               $this->edits = $edits;
-               $this->articles = $good;
-               $this->pages = $pages;
-               $this->users = $users;
-       }
-
-       /**
-        * @param $deltas Array
-        * @return SiteStatsUpdate
-        */
-       public static function factory( array $deltas ) {
-               $update = new self( 0, 0, 0 );
-
-               $fields = array( 'views', 'edits', 'pages', 'articles', 'users', 'images' );
-               foreach ( $fields as $field ) {
-                       if ( isset( $deltas[$field] ) && $deltas[$field] ) {
-                               $update->$field = $deltas[$field];
-                       }
-               }
-
-               return $update;
-       }
-
-       public function doUpdate() {
-               global $wgSiteStatsAsyncFactor;
-
-               $rate = $wgSiteStatsAsyncFactor; // convenience
-               // If set to do so, only do actual DB updates 1 every $rate times.
-               // The other times, just update "pending delta" values in memcached.
-               if ( $rate && ( $rate < 0 || mt_rand( 0, $rate - 1 ) != 0 ) ) {
-                       $this->doUpdatePendingDeltas();
-               } else {
-                       // Need a separate transaction because this a global lock
-                       wfGetDB( DB_MASTER )->onTransactionIdle( array( $this, 'tryDBUpdateInternal' ) );
-               }
-       }
-
-       /**
-        * Do not call this outside of SiteStatsUpdate
-        *
-        * @return void
-        */
-       public function tryDBUpdateInternal() {
-               global $wgSiteStatsAsyncFactor;
-
-               $dbw = wfGetDB( DB_MASTER );
-               $lockKey = wfMemcKey( 'site_stats' ); // prepend wiki ID
-               if ( $wgSiteStatsAsyncFactor ) {
-                       // Lock the table so we don't have double DB/memcached updates
-                       if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
-                               || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout
-                       ) {
-                               $this->doUpdatePendingDeltas();
-                               return;
-                       }
-                       $pd = $this->getPendingDeltas();
-                       // Piggy-back the async deltas onto those of this stats update....
-                       $this->views += ( $pd['ss_total_views']['+'] - $pd['ss_total_views']['-'] );
-                       $this->edits += ( $pd['ss_total_edits']['+'] - $pd['ss_total_edits']['-'] );
-                       $this->articles += ( $pd['ss_good_articles']['+'] - $pd['ss_good_articles']['-'] );
-                       $this->pages += ( $pd['ss_total_pages']['+'] - $pd['ss_total_pages']['-'] );
-                       $this->users += ( $pd['ss_users']['+'] - $pd['ss_users']['-'] );
-                       $this->images += ( $pd['ss_images']['+'] - $pd['ss_images']['-'] );
-               }
-
-               // Build up an SQL query of deltas and apply them...
-               $updates = '';
-               $this->appendUpdate( $updates, 'ss_total_views', $this->views );
-               $this->appendUpdate( $updates, 'ss_total_edits', $this->edits );
-               $this->appendUpdate( $updates, 'ss_good_articles', $this->articles );
-               $this->appendUpdate( $updates, 'ss_total_pages', $this->pages );
-               $this->appendUpdate( $updates, 'ss_users', $this->users );
-               $this->appendUpdate( $updates, 'ss_images', $this->images );
-               if ( $updates != '' ) {
-                       $dbw->update( 'site_stats', array( $updates ), array(), __METHOD__ );
-               }
-
-               if ( $wgSiteStatsAsyncFactor ) {
-                       // Decrement the async deltas now that we applied them
-                       $this->removePendingDeltas( $pd );
-                       // Commit the updates and unlock the table
-                       $dbw->unlock( $lockKey, __METHOD__ );
-               }
-       }
-
-       /**
-        * @param $dbw DatabaseBase
-        * @return bool|mixed
-        */
-       public static function cacheUpdate( $dbw ) {
-               global $wgActiveUserDays;
-               $dbr = wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow' ) );
-               # Get non-bot users than did some recent action other than making accounts.
-               # If account creation is included, the number gets inflated ~20+ fold on enwiki.
-               $activeUsers = $dbr->selectField(
-                       'recentchanges',
-                       'COUNT( DISTINCT rc_user_text )',
-                       array(
-                               'rc_user != 0',
-                               'rc_bot' => 0,
-                               'rc_log_type != ' . $dbr->addQuotes( 'newusers' ) . ' OR rc_log_type IS NULL',
-                               'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX ) - $wgActiveUserDays * 24 * 3600 ) ),
-                       ),
-                       __METHOD__
-               );
-               $dbw->update(
-                       'site_stats',
-                       array( 'ss_active_users' => intval( $activeUsers ) ),
-                       array( 'ss_row_id' => 1 ),
-                       __METHOD__
-               );
-               return $activeUsers;
-       }
-
-       protected function doUpdatePendingDeltas() {
-               $this->adjustPending( 'ss_total_views', $this->views );
-               $this->adjustPending( 'ss_total_edits', $this->edits );
-               $this->adjustPending( 'ss_good_articles', $this->articles );
-               $this->adjustPending( 'ss_total_pages', $this->pages );
-               $this->adjustPending( 'ss_users', $this->users );
-               $this->adjustPending( 'ss_images', $this->images );
-       }
-
-       /**
-        * @param $sql string
-        * @param $field string
-        * @param $delta integer
-        */
-       protected function appendUpdate( &$sql, $field, $delta ) {
-               if ( $delta ) {
-                       if ( $sql ) {
-                               $sql .= ',';
-                       }
-                       if ( $delta < 0 ) {
-                               $sql .= "$field=$field-" . abs( $delta );
-                       } else {
-                               $sql .= "$field=$field+" . abs( $delta );
-                       }
-               }
-       }
-
-       /**
-        * @param $type string
-        * @param string $sign ('+' or '-')
-        * @return string
-        */
-       private function getTypeCacheKey( $type, $sign ) {
-               return wfMemcKey( 'sitestatsupdate', 'pendingdelta', $type, $sign );
-       }
-
-       /**
-        * Adjust the pending deltas for a stat type.
-        * Each stat type has two pending counters, one for increments and decrements
-        * @param $type string
-        * @param $delta integer Delta (positive or negative)
-        * @return void
-        */
-       protected function adjustPending( $type, $delta ) {
-               global $wgMemc;
-
-               if ( $delta < 0 ) { // decrement
-                       $key = $this->getTypeCacheKey( $type, '-' );
-               } else { // increment
-                       $key = $this->getTypeCacheKey( $type, '+' );
-               }
-
-               $magnitude = abs( $delta );
-               if ( !$wgMemc->incr( $key, $magnitude ) ) { // not there?
-                       if ( !$wgMemc->add( $key, $magnitude ) ) { // race?
-                               $wgMemc->incr( $key, $magnitude );
-                       }
-               }
-       }
-
-       /**
-        * Get pending delta counters for each stat type
-        * @return Array Positive and negative deltas for each type
-        * @return void
-        */
-       protected function getPendingDeltas() {
-               global $wgMemc;
-
-               $pending = array();
-               foreach ( array( 'ss_total_views', 'ss_total_edits',
-                       'ss_good_articles', 'ss_total_pages', 'ss_users', 'ss_images' ) as $type )
-               {
-                       // Get pending increments and pending decrements
-                       $pending[$type]['+'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '+' ) );
-                       $pending[$type]['-'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '-' ) );
-               }
-
-               return $pending;
-       }
-
-       /**
-        * Reduce pending delta counters after updates have been applied
-        * @param array $pd Result of getPendingDeltas(), used for DB update
-        * @return void
-        */
-       protected function removePendingDeltas( array $pd ) {
-               global $wgMemc;
-
-               foreach ( $pd as $type => $deltas ) {
-                       foreach ( $deltas as $sign => $magnitude ) {
-                               // Lower the pending counter now that we applied these changes
-                               $wgMemc->decr( $this->getTypeCacheKey( $type, $sign ), $magnitude );
-                       }
-               }
-       }
-}
-
 /**
  * Class designed for counting of stats.
  */
index 5801806..750f319 100644 (file)
@@ -1379,61 +1379,58 @@ abstract class Skin extends ContextSource {
 
                if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
                        $uTalkTitle = $user->getTalkPage();
-
-                       if ( !$uTalkTitle->equals( $out->getTitle() ) ) {
-                               $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
-                               $nofAuthors = 0;
-                               if ( $lastSeenRev !== null ) {
-                                       $plural = true; // Default if we have a last seen revision: if unknown, use plural
-                                       $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
-                                       if ( $latestRev !== null ) {
-                                               // Singular if only 1 unseen revision, plural if several unseen revisions.
-                                               $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
-                                               $nofAuthors = $uTalkTitle->countAuthorsBetween(
-                                                       $lastSeenRev, $latestRev, 10, 'include_new' );
-                                       }
-                               } else {
-                                       // Singular if no revision -> diff link will show latest change only in any case
-                                       $plural = false;
+                       $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
+                       $nofAuthors = 0;
+                       if ( $lastSeenRev !== null ) {
+                               $plural = true; // Default if we have a last seen revision: if unknown, use plural
+                               $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
+                               if ( $latestRev !== null ) {
+                                       // Singular if only 1 unseen revision, plural if several unseen revisions.
+                                       $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
+                                       $nofAuthors = $uTalkTitle->countAuthorsBetween(
+                                               $lastSeenRev, $latestRev, 10, 'include_new' );
                                }
-                               $plural = $plural ? 2 : 1;
-                               // 2 signifies "more than one revision". We don't know how many, and even if we did,
-                               // the number of revisions or authors is not necessarily the same as the number of
-                               // "messages".
-                               $newMessagesLink = Linker::linkKnown(
-                                       $uTalkTitle,
-                                       $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
-                                       array(),
-                                       array( 'redirect' => 'no' )
-                               );
+                       } else {
+                               // Singular if no revision -> diff link will show latest change only in any case
+                               $plural = false;
+                       }
+                       $plural = $plural ? 999 : 1;
+                       // 999 signifies "more than one revision". We don't know how many, and even if we did,
+                       // the number of revisions or authors is not necessarily the same as the number of
+                       // "messages".
+                       $newMessagesLink = Linker::linkKnown(
+                               $uTalkTitle,
+                               $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
+                               array(),
+                               array( 'redirect' => 'no' )
+                       );
 
-                               $newMessagesDiffLink = Linker::linkKnown(
-                                       $uTalkTitle,
-                                       $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
-                                       array(),
-                                       $lastSeenRev !== null
-                                               ? array( 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' )
-                                               : array( 'diff' => 'cur' )
-                               );
+                       $newMessagesDiffLink = Linker::linkKnown(
+                               $uTalkTitle,
+                               $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
+                               array(),
+                               $lastSeenRev !== null
+                                       ? array( 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' )
+                                       : array( 'diff' => 'cur' )
+                       );
 
-                               if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
-                                       $newMessagesAlert = $this->msg(
-                                               'youhavenewmessagesfromusers',
-                                               $newMessagesLink,
-                                               $newMessagesDiffLink
-                                       )->numParams( $nofAuthors );
-                               } else {
-                                       // $nofAuthors === 11 signifies "11 or more" ("more than 10")
-                                       $newMessagesAlert = $this->msg(
-                                               $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
-                                               $newMessagesLink,
-                                               $newMessagesDiffLink
-                                       );
-                               }
-                               $newMessagesAlert = $newMessagesAlert->text();
-                               # Disable Squid cache
-                               $out->setSquidMaxage( 0 );
+                       if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
+                               $newMessagesAlert = $this->msg(
+                                       'youhavenewmessagesfromusers',
+                                       $newMessagesLink,
+                                       $newMessagesDiffLink
+                               )->numParams( $nofAuthors );
+                       } else {
+                               // $nofAuthors === 11 signifies "11 or more" ("more than 10")
+                               $newMessagesAlert = $this->msg(
+                                       $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
+                                       $newMessagesLink,
+                                       $newMessagesDiffLink
+                               );
                        }
+                       $newMessagesAlert = $newMessagesAlert->text();
+                       # Disable Squid cache
+                       $out->setSquidMaxage( 0 );
                } elseif ( count( $newtalks ) ) {
                        $sep = $this->msg( 'newtalkseparator' )->escaped();
                        $msgs = array();
@@ -1562,7 +1559,7 @@ abstract class Skin extends ContextSource {
         * editSectionLinkForOther().
         *
         * @param $nt      Title  The title being linked to (may not be the same as
-        *   $wgTitle, if the section is included from a template)
+        *   the current page, if the section is included from a template)
         * @param string $section The designation of the section being pointed to,
         *   to be included in the link, like "&section=$section"
         * @param string $tooltip The tooltip to use for the link: will be escaped
index e5b8872..da4c376 100644 (file)
@@ -130,44 +130,63 @@ class SkinTemplate extends Skin {
         */
        public function getLanguages() {
                global $wgHideInterlanguageLinks;
-               $out = $this->getOutput();
+               if ( $wgHideInterlanguageLinks ) {
+                       return array();
+               }
+
                $userLang = $this->getLanguage();
+               $languageLinks = array();
 
-               # Language links
-               $language_urls = array();
-
-               if ( !$wgHideInterlanguageLinks ) {
-                       foreach ( $out->getLanguageLinks() as $languageLinkText ) {
-                               $languageLinkParts = explode( ':', $languageLinkText, 2 );
-                               $class = 'interwiki-' . $languageLinkParts[0];
-                               unset( $languageLinkParts );
-                               $languageLinkTitle = Title::newFromText( $languageLinkText );
-                               if ( $languageLinkTitle ) {
-                                       $ilInterwikiCode = $languageLinkTitle->getInterwiki();
-                                       $ilLangName = Language::fetchLanguageName( $ilInterwikiCode );
-
-                                       if ( strval( $ilLangName ) === '' ) {
-                                               $ilLangName = $languageLinkText;
-                                       } else {
-                                               $ilLangName = $this->formatLanguageName( $ilLangName );
-                                       }
+               foreach ( $this->getOutput()->getLanguageLinks() as $languageLinkText ) {
+                       $languageLinkParts = explode( ':', $languageLinkText, 2 );
+                       $class = 'interlanguage-link interwiki-' . $languageLinkParts[0];
+                       unset( $languageLinkParts );
 
-                                       // CLDR extension or similar is required to localize the language name;
-                                       // otherwise we'll end up with the autonym again.
-                                       $ilLangLocalName = Language::fetchLanguageName( $ilInterwikiCode, $userLang->getCode() );
-
-                                       $language_urls[] = array(
-                                               'href' => $languageLinkTitle->getFullURL(),
-                                               'text' => $ilLangName,
-                                               'title' => wfMessage( 'tooltip-iwiki', $languageLinkTitle->getText(), $ilLangLocalName )->escaped(),
-                                               'class' => $class,
-                                               'lang' => wfBCP47( $ilInterwikiCode ),
-                                               'hreflang' => wfBCP47( $ilInterwikiCode ),
-                                       );
+                       $languageLinkTitle = Title::newFromText( $languageLinkText );
+                       if ( $languageLinkTitle ) {
+                               $ilInterwikiCode = $languageLinkTitle->getInterwiki();
+                               $ilLangName = Language::fetchLanguageName( $ilInterwikiCode );
+
+                               if ( strval( $ilLangName ) === '' ) {
+                                       $ilLangName = $languageLinkText;
+                               } else {
+                                       $ilLangName = $this->formatLanguageName( $ilLangName );
                                }
+
+                               // CLDR extension or similar is required to localize the language name;
+                               // otherwise we'll end up with the autonym again.
+                               $ilLangLocalName = Language::fetchLanguageName(
+                                       $ilInterwikiCode,
+                                       $userLang->getCode()
+                               );
+
+                               $languageLinkTitleText = $languageLinkTitle->getText();
+                               if ( $languageLinkTitleText === '' ) {
+                                       $ilTitle = wfMessage(
+                                               'interlanguage-link-title-langonly',
+                                               $ilLangLocalName
+                                       )->text();
+                               } else {
+                                       $ilTitle = wfMessage(
+                                               'interlanguage-link-title',
+                                               $languageLinkTitleText,
+                                               $ilLangLocalName
+                                       )->text();
+                               }
+
+                               $ilInterwikiCodeBCP47 = wfBCP47( $ilInterwikiCode );
+                               $languageLinks[] = array(
+                                       'href' => $languageLinkTitle->getFullURL(),
+                                       'text' => $ilLangName,
+                                       'title' => $ilTitle,
+                                       'class' => $class,
+                                       'lang' => $ilInterwikiCodeBCP47,
+                                       'hreflang' => $ilInterwikiCodeBCP47,
+                               );
                        }
                }
-               return $language_urls;
+
+               return $languageLinks;
        }
 
        protected function setupTemplateForOutput() {
@@ -217,15 +236,6 @@ class SkinTemplate extends Skin {
         * @param $out OutputPage
         */
        function outputPage( OutputPage $out = null ) {
-               global $wgContLang;
-               global $wgScript, $wgStylePath;
-               global $wgMimeType, $wgJsMimeType;
-               global $wgXhtmlNamespaces, $wgHtml5Version;
-               global $wgDisableCounters, $wgSitename, $wgLogo;
-               global $wgMaxCredits, $wgShowCreditsIfMax;
-               global $wgPageShowWatchingUsers;
-               global $wgArticlePath, $wgScriptPath, $wgServer;
-
                wfProfileIn( __METHOD__ );
                Profiler::instance()->setTemplated( true );
 
@@ -237,14 +247,45 @@ class SkinTemplate extends Skin {
                }
 
                $out = $this->getOutput();
-               $request = $this->getRequest();
                $user = $this->getUser();
-               $title = $this->getTitle();
 
                wfProfileIn( __METHOD__ . '-init' );
                $this->initPage( $out );
                wfProfileOut( __METHOD__ . '-init' );
+               $tpl = $this->prepareQuickTemplate( $out );
+               // execute template
+               wfProfileIn( __METHOD__ . '-execute' );
+               $res = $tpl->execute();
+               wfProfileOut( __METHOD__ . '-execute' );
+
+               // result may be an error
+               $this->printOrError( $res );
+
+               if ( $oldContext ) {
+                       $this->setContext( $oldContext );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * initialize various variables and generate the template
+        *
+        * @since 1.23
+        * @param $out OutputPage
+        * @return QuickTemplate the template to be executed by outputPage
+        */
+       protected function prepareQuickTemplate( OutputPage $out = null ) {
+               global $wgContLang, $wgScript, $wgStylePath,
+                       $wgMimeType, $wgJsMimeType, $wgXhtmlNamespaces, $wgHtml5Version,
+                       $wgDisableCounters, $wgSitename, $wgLogo, $wgMaxCredits,
+                       $wgShowCreditsIfMax, $wgPageShowWatchingUsers, $wgArticlePath,
+                       $wgScriptPath, $wgServer;
 
+               wfProfileIn( __METHOD__ );
+
+               $title = $this->getTitle();
+               $request = $this->getRequest();
                $tpl = $this->setupTemplateForOutput();
 
                wfProfileIn( __METHOD__ . '-stuff-head' );
@@ -523,18 +564,8 @@ class SkinTemplate extends Skin {
                $tpl->set( 'dataAfterContent', $this->afterContentHook() );
                wfProfileOut( __METHOD__ . '-stuff5' );
 
-               // execute template
-               wfProfileIn( __METHOD__ . '-execute' );
-               $res = $tpl->execute();
-               wfProfileOut( __METHOD__ . '-execute' );
-
-               // result may be an error
-               $this->printOrError( $res );
-
-               if ( $oldContext ) {
-                       $this->setContext( $oldContext );
-               }
                wfProfileOut( __METHOD__ );
+               return $tpl;
        }
 
        /**
@@ -729,7 +760,7 @@ class SkinTemplate extends Skin {
                        $personal_urls[$login_id] = $login_url;
                }
 
-               wfRunHooks( 'PersonalUrls', array( &$personal_urls, &$title ) );
+               wfRunHooks( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
                wfProfileOut( __METHOD__ );
                return $personal_urls;
        }
@@ -1008,7 +1039,9 @@ class SkinTemplate extends Skin {
                                        }
                                }
 
-                               if ( $title->getNamespace() !== NS_MEDIAWIKI && $title->quickUserCan( 'protect', $user ) && $title->getRestrictionTypes() ) {
+                               if ( $title->quickUserCan( 'protect', $user ) && $title->getRestrictionTypes() &&
+                                       MWNamespace::getRestrictionLevels( $title->getNamespace(), $user ) !== array( '' )
+                               ) {
                                        $mode = $title->isProtected() ? 'unprotect' : 'protect';
                                        $content_navigation['actions'][$mode] = array(
                                                'class' => ( $onPage && $action == $mode ) ? 'selected' : false,
@@ -1438,6 +1471,20 @@ abstract class QuickTemplate {
        public function getSkin() {
                return $this->data['skin'];
        }
+
+       /**
+        * Fetch the output of a QuickTemplate and return it
+        *
+        * @since 1.23
+        * @return String
+        */
+       public function getHTML() {
+               ob_start();
+               $this->execute();
+               $html = ob_get_contents();
+               ob_end_clean();
+               return $html;
+       }
 }
 
 /**
@@ -1998,9 +2045,10 @@ abstract class BaseTemplate extends QuickTemplate {
         * body and html tags.
         */
        function printTrail() { ?>
+<?php echo MWDebug::getDebugHTML( $this->getSkin()->getContext() ); ?>
 <?php $this->html( 'bottomscripts' ); /* JS call to runBodyOnloadHook */ ?>
 <?php $this->html( 'reporttime' ) ?>
-<?php echo MWDebug::getDebugHTML( $this->getSkin()->getContext() );
+<?php
        }
 
 }
index a6195fc..f70a6dc 100644 (file)
@@ -259,11 +259,7 @@ class SpecialPage {
         */
        public static function getTitleFor( $name, $subpage = false, $fragment = '' ) {
                $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
-               if ( $name ) {
-                       return Title::makeTitle( NS_SPECIAL, $name, $fragment );
-               } else {
-                       throw new MWException( "Invalid special page name \"$name\"" );
-               }
+               return Title::makeTitle( NS_SPECIAL, $name, $fragment );
        }
 
        /**
@@ -599,6 +595,49 @@ class SpecialPage {
                }
        }
 
+       /**
+        * If the user is not logged in, throws UserNotLoggedIn error.
+        *
+        * Default error message includes a link to Special:Userlogin with properly set 'returnto' query
+        * parameter.
+        *
+        * @since 1.23
+        * @param string|Message $reasonMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
+        *     will be used as message keys. If a string is given, the message will also receive a
+        *     formatted login link (generated using the 'loginreqlink' message) as first parameter. If a
+        *     Message is given, it will be passed on verbatim.
+        * @param string|Message $titleMsg [optional] Passed on to UserNotLoggedIn constructor. Strings
+        *     will be used as message keys.
+        * @throws UserNotLoggedIn
+        */
+       public function requireLogin( $reasonMsg = null, $titleMsg = null ) {
+               if ( $this->getUser()->isAnon() ) {
+                       // Use default messages if not given or explicit null passed
+                       if ( !$reasonMsg ) {
+                               $reasonMsg = 'exception-nologin-text-manual';
+                       }
+                       if ( !$titleMsg ) {
+                               $titleMsg = 'exception-nologin';
+                       }
+
+                       // Convert to Messages with current context
+                       if ( is_string( $reasonMsg ) ) {
+                               $loginreqlink = Linker::linkKnown(
+                                       SpecialPage::getTitleFor( 'Userlogin' ),
+                                       $this->msg( 'loginreqlink' )->escaped(),
+                                       array(),
+                                       array( 'returnto' => $this->getTitle()->getPrefixedText() )
+                               );
+                               $reasonMsg = $this->msg( $reasonMsg )->rawParams( $loginreqlink );
+                       }
+                       if ( is_string( $titleMsg ) ) {
+                               $titleMsg = $this->msg( $titleMsg );
+                       }
+
+                       throw new UserNotLoggedIn( $reasonMsg, $titleMsg );
+               }
+       }
+
        /**
         * Sets headers - this should be called from the execute() method of all derived classes!
         */
@@ -837,12 +876,10 @@ class SpecialPage {
         * @see wfMessage
         */
        public function msg( /* $args */ ) {
-               // Note: can't use func_get_args() directly as second or later item in
-               // a parameter list until PHP 5.3 or you get a fatal error.
-               // Works fine as the first parameter, which appears elsewhere in the
-               // code base. Sighhhh.
-               $args = func_get_args();
-               $message = call_user_func_array( array( $this->getContext(), 'msg' ), $args );
+               $message = call_user_func_array(
+                       array( $this->getContext(), 'msg' ),
+                       func_get_args()
+               );
                // RequestContext passes context to wfMessage, and the language is set from
                // the context, but setting the language for Message class removes the
                // interface message status, which breaks for example usernameless gender
@@ -881,7 +918,6 @@ class SpecialPage {
        public function getFinalGroupName() {
                global $wgSpecialPageGroups;
                $name = $this->getName();
-               $group = '-';
 
                // Allow overbidding the group from the wiki side
                $msg = $this->msg( 'specialpages-specialpagegroup-' . strtolower( $name ) )->inContentLanguage();
@@ -1424,7 +1460,6 @@ class SpecialAllMyUploads extends RedirectSpecialPage {
        }
 }
 
-
 /**
  * Redirect from Special:PermanentLink/### to index.php?oldid=###
  */
index 11edc8a..30eb129 100644 (file)
@@ -37,7 +37,7 @@
  * and bails out if not.
  *
  * To add a core special page, use the similar static list in
- * SpecialPage::$mList. To remove a core static special page at runtime, use
+ * SpecialPageFactory::$list. To remove a core static special page at runtime, use
  * a SpecialPage_initList hook.
  *
  * @ingroup SpecialPage
@@ -48,7 +48,7 @@ class SpecialPageFactory {
        /**
         * List of special page names to the subclass of SpecialPage which handles them.
         */
-       private static $mList = array(
+       private static $list = array(
                // Maintenance Reports
                'BrokenRedirects'           => 'BrokenRedirectsPage',
                'Deadendpages'              => 'DeadendpagesPage',
@@ -108,7 +108,7 @@ class SpecialPageFactory {
                'Log'                       => 'SpecialLog',
                'Watchlist'                 => 'SpecialWatchlist',
                'Newpages'                  => 'SpecialNewpages',
-               'Recentchanges'             => 'SpecialRecentchanges',
+               'Recentchanges'             => 'SpecialRecentChanges',
                'Recentchangeslinked'       => 'SpecialRecentchangeslinked',
                'Tags'                      => 'SpecialTags',
 
@@ -149,6 +149,7 @@ class SpecialPageFactory {
                'Undelete'                  => 'SpecialUndelete',
                'Whatlinkshere'             => 'SpecialWhatlinkshere',
                'MergeHistory'              => 'SpecialMergeHistory',
+               'ExpandTemplates'           => 'SpecialExpandTemplates',
 
                // Other
                'Booksources'               => 'SpecialBookSources',
@@ -169,11 +170,10 @@ class SpecialPageFactory {
                'Userlogout'                => 'SpecialUserlogout',
        );
 
-       private static $mAliases;
+       private static $aliases;
 
        /**
-        * Initialise the special page list
-        * This must be called before accessing SpecialPage::$mList
+        * Get the special page list
         *
         * @return array
         */
@@ -182,43 +182,43 @@ class SpecialPageFactory {
                global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
                global $wgEnableEmail, $wgEnableJavaScriptTest;
 
-               if ( !is_object( self::$mList ) ) {
+               if ( !is_object( self::$list ) ) {
                        wfProfileIn( __METHOD__ );
 
                        if ( !$wgDisableCounters ) {
-                               self::$mList['Popularpages'] = 'PopularpagesPage';
+                               self::$list['Popularpages'] = 'PopularpagesPage';
                        }
 
                        if ( !$wgDisableInternalSearch ) {
-                               self::$mList['Search'] = 'SpecialSearch';
+                               self::$list['Search'] = 'SpecialSearch';
                        }
 
                        if ( $wgEmailAuthentication ) {
-                               self::$mList['Confirmemail'] = 'EmailConfirmation';
-                               self::$mList['Invalidateemail'] = 'EmailInvalidation';
+                               self::$list['Confirmemail'] = 'EmailConfirmation';
+                               self::$list['Invalidateemail'] = 'EmailInvalidation';
                        }
 
                        if ( $wgEnableEmail ) {
-                               self::$mList['ChangeEmail'] = 'SpecialChangeEmail';
+                               self::$list['ChangeEmail'] = 'SpecialChangeEmail';
                        }
 
                        if ( $wgEnableJavaScriptTest ) {
-                               self::$mList['JavaScriptTest'] = 'SpecialJavaScriptTest';
+                               self::$list['JavaScriptTest'] = 'SpecialJavaScriptTest';
                        }
 
                        // Add extension special pages
-                       self::$mList = array_merge( self::$mList, $wgSpecialPages );
+                       self::$list = array_merge( self::$list, $wgSpecialPages );
 
                        // Run hooks
                        // This hook can be used to remove undesired built-in special pages
-                       wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) );
+                       wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
 
                        // Cast to object: func()[$key] doesn't work, but func()->$key does
-                       settype( self::$mList, 'object' );
+                       settype( self::$list, 'object' );
 
                        wfProfileOut( __METHOD__ );
                }
-               return self::$mList;
+               return self::$list;
        }
 
        /**
@@ -230,28 +230,28 @@ class SpecialPageFactory {
         * @return Object
         */
        static function getAliasList() {
-               if ( !is_object( self::$mAliases ) ) {
+               if ( !is_object( self::$aliases ) ) {
                        global $wgContLang;
                        $aliases = $wgContLang->getSpecialPageAliases();
 
                        // Objects are passed by reference by default, need to create a copy
                        $missingPages = clone self::getList();
 
-                       self::$mAliases = array();
+                       self::$aliases = array();
                        foreach ( $aliases as $realName => $aliasList ) {
                                foreach ( $aliasList as $alias ) {
-                                       self::$mAliases[$wgContLang->caseFold( $alias )] = $realName;
+                                       self::$aliases[$wgContLang->caseFold( $alias )] = $realName;
                                }
                                unset( $missingPages->$realName );
                        }
                        foreach ( $missingPages as $name => $stuff ) {
-                               self::$mAliases[$wgContLang->caseFold( $name )] = $name;
+                               self::$aliases[$wgContLang->caseFold( $name )] = $name;
                        }
 
                        // Cast to object: func()[$key] doesn't work, but func()->$key does
-                       self::$mAliases = (object)self::$mAliases;
+                       self::$aliases = (object)self::$aliases;
                }
-               return self::$mAliases;
+               return self::$aliases;
        }
 
        /**
diff --git a/includes/SqlDataUpdate.php b/includes/SqlDataUpdate.php
deleted file mode 100644 (file)
index 51188d8..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-<?php
-/**
- * Base code for update jobs that put some secondary data extracted
- * from article content into the database.
- *
- * 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
- */
-
-/**
- * Abstract base class for update jobs that put some secondary data extracted
- * from article content into the database.
- *
- * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
- *        a transaction will automatically be wrapped around the update. Starting another
- *        one would break the outer transaction bracket. If need be, subclasses can override
- *        the beginTransaction() and commitTransaction() methods.
- */
-abstract class SqlDataUpdate extends DataUpdate {
-
-       protected $mDb;            //!< Database connection reference
-       protected $mOptions;       //!< SELECT options to be used (array)
-
-       private   $mHasTransaction; //!< bool whether a transaction is open on this object (internal use only!)
-       protected $mUseTransaction; //!< bool whether this update should be wrapped in a transaction
-
-       /**
-        * Constructor
-        *
-        * @param bool $withTransaction whether this update should be wrapped in a transaction (default: true).
-        *             A transaction is only started if no transaction is already in progress,
-        *             see beginTransaction() for details.
-        **/
-       public function __construct( $withTransaction = true ) {
-               global $wgAntiLockFlags;
-
-               parent::__construct();
-
-               if ( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) {
-                       $this->mOptions = array();
-               } else {
-                       $this->mOptions = array( 'FOR UPDATE' );
-               }
-
-               // @todo get connection only when it's needed? make sure that doesn't break anything, especially transactions!
-               $this->mDb = wfGetDB( DB_MASTER );
-
-               $this->mWithTransaction = $withTransaction;
-               $this->mHasTransaction = false;
-       }
-
-       /**
-        * Begin a database transaction, if $withTransaction was given as true in the constructor for this SqlDataUpdate.
-        *
-        * Because nested transactions are not supported by the Database class, this implementation
-        * checks Database::trxLevel() and only opens a transaction if none is already active.
-        */
-       public function beginTransaction() {
-               if ( !$this->mWithTransaction ) {
-                       return;
-               }
-
-               // NOTE: nested transactions are not supported, only start a transaction if none is open
-               if ( $this->mDb->trxLevel() === 0 ) {
-                       $this->mDb->begin( get_class( $this ) . '::beginTransaction' );
-                       $this->mHasTransaction = true;
-               }
-       }
-
-       /**
-        * Commit the database transaction started via beginTransaction (if any).
-        */
-       public function commitTransaction() {
-               if ( $this->mHasTransaction ) {
-                       $this->mDb->commit( get_class( $this ) . '::commitTransaction' );
-                       $this->mHasTransaction = false;
-               }
-       }
-
-       /**
-        * Abort the database transaction started via beginTransaction (if any).
-        */
-       public function abortTransaction() {
-               if ( $this->mHasTransaction ) { //XXX: actually... maybe always?
-                       $this->mDb->rollback( get_class( $this ) . '::abortTransaction' );
-                       $this->mHasTransaction = false;
-               }
-       }
-
-       /**
-        * Invalidate the cache of a list of pages from a single namespace.
-        * This is intended for use by subclasses.
-        *
-        * @param $namespace Integer
-        * @param $dbkeys Array
-        */
-       protected function invalidatePages( $namespace, array $dbkeys ) {
-               if ( $dbkeys === array() ) {
-                       return;
-               }
-
-               /**
-                * Determine which pages need to be updated
-                * This is necessary to prevent the job queue from smashing the DB with
-                * large numbers of concurrent invalidations of the same page
-                */
-               $now = $this->mDb->timestamp();
-               $ids = array();
-               $res = $this->mDb->select( 'page', array( 'page_id' ),
-                       array(
-                               'page_namespace' => $namespace,
-                               'page_title' => $dbkeys,
-                               'page_touched < ' . $this->mDb->addQuotes( $now )
-                       ), __METHOD__
-               );
-
-               foreach ( $res as $row ) {
-                       $ids[] = $row->page_id;
-               }
-
-               if ( $ids === array() ) {
-                       return;
-               }
-
-               /**
-                * Do the update
-                * We still need the page_touched condition, in case the row has changed since
-                * the non-locking select above.
-                */
-               $this->mDb->update( 'page', array( 'page_touched' => $now ),
-                       array(
-                               'page_id' => $ids,
-                               'page_touched < ' . $this->mDb->addQuotes( $now )
-                       ), __METHOD__
-               );
-       }
-
-}
index 7a84fed..5f5ca74 100644 (file)
  * so that a lack of error-handling will be explicit.
  */
 class Status {
-       var $ok = true;
-       var $value;
+       /** @var bool */
+       public $ok = true;
+
+       /** @var mixed  */
+       public $value;
 
        /** Counters for batch operations */
-       public $successCount = 0, $failCount = 0;
+       /** @var int */
+       public $successCount = 0;
+
+       /** @var int */
+       public $failCount = 0;
+
        /** Array to indicate which items of the batch operations were successful */
+       /** @var array  */
        public $success = array();
 
-       /*semi-private*/ var $errors = array();
-       /*semi-private*/ var $cleanCallback = false;
+       /** @var array */
+       public $errors = array();
+
+       /** @var callable */
+       public $cleanCallback = false;
 
        /**
         * Factory function for fatal errors
@@ -81,7 +93,7 @@ class Status {
         * @param $ok Boolean: whether the operation completed
         * @param $value Mixed
         */
-       function setResult( $ok, $value = null ) {
+       public function setResult( $ok, $value = null ) {
                $this->ok = $ok;
                $this->value = $value;
        }
@@ -92,7 +104,7 @@ class Status {
         *
         * @return Boolean
         */
-       function isGood() {
+       public function isGood() {
                return $this->ok && !$this->errors;
        }
 
@@ -101,7 +113,7 @@ class Status {
         *
         * @return Boolean
         */
-       function isOK() {
+       public function isOK() {
                return $this->ok;
        }
 
@@ -110,7 +122,7 @@ class Status {
         *
         * @param string|Message $message message name or object
         */
-       function warning( $message /*, parameters... */ ) {
+       public function warning( $message /*, parameters... */ ) {
                $params = array_slice( func_get_args(), 1 );
                $this->errors[] = array(
                        'type' => 'warning',
@@ -124,7 +136,7 @@ class Status {
         *
         * @param string|Message $message message name or object
         */
-       function error( $message /*, parameters... */ ) {
+       public function error( $message /*, parameters... */ ) {
                $params = array_slice( func_get_args(), 1 );
                $this->errors[] = array(
                        'type' => 'error',
@@ -138,7 +150,7 @@ class Status {
         *
         * @param string|Message $message message name or object
         */
-       function fatal( $message /*, parameters... */ ) {
+       public function fatal( $message /*, parameters... */ ) {
                $params = array_slice( func_get_args(), 1 );
                $this->errors[] = array(
                        'type' => 'error',
@@ -150,7 +162,7 @@ class Status {
        /**
         * Sanitize the callback parameter on wakeup, to avoid arbitrary execution.
         */
-       function __wakeup() {
+       public function __wakeup() {
                $this->cleanCallback = false;
        }
 
@@ -177,7 +189,7 @@ class Status {
         * @param string $longContext a long enclosing context message name, for a list
         * @return String
         */
-       function getWikiText( $shortContext = false, $longContext = false ) {
+       public function getWikiText( $shortContext = false, $longContext = false ) {
                if ( count( $this->errors ) == 0 ) {
                        if ( $this->ok ) {
                                $this->fatal( 'internalerror_info',
@@ -188,15 +200,18 @@ class Status {
                        }
                }
                if ( count( $this->errors ) == 1 ) {
-                       $s = $this->getErrorMessage( $this->errors[0] );
+                       $s = $this->getErrorMessage( $this->errors[0] )->plain();
                        if ( $shortContext ) {
                                $s = wfMessage( $shortContext, $s )->plain();
                        } elseif ( $longContext ) {
                                $s = wfMessage( $longContext, "* $s\n" )->plain();
                        }
                } else {
-                       $s = '* ' . implode( "\n* ",
-                               $this->getErrorMessageArray( $this->errors ) ) . "\n";
+                       $errors = $this->getErrorMessageArray( $this->errors );
+                       foreach ( $errors as &$error ) {
+                               $error = $error->plain();
+                       }
+                       $s = '* ' . implode( "\n* ", $errors ) . "\n";
                        if ( $longContext ) {
                                $s = wfMessage( $longContext, $s )->plain();
                        } elseif ( $shortContext ) {
@@ -206,6 +221,56 @@ class Status {
                return $s;
        }
 
+       /**
+        * Get the error list as a Message object
+        *
+        * @param string $shortContext a short enclosing context message name, to
+        *        be used when there is a single error
+        * @param string $longContext a long enclosing context message name, for a list
+        * @return Message
+        */
+       public function getMessage( $shortContext = false, $longContext = false ) {
+               if ( count( $this->errors ) == 0 ) {
+                       if ( $this->ok ) {
+                               $this->fatal( 'internalerror_info',
+                                       __METHOD__ . " called for a good result, this is incorrect\n" );
+                       } else {
+                               $this->fatal( 'internalerror_info',
+                                       __METHOD__ . ": Invalid result object: no error text but not OK\n" );
+                       }
+               }
+               if ( count( $this->errors ) == 1 ) {
+                       $s = $this->getErrorMessage( $this->errors[0] );
+                       if ( $shortContext ) {
+                               $s = wfMessage( $shortContext, $s );
+                       } elseif ( $longContext ) {
+                               $wrapper = new RawMessage( "* \$1\n" );
+                               $wrapper->params( $s )->parse();
+                               $s = wfMessage( $longContext, $wrapper );
+                       }
+               } else {
+                       $msgs = $this->getErrorMessageArray( $this->errors );
+                       $msgCount = count( $msgs );
+
+                       if ( $shortContext ) {
+                               $msgCount++;
+                       }
+
+                       $wrapper = new RawMessage( '* $' . implode( "\n* \$", range( 1, $msgCount ) ) );
+                       $s = $wrapper->params( $msgs )->parse();
+
+                       if ( $longContext ) {
+                               $s = wfMessage( $longContext, $wrapper );
+                       } elseif ( $shortContext ) {
+                               $wrapper = new RawMessage( "\n\$1\n", $wrapper );
+                               $wrapper->parse();
+                               $s = wfMessage( $shortContext, $wrapper );
+                       }
+               }
+
+               return $s;
+       }
+
        /**
         * Return the message for a single error.
         * @param $error Mixed With an array & two values keyed by
@@ -230,7 +295,7 @@ class Status {
                } else {
                        $msg = wfMessage( $error );
                }
-               return $msg->plain();
+               return $msg;
        }
 
        /**
@@ -261,7 +326,7 @@ class Status {
         * @param $other Status Other Status object
         * @param $overwriteValue Boolean: whether to override the "value" member
         */
-       function merge( $other, $overwriteValue = false ) {
+       public function merge( $other, $overwriteValue = false ) {
                $this->errors = array_merge( $this->errors, $other->errors );
                $this->ok = $this->ok && $other->ok;
                if ( $overwriteValue ) {
@@ -277,7 +342,7 @@ class Status {
         * @return array A list in which each entry is an array with a message key as its first element.
         *         The remaining array elements are the message parameters.
         */
-       function getErrorsArray() {
+       public function getErrorsArray() {
                return $this->getStatusArray( "error" );
        }
 
@@ -287,14 +352,13 @@ class Status {
         * @return array A list in which each entry is an array with a message key as its first element.
         *         The remaining array elements are the message parameters.
         */
-       function getWarningsArray() {
+       public function getWarningsArray() {
                return $this->getStatusArray( "warning" );
        }
 
        /**
         * Returns a list of status messages of the given type
         * @param $type String
-        *
         * @return Array
         */
        protected function getStatusArray( $type ) {
@@ -302,7 +366,10 @@ class Status {
                foreach ( $this->errors as $error ) {
                        if ( $error['type'] === $type ) {
                                if ( $error['message'] instanceof Message ) {
-                                       $result[] = array_merge( array( $error['message']->getKey() ), $error['message']->getParams() );
+                                       $result[] = array_merge(
+                                               array( $error['message']->getKey() ),
+                                               $error['message']->getParams()
+                                       );
                                } elseif ( $error['params'] ) {
                                        $result[] = array_merge( array( $error['message'] ), $error['params'] );
                                } else {
@@ -310,6 +377,7 @@ class Status {
                                }
                        }
                }
+
                return $result;
        }
 
@@ -340,7 +408,7 @@ class Status {
         * @param string $msg message name
         * @return Boolean
         */
-       function hasMessage( $msg ) {
+       public function hasMessage( $msg ) {
                foreach ( $this->errors as $error ) {
                        if ( $error['message'] === $msg ) {
                                return true;
@@ -360,7 +428,7 @@ class Status {
         * @param $dest Message|String: Replacement message key or object
         * @return bool Return true if the replacement was done, false otherwise.
         */
-       function replaceMessage( $source, $dest ) {
+       public function replaceMessage( $source, $dest ) {
                $replaced = false;
                foreach ( $this->errors as $index => $error ) {
                        if ( $error['message'] === $source ) {
@@ -371,15 +439,6 @@ class Status {
                return $replaced;
        }
 
-       /**
-        * Backward compatibility function for WikiError -> Status migration
-        *
-        * @return String
-        */
-       public function getMessage() {
-               return $this->getWikiText();
-       }
-
        /**
         * @return mixed
         */
index 1ad643a..ef82705 100644 (file)
@@ -185,8 +185,8 @@ class StreamFile {
                                return 'unknown/unknown';
                        }
                        if ( $wgCheckFileExtensions && $wgStrictFileExtensions
-                               && !UploadBase::checkFileExtensionList( $extList, $wgFileExtensions ) )
-                       {
+                               && !UploadBase::checkFileExtensionList( $extList, $wgFileExtensions )
+                       {
                                return 'unknown/unknown';
                        }
                        if ( $wgVerifyMimeType && in_array( strtolower( $type ), $wgMimeTypeBlacklist ) ) {
diff --git a/includes/StringUtils.php b/includes/StringUtils.php
deleted file mode 100644 (file)
index c1545e6..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-<?php
-/**
- * Methods to play with strings.
- *
- * 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
- */
-
-/**
- * A collection of static methods to play with strings.
- */
-class StringUtils {
-
-       /**
-        * Test whether a string is valid UTF-8.
-        *
-        * The function check for invalid byte sequences, overlong encoding but
-        * not for different normalisations.
-        *
-        * This relies internally on the mbstring function mb_check_encoding()
-        * hardcoded to check against UTF-8. Whenever the function is not available
-        * we fallback to a pure PHP implementation. Setting $disableMbstring to
-        * true will skip the use of mb_check_encoding, this is mostly intended for
-        * unit testing our internal implementation.
-        *
-        * @since 1.21
-        * @note In MediaWiki 1.21, this function did not provide proper UTF-8 validation.
-        * In particular, the pure PHP code path did not in fact check for overlong forms.
-        * Beware of this when backporting code to that version of MediaWiki.
-        *
-        * @param string $value String to check
-        * @param boolean $disableMbstring Whether to use the pure PHP
-        * implementation instead of trying mb_check_encoding. Intended for unit
-        * testing. Default: false
-        *
-        * @return boolean Whether the given $value is a valid UTF-8 encoded string
-        */
-       static function isUtf8( $value, $disableMbstring = false ) {
-               $value = (string)$value;
-
-               // If the mbstring extension is loaded, use it. However, before PHP 5.4, values above
-               // U+10FFFF are incorrectly allowed, so we have to check for them separately.
-               if ( !$disableMbstring && function_exists( 'mb_check_encoding' ) ) {
-                       static $newPHP;
-                       if ( $newPHP === null ) {
-                               $newPHP = !mb_check_encoding( "\xf4\x90\x80\x80", 'UTF-8' );
-                       }
-
-                       return mb_check_encoding( $value, 'UTF-8' ) &&
-                               ( $newPHP || preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $value ) === 0 );
-               }
-
-               if ( preg_match( "/[\x80-\xff]/S", $value ) === 0 ) {
-                       // String contains only ASCII characters, has to be valid
-                       return true;
-               }
-
-               // PCRE implements repetition using recursion; to avoid a stack overflow (and segfault)
-               // for large input, we check for invalid sequences (<= 5 bytes) rather than valid
-               // sequences, which can be as long as the input string is. Multiple short regexes are
-               // used rather than a single long regex for performance.
-               static $regexes;
-               if ( $regexes === null ) {
-                       $cont = "[\x80-\xbf]";
-                       $after = "(?!$cont)"; // "(?:[^\x80-\xbf]|$)" would work here
-                       $regexes = array(
-                               // Continuation byte at the start
-                               "/^$cont/",
-
-                               // ASCII byte followed by a continuation byte
-                               "/[\\x00-\x7f]$cont/S",
-
-                               // Illegal byte
-                               "/[\xc0\xc1\xf5-\xff]/S",
-
-                               // Invalid 2-byte sequence, or valid one then an extra continuation byte
-                               "/[\xc2-\xdf](?!$cont$after)/S",
-
-                               // Invalid 3-byte sequence, or valid one then an extra continuation byte
-                               "/\xe0(?![\xa0-\xbf]$cont$after)/",
-                               "/[\xe1-\xec\xee\xef](?!$cont{2}$after)/S",
-                               "/\xed(?![\x80-\x9f]$cont$after)/",
-
-                               // Invalid 4-byte sequence, or valid one then an extra continuation byte
-                               "/\xf0(?![\x90-\xbf]$cont{2}$after)/",
-                               "/[\xf1-\xf3](?!$cont{3}$after)/S",
-                               "/\xf4(?![\x80-\x8f]$cont{2}$after)/",
-                       );
-               }
-
-               foreach ( $regexes as $regex ) {
-                       if ( preg_match( $regex, $value ) !== 0 ) {
-                               return false;
-                       }
-               }
-               return true;
-       }
-
-       /**
-        * Perform an operation equivalent to
-        *
-        *     preg_replace( "!$startDelim(.*?)$endDelim!", $replace, $subject );
-        *
-        * except that it's worst-case O(N) instead of O(N^2)
-        *
-        * Compared to delimiterReplace(), this implementation is fast but memory-
-        * hungry and inflexible. The memory requirements are such that I don't
-        * recommend using it on anything but guaranteed small chunks of text.
-        *
-        * @param $startDelim
-        * @param $endDelim
-        * @param $replace
-        * @param $subject
-        *
-        * @return string
-        */
-       static function hungryDelimiterReplace( $startDelim, $endDelim, $replace, $subject ) {
-               $segments = explode( $startDelim, $subject );
-               $output = array_shift( $segments );
-               foreach ( $segments as $s ) {
-                       $endDelimPos = strpos( $s, $endDelim );
-                       if ( $endDelimPos === false ) {
-                               $output .= $startDelim . $s;
-                       } else {
-                               $output .= $replace . substr( $s, $endDelimPos + strlen( $endDelim ) );
-                       }
-               }
-               return $output;
-       }
-
-       /**
-        * Perform an operation equivalent to
-        *
-        *   preg_replace_callback( "!$startDelim(.*)$endDelim!s$flags", $callback, $subject )
-        *
-        * This implementation is slower than hungryDelimiterReplace but uses far less
-        * memory. The delimiters are literal strings, not regular expressions.
-        *
-        * If the start delimiter ends with an initial substring of the end delimiter,
-        * e.g. in the case of C-style comments, the behavior differs from the model
-        * regex. In this implementation, the end must share no characters with the
-        * start, so e.g. /*\/ is not considered to be both the start and end of a
-        * comment. /*\/xy/*\/ is considered to be a single comment with contents /xy/.
-        *
-        * @param string $startDelim start delimiter
-        * @param string $endDelim end delimiter
-        * @param $callback Callback: function to call on each match
-        * @param $subject String
-        * @param string $flags regular expression flags
-        * @throws MWException
-        * @return string
-        */
-       static function delimiterReplaceCallback( $startDelim, $endDelim, $callback, $subject, $flags = '' ) {
-               $inputPos = 0;
-               $outputPos = 0;
-               $output = '';
-               $foundStart = false;
-               $encStart = preg_quote( $startDelim, '!' );
-               $encEnd = preg_quote( $endDelim, '!' );
-               $strcmp = strpos( $flags, 'i' ) === false ? 'strcmp' : 'strcasecmp';
-               $endLength = strlen( $endDelim );
-               $m = array();
-
-               while ( $inputPos < strlen( $subject ) &&
-                       preg_match( "!($encStart)|($encEnd)!S$flags", $subject, $m, PREG_OFFSET_CAPTURE, $inputPos ) )
-               {
-                       $tokenOffset = $m[0][1];
-                       if ( $m[1][0] != '' ) {
-                               if ( $foundStart &&
-                                       $strcmp( $endDelim, substr( $subject, $tokenOffset, $endLength ) ) == 0 )
-                               {
-                                       # An end match is present at the same location
-                                       $tokenType = 'end';
-                                       $tokenLength = $endLength;
-                               } else {
-                                       $tokenType = 'start';
-                                       $tokenLength = strlen( $m[0][0] );
-                               }
-                       } elseif ( $m[2][0] != '' ) {
-                               $tokenType = 'end';
-                               $tokenLength = strlen( $m[0][0] );
-                       } else {
-                               throw new MWException( 'Invalid delimiter given to ' . __METHOD__ );
-                       }
-
-                       if ( $tokenType == 'start' ) {
-                               # Only move the start position if we haven't already found a start
-                               # This means that START START END matches outer pair
-                               if ( !$foundStart ) {
-                                       # Found start
-                                       $inputPos = $tokenOffset + $tokenLength;
-                                       # Write out the non-matching section
-                                       $output .= substr( $subject, $outputPos, $tokenOffset - $outputPos );
-                                       $outputPos = $tokenOffset;
-                                       $contentPos = $inputPos;
-                                       $foundStart = true;
-                               } else {
-                                       # Move the input position past the *first character* of START,
-                                       # to protect against missing END when it overlaps with START
-                                       $inputPos = $tokenOffset + 1;
-                               }
-                       } elseif ( $tokenType == 'end' ) {
-                               if ( $foundStart ) {
-                                       # Found match
-                                       $output .= call_user_func( $callback, array(
-                                               substr( $subject, $outputPos, $tokenOffset + $tokenLength - $outputPos ),
-                                               substr( $subject, $contentPos, $tokenOffset - $contentPos )
-                                       ));
-                                       $foundStart = false;
-                               } else {
-                                       # Non-matching end, write it out
-                                       $output .= substr( $subject, $inputPos, $tokenOffset + $tokenLength - $outputPos );
-                               }
-                               $inputPos = $outputPos = $tokenOffset + $tokenLength;
-                       } else {
-                               throw new MWException( 'Invalid delimiter given to ' . __METHOD__ );
-                       }
-               }
-               if ( $outputPos < strlen( $subject ) ) {
-                       $output .= substr( $subject, $outputPos );
-               }
-               return $output;
-       }
-
-       /**
-        * Perform an operation equivalent to
-        *
-        *   preg_replace( "!$startDelim(.*)$endDelim!$flags", $replace, $subject )
-        *
-        * @param string $startDelim start delimiter regular expression
-        * @param string $endDelim end delimiter regular expression
-        * @param string $replace replacement string. May contain $1, which will be
-        *                 replaced by the text between the delimiters
-        * @param string $subject to search
-        * @param string $flags regular expression flags
-        * @return String: The string with the matches replaced
-        */
-       static function delimiterReplace( $startDelim, $endDelim, $replace, $subject, $flags = '' ) {
-               $replacer = new RegexlikeReplacer( $replace );
-               return self::delimiterReplaceCallback( $startDelim, $endDelim,
-                       $replacer->cb(), $subject, $flags );
-       }
-
-       /**
-        * More or less "markup-safe" explode()
-        * Ignores any instances of the separator inside <...>
-        * @param string $separator
-        * @param string $text
-        * @return array
-        */
-       static function explodeMarkup( $separator, $text ) {
-               $placeholder = "\x00";
-
-               // Remove placeholder instances
-               $text = str_replace( $placeholder, '', $text );
-
-               // Replace instances of the separator inside HTML-like tags with the placeholder
-               $replacer = new DoubleReplacer( $separator, $placeholder );
-               $cleaned = StringUtils::delimiterReplaceCallback( '<', '>', $replacer->cb(), $text );
-
-               // Explode, then put the replaced separators back in
-               $items = explode( $separator, $cleaned );
-               foreach ( $items as $i => $str ) {
-                       $items[$i] = str_replace( $placeholder, $separator, $str );
-               }
-
-               return $items;
-       }
-
-       /**
-        * Escape a string to make it suitable for inclusion in a preg_replace()
-        * replacement parameter.
-        *
-        * @param string $string
-        * @return string
-        */
-       static function escapeRegexReplacement( $string ) {
-               $string = str_replace( '\\', '\\\\', $string );
-               $string = str_replace( '$', '\\$', $string );
-               return $string;
-       }
-
-       /**
-        * Workalike for explode() with limited memory usage.
-        * Returns an Iterator
-        * @param string $separator
-        * @param string $subject
-        * @return ArrayIterator|ExplodeIterator
-        */
-       static function explode( $separator, $subject ) {
-               if ( substr_count( $subject, $separator ) > 1000 ) {
-                       return new ExplodeIterator( $separator, $subject );
-               } else {
-                       return new ArrayIterator( explode( $separator, $subject ) );
-               }
-       }
-}
-
-/**
- * Base class for "replacers", objects used in preg_replace_callback() and
- * StringUtils::delimiterReplaceCallback()
- */
-class Replacer {
-
-       /**
-        * @return array
-        */
-       function cb() {
-               return array( &$this, 'replace' );
-       }
-}
-
-/**
- * Class to replace regex matches with a string similar to that used in preg_replace()
- */
-class RegexlikeReplacer extends Replacer {
-       var $r;
-
-       /**
-        * @param string $r
-        */
-       function __construct( $r ) {
-               $this->r = $r;
-       }
-
-       /**
-        * @param array $matches
-        * @return string
-        */
-       function replace( $matches ) {
-               $pairs = array();
-               foreach ( $matches as $i => $match ) {
-                       $pairs["\$$i"] = $match;
-               }
-               return strtr( $this->r, $pairs );
-       }
-
-}
-
-/**
- * Class to perform secondary replacement within each replacement string
- */
-class DoubleReplacer extends Replacer {
-
-       /**
-        * @param $from
-        * @param $to
-        * @param int $index
-        */
-       function __construct( $from, $to, $index = 0 ) {
-               $this->from = $from;
-               $this->to = $to;
-               $this->index = $index;
-       }
-
-       /**
-        * @param array $matches
-        * @return mixed
-        */
-       function replace( $matches ) {
-               return str_replace( $this->from, $this->to, $matches[$this->index] );
-       }
-}
-
-/**
- * Class to perform replacement based on a simple hashtable lookup
- */
-class HashtableReplacer extends Replacer {
-       var $table, $index;
-
-       /**
-        * @param $table
-        * @param int $index
-        */
-       function __construct( $table, $index = 0 ) {
-               $this->table = $table;
-               $this->index = $index;
-       }
-
-       /**
-        * @param array $matches
-        * @return mixed
-        */
-       function replace( $matches ) {
-               return $this->table[$matches[$this->index]];
-       }
-}
-
-/**
- * Replacement array for FSS with fallback to strtr()
- * Supports lazy initialisation of FSS resource
- */
-class ReplacementArray {
-       /*mostly private*/ var $data = false;
-       /*mostly private*/ var $fss = false;
-
-       /**
-        * Create an object with the specified replacement array
-        * The array should have the same form as the replacement array for strtr()
-        * @param array $data
-        */
-       function __construct( $data = array() ) {
-               $this->data = $data;
-       }
-
-       /**
-        * @return array
-        */
-       function __sleep() {
-               return array( 'data' );
-       }
-
-       function __wakeup() {
-               $this->fss = false;
-       }
-
-       /**
-        * Set the whole replacement array at once
-        * @param array $data
-        */
-       function setArray( $data ) {
-               $this->data = $data;
-               $this->fss = false;
-       }
-
-       /**
-        * @return array|bool
-        */
-       function getArray() {
-               return $this->data;
-       }
-
-       /**
-        * Set an element of the replacement array
-        * @param string $from
-        * @param string $to
-        */
-       function setPair( $from, $to ) {
-               $this->data[$from] = $to;
-               $this->fss = false;
-       }
-
-       /**
-        * @param array $data
-        */
-       function mergeArray( $data ) {
-               $this->data = array_merge( $this->data, $data );
-               $this->fss = false;
-       }
-
-       /**
-        * @param ReplacementArray $other
-        */
-       function merge( $other ) {
-               $this->data = array_merge( $this->data, $other->data );
-               $this->fss = false;
-       }
-
-       /**
-        * @param string $from
-        */
-       function removePair( $from ) {
-               unset( $this->data[$from] );
-               $this->fss = false;
-       }
-
-       /**
-        * @param array $data
-        */
-       function removeArray( $data ) {
-               foreach ( $data as $from => $to ) {
-                       $this->removePair( $from );
-               }
-               $this->fss = false;
-       }
-
-       /**
-        * @param string $subject
-        * @return string
-        */
-       function replace( $subject ) {
-               if ( function_exists( 'fss_prep_replace' ) ) {
-                       wfProfileIn( __METHOD__ . '-fss' );
-                       if ( $this->fss === false ) {
-                               $this->fss = fss_prep_replace( $this->data );
-                       }
-                       $result = fss_exec_replace( $this->fss, $subject );
-                       wfProfileOut( __METHOD__ . '-fss' );
-               } else {
-                       wfProfileIn( __METHOD__ . '-strtr' );
-                       $result = strtr( $subject, $this->data );
-                       wfProfileOut( __METHOD__ . '-strtr' );
-               }
-               return $result;
-       }
-}
-
-/**
- * An iterator which works exactly like:
- *
- * foreach ( explode( $delim, $s ) as $element ) {
- *    ...
- * }
- *
- * Except it doesn't use 193 byte per element
- */
-class ExplodeIterator implements Iterator {
-       // The subject string
-       var $subject, $subjectLength;
-
-       // The delimiter
-       var $delim, $delimLength;
-
-       // The position of the start of the line
-       var $curPos;
-
-       // The position after the end of the next delimiter
-       var $endPos;
-
-       // The current token
-       var $current;
-
-       /**
-        * Construct a DelimIterator
-        * @param string $delim
-        * @param string $subject
-        */
-       function __construct( $delim, $subject ) {
-               $this->subject = $subject;
-               $this->delim = $delim;
-
-               // Micro-optimisation (theoretical)
-               $this->subjectLength = strlen( $subject );
-               $this->delimLength = strlen( $delim );
-
-               $this->rewind();
-       }
-
-       function rewind() {
-               $this->curPos = 0;
-               $this->endPos = strpos( $this->subject, $this->delim );
-               $this->refreshCurrent();
-       }
-
-       function refreshCurrent() {
-               if ( $this->curPos === false ) {
-                       $this->current = false;
-               } elseif ( $this->curPos >= $this->subjectLength ) {
-                       $this->current = '';
-               } elseif ( $this->endPos === false ) {
-                       $this->current = substr( $this->subject, $this->curPos );
-               } else {
-                       $this->current = substr( $this->subject, $this->curPos, $this->endPos - $this->curPos );
-               }
-       }
-
-       function current() {
-               return $this->current;
-       }
-
-       /**
-        * @return int|bool Current position or boolean false if invalid
-        */
-       function key() {
-               return $this->curPos;
-       }
-
-       /**
-        * @return string
-        */
-       function next() {
-               if ( $this->endPos === false ) {
-                       $this->curPos = false;
-               } else {
-                       $this->curPos = $this->endPos + $this->delimLength;
-                       if ( $this->curPos >= $this->subjectLength ) {
-                               $this->endPos = false;
-                       } else {
-                               $this->endPos = strpos( $this->subject, $this->delim, $this->curPos );
-                       }
-               }
-               $this->refreshCurrent();
-               return $this->current;
-       }
-
-       /**
-        * @return bool
-        */
-       function valid() {
-               return $this->curPos !== false;
-       }
-}
index edcd6a8..c1c6455 100644 (file)
@@ -93,9 +93,9 @@ class MWTimestamp {
                        # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6
                        $strtime = preg_replace( '/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
                                        str_replace( '+00:00', 'UTC', $ts ) );
-               } elseif ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
+               } elseif ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z?$/', $ts, $da ) ) {
                        # TS_ISO_8601
-               } elseif ( preg_match( '/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
+               } elseif ( preg_match( '/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(?:\.*\d*)?Z?$/', $ts, $da ) ) {
                        #TS_ISO_8601_BASIC
                } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d*[\+\- ](\d\d)$/', $ts, $da ) ) {
                        # TS_POSTGRES
index 21872e4..2961500 100644 (file)
@@ -86,6 +86,7 @@ class Title {
        var $mRedirect = null;            // /< Is the article at this title a redirect?
        var $mNotificationTimestamp = array(); // /< Associative array of user ID -> timestamp/false
        var $mHasSubpage;                 // /< Whether a page has any subpages
+       private $mPageLanguage = false;   // /< The (string) language code of the page's language and content code.
        // @}
 
        /**
@@ -272,7 +273,7 @@ class Title {
        /**
         * Make a Title object from a DB row
         *
-        * @param $row Object database row (needs at least page_title,page_namespace)
+        * @param stdClass $row Object database row (needs at least page_title,page_namespace)
         * @return Title corresponding Title
         */
        public static function newFromRow( $row ) {
@@ -285,7 +286,7 @@ class Title {
         * Load Title object fields from a DB row.
         * If false is given, the title will be treated as non-existing.
         *
-        * @param $row Object|bool database row
+        * @param $row stdClass|bool database row
         */
        public function loadFromRow( $row ) {
                if ( $row ) { // page found
@@ -1547,9 +1548,9 @@ class Title {
                                $url = false;
                                $matches = array();
 
-                               if ( !empty( $wgActionPaths ) &&
-                                       preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches ) )
-                               {
+                               if ( !empty( $wgActionPaths )
+                                       && preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches )
+                               {
                                        $action = urldecode( $matches[2] );
                                        if ( isset( $wgActionPaths[$action] ) ) {
                                                $query = $matches[1];
@@ -1563,12 +1564,12 @@ class Title {
                                        }
                                }
 
-                               if ( $url === false &&
-                                       $wgVariantArticlePath &&
-                                       $wgContLang->getCode() === $this->getPageLanguage()->getCode() &&
-                                       $this->getPageLanguage()->hasVariants() &&
-                                       preg_match( '/^variant=([^&]*)$/', $query, $matches ) )
-                               {
+                               if ( $url === false
+                                       && $wgVariantArticlePath
+                                       && $wgContLang->getCode() === $this->getPageLanguage()->getCode()
+                                       && $this->getPageLanguage()->hasVariants()
+                                       && preg_match( '/^variant=([^&]*)$/', $query, $matches )
+                               {
                                        $variant = urldecode( $matches[1] );
                                        if ( $this->getPageLanguage()->hasVariant( $variant ) ) {
                                                // Only do the variant replacement if the given variant is a valid
@@ -2124,9 +2125,9 @@ class Title {
                                if ( $title_protection['pt_create_perm'] == 'autoconfirmed' ) {
                                        $title_protection['pt_create_perm'] = 'editsemiprotected'; // B/C
                                }
-                               if ( $title_protection['pt_create_perm'] == '' ||
-                                       !$user->isAllowed( $title_protection['pt_create_perm'] ) )
-                               {
+                               if ( $title_protection['pt_create_perm'] == ''
+                                       || !$user->isAllowed( $title_protection['pt_create_perm'] )
+                               {
                                        $errors[] = array( 'titleprotected', User::whoIs( $title_protection['pt_user'] ), $title_protection['pt_reason'] );
                                }
                        }
@@ -2147,8 +2148,8 @@ class Title {
                        }
                } elseif ( $action == 'delete' ) {
                        if ( $doExpensiveQueries && $wgDeleteRevisionsLimit
-                               && !$this->userCan( 'bigdelete', $user ) && $this->isBigDeletion() )
-                       {
+                               && !$this->userCan( 'bigdelete', $user ) && $this->isBigDeletion()
+                       {
                                $errors[] = array( 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) );
                        }
                }
@@ -3110,6 +3111,7 @@ class Title {
                $this->mLatestID = false;
                $this->mContentModel = false;
                $this->mEstimateRevisions = null;
+               $this->mPageLanguage = false;
        }
 
        /**
@@ -3214,8 +3216,8 @@ class Title {
 
                                        # Redundant interwiki prefix to the local wiki
                                        if ( $wgLocalInterwiki !== false
-                                               && 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) )
-                                       {
+                                               && 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki )
+                                       {
                                                if ( $dbkey == '' ) {
                                                        # Can't have an empty self-link
                                                        return false;
@@ -3993,9 +3995,9 @@ class Title {
                        // We don't know whether this function was called before
                        // or after moving the root page, so check both
                        // $this and $nt
-                       if ( $oldSubpage->getArticleID() == $this->getArticleID() ||
-                                       $oldSubpage->getArticleID() == $nt->getArticleID() )
-                       {
+                       if ( $oldSubpage->getArticleID() == $this->getArticleID()
+                               || $oldSubpage->getArticleID() == $nt->getArticleID()
+                       {
                                // When moving a page to a subpage of itself,
                                // don't move it twice
                                continue;
@@ -4812,18 +4814,26 @@ class Title {
         * @return Language
         */
        public function getPageLanguage() {
-               global $wgLang;
+               global $wgLang, $wgLanguageCode;
+               wfProfileIn( __METHOD__ );
                if ( $this->isSpecialPage() ) {
                        // special pages are in the user language
+                       wfProfileOut( __METHOD__ );
                        return $wgLang;
                }
 
-               //TODO: use the LinkCache to cache this! Note that this may depend on user settings, so the cache should be only per-request.
-               //NOTE: ContentHandler::getPageLanguage() may need to load the content to determine the page language!
-               $contentHandler = ContentHandler::getForTitle( $this );
-               $pageLang = $contentHandler->getPageLanguage( $this );
-
-               return wfGetLangObj( $pageLang );
+               if ( !$this->mPageLanguage || $this->mPageLanguage[1] !== $wgLanguageCode ) {
+                       // Note that this may depend on user settings, so the cache should be only per-request.
+                       // NOTE: ContentHandler::getPageLanguage() may need to load the content to determine the page language!
+                       // Checking $wgLanguageCode hasn't changed for the benefit of unit tests.
+                       $contentHandler = ContentHandler::getForTitle( $this );
+                       $langObj = wfGetLangObj( $contentHandler->getPageLanguage( $this ) );
+                       $this->mPageLanguage = array( $langObj->getCode(), $wgLanguageCode );
+               } else {
+                       $langObj = wfGetLangObj( $this->mPageLanguage[0] );
+               }
+               wfProfileOut( __METHOD__ );
+               return $langObj;
        }
 
        /**
diff --git a/includes/UIDGenerator.php b/includes/UIDGenerator.php
deleted file mode 100644 (file)
index 963e51a..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-<?php
-/**
- * This file deals with UID generation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @author Aaron Schulz
- */
-
-/**
- * Class for getting statistically unique IDs
- *
- * @since 1.21
- */
-class UIDGenerator {
-       /** @var UIDGenerator */
-       protected static $instance = null;
-
-       protected $nodeId32; // string; node ID in binary (32 bits)
-       protected $nodeId48; // string; node ID in binary (48 bits)
-
-       protected $lockFile88; // string; local file path
-       protected $lockFile128; // string; local file path
-
-       /** @var Array */
-       protected $fileHandles = array(); // cache file handles
-
-       const QUICK_RAND = 1; // get randomness from fast and insecure sources
-
-       protected function __construct() {
-               $idFile = wfTempDir() . '/mw-' . __CLASS__ . '-UID-nodeid';
-               $nodeId = is_file( $idFile ) ? file_get_contents( $idFile ) : '';
-               // Try to get some ID that uniquely identifies this machine (RFC 4122)...
-               if ( !preg_match( '/^[0-9a-f]{12}$/i', $nodeId ) ) {
-                       wfSuppressWarnings();
-                       if ( wfIsWindows() ) {
-                               // http://technet.microsoft.com/en-us/library/bb490913.aspx
-                               $csv = trim( wfShellExec( 'getmac /NH /FO CSV' ) );
-                               $line = substr( $csv, 0, strcspn( $csv, "\n" ) );
-                               $info = str_getcsv( $line );
-                               $nodeId = isset( $info[0] ) ? str_replace( '-', '', $info[0] ) : '';
-                       } elseif ( is_executable( '/sbin/ifconfig' ) ) { // Linux/BSD/Solaris/OS X
-                               // See http://linux.die.net/man/8/ifconfig
-                               $m = array();
-                               preg_match( '/\s([0-9a-f]{2}(:[0-9a-f]{2}){5})\s/',
-                                       wfShellExec( '/sbin/ifconfig -a' ), $m );
-                               $nodeId = isset( $m[1] ) ? str_replace( ':', '', $m[1] ) : '';
-                       }
-                       wfRestoreWarnings();
-                       if ( !preg_match( '/^[0-9a-f]{12}$/i', $nodeId ) ) {
-                               $nodeId = MWCryptRand::generateHex( 12, true );
-                               $nodeId[1] = dechex( hexdec( $nodeId[1] ) | 0x1 ); // set multicast bit
-                       }
-                       file_put_contents( $idFile, $nodeId ); // cache
-               }
-               $this->nodeId32 = wfBaseConvert( substr( sha1( $nodeId ), 0, 8 ), 16, 2, 32 );
-               $this->nodeId48 = wfBaseConvert( $nodeId, 16, 2, 48 );
-               // If different processes run as different users, they may have different temp dirs.
-               // This is dealt with by initializing the clock sequence number and counters randomly.
-               $this->lockFile88 = wfTempDir() . '/mw-' . __CLASS__ . '-UID-88';
-               $this->lockFile128 = wfTempDir() . '/mw-' . __CLASS__ . '-UID-128';
-       }
-
-       /**
-        * @return UIDGenerator
-        */
-       protected static function singleton() {
-               if ( self::$instance === null ) {
-                       self::$instance = new self();
-               }
-               return self::$instance;
-       }
-
-       /**
-        * Get a statistically unique 88-bit unsigned integer ID string.
-        * The bits of the UID are prefixed with the time (down to the millisecond).
-        *
-        * These IDs are suitable as values for the shard key of distributed data.
-        * If a column uses these as values, it should be declared UNIQUE to handle collisions.
-        * New rows almost always have higher UIDs, which makes B-TREE updates on INSERT fast.
-        * They can also be stored "DECIMAL(27) UNSIGNED" or BINARY(11) in MySQL.
-        *
-        * UID generation is serialized on each server (as the node ID is for the whole machine).
-        *
-        * @param $base integer Specifies a base other than 10
-        * @return string Number
-        * @throws MWException
-        */
-       public static function newTimestampedUID88( $base = 10 ) {
-               if ( !is_integer( $base ) || $base > 36 || $base < 2 ) {
-                       throw new MWException( "Base must an integer be between 2 and 36" );
-               }
-               $gen = self::singleton();
-               $time = $gen->getTimestampAndDelay( 'lockFile88', 1, 1024 );
-               return wfBaseConvert( $gen->getTimestampedID88( $time ), 2, $base );
-       }
-
-       /**
-        * @param array $time (UIDGenerator::millitime(), clock sequence)
-        * @return string 88 bits
-        */
-       protected function getTimestampedID88( array $info ) {
-               list( $time, $counter ) = $info;
-               // Take the 46 MSBs of "milliseconds since epoch"
-               $id_bin = $this->millisecondsSinceEpochBinary( $time );
-               // Add a 10 bit counter resulting in 56 bits total
-               $id_bin .= str_pad( decbin( $counter ), 10, '0', STR_PAD_LEFT );
-               // Add the 32 bit node ID resulting in 88 bits total
-               $id_bin .= $this->nodeId32;
-               // Convert to a 1-27 digit integer string
-               if ( strlen( $id_bin ) !== 88 ) {
-                       throw new MWException( "Detected overflow for millisecond timestamp." );
-               }
-               return $id_bin;
-       }
-
-       /**
-        * Get a statistically unique 128-bit unsigned integer ID string.
-        * The bits of the UID are prefixed with the time (down to the millisecond).
-        *
-        * These IDs are suitable as globally unique IDs, without any enforced uniqueness.
-        * New rows almost always have higher UIDs, which makes B-TREE updates on INSERT fast.
-        * They can also be stored as "DECIMAL(39) UNSIGNED" or BINARY(16) in MySQL.
-        *
-        * UID generation is serialized on each server (as the node ID is for the whole machine).
-        *
-        * @param $base integer Specifies a base other than 10
-        * @return string Number
-        * @throws MWException
-        */
-       public static function newTimestampedUID128( $base = 10 ) {
-               if ( !is_integer( $base ) || $base > 36 || $base < 2 ) {
-                       throw new MWException( "Base must be an integer between 2 and 36" );
-               }
-               $gen = self::singleton();
-               $time = $gen->getTimestampAndDelay( 'lockFile128', 16384, 1048576 );
-               return wfBaseConvert( $gen->getTimestampedID128( $time ), 2, $base );
-       }
-
-       /**
-        * @param array $info (UIDGenerator::millitime(), counter, clock sequence)
-        * @return string 128 bits
-        */
-       protected function getTimestampedID128( array $info ) {
-               list( $time, $counter, $clkSeq ) = $info;
-               // Take the 46 MSBs of "milliseconds since epoch"
-               $id_bin = $this->millisecondsSinceEpochBinary( $time );
-               // Add a 20 bit counter resulting in 66 bits total
-               $id_bin .= str_pad( decbin( $counter ), 20, '0', STR_PAD_LEFT );
-               // Add a 14 bit clock sequence number resulting in 80 bits total
-               $id_bin .= str_pad( decbin( $clkSeq ), 14, '0', STR_PAD_LEFT );
-               // Add the 48 bit node ID resulting in 128 bits total
-               $id_bin .= $this->nodeId48;
-               // Convert to a 1-39 digit integer string
-               if ( strlen( $id_bin ) !== 128 ) {
-                       throw new MWException( "Detected overflow for millisecond timestamp." );
-               }
-               return $id_bin;
-       }
-
-       /**
-        * Return an RFC4122 compliant v4 UUID
-        *
-        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
-        * @return string
-        * @throws MWException
-        */
-       public static function newUUIDv4( $flags = 0 ) {
-               $hex = ( $flags & self::QUICK_RAND )
-                       ? wfRandomString( 31 )
-                       : MWCryptRand::generateHex( 31 );
-
-               return sprintf( '%s-%s-%s-%s-%s',
-                       // "time_low" (32 bits)
-                       substr( $hex, 0, 8 ),
-                       // "time_mid" (16 bits)
-                       substr( $hex, 8, 4 ),
-                       // "time_hi_and_version" (16 bits)
-                       '4' . substr( $hex, 12, 3 ),
-                       // "clk_seq_hi_res (8 bits, variant is binary 10x) and "clk_seq_low" (8 bits)
-                       dechex( 0x8 | ( hexdec( $hex[15] ) & 0x3 ) ) . $hex[16] . substr( $hex, 17, 2 ),
-                       // "node" (48 bits)
-                       substr( $hex, 19, 12 )
-               );
-       }
-
-       /**
-        * Return an RFC4122 compliant v4 UUID
-        *
-        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
-        * @return string 32 hex characters with no hyphens
-        * @throws MWException
-        */
-       public static function newRawUUIDv4( $flags = 0 ) {
-               return str_replace( '-', '', self::newUUIDv4( $flags ) );
-       }
-
-       /**
-        * Get a (time,counter,clock sequence) where (time,counter) is higher
-        * than any previous (time,counter) value for the given clock sequence.
-        * This is useful for making UIDs sequential on a per-node bases.
-        *
-        * @param string $lockFile Name of a local lock file
-        * @param $clockSeqSize integer The number of possible clock sequence values
-        * @param $counterSize integer The number of possible counter values
-        * @return Array (result of UIDGenerator::millitime(), counter, clock sequence)
-        * @throws MWException
-        */
-       protected function getTimestampAndDelay( $lockFile, $clockSeqSize, $counterSize ) {
-               // Get the UID lock file handle
-               if ( isset( $this->fileHandles[$lockFile] ) ) {
-                       $handle = $this->fileHandles[$lockFile];
-               } else {
-                       $handle = fopen( $this->$lockFile, 'cb+' );
-                       $this->fileHandles[$lockFile] = $handle ?: null; // cache
-               }
-               // Acquire the UID lock file
-               if ( $handle === false ) {
-                       throw new MWException( "Could not open '{$this->$lockFile}'." );
-               } elseif ( !flock( $handle, LOCK_EX ) ) {
-                       throw new MWException( "Could not acquire '{$this->$lockFile}'." );
-               }
-               // Get the current timestamp, clock sequence number, last time, and counter
-               rewind( $handle );
-               $data = explode( ' ', fgets( $handle ) ); // "<clk seq> <sec> <msec> <counter> <offset>"
-               $clockChanged = false; // clock set back significantly?
-               if ( count( $data ) == 5 ) { // last UID info already initialized
-                       $clkSeq = (int)$data[0] % $clockSeqSize;
-                       $prevTime = array( (int)$data[1], (int)$data[2] );
-                       $offset = (int)$data[4] % $counterSize; // random counter offset
-                       $counter = 0; // counter for UIDs with the same timestamp
-                       // Delay until the clock reaches the time of the last ID.
-                       // This detects any microtime() drift among processes.
-                       $time = $this->timeWaitUntil( $prevTime );
-                       if ( !$time ) { // too long to delay?
-                               $clockChanged = true; // bump clock sequence number
-                               $time = self::millitime();
-                       } elseif ( $time == $prevTime ) {
-                               // Bump the counter if there are timestamp collisions
-                               $counter = (int)$data[3] % $counterSize;
-                               if ( ++$counter >= $counterSize ) { // sanity (starts at 0)
-                                       flock( $handle, LOCK_UN ); // abort
-                                       throw new MWException( "Counter overflow for timestamp value." );
-                               }
-                       }
-               } else { // last UID info not initialized
-                       $clkSeq = mt_rand( 0, $clockSeqSize - 1 );
-                       $counter = 0;
-                       $offset = mt_rand( 0, $counterSize - 1 );
-                       $time = self::millitime();
-               }
-               // microtime() and gettimeofday() can drift from time() at least on Windows.
-               // The drift is immediate for processes running while the system clock changes.
-               // time() does not have this problem. See https://bugs.php.net/bug.php?id=42659.
-               if ( abs( time() - $time[0] ) >= 2 ) {
-                       // We don't want processes using too high or low timestamps to avoid duplicate
-                       // UIDs and clock sequence number churn. This process should just be restarted.
-                       flock( $handle, LOCK_UN ); // abort
-                       throw new MWException( "Process clock is outdated or drifted." );
-               }
-               // If microtime() is synced and a clock change was detected, then the clock went back
-               if ( $clockChanged ) {
-                       // Bump the clock sequence number and also randomize the counter offset,
-                       // which is useful for UIDs that do not include the clock sequence number.
-                       $clkSeq = ( $clkSeq + 1 ) % $clockSeqSize;
-                       $offset = mt_rand( 0, $counterSize - 1 );
-                       trigger_error( "Clock was set back; sequence number incremented." );
-               }
-               // Update the (clock sequence number, timestamp, counter)
-               ftruncate( $handle, 0 );
-               rewind( $handle );
-               fwrite( $handle, "{$clkSeq} {$time[0]} {$time[1]} {$counter} {$offset}" );
-               fflush( $handle );
-               // Release the UID lock file
-               flock( $handle, LOCK_UN );
-
-               return array( $time, ( $counter + $offset ) % $counterSize, $clkSeq );
-       }
-
-       /**
-        * Wait till the current timestamp reaches $time and return the current
-        * timestamp. This returns false if it would have to wait more than 10ms.
-        *
-        * @param array $time Result of UIDGenerator::millitime()
-        * @return Array|bool UIDGenerator::millitime() result or false
-        */
-       protected function timeWaitUntil( array $time ) {
-               do {
-                       $ct = self::millitime();
-                       if ( $ct >= $time ) { // http://php.net/manual/en/language.operators.comparison.php
-                               return $ct; // current timestamp is higher than $time
-                       }
-               } while ( ( ( $time[0] - $ct[0] ) * 1000 + ( $time[1] - $ct[1] ) ) <= 10 );
-
-               return false;
-       }
-
-       /**
-        * @param array $time Result of UIDGenerator::millitime()
-        * @return string 46 MSBs of "milliseconds since epoch" in binary (rolls over in 4201)
-        */
-       protected function millisecondsSinceEpochBinary( array $time ) {
-               list( $sec, $msec ) = $time;
-               $ts = 1000 * $sec + $msec;
-               if ( $ts > pow( 2, 52 ) ) {
-                       throw new MWException( __METHOD__ .
-                               ': sorry, this function doesn\'t work after the year 144680' );
-               }
-               return substr( wfBaseConvert( $ts, 10, 2, 46 ), -46 );
-       }
-
-       /**
-        * @return Array (current time in seconds, milliseconds since then)
-        */
-       protected static function millitime() {
-               list( $msec, $sec ) = explode( ' ', microtime() );
-               return array( (int)$sec, (int)( $msec * 1000 ) );
-       }
-
-       function __destruct() {
-               array_map( 'fclose', $this->fileHandles );
-       }
-}
index 12912e1..a2e7023 100644 (file)
@@ -1307,8 +1307,8 @@ class User {
 
                // Proxy blocking
                if ( !$block instanceof Block && $ip !== null && !$this->isAllowed( 'proxyunbannable' )
-                       && !in_array( $ip, $wgProxyWhitelist ) )
-               {
+                       && !in_array( $ip, $wgProxyWhitelist )
+               {
                        // Local list
                        if ( self::isLocallyBlockedProxy( $ip ) ) {
                                $block = new Block;
@@ -1632,8 +1632,8 @@ class User {
                $blocked = $this->isBlocked( $bFromSlave );
                $allowUsertalk = ( $wgBlockAllowsUTEdit ? $this->mAllowUsertalk : false );
                // If a user's name is suppressed, they cannot make edits anywhere
-               if ( !$this->mHideName && $allowUsertalk && $title->getText() === $this->getName() &&
-                 $title->getNamespace() == NS_USER_TALK ) {
+               if ( !$this->mHideName && $allowUsertalk && $title->getText() === $this->getName()
+                       && $title->getNamespace() == NS_USER_TALK ) {
                        $blocked = false;
                        wfDebug( __METHOD__ . ": self-talk page, ignoring any blocks\n" );
                }
@@ -2173,14 +2173,21 @@ class User {
        /**
         * Set the password for a password reminder or new account email
         *
-        * @param string $str New password to set
+        * @param $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 ) {
                $this->load();
-               $this->mNewpassword = self::crypt( $str );
-               if ( $throttle ) {
-                       $this->mNewpassTime = wfTimestampNow();
+
+               if ( $str === null ) {
+                       $this->mNewpassword = '';
+                       $this->mNewpassTime = null;
+               } else {
+                       $this->mNewpassword = self::crypt( $str );
+                       if ( $throttle ) {
+                               $this->mNewpassTime = wfTimestampNow();
+                       }
                }
        }
 
@@ -3021,8 +3028,9 @@ class User {
         * the next change of the page if it's watched etc.
         * @note If the user doesn't have 'editmywatchlist', this will do nothing.
         * @param $title Title of the article to look at
+        * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
         */
-       public function clearNotification( &$title ) {
+       public function clearNotification( &$title, $oldid = 0 ) {
                global $wgUseEnotif, $wgShowUpdatedMarker;
 
                // Do nothing if the database is locked to writes
@@ -3035,12 +3043,25 @@ class User {
                        return;
                }
 
-               if ( $title->getNamespace() == NS_USER_TALK &&
-                       $title->getText() == $this->getName() ) {
-                       if ( !wfRunHooks( 'UserClearNewTalkNotification', array( &$this ) ) ) {
+               // If we're working on user's talk page, we should update the talk page message indicator
+               if ( $title->getNamespace() == NS_USER_TALK && $title->getText() == $this->getName() ) {
+                       if ( !wfRunHooks( 'UserClearNewTalkNotification', array( &$this, $oldid ) ) ) {
                                return;
                        }
-                       $this->setNewtalk( false );
+
+                       $nextid = $oldid ? $title->getNextRevisionID( $oldid ) : null;
+
+                       if ( !$oldid || !$nextid ) {
+                               // If we're looking at the latest revision, we should definitely clear it
+                               $this->setNewtalk( false );
+                       } else {
+                               // Otherwise we should update its revision, if it's present
+                               if ( $this->getNewtalk() ) {
+                                       // Naturally the other one won't clear by itself
+                                       $this->setNewtalk( false );
+                                       $this->setNewtalk( true, Revision::newFromId( $nextid ) );
+                               }
+                       }
                }
 
                if ( !$wgUseEnotif && !$wgShowUpdatedMarker ) {
@@ -3057,13 +3078,11 @@ class User {
                // and when it does have to be executed, it can be on a slave
                // If this is the user's newtalk page, we always update the timestamp
                $force = '';
-               if ( $title->getNamespace() == NS_USER_TALK &&
-                       $title->getText() == $this->getName() )
-               {
+               if ( $title->getNamespace() == NS_USER_TALK && $title->getText() == $this->getName() ) {
                        $force = 'force';
                }
 
-               $this->getWatchedItem( $title )->resetNotificationTimestamp( $force );
+               $this->getWatchedItem( $title )->resetNotificationTimestamp( $force, $oldid );
        }
 
        /**
@@ -3091,14 +3110,12 @@ class User {
                if ( $id != 0 ) {
                        $dbw = wfGetDB( DB_MASTER );
                        $dbw->update( 'watchlist',
-                               array( /* SET */
-                                       'wl_notificationtimestamp' => null
-                               ), array( /* WHERE */
-                                       'wl_user' => $id
-                               ), __METHOD__
+                               array( /* SET */ 'wl_notificationtimestamp' => null ),
+                               array( /* WHERE */ 'wl_user' => $id ),
+                               __METHOD__
                        );
-               #       We also need to clear here the "you have new message" notification for the own user_talk page
-               #       This is cleared one page view later in Article::viewUpdates();
+                       // We also need to clear here the "you have new message" notification for the own user_talk page;
+                       // it's cleared one page view later in WikiPage::doViewUpdates().
                }
        }
 
@@ -3494,56 +3511,6 @@ class User {
                return (bool)$userblock->doAutoblock( $this->getRequest()->getIP() );
        }
 
-       /**
-        * Generate a string which will be different for any combination of
-        * user options which would produce different parser output.
-        * This will be used as part of the hash key for the parser cache,
-        * so users with the same options can share the same cached data
-        * safely.
-        *
-        * Extensions which require it should install 'PageRenderingHash' hook,
-        * which will give them a chance to modify this key based on their own
-        * settings.
-        *
-        * @deprecated since 1.17 use the ParserOptions object to get the relevant options
-        * @return string Page rendering hash
-        */
-       public function getPageRenderingHash() {
-               wfDeprecated( __METHOD__, '1.17' );
-
-               global $wgRenderHashAppend, $wgLang, $wgContLang;
-               if ( $this->mHash ) {
-                       return $this->mHash;
-               }
-
-               // stubthreshold is only included below for completeness,
-               // since it disables the parser cache, its value will always
-               // be 0 when this function is called by parsercache.
-
-               $confstr = $this->getOption( 'math' );
-               $confstr .= '!' . $this->getStubThreshold();
-               $confstr .= '!' . ( $this->getOption( 'numberheadings' ) ? '1' : '' );
-               $confstr .= '!' . $wgLang->getCode();
-               $confstr .= '!' . $this->getOption( 'thumbsize' );
-               // add in language specific options, if any
-               $extra = $wgContLang->getExtraHashOptions();
-               $confstr .= $extra;
-
-               // Since the skin could be overloading link(), it should be
-               // included here but in practice, none of our skins do that.
-
-               $confstr .= $wgRenderHashAppend;
-
-               // Give a chance for extensions to modify the hash, if they have
-               // extra options or other effects on the parser cache.
-               wfRunHooks( 'PageRenderingHash', array( &$confstr ) );
-
-               // Make it a valid memcached key fragment
-               $confstr = str_replace( ' ', '_', $confstr );
-               $this->mHash = $confstr;
-               return $confstr;
-       }
-
        /**
         * Get whether the user is explicitly blocked from account creation.
         * @return bool|Block
@@ -3643,9 +3610,9 @@ class User {
                        // Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
                        // Check for this with iconv
                        $cp1252Password = iconv( 'UTF-8', 'WINDOWS-1252//TRANSLIT', $password );
-                       if ( $cp1252Password != $password &&
-                               self::comparePasswords( $this->mPassword, $cp1252Password, $this->mId ) )
-                       {
+                       if ( $cp1252Password != $password
+                               && self::comparePasswords( $this->mPassword, $cp1252Password, $this->mId )
+                       {
                                return true;
                        }
                }
index 8ab10b2..39c3e18 100644 (file)
@@ -352,14 +352,19 @@ class UserMailer {
                        ini_set( 'html_errors', '0' );
                        set_error_handler( 'UserMailer::errorHandler' );
 
-                       $safeMode = wfIniGetBool( 'safe_mode' );
-
-                       foreach ( $to as $recip ) {
-                               if ( $safeMode ) {
-                                       $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers );
-                               } else {
-                                       $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers, $wgAdditionalMailParams );
+                       try {
+                               $safeMode = wfIniGetBool( 'safe_mode' );
+
+                               foreach ( $to as $recip ) {
+                                       if ( $safeMode ) {
+                                               $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers );
+                                       } else {
+                                               $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers, $wgAdditionalMailParams );
+                                       }
                                }
+                       } catch ( Exception $e ) {
+                               restore_error_handler();
+                               throw $e;
                        }
 
                        restore_error_handler();
@@ -625,11 +630,11 @@ class EmailNotification {
                                // Send updates to watchers other than the current editor
                                $userArray = UserArray::newFromIDs( $watchers );
                                foreach ( $userArray as $watchingUser ) {
-                                       if ( $watchingUser->getOption( 'enotifwatchlistpages' ) &&
-                                               ( !$minorEdit || $watchingUser->getOption( 'enotifminoredits' ) ) &&
-                                               $watchingUser->isEmailConfirmed() &&
-                                               $watchingUser->getID() != $userTalkId )
-                                       {
+                                       if ( $watchingUser->getOption( 'enotifwatchlistpages' )
+                                               && ( !$minorEdit || $watchingUser->getOption( 'enotifminoredits' ) )
+                                               && $watchingUser->isEmailConfirmed()
+                                               && $watchingUser->getID() != $userTalkId
+                                       {
                                                $this->compose( $watchingUser );
                                        }
                                }
@@ -667,9 +672,9 @@ class EmailNotification {
                                wfDebug( __METHOD__ . ": user talk page edited, but user does not exist\n" );
                        } elseif ( $targetUser->getId() == $editor->getId() ) {
                                wfDebug( __METHOD__ . ": user edited their own talk page, no notification sent\n" );
-                       } elseif ( $targetUser->getOption( 'enotifusertalkpages' ) &&
-                               ( !$minorEdit || $targetUser->getOption( 'enotifminoredits' ) ) )
-                       {
+                       } elseif ( $targetUser->getOption( 'enotifusertalkpages' )
+                               && ( !$minorEdit || $targetUser->getOption( 'enotifminoredits' ) )
+                       {
                                if ( !$targetUser->isEmailConfirmed() ) {
                                        wfDebug( __METHOD__ . ": talk page owner doesn't have validated email\n" );
                                } elseif ( !wfRunHooks( 'AbortTalkPageEmailNotification', array( $targetUser, $title ) ) ) {
@@ -777,8 +782,8 @@ class EmailNotification {
                $adminAddress = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
                if ( $wgEnotifRevealEditorAddress
                        && ( $this->editor->getEmail() != '' )
-                       && $this->editor->getOption( 'enotifrevealaddr' ) )
-               {
+                       && $this->editor->getOption( 'enotifrevealaddr' )
+               {
                        $editorAddress = new MailAddress( $this->editor );
                        if ( $wgEnotifFromEditor ) {
                                $this->from = $editorAddress;
diff --git a/includes/ViewCountUpdate.php b/includes/ViewCountUpdate.php
deleted file mode 100644 (file)
index 22a4649..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-/**
- * Update for the 'page_counter' field
- *
- * 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
- */
-
-/**
- * Update for the 'page_counter' field, when $wgDisableCounters is false.
- *
- * Depending on $wgHitcounterUpdateFreq, this will directly increment the
- * 'page_counter' field or use the 'hitcounter' table and then collect the data
- * from that table to update the 'page_counter' field in a batch operation.
- */
-class ViewCountUpdate implements DeferrableUpdate {
-       protected $id;
-
-       /**
-        * Constructor
-        *
-        * @param $id Integer: page ID to increment the view count
-        */
-       public function __construct( $id ) {
-               $this->id = intval( $id );
-       }
-
-       /**
-        * Run the update
-        */
-       public function doUpdate() {
-               global $wgHitcounterUpdateFreq;
-
-               $dbw = wfGetDB( DB_MASTER );
-
-               if ( $wgHitcounterUpdateFreq <= 1 || $dbw->getType() == 'sqlite' ) {
-                       $dbw->update( 'page', array( 'page_counter = page_counter + 1' ), array( 'page_id' => $this->id ), __METHOD__ );
-                       return;
-               }
-
-               # Not important enough to warrant an error page in case of failure
-               try {
-                       $dbw->insert( 'hitcounter', array( 'hc_id' => $this->id ), __METHOD__ );
-                       $checkfreq = intval( $wgHitcounterUpdateFreq / 25 + 1 );
-                       if ( rand() % $checkfreq == 0 && $dbw->lastErrno() == 0 ) {
-                               $this->collect();
-                       }
-               } catch ( DBError $e ) {}
-       }
-
-       protected function collect() {
-               global $wgHitcounterUpdateFreq;
-
-               $dbw = wfGetDB( DB_MASTER );
-
-               $rown = $dbw->selectField( 'hitcounter', 'COUNT(*)', array(), __METHOD__ );
-
-               if ( $rown < $wgHitcounterUpdateFreq ) {
-                       return;
-               }
-
-               wfProfileIn( __METHOD__ . '-collect' );
-               $old_user_abort = ignore_user_abort( true );
-
-               $dbw->lockTables( array(), array( 'hitcounter' ), __METHOD__, false );
-
-               $dbType = $dbw->getType();
-               $tabletype = $dbType == 'mysql' ? "ENGINE=HEAP " : '';
-               $hitcounterTable = $dbw->tableName( 'hitcounter' );
-               $acchitsTable = $dbw->tableName( 'acchits' );
-               $pageTable = $dbw->tableName( 'page' );
-
-               $dbw->query( "CREATE TEMPORARY TABLE $acchitsTable $tabletype AS " .
-                       "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable " .
-                       'GROUP BY hc_id', __METHOD__ );
-               $dbw->delete( 'hitcounter', '*', __METHOD__ );
-               $dbw->unlockTables( __METHOD__ );
-
-               if ( $dbType == 'mysql' ) {
-                       $dbw->query( "UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n " .
-                               'WHERE page_id = hc_id', __METHOD__ );
-               } else {
-                       $dbw->query( "UPDATE $pageTable SET page_counter=page_counter + hc_n " .
-                               "FROM $acchitsTable WHERE page_id = hc_id", __METHOD__ );
-               }
-               $dbw->query( "DROP TABLE $acchitsTable", __METHOD__ );
-
-               ignore_user_abort( $old_user_abort );
-               wfProfileOut( __METHOD__ . '-collect' );
-       }
-}
index 1e07e7c..d2fb468 100644 (file)
@@ -173,8 +173,9 @@ class WatchedItem {
         *
         * @param $force Whether to force the write query to be executed even if the
         *        page is not watched or the notification timestamp is already NULL.
+        * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
         */
-       public function resetNotificationTimestamp( $force = '' ) {
+       public function resetNotificationTimestamp( $force = '', $oldid = 0 ) {
                // Only loggedin user can have a watchlist
                if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
                        return;
@@ -187,10 +188,50 @@ class WatchedItem {
                        }
                }
 
+               $title = $this->getTitle();
+               if ( !$oldid ) {
+                       // No oldid given, assuming latest revision; clear the timestamp.
+                       $notificationTimestamp = null;
+               } elseif ( !$title->getNextRevisionID( $oldid ) ) {
+                       // Oldid given and is the latest revision for this title; clear the timestamp.
+                       $notificationTimestamp = null;
+               } else {
+                       // See if the version marked as read is more recent than the one we're viewing.
+                       // Call load() if it wasn't called before due to $force.
+                       $this->load();
+
+                       if ( $this->timestamp === null ) {
+                               // This can only happen if $force is enabled.
+                               $notificationTimestamp = null;
+                       } else {
+                               // Oldid given and isn't the latest; update the timestamp.
+                               // This will result in no further notification emails being sent!
+                               $dbr = wfGetDB( DB_SLAVE );
+                               $notificationTimestamp = $dbr->selectField(
+                                       'revision', 'rev_timestamp',
+                                       array( 'rev_page' => $title->getArticleID(), 'rev_id' => $oldid )
+                               );
+                               // We need to go one second to the future because of various strict comparisons
+                               // throughout the codebase
+                               $ts = new MWTimestamp( $notificationTimestamp );
+                               $ts->timestamp->add( new DateInterval( 'PT1S' ) );
+                               $notificationTimestamp = $ts->getTimestamp( TS_MW );
+
+                               if ( $notificationTimestamp < $this->timestamp ) {
+                                       if ( $force != 'force' ) {
+                                               return;
+                                       } else {
+                                               // This is a little silly…
+                                               $notificationTimestamp = $this->timestamp;
+                                       }
+                               }
+                       }
+               }
+
                // If the page is watched by the user (or may be watched), update the timestamp on any
                // any matching rows
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => null ),
+               $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $notificationTimestamp ),
                        $this->dbCond(), __METHOD__ );
                $this->timestamp = null;
        }
index b17cb9e..dfa8cf6 100644 (file)
@@ -50,6 +50,12 @@ class WebRequest {
         */
        private $ip;
 
+       /**
+        * Cached URL protocol
+        * @var string
+        */
+       protected $protocol;
+
        public function __construct() {
                /// @todo FIXME: This preemptive de-quoting can interfere with other web libraries
                ///        and increases our memory footprint. It would be cleaner to do on
@@ -107,8 +113,8 @@ class WebRequest {
                                $router->add( "$wgScript/$1" );
 
                                if ( isset( $_SERVER['SCRIPT_NAME'] )
-                                       && preg_match( '/\.php5?/', $_SERVER['SCRIPT_NAME'] ) )
-                               {
+                                       && preg_match( '/\.php5?/', $_SERVER['SCRIPT_NAME'] )
+                               {
                                        # Check for SCRIPT_NAME, we handle index.php explicitly
                                        # But we do have some other .php files such as img_auth.php
                                        # Don't let root article paths clober the parsing for them
@@ -160,7 +166,8 @@ class WebRequest {
         * @return string
         */
        public static function detectServer() {
-               list( $proto, $stdPort ) = self::detectProtocolAndStdPort();
+               $proto = self::detectProtocol();
+               $stdPort = $proto === 'https' ? 443 : 80;
 
                $varNames = array( 'HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR' );
                $host = 'localhost';
@@ -189,25 +196,32 @@ class WebRequest {
        }
 
        /**
+        * Detect the protocol from $_SERVER.
+        * This is for use prior to Setup.php, when no WebRequest object is available.
+        * At other times, use the non-static function getProtocol().
+        *
         * @return array
         */
-       public static function detectProtocolAndStdPort() {
+       public static function detectProtocol() {
                if ( ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) ||
                        ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &&
                        $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) ) {
-                       $arr = array( 'https', 443 );
+                       return 'https';
                } else {
-                       $arr = array( 'http', 80 );
+                       return 'http';
                }
                return $arr;
        }
 
        /**
+        * Get the current URL protocol (http or https)
         * @return string
         */
-       public static function detectProtocol() {
-               list( $proto, ) = self::detectProtocolAndStdPort();
-               return $proto;
+       public function getProtocol() {
+               if ( $this->protocol === null ) {
+                       $this->protocol = self::detectProtocol();
+               }
+               return $this->protocol;
        }
 
        /**
@@ -466,6 +480,20 @@ class WebRequest {
                        : null;
        }
 
+       /**
+        * Fetch a floating point value from the input or return $default if not set.
+        * Guaranteed to return a float; non-numeric input will typically
+        * return 0.
+        *
+        * @since 1.23
+        * @param $name String
+        * @param $default Float
+        * @return Float
+        */
+       public function getFloat( $name, $default = 0 ) {
+               return floatval( $this->getVal( $name, $default ) );
+       }
+
        /**
         * Fetch a boolean value from the input or return $default if not set.
         * Guaranteed to return true or false, with normal PHP semantics for
@@ -1312,9 +1340,10 @@ class FauxRequest extends WebRequest {
         *   fake GET/POST values
         * @param bool $wasPosted whether to treat the data as POST
         * @param $session Mixed: session array or null
+        * @param string $protocol 'http' or 'https'
         * @throws MWException
         */
-       public function __construct( $data = array(), $wasPosted = false, $session = null ) {
+       public function __construct( $data = array(), $wasPosted = false, $session = null, $protocol = 'http' ) {
                if ( is_array( $data ) ) {
                        $this->data = $data;
                } else {
@@ -1324,6 +1353,7 @@ class FauxRequest extends WebRequest {
                if ( $session ) {
                        $this->session = $session;
                }
+               $this->protocol = $protocol;
        }
 
        /**
@@ -1385,6 +1415,10 @@ class FauxRequest extends WebRequest {
                $this->notImplemented( __METHOD__ );
        }
 
+       public function getProtocol() {
+               return $this->protocol;
+       }
+
        /**
         * @param string $name The name of the header to get (case insensitive).
         * @return bool|string
@@ -1488,6 +1522,12 @@ class FauxRequest extends WebRequest {
 class DerivativeRequest extends FauxRequest {
        private $base;
 
+       /**
+        * @param WebRequest $base
+        * @param array $data Array of *non*-urlencoded key => value pairs, the
+        *   fake GET/POST values
+        * @param bool $wasPosted Whether to treat the data as POST
+        */
        public function __construct( WebRequest $base, $data, $wasPosted = false ) {
                $this->base = $base;
                parent::__construct( $data, $wasPosted );
@@ -1524,4 +1564,8 @@ class DerivativeRequest extends FauxRequest {
        public function getIP() {
                return $this->base->getIP();
        }
+
+       public function getProtocol() {
+               return $this->base->getProtocol();
+       }
 }
index edfbba2..5ebf5a0 100644 (file)
@@ -95,8 +95,8 @@ class MediaWiki {
                        // Check variant links so that interwiki links don't have to worry
                        // about the possible different language variants
                        if ( count( $wgContLang->getVariants() ) > 1
-                               && !is_null( $ret ) && $ret->getArticleID() == 0 )
-                       {
+                               && !is_null( $ret ) && $ret->getArticleID() == 0
+                       {
                                $wgContLang->findVariantLink( $title, $ret );
                        }
                }
@@ -197,9 +197,9 @@ class MediaWiki {
                wfRunHooks( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
 
                // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty.
-               if ( is_null( $title ) || ( $title->getDBkey() == '' && $title->getInterwiki() == '' ) ||
-                       $title->isSpecial( 'Badtitle' ) )
-               {
+               if ( is_null( $title ) || ( $title->getDBkey() == '' && $title->getInterwiki() == '' )
+                       || $title->isSpecial( 'Badtitle' )
+               {
                        $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
                        wfProfileOut( __METHOD__ );
                        throw new BadTitleError();
@@ -242,8 +242,8 @@ class MediaWiki {
                        }
                        // Check for a redirect loop
                        if ( !preg_match( '/^' . preg_quote( $wgServer, '/' ) . '/', $url )
-                               && $title->isLocal() )
-                       {
+                               && $title->isLocal()
+                       {
                                // 301 so google et al report the target as the actual url.
                                $output->redirect( $url, 301 );
                        } else {
@@ -253,11 +253,11 @@ class MediaWiki {
                        }
                // Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant
                } elseif ( $request->getVal( 'action', 'view' ) == 'view' && !$request->wasPosted()
-                       && ( $request->getVal( 'title' ) === null ||
-                               $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
+                       && ( $request->getVal( 'title' ) === null
+                               || $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
                        && !count( $request->getValueNames( array( 'action', 'title' ) ) )
-                       && wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) ) )
-               {
+                       && wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) )
+               {
                        if ( $title->isSpecialPage() ) {
                                list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
                                if ( $name ) {
@@ -302,13 +302,6 @@ class MediaWiki {
                        $article = $this->initializeArticle();
                        if ( is_object( $article ) ) {
                                $pageView = true;
-                               /**
-                                * $wgArticle is deprecated, do not use it.
-                                * @deprecated since 1.18
-                                */
-                               global $wgArticle;
-                               $wgArticle = new DeprecatedGlobal( 'wgArticle', $article, '1.18' );
-
                                $this->performAction( $article, $requestTitle );
                        } elseif ( is_string( $article ) ) {
                                $output->redirect( $article );
@@ -365,12 +358,12 @@ class MediaWiki {
                $action = $request->getVal( 'action', 'view' );
                $file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null;
                if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
-                       && !$request->getVal( 'oldid' ) && // ... and are not old revisions
-                       !$request->getVal( 'diff' ) && // ... and not when showing diff
-                       $request->getVal( 'redirect' ) != 'no' && // ... unless explicitly told not to
+                       && !$request->getVal( 'oldid' ) // ... and are not old revisions
+                       && !$request->getVal( 'diff' ) // ... and not when showing diff
+                       && $request->getVal( 'redirect' ) != 'no' // ... unless explicitly told not to
                        // ... and the article is not a non-redirect image page with associated file
-                       !( is_object( $file ) && $file->exists() && !$file->getRedirected() ) )
-               {
+                       && !( is_object( $file ) && $file->exists() && !$file->getRedirected() )
+               {
                        // Give extensions a change to ignore/handle redirects as needed
                        $ignoreRedirect = $target = false;
 
@@ -427,8 +420,8 @@ class MediaWiki {
                $user = $this->context->getUser();
 
                if ( !wfRunHooks( 'MediaWikiPerformAction',
-                       array( $output, $page, $title, $user, $request, $this ) ) )
-               {
+                               array( $output, $page, $title, $user, $request, $this ) )
+               {
                        wfProfileOut( __METHOD__ );
                        return;
                }
@@ -547,7 +540,7 @@ class MediaWiki {
                                        && $this->context->getUser()->requiresHTTPS()
                                )
                        ) &&
-                       $request->detectProtocol() == 'http'
+                       $request->getProtocol() == 'http'
                ) {
                        $oldUrl = $request->getFullRequestURL();
                        $redirUrl = str_replace( 'http://', 'https://', $oldUrl );
@@ -588,6 +581,7 @@ class MediaWiki {
                                                $cache->loadFromFileCache( $this->context );
                                        }
                                        // Do any stats increment/watchlist stuff
+                                       // Assume we're viewing the latest revision (this should always be the case with file cache)
                                        $this->context->getWikiPage()->doViewUpdates( $this->context->getUser() );
                                        // Tell OutputPage that output is taken care of
                                        $this->context->getOutput()->disable();
@@ -687,7 +681,7 @@ class MediaWiki {
                                // We don't want exceptions thrown during job execution to
                                // be reported to the user since the output is already sent.
                                // Instead we just log them.
-                               wfDebugLog( 'exception', $e->getLogMessage() );
+                               MWExceptionHandler::logException( $e );
                        }
                }
        }
index fe1ff88..2b192b0 100644 (file)
@@ -189,4 +189,45 @@ class WikiFilePage extends WikiPage {
                }
                return parent::doPurge();
        }
+
+       /**
+        * Get the categories this file is a member of on the wiki where it was uploaded.
+        * For local files, this is the same as getCategories().
+        * For foreign API files (InstantCommons), this is not supported currently.
+        * Results will include hidden categories.
+        *
+        * @return TitleArray|Title[]
+        * @since 1.23
+        */
+       public function getForeignCategories() {
+               $this->loadFile();
+               $title = $this->mTitle;
+               $file = $this->mFile;
+
+               if ( ! $file instanceof LocalFile ) {
+                       wfDebug( __CLASS__ . '::' . __METHOD__ . ' is not supported for this file' );
+                       return TitleArray::newFromResult( new FakeResultWrapper( array() ) );
+               }
+
+               /** @var LocalRepo $repo */
+               $repo = $file->getRepo();
+               $dbr = $repo->getSlaveDB();
+
+               $res = $dbr->select(
+                       array( 'page', 'categorylinks' ),
+                       array(
+                               'page_title' => 'cl_to',
+                               'page_namespace' => NS_CATEGORY,
+                       ),
+                       array(
+                               'page_namespace' => $title->getNamespace(),
+                               'page_title' => $title->getDBkey(),
+                       ),
+                       __METHOD__,
+                       array(),
+                       array( 'categorylinks' => array( 'INNER JOIN', 'page_id = cl_from' ) )
+               );
+
+               return TitleArray::newFromResult( $res );
+       }
 }
index 7c3dc93..9507e5f 100644 (file)
@@ -48,9 +48,11 @@ class WikiPage implements Page, IDBAccessObject {
        public $mDataLoaded = false;         // !< Boolean
        public $mIsRedirect = false;         // !< Boolean
        public $mLatest = false;             // !< Integer (false means "not loaded")
-       public $mPreparedEdit = false;       // !< Array
        /**@}}*/
 
+       /** @var stdclass Map of cache fields (text, parser output, ect) for a proposed/new edit */
+       protected $mPreparedEdit = false;
+
        /**
         * @var int
         */
@@ -242,6 +244,18 @@ class WikiPage implements Page, IDBAccessObject {
                $this->mTimestamp = '';
                $this->mIsRedirect = false;
                $this->mLatest = false;
+               // Bug 57026: do not clear mPreparedEdit since prepareTextForEdit() already checks
+               // the requested rev ID and content against the cached one for equality. For most
+               // content types, the output should not change during the lifetime of this cache.
+               // Clearing it can cause extra parses on edit for no reason.
+       }
+
+       /**
+        * Clear the mPreparedEdit cache field, as may be needed by mutable content types
+        * @return void
+        * @since 1.23
+        */
+       public function clearPreparedEdit() {
                $this->mPreparedEdit = false;
        }
 
@@ -1134,9 +1148,10 @@ class WikiPage implements Page, IDBAccessObject {
 
        /**
         * Do standard deferred updates after page view
-        * @param $user User The relevant user
+        * @param User $user The relevant user
+        * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
         */
-       public function doViewUpdates( User $user ) {
+       public function doViewUpdates( User $user, $oldid = 0 ) {
                global $wgDisableCounters;
                if ( wfReadOnly() ) {
                        return;
@@ -1149,7 +1164,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                // Update newtalk / watchlist notification status
-               $user->clearNotification( $this->mTitle );
+               $user->clearNotification( $this->mTitle, $oldid );
        }
 
        /**
@@ -2232,7 +2247,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return Status
         */
        public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) {
-               global $wgCascadingRestrictionLevels;
+               global $wgCascadingRestrictionLevels, $wgContLang;
 
                if ( wfReadOnly() ) {
                        return Status::newFatal( 'readonlytext', wfReadOnlyReason() );
@@ -2305,6 +2320,9 @@ class WikiPage implements Page, IDBAccessObject {
                        $logAction = 'protect';
                }
 
+               // Truncate for whole multibyte characters
+               $reason = $wgContLang->truncate( $reason, 255 );
+
                if ( $id ) { // Protection of existing page
                        if ( !wfRunHooks( 'ArticleProtect', array( &$this, &$user, $limit, $reason ) ) ) {
                                return Status::newGood();
@@ -2378,7 +2396,7 @@ class WikiPage implements Page, IDBAccessObject {
                                                'pt_namespace' => $this->mTitle->getNamespace(),
                                                'pt_title' => $this->mTitle->getDBkey(),
                                                'pt_create_perm' => $limit['create'],
-                                               'pt_timestamp' => $dbw->encodeExpiry( wfTimestampNow() ),
+                                               'pt_timestamp' => $dbw->timestamp(),
                                                'pt_expiry' => $dbw->encodeExpiry( $expiry['create'] ),
                                                'pt_user' => $user->getId(),
                                                'pt_reason' => $reason,
@@ -2406,7 +2424,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                // Update the protection log
                $log = new LogPage( 'protect' );
-               $log->addEntry( $logAction, $this->mTitle, trim( $reason ), $params, $user );
+               $log->addEntry( $logAction, $this->mTitle, $reason, $params, $user );
 
                return Status::newGood();
        }
@@ -2746,6 +2764,9 @@ class WikiPage implements Page, IDBAccessObject {
                $updates = $this->getDeletionUpdates( $content );
                DataUpdate::runUpdates( $updates );
 
+               // Reparse any pages transcluding this page
+               LinksUpdate::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
+
                // Clear caches
                WikiPage::onArticleDelete( $this->mTitle );
 
index ac0539d..45441fd 100644 (file)
@@ -500,34 +500,34 @@ class Xml {
                $options = self::option( $other, 'other', $selected === 'other' );
 
                foreach ( explode( "\n", $list ) as $option ) {
-                               $value = trim( $option );
-                               if ( $value == '' ) {
-                                       continue;
-                               } elseif ( substr( $value, 0, 1 ) == '*' && substr( $value, 1, 1 ) != '*' ) {
-                                       // A new group is starting ...
-                                       $value = trim( substr( $value, 1 ) );
-                                       if ( $optgroup ) {
-                                               $options .= self::closeElement( 'optgroup' );
-                                       }
-                                       $options .= self::openElement( 'optgroup', array( 'label' => $value ) );
-                                       $optgroup = true;
-                               } elseif ( substr( $value, 0, 2 ) == '**' ) {
-                                       // groupmember
-                                       $value = trim( substr( $value, 2 ) );
-                                       $options .= self::option( $value, $value, $selected === $value );
-                               } else {
-                                       // groupless reason list
-                                       if ( $optgroup ) {
-                                               $options .= self::closeElement( 'optgroup' );
-                                       }
-                                       $options .= self::option( $value, $value, $selected === $value );
-                                       $optgroup = false;
+                       $value = trim( $option );
+                       if ( $value == '' ) {
+                               continue;
+                       } elseif ( substr( $value, 0, 1 ) == '*' && substr( $value, 1, 1 ) != '*' ) {
+                               // A new group is starting ...
+                               $value = trim( substr( $value, 1 ) );
+                               if ( $optgroup ) {
+                                       $options .= self::closeElement( 'optgroup' );
                                }
+                               $options .= self::openElement( 'optgroup', array( 'label' => $value ) );
+                               $optgroup = true;
+                       } elseif ( substr( $value, 0, 2 ) == '**' ) {
+                               // groupmember
+                               $value = trim( substr( $value, 2 ) );
+                               $options .= self::option( $value, $value, $selected === $value );
+                       } else {
+                               // groupless reason list
+                               if ( $optgroup ) {
+                                       $options .= self::closeElement( 'optgroup' );
+                               }
+                               $options .= self::option( $value, $value, $selected === $value );
+                               $optgroup = false;
                        }
+               }
 
-                       if ( $optgroup ) {
-                               $options .= self::closeElement( 'optgroup' );
-                       }
+               if ( $optgroup ) {
+                       $options .= self::closeElement( 'optgroup' );
+               }
 
                $attribs = array();
 
diff --git a/includes/XmlTypeCheck.php b/includes/XmlTypeCheck.php
deleted file mode 100644 (file)
index 92ca7d8..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-<?php
-/**
- * XML syntax and type checker.
- *
- * 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
- */
-
-class XmlTypeCheck {
-       /**
-        * Will be set to true or false to indicate whether the file is
-        * well-formed XML. Note that this doesn't check schema validity.
-        */
-       public $wellFormed = false;
-
-       /**
-        * Will be set to true if the optional element filter returned
-        * a match at some point.
-        */
-       public $filterMatch = false;
-
-       /**
-        * Name of the document's root element, including any namespace
-        * as an expanded URL.
-        */
-       public $rootElement = '';
-
-       /**
-        * @param string $input a filename or string containing the XML element
-        * @param callable $filterCallback (optional)
-        *        Function to call to do additional custom validity checks from the
-        *        SAX element handler event. This gives you access to the element
-        *        namespace, name, and attributes, but not to text contents.
-        *        Filter should return 'true' to toggle on $this->filterMatch
-        * @param boolean $isFile (optional) indicates if the first parameter is a
-        *        filename (default, true) or if it is a string (false)
-        */
-       function __construct( $input, $filterCallback = null, $isFile = true ) {
-               $this->filterCallback = $filterCallback;
-               if ( $isFile ) {
-                       $this->validateFromFile( $input );
-               } else {
-                       $this->validateFromString( $input );
-               }
-       }
-
-       /**
-        * Alternative constructor: from filename
-        *
-        * @param string $fname the filename of an XML document
-        * @param callable $filterCallback (optional)
-        *        Function to call to do additional custom validity checks from the
-        *        SAX element handler event. This gives you access to the element
-        *        namespace, name, and attributes, but not to text contents.
-        *        Filter should return 'true' to toggle on $this->filterMatch
-        * @return XmlTypeCheck
-        */
-       public static function newFromFilename( $fname, $filterCallback = null ) {
-               return new self( $fname, $filterCallback, true );
-       }
-
-       /**
-        * Alternative constructor: from string
-        *
-        * @param string $string a string containing an XML element
-        * @param callable $filterCallback (optional)
-        *        Function to call to do additional custom validity checks from the
-        *        SAX element handler event. This gives you access to the element
-        *        namespace, name, and attributes, but not to text contents.
-        *        Filter should return 'true' to toggle on $this->filterMatch
-        * @return XmlTypeCheck
-        */
-       public static function newFromString( $string, $filterCallback = null ) {
-               return new self( $string, $filterCallback, false );
-       }
-
-       /**
-        * Get the root element. Simple accessor to $rootElement
-        *
-        * @return string
-        */
-       public function getRootElement() {
-               return $this->rootElement;
-       }
-
-       /**
-        * Get an XML parser with the root element handler.
-        * @see XmlTypeCheck::rootElementOpen()
-        * @return resource a resource handle for the XML parser
-        */
-       private function getParser() {
-               $parser = xml_parser_create_ns( 'UTF-8' );
-               // case folding violates XML standard, turn it off
-               xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
-               xml_set_element_handler( $parser, array( $this, 'rootElementOpen' ), false );
-               return $parser;
-       }
-
-       /**
-        * @param string $fname the filename
-        */
-       private function validateFromFile( $fname ) {
-               $parser = $this->getParser();
-
-               if ( file_exists( $fname ) ) {
-                       $file = fopen( $fname, "rb" );
-                       if ( $file ) {
-                               do {
-                                       $chunk = fread( $file, 32768 );
-                                       $ret = xml_parse( $parser, $chunk, feof( $file ) );
-                                       if ( $ret == 0 ) {
-                                               $this->wellFormed = false;
-                                               fclose( $file );
-                                               xml_parser_free( $parser );
-                                               return;
-                                       }
-                               } while ( !feof( $file ) );
-
-                               fclose( $file );
-                       }
-               }
-               $this->wellFormed = true;
-
-               xml_parser_free( $parser );
-       }
-
-       /**
-        *
-        * @param string $string the XML-input-string to be checked.
-        */
-       private function validateFromString( $string ) {
-               $parser = $this->getParser();
-               $ret = xml_parse( $parser, $string, true );
-               xml_parser_free( $parser );
-               if ( $ret == 0 ) {
-                       $this->wellFormed = false;
-                       return;
-               }
-               $this->wellFormed = true;
-       }
-
-       /**
-        * @param $parser
-        * @param $name
-        * @param $attribs
-        */
-       private function rootElementOpen( $parser, $name, $attribs ) {
-               $this->rootElement = $name;
-
-               if ( is_callable( $this->filterCallback ) ) {
-                       xml_set_element_handler( $parser, array( $this, 'elementOpen' ), false );
-                       $this->elementOpen( $parser, $name, $attribs );
-               } else {
-                       // We only need the first open element
-                       xml_set_element_handler( $parser, false, false );
-               }
-       }
-
-       /**
-        * @param $parser
-        * @param $name
-        * @param $attribs
-        */
-       private function elementOpen( $parser, $name, $attribs ) {
-               if ( call_user_func( $this->filterCallback, $name, $attribs ) ) {
-                       // Filter hit!
-                       $this->filterMatch = true;
-               }
-       }
-}
diff --git a/includes/ZipDirectoryReader.php b/includes/ZipDirectoryReader.php
deleted file mode 100644 (file)
index 307efce..0000000
+++ /dev/null
@@ -1,712 +0,0 @@
-<?php
-/**
- * ZIP file directories reader, for the purposes of upload verification.
- *
- * 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
- */
-
-/**
- * A class for reading ZIP file directories, for the purposes of upload
- * verification.
- *
- * Only a functional interface is provided: ZipFileReader::read(). No access is
- * given to object instances.
- *
- */
-class ZipDirectoryReader {
-       /**
-        * Read a ZIP file and call a function for each file discovered in it.
-        *
-        * Because this class is aimed at verification, an error is raised on
-        * suspicious or ambiguous input, instead of emulating some standard
-        * behavior.
-        *
-        * @param string $fileName The archive file name
-        * @param array $callback The callback function. It will be called for each file
-        *   with a single associative array each time, with members:
-        *
-        *      - name: The file name. Directories conventionally have a trailing
-        *        slash.
-        *
-        *      - mtime: The file modification time, in MediaWiki 14-char format
-        *
-        *      - size: The uncompressed file size
-        *
-        * @param array $options An associative array of read options, with the option
-        *    name in the key. This may currently contain:
-        *
-        *      - zip64: If this is set to true, then we will emulate a
-        *        library with ZIP64 support, like OpenJDK 7. If it is set to
-        *        false, then we will emulate a library with no knowledge of
-        *        ZIP64.
-        *
-        *        NOTE: The ZIP64 code is untested and probably doesn't work. It
-        *        turned out to be easier to just reject ZIP64 archive uploads,
-        *        since they are likely to be very rare. Confirming safety of a
-        *        ZIP64 file is fairly complex. What do you do with a file that is
-        *        ambiguous and broken when read with a non-ZIP64 reader, but valid
-        *        when read with a ZIP64 reader? This situation is normal for a
-        *        valid ZIP64 file, and working out what non-ZIP64 readers will make
-        *        of such a file is not trivial.
-        *
-        * @return Status object. The following fatal errors are defined:
-        *
-        *      - zip-file-open-error: The file could not be opened.
-        *
-        *      - zip-wrong-format: The file does not appear to be a ZIP file.
-        *
-        *      - zip-bad: There was something wrong or ambiguous about the file
-        *        data.
-        *
-        *      - zip-unsupported: The ZIP file uses features which
-        *        ZipDirectoryReader does not support.
-        *
-        * The default messages for those fatal errors are written in a way that
-        * makes sense for upload verification.
-        *
-        * If a fatal error is returned, more information about the error will be
-        * available in the debug log.
-        *
-        * Note that the callback function may be called any number of times before
-        * a fatal error is returned. If this occurs, the data sent to the callback
-        * function should be discarded.
-        */
-       public static function read( $fileName, $callback, $options = array() ) {
-               $zdr = new self( $fileName, $callback, $options );
-               return $zdr->execute();
-       }
-
-       /** The file name */
-       var $fileName;
-
-       /** The opened file resource */
-       var $file;
-
-       /** The cached length of the file, or null if it has not been loaded yet. */
-       var $fileLength;
-
-       /** A segmented cache of the file contents */
-       var $buffer;
-
-       /** The file data callback */
-       var $callback;
-
-       /** The ZIP64 mode */
-       var $zip64 = false;
-
-       /** Stored headers */
-       var $eocdr, $eocdr64, $eocdr64Locator;
-
-       var $data;
-
-       /** The "extra field" ID for ZIP64 central directory entries */
-       const ZIP64_EXTRA_HEADER = 0x0001;
-
-       /** The segment size for the file contents cache */
-       const SEGSIZE = 16384;
-
-       /** The index of the "general field" bit for UTF-8 file names */
-       const GENERAL_UTF8 = 11;
-
-       /** The index of the "general field" bit for central directory encryption */
-       const GENERAL_CD_ENCRYPTED = 13;
-
-       /**
-        * Private constructor
-        */
-       protected function __construct( $fileName, $callback, $options ) {
-               $this->fileName = $fileName;
-               $this->callback = $callback;
-
-               if ( isset( $options['zip64'] ) ) {
-                       $this->zip64 = $options['zip64'];
-               }
-       }
-
-       /**
-        * Read the directory according to settings in $this.
-        *
-        * @return Status
-        */
-       function execute() {
-               $this->file = fopen( $this->fileName, 'r' );
-               $this->data = array();
-               if ( !$this->file ) {
-                       return Status::newFatal( 'zip-file-open-error' );
-               }
-
-               $status = Status::newGood();
-               try {
-                       $this->readEndOfCentralDirectoryRecord();
-                       if ( $this->zip64 ) {
-                               list( $offset, $size ) = $this->findZip64CentralDirectory();
-                               $this->readCentralDirectory( $offset, $size );
-                       } else {
-                               if ( $this->eocdr['CD size'] == 0xffffffff
-                                       || $this->eocdr['CD offset'] == 0xffffffff
-                                       || $this->eocdr['CD entries total'] == 0xffff )
-                               {
-                                       $this->error( 'zip-unsupported', 'Central directory header indicates ZIP64, ' .
-                                               'but we are in legacy mode. Rejecting this upload is necessary to avoid ' .
-                                               'opening vulnerabilities on clients using OpenJDK 7 or later.' );
-                               }
-
-                               list( $offset, $size ) = $this->findOldCentralDirectory();
-                               $this->readCentralDirectory( $offset, $size );
-                       }
-               } catch ( ZipDirectoryReaderError $e ) {
-                       $status->fatal( $e->getErrorCode() );
-               }
-
-               fclose( $this->file );
-               return $status;
-       }
-
-       /**
-        * Throw an error, and log a debug message
-        */
-       function error( $code, $debugMessage ) {
-               wfDebug( __CLASS__ . ": Fatal error: $debugMessage\n" );
-               throw new ZipDirectoryReaderError( $code );
-       }
-
-       /**
-        * Read the header which is at the end of the central directory,
-        * unimaginatively called the "end of central directory record" by the ZIP
-        * spec.
-        */
-       function readEndOfCentralDirectoryRecord() {
-               $info = array(
-                       'signature' => 4,
-                       'disk' => 2,
-                       'CD start disk' => 2,
-                       'CD entries this disk' => 2,
-                       'CD entries total' => 2,
-                       'CD size' => 4,
-                       'CD offset' => 4,
-                       'file comment length' => 2,
-               );
-               $structSize = $this->getStructSize( $info );
-               $startPos = $this->getFileLength() - 65536 - $structSize;
-               if ( $startPos < 0 ) {
-                       $startPos = 0;
-               }
-
-               $block = $this->getBlock( $startPos );
-               $sigPos = strrpos( $block, "PK\x05\x06" );
-               if ( $sigPos === false ) {
-                       $this->error( 'zip-wrong-format',
-                               "zip file lacks EOCDR signature. It probably isn't a zip file." );
-               }
-
-               $this->eocdr = $this->unpack( substr( $block, $sigPos ), $info );
-               $this->eocdr['EOCDR size'] = $structSize + $this->eocdr['file comment length'];
-
-               if ( $structSize + $this->eocdr['file comment length'] != strlen( $block ) - $sigPos ) {
-                       $this->error( 'zip-bad', 'trailing bytes after the end of the file comment' );
-               }
-               if ( $this->eocdr['disk'] !== 0
-                       || $this->eocdr['CD start disk'] !== 0 )
-               {
-                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR)' );
-               }
-               $this->eocdr += $this->unpack(
-                       $block,
-                       array( 'file comment' => array( 'string', $this->eocdr['file comment length'] ) ),
-                       $sigPos + $structSize );
-               $this->eocdr['position'] = $startPos + $sigPos;
-       }
-
-       /**
-        * Read the header called the "ZIP64 end of central directory locator". An
-        * error will be raised if it does not exist.
-        */
-       function readZip64EndOfCentralDirectoryLocator() {
-               $info = array(
-                       'signature' => array( 'string', 4 ),
-                       'eocdr64 start disk' => 4,
-                       'eocdr64 offset' => 8,
-                       'number of disks' => 4,
-               );
-               $structSize = $this->getStructSize( $info );
-
-               $block = $this->getBlock( $this->getFileLength() - $this->eocdr['EOCDR size']
-                       - $structSize, $structSize );
-               $this->eocdr64Locator = $data = $this->unpack( $block, $info );
-
-               if ( $data['signature'] !== "PK\x06\x07" ) {
-                       // Note: Java will allow this and continue to read the
-                       // EOCDR64, so we have to reject the upload, we can't
-                       // just use the EOCDR header instead.
-                       $this->error( 'zip-bad', 'wrong signature on Zip64 end of central directory locator' );
-               }
-       }
-
-       /**
-        * Read the header called the "ZIP64 end of central directory record". It
-        * may replace the regular "end of central directory record" in ZIP64 files.
-        */
-       function readZip64EndOfCentralDirectoryRecord() {
-               if ( $this->eocdr64Locator['eocdr64 start disk'] != 0
-                       || $this->eocdr64Locator['number of disks'] != 0 )
-               {
-                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR64 locator)' );
-               }
-
-               $info = array(
-                       'signature' => array( 'string', 4 ),
-                       'EOCDR64 size' => 8,
-                       'version made by' => 2,
-                       'version needed' => 2,
-                       'disk' => 4,
-                       'CD start disk' => 4,
-                       'CD entries this disk' => 8,
-                       'CD entries total' => 8,
-                       'CD size' => 8,
-                       'CD offset' => 8
-               );
-               $structSize = $this->getStructSize( $info );
-               $block = $this->getBlock( $this->eocdr64Locator['eocdr64 offset'], $structSize );
-               $this->eocdr64 = $data = $this->unpack( $block, $info );
-               if ( $data['signature'] !== "PK\x06\x06" ) {
-                       $this->error( 'zip-bad', 'wrong signature on Zip64 end of central directory record' );
-               }
-               if ( $data['disk'] !== 0
-                       || $data['CD start disk'] !== 0 )
-               {
-                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR64)' );
-               }
-       }
-
-       /**
-        * Find the location of the central directory, as would be seen by a
-        * non-ZIP64 reader.
-        *
-        * @return List containing offset, size and end position.
-        */
-       function findOldCentralDirectory() {
-               $size = $this->eocdr['CD size'];
-               $offset = $this->eocdr['CD offset'];
-               $endPos = $this->eocdr['position'];
-
-               // Some readers use the EOCDR position instead of the offset field
-               // to find the directory, so to be safe, we check if they both agree.
-               if ( $offset + $size != $endPos ) {
-                       $this->error( 'zip-bad', 'the central directory does not immediately precede the end ' .
-                               'of central directory record' );
-               }
-               return array( $offset, $size );
-       }
-
-       /**
-        * Find the location of the central directory, as would be seen by a
-        * ZIP64-compliant reader.
-        *
-        * @return array List containing offset, size and end position.
-        */
-       function findZip64CentralDirectory() {
-               // The spec is ambiguous about the exact rules of precedence between the
-               // ZIP64 headers and the original headers. Here we follow zip_util.c
-               // from OpenJDK 7.
-               $size = $this->eocdr['CD size'];
-               $offset = $this->eocdr['CD offset'];
-               $numEntries = $this->eocdr['CD entries total'];
-               $endPos = $this->eocdr['position'];
-               if ( $size == 0xffffffff
-                       || $offset == 0xffffffff
-                       || $numEntries == 0xffff )
-               {
-                       $this->readZip64EndOfCentralDirectoryLocator();
-
-                       if ( isset( $this->eocdr64Locator['eocdr64 offset'] ) ) {
-                               $this->readZip64EndOfCentralDirectoryRecord();
-                               if ( isset( $this->eocdr64['CD offset'] ) ) {
-                                       $size = $this->eocdr64['CD size'];
-                                       $offset = $this->eocdr64['CD offset'];
-                                       $endPos = $this->eocdr64Locator['eocdr64 offset'];
-                               }
-                       }
-               }
-               // Some readers use the EOCDR position instead of the offset field
-               // to find the directory, so to be safe, we check if they both agree.
-               if ( $offset + $size != $endPos ) {
-                       $this->error( 'zip-bad', 'the central directory does not immediately precede the end ' .
-                               'of central directory record' );
-               }
-               return array( $offset, $size );
-       }
-
-       /**
-        * Read the central directory at the given location
-        */
-       function readCentralDirectory( $offset, $size ) {
-               $block = $this->getBlock( $offset, $size );
-
-               $fixedInfo = array(
-                       'signature' => array( 'string', 4 ),
-                       'version made by' => 2,
-                       'version needed' => 2,
-                       'general bits' => 2,
-                       'compression method' => 2,
-                       'mod time' => 2,
-                       'mod date' => 2,
-                       'crc-32' => 4,
-                       'compressed size' => 4,
-                       'uncompressed size' => 4,
-                       'name length' => 2,
-                       'extra field length' => 2,
-                       'comment length' => 2,
-                       'disk number start' => 2,
-                       'internal attrs' => 2,
-                       'external attrs' => 4,
-                       'local header offset' => 4,
-               );
-               $fixedSize = $this->getStructSize( $fixedInfo );
-
-               $pos = 0;
-               while ( $pos < $size ) {
-                       $data = $this->unpack( $block, $fixedInfo, $pos );
-                       $pos += $fixedSize;
-
-                       if ( $data['signature'] !== "PK\x01\x02" ) {
-                               $this->error( 'zip-bad', 'Invalid signature found in directory entry' );
-                       }
-
-                       $variableInfo = array(
-                               'name' => array( 'string', $data['name length'] ),
-                               'extra field' => array( 'string', $data['extra field length'] ),
-                               'comment' => array( 'string', $data['comment length'] ),
-                       );
-                       $data += $this->unpack( $block, $variableInfo, $pos );
-                       $pos += $this->getStructSize( $variableInfo );
-
-                       if ( $this->zip64 && (
-                                  $data['compressed size'] == 0xffffffff
-                               || $data['uncompressed size'] == 0xffffffff
-                               || $data['local header offset'] == 0xffffffff ) )
-                       {
-                               $zip64Data = $this->unpackZip64Extra( $data['extra field'] );
-                               if ( $zip64Data ) {
-                                       $data = $zip64Data + $data;
-                               }
-                       }
-
-                       if ( $this->testBit( $data['general bits'], self::GENERAL_CD_ENCRYPTED ) ) {
-                               $this->error( 'zip-unsupported', 'central directory encryption is not supported' );
-                       }
-
-                       // Convert the timestamp into MediaWiki format
-                       // For the format, please see the MS-DOS 2.0 Programmer's Reference,
-                       // pages 3-5 and 3-6.
-                       $time = $data['mod time'];
-                       $date = $data['mod date'];
-
-                       $year = 1980 + ( $date >> 9 );
-                       $month = ( $date >> 5 ) & 15;
-                       $day = $date & 31;
-                       $hour = ( $time >> 11 ) & 31;
-                       $minute = ( $time >> 5 ) & 63;
-                       $second = ( $time & 31 ) * 2;
-                       $timestamp = sprintf( "%04d%02d%02d%02d%02d%02d",
-                               $year, $month, $day, $hour, $minute, $second );
-
-                       // Convert the character set in the file name
-                       if ( !function_exists( 'iconv' )
-                               || $this->testBit( $data['general bits'], self::GENERAL_UTF8 ) )
-                       {
-                               $name = $data['name'];
-                       } else {
-                               $name = iconv( 'CP437', 'UTF-8', $data['name'] );
-                       }
-
-                       // Compile a data array for the user, with a sensible format
-                       $userData = array(
-                               'name' => $name,
-                               'mtime' => $timestamp,
-                               'size' => $data['uncompressed size'],
-                       );
-                       call_user_func( $this->callback, $userData );
-               }
-       }
-
-       /**
-        * Interpret ZIP64 "extra field" data and return an associative array.
-        * @return array|bool
-        */
-       function unpackZip64Extra( $extraField ) {
-               $extraHeaderInfo = array(
-                       'id' => 2,
-                       'size' => 2,
-               );
-               $extraHeaderSize = $this->getStructSize( $extraHeaderInfo );
-
-               $zip64ExtraInfo = array(
-                       'uncompressed size' => 8,
-                       'compressed size' => 8,
-                       'local header offset' => 8,
-                       'disk number start' => 4,
-               );
-
-               $extraPos = 0;
-               while ( $extraPos < strlen( $extraField ) ) {
-                       $extra = $this->unpack( $extraField, $extraHeaderInfo, $extraPos );
-                       $extraPos += $extraHeaderSize;
-                       $extra += $this->unpack( $extraField,
-                               array( 'data' => array( 'string', $extra['size'] ) ),
-                               $extraPos );
-                       $extraPos += $extra['size'];
-
-                       if ( $extra['id'] == self::ZIP64_EXTRA_HEADER ) {
-                               return $this->unpack( $extra['data'], $zip64ExtraInfo );
-                       }
-               }
-
-               return false;
-       }
-
-       /**
-        * Get the length of the file.
-        */
-       function getFileLength() {
-               if ( $this->fileLength === null ) {
-                       $stat = fstat( $this->file );
-                       $this->fileLength = $stat['size'];
-               }
-               return $this->fileLength;
-       }
-
-       /**
-        * Get the file contents from a given offset. If there are not enough bytes
-        * in the file to satisfy the request, an exception will be thrown.
-        *
-        * @param int $start The byte offset of the start of the block.
-        * @param int $length The number of bytes to return. If omitted, the remainder
-        *    of the file will be returned.
-        *
-        * @return string
-        */
-       function getBlock( $start, $length = null ) {
-               $fileLength = $this->getFileLength();
-               if ( $start >= $fileLength ) {
-                       $this->error( 'zip-bad', "getBlock() requested position $start, " .
-                               "file length is $fileLength" );
-               }
-               if ( $length === null ) {
-                       $length = $fileLength - $start;
-               }
-               $end = $start + $length;
-               if ( $end > $fileLength ) {
-                       $this->error( 'zip-bad', "getBlock() requested end position $end, " .
-                               "file length is $fileLength" );
-               }
-               $startSeg = floor( $start / self::SEGSIZE );
-               $endSeg = ceil( $end / self::SEGSIZE );
-
-               $block = '';
-               for ( $segIndex = $startSeg; $segIndex <= $endSeg; $segIndex++ ) {
-                       $block .= $this->getSegment( $segIndex );
-               }
-
-               $block = substr( $block,
-                       $start - $startSeg * self::SEGSIZE,
-                       $length );
-
-               if ( strlen( $block ) < $length ) {
-                       $this->error( 'zip-bad', 'getBlock() returned an unexpectedly small amount of data' );
-               }
-
-               return $block;
-       }
-
-       /**
-        * Get a section of the file starting at position $segIndex * self::SEGSIZE,
-        * of length self::SEGSIZE. The result is cached. This is a helper function
-        * for getBlock().
-        *
-        * If there are not enough bytes in the file to satisfy the request, the
-        * return value will be truncated. If a request is made for a segment beyond
-        * the end of the file, an empty string will be returned.
-        * @return string
-        */
-       function getSegment( $segIndex ) {
-               if ( !isset( $this->buffer[$segIndex] ) ) {
-                       $bytePos = $segIndex * self::SEGSIZE;
-                       if ( $bytePos >= $this->getFileLength() ) {
-                               $this->buffer[$segIndex] = '';
-                               return '';
-                       }
-                       if ( fseek( $this->file, $bytePos ) ) {
-                               $this->error( 'zip-bad', "seek to $bytePos failed" );
-                       }
-                       $seg = fread( $this->file, self::SEGSIZE );
-                       if ( $seg === false ) {
-                               $this->error( 'zip-bad', "read from $bytePos failed" );
-                       }
-                       $this->buffer[$segIndex] = $seg;
-               }
-               return $this->buffer[$segIndex];
-       }
-
-       /**
-        * Get the size of a structure in bytes. See unpack() for the format of $struct.
-        * @return int
-        */
-       function getStructSize( $struct ) {
-               $size = 0;
-               foreach ( $struct as $type ) {
-                       if ( is_array( $type ) ) {
-                               list( , $fieldSize ) = $type;
-                               $size += $fieldSize;
-                       } else {
-                               $size += $type;
-                       }
-               }
-               return $size;
-       }
-
-       /**
-        * Unpack a binary structure. This is like the built-in unpack() function
-        * except nicer.
-        *
-        * @param string $string The binary data input
-        *
-        * @param array $struct An associative array giving structure members and their
-        *    types. In the key is the field name. The value may be either an
-        *    integer, in which case the field is a little-endian unsigned integer
-        *    encoded in the given number of bytes, or an array, in which case the
-        *    first element of the array is the type name, and the subsequent
-        *    elements are type-dependent parameters. Only one such type is defined:
-        *       - "string": The second array element gives the length of string.
-        *          Not null terminated.
-        *
-        * @param int $offset The offset into the string at which to start unpacking.
-        *
-        * @throws MWException
-        * @return array Unpacked associative array. Note that large integers in the input
-        *    may be represented as floating point numbers in the return value, so
-        *    the use of weak comparison is advised.
-        */
-       function unpack( $string, $struct, $offset = 0 ) {
-               $size = $this->getStructSize( $struct );
-               if ( $offset + $size > strlen( $string ) ) {
-                       $this->error( 'zip-bad', 'unpack() would run past the end of the supplied string' );
-               }
-
-               $data = array();
-               $pos = $offset;
-               foreach ( $struct as $key => $type ) {
-                       if ( is_array( $type ) ) {
-                               list( $typeName, $fieldSize ) = $type;
-                               switch ( $typeName ) {
-                               case 'string':
-                                       $data[$key] = substr( $string, $pos, $fieldSize );
-                                       $pos += $fieldSize;
-                                       break;
-                               default:
-                                       throw new MWException( __METHOD__ . ": invalid type \"$typeName\"" );
-                               }
-                       } else {
-                               // Unsigned little-endian integer
-                               $length = intval( $type );
-
-                               // Calculate the value. Use an algorithm which automatically
-                               // upgrades the value to floating point if necessary.
-                               $value = 0;
-                               for ( $i = $length - 1; $i >= 0; $i-- ) {
-                                       $value *= 256;
-                                       $value += ord( $string[$pos + $i] );
-                               }
-
-                               // Throw an exception if there was loss of precision
-                               if ( $value > pow( 2, 52 ) ) {
-                                       $this->error( 'zip-unsupported', 'number too large to be stored in a double. ' .
-                                               'This could happen if we tried to unpack a 64-bit structure ' .
-                                               'at an invalid location.' );
-                               }
-                               $data[$key] = $value;
-                               $pos += $length;
-                       }
-               }
-
-               return $data;
-       }
-
-       /**
-        * Returns a bit from a given position in an integer value, converted to
-        * boolean.
-        *
-        * @param $value integer
-        * @param int $bitIndex The index of the bit, where 0 is the LSB.
-        * @return bool
-        */
-       function testBit( $value, $bitIndex ) {
-               return (bool)( ( $value >> $bitIndex ) & 1 );
-       }
-
-       /**
-        * Debugging helper function which dumps a string in hexdump -C format.
-        */
-       function hexDump( $s ) {
-               $n = strlen( $s );
-               for ( $i = 0; $i < $n; $i += 16 ) {
-                       printf( "%08X ", $i );
-                       for ( $j = 0; $j < 16; $j++ ) {
-                               print " ";
-                               if ( $j == 8 ) {
-                                       print " ";
-                               }
-                               if ( $i + $j >= $n ) {
-                                       print "  ";
-                               } else {
-                                       printf( "%02X", ord( $s[$i + $j] ) );
-                               }
-                       }
-
-                       print "  |";
-                       for ( $j = 0; $j < 16; $j++ ) {
-                               if ( $i + $j >= $n ) {
-                                       print " ";
-                               } elseif ( ctype_print( $s[$i + $j] ) ) {
-                                       print $s[$i + $j];
-                               } else {
-                                       print '.';
-                               }
-                       }
-                       print "|\n";
-               }
-       }
-}
-
-/**
- * Internal exception class. Will be caught by private code.
- */
-class ZipDirectoryReaderError extends Exception {
-       var $errorCode;
-
-       function __construct( $code ) {
-               $this->errorCode = $code;
-               parent::__construct( "ZipDirectoryReader error: $code" );
-       }
-
-       /**
-        * @return mixed
-        */
-       function getErrorCode() {
-               return $this->errorCode;
-       }
-}
index bfdda7b..186ad46 100644 (file)
@@ -133,7 +133,8 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
         * @param string|null $key
         */
        public function addCachedHTML( $computeFunction, $args = array(), $key = null ) {
-               $this->getOutput()->addHTML( $this->cacheHelper->getCachedValue( $computeFunction, $args, $key ) );
+               $html = $this->cacheHelper->getCachedValue( $computeFunction, $args, $key );
+               $this->getOutput()->addHTML( $html );
        }
 
        /**
@@ -147,7 +148,8 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
        }
 
        /**
-        * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
+        * Sets the time to live for the cache, in seconds or a unix timestamp
+        * indicating the point of expiry.
         *
         * @since 1.20
         *
@@ -184,5 +186,4 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
                        $this->getOutput()->setSubtitle( $this->cacheHelper->getCachedNotice( $this->getContext() ) );
                }
        }
-
 }
index 0a2bf30..97c1605 100644 (file)
@@ -74,6 +74,7 @@ class CreditsAction extends FormlessAction {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $s;
        }
 
@@ -94,6 +95,7 @@ class CreditsAction extends FormlessAction {
                        $d = '';
                        $t = '';
                }
+
                return $this->msg( 'lastmodifiedatby', $d, $t )->rawParams(
                        $this->userLink( $user ) )->params( $user->getName() )->escaped();
        }
@@ -125,6 +127,7 @@ class CreditsAction extends FormlessAction {
                $anon_ips = array();
 
                # Sift for real versus user names
+               /** @var $user User */
                foreach ( $contributors as $user ) {
                        $cnt--;
                        if ( $user->isLoggedIn() ) {
@@ -175,6 +178,7 @@ class CreditsAction extends FormlessAction {
                }
 
                $count = count( $fulllist );
+
                # "Based on work by ..."
                return $count
                        ? $this->msg( 'othercontribs' )->rawParams(
index db7123d..069d570 100644 (file)
@@ -43,7 +43,5 @@ class DeleteAction extends FormlessAction {
        public function show() {
 
                $this->page->delete();
-
        }
-
 }
index 3dd4c48..72210a9 100644 (file)
@@ -49,9 +49,7 @@ class EditAction extends FormlessAction {
                        $editor = new EditPage( $page );
                        $editor->edit();
                }
-
        }
-
 }
 
 /**
@@ -75,5 +73,4 @@ class SubmitAction extends EditAction {
 
                parent::show();
        }
-
 }
index e58791e..34db1d2 100644 (file)
@@ -37,6 +37,9 @@ class HistoryAction extends FormlessAction {
        const DIR_PREV = 0;
        const DIR_NEXT = 1;
 
+       /** @var array Array of message keys and strings */
+       public $message;
+
        public function getName() {
                return 'history';
        }
@@ -122,6 +125,7 @@ class HistoryAction extends FormlessAction {
                if ( $feedType ) {
                        $this->feed( $feedType );
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -141,6 +145,7 @@ class HistoryAction extends FormlessAction {
                                )
                        );
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -162,7 +167,7 @@ class HistoryAction extends FormlessAction {
                }
                if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
                        $checkDeleted = Xml::checkLabel( $this->msg( 'history-show-deleted' )->text(),
-                       'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
+                               'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
                } else {
                        $checkDeleted = '';
                }
@@ -178,7 +183,10 @@ class HistoryAction extends FormlessAction {
                        ) .
                        Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n" .
                        Html::hidden( 'action', 'history' ) . "\n" .
-                       Xml::dateMenu( ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ), $month ) . '&#160;' .
+                       Xml::dateMenu(
+                               ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ),
+                               $month
+                       ) . '&#160;' .
                        ( $tagSelector ? ( implode( '&#160;', $tagSelector ) . '&#160;' ) : '' ) .
                        $checkDeleted .
                        Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" .
@@ -316,9 +324,10 @@ class HistoryAction extends FormlessAction {
                                $wgContLang->time( $rev->getTimestamp() ) )->inContentLanguage()->text();
                } else {
                        $title = $rev->getUserText() .
-                       $this->msg( 'colon-separator' )->inContentLanguage()->text() .
-                       FeedItem::stripComment( $rev->getComment() );
+                               $this->msg( 'colon-separator' )->inContentLanguage()->text() .
+                               FeedItem::stripComment( $rev->getComment() );
                }
+
                return new FeedItem(
                        $title,
                        $text,
@@ -335,14 +344,28 @@ class HistoryAction extends FormlessAction {
  * @ingroup Actions
  */
 class HistoryPager extends ReverseChronologicalPager {
-       public $lastRow = false, $counter, $historyPage, $buttons, $conds;
+       /**
+        * @var bool|stdClass
+        */
+       public $lastRow = false;
+
+       public $counter, $historyPage, $buttons, $conds;
+
        protected $oldIdChecked;
+
        protected $preventClickjacking = false;
        /**
         * @var array
         */
        protected $parentLens;
 
+       /**
+        * @param HistoryAction $historyPage
+        * @param string $year
+        * @param string $month
+        * @param string $tagFilter
+        * @param array $conds
+        */
        function __construct( $historyPage, $year = '', $month = '', $tagFilter = '', $conds = array() ) {
                parent::__construct( $historyPage->getContext() );
                $this->historyPage = $historyPage;
@@ -383,6 +406,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        $this->tagFilter
                );
                wfRunHooks( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
+
                return $queryInfo;
        }
 
@@ -390,6 +414,10 @@ class HistoryPager extends ReverseChronologicalPager {
                return 'rev_timestamp';
        }
 
+       /**
+        * @param stdClass $row
+        * @return string
+        */
        function formatRow( $row ) {
                if ( $this->lastRow ) {
                        $latest = ( $this->counter == 1 && $this->mIsFirst );
@@ -401,6 +429,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        $s = '';
                }
                $this->lastRow = $row;
+
                return $s;
        }
 
@@ -457,13 +486,15 @@ class HistoryPager extends ReverseChronologicalPager {
 
                $s .= $this->buttons;
                $s .= '<ul id="pagehistory">' . "\n";
+
                return $s;
        }
 
        private function getRevisionButton( $name, $msg ) {
                $this->preventClickjacking();
                # Note bug #20966, <button> is non-standard in IE<8
-               $element = Html::element( 'button',
+               $element = Html::element(
+                       'button',
                        array(
                                'type' => 'submit',
                                'name' => $name,
@@ -502,6 +533,7 @@ class HistoryPager extends ReverseChronologicalPager {
                        $s .= $this->buttons;
                }
                $s .= '</form>';
+
                return $s;
        }
 
@@ -526,16 +558,17 @@ class HistoryPager extends ReverseChronologicalPager {
         *
         * @todo document some more, and maybe clean up the code (some params redundant?)
         *
-        * @param $row Object: the database row corresponding to the previous line.
-        * @param $next Mixed: the database row corresponding to the next line. (chronologically previous)
-        * @param $notificationtimestamp
-        * @param $latest Boolean: whether this row corresponds to the page's latest revision.
-        * @param $firstInList Boolean: whether this row corresponds to the first displayed on this history page.
-        * @return String: HTML output for the row
+        * @param stdClass $row The database row corresponding to the previous line.
+        * @param mixed $next The database row corresponding to the next line
+        *   (chronologically previous)
+        * @param bool|string $notificationtimestamp
+        * @param bool $latest Whether this row corresponds to the page's latest revision.
+        * @param bool $firstInList Whether this row corresponds to the first
+        *   displayed on this history page.
+        * @return string HTML output for the row
         */
        function historyLine( $row, $next, $notificationtimestamp = false,
-               $latest = false, $firstInList = false )
-       {
+               $latest = false, $firstInList = false ) {
                $rev = new Revision( $row );
                $rev->setTitle( $this->getTitle() );
 
@@ -548,12 +581,14 @@ class HistoryPager extends ReverseChronologicalPager {
 
                $curlink = $this->curLink( $rev, $latest );
                $lastlink = $this->lastLink( $rev, $next );
-               $diffButtons = $this->diffButtons( $rev, $firstInList );
+               $curLastlinks = $curlink . $this->historyPage->message['pipe-separator'] . $lastlink;
                $histLinks = Html::rawElement(
-                               'span',
-                               array( 'class' => 'mw-history-histlinks' ),
-                               $this->msg( 'parentheses' )->rawParams( $curlink . $this->historyPage->message['pipe-separator'] . $lastlink )->escaped()
+                       'span',
+                       array( 'class' => 'mw-history-histlinks' ),
+                       $this->msg( 'parentheses' )->rawParams( $curLastlinks )->escaped()
                );
+
+               $diffButtons = $this->diffButtons( $rev, $firstInList );
                $s = $histLinks . $diffButtons;
 
                $link = $this->revLink( $rev );
@@ -627,7 +662,11 @@ class HistoryPager extends ReverseChronologicalPager {
                if ( $prevRev && $this->getTitle()->quickUserCan( 'edit', $user ) ) {
                        if ( $latest && $this->getTitle()->quickUserCan( 'rollback', $user ) ) {
                                // Get a rollback link without the brackets
-                               $rollbackLink = Linker::generateRollback( $rev, $this->getContext(), array( 'verify', 'noBrackets' ) );
+                               $rollbackLink = Linker::generateRollback(
+                                       $rev,
+                                       $this->getContext(),
+                                       array( 'verify', 'noBrackets' )
+                               );
                                if ( $rollbackLink ) {
                                        $this->preventClickjacking();
                                        $tools[] = $rollbackLink;
@@ -635,8 +674,8 @@ class HistoryPager extends ReverseChronologicalPager {
                        }
 
                        if ( !$rev->isDeleted( Revision::DELETED_TEXT )
-                               && !$prevRev->isDeleted( Revision::DELETED_TEXT ) )
-                       {
+                               && !$prevRev->isDeleted( Revision::DELETED_TEXT )
+                       {
                                # Create undo tooltip for the first (=latest) line only
                                $undoTooltip = $latest
                                        ? array( 'title' => $this->msg( 'tooltip-undo' )->text() )
@@ -705,6 +744,7 @@ class HistoryPager extends ReverseChronologicalPager {
                if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
                        $link = "<span class=\"history-deleted\">$link</span>";
                }
+
                return $link;
        }
 
@@ -758,8 +798,8 @@ class HistoryPager extends ReverseChronologicalPager {
                                )
                        );
                } elseif ( !$prevRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
-                       || !$nextRev->userCan( Revision::DELETED_TEXT, $this->getUser() ) )
-               {
+                       || !$nextRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+               {
                        return $last;
                } else {
                        return Linker::linkKnown(
@@ -816,6 +856,7 @@ class HistoryPager extends ReverseChronologicalPager {
                                array_merge( $radio, $checkmark, array(
                                        'name' => 'diff',
                                        'id' => "mw-diff-$id" ) ) );
+
                        return $first . $second;
                } else {
                        return '';
@@ -842,9 +883,11 @@ class HistoryPager extends ReverseChronologicalPager {
  * Backwards-compatibility alias
  */
 class HistoryPage extends HistoryAction {
-       public function __construct( Page $article ) { # Just to make it public
+       // @codingStandardsIgnoreStart Needed "useless" override to make it public.
+       public function __construct( Page $article ) {
                parent::__construct( $article );
        }
+       // @codingStandardsIgnoreEnd
 
        public function history() {
                $this->onView();
index 7fc9033..811e35d 100644 (file)
@@ -153,6 +153,7 @@ class InfoAction extends FormlessAction {
         */
        protected function makeHeader( $header ) {
                $spanAttribs = array( 'class' => 'mw-headline', 'id' => Sanitizer::escapeId( $header ) );
+
                return Html::rawElement( 'h2', array(), Html::element( 'span', $spanAttribs, $header ) );
        }
 
@@ -277,6 +278,12 @@ class InfoAction extends FormlessAction {
                        Language::fetchLanguageName( $pageLang, $lang->getCode() )
                        . ' ' . $this->msg( 'parentheses', $pageLang ) );
 
+               // Content model of the page
+               $pageInfo['header-basic'][] = array(
+                       $this->msg( 'pageinfo-content-model' ),
+                       ContentHandler::getLocalizedName( $title->getContentModel() )
+               );
+
                // Search engine status
                $pOutput = new ParserOutput();
                if ( isset( $pageProperties['noindex'] ) ) {
@@ -300,7 +307,7 @@ class InfoAction extends FormlessAction {
                if (
                        $user->isAllowed( 'unwatchedpages' ) ||
                        ( $wgUnwatchedPageThreshold !== false &&
-                         $pageCounts['watchers'] >= $wgUnwatchedPageThreshold )
+                               $pageCounts['watchers'] >= $wgUnwatchedPageThreshold )
                ) {
                        // Number of page watchers
                        $pageInfo['header-basic'][] = array(
@@ -730,6 +737,7 @@ class InfoAction extends FormlessAction {
                );
 
                wfProfileOut( __METHOD__ );
+
                return $result;
        }
 
@@ -755,6 +763,7 @@ class InfoAction extends FormlessAction {
                $anon_ips = array();
 
                # Sift for real versus user names
+               /** @var $user User */
                foreach ( $contributors as $user ) {
                        $page = $user->isAnon()
                                ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
@@ -797,6 +806,7 @@ class InfoAction extends FormlessAction {
                }
 
                $count = count( $fulllist );
+
                # "Based on work by ..."
                return $count
                        ? $this->msg( 'othercontribs' )->rawParams(
index ff6cf13..4016f67 100644 (file)
@@ -70,6 +70,7 @@ class MarkpatrolledAction extends FormlessAction {
                        $this->getOutput()->setPageTitle( $this->msg( 'markedaspatrollederror' ) );
                        $this->getOutput()->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
                        $this->getOutput()->returnToMain( null, $return );
+
                        return;
                }
 
index ec6648e..8b2bfaa 100644 (file)
@@ -43,9 +43,7 @@ class ProtectAction extends FormlessAction {
        public function show() {
 
                $this->page->protect();
-
        }
-
 }
 
 /**
@@ -64,7 +62,5 @@ class UnprotectAction extends ProtectAction {
        public function show() {
 
                $this->page->unprotect();
-
        }
-
 }
index 32751e4..a0116fb 100644 (file)
@@ -94,9 +94,14 @@ class RawAction extends FormlessAction {
                # Output may contain user-specific data;
                # vary generated content for open sessions on private wikis
                $privateCache = !User::isEveryoneAllowed( 'read' ) && ( $smaxage == 0 || session_id() != '' );
+               // Bug 53032 - make this private if user is logged in,
+               // so we don't accidentally cache cookies
+               $privateCache = $privateCache ?: $this->getUser()->isLoggedIn();
                # allow the client to cache this for 24 hours
                $mode = $privateCache ? 'private' : 'public';
-               $response->header( 'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage );
+               $response->header(
+                       'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage
+               );
 
                $text = $this->getRawText();
 
@@ -135,8 +140,9 @@ class RawAction extends FormlessAction {
 
                // If it's a MediaWiki message we can just hit the message cache
                if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) {
-                       // The first "true" is to use the database, the second is to use the content langue
-                       // and the last one is to specify the message key already contains the language in it ("/de", etc.)
+                       // The first "true" is to use the database, the second is to use
+                       // the content langue and the last one is to specify the message
+                       // key already contains the language in it ("/de", etc.).
                        $text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true );
                        // If the message doesn't exist, return a blank
                        if ( $text === false ) {
@@ -178,7 +184,11 @@ class RawAction extends FormlessAction {
                }
 
                if ( $text !== false && $text !== '' && $request->getVal( 'templates' ) === 'expand' ) {
-                       $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
+                       $text = $wgParser->preprocess(
+                               $text,
+                               $title,
+                               ParserOptions::newFromContext( $this->getContext() )
+                       );
                }
 
                return $text;
@@ -212,6 +222,7 @@ class RawAction extends FormlessAction {
                                $oldid = 0;
                                break;
                }
+
                return $oldid;
        }
 
@@ -273,6 +284,7 @@ class RawPage extends RawAction {
                if ( $this->mOldId !== null ) {
                        return $this->mOldId;
                }
+
                return parent::getOldId();
        }
 }
index 3d244fb..c9b3f8f 100644 (file)
@@ -43,7 +43,5 @@ class RenderAction extends FormlessAction {
        public function show() {
 
                $this->page->render();
-
        }
-
 }
index a5fc4e1..cdd139e 100644 (file)
@@ -38,7 +38,8 @@ class RevertAction extends Action {
                $this->getOutput()->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
        }
 
-       public function execute() {}
+       public function execute() {
+       }
 }
 
 /**
@@ -47,6 +48,9 @@ class RevertAction extends Action {
  * @ingroup Actions
  */
 class RevertFileAction extends FormAction {
+       /**
+        * @var OldLocalFile
+        */
        protected $oldFile;
 
        public function getName() {
@@ -63,12 +67,16 @@ class RevertFileAction extends FormAction {
                $oldimage = $this->getRequest()->getText( 'oldimage' );
                if ( strlen( $oldimage ) < 16
                        || strpos( $oldimage, '/' ) !== false
-                       || strpos( $oldimage, '\\' ) !== false )
-               {
+                       || strpos( $oldimage, '\\' ) !== false
+               {
                        throw new ErrorPageError( 'internalerror', 'unexpected', array( 'oldimage', $oldimage ) );
                }
 
-               $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->getTitle(), $oldimage );
+               $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName(
+                       $this->getTitle(),
+                       $oldimage
+               );
+
                if ( !$this->oldFile->exists() ) {
                        throw new ErrorPageError( '', 'filerevert-badversion' );
                }
@@ -99,8 +107,10 @@ class RevertFileAction extends FormAction {
                                'raw' => true,
                                'default' => $this->msg( 'filerevert-intro',
                                        $this->getTitle()->getText(), $userDate, $userTime,
-                                       wfExpandUrl( $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ),
-                                               PROTO_CURRENT ) )->parseAsBlock()
+                                       wfExpandUrl(
+                                               $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ),
+                                               PROTO_CURRENT
+                                       ) )->parseAsBlock()
                        ),
                        'comment' => array(
                                'type' => 'text',
@@ -112,10 +122,21 @@ class RevertFileAction extends FormAction {
        }
 
        public function onSubmit( $data ) {
-               $source = $this->page->getFile()->getArchiveVirtualUrl( $this->getRequest()->getText( 'oldimage' ) );
+               $source = $this->page->getFile()->getArchiveVirtualUrl(
+                       $this->getRequest()->getText( 'oldimage' )
+               );
                $comment = $data['comment'];
+
                // TODO: Preserve file properties from database instead of reloading from file
-               return $this->page->getFile()->upload( $source, $comment, $comment, 0, false, false, $this->getUser() );
+               return $this->page->getFile()->upload(
+                       $source,
+                       $comment,
+                       $comment,
+                       0,
+                       false,
+                       false,
+                       $this->getUser()
+               );
        }
 
        public function onSuccess() {
@@ -139,6 +160,7 @@ class RevertFileAction extends FormAction {
 
        protected function getDescription() {
                $this->getOutput()->addBacklinkSubtitle( $this->getTitle() );
+
                return '';
        }
 }
index 2949fa9..1803629 100644 (file)
@@ -49,6 +49,7 @@ class RevisiondeleteAction extends FormlessAction {
        public function show() {
                $special = SpecialPageFactory::getPage( 'Revisiondelete' );
                $special->setContext( $this->getContext() );
+               $special->getContext()->setTitle( $special->getTitle() );
                $special->run( '' );
        }
 }
index 81bad9d..d48a0ea 100644 (file)
@@ -53,7 +53,9 @@ class RollbackAction extends FormlessAction {
                        throw new ThrottledError;
                }
 
-               if ( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) {
+               if ( isset( $result[0][0] ) &&
+                       ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' )
+               ) {
                        $this->getOutput()->setPageTitle( $this->msg( 'rollbackfailed' ) );
                        $errArray = $result[0];
                        $errMsg = array_shift( $errArray );
@@ -91,12 +93,21 @@ class RollbackAction extends FormlessAction {
 
                $old = Linker::revUserTools( $current );
                $new = Linker::revUserTools( $target );
-               $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )->parseAsBlock() );
+               $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )
+                       ->parseAsBlock() );
                $this->getOutput()->returnToMain( false, $this->getTitle() );
 
-               if ( !$request->getBool( 'hidediff', false ) && !$this->getUser()->getBoolOption( 'norollbackdiff', false ) ) {
+               if ( !$request->getBool( 'hidediff', false ) &&
+                       !$this->getUser()->getBoolOption( 'norollbackdiff', false )
+               ) {
                        $contentHandler = $current->getContentHandler();
-                       $de = $contentHandler->createDifferenceEngine( $this->getContext(), $current->getId(), $newId, false, true );
+                       $de = $contentHandler->createDifferenceEngine(
+                               $this->getContext(),
+                               $current->getId(),
+                               $newId,
+                               false,
+                               true
+                       );
                        $de->showDiff( '', '' );
                }
        }
index e227197..3a24565 100644 (file)
@@ -43,5 +43,4 @@ class ViewAction extends FormlessAction {
        public function show() {
                $this->page->view();
        }
-
 }
index 929c1b5..e1b5d52 100644 (file)
@@ -51,6 +51,7 @@ class WatchAction extends FormAction {
                wfProfileIn( __METHOD__ );
                self::doWatch( $this->getTitle(), $this->getUser() );
                wfProfileOut( __METHOD__ );
+
                return true;
        }
 
@@ -96,7 +97,9 @@ class WatchAction extends FormAction {
         * @return Status
         */
        public static function doWatchOrUnwatch( $watch, Title $title, User $user ) {
-               if ( $user->isLoggedIn() && $user->isWatched( $title, WatchedItem::IGNORE_USER_RIGHTS ) != $watch ) {
+               if ( $user->isLoggedIn() &&
+                       $user->isWatched( $title, WatchedItem::IGNORE_USER_RIGHTS ) != $watch
+               ) {
                        // If the user doesn't have 'editmywatchlist', we still want to
                        // allow them to add but not remove items via edits and such.
                        if ( $watch ) {
@@ -105,6 +108,7 @@ class WatchAction extends FormAction {
                                return self::doUnwatch( $title, $user );
                        }
                }
+
                return Status::newGood();
        }
 
@@ -116,8 +120,12 @@ class WatchAction extends FormAction {
         * @param int $checkRights Passed through to $user->addWatch()
         * @return Status
         */
-       public static function doWatch( Title $title, User $user, $checkRights = WatchedItem::CHECK_USER_RIGHTS ) {
-               if ( $checkRights !== WatchedItem::IGNORE_USER_RIGHTS && !$user->isAllowed( 'editmywatchlist' ) ) {
+       public static function doWatch( Title $title, User $user,
+               $checkRights = WatchedItem::CHECK_USER_RIGHTS
+       ) {
+               if ( $checkRights !== WatchedItem::IGNORE_USER_RIGHTS &&
+                       !$user->isAllowed( 'editmywatchlist' )
+               ) {
                        return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
                }
 
@@ -129,6 +137,7 @@ class WatchAction extends FormAction {
                        $user->addWatch( $title, $checkRights );
                        wfRunHooks( 'WatchArticleComplete', array( &$user, &$page ) );
                }
+
                return $status;
        }
 
@@ -152,6 +161,7 @@ class WatchAction extends FormAction {
                        $user->removeWatch( $title );
                        wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$page ) );
                }
+
                return $status;
        }
 
@@ -220,6 +230,7 @@ class UnwatchAction extends WatchAction {
                wfProfileIn( __METHOD__ );
                self::doUnwatch( $this->getTitle(), $this->getUser() );
                wfProfileOut( __METHOD__ );
+
                return true;
        }
 
index ce6ecda..b6a7ca8 100644 (file)
  * The class functions are divided into several areas of functionality:
  *
  * Module parameters: Derived classes can define getAllowedParams() to specify
- *     which parameters to expect, how to parse and validate them.
+ *    which parameters to expect, how to parse and validate them.
  *
  * Profiling: various methods to allow keeping tabs on various tasks and their
- *     time costs
+ *    time costs
  *
  * Self-documentation: code to allow the API to document its own state
  *
  * @ingroup API
  */
 abstract class ApiBase extends ContextSource {
-
        // These constants allow modules to specify exactly how to treat incoming parameters.
 
-       const PARAM_DFLT = 0; // Default value of the parameter
-       const PARAM_ISMULTI = 1; // Boolean, do we accept more than one item for this parameter (e.g.: titles)?
-       const PARAM_TYPE = 2; // Can be either a string type (e.g.: 'integer') or an array of allowed values
-       const PARAM_MAX = 3; // Max value allowed for a parameter. Only applies if TYPE='integer'
-       const PARAM_MAX2 = 4; // Max value allowed for a parameter for bots and sysops. Only applies if TYPE='integer'
-       const PARAM_MIN = 5; // Lowest value allowed for a parameter. Only applies if TYPE='integer'
-       const PARAM_ALLOW_DUPLICATES = 6; // Boolean, do we allow the same value to be set more than once when ISMULTI=true
-       const PARAM_DEPRECATED = 7; // Boolean, is the parameter deprecated (will show a warning)
+       // Default value of the parameter
+       const PARAM_DFLT = 0;
+       // Boolean, do we accept more than one item for this parameter (e.g.: titles)?
+       const PARAM_ISMULTI = 1;
+       // Can be either a string type (e.g.: 'integer') or an array of allowed values
+       const PARAM_TYPE = 2;
+       // Max value allowed for a parameter. Only applies if TYPE='integer'
+       const PARAM_MAX = 3;
+       // Max value allowed for a parameter for bots and sysops. Only applies if TYPE='integer'
+       const PARAM_MAX2 = 4;
+       // Lowest value allowed for a parameter. Only applies if TYPE='integer'
+       const PARAM_MIN = 5;
+       // Boolean, do we allow the same value to be set more than once when ISMULTI=true
+       const PARAM_ALLOW_DUPLICATES = 6;
+       // Boolean, is the parameter deprecated (will show a warning)
+       const PARAM_DEPRECATED = 7;
        /// @since 1.17
        const PARAM_REQUIRED = 8; // Boolean, is the parameter required?
        /// @since 1.17
-       const PARAM_RANGE_ENFORCE = 9; // Boolean, if MIN/MAX are set, enforce (die) these? Only applies if TYPE='integer' Use with extreme caution
-
-       const PROP_ROOT = 'ROOT'; // Name of property group that is on the root element of the result, i.e. not part of a list
-       const PROP_LIST = 'LIST'; // Boolean, is the result multiple items? Defaults to true for query modules, to false for other modules
+       // Boolean, if MIN/MAX are set, enforce (die) these?
+       // Only applies if TYPE='integer' Use with extreme caution
+       const PARAM_RANGE_ENFORCE = 9;
+
+       // Name of property group that is on the root element of the result,
+       // i.e. not part of a list
+       const PROP_ROOT = 'ROOT';
+       // Boolean, is the result multiple items? Defaults to true for query modules,
+       // to false for other modules
+       const PROP_LIST = 'LIST';
        const PROP_TYPE = 0; // Type of the property, uses same format as PARAM_TYPE
-       const PROP_NULLABLE = 1; // Boolean, can the property be not included in the result? Defaults to false
+       // Boolean, can the property be not included in the result? Defaults to false
+       const PROP_NULLABLE = 1;
 
        const LIMIT_BIG1 = 500; // Fast query, std user limit
        const LIMIT_BIG2 = 5000; // Fast query, bot/sysop limit
@@ -124,6 +138,7 @@ abstract class ApiBase extends ContextSource {
         */
        public function getVersion() {
                wfDeprecated( __METHOD__, '1.21' );
+
                return '';
        }
 
@@ -162,9 +177,9 @@ abstract class ApiBase extends ContextSource {
        public function getModuleProfileName( $db = false ) {
                if ( $db ) {
                        return 'API:' . $this->mModuleName . '-DB';
-               } else {
-                       return 'API:' . $this->mModuleName;
                }
+
+               return 'API:' . $this->mModuleName;
        }
 
        /**
@@ -194,6 +209,7 @@ abstract class ApiBase extends ContextSource {
                if ( $this->isMain() ) {
                        ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
                }
+
                return $this->getMain()->getResult();
        }
 
@@ -216,6 +232,7 @@ abstract class ApiBase extends ContextSource {
         */
        public function createContext() {
                wfDeprecated( __METHOD__, '1.19' );
+
                return new DerivativeContext( $this->getContext() );
        }
 
@@ -293,7 +310,8 @@ abstract class ApiBase extends ContextSource {
                                $msg .= "\nThis module only accepts POST requests";
                        }
                        if ( $this->isReadMode() || $this->isWriteMode() ||
-                                       $this->mustBePosted() ) {
+                               $this->mustBePosted()
+                       ) {
                                $msg .= "\n";
                        }
 
@@ -359,8 +377,10 @@ abstract class ApiBase extends ContextSource {
                                $msg = '  ';
                        }
                        $msg .= implode( $prefix, $input ) . "\n";
+
                        return $msg;
                }
+
                return '';
        }
 
@@ -392,7 +412,9 @@ abstract class ApiBase extends ContextSource {
 
                                //handle missing type
                                if ( !isset( $paramSettings[ApiBase::PARAM_TYPE] ) ) {
-                                       $dflt = isset( $paramSettings[ApiBase::PARAM_DFLT] ) ? $paramSettings[ApiBase::PARAM_DFLT] : null;
+                                       $dflt = isset( $paramSettings[ApiBase::PARAM_DFLT] )
+                                               ? $paramSettings[ApiBase::PARAM_DFLT]
+                                               : null;
                                        if ( is_bool( $dflt ) ) {
                                                $paramSettings[ApiBase::PARAM_TYPE] = 'boolean';
                                        } elseif ( is_string( $dflt ) || is_null( $dflt ) ) {
@@ -402,18 +424,26 @@ abstract class ApiBase extends ContextSource {
                                        }
                                }
 
-                               if ( isset( $paramSettings[self::PARAM_DEPRECATED] ) && $paramSettings[self::PARAM_DEPRECATED] ) {
+                               if ( isset( $paramSettings[self::PARAM_DEPRECATED] )
+                                       && $paramSettings[self::PARAM_DEPRECATED]
+                               ) {
                                        $desc = "DEPRECATED! $desc";
                                }
 
-                               if ( isset( $paramSettings[self::PARAM_REQUIRED] ) && $paramSettings[self::PARAM_REQUIRED] ) {
+                               if ( isset( $paramSettings[self::PARAM_REQUIRED] )
+                                       && $paramSettings[self::PARAM_REQUIRED]
+                               ) {
                                        $desc .= $paramPrefix . "This parameter is required";
                                }
 
-                               $type = isset( $paramSettings[self::PARAM_TYPE] ) ? $paramSettings[self::PARAM_TYPE] : null;
+                               $type = isset( $paramSettings[self::PARAM_TYPE] )
+                                       ? $paramSettings[self::PARAM_TYPE]
+                                       : null;
                                if ( isset( $type ) ) {
                                        $hintPipeSeparated = true;
-                                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] ) ? $paramSettings[self::PARAM_ISMULTI] : false;
+                                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
+                                               ? $paramSettings[self::PARAM_ISMULTI]
+                                               : false;
                                        if ( $multi ) {
                                                $prompt = 'Values (separate with \'|\'): ';
                                        } else {
@@ -437,7 +467,8 @@ abstract class ApiBase extends ContextSource {
                                        } else {
                                                switch ( $type ) {
                                                        case 'namespace':
-                                                               // Special handling because namespaces are type-limited, yet they are not given
+                                                               // Special handling because namespaces are
+                                                               // type-limited, yet they are not given
                                                                $desc .= $paramPrefix . $prompt;
                                                                $desc .= wordwrap( implode( ', ', MWNamespace::getValidNamespaces() ),
                                                                        100, $descWordwrap );
@@ -456,11 +487,14 @@ abstract class ApiBase extends ContextSource {
                                                                $hasMax = isset( $paramSettings[self::PARAM_MAX] );
                                                                if ( $hasMin || $hasMax ) {
                                                                        if ( !$hasMax ) {
-                                                                               $intRangeStr = "The value$s must be no less than {$paramSettings[self::PARAM_MIN]}";
+                                                                               $intRangeStr = "The value$s must be no less than " .
+                                                                                       "{$paramSettings[self::PARAM_MIN]}";
                                                                        } elseif ( !$hasMin ) {
-                                                                               $intRangeStr = "The value$s must be no more than {$paramSettings[self::PARAM_MAX]}";
+                                                                               $intRangeStr = "The value$s must be no more than " .
+                                                                                       "{$paramSettings[self::PARAM_MAX]}";
                                                                        } else {
-                                                                               $intRangeStr = "The value$s must be between {$paramSettings[self::PARAM_MIN]} and {$paramSettings[self::PARAM_MAX]}";
+                                                                               $intRangeStr = "The value$s must be between " .
+                                                                                       "{$paramSettings[self::PARAM_MIN]} and {$paramSettings[self::PARAM_MAX]}";
                                                                        }
 
                                                                        $desc .= $paramPrefix . $intRangeStr;
@@ -479,9 +513,10 @@ abstract class ApiBase extends ContextSource {
 
                                                $isArray = is_array( $type );
                                                if ( !$isArray
-                                                               || $isArray && count( $type ) > self::LIMIT_SML1 ) {
+                                                       || $isArray && count( $type ) > self::LIMIT_SML1
+                                               ) {
                                                        $desc .= $paramPrefix . "Maximum number of values " .
-                                                                       self::LIMIT_SML1 . " (" . self::LIMIT_SML2 . " for bots)";
+                                                               self::LIMIT_SML1 . " (" . self::LIMIT_SML2 . " for bots)";
                                                }
                                        }
                                }
@@ -493,11 +528,11 @@ abstract class ApiBase extends ContextSource {
 
                                $msg .= sprintf( "  %-19s - %s\n", $this->encodeParamName( $paramName ), $desc );
                        }
-                       return $msg;
 
-               } else {
-                       return false;
+                       return $msg;
                }
+
+               return false;
        }
 
        /**
@@ -555,6 +590,7 @@ abstract class ApiBase extends ContextSource {
        public function getFinalParams( $flags = 0 ) {
                $params = $this->getAllowedParams( $flags );
                wfRunHooks( 'APIGetAllowedParams', array( &$this, &$params, $flags ) );
+
                return $params;
        }
 
@@ -567,6 +603,7 @@ abstract class ApiBase extends ContextSource {
        public function getFinalParamDescription() {
                $desc = $this->getParamDescription();
                wfRunHooks( 'APIGetParamDescription', array( &$this, &$desc ) );
+
                return $desc;
        }
 
@@ -599,6 +636,7 @@ abstract class ApiBase extends ContextSource {
        public function getFinalResultProperties() {
                $properties = $this->getResultProperties();
                wfRunHooks( 'APIGetResultProperties', array( $this, &$properties ) );
+
                return $properties;
        }
 
@@ -624,6 +662,7 @@ abstract class ApiBase extends ContextSource {
        public function getFinalDescription() {
                $desc = $this->getDescription();
                wfRunHooks( 'APIGetDescription', array( &$this, &$desc ) );
+
                return $desc;
        }
 
@@ -660,6 +699,7 @@ abstract class ApiBase extends ContextSource {
                        }
                        $this->mParamCache[$parseLimit] = $results;
                }
+
                return $this->mParamCache[$parseLimit];
        }
 
@@ -672,6 +712,7 @@ abstract class ApiBase extends ContextSource {
        protected function getParameter( $paramName, $parseLimit = true ) {
                $params = $this->getFinalParams();
                $paramSettings = $params[$paramName];
+
                return $this->getParameterFromSettings( $paramName, $paramSettings, $parseLimit );
        }
 
@@ -688,9 +729,14 @@ abstract class ApiBase extends ContextSource {
                        array( $this, "parameterNotEmpty" ) ) ), $required );
 
                if ( count( $intersection ) > 1 ) {
-                       $this->dieUsage( "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together', 'invalidparammix' );
+                       $this->dieUsage(
+                               "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together',
+                               'invalidparammix' );
                } elseif ( count( $intersection ) == 0 ) {
-                       $this->dieUsage( "One of the parameters {$p}" . implode( ", {$p}", $required ) . ' is required', 'missingparam' );
+                       $this->dieUsage(
+                               "One of the parameters {$p}" . implode( ", {$p}", $required ) . ' is required',
+                               'missingparam'
+                       );
                }
        }
 
@@ -705,8 +751,14 @@ abstract class ApiBase extends ContextSource {
                $params = implode( ", {$p}", $params );
 
                return array(
-                       array( 'code' => "{$p}missingparam", 'info' => "One of the parameters {$p}{$params} is required" ),
-                       array( 'code' => "{$p}invalidparammix", 'info' => "The parameters {$p}{$params} can not be used together" )
+                       array(
+                               'code' => "{$p}missingparam",
+                               'info' => "One of the parameters {$p}{$params} is required"
+                       ),
+                       array(
+                               'code' => "{$p}invalidparammix",
+                               'info' => "The parameters {$p}{$params} can not be used together"
+                       )
                );
        }
 
@@ -724,7 +776,10 @@ abstract class ApiBase extends ContextSource {
                        array( $this, "parameterNotEmpty" ) ) ), $required );
 
                if ( count( $intersection ) > 1 ) {
-                       $this->dieUsage( "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together', 'invalidparammix' );
+                       $this->dieUsage(
+                               "The parameters {$p}" . implode( ", {$p}", $intersection ) . ' can not be used together',
+                               'invalidparammix'
+                       );
                }
        }
 
@@ -739,7 +794,10 @@ abstract class ApiBase extends ContextSource {
                $params = implode( ", {$p}", $params );
 
                return array(
-                       array( 'code' => "{$p}invalidparammix", 'info' => "The parameters {$p}{$params} can not be used together" )
+                       array(
+                               'code' => "{$p}invalidparammix",
+                               'info' => "The parameters {$p}{$params} can not be used together"
+                       )
                );
        }
 
@@ -810,6 +868,7 @@ abstract class ApiBase extends ContextSource {
         */
        public static function getValidNamespaces() {
                wfDeprecated( __METHOD__, '1.17' );
+
                return MWNamespace::getValidNamespaces();
        }
 
@@ -818,7 +877,7 @@ abstract class ApiBase extends ContextSource {
         * @param string $watchlist Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
         * @param $titleObj Title the page under consideration
         * @param string $userOption The user option to consider when $watchlist=preferences.
-        *      If not set will magically default to either watchdefault or watchcreations
+        *    If not set will use watchdefault always and watchcreations if $titleObj doesn't exist.
         * @return bool
         */
        protected function getWatchlistValue( $watchlist, $titleObj, $userOption = null ) {
@@ -837,11 +896,12 @@ abstract class ApiBase extends ContextSource {
                                if ( $userWatching ) {
                                        return true;
                                }
-                               # If no user option was passed, use watchdefault or watchcreations
+                               # If no user option was passed, use watchdefault and watchcreations
                                if ( is_null( $userOption ) ) {
-                                       $userOption = $titleObj->exists()
-                                                       ? 'watchdefault' : 'watchcreations';
+                                       return $this->getUser()->getBoolOption( 'watchdefault' ) ||
+                                               $this->getUser()->getBoolOption( 'watchcreations' ) && !$titleObj->exists();
                                }
+
                                # Watch the article based on the user preference
                                return $this->getUser()->getBoolOption( $userOption );
 
@@ -889,12 +949,24 @@ abstract class ApiBase extends ContextSource {
                        $deprecated = false;
                        $required = false;
                } else {
-                       $default = isset( $paramSettings[self::PARAM_DFLT] ) ? $paramSettings[self::PARAM_DFLT] : null;
-                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] ) ? $paramSettings[self::PARAM_ISMULTI] : false;
-                       $type = isset( $paramSettings[self::PARAM_TYPE] ) ? $paramSettings[self::PARAM_TYPE] : null;
-                       $dupes = isset( $paramSettings[self::PARAM_ALLOW_DUPLICATES] ) ? $paramSettings[self::PARAM_ALLOW_DUPLICATES] : false;
-                       $deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] ) ? $paramSettings[self::PARAM_DEPRECATED] : false;
-                       $required = isset( $paramSettings[self::PARAM_REQUIRED] ) ? $paramSettings[self::PARAM_REQUIRED] : false;
+                       $default = isset( $paramSettings[self::PARAM_DFLT] )
+                               ? $paramSettings[self::PARAM_DFLT]
+                               : null;
+                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
+                               ? $paramSettings[self::PARAM_ISMULTI]
+                               : false;
+                       $type = isset( $paramSettings[self::PARAM_TYPE] )
+                               ? $paramSettings[self::PARAM_TYPE]
+                               : null;
+                       $dupes = isset( $paramSettings[self::PARAM_ALLOW_DUPLICATES] )
+                               ? $paramSettings[self::PARAM_ALLOW_DUPLICATES]
+                               : false;
+                       $deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] )
+                               ? $paramSettings[self::PARAM_DEPRECATED]
+                               : false;
+                       $required = isset( $paramSettings[self::PARAM_REQUIRED] )
+                               ? $paramSettings[self::PARAM_REQUIRED]
+                               : false;
 
                        // When type is not given, and no choices, the type is the same as $default
                        if ( !isset( $type ) ) {
@@ -909,14 +981,21 @@ abstract class ApiBase extends ContextSource {
                if ( $type == 'boolean' ) {
                        if ( isset( $default ) && $default !== false ) {
                                // Having a default value of anything other than 'false' is not allowed
-                               ApiBase::dieDebug( __METHOD__, "Boolean param $encParamName's default is set to '$default'. Boolean parameters must default to false." );
+                               ApiBase::dieDebug(
+                                       __METHOD__,
+                                       "Boolean param $encParamName's default is set to '$default'. " .
+                                               "Boolean parameters must default to false."
+                               );
                        }
 
                        $value = $this->getMain()->getCheck( $encParamName );
                } elseif ( $type == 'upload' ) {
                        if ( isset( $default ) ) {
                                // Having a default value is not allowed
-                               ApiBase::dieDebug( __METHOD__, "File upload param $encParamName's default is set to '$default'. File upload parameters may not have a default." );
+                               ApiBase::dieDebug(
+                                       __METHOD__,
+                                       "File upload param $encParamName's default is set to " .
+                                               "'$default'. File upload parameters may not have a default." );
                        }
                        if ( $multi ) {
                                ApiBase::dieDebug( __METHOD__, "Multi-values not supported for $encParamName" );
@@ -930,8 +1009,8 @@ abstract class ApiBase extends ContextSource {
                                if ( $value !== null ) {
                                        $this->dieUsage(
                                                "File upload param $encParamName is not a file upload; " .
-                                               "be sure to use multipart/form-data for your POST and include " .
-                                               "a filename in the Content-Disposition header.",
+                                                       "be sure to use multipart/form-data for your POST and include " .
+                                                       "a filename in the Content-Disposition header.",
                                                "badupload_{$encParamName}"
                                        );
                                }
@@ -945,7 +1024,12 @@ abstract class ApiBase extends ContextSource {
                }
 
                if ( isset( $value ) && ( $multi || is_array( $type ) ) ) {
-                       $value = $this->parseMultiValue( $encParamName, $value, $multi, is_array( $type ) ? $type : null );
+                       $value = $this->parseMultiValue(
+                               $encParamName,
+                               $value,
+                               $multi,
+                               is_array( $type ) ? $type : null
+                       );
                }
 
                // More validation only when choices were not given
@@ -964,7 +1048,7 @@ abstract class ApiBase extends ContextSource {
                                                $min = isset( $paramSettings[self::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : null;
                                                $max = isset( $paramSettings[self::PARAM_MAX] ) ? $paramSettings[self::PARAM_MAX] : null;
                                                $enforceLimits = isset( $paramSettings[self::PARAM_RANGE_ENFORCE] )
-                                                               ? $paramSettings[self::PARAM_RANGE_ENFORCE] : false;
+                                                       ? $paramSettings[self::PARAM_RANGE_ENFORCE] : false;
 
                                                if ( is_array( $value ) ) {
                                                        $value = array_map( 'intval', $value );
@@ -985,19 +1069,32 @@ abstract class ApiBase extends ContextSource {
                                                        // Don't do any validation whatsoever
                                                        break;
                                                }
-                                               if ( !isset( $paramSettings[self::PARAM_MAX] ) || !isset( $paramSettings[self::PARAM_MAX2] ) ) {
-                                                       ApiBase::dieDebug( __METHOD__, "MAX1 or MAX2 are not defined for the limit $encParamName" );
+                                               if ( !isset( $paramSettings[self::PARAM_MAX] )
+                                                       || !isset( $paramSettings[self::PARAM_MAX2] )
+                                               ) {
+                                                       ApiBase::dieDebug(
+                                                               __METHOD__,
+                                                               "MAX1 or MAX2 are not defined for the limit $encParamName"
+                                                       );
                                                }
                                                if ( $multi ) {
                                                        ApiBase::dieDebug( __METHOD__, "Multi-values not supported for $encParamName" );
                                                }
                                                $min = isset( $paramSettings[self::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : 0;
                                                if ( $value == 'max' ) {
-                                                       $value = $this->getMain()->canApiHighLimits() ? $paramSettings[self::PARAM_MAX2] : $paramSettings[self::PARAM_MAX];
+                                                       $value = $this->getMain()->canApiHighLimits()
+                                                               ? $paramSettings[self::PARAM_MAX2]
+                                                               : $paramSettings[self::PARAM_MAX];
                                                        $this->getResult()->setParsedLimit( $this->getModuleName(), $value );
                                                } else {
                                                        $value = intval( $value );
-                                                       $this->validateLimit( $paramName, $value, $min, $paramSettings[self::PARAM_MAX], $paramSettings[self::PARAM_MAX2] );
+                                                       $this->validateLimit(
+                                                               $paramName,
+                                                               $value,
+                                                               $min,
+                                                               $paramSettings[self::PARAM_MAX],
+                                                               $paramSettings[self::PARAM_MAX2]
+                                                       );
                                                }
                                                break;
                                        case 'boolean':
@@ -1064,13 +1161,16 @@ abstract class ApiBase extends ContextSource {
                        return array();
                }
 
-               // This is a bit awkward, but we want to avoid calling canApiHighLimits() because it unstubs $wgUser
+               // This is a bit awkward, but we want to avoid calling canApiHighLimits()
+               // because it unstubs $wgUser
                $valuesList = explode( '|', $value, self::LIMIT_SML2 + 1 );
-               $sizeLimit = count( $valuesList ) > self::LIMIT_SML1 && $this->mMainModule->canApiHighLimits() ?
-                               self::LIMIT_SML2 : self::LIMIT_SML1;
+               $sizeLimit = count( $valuesList ) > self::LIMIT_SML1 && $this->mMainModule->canApiHighLimits()
+                       ? self::LIMIT_SML2
+                       : self::LIMIT_SML1;
 
                if ( self::truncateArray( $valuesList, $sizeLimit ) ) {
-                       $this->setWarning( "Too many values supplied for parameter '$valueName': the limit is $sizeLimit" );
+                       $this->setWarning( "Too many values supplied for parameter '$valueName': " .
+                               "the limit is $sizeLimit" );
                }
 
                if ( !$allowMultiple && count( $valuesList ) != 1 ) {
@@ -1079,8 +1179,13 @@ abstract class ApiBase extends ContextSource {
                                return $value;
                        }
 
-                       $possibleValues = is_array( $allowedValues ) ? "of '" . implode( "', '", $allowedValues ) . "'" : '';
-                       $this->dieUsage( "Only one $possibleValues is allowed for parameter '$valueName'", "multival_$valueName" );
+                       $possibleValues = is_array( $allowedValues )
+                               ? "of '" . implode( "', '", $allowedValues ) . "'"
+                               : '';
+                       $this->dieUsage(
+                               "Only one $possibleValues is allowed for parameter '$valueName'",
+                               "multival_$valueName"
+                       );
                }
 
                if ( is_array( $allowedValues ) ) {
@@ -1092,7 +1197,10 @@ abstract class ApiBase extends ContextSource {
                                        $vals = implode( ", ", $unknown );
                                        $this->setWarning( "Unrecognized value$s for parameter '$valueName': $vals" );
                                } else {
-                                       $this->dieUsage( "Unrecognized value for parameter '$valueName': {$valuesList[0]}", "unknown_$valueName" );
+                                       $this->dieUsage(
+                                               "Unrecognized value for parameter '$valueName': {$valuesList[0]}",
+                                               "unknown_$valueName"
+                                       );
                                }
                        }
                        // Now throw them out
@@ -1120,7 +1228,8 @@ abstract class ApiBase extends ContextSource {
                        $value = $min;
                }
 
-               // Minimum is always validated, whereas maximum is checked only if not running in internal call mode
+               // Minimum is always validated, whereas maximum is checked only if not
+               // running in internal call mode
                if ( $this->getMain()->isInternalMode() ) {
                        return;
                }
@@ -1130,7 +1239,8 @@ abstract class ApiBase extends ContextSource {
                if ( !is_null( $max ) && $value > $max ) {
                        if ( !is_null( $botMax ) && $this->getMain()->canApiHighLimits() ) {
                                if ( $value > $botMax ) {
-                                       $msg = $this->encodeParamName( $paramName ) . " may not be over $botMax (set to $value) for bots or sysops";
+                                       $msg = $this->encodeParamName( $paramName ) .
+                                               " may not be over $botMax (set to $value) for bots or sysops";
                                        $this->warnOrDie( $msg, $enforceLimits );
                                        $value = $botMax;
                                }
@@ -1151,8 +1261,12 @@ abstract class ApiBase extends ContextSource {
        function validateTimestamp( $value, $encParamName ) {
                $unixTimestamp = wfTimestamp( TS_UNIX, $value );
                if ( $unixTimestamp === false ) {
-                       $this->dieUsage( "Invalid value '$value' for timestamp parameter $encParamName", "badtimestamp_{$encParamName}" );
+                       $this->dieUsage(
+                               "Invalid value '$value' for timestamp parameter $encParamName",
+                               "badtimestamp_{$encParamName}"
+                       );
                }
+
                return wfTimestamp( TS_MW, $unixTimestamp );
        }
 
@@ -1165,8 +1279,12 @@ abstract class ApiBase extends ContextSource {
        private function validateUser( $value, $encParamName ) {
                $title = Title::makeTitleSafe( NS_USER, $value );
                if ( $title === null ) {
-                       $this->dieUsage( "Invalid value '$value' for user parameter $encParamName", "baduser_{$encParamName}" );
+                       $this->dieUsage(
+                               "Invalid value '$value' for user parameter $encParamName",
+                               "baduser_{$encParamName}"
+                       );
                }
+
                return $title->getText();
        }
 
@@ -1179,9 +1297,9 @@ abstract class ApiBase extends ContextSource {
        private function warnOrDie( $msg, $enforceLimits = false ) {
                if ( $enforceLimits ) {
                        $this->dieUsage( $msg, 'integeroutofrange' );
-               } else {
-                       $this->setWarning( $msg );
                }
+
+               $this->setWarning( $msg );
        }
 
        /**
@@ -1196,6 +1314,7 @@ abstract class ApiBase extends ContextSource {
                        array_pop( $arr );
                        $modified = true;
                }
+
                return $modified;
        }
 
@@ -1213,7 +1332,12 @@ abstract class ApiBase extends ContextSource {
         */
        public function dieUsage( $description, $errorCode, $httpRespCode = 0, $extradata = null ) {
                Profiler::instance()->close();
-               throw new UsageException( $description, $this->encodeParamName( $errorCode ), $httpRespCode, $extradata );
+               throw new UsageException(
+                       $description,
+                       $this->encodeParamName( $errorCode ),
+                       $httpRespCode,
+                       $extradata
+               );
        }
 
        /**
@@ -1221,7 +1345,7 @@ abstract class ApiBase extends ContextSource {
         *
         * @since 1.22
         * @param Status $status Status object
-        * @throws UsageException
+        * @throws MWException
         */
        public function dieStatus( $status ) {
                if ( $status->isGood() ) {
@@ -1254,6 +1378,7 @@ abstract class ApiBase extends ContextSource {
                $this->dieUsage( $msg->inLanguage( 'en' )->useDatabase( false )->plain(), $code );
        }
 
+       // @codingStandardsIgnoreStart Allow long lines. Cannot split these.
        /**
         * Array that maps message keys to error messages. $1 and friends are replaced.
         */
@@ -1263,74 +1388,239 @@ abstract class ApiBase extends ContextSource {
                'unknownerror-nocode' => array( 'code' => 'unknownerror', 'info' => 'Unknown error' ),
 
                // Messages from Title::getUserPermissionsErrors()
-               'ns-specialprotected' => array( 'code' => 'unsupportednamespace', 'info' => "Pages in the Special namespace can't be edited" ),
-               'protectedinterface' => array( 'code' => 'protectednamespace-interface', 'info' => "You're not allowed to edit interface messages" ),
-               'namespaceprotected' => array( 'code' => 'protectednamespace', 'info' => "You're not allowed to edit pages in the \"\$1\" namespace" ),
-               'customcssprotected' => array( 'code' => 'customcssprotected', 'info' => "You're not allowed to edit custom CSS pages" ),
-               'customjsprotected' => array( 'code' => 'customjsprotected', 'info' => "You're not allowed to edit custom JavaScript pages" ),
-               'cascadeprotected' => array( 'code' => 'cascadeprotected', 'info' => "The page you're trying to edit is protected because it's included in a cascade-protected page" ),
-               'protectedpagetext' => array( 'code' => 'protectedpage', 'info' => "The \"\$1\" right is required to edit this page" ),
-               'protect-cantedit' => array( 'code' => 'cantedit', 'info' => "You can't protect this page because you can't edit it" ),
-               'badaccess-group0' => array( 'code' => 'permissiondenied', 'info' => "Permission denied" ), // Generic permission denied message
-               'badaccess-groups' => array( 'code' => 'permissiondenied', 'info' => "Permission denied" ),
-               'titleprotected' => array( 'code' => 'protectedtitle', 'info' => "This title has been protected from creation" ),
-               'nocreate-loggedin' => array( 'code' => 'cantcreate', 'info' => "You don't have permission to create new pages" ),
-               'nocreatetext' => array( 'code' => 'cantcreate-anon', 'info' => "Anonymous users can't create new pages" ),
-               'movenologintext' => array( 'code' => 'cantmove-anon', 'info' => "Anonymous users can't move pages" ),
-               'movenotallowed' => array( 'code' => 'cantmove', 'info' => "You don't have permission to move pages" ),
-               'confirmedittext' => array( 'code' => 'confirmemail', 'info' => "You must confirm your email address before you can edit" ),
-               'blockedtext' => array( 'code' => 'blocked', 'info' => "You have been blocked from editing" ),
-               'autoblockedtext' => array( 'code' => 'autoblocked', 'info' => "Your IP address has been blocked automatically, because it was used by a blocked user" ),
+               'ns-specialprotected' => array(
+                       'code' => 'unsupportednamespace',
+                       'info' => "Pages in the Special namespace can't be edited"
+               ),
+               'protectedinterface' => array(
+                       'code' => 'protectednamespace-interface',
+                       'info' => "You're not allowed to edit interface messages"
+               ),
+               'namespaceprotected' => array(
+                       'code' => 'protectednamespace',
+                       'info' => "You're not allowed to edit pages in the \"\$1\" namespace"
+               ),
+               'customcssprotected' => array(
+                       'code' => 'customcssprotected',
+                       'info' => "You're not allowed to edit custom CSS pages"
+               ),
+               'customjsprotected' => array(
+                       'code' => 'customjsprotected',
+                       'info' => "You're not allowed to edit custom JavaScript pages"
+               ),
+               'cascadeprotected' => array(
+                       'code' => 'cascadeprotected',
+                       'info' => "The page you're trying to edit is protected because it's included in a cascade-protected page"
+               ),
+               'protectedpagetext' => array(
+                       'code' => 'protectedpage',
+                       'info' => "The \"\$1\" right is required to edit this page"
+               ),
+               'protect-cantedit' => array(
+                       'code' => 'cantedit',
+                       'info' => "You can't protect this page because you can't edit it"
+               ),
+               'badaccess-group0' => array(
+                       'code' => 'permissiondenied',
+                       'info' => "Permission denied"
+               ), // Generic permission denied message
+               'badaccess-groups' => array(
+                       'code' => 'permissiondenied',
+                       'info' => "Permission denied"
+               ),
+               'titleprotected' => array(
+                       'code' => 'protectedtitle',
+                       'info' => "This title has been protected from creation"
+               ),
+               'nocreate-loggedin' => array(
+                       'code' => 'cantcreate',
+                       'info' => "You don't have permission to create new pages"
+               ),
+               'nocreatetext' => array(
+                       'code' => 'cantcreate-anon',
+                       'info' => "Anonymous users can't create new pages"
+               ),
+               'movenologintext' => array(
+                       'code' => 'cantmove-anon',
+                       'info' => "Anonymous users can't move pages"
+               ),
+               'movenotallowed' => array(
+                       'code' => 'cantmove',
+                       'info' => "You don't have permission to move pages"
+               ),
+               'confirmedittext' => array(
+                       'code' => 'confirmemail',
+                       'info' => "You must confirm your email address before you can edit"
+               ),
+               'blockedtext' => array(
+                       'code' => 'blocked',
+                       'info' => "You have been blocked from editing"
+               ),
+               'autoblockedtext' => array(
+                       'code' => 'autoblocked',
+                       'info' => "Your IP address has been blocked automatically, because it was used by a blocked user"
+               ),
 
                // Miscellaneous interface messages
-               'actionthrottledtext' => array( 'code' => 'ratelimited', 'info' => "You've exceeded your rate limit. Please wait some time and try again" ),
-               'alreadyrolled' => array( 'code' => 'alreadyrolled', 'info' => "The page you tried to rollback was already rolled back" ),
-               'cantrollback' => array( 'code' => 'onlyauthor', 'info' => "The page you tried to rollback only has one author" ),
-               'readonlytext' => array( 'code' => 'readonly', 'info' => "The wiki is currently in read-only mode" ),
-               'sessionfailure' => array( 'code' => 'badtoken', 'info' => "Invalid token" ),
-               'cannotdelete' => array( 'code' => 'cantdelete', 'info' => "Couldn't delete \"\$1\". Maybe it was deleted already by someone else" ),
-               'notanarticle' => array( 'code' => 'missingtitle', 'info' => "The page you requested doesn't exist" ),
-               'selfmove' => array( 'code' => 'selfmove', 'info' => "Can't move a page to itself" ),
-               'immobile_namespace' => array( 'code' => 'immobilenamespace', 'info' => "You tried to move pages from or to a namespace that is protected from moving" ),
-               'articleexists' => array( 'code' => 'articleexists', 'info' => "The destination article already exists and is not a redirect to the source article" ),
-               'protectedpage' => array( 'code' => 'protectedpage', 'info' => "You don't have permission to perform this move" ),
-               'hookaborted' => array( 'code' => 'hookaborted', 'info' => "The modification you tried to make was aborted by an extension hook" ),
-               'cantmove-titleprotected' => array( 'code' => 'protectedtitle', 'info' => "The destination article has been protected from creation" ),
-               'imagenocrossnamespace' => array( 'code' => 'nonfilenamespace', 'info' => "Can't move a file to a non-file namespace" ),
-               'imagetypemismatch' => array( 'code' => 'filetypemismatch', 'info' => "The new file extension doesn't match its type" ),
+               'actionthrottledtext' => array(
+                       'code' => 'ratelimited',
+                       'info' => "You've exceeded your rate limit. Please wait some time and try again"
+               ),
+               'alreadyrolled' => array(
+                       'code' => 'alreadyrolled',
+                       'info' => "The page you tried to rollback was already rolled back"
+               ),
+               'cantrollback' => array(
+                       'code' => 'onlyauthor',
+                       'info' => "The page you tried to rollback only has one author"
+               ),
+               'readonlytext' => array(
+                       'code' => 'readonly',
+                       'info' => "The wiki is currently in read-only mode"
+               ),
+               'sessionfailure' => array(
+                       'code' => 'badtoken',
+                       'info' => "Invalid token" ),
+               'cannotdelete' => array(
+                       'code' => 'cantdelete',
+                       'info' => "Couldn't delete \"\$1\". Maybe it was deleted already by someone else"
+               ),
+               'notanarticle' => array(
+                       'code' => 'missingtitle',
+                       'info' => "The page you requested doesn't exist"
+               ),
+               'selfmove' => array( 'code' => 'selfmove', 'info' => "Can't move a page to itself"
+               ),
+               'immobile_namespace' => array(
+                       'code' => 'immobilenamespace',
+                       'info' => "You tried to move pages from or to a namespace that is protected from moving"
+               ),
+               'articleexists' => array(
+                       'code' => 'articleexists',
+                       'info' => "The destination article already exists and is not a redirect to the source article"
+               ),
+               'protectedpage' => array(
+                       'code' => 'protectedpage',
+                       'info' => "You don't have permission to perform this move"
+               ),
+               'hookaborted' => array(
+                       'code' => 'hookaborted',
+                       'info' => "The modification you tried to make was aborted by an extension hook"
+               ),
+               'cantmove-titleprotected' => array(
+                       'code' => 'protectedtitle',
+                       'info' => "The destination article has been protected from creation"
+               ),
+               'imagenocrossnamespace' => array(
+                       'code' => 'nonfilenamespace',
+                       'info' => "Can't move a file to a non-file namespace"
+               ),
+               'imagetypemismatch' => array(
+                       'code' => 'filetypemismatch',
+                       'info' => "The new file extension doesn't match its type"
+               ),
                // 'badarticleerror' => shouldn't happen
                // 'badtitletext' => shouldn't happen
                'ip_range_invalid' => array( 'code' => 'invalidrange', 'info' => "Invalid IP range" ),
-               'range_block_disabled' => array( 'code' => 'rangedisabled', 'info' => "Blocking IP ranges has been disabled" ),
-               'nosuchusershort' => array( 'code' => 'nosuchuser', 'info' => "The user you specified doesn't exist" ),
+               'range_block_disabled' => array(
+                       'code' => 'rangedisabled',
+                       'info' => "Blocking IP ranges has been disabled"
+               ),
+               'nosuchusershort' => array(
+                       'code' => 'nosuchuser',
+                       'info' => "The user you specified doesn't exist"
+               ),
                'badipaddress' => array( 'code' => 'invalidip', 'info' => "Invalid IP address specified" ),
                'ipb_expiry_invalid' => array( 'code' => 'invalidexpiry', 'info' => "Invalid expiry time" ),
-               'ipb_already_blocked' => array( 'code' => 'alreadyblocked', 'info' => "The user you tried to block was already blocked" ),
-               'ipb_blocked_as_range' => array( 'code' => 'blockedasrange', 'info' => "IP address \"\$1\" was blocked as part of range \"\$2\". You can't unblock the IP individually, but you can unblock the range as a whole." ),
-               'ipb_cant_unblock' => array( 'code' => 'cantunblock', 'info' => "The block you specified was not found. It may have been unblocked already" ),
-               'mailnologin' => array( 'code' => 'cantsend', 'info' => "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" ),
-               'ipbblocked' => array( 'code' => 'ipbblocked', 'info' => 'You cannot block or unblock users while you are yourself blocked' ),
-               'ipbnounblockself' => array( 'code' => 'ipbnounblockself', 'info' => 'You are not allowed to unblock yourself' ),
-               'usermaildisabled' => array( 'code' => 'usermaildisabled', 'info' => "User email has been disabled" ),
-               'blockedemailuser' => array( 'code' => 'blockedfrommail', 'info' => "You have been blocked from sending email" ),
-               'notarget' => array( 'code' => 'notarget', 'info' => "You have not specified a valid target for this action" ),
-               'noemail' => array( 'code' => 'noemail', 'info' => "The user has not specified a valid email address, or has chosen not to receive email from other users" ),
-               'rcpatroldisabled' => array( 'code' => 'patroldisabled', 'info' => "Patrolling is disabled on this wiki" ),
-               'markedaspatrollederror-noautopatrol' => array( 'code' => 'noautopatrol', 'info' => "You don't have permission to patrol your own changes" ),
-               'delete-toobig' => array( 'code' => 'bigdelete', 'info' => "You can't delete this page because it has more than \$1 revisions" ),
-               'movenotallowedfile' => array( 'code' => 'cantmovefile', 'info' => "You don't have permission to move files" ),
-               'userrights-no-interwiki' => array( 'code' => 'nointerwikiuserrights', 'info' => "You don't have permission to change user rights on other wikis" ),
-               'userrights-nodatabase' => array( 'code' => 'nosuchdatabase', 'info' => "Database \"\$1\" does not exist or is not local" ),
+               'ipb_already_blocked' => array(
+                       'code' => 'alreadyblocked',
+                       'info' => "The user you tried to block was already blocked"
+               ),
+               'ipb_blocked_as_range' => array(
+                       'code' => 'blockedasrange',
+                       'info' => "IP address \"\$1\" was blocked as part of range \"\$2\". You can't unblock the IP individually, but you can unblock the range as a whole."
+               ),
+               'ipb_cant_unblock' => array(
+                       'code' => 'cantunblock',
+                       'info' => "The block you specified was not found. It may have been unblocked already"
+               ),
+               'mailnologin' => array(
+                       'code' => 'cantsend',
+                       'info' => "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"
+               ),
+               'ipbblocked' => array(
+                       'code' => 'ipbblocked',
+                       'info' => 'You cannot block or unblock users while you are yourself blocked'
+               ),
+               'ipbnounblockself' => array(
+                       'code' => 'ipbnounblockself',
+                       'info' => 'You are not allowed to unblock yourself'
+               ),
+               'usermaildisabled' => array(
+                       'code' => 'usermaildisabled',
+                       'info' => "User email has been disabled"
+               ),
+               'blockedemailuser' => array(
+                       'code' => 'blockedfrommail',
+                       'info' => "You have been blocked from sending email"
+               ),
+               'notarget' => array(
+                       'code' => 'notarget',
+                       'info' => "You have not specified a valid target for this action"
+               ),
+               'noemail' => array(
+                       'code' => 'noemail',
+                       'info' => "The user has not specified a valid email address, or has chosen not to receive email from other users"
+               ),
+               'rcpatroldisabled' => array(
+                       'code' => 'patroldisabled',
+                       'info' => "Patrolling is disabled on this wiki"
+               ),
+               'markedaspatrollederror-noautopatrol' => array(
+                       'code' => 'noautopatrol',
+                       'info' => "You don't have permission to patrol your own changes"
+               ),
+               'delete-toobig' => array(
+                       'code' => 'bigdelete',
+                       'info' => "You can't delete this page because it has more than \$1 revisions"
+               ),
+               'movenotallowedfile' => array(
+                       'code' => 'cantmovefile',
+                       'info' => "You don't have permission to move files"
+               ),
+               'userrights-no-interwiki' => array(
+                       'code' => 'nointerwikiuserrights',
+                       'info' => "You don't have permission to change user rights on other wikis"
+               ),
+               'userrights-nodatabase' => array(
+                       'code' => 'nosuchdatabase',
+                       'info' => "Database \"\$1\" does not exist or is not local"
+               ),
                'nouserspecified' => array( 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ),
                'noname' => array( 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ),
                'summaryrequired' => array( 'code' => 'summaryrequired', 'info' => 'Summary required' ),
-               'import-rootpage-invalid' => array( 'code' => 'import-rootpage-invalid', 'info' => 'Root page is an invalid title' ),
-               'import-rootpage-nosubpage' => array( 'code' => 'import-rootpage-nosubpage', 'info' => 'Namespace "$1" of the root page does not allow subpages' ),
+               'import-rootpage-invalid' => array(
+                       'code' => 'import-rootpage-invalid',
+                       'info' => 'Root page is an invalid title'
+               ),
+               'import-rootpage-nosubpage' => array(
+                       'code' => 'import-rootpage-nosubpage',
+                       'info' => 'Namespace "$1" of the root page does not allow subpages'
+               ),
 
                // API-specific messages
-               'readrequired' => array( 'code' => 'readapidenied', 'info' => "You need read permission to use this module" ),
-               'writedisabled' => array( 'code' => 'noapiwrite', 'info' => "Editing of this wiki through the API is disabled. Make sure the \$wgEnableWriteAPI=true; statement is included in the wiki's LocalSettings.php file" ),
-               'writerequired' => array( 'code' => 'writeapidenied', 'info' => "You're not allowed to edit this wiki through the API" ),
+               'readrequired' => array(
+                       'code' => 'readapidenied',
+                       'info' => "You need read permission to use this module"
+               ),
+               'writedisabled' => array(
+                       'code' => 'noapiwrite',
+                       'info' => "Editing of this wiki through the API is disabled. Make sure the \$wgEnableWriteAPI=true; statement is included in the wiki's LocalSettings.php file"
+               ),
+               'writerequired' => array(
+                       'code' => 'writeapidenied',
+                       'info' => "You're not allowed to edit this wiki through the API"
+               ),
                'missingparam' => array( 'code' => 'no$1', 'info' => "The \$1 parameter must be set" ),
                'invalidtitle' => array( 'code' => 'invalidtitle', 'info' => "Bad title \"\$1\"" ),
                'nosuchpageid' => array( 'code' => 'nosuchpageid', 'info' => "There is no page with ID \$1" ),
@@ -1339,80 +1629,245 @@ abstract class ApiBase extends ContextSource {
                'invaliduser' => array( 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ),
                'invalidexpiry' => array( 'code' => 'invalidexpiry', 'info' => "Invalid expiry time \"\$1\"" ),
                'pastexpiry' => array( 'code' => 'pastexpiry', 'info' => "Expiry time \"\$1\" is in the past" ),
-               'create-titleexists' => array( 'code' => 'create-titleexists', 'info' => "Existing titles can't be protected with 'create'" ),
-               'missingtitle-createonly' => array( 'code' => 'missingtitle-createonly', 'info' => "Missing titles can only be protected with 'create'" ),
-               'cantblock' => array( 'code' => 'cantblock', 'info' => "You don't have permission to block users" ),
-               'canthide' => array( 'code' => 'canthide', 'info' => "You don't have permission to hide user names from the block log" ),
-               'cantblock-email' => array( 'code' => 'cantblock-email', 'info' => "You don't have permission to block users from sending email through the wiki" ),
-               'unblock-notarget' => array( 'code' => 'notarget', 'info' => "Either the id or the user parameter must be set" ),
-               'unblock-idanduser' => array( 'code' => 'idanduser', 'info' => "The id and user parameters can't be used together" ),
-               'cantunblock' => array( 'code' => 'permissiondenied', 'info' => "You don't have permission to unblock users" ),
-               'cannotundelete' => array( 'code' => 'cantundelete', 'info' => "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already" ),
-               'permdenied-undelete' => array( 'code' => 'permissiondenied', 'info' => "You don't have permission to restore deleted revisions" ),
-               'createonly-exists' => array( 'code' => 'articleexists', 'info' => "The article you tried to create has been created already" ),
-               'nocreate-missing' => array( 'code' => 'missingtitle', 'info' => "The article you tried to edit doesn't exist" ),
-               'nosuchrcid' => array( 'code' => 'nosuchrcid', 'info' => "There is no change with rcid \"\$1\"" ),
-               'protect-invalidaction' => array( 'code' => 'protect-invalidaction', 'info' => "Invalid protection type \"\$1\"" ),
-               'protect-invalidlevel' => array( 'code' => 'protect-invalidlevel', 'info' => "Invalid protection level \"\$1\"" ),
-               'toofewexpiries' => array( 'code' => 'toofewexpiries', 'info' => "\$1 expiry timestamps were provided where \$2 were needed" ),
-               'cantimport' => array( 'code' => 'cantimport', 'info' => "You don't have permission to import pages" ),
-               'cantimport-upload' => array( 'code' => 'cantimport-upload', 'info' => "You don't have permission to import uploaded pages" ),
+               'create-titleexists' => array(
+                       'code' => 'create-titleexists',
+                       'info' => "Existing titles can't be protected with 'create'"
+               ),
+               'missingtitle-createonly' => array(
+                       'code' => 'missingtitle-createonly',
+                       'info' => "Missing titles can only be protected with 'create'"
+               ),
+               'cantblock' => array( 'code' => 'cantblock',
+                       'info' => "You don't have permission to block users"
+               ),
+               'canthide' => array(
+                       'code' => 'canthide',
+                       'info' => "You don't have permission to hide user names from the block log"
+               ),
+               'cantblock-email' => array(
+                       'code' => 'cantblock-email',
+                       'info' => "You don't have permission to block users from sending email through the wiki"
+               ),
+               'unblock-notarget' => array(
+                       'code' => 'notarget',
+                       'info' => "Either the id or the user parameter must be set"
+               ),
+               'unblock-idanduser' => array(
+                       'code' => 'idanduser',
+                       'info' => "The id and user parameters can't be used together"
+               ),
+               'cantunblock' => array(
+                       'code' => 'permissiondenied',
+                       'info' => "You don't have permission to unblock users"
+               ),
+               'cannotundelete' => array(
+                       'code' => 'cantundelete',
+                       'info' => "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already"
+               ),
+               'permdenied-undelete' => array(
+                       'code' => 'permissiondenied',
+                       'info' => "You don't have permission to restore deleted revisions"
+               ),
+               'createonly-exists' => array(
+                       'code' => 'articleexists',
+                       'info' => "The article you tried to create has been created already"
+               ),
+               'nocreate-missing' => array(
+                       'code' => 'missingtitle',
+                       'info' => "The article you tried to edit doesn't exist"
+               ),
+               'nosuchrcid' => array(
+                       'code' => 'nosuchrcid',
+                       'info' => "There is no change with rcid \"\$1\""
+               ),
+               'protect-invalidaction' => array(
+                       'code' => 'protect-invalidaction',
+                       'info' => "Invalid protection type \"\$1\""
+               ),
+               'protect-invalidlevel' => array(
+                       'code' => 'protect-invalidlevel',
+                       'info' => "Invalid protection level \"\$1\""
+               ),
+               'toofewexpiries' => array(
+                       'code' => 'toofewexpiries',
+                       'info' => "\$1 expiry timestamps were provided where \$2 were needed"
+               ),
+               'cantimport' => array(
+                       'code' => 'cantimport',
+                       'info' => "You don't have permission to import pages"
+               ),
+               'cantimport-upload' => array(
+                       'code' => 'cantimport-upload',
+                       'info' => "You don't have permission to import uploaded pages"
+               ),
                'importnofile' => array( 'code' => 'nofile', 'info' => "You didn't upload a file" ),
-               'importuploaderrorsize' => array( 'code' => 'filetoobig', 'info' => 'The file you uploaded is bigger than the maximum upload size' ),
-               'importuploaderrorpartial' => array( 'code' => 'partialupload', 'info' => 'The file was only partially uploaded' ),
-               'importuploaderrortemp' => array( 'code' => 'notempdir', 'info' => 'The temporary upload directory is missing' ),
-               'importcantopen' => array( 'code' => 'cantopenfile', 'info' => "Couldn't open the uploaded file" ),
-               'import-noarticle' => array( 'code' => 'badinterwiki', 'info' => 'Invalid interwiki title specified' ),
-               'importbadinterwiki' => array( 'code' => 'badinterwiki', 'info' => 'Invalid interwiki title specified' ),
-               'import-unknownerror' => array( 'code' => 'import-unknownerror', 'info' => "Unknown error on import: \"\$1\"" ),
-               'cantoverwrite-sharedfile' => array( 'code' => 'cantoverwrite-sharedfile', 'info' => 'The target file exists on a shared repository and you do not have permission to override it' ),
-               'sharedfile-exists' => array( 'code' => 'fileexists-sharedrepo-perm', 'info' => 'The target file exists on a shared repository. Use the ignorewarnings parameter to override it.' ),
-               'mustbeposted' => array( 'code' => 'mustbeposted', 'info' => "The \$1 module requires a POST request" ),
-               'show' => array( 'code' => 'show', 'info' => 'Incorrect parameter - mutually exclusive values may not be supplied' ),
-               'specialpage-cantexecute' => array( 'code' => 'specialpage-cantexecute', 'info' => "You don't have permission to view the results of this special page" ),
-               'invalidoldimage' => array( 'code' => 'invalidoldimage', 'info' => 'The oldimage parameter has invalid format' ),
-               'nodeleteablefile' => array( 'code' => 'nodeleteablefile', 'info' => 'No such old version of the file' ),
-               'fileexists-forbidden' => array( 'code' => 'fileexists-forbidden', 'info' => 'A file with name "$1" already exists, and cannot be overwritten.' ),
-               'fileexists-shared-forbidden' => array( 'code' => 'fileexists-shared-forbidden', 'info' => 'A file with name "$1" already exists in the shared file repository, and cannot be overwritten.' ),
-               'filerevert-badversion' => array( 'code' => 'filerevert-badversion', 'info' => 'There is no previous local version of this file with the provided timestamp.' ),
+               'importuploaderrorsize' => array(
+                       'code' => 'filetoobig',
+                       'info' => 'The file you uploaded is bigger than the maximum upload size'
+               ),
+               'importuploaderrorpartial' => array(
+                       'code' => 'partialupload',
+                       'info' => 'The file was only partially uploaded'
+               ),
+               'importuploaderrortemp' => array(
+                       'code' => 'notempdir',
+                       'info' => 'The temporary upload directory is missing'
+               ),
+               'importcantopen' => array(
+                       'code' => 'cantopenfile',
+                       'info' => "Couldn't open the uploaded file"
+               ),
+               'import-noarticle' => array(
+                       'code' => 'badinterwiki',
+                       'info' => 'Invalid interwiki title specified'
+               ),
+               'importbadinterwiki' => array(
+                       'code' => 'badinterwiki',
+                       'info' => 'Invalid interwiki title specified'
+               ),
+               'import-unknownerror' => array(
+                       'code' => 'import-unknownerror',
+                       'info' => "Unknown error on import: \"\$1\""
+               ),
+               'cantoverwrite-sharedfile' => array(
+                       'code' => 'cantoverwrite-sharedfile',
+                       'info' => 'The target file exists on a shared repository and you do not have permission to override it'
+               ),
+               'sharedfile-exists' => array(
+                       'code' => 'fileexists-sharedrepo-perm',
+                       'info' => 'The target file exists on a shared repository. Use the ignorewarnings parameter to override it.'
+               ),
+               'mustbeposted' => array(
+                       'code' => 'mustbeposted',
+                       'info' => "The \$1 module requires a POST request"
+               ),
+               'show' => array(
+                       'code' => 'show',
+                       'info' => 'Incorrect parameter - mutually exclusive values may not be supplied'
+               ),
+               'specialpage-cantexecute' => array(
+                       'code' => 'specialpage-cantexecute',
+                       'info' => "You don't have permission to view the results of this special page"
+               ),
+               'invalidoldimage' => array(
+                       'code' => 'invalidoldimage',
+                       'info' => 'The oldimage parameter has invalid format'
+               ),
+               'nodeleteablefile' => array(
+                       'code' => 'nodeleteablefile',
+                       'info' => 'No such old version of the file'
+               ),
+               'fileexists-forbidden' => array(
+                       'code' => 'fileexists-forbidden',
+                       'info' => 'A file with name "$1" already exists, and cannot be overwritten.'
+               ),
+               'fileexists-shared-forbidden' => array(
+                       'code' => 'fileexists-shared-forbidden',
+                       'info' => 'A file with name "$1" already exists in the shared file repository, and cannot be overwritten.'
+               ),
+               'filerevert-badversion' => array(
+                       'code' => 'filerevert-badversion',
+                       'info' => 'There is no previous local version of this file with the provided timestamp.'
+               ),
 
                // ApiEditPage messages
-               'noimageredirect-anon' => array( 'code' => 'noimageredirect-anon', 'info' => "Anonymous users can't create image redirects" ),
-               'noimageredirect-logged' => array( 'code' => 'noimageredirect', 'info' => "You don't have permission to create image redirects" ),
-               'spamdetected' => array( 'code' => 'spamdetected', 'info' => "Your edit was refused because it contained a spam fragment: \"\$1\"" ),
-               'contenttoobig' => array( 'code' => 'contenttoobig', 'info' => "The content you supplied exceeds the article size limit of \$1 kilobytes" ),
+               'noimageredirect-anon' => array(
+                       'code' => 'noimageredirect-anon',
+                       'info' => "Anonymous users can't create image redirects"
+               ),
+               'noimageredirect-logged' => array(
+                       'code' => 'noimageredirect',
+                       'info' => "You don't have permission to create image redirects"
+               ),
+               'spamdetected' => array(
+                       'code' => 'spamdetected',
+                       'info' => "Your edit was refused because it contained a spam fragment: \"\$1\""
+               ),
+               'contenttoobig' => array(
+                       'code' => 'contenttoobig',
+                       'info' => "The content you supplied exceeds the article size limit of \$1 kilobytes"
+               ),
                'noedit-anon' => array( 'code' => 'noedit-anon', 'info' => "Anonymous users can't edit pages" ),
                'noedit' => array( 'code' => 'noedit', 'info' => "You don't have permission to edit pages" ),
-               'wasdeleted' => array( 'code' => 'pagedeleted', 'info' => "The page has been deleted since you fetched its timestamp" ),
-               'blankpage' => array( 'code' => 'emptypage', 'info' => "Creating new, empty pages is not allowed" ),
+               'wasdeleted' => array(
+                       'code' => 'pagedeleted',
+                       'info' => "The page has been deleted since you fetched its timestamp"
+               ),
+               'blankpage' => array(
+                       'code' => 'emptypage',
+                       'info' => "Creating new, empty pages is not allowed"
+               ),
                'editconflict' => array( 'code' => 'editconflict', 'info' => "Edit conflict detected" ),
                'hashcheckfailed' => array( 'code' => 'badmd5', 'info' => "The supplied MD5 hash was incorrect" ),
-               'missingtext' => array( 'code' => 'notext', 'info' => "One of the text, appendtext, prependtext and undo parameters must be set" ),
-               'emptynewsection' => array( 'code' => 'emptynewsection', 'info' => 'Creating empty new sections is not possible.' ),
-               'revwrongpage' => array( 'code' => 'revwrongpage', 'info' => "r\$1 is not a revision of \"\$2\"" ),
-               'undo-failure' => array( 'code' => 'undofailure', 'info' => 'Undo failed due to conflicting intermediate edits' ),
+               'missingtext' => array(
+                       'code' => 'notext',
+                       'info' => "One of the text, appendtext, prependtext and undo parameters must be set"
+               ),
+               'emptynewsection' => array(
+                       'code' => 'emptynewsection',
+                       'info' => 'Creating empty new sections is not possible.'
+               ),
+               'revwrongpage' => array(
+                       'code' => 'revwrongpage',
+                       'info' => "r\$1 is not a revision of \"\$2\""
+               ),
+               'undo-failure' => array(
+                       'code' => 'undofailure',
+                       'info' => 'Undo failed due to conflicting intermediate edits'
+               ),
 
                // Messages from WikiPage::doEit()
-               'edit-hook-aborted' => array( 'code' => 'edit-hook-aborted', 'info' => "Your edit was aborted by an ArticleSave hook" ),
-               'edit-gone-missing' => array( 'code' => 'edit-gone-missing', 'info' => "The page you tried to edit doesn't seem to exist anymore" ),
+               'edit-hook-aborted' => array(
+                       'code' => 'edit-hook-aborted',
+                       'info' => "Your edit was aborted by an ArticleSave hook"
+               ),
+               'edit-gone-missing' => array(
+                       'code' => 'edit-gone-missing',
+                       'info' => "The page you tried to edit doesn't seem to exist anymore"
+               ),
                'edit-conflict' => array( 'code' => 'editconflict', 'info' => "Edit conflict detected" ),
-               'edit-already-exists' => array( 'code' => 'edit-already-exists', 'info' => "It seems the page you tried to create already exist" ),
+               'edit-already-exists' => array(
+                       'code' => 'edit-already-exists',
+                       'info' => 'It seems the page you tried to create already exist'
+               ),
 
                // uploadMsgs
                'invalid-file-key' => array( 'code' => 'invalid-file-key', 'info' => 'Not a valid file key' ),
                'nouploadmodule' => array( 'code' => 'nouploadmodule', 'info' => 'No upload module set' ),
-               'uploaddisabled' => array( 'code' => 'uploaddisabled', 'info' => 'Uploads are not enabled. Make sure $wgEnableUploads is set to true in LocalSettings.php and the PHP ini setting file_uploads is true' ),
-               'copyuploaddisabled' => array( 'code' => 'copyuploaddisabled', 'info' => 'Uploads by URL is not enabled. Make sure $wgAllowCopyUploads is set to true in LocalSettings.php.' ),
-               'copyuploadbaddomain' => array( 'code' => 'copyuploadbaddomain', 'info' => 'Uploads by URL are not allowed from this domain.' ),
-               'copyuploadbadurl' => array( 'code' => 'copyuploadbadurl', 'info' => 'Upload not allowed from this URL.' ),
-
-               'filename-tooshort' => array( 'code' => 'filename-tooshort', 'info' => 'The filename is too short' ),
+               'uploaddisabled' => array(
+                       'code' => 'uploaddisabled',
+                       'info' => 'Uploads are not enabled. Make sure $wgEnableUploads is set to true in LocalSettings.php and the PHP ini setting file_uploads is true'
+               ),
+               'copyuploaddisabled' => array(
+                       'code' => 'copyuploaddisabled',
+                       'info' => 'Uploads by URL is not enabled. Make sure $wgAllowCopyUploads is set to true in LocalSettings.php.'
+               ),
+               'copyuploadbaddomain' => array(
+                       'code' => 'copyuploadbaddomain',
+                       'info' => 'Uploads by URL are not allowed from this domain.'
+               ),
+               'copyuploadbadurl' => array(
+                       'code' => 'copyuploadbadurl',
+                       'info' => 'Upload not allowed from this URL.'
+               ),
+
+               'filename-tooshort' => array(
+                       'code' => 'filename-tooshort',
+                       'info' => 'The filename is too short'
+               ),
                'filename-toolong' => array( 'code' => 'filename-toolong', 'info' => 'The filename is too long' ),
-               'illegal-filename' => array( 'code' => 'illegal-filename', 'info' => 'The filename is not allowed' ),
-               'filetype-missing' => array( 'code' => 'filetype-missing', 'info' => 'The file is missing an extension' ),
+               'illegal-filename' => array(
+                       'code' => 'illegal-filename',
+                       'info' => 'The filename is not allowed'
+               ),
+               'filetype-missing' => array(
+                       'code' => 'filetype-missing',
+                       'info' => 'The file is missing an extension'
+               ),
 
                'mustbeloggedin' => array( 'code' => 'mustbeloggedin', 'info' => 'You must be logged in to $1.' )
        );
+       // @codingStandardsIgnoreEnd
 
        /**
         * Helper function for readonly errors
@@ -1447,18 +1902,19 @@ abstract class ApiBase extends ContextSource {
                global $wgDebugAPI;
                if ( $wgDebugAPI !== true ) {
                        $this->dieUsageMsg( $error );
-               } else {
-                       if ( is_string( $error ) ) {
-                               $error = array( $error );
-                       }
-                       $parsed = $this->parseMsg( $error );
-                       $this->setWarning( '$wgDebugAPI: ' . $parsed['code']
-                               . ' - ' . $parsed['info'] );
                }
+
+               if ( is_string( $error ) ) {
+                       $error = array( $error );
+               }
+
+               $parsed = $this->parseMsg( $error );
+               $this->setWarning( '$wgDebugAPI: ' . $parsed['code'] . ' - ' . $parsed['info'] );
        }
 
        /**
-        * Die with the $prefix.'badcontinue' error. This call is common enough to make it into the base method.
+        * Die with the $prefix.'badcontinue' error. This call is common enough to
+        * make it into the base method.
         * @param $condition boolean will only die if this value is true
         * @since 1.21
         */
@@ -1501,6 +1957,7 @@ abstract class ApiBase extends ContextSource {
         * Internal code errors should be reported with this method
         * @param string $method Method or function name
         * @param string $message Error message
+        * @throws MWException
         */
        protected static function dieDebug( $method, $message ) {
                throw new MWException( "Internal error in $method: $message" );
@@ -1521,6 +1978,7 @@ abstract class ApiBase extends ContextSource {
        public function isReadMode() {
                return true;
        }
+
        /**
         * Indicates whether this module requires write mode
         * @return bool
@@ -1573,7 +2031,10 @@ abstract class ApiBase extends ContextSource {
                        }
                        $token = $user->getOption( 'watchlisttoken' );
                        if ( $token == '' || $token != $params['token'] ) {
-                               $this->dieUsage( 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences', 'bad_wltoken' );
+                               $this->dieUsage(
+                                       'Incorrect watchlist token provided -- please set a correct token in Special:Preferences',
+                                       'bad_wltoken'
+                               );
                        }
                } else {
                        if ( !$this->getUser()->isLoggedIn() ) {
@@ -1584,11 +2045,13 @@ abstract class ApiBase extends ContextSource {
                        }
                        $user = $this->getUser();
                }
+
                return $user;
        }
 
        /**
-        * @return bool|string|array Returns a false if the module has no help url, else returns a (array of) string
+        * @return bool|string|array Returns a false if the module has no help URL,
+        *   else returns a (array of) string
         */
        public function getHelpUrls() {
                return false;
@@ -1600,7 +2063,8 @@ abstract class ApiBase extends ContextSource {
         * Don't call this function directly: use getFinalPossibleErrors() to allow
         * hooks to modify parameters as needed.
         *
-        * @return array in the format of array( key, param1, param2, ... ) or array( 'code' => ..., 'info' => ... )
+        * @return array in the format of array( key, param1, param2, ... )
+        *   or array( 'code' => ..., 'info' => ... )
         */
        public function getPossibleErrors() {
                $ret = array();
@@ -1608,14 +2072,17 @@ abstract class ApiBase extends ContextSource {
                $params = $this->getFinalParams();
                if ( $params ) {
                        foreach ( $params as $paramName => $paramSettings ) {
-                               if ( isset( $paramSettings[ApiBase::PARAM_REQUIRED] ) && $paramSettings[ApiBase::PARAM_REQUIRED] ) {
+                               if ( isset( $paramSettings[ApiBase::PARAM_REQUIRED] )
+                                       && $paramSettings[ApiBase::PARAM_REQUIRED]
+                               ) {
                                        $ret[] = array( 'missingparam', $paramName );
                                }
                        }
                        if ( array_key_exists( 'continue', $params ) ) {
                                $ret[] = array(
                                        'code' => 'badcontinue',
-                                       'info' => 'Invalid continue param. You should pass the original value returned by the previous query'
+                                       'info' => 'Invalid continue param. You should pass the ' .
+                                               'original value returned by the previous query'
                                );
                        }
                }
@@ -1656,12 +2123,14 @@ abstract class ApiBase extends ContextSource {
        public function getFinalPossibleErrors() {
                $possibleErrors = $this->getPossibleErrors();
                wfRunHooks( 'APIGetPossibleErrors', array( $this, &$possibleErrors ) );
+
                return $possibleErrors;
        }
 
        /**
         * Parses a list of errors into a standardised format
-        * @param array $errors List of errors. Items can be in the for array( key, param1, param2, ... ) or array( 'code' => ..., 'info' => ... )
+        * @param array $errors List of errors. Items can be in the for
+        *   array( key, param1, param2, ... ) or array( 'code' => ..., 'info' => ... )
         * @return array Parsed list of errors with items in the form array( 'code' => ..., 'info' => ... )
         */
        public function parseErrors( $errors ) {
@@ -1674,6 +2143,7 @@ abstract class ApiBase extends ContextSource {
                                $ret[] = $this->parseMsg( $row );
                        }
                }
+
                return $ret;
        }
 
@@ -1687,7 +2157,7 @@ abstract class ApiBase extends ContextSource {
         */
        public function profileIn() {
                if ( $this->mTimeIn !== 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called twice without calling profileOut()' );
+                       ApiBase::dieDebug( __METHOD__, 'Called twice without calling profileOut()' );
                }
                $this->mTimeIn = microtime( true );
                wfProfileIn( $this->getModuleProfileName() );
@@ -1698,10 +2168,13 @@ abstract class ApiBase extends ContextSource {
         */
        public function profileOut() {
                if ( $this->mTimeIn === 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called without calling profileIn() first' );
+                       ApiBase::dieDebug( __METHOD__, 'Called without calling profileIn() first' );
                }
                if ( $this->mDBTimeIn !== 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'must be called after database profiling is done with profileDBOut()' );
+                       ApiBase::dieDebug(
+                               __METHOD__,
+                               'Must be called after database profiling is done with profileDBOut()'
+                       );
                }
 
                $this->mModuleTime += microtime( true ) - $this->mTimeIn;
@@ -1728,8 +2201,9 @@ abstract class ApiBase extends ContextSource {
         */
        public function getProfileTime() {
                if ( $this->mTimeIn !== 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called without calling profileOut() first' );
+                       ApiBase::dieDebug( __METHOD__, 'Called without calling profileOut() first' );
                }
+
                return $this->mModuleTime;
        }
 
@@ -1743,10 +2217,13 @@ abstract class ApiBase extends ContextSource {
         */
        public function profileDBIn() {
                if ( $this->mTimeIn === 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'must be called while profiling the entire module with profileIn()' );
+                       ApiBase::dieDebug(
+                               __METHOD__,
+                               'Must be called while profiling the entire module with profileIn()'
+                       );
                }
                if ( $this->mDBTimeIn !== 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called twice without calling profileDBOut()' );
+                       ApiBase::dieDebug( __METHOD__, 'Called twice without calling profileDBOut()' );
                }
                $this->mDBTimeIn = microtime( true );
                wfProfileIn( $this->getModuleProfileName( true ) );
@@ -1757,10 +2234,11 @@ abstract class ApiBase extends ContextSource {
         */
        public function profileDBOut() {
                if ( $this->mTimeIn === 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'must be called while profiling the entire module with profileIn()' );
+                       ApiBase::dieDebug( __METHOD__, 'Must be called while profiling ' .
+                               'the entire module with profileIn()' );
                }
                if ( $this->mDBTimeIn === 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called without calling profileDBIn() first' );
+                       ApiBase::dieDebug( __METHOD__, 'Called without calling profileDBIn() first' );
                }
 
                $time = microtime( true ) - $this->mDBTimeIn;
@@ -1777,8 +2255,9 @@ abstract class ApiBase extends ContextSource {
         */
        public function getProfileDBTime() {
                if ( $this->mDBTimeIn !== 0 ) {
-                       ApiBase::dieDebug( __METHOD__, 'called without calling profileDBOut() first' );
+                       ApiBase::dieDebug( __METHOD__, 'Called without calling profileDBOut() first' );
                }
+
                return $this->mDBTime;
        }
 
@@ -1792,6 +2271,7 @@ abstract class ApiBase extends ContextSource {
                        $this->mSlaveDB = wfGetDB( DB_SLAVE, 'api' );
                        $this->profileDBOut();
                }
+
                return $this->mSlaveDB;
        }
 
index 975153a..332fa9e 100644 (file)
@@ -55,8 +55,11 @@ class ApiBlock extends ApiBase {
                }
 
                $target = User::newFromName( $params['user'] );
-               // Bug 38633 - if the target is a user (not an IP address), but it doesn't exist or is unusable, error.
-               if ( $target instanceof User && ( $target->isAnon() /* doesn't exist */ || !User::isUsableName( $target->getName() ) ) ) {
+               // Bug 38633 - if the target is a user (not an IP address), but it
+               // doesn't exist or is unusable, error.
+               if ( $target instanceof User &&
+                       ( $target->isAnon() /* doesn't exist */ || !User::isUsableName( $target->getName() ) )
+               ) {
                        $this->dieUsageMsg( array( 'nosuchuser', $params['user'] ) );
                }
 
@@ -167,14 +170,18 @@ class ApiBlock extends ApiBase {
                return array(
                        'user' => 'Username, IP address or IP range you want to block',
                        'token' => 'A block token previously obtained through prop=info',
-                       'expiry' => 'Relative expiry time, e.g. \'5 months\' or \'2 weeks\'. If set to \'infinite\', \'indefinite\' or \'never\', the block will never expire.',
+                       'expiry' => 'Relative expiry time, e.g. \'5 months\' or \'2 weeks\'. ' .
+                               'If set to \'infinite\', \'indefinite\' or \'never\', the block will never expire.',
                        'reason' => 'Reason for block',
                        'anononly' => 'Block anonymous users only (i.e. disable anonymous edits for this IP)',
                        'nocreate' => 'Prevent account creation',
-                       'autoblock' => 'Automatically block the last used IP address, and any subsequent IP addresses they try to login from',
-                       'noemail' => 'Prevent user from sending email through the wiki. (Requires the "blockemail" right.)',
+                       'autoblock' => 'Automatically block the last used IP address, and ' .
+                               'any subsequent IP addresses they try to login from',
+                       'noemail'
+                               => 'Prevent user from sending email through the wiki. (Requires the "blockemail" right.)',
                        'hidename' => 'Hide the username from the block log. (Requires the "hideuser" right.)',
-                       'allowusertalk' => 'Allow the user to edit their own talk page (depends on $wgBlockAllowsUTEdit)',
+                       'allowusertalk'
+                               => 'Allow the user to edit their own talk page (depends on $wgBlockAllowsUTEdit)',
                        'reblock' => 'If the user is already blocked, overwrite the existing block',
                        'watchuser' => 'Watch the user/IP\'s user and talk pages',
                );
index 1e35c34..237e8c8 100644 (file)
@@ -65,12 +65,15 @@ class ApiComparePages extends ApiBase {
                $difftext = $de->getDiffBody();
 
                if ( $difftext === false ) {
-                       $this->dieUsage( 'The diff cannot be retrieved. ' .
-                               'Maybe one or both revisions do not exist or you do not have permission to view them.', 'baddiff' );
-               } else {
-                       ApiResult::setContent( $vals, $difftext );
+                       $this->dieUsage(
+                               'The diff cannot be retrieved. Maybe one or both revisions do ' .
+                                       'not exist or you do not have permission to view them.',
+                               'baddiff'
+                       );
                }
 
+               ApiResult::setContent( $vals, $difftext );
+
                $this->getResult()->addValue( null, $this->getModuleName(), $vals );
        }
 
@@ -88,15 +91,20 @@ class ApiComparePages extends ApiBase {
                        if ( !$title || $title->isExternal() ) {
                                $this->dieUsageMsg( array( 'invalidtitle', $titleText ) );
                        }
+
                        return $title->getLatestRevID();
                } elseif ( $titleId ) {
                        $title = Title::newFromID( $titleId );
                        if ( !$title ) {
                                $this->dieUsageMsg( array( 'nosuchpageid', $titleId ) );
                        }
+
                        return $title->getLatestRevID();
                }
-               $this->dieUsage( 'inputneeded', 'A title, a page ID, or a revision number is needed for both the from and the to parameters' );
+               $this->dieUsage(
+                       'A title, a page ID, or a revision number is needed for both the from and the to parameters',
+                       'inputneeded'
+               );
        }
 
        public function getAllowedParams() {
@@ -159,7 +167,11 @@ class ApiComparePages extends ApiBase {
                        array( 'code' => 'inputneeded', 'info' => 'A title or a revision is needed' ),
                        array( 'invalidtitle', 'title' ),
                        array( 'nosuchpageid', 'pageid' ),
-                       array( 'code' => 'baddiff', 'info' => 'The diff cannot be retrieved. Maybe one or both revisions do not exist or you do not have permission to view them.' ),
+                       array(
+                               'code' => 'baddiff',
+                               'info' => 'The diff cannot be retrieved. Maybe one or both ' .
+                                       'revisions do not exist or you do not have permission to view them.'
+                       ),
                ) );
        }
 
index 0e752c5..439f46b 100644 (file)
@@ -39,7 +39,10 @@ class ApiCreateAccount extends ApiBase {
                // Use userCan in order to hit GlobalBlock checks (according to Special:userlogin)
                $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
                if ( !$loginTitle->userCan( 'createaccount', $this->getUser() ) ) {
-                       $this->dieUsage( 'You do not have the right to create a new account', 'permdenied-createaccount' );
+                       $this->dieUsage(
+                               'You do not have the right to create a new account',
+                               'permdenied-createaccount'
+                       );
                }
                if ( $this->getUser()->isBlockedFromCreateAccount() ) {
                        $this->dieUsage( 'You cannot create a new account because you are blocked', 'blocked' );
@@ -96,7 +99,12 @@ class ApiCreateAccount extends ApiBase {
                        if ( $params['mailpassword'] ) {
                                // If mailpassword was set, disable the password and send an email.
                                $user->setPassword( null );
-                               $status->merge( $loginForm->mailPasswordInternal( $user, false, 'createaccount-title', 'createaccount-text' ) );
+                               $status->merge( $loginForm->mailPasswordInternal(
+                                       $user,
+                                       false,
+                                       'createaccount-title',
+                                       'createaccount-text'
+                               ) );
                        } elseif ( $wgEmailAuthentication && Sanitizer::validateEmail( $user->getEmail() ) ) {
                                // Send out an email authentication message if needed
                                $status->merge( $user->sendConfirmationMail() );
@@ -172,6 +180,7 @@ class ApiCreateAccount extends ApiBase {
 
        public function getAllowedParams() {
                global $wgEmailConfirmToEdit;
+
                return array(
                        'name' => array(
                                ApiBase::PARAM_TYPE => 'user',
@@ -196,6 +205,7 @@ class ApiCreateAccount extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'name' => 'Username',
                        'password' => "Password (ignored if {$p}mailpassword is set)",
@@ -205,7 +215,8 @@ class ApiCreateAccount extends ApiBase {
                        'realname' => 'Real name of user (optional)',
                        'mailpassword' => 'If set to any value, a random password will be emailed to the user',
                        'reason' => 'Optional reason for creating the account to be put in the logs',
-                       'language' => 'Language code to set as default for the user (optional, defaults to content language)'
+                       'language'
+                               => 'Language code to set as default for the user (optional, defaults to content language)'
                );
        }
 
@@ -254,7 +265,10 @@ class ApiCreateAccount extends ApiBase {
                $errors = parent::getPossibleErrors();
                // All local errors are from LoginForm, which means they're actually message keys.
                foreach ( $localErrors as $error ) {
-                       $errors[] = array( 'code' => $error, 'info' => wfMessage( $error )->inLanguage( 'en' )->useDatabase( false )->parse() );
+                       $errors[] = array(
+                               'code' => $error,
+                               'info' => wfMessage( $error )->inLanguage( 'en' )->useDatabase( false )->parse()
+                       );
                }
 
                $errors[] = array(
@@ -278,8 +292,10 @@ class ApiCreateAccount extends ApiBase {
                global $wgMinimalPasswordLength;
                $errors[] = array(
                        'code' => 'passwordtooshort',
-                       'info' => wfMessage( 'passwordtooshort', $wgMinimalPasswordLength )->inLanguage( 'en' )->useDatabase( false )->parse()
+                       'info' => wfMessage( 'passwordtooshort', $wgMinimalPasswordLength )
+                               ->inLanguage( 'en' )->useDatabase( false )->parse()
                );
+
                return $errors;
        }
 
index aea1048..c09cad3 100644 (file)
@@ -31,7 +31,6 @@
  * @ingroup API
  */
 class ApiDelete extends ApiBase {
-
        /**
         * Extracts the title, token, and reason from the request parameters and invokes
         * the local delete() function with these as arguments. It does not make use of
@@ -52,7 +51,14 @@ class ApiDelete extends ApiBase {
                $user = $this->getUser();
 
                if ( $titleObj->getNamespace() == NS_FILE ) {
-                       $status = self::deleteFile( $pageObj, $user, $params['token'], $params['oldimage'], $reason, false );
+                       $status = self::deleteFile(
+                               $pageObj,
+                               $user,
+                               $params['token'],
+                               $params['oldimage'],
+                               $reason,
+                               false
+                       );
                } else {
                        $status = self::delete( $pageObj, $user, $params['token'], $reason );
                }
@@ -121,20 +127,23 @@ class ApiDelete extends ApiBase {
                }
 
                $error = '';
+
                // Luckily, Article.php provides a reusable delete function that does the hard work for us
                return $page->doDeleteArticleReal( $reason, false, 0, true, $error );
        }
 
        /**
-        * @param $page WikiPage|Page object to work on
-        * @param $user User doing the action
-        * @param $token
-        * @param $oldimage
-        * @param $reason
-        * @param $suppress bool
+        * @param Page $page Object to work on
+        * @param User $user User doing the action
+        * @param string $token Delete token (same as edit token)
+        * @param string $oldimage Archive name
+        * @param string $reason Reason for the deletion. Autogenerated if null.
+        * @param bool $suppress Whether to mark all deleted versions as restricted
         * @return Status|array
         */
-       public static function deleteFile( Page $page, User $user, $token, $oldimage, &$reason = null, $suppress = false ) {
+       public static function deleteFile( Page $page, User $user, $token, $oldimage,
+               &$reason = null, $suppress = false
+       ) {
                $title = $page->getTitle();
                $errors = self::getPermissionsError( $title, $user, $token );
                if ( count( $errors ) ) {
@@ -159,6 +168,7 @@ class ApiDelete extends ApiBase {
                if ( is_null( $reason ) ) { // Log and RC don't like null reasons
                        $reason = '';
                }
+
                return FileDeleteForm::doDelete( $title, $file, $oldimage, $reason, $suppress, $user );
        }
 
@@ -204,13 +214,16 @@ class ApiDelete extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'title' => "Title of the page you want to delete. Cannot be used together with {$p}pageid",
                        'pageid' => "Page ID of the page you want to delete. Cannot be used together with {$p}title",
                        'token' => 'A delete token previously retrieved through prop=info',
-                       'reason' => 'Reason for the deletion. If not set, an automatically generated reason will be used',
+                       'reason'
+                               => 'Reason for the deletion. If not set, an automatically generated reason will be used',
                        'watch' => 'Add the page to your watchlist',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'watchlist' => 'Unconditionally add or remove the page from your ' .
+                               'watchlist, use preferences or do not change watch',
                        'unwatch' => 'Remove the page from your watchlist',
                        'oldimage' => 'The name of the old image to delete as provided by iiprop=archivename'
                );
@@ -255,7 +268,8 @@ class ApiDelete extends ApiBase {
        public function getExamples() {
                return array(
                        'api.php?action=delete&title=Main%20Page&token=123ABC' => 'Delete the Main Page',
-                       'api.php?action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move' => 'Delete the Main Page with the reason "Preparing for move"',
+                       'api.php?action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move'
+                               => 'Delete the Main Page with the reason "Preparing for move"',
                );
        }
 
index bd61895..73eebca 100644 (file)
  * @ingroup API
  */
 class ApiEditPage extends ApiBase {
-
        public function execute() {
                $user = $this->getUser();
                $params = $this->extractRequestParams();
 
                if ( is_null( $params['text'] ) && is_null( $params['appendtext'] ) &&
-                               is_null( $params['prependtext'] ) &&
-                               $params['undo'] == 0 )
-               {
+                       is_null( $params['prependtext'] ) &&
+                       $params['undo'] == 0
+               {
                        $this->dieUsageMsg( 'missingtext' );
                }
 
@@ -53,8 +52,8 @@ class ApiEditPage extends ApiBase {
                                $oldTitle = $titleObj;
 
                                $titles = Revision::newFromTitle( $oldTitle, false, Revision::READ_LATEST )
-                                                       ->getContent( Revision::FOR_THIS_USER, $user )
-                                                       ->getRedirectChain();
+                                       ->getContent( Revision::FOR_THIS_USER, $user )
+                                       ->getRedirectChain();
                                // array_shift( $titles );
 
                                $redirValues = array();
@@ -88,7 +87,8 @@ class ApiEditPage extends ApiBase {
                        $contentHandler = ContentHandler::getForModelID( $params['contentmodel'] );
                }
 
-               // @todo ask handler whether direct editing is supported at all! make allowFlatEdit() method or some such
+               // @todo Ask handler whether direct editing is supported at all! make
+               // allowFlatEdit() method or some such
 
                if ( !isset( $params['contentformat'] ) || $params['contentformat'] == '' ) {
                        $params['contentformat'] = $contentHandler->getDefaultFormat();
@@ -101,7 +101,7 @@ class ApiEditPage extends ApiBase {
                        $model = $contentHandler->getModelID();
 
                        $this->dieUsage( "The requested format $contentFormat is not supported for content model " .
-                                                       " $model used by $name", 'badformat' );
+                               " $model used by $name", 'badformat' );
                }
 
                if ( $params['createonly'] && $titleObj->exists() ) {
@@ -121,8 +121,7 @@ class ApiEditPage extends ApiBase {
                }
 
                $toMD5 = $params['text'];
-               if ( !is_null( $params['appendtext'] ) || !is_null( $params['prependtext'] ) )
-               {
+               if ( !is_null( $params['appendtext'] ) || !is_null( $params['prependtext'] ) ) {
                        $content = $pageObj->getContent();
 
                        if ( !$content ) {
@@ -138,6 +137,7 @@ class ApiEditPage extends ApiBase {
                                                $content = ContentHandler::makeContent( $text, $this->getTitle() );
                                        } catch ( MWContentSerializationException $ex ) {
                                                $this->dieUsage( $ex->getMessage(), 'parseerror' );
+
                                                return;
                                        }
                                } else {
@@ -156,7 +156,10 @@ class ApiEditPage extends ApiBase {
                        if ( !is_null( $params['section'] ) ) {
                                if ( !$contentHandler->supportsSections() ) {
                                        $modelName = $contentHandler->getModelID();
-                                       $this->dieUsage( "Sections are not supported for this content model: $modelName.", 'sectionsnotsupported' );
+                                       $this->dieUsage(
+                                               "Sections are not supported for this content model: $modelName.",
+                                               'sectionsnotsupported'
+                                       );
                                }
 
                                if ( $params['section'] == 'new' ) {
@@ -187,7 +190,7 @@ class ApiEditPage extends ApiBase {
                        if ( $params['undoafter'] > 0 ) {
                                if ( $params['undo'] < $params['undoafter'] ) {
                                        list( $params['undo'], $params['undoafter'] ) =
-                                       array( $params['undoafter'], $params['undo'] );
+                                               array( $params['undoafter'], $params['undo'] );
                                }
                                $undoafterRev = Revision::newFromID( $params['undoafter'] );
                        }
@@ -204,13 +207,19 @@ class ApiEditPage extends ApiBase {
                        }
 
                        if ( $undoRev->getPage() != $pageObj->getID() ) {
-                               $this->dieUsageMsg( array( 'revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText() ) );
+                               $this->dieUsageMsg( array( 'revwrongpage', $undoRev->getID(),
+                                       $titleObj->getPrefixedText() ) );
                        }
                        if ( $undoafterRev->getPage() != $pageObj->getID() ) {
-                               $this->dieUsageMsg( array( 'revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText() ) );
+                               $this->dieUsageMsg( array( 'revwrongpage', $undoafterRev->getID(),
+                                       $titleObj->getPrefixedText() ) );
                        }
 
-                       $newContent = $contentHandler->getUndoContent( $pageObj->getRevision(), $undoRev, $undoafterRev );
+                       $newContent = $contentHandler->getUndoContent(
+                               $pageObj->getRevision(),
+                               $undoRev,
+                               $undoafterRev
+                       );
 
                        if ( !$newContent ) {
                                $this->dieUsageMsg( 'undo-failure' );
@@ -220,8 +229,11 @@ class ApiEditPage extends ApiBase {
 
                        // 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['undo'], $undoRev->getUserText() )->inContentLanguage()->text();
+                       if ( is_null( $params['summary'] ) &&
+                               $titleObj->getNextRevisionID( $undoafterRev->getID() ) == $params['undo']
+                       ) {
+                               $params['summary'] = wfMessage( 'undo-summary' )
+                                       ->params ( $params['undo'], $undoRev->getUserText() )->inContentLanguage()->text();
                        }
                }
 
@@ -333,9 +345,9 @@ class ApiEditPage extends ApiBase {
 
                // The following is needed to give the hook the full content of the
                // new revision rather than just the current section. (Bug 52077)
-               if ( !is_null( $params['section'] ) && $contentHandler->supportsSections() && $titleObj->exists() ) {
-
-                       $sectionTitle = '';
+               if ( !is_null( $params['section'] ) &&
+                       $contentHandler->supportsSections() && $titleObj->exists()
+               ) {
                        // If sectiontitle is set, use it, otherwise use the summary as the section title (for
                        // backwards compatibility with old forms/bots).
                        if ( $ep->sectiontitle !== '' ) {
@@ -346,7 +358,11 @@ class ApiEditPage extends ApiBase {
 
                        $contentObj = $contentHandler->unserializeContent( $content, $contentFormat );
 
-                       $fullContentObj = $articleObject->replaceSectionContent( $params['section'], $contentObj, $sectionTitle );
+                       $fullContentObj = $articleObject->replaceSectionContent(
+                               $params['section'],
+                               $contentObj,
+                               $sectionTitle
+                       );
                        if ( $fullContentObj ) {
                                $content = $fullContentObj->serialize( $contentFormat );
                        } else {
@@ -363,10 +379,11 @@ class ApiEditPage extends ApiBase {
                        if ( count( $r ) ) {
                                $r['result'] = 'Failure';
                                $apiResult->addValue( null, $this->getModuleName(), $r );
+
                                return;
-                       } else {
-                               $this->dieUsageMsg( 'hookaborted' );
                        }
+
+                       $this->dieUsageMsg( 'hookaborted' );
                }
 
                // Do the actual save
@@ -510,14 +527,25 @@ class ApiEditPage extends ApiBase {
                                array( 'emptynewsection' ),
                                array( 'unknownerror', 'retval' ),
                                array( 'code' => 'nosuchsection', 'info' => 'There is no section section.' ),
-                               array( 'code' => 'invalidsection', 'info' => 'The section parameter must be set to an integer or \'new\'' ),
-                               array( 'code' => 'sectionsnotsupported', 'info' => 'Sections are not supported for this type of page.' ),
-                               array( 'code' => 'editnotsupported', 'info' => 'Editing of this type of page is not supported using '
-                                                                                                                               . 'the text based edit API.' ),
-                               array( 'code' => 'appendnotsupported', 'info' => 'This type of page can not be edited by appending '
-                                                                                                                               . 'or prepending text.' ),
-                               array( 'code' => 'badformat', 'info' => 'The requested serialization format can not be applied to '
-                                                                                                               . 'the page\'s content model' ),
+                               array(
+                                       'code' => 'invalidsection',
+                                       'info' => 'The section parameter must be set to an integer or \'new\''
+                               ),
+                               array(
+                                       'code' => 'sectionsnotsupported',
+                                       'info' => 'Sections are not supported for this type of page.'
+                               ),
+                               array(
+                                       'code' => 'editnotsupported',
+                                       'info' => 'Editing of this type of page is not supported using the text based edit API.'
+                               ),
+                               array(
+                                       'code' => 'appendnotsupported',
+                                       'info' => 'This type of page can not be edited by appending or prepending text.' ),
+                               array(
+                                       'code' => 'badformat',
+                                       'info' => 'The requested serialization format can not be applied to the page\'s content model'
+                               ),
                                array( 'customcssprotected' ),
                                array( 'customjsprotected' ),
                        )
@@ -591,36 +619,46 @@ class ApiEditPage extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'title' => "Title of the page you want to edit. Cannot be used together with {$p}pageid",
                        'pageid' => "Page ID of the page you want to edit. Cannot be used together with {$p}title",
                        'section' => 'Section number. 0 for the top section, \'new\' for a new section',
                        'sectiontitle' => 'The title for a new section',
                        'text' => 'Page content',
-                       'token' => array( 'Edit token. You can get one of these through prop=info.',
-                                               "The token should always be sent as the last parameter, or at least, after the {$p}text parameter"
+                       'token' => array(
+                               'Edit token. You can get one of these through prop=info.',
+                               "The token should always be sent as the last parameter, or at " .
+                                       "least, after the {$p}text parameter"
                        ),
-                       'summary' => "Edit summary. Also section title when {$p}section=new and {$p}sectiontitle is not set",
+                       'summary'
+                               => "Edit summary. Also section title when {$p}section=new and {$p}sectiontitle is not set",
                        'minor' => 'Minor edit',
                        'notminor' => 'Non-minor edit',
                        'bot' => 'Mark this edit as bot',
-                       'basetimestamp' => array( 'Timestamp of the base revision (obtained through prop=revisions&rvprop=timestamp).',
-                                               'Used to detect edit conflicts; leave unset to ignore conflicts'
+                       'basetimestamp' => array(
+                               'Timestamp of the base revision (obtained through prop=revisions&rvprop=timestamp).',
+                               'Used to detect edit conflicts; leave unset to ignore conflicts'
                        ),
-                       'starttimestamp' => array( 'Timestamp when you obtained the edit token.',
-                                               'Used to detect edit conflicts; leave unset to ignore conflicts'
+                       'starttimestamp' => array(
+                               'Timestamp when you obtained the edit token.',
+                               'Used to detect edit conflicts; leave unset to ignore conflicts'
                        ),
                        'recreate' => 'Override any errors about the article having been deleted in the meantime',
                        'createonly' => 'Don\'t edit the page if it exists already',
                        'nocreate' => 'Throw an error if the page doesn\'t exist',
                        'watch' => 'Add the page to your watchlist',
                        'unwatch' => 'Remove the page from your watchlist',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
-                       'md5' => array( "The MD5 hash of the {$p}text parameter, or the {$p}prependtext and {$p}appendtext parameters concatenated.",
-                                       'If set, the edit won\'t be done unless the hash is correct' ),
+                       'watchlist' => 'Unconditionally add or remove the page from your ' .
+                               'watchlist, use preferences or do not change watch',
+                       'md5' => array(
+                               "The MD5 hash of the {$p}text parameter, or the {$p}prependtext " .
+                                       "and {$p}appendtext parameters concatenated.",
+                               'If set, the edit won\'t be done unless the hash is correct'
+                       ),
                        'prependtext' => "Add this text to the beginning of the page. Overrides {$p}text",
                        'appendtext' => array( "Add this text to the end of the page. Overrides {$p}text.",
-                                               "Use {$p}section=new to append a new section" ),
+                               "Use {$p}section=new to append a new section" ),
                        'undo' => "Undo this revision. Overrides {$p}text, {$p}prependtext and {$p}appendtext",
                        'undoafter' => 'Undo all revisions from undo to this one. If not set, just undo one revision',
                        'redirect' => 'Automatically resolve redirects',
@@ -674,11 +712,14 @@ class ApiEditPage extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=edit&title=Test&summary=test%20summary&text=article%20content&basetimestamp=20070824123454&token=%2B\\'
+                       'api.php?action=edit&title=Test&summary=test%20summary&' .
+                       'text=article%20content&basetimestamp=20070824123454&token=%2B\\'
                                => 'Edit a page (anonymous user)',
-                       'api.php?action=edit&title=Test&summary=NOTOC&minor=&prependtext=__NOTOC__%0A&basetimestamp=20070824123454&token=%2B\\'
+                       'api.php?action=edit&title=Test&summary=NOTOC&minor=&' .
+                               'prependtext=__NOTOC__%0A&basetimestamp=20070824123454&token=%2B\\'
                                => 'Prepend __NOTOC__ to a page (anonymous user)',
-                       'api.php?action=edit&title=Test&undo=13585&undoafter=13579&basetimestamp=20070824123454&token=%2B\\'
+                       'api.php?action=edit&title=Test&undo=13585&undoafter=13579&' .
+                               'basetimestamp=20070824123454&token=%2B\\'
                                => 'Undo r13579 through r13585 with autosummary (anonymous user)',
                );
        }
index cd0d0cb..29f7e05 100644 (file)
@@ -149,7 +149,8 @@ class ApiEmailUser extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=emailuser&target=WikiSysop&text=Content' => 'Send an email to the User "WikiSysop" with the text "Content"',
+                       'api.php?action=emailuser&target=WikiSysop&text=Content'
+                               => 'Send an email to the User "WikiSysop" with the text "Content"',
                );
        }
 
index 0569109..bf69410 100644 (file)
@@ -41,7 +41,7 @@ class ApiFeedContributions extends ApiBase {
        public function execute() {
                $params = $this->extractRequestParams();
 
-               global $wgFeed, $wgFeedClasses, $wgSitename, $wgLanguageCode;
+               global $wgFeed, $wgFeedClasses, $wgFeedLimit, $wgSitename, $wgLanguageCode;
 
                if ( !$wgFeed ) {
                        $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
@@ -61,8 +61,8 @@ class ApiFeedContributions extends ApiBase {
                $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL();
 
                $target = $params['user'] == 'newbies'
-                               ? 'newbies'
-                               : Title::makeTitleSafe( NS_USER, $params['user'] )->getText();
+                       ? 'newbies'
+                       : Title::makeTitleSafe( NS_USER, $params['user'] )->getText();
 
                $feed = new $wgFeedClasses[$params['feedformat']] (
                        $feedTitle,
@@ -81,6 +81,10 @@ class ApiFeedContributions extends ApiBase {
                        'showSizeDiff' => $params['showsizediff'],
                ) );
 
+               if ( $pager->getLimit() > $wgFeedLimit ) {
+                       $pager->setLimit( $wgFeedLimit );
+               }
+
                $feedItems = array();
                if ( $pager->getNumRows() > 0 ) {
                        foreach ( $pager->mResult as $row ) {
@@ -107,6 +111,7 @@ class ApiFeedContributions extends ApiBase {
                                $comments
                        );
                }
+
                return null;
        }
 
@@ -142,12 +147,14 @@ class ApiFeedContributions extends ApiBase {
                                htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
                                "</p>\n<hr />\n<div>" . $html . "</div>";
                }
+
                return '';
        }
 
        public function getAllowedParams() {
                global $wgFeedClasses;
                $feedFormatNames = array_keys( $wgFeedClasses );
+
                return array(
                        'feedformat' => array(
                                ApiBase::PARAM_DFLT => 'rss',
index fbb70fb..84c1fae 100644 (file)
@@ -132,16 +132,21 @@ class ApiFeedWatchlist extends ApiBase {
                        $feedTitle = $wgSitename . ' - ' . $msg . ' [' . $wgLanguageCode . ']';
                        $feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullURL();
 
-                       $feed = new $wgFeedClasses[$params['feedformat']] ( $feedTitle, htmlspecialchars( $msg ), $feedUrl );
+                       $feed = new $wgFeedClasses[$params['feedformat']] (
+                               $feedTitle,
+                               htmlspecialchars( $msg ),
+                               $feedUrl
+                       );
 
                        ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
-
                } catch ( Exception $e ) {
-
                        // Error results should not be cached
                        $this->getMain()->setCacheMaxAge( 0 );
 
-                       $feedTitle = $wgSitename . ' - Error - ' . wfMessage( 'watchlist' )->inContentLanguage()->text() . ' [' . $wgLanguageCode . ']';
+                       // @todo FIXME: Localise  brackets
+                       $feedTitle = $wgSitename . ' - Error - ' .
+                               wfMessage( 'watchlist' )->inContentLanguage()->text() .
+                               ' [' . $wgLanguageCode . ']';
                        $feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullURL();
 
                        $feedFormat = isset( $params['feedformat'] ) ? $params['feedformat'] : 'rss';
@@ -179,8 +184,11 @@ class ApiFeedWatchlist extends ApiBase {
                // The anchor won't work for sections that have dupes on page
                // as there's no way to strip that info from ApiWatchlist (apparently?).
                // RegExp in the line below is equal to Linker::formatAutocomments().
-               if ( $this->linkToSections && $comment !== null && preg_match( '!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment, $matches ) ) {
+               if ( $this->linkToSections && $comment !== null &&
+                       preg_match( '!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment, $matches )
+               ) {
                        global $wgParser;
+
                        $sectionTitle = $wgParser->stripSectionName( $matches[2] );
                        $sectionTitle = Sanitizer::normalizeSectionNameWhitespace( $sectionTitle );
                        $titleUrl .= Title::newFromText( '#' . $sectionTitle )->getFragmentForURL();
@@ -199,6 +207,7 @@ class ApiFeedWatchlist extends ApiBase {
                        $this->watchlistModule = $this->getMain()->getModuleManager()->getModule( 'query' )
                                ->getModuleManager()->getModule( 'watchlist' );
                }
+
                return $this->watchlistModule;
        }
 
@@ -235,11 +244,13 @@ class ApiFeedWatchlist extends ApiBase {
                        $ret['wltype'] = null;
                        $ret['wlexcludeuser'] = null;
                }
+
                return $ret;
        }
 
        public function getParamDescription() {
                $wldescr = $this->getWatchlistModule()->getParamDescription();
+
                return array(
                        'feedformat' => 'The format of the feed',
                        'hours' => 'List pages modified within this many hours from now',
index cbb2ba6..dc5e24e 100644 (file)
@@ -46,7 +46,15 @@ class ApiFileRevert extends ApiBase {
                $this->checkPermissions( $this->getUser() );
 
                $sourceUrl = $this->file->getArchiveVirtualUrl( $this->archiveName );
-               $status = $this->file->upload( $sourceUrl, $this->params['comment'], $this->params['comment'], 0, false, false, $this->getUser() );
+               $status = $this->file->upload(
+                       $sourceUrl,
+                       $this->params['comment'],
+                       $this->params['comment'],
+                       0,
+                       false,
+                       false,
+                       $this->getUser()
+               );
 
                if ( $status->isGood() ) {
                        $result = array( 'result' => 'Success' );
@@ -58,7 +66,6 @@ class ApiFileRevert extends ApiBase {
                }
 
                $this->getResult()->addValue( null, $this->getModuleName(), $result );
-
        }
 
        /**
@@ -130,7 +137,6 @@ class ApiFileRevert extends ApiBase {
                                ApiBase::PARAM_REQUIRED => true
                        ),
                );
-
        }
 
        public function getParamDescription() {
@@ -187,7 +193,8 @@ class ApiFileRevert extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=filerevert&filename=Wiki.png&comment=Revert&archivename=20110305152740!Wiki.png&token=123ABC'
+                       'api.php?action=filerevert&filename=Wiki.png&comment=Revert&' .
+                               'archivename=20110305152740!Wiki.png&token=123ABC'
                                => 'Revert Wiki.png to the version of 20110305152740',
                );
        }
index b89fb3a..63a5502 100644 (file)
@@ -30,7 +30,6 @@
  * @ingroup API
  */
 abstract class ApiFormatBase extends ApiBase {
-
        private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp, $mCleared;
        private $mBufferResult = false, $mBuffer, $mDisabled = false;
 
@@ -43,9 +42,9 @@ abstract class ApiFormatBase extends ApiBase {
        public function __construct( $main, $format ) {
                parent::__construct( $main, $format );
 
-               $this->mIsHtml = ( substr( $format, - 2, 2 ) === 'fm' ); // ends with 'fm'
+               $this->mIsHtml = ( substr( $format, -2, 2 ) === 'fm' ); // ends with 'fm'
                if ( $this->mIsHtml ) {
-                       $this->mFormat = substr( $format, 0, - 2 ); // remove ending 'fm'
+                       $this->mFormat = substr( $format, 0, -2 ); // remove ending 'fm'
                } else {
                        $this->mFormat = $format;
                }
@@ -156,17 +155,20 @@ abstract class ApiFormatBase extends ApiBase {
 <!DOCTYPE HTML>
 <html>
 <head>
-<?php if ( $this->mUnescapeAmps ) {
+<?php
+                       if ( $this->mUnescapeAmps ) {
 ?>     <title>MediaWiki API</title>
-<?php } else {
+<?php
+                       } else {
 ?>     <title>MediaWiki API Result</title>
-<?php } ?>
+<?php
+                       }
+?>
 </head>
 <body>
 <?php
-
-
                        if ( !$isHelpScreen ) {
+// @codingStandardsIgnoreStart Exclude long line from CodeSniffer checks
 ?>
 <br />
 <small>
@@ -179,15 +181,14 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
 </small>
 <pre style='white-space: pre-wrap;'>
 <?php
-
-
-                       } else { // don't wrap the contents of the <pre> for help screens
-                                 // because these are actually formatted to rely on
-                                 // the monospaced font for layout purposes
+// @codingStandardsIgnoreEnd
+                       // don't wrap the contents of the <pre> for help screens
+                       // because these are actually formatted to rely on
+                       // the monospaced font for layout purposes
+                       } else {
 ?>
 <pre>
 <?php
-
                        }
                }
        }
@@ -206,8 +207,6 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
 </body>
 </html>
 <?php
-
-
                }
        }
 
@@ -281,7 +280,11 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
                // identify URLs
                $protos = wfUrlProtocolsWithoutProtRel();
                // This regex hacks around bug 13218 (&quot; included in the URL)
-               $text = preg_replace( "#(((?i)$protos).*?)(&quot;)?([ \\'\"<>\n]|&lt;|&gt;|&quot;)#", '<a href="\\1">\\1</a>\\3\\4', $text );
+               $text = preg_replace(
+                       "#(((?i)$protos).*?)(&quot;)?([ \\'\"<>\n]|&lt;|&gt;|&quot;)#",
+                       '<a href="\\1">\\1</a>\\3\\4',
+                       $text
+               );
 
                /**
                 * Temporary fix for bad links in help messages. As a special case,
@@ -360,8 +363,8 @@ class ApiFormatFeedWrapper extends ApiFormatBase {
 
        /**
         * This class expects the result data to be in a custom format set by self::setResult()
-        * $result['_feed']             - an instance of one of the $wgFeedClasses classes
-        * $result['_feeditems']        - an array of FeedItem instances
+        * $result['_feed'] - an instance of one of the $wgFeedClasses classes
+        * $result['_feeditems'] - an array of FeedItem instances
         */
        public function execute() {
                $data = $this->getResultData();
index 342a580..be0b58b 100644 (file)
@@ -43,6 +43,7 @@ class ApiFormatJson extends ApiFormatBase {
                if ( $params['callback'] ) {
                        return 'text/javascript';
                }
+
                return 'application/json';
        }
 
@@ -80,16 +81,18 @@ class ApiFormatJson extends ApiFormatBase {
 
        public function getParamDescription() {
                return array(
-                       'callback' => 'If specified, wraps the output into a given function call. For safety, all user-specific data will be restricted.',
-                       'utf8' => 'If specified, encodes most (but not all) non-ASCII characters as UTF-8 instead of replacing them with hexadecimal escape sequences.',
+                       'callback' => 'If specified, wraps the output into a given function ' .
+                               'call. For safety, all user-specific data will be restricted.',
+                       'utf8' => 'If specified, encodes most (but not all) non-ASCII ' .
+                               'characters as UTF-8 instead of replacing them with hexadecimal escape sequences.',
                );
        }
 
        public function getDescription() {
                if ( $this->mIsRaw ) {
                        return 'Output data with the debugging elements in JSON format' . parent::getDescription();
-               } else {
-                       return 'Output data in JSON format' . parent::getDescription();
                }
+
+               return 'Output data in JSON format' . parent::getDescription();
        }
 }
index d278efa..45003e9 100644 (file)
@@ -58,6 +58,7 @@ class ApiFormatRaw extends ApiFormatBase {
                $data = $this->getResultData();
                if ( isset( $data['error'] ) ) {
                        $this->mErrorFallback->execute();
+
                        return;
                }
 
index 5685d93..df8e745 100644 (file)
@@ -38,10 +38,12 @@ class ApiFormatWddx extends ApiFormatBase {
                // Some versions of PHP have a broken wddx_serialize_value, see
                // PHP bug 45314. Test encoding an affected character (U+00A0)
                // to avoid this.
-               $expected = "<wddxPacket version='1.0'><header/><data><string>\xc2\xa0</string></data></wddxPacket>";
+               $expected =
+                       "<wddxPacket version='1.0'><header/><data><string>\xc2\xa0</string></data></wddxPacket>";
                if ( function_exists( 'wddx_serialize_value' )
-                               && !$this->getIsHtml()
-                               && wddx_serialize_value( "\xc2\xa0" ) == $expected ) {
+                       && !$this->getIsHtml()
+                       && wddx_serialize_value( "\xc2\xa0" ) == $expected
+               ) {
                        $this->printText( wddx_serialize_value( $this->getResultData() ) );
                } else {
                        // Don't do newlines and indentation if we weren't asked
index 4ec149c..e707eb4 100644 (file)
@@ -69,7 +69,7 @@ class ApiFormatXml extends ApiFormatBase {
                $this->printText(
                        self::recXmlPrint( $this->mRootElemName,
                                $data,
-                               $this->getIsHtml() ? - 2 : null
+                               $this->getIsHtml() ? -2 : null
                        )
                );
        }
@@ -160,7 +160,8 @@ class ApiFormatXml extends ApiFormatBase {
                        }
 
                        if ( is_null( $subElemIndName ) && count( $indElements ) ) {
-                               ApiBase::dieDebug( __METHOD__, "($elemName, ...) has integer keys without _element value. Use ApiResult::setIndexedTagName()." );
+                               ApiBase::dieDebug( __METHOD__, "($elemName, ...) has integer keys " .
+                                       "without _element value. Use ApiResult::setIndexedTagName()." );
                        }
 
                        if ( count( $subElements ) && count( $indElements ) && !is_null( $subElemContent ) ) {
@@ -193,6 +194,7 @@ class ApiFormatXml extends ApiFormatBase {
                                $retval .= $indstr . Xml::element( $elemName, null, $elemValue );
                        }
                }
+
                return $retval;
        }
 
@@ -200,17 +202,21 @@ class ApiFormatXml extends ApiFormatBase {
                $nt = Title::newFromText( $this->mXslt );
                if ( is_null( $nt ) || !$nt->exists() ) {
                        $this->setWarning( 'Invalid or non-existent stylesheet specified' );
+
                        return;
                }
                if ( $nt->getNamespace() != NS_MEDIAWIKI ) {
                        $this->setWarning( 'Stylesheet should be in the MediaWiki namespace.' );
+
                        return;
                }
-               if ( substr( $nt->getText(), - 4 ) !== '.xsl' ) {
+               if ( substr( $nt->getText(), -4 ) !== '.xsl' ) {
                        $this->setWarning( 'Stylesheet should have .xsl extension.' );
+
                        return;
                }
-               $this->printText( '<?xml-stylesheet href="' . htmlspecialchars( $nt->getLocalURL( 'action=raw' ) ) . '" type="text/xsl" ?>' );
+               $this->printText( '<?xml-stylesheet href="' .
+                       htmlspecialchars( $nt->getLocalURL( 'action=raw' ) ) . '" type="text/xsl" ?>' );
        }
 
        public function getAllowedParams() {
index 9cafc5b..5b1f29c 100644 (file)
@@ -30,7 +30,6 @@
  * @ingroup API
  */
 class ApiHelp extends ApiBase {
-
        /**
         * Module for displaying help
         */
@@ -68,19 +67,22 @@ class ApiHelp extends ApiBase {
                                // In case the '+' was typed into URL, it resolves as a space
                                $subNames = explode( ' ', $m );
                        }
+
                        $module = $this->getMain();
-                       for ( $i = 0; $i < count( $subNames ); $i++ ) {
+                       $subNamesCount = count( $subNames );
+                       for ( $i = 0; $i < $subNamesCount; $i++ ) {
                                $subs = $module->getModuleManager();
                                if ( $subs === null ) {
                                        $module = null;
                                } else {
                                        $module = $subs->getModule( $subNames[$i] );
                                }
+
                                if ( $module === null ) {
                                        if ( count( $subNames ) === 2
-                                                       && $i === 1
-                                                       && $subNames[0] === 'query'
-                                                       && in_array( $subNames[1], $queryModules )
+                                               && $i === 1
+                                               && $subNames[0] === 'query'
+                                               && in_array( $subNames[1], $queryModules )
                                        ) {
                                                // Legacy: This is one of the renamed 'querymodule=...' parameters,
                                                // do not use '+' notation in the output, use submodule's name instead.
@@ -94,6 +96,7 @@ class ApiHelp extends ApiBase {
                                        $type = $subs->getModuleGroup( $subNames[$i] );
                                }
                        }
+
                        if ( $module !== null ) {
                                $r[] = $this->buildModuleHelp( $module, $type );
                        }
@@ -141,8 +144,10 @@ class ApiHelp extends ApiBase {
 
        public function getParamDescription() {
                return array(
-                       'modules' => 'List of module names (value of the action= parameter). Can specify submodules with a \'+\'',
-                       'querymodules' => 'Use modules=query+value instead. List of query module names (value of prop=, meta= or list= parameter)',
+                       'modules' => 'List of module names (value of the action= parameter). ' .
+                               'Can specify submodules with a \'+\'',
+                       'querymodules' => 'Use modules=query+value instead. List of query ' .
+                               'module names (value of prop=, meta= or list= parameter)',
                );
        }
 
@@ -154,8 +159,10 @@ class ApiHelp extends ApiBase {
                return array(
                        'api.php?action=help' => 'Whole help page',
                        'api.php?action=help&modules=protect' => 'Module (action) help page',
-                       'api.php?action=help&modules=query+categorymembers' => 'Help for the query/categorymembers module',
-                       'api.php?action=help&modules=login|query+info' => 'Help for the login and query/info modules',
+                       'api.php?action=help&modules=query+categorymembers'
+                               => 'Help for the query/categorymembers module',
+                       'api.php?action=help&modules=login|query+info'
+                               => 'Help for the login and query/info modules',
                );
        }
 
index 7a60e83..5d2ee6f 100644 (file)
 class ApiImageRotate extends ApiBase {
        private $mPageSet = null;
 
-       public function __construct( $main, $action ) {
-               parent::__construct( $main, $action );
-       }
-
        /**
         * Add all items from $values into the result
         * @param array $result output
@@ -145,6 +141,7 @@ class ApiImageRotate extends ApiBase {
                if ( $this->mPageSet === null ) {
                        $this->mPageSet = new ApiPageSet( $this, 0, NS_FILE );
                }
+
                return $this->mPageSet;
        }
 
@@ -163,6 +160,7 @@ class ApiImageRotate extends ApiBase {
                if ( $permissionErrors ) {
                        // Just return the first error
                        $msg = $this->parseMsg( $permissionErrors[0] );
+
                        return $msg['info'];
                }
 
@@ -191,11 +189,13 @@ class ApiImageRotate extends ApiBase {
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
                }
+
                return $result;
        }
 
        public function getParamDescription() {
                $pageSet = $this->getPageSet();
+
                return $pageSet->getFinalParamDescription() + array(
                        'rotation' => 'Degrees to rotate image clockwise',
                        'token' => 'Edit token. You can get one of these through action=tokens',
@@ -216,6 +216,7 @@ class ApiImageRotate extends ApiBase {
 
        public function getPossibleErrors() {
                $pageSet = $this->getPageSet();
+
                return array_merge(
                        parent::getPossibleErrors(),
                        $pageSet->getFinalPossibleErrors()
index f48a822..295f16e 100644 (file)
@@ -99,6 +99,7 @@ class ApiImport extends ApiBase {
 
        public function getAllowedParams() {
                global $wgImportSources;
+
                return array(
                        'token' => array(
                                ApiBase::PARAM_TYPE => 'string',
@@ -176,7 +177,8 @@ class ApiImport extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=import&interwikisource=meta&interwikipage=Help:ParserFunctions&namespace=100&fullhistory=&token=123ABC'
+                       'api.php?action=import&interwikisource=meta&interwikipage=Help:ParserFunctions&' .
+                               'namespace=100&fullhistory=&token=123ABC'
                                => 'Import [[meta:Help:Parserfunctions]] to namespace 100 with full history',
                );
        }
index b51d441..fe3143e 100644 (file)
@@ -52,6 +52,7 @@ class ApiLogin extends ApiBase {
                                'result' => 'Aborted',
                                'reason' => 'Cannot log in when using a callback',
                        ) );
+
                        return;
                }
 
@@ -131,7 +132,9 @@ class ApiLogin extends ApiBase {
                                $result['result'] = 'NotExists';
                                break;
 
-                       case LoginForm::RESET_PASS: // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin - "The e-mailed temporary password should not be used for actual logins;"
+                       // bug 20223 - Treat a temporary password as wrong. Per SpecialUserLogin:
+                       // The e-mailed temporary password should not be used for actual logins.
+                       case LoginForm::RESET_PASS:
                        case LoginForm::WRONG_PASS:
                                $result['result'] = 'WrongPass';
                                break;
@@ -254,25 +257,40 @@ class ApiLogin extends ApiBase {
 
        public function getDescription() {
                return array(
-                       'Log in and get the authentication tokens. ',
-                       'In the event of a successful log-in, a cookie will be attached',
-                       'to your session. In the event of a failed log-in, you will not ',
-                       'be able to attempt another log-in through this method for 5 seconds.',
-                       'This is to prevent password guessing by automated password crackers'
+                       'Log in and get the authentication tokens.',
+                       'In the event of a successful log-in, a cookie will be attached to your session.',
+                       'In the event of a failed log-in, you will not be able to attempt another log-in',
+                       'through this method for 5 seconds. This is to prevent password guessing by',
+                       'automated password crackers'
                );
        }
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'NeedToken', 'info' => 'You need to resubmit your login with the specified token. See https://bugzilla.wikimedia.org/show_bug.cgi?id=23076' ),
+                       array(
+                               'code' => 'NeedToken', 'info' => 'You need to resubmit your ' .
+                               'login with the specified token. See ' .
+                                       'https://bugzilla.wikimedia.org/show_bug.cgi?id=23076'
+                       ),
                        array( 'code' => 'WrongToken', 'info' => 'You specified an invalid token' ),
                        array( 'code' => 'NoName', 'info' => 'You didn\'t set the lgname parameter' ),
-                       array( 'code' => 'Illegal', 'info' => ' You provided an illegal username' ),
-                       array( 'code' => 'NotExists', 'info' => ' The username you provided doesn\'t exist' ),
-                       array( 'code' => 'EmptyPass', 'info' => ' You didn\'t set the lgpassword parameter or you left it empty' ),
-                       array( 'code' => 'WrongPass', 'info' => ' The password you provided is incorrect' ),
-                       array( 'code' => 'WrongPluginPass', 'info' => 'Same as "WrongPass", returned when an authentication plugin rather than MediaWiki itself rejected the password' ),
-                       array( 'code' => 'CreateBlocked', 'info' => 'The wiki tried to automatically create a new account for you, but your IP address has been blocked from account creation' ),
+                       array( 'code' => 'Illegal', 'info' => 'You provided an illegal username' ),
+                       array( 'code' => 'NotExists', 'info' => 'The username you provided doesn\'t exist' ),
+                       array(
+                               'code' => 'EmptyPass',
+                               'info' => 'You didn\'t set the lgpassword parameter or you left it empty'
+                       ),
+                       array( 'code' => 'WrongPass', 'info' => 'The password you provided is incorrect' ),
+                       array(
+                               'code' => 'WrongPluginPass',
+                               'info' => 'Same as "WrongPass", returned when an authentication ' .
+                                       'plugin rather than MediaWiki itself rejected the password'
+                       ),
+                       array(
+                               'code' => 'CreateBlocked',
+                               'info' => 'The wiki tried to automatically create a new account ' .
+                                       'for you, but your IP address has been blocked from account creation'
+                       ),
                        array( 'code' => 'Throttled', 'info' => 'You\'ve logged in too many times in a short time' ),
                        array( 'code' => 'Blocked', 'info' => 'User is blocked' ),
                ) );
index c10d85c..829ba6f 100644 (file)
@@ -110,6 +110,7 @@ class ApiMain extends ApiBase {
                'none' => 'ApiFormatNone',
        );
 
+       // @codingStandardsIgnoreStart String contenation on "msg" not allowed to break long line
        /**
         * List of user roles that are specifically relevant to the API.
         * array( 'right' => array ( 'msg'    => 'Some message with a $1',
@@ -126,6 +127,7 @@ class ApiMain extends ApiBase {
                        'params' => array( ApiBase::LIMIT_SML2, ApiBase::LIMIT_BIG2 )
                )
        );
+       // @codingStandardsIgnoreEnd
 
        /**
         * @var ApiFormatBase
@@ -144,7 +146,8 @@ class ApiMain extends ApiBase {
        /**
         * Constructs an instance of ApiMain that utilizes the module and format specified by $request.
         *
-        * @param $context IContextSource|WebRequest - if this is an instance of FauxRequest, errors are thrown and no printing occurs
+        * @param $context IContextSource|WebRequest - if this is an instance of
+        *    FauxRequest, errors are thrown and no printing occurs
         * @param bool $enableWrite should be set to true if the api may modify data
         */
        public function __construct( $context = null, $enableWrite = false ) {
@@ -182,16 +185,17 @@ class ApiMain extends ApiBase {
                        }
                }
 
-               global $wgAPIModules;
+               global $wgAPIModules, $wgAPIFormatModules;
                $this->mModuleMgr = new ApiModuleManager( $this );
                $this->mModuleMgr->addModules( self::$Modules, 'action' );
                $this->mModuleMgr->addModules( $wgAPIModules, 'action' );
                $this->mModuleMgr->addModules( self::$Formats, 'format' );
+               $this->mModuleMgr->addModules( $wgAPIFormatModules, 'format' );
 
                $this->mResult = new ApiResult( $this );
                $this->mEnableWrite = $enableWrite;
 
-               $this->mSquidMaxage = - 1; // flag for executeActionWithErrorHandling()
+               $this->mSquidMaxage = -1; // flag for executeActionWithErrorHandling()
                $this->mCommit = false;
        }
 
@@ -270,6 +274,7 @@ class ApiMain extends ApiBase {
        public function setCacheMode( $mode ) {
                if ( !in_array( $mode, array( 'private', 'public', 'anon-public-user-private' ) ) ) {
                        wfDebug( __METHOD__ . ": unrecognised cache mode \"$mode\"\n" );
+
                        // Ignore for forwards-compatibility
                        return;
                }
@@ -278,6 +283,7 @@ class ApiMain extends ApiBase {
                        // Private wiki, only private headers
                        if ( $mode !== 'private' ) {
                                wfDebug( __METHOD__ . ": ignoring request for $mode cache mode, private wiki\n" );
+
                                return;
                        }
                }
@@ -337,6 +343,7 @@ class ApiMain extends ApiBase {
                if ( $printer === null ) {
                        $this->dieUsage( "Unrecognized format: {$format}", 'unknown_format' );
                }
+
                return $printer;
        }
 
@@ -383,13 +390,8 @@ class ApiMain extends ApiBase {
                        wfRunHooks( 'ApiMain::onException', array( $this, $e ) );
 
                        // Log it
-                       if ( $e instanceof MWException && !( $e instanceof UsageException ) ) {
-                               global $wgLogExceptionBacktrace;
-                               if ( $wgLogExceptionBacktrace ) {
-                                       wfDebugLog( 'exception', $e->getLogMessage() . "\n" . $e->getTraceAsString() . "\n" );
-                               } else {
-                                       wfDebugLog( 'exception', $e->getLogMessage() );
-                               }
+                       if ( !( $e instanceof UsageException ) ) {
+                               MWExceptionHandler::logException( $e );
                        }
 
                        // Handle any kind of exception by outputting properly formatted error message.
@@ -461,6 +463,7 @@ class ApiMain extends ApiBase {
                } else {
                        $origins = explode( ' ', $originHeader );
                }
+
                if ( !in_array( $originParam, $origins ) ) {
                        // origin parameter set but incorrect
                        // Send a 403 response
@@ -468,13 +471,22 @@ class ApiMain extends ApiBase {
                        $response->header( "HTTP/1.1 403 $message", true, 403 );
                        $response->header( 'Cache-Control: no-cache' );
                        echo "'origin' parameter does not match Origin header\n";
+
                        return false;
                }
-               if ( self::matchOrigin( $originParam, $wgCrossSiteAJAXdomains, $wgCrossSiteAJAXdomainExceptions ) ) {
+
+               $matchOrigin = self::matchOrigin(
+                       $originParam,
+                       $wgCrossSiteAJAXdomains,
+                       $wgCrossSiteAJAXdomainExceptions
+               );
+
+               if ( $matchOrigin ) {
                        $response->header( "Access-Control-Allow-Origin: $originParam" );
                        $response->header( 'Access-Control-Allow-Credentials: true' );
                        $this->getOutput()->addVaryHeader( 'Origin' );
                }
+
                return true;
        }
 
@@ -483,7 +495,8 @@ class ApiMain extends ApiBase {
         * @param string $value Origin header
         * @param array $rules Set of wildcard rules
         * @param array $exceptions Set of wildcard rules
-        * @return bool True if $value matches a rule in $rules and doesn't match any rules in $exceptions, false otherwise
+        * @return bool True if $value matches a rule in $rules and doesn't match
+        *    any rules in $exceptions, false otherwise
         */
        protected static function matchOrigin( $value, $rules, $exceptions ) {
                foreach ( $rules as $rule ) {
@@ -494,9 +507,11 @@ class ApiMain extends ApiBase {
                                                return false;
                                        }
                                }
+
                                return true;
                        }
                }
+
                return false;
        }
 
@@ -515,6 +530,7 @@ class ApiMain extends ApiBase {
                        array( '.*?', '.' ),
                        $wildcard
                );
+
                return "/https?:\/\/$wildcard/";
        }
 
@@ -529,6 +545,7 @@ class ApiMain extends ApiBase {
 
                if ( $this->mCacheMode == 'private' ) {
                        $response->header( 'Cache-Control: private' );
+
                        return;
                }
 
@@ -540,6 +557,7 @@ class ApiMain extends ApiBase {
                                if ( $out->haveCacheVaryCookies() ) {
                                        // Logged in, mark this request private
                                        $response->header( 'Cache-Control: private' );
+
                                        return;
                                }
                                // Logged out, send normal public headers below
@@ -547,6 +565,7 @@ class ApiMain extends ApiBase {
                                // Logged in or otherwise has session (e.g. anonymous users who have edited)
                                // Mark request private
                                $response->header( 'Cache-Control: private' );
+
                                return;
                        } // else no XVO and anonymous, send public headers below
                }
@@ -570,6 +589,7 @@ class ApiMain extends ApiBase {
                        // Sending a Vary header in this case is harmless, and protects us
                        // against conditional calls of setCacheMaxAge().
                        $response->header( 'Cache-Control: private' );
+
                        return;
                }
 
@@ -643,7 +663,10 @@ class ApiMain extends ApiBase {
                                'code' => 'internal_api_error_' . get_class( $e ),
                                'info' => $info,
                        );
-                       ApiResult::setContent( $errMessage, $wgShowExceptionDetails ? "\n\n{$e->getTraceAsString()}\n\n" : '' );
+                       ApiResult::setContent(
+                               $errMessage,
+                               $wgShowExceptionDetails ? "\n\n{$e->getTraceAsString()}\n\n" : ''
+                       );
                }
 
                // Remember all the warnings to re-add them later
@@ -719,12 +742,17 @@ class ApiMain extends ApiBase {
                if ( $salt !== false ) {
                        if ( !isset( $moduleParams['token'] ) ) {
                                $this->dieUsageMsg( array( 'missingparam', 'token' ) );
-                       } else {
-                               if ( !$this->getUser()->matchEditToken( $moduleParams['token'], $salt, $this->getContext()->getRequest() ) ) {
-                                       $this->dieUsageMsg( 'sessionfailure' );
-                               }
+                       }
+
+                       if ( !$this->getUser()->matchEditToken(
+                               $moduleParams['token'],
+                               $salt,
+                               $this->getContext()->getRequest() )
+                       ) {
+                               $this->dieUsageMsg( 'sessionfailure' );
                        }
                }
+
                return $module;
        }
 
@@ -748,12 +776,12 @@ class ApiMain extends ApiBase {
 
                                if ( $wgShowHostnames ) {
                                        $this->dieUsage( "Waiting for $host: $lag seconds lagged", 'maxlag' );
-                               } else {
-                                       $this->dieUsage( "Waiting for a database server: $lag seconds lagged", 'maxlag' );
                                }
-                               return false;
+
+                               $this->dieUsage( "Waiting for a database server: $lag seconds lagged", 'maxlag' );
                        }
                }
+
                return true;
        }
 
@@ -764,8 +792,8 @@ class ApiMain extends ApiBase {
        protected function checkExecutePermissions( $module ) {
                $user = $this->getUser();
                if ( $module->isReadMode() && !User::isEveryoneAllowed( 'read' ) &&
-                       !$user->isAllowed( 'read' ) )
-               {
+                       !$user->isAllowed( 'read' )
+               {
                        $this->dieUsageMsg( 'readrequired' );
                }
                if ( $module->isWriteMode() ) {
@@ -848,7 +876,7 @@ class ApiMain extends ApiBase {
 
        /**
         * Log the preceding request
-        * @param $time Time in seconds
+        * @param int $time Time in seconds
         */
        protected function logRequest( $time ) {
                $request = $this->getRequest();
@@ -882,10 +910,12 @@ class ApiMain extends ApiBase {
                static $table;
                if ( !$table ) {
                        $chars = ';@$!*(),/:';
-                       for ( $i = 0; $i < strlen( $chars ); $i++ ) {
+                       $numChars = strlen( $chars );
+                       for ( $i = 0; $i < $numChars; $i++ ) {
                                $table[rawurlencode( $chars[$i] )] = $chars[$i];
                        }
                }
+
                return strtr( rawurlencode( $s ), $table );
        }
 
@@ -901,6 +931,7 @@ class ApiMain extends ApiBase {
         */
        public function getVal( $name, $default = null ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getVal( $name, $default );
        }
 
@@ -910,6 +941,7 @@ class ApiMain extends ApiBase {
         */
        public function getCheck( $name ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getCheck( $name );
        }
 
@@ -922,6 +954,7 @@ class ApiMain extends ApiBase {
         */
        public function getUpload( $name ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getUpload( $name );
        }
 
@@ -1039,13 +1072,17 @@ class ApiMain extends ApiBase {
                        'smaxage' => 'Set the s-maxage header to this many seconds. Errors are never cached',
                        'maxage' => 'Set the max-age header to this many seconds. Errors are never cached',
                        'requestid' => 'Request ID to distinguish requests. This will just be output back to you',
-                       'servedby' => 'Include the hostname that served the request in the results. Unconditionally shown on error',
+                       'servedby' => 'Include the hostname that served the request in the ' .
+                               'results. Unconditionally shown on error',
                        'origin' => array(
-                               'When accessing the API using a cross-domain AJAX request (CORS), set this to the originating domain.',
-                               'This must be included in any pre-flight request, and therefore must be part of the request URI (not the POST body).',
-                               'This must match one of the origins in the Origin: header exactly, so it has to be set to something like http://en.wikipedia.org or https://meta.wikimedia.org .',
-                               'If this parameter does not match the Origin: header, a 403 response will be returned.',
-                               'If this parameter matches the Origin: header and the origin is whitelisted, an Access-Control-Allow-Origin header will be set.',
+                               'When accessing the API using a cross-domain AJAX request (CORS), set this to the',
+                               'originating domain. This must be included in any pre-flight request, and',
+                               'therefore must be part of the request URI (not the POST body). This must match',
+                               'one of the origins in the Origin: header exactly, so it has to be set to ',
+                               'something like http://en.wikipedia.org or https://meta.wikimedia.org . If this',
+                               'parameter does not match the Origin: header, a 403 response will be returned. If',
+                               'this parameter matches the Origin: header and the origin is whitelisted, an',
+                               'Access-Control-Allow-Origin header will be set.',
                        ),
                );
        }
@@ -1059,14 +1096,14 @@ class ApiMain extends ApiBase {
                return array(
                        '',
                        '',
-                       '**********************************************************************************************************',
-                       '**                                                                                                      **',
-                       '**                      This is an auto-generated MediaWiki API documentation page                      **',
-                       '**                                                                                                      **',
-                       '**                                     Documentation and Examples:                                      **',
-                       '**                                  https://www.mediawiki.org/wiki/API                                  **',
-                       '**                                                                                                      **',
-                       '**********************************************************************************************************',
+                       '**********************************************************************************************',
+                       '**                                                                                          **',
+                       '**                This is an auto-generated MediaWiki API documentation page                **',
+                       '**                                                                                          **',
+                       '**                               Documentation and Examples:                                **',
+                       '**                            https://www.mediawiki.org/wiki/API                            **',
+                       '**                                                                                          **',
+                       '**********************************************************************************************',
                        '',
                        'Status:                All features shown on this page should be working, but the API',
                        '                       is still in active development, and may change at any time.',
@@ -1079,13 +1116,15 @@ class ApiMain extends ApiBase {
                        '                       In the case of an invalid action being passed, these will have a value',
                        '                       of "unknown_action"',
                        '',
-                       '                       For more information see https://www.mediawiki.org/wiki/API:Errors_and_warnings',
+                       '                       For more information see https://www.mediawiki.org' .
+                               '/wiki/API:Errors_and_warnings',
                        '',
                        'Documentation:         https://www.mediawiki.org/wiki/API:Main_page',
                        'FAQ                    https://www.mediawiki.org/wiki/API:FAQ',
                        'Mailing list:          https://lists.wikimedia.org/mailman/listinfo/mediawiki-api',
                        'Api Announcements:     https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce',
-                       'Bugs & Requests:       https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts',
+                       'Bugs & Requests:       https://bugzilla.wikimedia.org/buglist.cgi?component=API&' .
+                               'bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts',
                        '',
                        '',
                        '',
@@ -1114,11 +1153,12 @@ class ApiMain extends ApiBase {
        protected function getCredits() {
                return array(
                        'API developers:',
-                       '    Roan Kattouw "<Firstname>.<Lastname>@gmail.com" (lead developer Sep 2007-2009)',
+                       '    Roan Kattouw - roan . kattouw @ gmail . com (lead developer Sep 2007-2009)',
                        '    Victor Vasiliev - vasilvv @ gmail . com',
                        '    Bryan Tong Minh - bryan . tongminh @ gmail . com',
                        '    Sam Reed - sam @ reedyboy . net',
-                       '    Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007, 2012-present)',
+                       '    Yuri Astrakhan - yuri . astrakhan @ gmail . com (creator, lead ' .
+                               'developer Sep 2006-Sep 2007, 2012-present)',
                        '',
                        'Please send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org',
                        'or file a bug report at https://bugzilla.wikimedia.org/'
@@ -1155,6 +1195,7 @@ class ApiMain extends ApiBase {
                if ( $wgAPICacheHelpTimeout > 0 ) {
                        $wgMemc->set( $key, $retval, $wgAPICacheHelpTimeout );
                }
+
                return $retval;
        }
 
@@ -1185,7 +1226,7 @@ class ApiMain extends ApiBase {
                foreach ( self::$mRights as $right => $rightMsg ) {
                        $groups = User::getGroupsWithPermission( $right );
                        $msg .= "* " . $right . " *\n  " . wfMsgReplaceArgs( $rightMsg['msg'], $rightMsg['params'] ) .
-                                               "\nGranted to:\n  " . str_replace( '*', 'all', implode( ', ', $groups ) ) . "\n\n";
+                               "\nGranted to:\n  " . str_replace( '*', 'all', implode( ', ', $groups ) ) . "\n\n";
                }
 
                $msg .= "\n$astriks Formats  $astriks\n\n";
@@ -1206,7 +1247,8 @@ class ApiMain extends ApiBase {
 
        /**
         * @param $module ApiBase
-        * @param string $paramName What type of request is this? e.g. action, query, list, prop, meta, format
+        * @param string $paramName What type of request is this? e.g. action,
+        *    query, list, prop, meta, format
         * @return string
         */
        public static function makeHelpMsgHeader( $module, $paramName ) {
@@ -1239,6 +1281,7 @@ class ApiMain extends ApiBase {
         */
        public function getShowVersions() {
                wfDeprecated( __METHOD__, '1.21' );
+
                return false;
        }
 
@@ -1341,6 +1384,7 @@ class UsageException extends MWException {
                if ( is_array( $this->mExtraData ) ) {
                        $result = array_merge( $result, $this->mExtraData );
                }
+
                return $result;
        }
 
index 100392b..c33e18c 100644 (file)
@@ -97,6 +97,7 @@ class ApiModuleManager extends ContextSource {
                                // cache this instance in case it is needed later
                                $this->mInstances[$moduleName] = $instance;
                        }
+
                        return $instance;
                }
        }
@@ -116,6 +117,7 @@ class ApiModuleManager extends ContextSource {
                                $result[] = $name;
                        }
                }
+
                return $result;
        }
 
@@ -131,6 +133,7 @@ class ApiModuleManager extends ContextSource {
                                $result[$name] = $grpCls[1];
                        }
                }
+
                return $result;
        }
 
@@ -143,9 +146,9 @@ class ApiModuleManager extends ContextSource {
        public function isDefined( $moduleName, $group = null ) {
                if ( isset( $this->mModules[$moduleName] ) ) {
                        return $group === null || $this->mModules[$moduleName][0] === $group;
-               } else {
-                       return false;
                }
+
+               return false;
        }
 
        /**
@@ -156,9 +159,9 @@ class ApiModuleManager extends ContextSource {
        public function getModuleGroup( $moduleName ) {
                if ( isset( $this->mModules[$moduleName] ) ) {
                        return $this->mModules[$moduleName][0];
-               } else {
-                       return null;
                }
+
+               return null;
        }
 
        /**
index c18036c..20ac48a 100644 (file)
@@ -61,8 +61,8 @@ class ApiMove extends ApiBase {
 
                if ( $toTitle->getNamespace() == NS_FILE
                        && !RepoGroup::singleton()->getLocalRepo()->findFile( $toTitle )
-                       && wfFindFile( $toTitle ) )
-               {
+                       && wfFindFile( $toTitle )
+               {
                        if ( !$params['ignorewarnings'] && $user->isAllowed( 'reupload-shared' ) ) {
                                $this->dieUsageMsg( 'sharedfile-exists' );
                        } elseif ( !$user->isAllowed( 'reupload-shared' ) ) {
@@ -77,7 +77,11 @@ class ApiMove extends ApiBase {
                        $this->dieUsageMsg( reset( $retval ) );
                }
 
-               $r = array( 'from' => $fromTitle->getPrefixedText(), 'to' => $toTitle->getPrefixedText(), 'reason' => $params['reason'] );
+               $r = array(
+                       'from' => $fromTitle->getPrefixedText(),
+                       'to' => $toTitle->getPrefixedText(),
+                       'reason' => $params['reason']
+               );
 
                if ( $fromTitle->exists() ) {
                        //NOTE: we assume that if the old title exists, it's because it was re-created as
@@ -115,7 +119,7 @@ class ApiMove extends ApiBase {
                // Move subpages
                if ( $params['movesubpages'] ) {
                        $r['subpages'] = $this->moveSubpages( $fromTitle, $toTitle,
-                                       $params['reason'], $params['noredirect'] );
+                               $params['reason'], $params['noredirect'] );
                        $result->setIndexedTagName( $r['subpages'], 'subpage' );
 
                        if ( $params['movetalk'] ) {
@@ -153,20 +157,21 @@ class ApiMove extends ApiBase {
                $success = $fromTitle->moveSubpages( $toTitle, true, $reason, !$noredirect );
                if ( isset( $success[0] ) ) {
                        return array( 'error' => $this->parseMsg( $success ) );
-               } else {
-                       // At least some pages could be moved
-                       // Report each of them separately
-                       foreach ( $success as $oldTitle => $newTitle ) {
-                               $r = array( 'from' => $oldTitle );
-                               if ( is_array( $newTitle ) ) {
-                                       $r['error'] = $this->parseMsg( reset( $newTitle ) );
-                               } else {
-                                       // Success
-                                       $r['to'] = $newTitle;
-                               }
-                               $retval[] = $r;
+               }
+
+               // At least some pages could be moved
+               // Report each of them separately
+               foreach ( $success as $oldTitle => $newTitle ) {
+                       $r = array( 'from' => $oldTitle );
+                       if ( is_array( $newTitle ) ) {
+                               $r['error'] = $this->parseMsg( reset( $newTitle ) );
+                       } else {
+                               // Success
+                               $r['to'] = $newTitle;
                        }
+                       $retval[] = $r;
                }
+
                return $retval;
        }
 
@@ -219,6 +224,7 @@ class ApiMove extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'from' => "Title of the page you want to move. Cannot be used together with {$p}fromid",
                        'fromid' => "Page ID of the page you want to move. Cannot be used together with {$p}from",
@@ -230,7 +236,8 @@ class ApiMove extends ApiBase {
                        'noredirect' => 'Don\'t create a redirect',
                        'watch' => 'Add the page and the redirect to your watchlist',
                        'unwatch' => 'Remove the page and the redirect from your watchlist',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'watchlist' => 'Unconditionally add or remove the page from your ' .
+                               'watchlist, use preferences or do not change watch',
                        'ignorewarnings' => 'Ignore any warnings'
                );
        }
@@ -291,7 +298,8 @@ class ApiMove extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=move&from=Badtitle&to=Goodtitle&token=123ABC&reason=Misspelled%20title&movetalk=&noredirect='
+                       'api.php?action=move&from=Badtitle&to=Goodtitle&token=123ABC&' .
+                               'reason=Misspelled%20title&movetalk=&noredirect='
                );
        }
 
index 315ace3..4b8578b 100644 (file)
@@ -40,6 +40,7 @@ class ApiOpenSearch extends ApiBase {
                if ( in_array( $format, $allowed ) ) {
                        return $this->getMain()->createPrinterByName( $format );
                }
+
                return $this->getMain()->createPrinterByName( $allowed[0] );
        }
 
@@ -89,10 +90,12 @@ class ApiOpenSearch extends ApiBase {
        }
 
        public function getAllowedParams() {
+               global $wgOpenSearchDefaultLimit;
+
                return array(
                        'search' => null,
                        'limit' => array(
-                               ApiBase::PARAM_DFLT => 10,
+                               ApiBase::PARAM_DFLT => $wgOpenSearchDefaultLimit,
                                ApiBase::PARAM_TYPE => 'limit',
                                ApiBase::PARAM_MIN => 1,
                                ApiBase::PARAM_MAX => 100,
index 7256066..929b0b6 100644 (file)
@@ -31,7 +31,6 @@
  * @ingroup API
  */
 class ApiOptions extends ApiBase {
-
        /**
         * Changes preferences of the current user.
         */
@@ -172,9 +171,13 @@ class ApiOptions extends ApiBase {
                        'token' => 'An options token previously obtained through the action=tokens',
                        'reset' => 'Resets preferences to the site defaults',
                        'resetkinds' => 'List of types of options to reset when the "reset" option is set',
-                       'change' => 'List of changes, formatted name=value (e.g. skin=vector), value cannot contain pipe characters. If no value is given (not even an equals sign), e.g., optionname|otheroption|..., the option will be reset to its default value',
+                       'change' => 'List of changes, formatted name=value (e.g. skin=vector), ' .
+                               'value cannot contain pipe characters. If no value is given (not ' .
+                               'even an equals sign), e.g., optionname|otheroption|..., the ' .
+                               'option will be reset to its default value',
                        'optionname' => 'A name of a option which should have an optionvalue set',
-                       'optionvalue' => 'A value of the option specified by the optionname, can contain pipe characters',
+                       'optionvalue' => 'A value of the option specified by the optionname, ' .
+                               'can contain pipe characters',
                );
        }
 
@@ -182,7 +185,8 @@ class ApiOptions extends ApiBase {
                return array(
                        'Change preferences of the current user',
                        'Only options which are registered in core or in one of installed extensions,',
-                       'or as options with keys prefixed with \'userjs-\' (intended to be used by user scripts), can be set.'
+                       'or as options with keys prefixed with \'userjs-\' (intended to be used by user',
+                       'scripts), can be set.'
                );
        }
 
@@ -209,7 +213,8 @@ class ApiOptions extends ApiBase {
                return array(
                        'api.php?action=options&reset=&token=123ABC',
                        'api.php?action=options&change=skin=vector|hideminor=1&token=123ABC',
-                       'api.php?action=options&reset=&change=skin=monobook&optionname=nickname&optionvalue=[[User:Beau|Beau]]%20([[User_talk:Beau|talk]])&token=123ABC',
+                       'api.php?action=options&reset=&change=skin=monobook&optionname=nickname&' .
+                               'optionvalue=[[User:Beau|Beau]]%20([[User_talk:Beau|talk]])&token=123ABC',
                );
        }
 }
index b05cb2b..e95e680 100644 (file)
@@ -112,7 +112,8 @@ class ApiPageSet extends ApiBase {
 
        /**
         * Populate the PageSet from the request parameters.
-        * @param bool $isDryRun If true, instantiates generator, but only to mark relevant parameters as used
+        * @param bool $isDryRun If true, instantiates generator, but only to mark
+        *    relevant parameters as used
         */
        private function executeInternal( $isDryRun ) {
                $this->profileIn();
@@ -200,8 +201,9 @@ class ApiPageSet extends ApiBase {
                                                break;
                                        case 'revids':
                                                if ( $this->mResolveRedirects ) {
-                                                       $this->setWarning( 'Redirect resolution cannot be used together with the revids= parameter. ' .
-                                                               'Any redirects the revids= point to have not been resolved.' );
+                                                       $this->setWarning( 'Redirect resolution cannot be used ' .
+                                                               'together with the revids= parameter. Any redirects ' .
+                                                               'the revids= point to have not been resolved.' );
                                                }
                                                $this->mResolveRedirects = false;
                                                $this->initFromRevIDs( $this->mParams['revids'] );
@@ -244,6 +246,7 @@ class ApiPageSet extends ApiBase {
                if ( isset( $this->mParams['revids'] ) ) {
                        return 'revids';
                }
+
                return null;
        }
 
@@ -289,6 +292,7 @@ class ApiPageSet extends ApiBase {
                $this->mRequestedPageFields = array_diff_key( $this->mRequestedPageFields, $pageFlds );
 
                $pageFlds = array_merge( $pageFlds, $this->mRequestedPageFields );
+
                return array_keys( $pageFlds );
        }
 
@@ -391,6 +395,7 @@ class ApiPageSet extends ApiBase {
                if ( !empty( $values ) && $result ) {
                        $result->setIndexedTagName( $values, 'r' );
                }
+
                return $values;
        }
 
@@ -421,6 +426,7 @@ class ApiPageSet extends ApiBase {
                if ( !empty( $values ) && $result ) {
                        $result->setIndexedTagName( $values, 'n' );
                }
+
                return $values;
        }
 
@@ -451,6 +457,7 @@ class ApiPageSet extends ApiBase {
                if ( !empty( $values ) && $result ) {
                        $result->setIndexedTagName( $values, 'c' );
                }
+
                return $values;
        }
 
@@ -487,6 +494,7 @@ class ApiPageSet extends ApiBase {
                if ( !empty( $values ) && $result ) {
                        $result->setIndexedTagName( $values, 'i' );
                }
+
                return $values;
        }
 
@@ -522,6 +530,7 @@ class ApiPageSet extends ApiBase {
                if ( !empty( $values ) && $result ) {
                        $result->setIndexedTagName( $values, 'rev' );
                }
+
                return $values;
        }
 
@@ -584,7 +593,7 @@ class ApiPageSet extends ApiBase {
 
        /**
         * Extract all requested fields from the row received from the database
-        * @param $row Result row
+        * @param stdClass $row Result row
         */
        public function processDbRow( $row ) {
                // Store Title object in various data structures
@@ -642,7 +651,7 @@ class ApiPageSet extends ApiBase {
                // Get pageIDs data from the `page` table
                $this->profileDBIn();
                $res = $db->select( 'page', $this->getPageTableFields(), $set,
-                                       __METHOD__ );
+                       __METHOD__ );
                $this->profileDBOut();
 
                // Hack: get the ns:titles stored in array(ns => array(titles)) format
@@ -676,7 +685,7 @@ class ApiPageSet extends ApiBase {
                        // Get pageIDs data from the `page` table
                        $this->profileDBIn();
                        $res = $db->select( 'page', $this->getPageTableFields(), $set,
-                                               __METHOD__ );
+                               __METHOD__ );
                        $this->profileDBOut();
                }
 
@@ -863,7 +872,12 @@ class ApiPageSet extends ApiBase {
                foreach ( $res as $row ) {
                        $rdfrom = intval( $row->rd_from );
                        $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
-                       $to = Title::makeTitle( $row->rd_namespace, $row->rd_title, $row->rd_fragment, $row->rd_interwiki );
+                       $to = Title::makeTitle(
+                               $row->rd_namespace,
+                               $row->rd_title,
+                               $row->rd_fragment,
+                               $row->rd_interwiki
+                       );
                        unset( $this->mPendingRedirectIDs[$rdfrom] );
                        if ( !$to->isExternal() && !isset( $this->mAllPages[$row->rd_namespace][$row->rd_title] ) ) {
                                $lb->add( $row->rd_namespace, $row->rd_title );
@@ -886,6 +900,7 @@ class ApiPageSet extends ApiBase {
                                unset( $this->mPendingRedirectIDs[$id] );
                        }
                }
+
                return $lb;
        }
 
@@ -941,8 +956,9 @@ class ApiPageSet extends ApiBase {
                                // Variants checking
                                global $wgContLang;
                                if ( $this->mConvertTitles &&
-                                               count( $wgContLang->getVariants() ) > 1 &&
-                                               !$titleObj->exists() ) {
+                                       count( $wgContLang->getVariants() ) > 1 &&
+                                       !$titleObj->exists()
+                               ) {
                                        // Language::findVariantLink will modify titleText and titleObj into
                                        // the canonical variant if possible
                                        $titleText = is_string( $title ) ? $title : $titleObj->getPrefixedText();
@@ -1040,6 +1056,7 @@ class ApiPageSet extends ApiBase {
                                $result['generator'] = null;
                        }
                }
+
                return $result;
        }
 
@@ -1067,6 +1084,7 @@ class ApiPageSet extends ApiBase {
                        sort( $gens );
                        self::$generators = $gens;
                }
+
                return self::$generators;
        }
 
@@ -1075,19 +1093,34 @@ class ApiPageSet extends ApiBase {
                        'titles' => 'A list of titles to work on',
                        'pageids' => 'A list of page IDs to work on',
                        'revids' => 'A list of revision IDs to work on',
-                       'generator' => array( 'Get the list of pages to work on by executing the specified query module.',
-                               'NOTE: generator parameter names must be prefixed with a \'g\', see examples' ),
+                       'generator' => array(
+                               'Get the list of pages to work on by executing the specified query module.',
+                               'NOTE: generator parameter names must be prefixed with a \'g\', see examples'
+                       ),
                        'redirects' => 'Automatically resolve redirects',
-                       'converttitles' => array( 'Convert titles to other variants if necessary. Only works if the wiki\'s content language supports variant conversion.',
-                               'Languages that support variant conversion include ' . implode( ', ', LanguageConverter::$languagesWithVariants ) ),
+                       'converttitles' => array(
+                               'Convert titles to other variants if necessary. Only works if ' .
+                                       'the wiki\'s content language supports variant conversion.',
+                               'Languages that support variant conversion include ' .
+                                       implode( ', ', LanguageConverter::$languagesWithVariants )
+                       ),
                );
        }
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'multisource', 'info' => "Cannot use 'pageids' at the same time as 'dataSource'" ),
-                       array( 'code' => 'multisource', 'info' => "Cannot use 'revids' at the same time as 'dataSource'" ),
-                       array( 'code' => 'badgenerator', 'info' => 'Module $generatorName cannot be used as a generator' ),
+                       array(
+                               'code' => 'multisource',
+                               'info' => "Cannot use 'pageids' at the same time as 'dataSource'"
+                       ),
+                       array(
+                               'code' => 'multisource',
+                               'info' => "Cannot use 'revids' at the same time as 'dataSource'"
+                       ),
+                       array(
+                               'code' => 'badgenerator',
+                               'info' => 'Module $generatorName cannot be used as a generator'
+                       ),
                ) );
        }
 }
index 3e1a753..2b4710a 100644 (file)
@@ -226,7 +226,8 @@ class ApiParamInfo extends ApiBase {
                        if ( isset( $p[ApiBase::PARAM_TYPE] ) ) {
                                $a['type'] = $p[ApiBase::PARAM_TYPE];
                                if ( is_array( $a['type'] ) ) {
-                                       $a['type'] = array_values( $a['type'] ); // to prevent sparse arrays from being serialized to JSON as objects
+                                       // To prevent sparse arrays from being serialized to JSON as objects
+                                       $a['type'] = array_values( $a['type'] );
                                        $result->setIndexedTagName( $a['type'], 't' );
                                }
                        }
@@ -317,6 +318,7 @@ class ApiParamInfo extends ApiBase {
                sort( $querymodules );
                $formatmodules = $this->getMain()->getModuleManager()->getNames( 'format' );
                sort( $formatmodules );
+
                return array(
                        'modules' => array(
                                ApiBase::PARAM_ISMULTI => true,
@@ -340,7 +342,8 @@ class ApiParamInfo extends ApiBase {
                        'modules' => 'List of module names (value of the action= parameter)',
                        'querymodules' => 'List of query module names (value of prop=, meta= or list= parameter)',
                        'mainmodule' => 'Get information about the main (top-level) module as well',
-                       'pagesetmodule' => 'Get information about the pageset module (providing titles= and friends) as well',
+                       'pagesetmodule' => 'Get information about the pageset module ' .
+                               '(providing titles= and friends) as well',
                        'formatmodules' => 'List of format module names (value of format= parameter)',
                );
        }
index a369994..88904c0 100644 (file)
@@ -60,7 +60,10 @@ class ApiParse extends ApiBase {
                $format = $params['contentformat'];
 
                if ( !is_null( $page ) && ( !is_null( $text ) || $titleProvided ) ) {
-                       $this->dieUsage( 'The page parameter cannot be used together with the text and title parameters', 'params' );
+                       $this->dieUsage(
+                               'The page parameter cannot be used together with the text and title parameters',
+                               'params'
+                       );
                }
 
                $prop = array_flip( $params['prop'] );
@@ -76,9 +79,12 @@ class ApiParse extends ApiBase {
                // TODO: Does this still need $wgTitle?
                global $wgParser, $wgTitle;
 
-               // Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
+               // Currently unnecessary, code to act as a safeguard against any change
+               // in current behavior of uselang
                $oldLang = null;
-               if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
+               if ( isset( $params['uselang'] )
+                       && $params['uselang'] != $this->getContext()->getLanguage()->getCode()
+               ) {
                        $oldLang = $this->getContext()->getLanguage(); // Backup language
                        $this->getContext()->setLanguage( Language::factory( $params['uselang'] ) );
                }
@@ -125,7 +131,7 @@ class ApiParse extends ApiBase {
                                                'action' => 'query',
                                                'redirects' => '',
                                        );
-                                       if ( !is_null ( $pageid ) ) {
+                                       if ( !is_null( $pageid ) ) {
                                                $reqParams['pageids'] = $pageid;
                                        } else { // $page
                                                $reqParams['titles'] = $page;
@@ -219,6 +225,7 @@ class ApiParse extends ApiBase {
                                        ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
                                }
                                $result->addValue( null, $this->getModuleName(), $result_array );
+
                                return;
                        }
 
@@ -249,7 +256,10 @@ class ApiParse extends ApiBase {
 
                if ( !is_null( $params['summary'] ) ) {
                        $result_array['parsedsummary'] = array();
-                       ApiResult::setContent( $result_array['parsedsummary'], Linker::formatComment( $params['summary'], $titleObj ) );
+                       ApiResult::setContent(
+                               $result_array['parsedsummary'],
+                               Linker::formatComment( $params['summary'], $titleObj )
+                       );
                }
 
                if ( isset( $prop['langlinks'] ) || isset( $prop['languageshtml'] ) ) {
@@ -300,8 +310,8 @@ class ApiParse extends ApiBase {
 
                if ( isset( $prop['displaytitle'] ) ) {
                        $result_array['displaytitle'] = $p_result->getDisplayTitle() ?
-                                                       $p_result->getDisplayTitle() :
-                                                       $titleObj->getPrefixedText();
+                               $p_result->getDisplayTitle() :
+                               $titleObj->getPrefixedText();
                }
 
                if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) {
@@ -321,7 +331,10 @@ class ApiParse extends ApiBase {
 
                        if ( isset( $prop['headhtml'] ) ) {
                                $result_array['headhtml'] = array();
-                               ApiResult::setContent( $result_array['headhtml'], $context->getOutput()->headElement( $context->getSkin() ) );
+                               ApiResult::setContent(
+                                       $result_array['headhtml'],
+                                       $context->getOutput()->headElement( $context->getSkin() )
+                               );
                        }
                }
 
@@ -395,6 +408,7 @@ class ApiParse extends ApiBase {
                $popts->setIsSectionPreview( $params['sectionpreview'] );
 
                wfProfileOut( __METHOD__ );
+
                return $popts;
        }
 
@@ -411,22 +425,24 @@ class ApiParse extends ApiBase {
                if ( $this->section !== false && $this->content !== null ) {
                        $this->content = $this->getSectionContent(
                                $this->content,
-                               !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText() );
+                               !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText()
+                       );
 
                        // Not cached (save or load)
                        return $this->content->getParserOutput( $page->getTitle(), null, $popts );
-               } else {
-                       // Try the parser cache first
-                       // getParserOutput will save to Parser cache if able
-                       $pout = $page->getParserOutput( $popts );
-                       if ( !$pout ) {
-                               $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
-                       }
-                       if ( $getWikitext ) {
-                               $this->content = $page->getContent( Revision::RAW );
-                       }
-                       return $pout;
                }
+
+               // Try the parser cache first
+               // getParserOutput will save to Parser cache if able
+               $pout = $page->getParserOutput( $popts );
+               if ( !$pout ) {
+                       $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
+               }
+               if ( $getWikitext ) {
+                       $this->content = $page->getContent( Revision::RAW );
+               }
+
+               return $pout;
        }
 
        private function getSectionContent( Content $content, $what ) {
@@ -439,6 +455,7 @@ class ApiParse extends ApiBase {
                        $this->dieUsage( "Sections are not supported by " . $what, 'nosuchsection' );
                        $section = false;
                }
+
                return $section;
        }
 
@@ -456,34 +473,68 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $bits[1] );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
        private function formatCategoryLinks( $links ) {
                $result = array();
+
+               if ( !$links ) {
+                       return $result;
+               }
+
+               // Fetch hiddencat property
+               $lb = new LinkBatch;
+               $lb->setArray( array( NS_CATEGORY => $links ) );
+               $db = $this->getDB();
+               $res = $db->select( array( 'page', 'page_props' ),
+                       array( 'page_title', 'pp_propname' ),
+                       $lb->constructSet( 'page', $db ),
+                       __METHOD__,
+                       array(),
+                       array( 'page_props' => array(
+                               'LEFT JOIN', array( 'pp_propname' => 'hiddencat', 'pp_page = page_id' )
+                       ) )
+               );
+               $hiddencats = array();
+               foreach ( $res as $row ) {
+                       $hiddencats[$row->page_title] = isset( $row->pp_propname );
+               }
+
                foreach ( $links as $link => $sortkey ) {
                        $entry = array();
                        $entry['sortkey'] = $sortkey;
                        ApiResult::setContent( $entry, $link );
+                       if ( !isset( $hiddencats[$link] ) ) {
+                               $entry['missing'] = '';
+                       } elseif ( $hiddencats[$link] ) {
+                               $entry['hidden'] = '';
+                       }
                        $result[] = $entry;
                }
+
                return $result;
        }
 
        private function categoriesHtml( $categories ) {
                $context = $this->getContext();
                $context->getOutput()->addCategoryLinks( $categories );
+
                return $context->getSkin()->getCategories();
        }
 
        /**
-        * @deprecated since 1.18 No modern skin generates language links this way, please use language links
-        *                        data to generate your own HTML.
+        * @deprecated since 1.18 No modern skin generates language links this way,
+        * please use language links data to generate your own HTML.
         * @param $languages array
         * @return string
         */
        private function languagesHtml( $languages ) {
                wfDeprecated( __METHOD__, '1.18' );
+               $this->setWarning( '"action=parse&prop=languageshtml" is deprecated ' .
+                       'and will be removed in MediaWiki 1.24. Use "prop=langlinks" ' .
+                       'to generate your own HTML.' );
 
                global $wgContLang, $wgHideInterlanguageLinks;
 
@@ -491,7 +542,8 @@ class ApiParse extends ApiBase {
                        return '';
                }
 
-               $s = htmlspecialchars( wfMessage( 'otherlanguages' )->text() . wfMessage( 'colon-separator' )->text() );
+               $s = htmlspecialchars( wfMessage( 'otherlanguages' )->text() .
+                       wfMessage( 'colon-separator' )->text() );
 
                $langs = array();
                foreach ( $languages as $l ) {
@@ -525,6 +577,7 @@ class ApiParse extends ApiBase {
                                $result[] = $entry;
                        }
                }
+
                return $result;
        }
 
@@ -544,6 +597,7 @@ class ApiParse extends ApiBase {
                                $result[] = $entry;
                        }
                }
+
                return $result;
        }
 
@@ -555,6 +609,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $content );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -566,6 +621,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $value );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -577,6 +633,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $link );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -602,7 +659,8 @@ class ApiParse extends ApiBase {
                                ApiBase::PARAM_TYPE => 'integer',
                        ),
                        'prop' => array(
-                               ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|images|externallinks|sections|revid|displaytitle|iwlinks|properties',
+                               ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|' .
+                                       'images|externallinks|sections|revid|displaytitle|iwlinks|properties',
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_TYPE => array(
                                        'text',
@@ -645,6 +703,7 @@ class ApiParse extends ApiBase {
        public function getParamDescription() {
                $p = $this->getModulePrefix();
                $wikitext = CONTENT_MODEL_WIKITEXT;
+
                return array(
                        'text' => "Text to parse. Use {$p}title or {$p}contentmodel to control the content model",
                        'summary' => 'Summary to parse',
@@ -660,7 +719,8 @@ class ApiParse extends ApiBase {
                                ' langlinks      - Gives the language links in the parsed wikitext',
                                ' categories     - Gives the categories in the parsed wikitext',
                                ' categorieshtml - Gives the HTML version of the categories',
-                               ' languageshtml  - Gives the HTML version of the language links',
+                               ' languageshtml  - DEPRECATED. Will be removed in MediaWiki 1.24.',
+                               '                  Gives the HTML version of the language links',
                                ' links          - Gives the internal links in the parsed wikitext',
                                ' templates      - Gives the templates in the parsed wikitext',
                                ' images         - Gives the images in the parsed wikitext',
@@ -707,9 +767,11 @@ class ApiParse extends ApiBase {
 
        public function getDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'Parses content and returns parser output',
-                       'See the various prop-Modules of action=query to get information from the current version of a page',
+                       'See the various prop-Modules of action=query to get information from the current' .
+                               'version of a page',
                        'There are several ways to specify the text to parse:',
                        "1) Specify a page or revision, using {$p}page, {$p}pageid, or {$p}oldid.",
                        "2) Specify content explicitly, using {$p}text, {$p}title, and {$p}contentmodel.",
@@ -719,15 +781,24 @@ class ApiParse extends ApiBase {
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'params', 'info' => 'The page parameter cannot be used together with the text and title parameters' ),
+                       array(
+                               'code' => 'params',
+                               'info' => 'The page parameter cannot be used together with the text and title parameters'
+                       ),
                        array( 'code' => 'missingrev', 'info' => 'There is no revision ID oldid' ),
-                       array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view deleted revisions' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You don\'t have permission to view deleted revisions'
+                       ),
                        array( 'code' => 'missingtitle', 'info' => 'The page you specified doesn\'t exist' ),
                        array( 'code' => 'nosuchsection', 'info' => 'There is no section sectionnumber in page' ),
                        array( 'nosuchpageid' ),
                        array( 'invalidtitle', 'title' ),
                        array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
-                       array( 'code' => 'notwikitext', 'info' => 'The requested operation is only supported on wikitext content.' ),
+                       array(
+                               'code' => 'notwikitext',
+                               'info' => 'The requested operation is only supported on wikitext content.'
+                       ),
                        array( 'code' => 'pagecannotexist', 'info' => "Namespace doesn't allow actual pages" ),
                ) );
        }
@@ -736,7 +807,8 @@ class ApiParse extends ApiBase {
                return array(
                        'api.php?action=parse&page=Project:Sandbox' => 'Parse a page',
                        'api.php?action=parse&text={{Project:Sandbox}}' => 'Parse wikitext',
-                       'api.php?action=parse&text={{PAGENAME}}&title=Test' => 'Parse wikitext, specifying the page title',
+                       'api.php?action=parse&text={{PAGENAME}}&title=Test'
+                               => 'Parse wikitext, specifying the page title',
                        'api.php?action=parse&summary=Some+[[link]]&prop=' => 'Parse a summary',
                );
        }
index bd2fde2..46bd94e 100644 (file)
@@ -123,7 +123,8 @@ class ApiPatrol extends ApiBase {
                                        'code' => 'notpatrollable',
                                        'info' => "The revision can't be patrolled as it's too old"
                                )
-               ) );
+                       )
+               );
        }
 
        public function needsToken() {
index 7830c8b..80c76b3 100644 (file)
@@ -28,7 +28,6 @@
  * @ingroup API
  */
 class ApiProtect extends ApiBase {
-
        public function execute() {
                global $wgRestrictionLevels;
                $params = $this->extractRequestParams();
@@ -47,7 +46,11 @@ class ApiProtect extends ApiBase {
                        if ( count( $expiry ) == 1 ) {
                                $expiry = array_fill( 0, count( $params['protections'] ), $expiry[0] );
                        } else {
-                               $this->dieUsageMsg( array( 'toofewexpiries', count( $expiry ), count( $params['protections'] ) ) );
+                               $this->dieUsageMsg( array(
+                                       'toofewexpiries',
+                                       count( $expiry ),
+                                       count( $params['protections'] )
+                               ) );
                        }
                }
 
@@ -90,17 +93,23 @@ class ApiProtect extends ApiBase {
                                $expiryarray[$p[0]] = $exp;
                        }
                        $resultProtections[] = array( $p[0] => $protections[$p[0]],
-                                       'expiry' => ( $expiryarray[$p[0]] == $db->getInfinity() ?
-                                                               'infinite' :
-                                                               wfTimestamp( TS_ISO_8601, $expiryarray[$p[0]] ) ) );
+                               'expiry' => ( $expiryarray[$p[0]] == $db->getInfinity() ?
+                                       'infinite' :
+                                       wfTimestamp( TS_ISO_8601, $expiryarray[$p[0]] ) ) );
                }
 
                $cascade = $params['cascade'];
 
                $watch = $params['watch'] ? 'watch' : $params['watchlist'];
-               $this->setWatch( $watch, $titleObj );
-
-               $status = $pageObj->doUpdateRestrictions( $protections, $expiryarray, $cascade, $params['reason'], $this->getUser() );
+               $this->setWatch( $watch, $titleObj, 'watchdefault' );
+
+               $status = $pageObj->doUpdateRestrictions(
+                       $protections,
+                       $expiryarray,
+                       $cascade,
+                       $params['reason'],
+                       $this->getUser()
+               );
 
                if ( !$status->isOK() ) {
                        $this->dieStatus( $status );
@@ -167,18 +176,25 @@ class ApiProtect extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'title' => "Title of the page you want to (un)protect. Cannot be used together with {$p}pageid",
                        'pageid' => "ID of the page you want to (un)protect. Cannot be used together with {$p}title",
                        'token' => 'A protect token previously retrieved through prop=info',
                        'protections' => 'List of protection levels, formatted action=group (e.g. edit=sysop)',
-                       'expiry' => array( 'Expiry timestamps. If only one timestamp is set, it\'ll be used for all protections.',
-                                       'Use \'infinite\', \'indefinite\' or \'never\', for a never-expiring protection.' ),
+                       'expiry' => array(
+                               'Expiry timestamps. If only one timestamp is ' .
+                                       'set, it\'ll be used for all protections.',
+                               'Use \'infinite\', \'indefinite\' or \'never\', for a never-expiring protection.'
+                       ),
                        'reason' => 'Reason for (un)protecting',
-                       'cascade' => array( 'Enable cascading protection (i.e. protect pages included in this page)',
-                                       'Ignored if not all protection levels are \'sysop\' or \'protect\'' ),
+                       'cascade' => array(
+                               'Enable cascading protection (i.e. protect pages included in this page)',
+                               'Ignored if not all protection levels are \'sysop\' or \'protect\''
+                       ),
                        'watch' => 'If set, add the page being (un)protected to your watchlist',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'watchlist' => 'Unconditionally add or remove the page from your ' .
+                               'watchlist, use preferences or do not change watch',
                );
        }
 
@@ -221,8 +237,10 @@ class ApiProtect extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=sysop|move=sysop&cascade=&expiry=20070901163000|never',
-                       'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=all|move=all&reason=Lifting%20restrictions'
+                       'api.php?action=protect&title=Main%20Page&token=123ABC&' .
+                               'protections=edit=sysop|move=sysop&cascade=&expiry=20070901163000|never',
+                       'api.php?action=protect&title=Main%20Page&token=123ABC&' .
+                               'protections=edit=all|move=all&reason=Lifting%20restrictions'
                );
        }
 
index 0812ba5..c0dd808 100644 (file)
@@ -30,7 +30,6 @@
  * @ingroup API
  */
 class ApiPurge extends ApiBase {
-
        private $mPageSet;
 
        /**
@@ -91,7 +90,12 @@ class ApiPurge extends ApiBase {
 
                                        # Parse content; note that HTML generation is only needed if we want to cache the result.
                                        $content = $page->getContent( Revision::RAW );
-                                       $p_result = $content->getParserOutput( $title, $page->getLatest(), $popts, $wgEnableParserCache );
+                                       $p_result = $content->getParserOutput(
+                                               $title,
+                                               $page->getLatest(),
+                                               $popts,
+                                               $wgEnableParserCache
+                                       );
 
                                        # Update the links tables
                                        $updates = $content->getSecondaryDataUpdates(
@@ -139,6 +143,7 @@ class ApiPurge extends ApiBase {
                if ( !isset( $this->mPageSet ) ) {
                        $this->mPageSet = new ApiPageSet( $this );
                }
+
                return $this->mPageSet;
        }
 
@@ -159,6 +164,7 @@ class ApiPurge extends ApiBase {
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
                }
+
                return $result;
        }
 
index e03837f..cec1ca8 100644 (file)
@@ -163,6 +163,7 @@ class ApiQuery extends ApiBase {
                        $this->mNamedDB[$name] = wfGetDB( $db, $groups );
                        $this->profileDBOut();
                }
+
                return $this->mNamedDB[$name];
        }
 
@@ -181,6 +182,7 @@ class ApiQuery extends ApiBase {
         */
        public function getModules() {
                wfDeprecated( __METHOD__, '1.21' );
+
                return $this->getModuleManager()->getNamesWithClasses();
        }
 
@@ -197,6 +199,7 @@ class ApiQuery extends ApiBase {
                                $gens[$name] = $class;
                        }
                }
+
                return $gens;
        }
 
@@ -216,8 +219,8 @@ class ApiQuery extends ApiBase {
        public function getCustomPrinter() {
                // If &exportnowrap is set, use the raw formatter
                if ( $this->getParameter( 'export' ) &&
-                               $this->getParameter( 'exportnowrap' ) )
-               {
+                       $this->getParameter( 'exportnowrap' )
+               {
                        return new ApiFormatRaw( $this->getMain(),
                                $this->getMain()->createPrinterByName( 'xml' ) );
                } else {
@@ -407,6 +410,7 @@ class ApiQuery extends ApiBase {
                        }
                }
                $this->dieContinueUsageIf( $completeModules !== null && count( $tmp ) !== 0 );
+
                return $modules;
        }
 
@@ -429,6 +433,7 @@ class ApiQuery extends ApiBase {
                } else { // private
                        $cacheMode = 'private';
                }
+
                return $cacheMode;
        }
 
@@ -514,10 +519,12 @@ class ApiQuery extends ApiBase {
                        ApiQueryBase::addTitleInfo( $vals, $title );
                        $vals['special'] = '';
                        if ( $title->isSpecialPage() &&
-                                       !SpecialPageFactory::exists( $title->getDBkey() ) ) {
+                               !SpecialPageFactory::exists( $title->getDBkey() )
+                       ) {
                                $vals['missing'] = '';
                        } elseif ( $title->getNamespace() == NS_MEDIA &&
-                                       !wfFindFile( $title ) ) {
+                               !wfFindFile( $title )
+                       ) {
                                $vals['missing'] = '';
                        }
                        $pages[$fakeId] = $vals;
@@ -566,6 +573,7 @@ class ApiQuery extends ApiBase {
                        $this->mGeneratorContinue = array();
                }
                $this->mGeneratorContinue[$paramName] = $paramValue;
+
                return true;
        }
 
@@ -638,6 +646,7 @@ class ApiQuery extends ApiBase {
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
                }
+
                return $result;
        }
 
@@ -699,25 +708,32 @@ class ApiQuery extends ApiBase {
 
        public function getParamDescription() {
                return $this->getPageSet()->getFinalParamDescription() + array(
-                       'prop' => 'Which properties to get for the titles/revisions/pageids. Module help is available below',
+                       'prop' => 'Which properties to get for the titles/revisions/pageids. ' .
+                               'Module help is available below',
                        'list' => 'Which lists to get. Module help is available below',
                        'meta' => 'Which metadata to get about the site. Module help is available below',
                        'indexpageids' => 'Include an additional pageids section listing all returned page IDs',
                        'export' => 'Export the current revisions of all given or generated pages',
-                       'exportnowrap' => 'Return the export XML without wrapping it in an XML result (same format as Special:Export). Can only be used with export',
+                       'exportnowrap' => 'Return the export XML without wrapping it in an ' .
+                               'XML result (same format as Special:Export). Can only be used with export',
                        'iwurl' => 'Whether to get the full URL if the title is an interwiki link',
                        'continue' => array(
-                               'When present, formats query-continue as key-value pairs that should simply be merged into the original request.',
+                               'When present, formats query-continue as key-value pairs that ' .
+                                       'should simply be merged into the original request.',
                                'This parameter must be set to an empty string in the initial query.',
-                               'This parameter is recommended for all new development, and will be made default in the next API version.' ),
+                               'This parameter is recommended for all new development, and ' .
+                                       'will be made default in the next API version.'
+                       ),
                );
        }
 
        public function getDescription() {
                return array(
-                       'Query API module allows applications to get needed pieces of data from the MediaWiki databases,',
+                       'Query API module allows applications to get needed pieces of data ' .
+                               'from the MediaWiki databases,',
                        'and is loosely based on the old query.php interface.',
-                       'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites'
+                       'All data modifications will first have to use query to acquire a ' .
+                               'token to prevent abuse from malicious sites'
                );
        }
 
@@ -730,7 +746,8 @@ class ApiQuery extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=revisions&meta=siteinfo&titles=Main%20Page&rvprop=user|comment&continue=',
+                       'api.php?action=query&prop=revisions&meta=siteinfo&' .
+                               'titles=Main%20Page&rvprop=user|comment&continue=',
                        'api.php?action=query&generator=allpages&gapprefix=API/&prop=revisions&continue=',
                );
        }
index 3f5c6ee..d0ab59e 100644 (file)
@@ -80,7 +80,8 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
                }
 
                if ( isset( $params['prefix'] ) ) {
-                       $this->addWhere( 'cat_title' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                       $this->addWhere( 'cat_title' .
+                               $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                }
 
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
@@ -109,8 +110,9 @@ class ApiQueryAllCategories extends ApiQueryGeneratorBase {
                $result = $this->getResult();
                $count = 0;
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional cats to be had. Stop here...
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional cats to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->cat_title );
                                break;
                        }
index ccc7a3a..9f97cac 100644 (file)
@@ -32,7 +32,6 @@
  * @ingroup API
  */
 class ApiQueryAllImages extends ApiQueryGeneratorBase {
-
        protected $mRepo;
 
        public function __construct( $query, $moduleName ) {
@@ -65,7 +64,11 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
         */
        public function executeGenerator( $resultPageSet ) {
                if ( $resultPageSet->isResolvingRedirects() ) {
-                       $this->dieUsage( 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator', 'params' );
+                       $this->dieUsage(
+                               'Use "gaifilterredir=nonredirects" option instead of "redirects" ' .
+                                       'when using allimages as a generator',
+                               'params'
+                       );
                }
 
                $this->run( $resultPageSet );
@@ -78,7 +81,10 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
        private function run( $resultPageSet = null ) {
                $repo = $this->mRepo;
                if ( !$repo instanceof LocalRepo ) {
-                       $this->dieUsage( 'Local file repository does not support querying all images', 'unsupportedrepo' );
+                       $this->dieUsage(
+                               'Local file repository does not support querying all images',
+                               'unsupportedrepo'
+                       );
                }
 
                $prefix = $this->getModulePrefix();
@@ -103,11 +109,17 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                        $disallowed = array( 'start', 'end', 'user' );
                        foreach ( $disallowed as $pname ) {
                                if ( isset( $params[$pname] ) ) {
-                                       $this->dieUsage( "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=timestamp", 'badparams' );
+                                       $this->dieUsage(
+                                               "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=timestamp",
+                                               'badparams'
+                                       );
                                }
                        }
                        if ( $params['filterbots'] != 'all' ) {
-                                       $this->dieUsage( "Parameter '{$prefix}filterbots' can only be used with {$prefix}sort=timestamp", 'badparams' );
+                               $this->dieUsage(
+                                       "Parameter '{$prefix}filterbots' can only be used with {$prefix}sort=timestamp",
+                                       'badparams'
+                               );
                        }
 
                        // Pagination
@@ -125,23 +137,36 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                        $this->addWhereRange( 'img_name', ( $ascendingOrder ? 'newer' : 'older' ), $from, $to );
 
                        if ( isset( $params['prefix'] ) ) {
-                               $this->addWhere( 'img_name' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                               $this->addWhere( 'img_name' .
+                                       $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                        }
                } else {
                        // Check mutually exclusive params
                        $disallowed = array( 'from', 'to', 'prefix' );
                        foreach ( $disallowed as $pname ) {
                                if ( isset( $params[$pname] ) ) {
-                                       $this->dieUsage( "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=name", 'badparams' );
+                                       $this->dieUsage(
+                                               "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=name",
+                                               'badparams'
+                                       );
                                }
                        }
                        if ( !is_null( $params['user'] ) && $params['filterbots'] != 'all' ) {
-                               // Since filterbots checks if each user has the bot right, it doesn't make sense to use it with user
-                               $this->dieUsage( "Parameters '{$prefix}user' and '{$prefix}filterbots' cannot be used together", 'badparams' );
+                               // Since filterbots checks if each user has the bot right, it
+                               // doesn't make sense to use it with user
+                               $this->dieUsage(
+                                       "Parameters '{$prefix}user' and '{$prefix}filterbots' cannot be used together",
+                                       'badparams'
+                               );
                        }
 
                        // Pagination
-                       $this->addTimestampWhereRange( 'img_timestamp', ( $ascendingOrder ? 'newer' : 'older' ), $params['start'], $params['end'] );
+                       $this->addTimestampWhereRange(
+                               'img_timestamp',
+                               $ascendingOrder ? 'newer' : 'older',
+                               $params['start'],
+                               $params['end']
+                       );
 
                        // Image filters
                        if ( !is_null( $params['user'] ) ) {
@@ -156,7 +181,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                                                'ug_user = img_user'
                                        )
                                ) ) );
-                               $groupCond = ( $params['filterbots'] == 'nobots' ? 'NULL': 'NOT NULL' );
+                               $groupCond = ( $params['filterbots'] == 'nobots' ? 'NULL' : 'NOT NULL' );
                                $this->addWhere( "ug_group IS $groupCond" );
                        }
                }
@@ -222,8 +247,9 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                $count = 0;
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                if ( $params['sort'] == 'name' ) {
                                        $this->setContinueEnumParameter( 'continue', $row->img_name );
                                } else {
@@ -326,6 +352,7 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'sort' => 'Property to sort by',
                        'dir' => 'The direction in which to list',
@@ -335,13 +362,16 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                        'start' => "The timestamp to start enumerating from. Can only be used with {$p}sort=timestamp",
                        'end' => "The timestamp to end enumerating. Can only be used with {$p}sort=timestamp",
                        'prop' => ApiQueryImageInfo::getPropertyDescriptions( $this->propertyFilter ),
-                       'prefix' => "Search for all image titles that begin with this value. Can only be used with {$p}sort=name",
+                       'prefix' => "Search for all image titles that begin with this " .
+                               "value. Can only be used with {$p}sort=name",
                        'minsize' => 'Limit to images with at least this many bytes',
                        'maxsize' => 'Limit to images with at most this many bytes',
                        'sha1' => "SHA1 hash of image. Overrides {$p}sha1base36",
                        'sha1base36' => 'SHA1 hash of image in base 36 (used in MediaWiki)',
-                       'user' => "Only return files uploaded by this user. Can only be used with {$p}sort=timestamp. Cannot be used together with {$p}filterbots",
-                       'filterbots' => "How to filter files uploaded by bots. Can only be used with {$p}sort=timestamp. Cannot be used together with {$p}user",
+                       'user' => "Only return files uploaded by this user. Can only be used " .
+                               "with {$p}sort=timestamp. Cannot be used together with {$p}filterbots",
+                       'filterbots' => "How to filter files uploaded by bots. Can only be " .
+                               "used with {$p}sort=timestamp. Cannot be used together with {$p}user",
                        'mime' => 'What MIME type to search for. e.g. image/jpeg. Disabled in Miser Mode',
                        'limit' => 'How many images in total to return',
                );
@@ -368,20 +398,54 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
 
        public function getPossibleErrors() {
                $p = $this->getModulePrefix();
+
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'params', 'info' => 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator' ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}start' can only be used with {$p}sort=timestamp" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}end' can only be used with {$p}sort=timestamp" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}user' can only be used with {$p}sort=timestamp" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}filterbots' can only be used with {$p}sort=timestamp" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}from' can only be used with {$p}sort=name" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}to' can only be used with {$p}sort=name" ),
-                       array( 'code' => 'badparams', 'info' => "Parameter'{$p}prefix' can only be used with {$p}sort=name" ),
-                       array( 'code' => 'badparams', 'info' => "Parameters '{$p}user' and '{$p}filterbots' cannot be used together" ),
-                       array( 'code' => 'unsupportedrepo', 'info' => 'Local file repository does not support querying all images' ),
+                       array(
+                               'code' => 'params',
+                               'info' => 'Use "gaifilterredir=nonredirects" option instead ' .
+                                       'of "redirects" when using allimages as a generator'
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}start' can only be used with {$p}sort=timestamp"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}end' can only be used with {$p}sort=timestamp"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}user' can only be used with {$p}sort=timestamp"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}filterbots' can only be used with {$p}sort=timestamp"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}from' can only be used with {$p}sort=name"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}to' can only be used with {$p}sort=name"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameter'{$p}prefix' can only be used with {$p}sort=name"
+                       ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "Parameters '{$p}user' and '{$p}filterbots' cannot be used together"
+                       ),
+                       array(
+                               'code' => 'unsupportedrepo',
+                               'info' => 'Local file repository does not support querying all images' ),
                        array( 'code' => 'mimesearchdisabled', 'info' => 'MIME search disabled in Miser Mode' ),
                        array( 'code' => 'invalidsha1hash', 'info' => 'The SHA1 hash provided is not valid' ),
-                       array( 'code' => 'invalidsha1base36hash', 'info' => 'The SHA1Base36 hash provided is not valid' ),
+                       array(
+                               'code' => 'invalidsha1base36hash',
+                               'info' => 'The SHA1Base36 hash provided is not valid'
+                       ),
                ) );
        }
 
@@ -391,11 +455,13 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase {
                                'Simple Use',
                                'Show a list of files starting at the letter "B"',
                        ),
-                       'api.php?action=query&list=allimages&aiprop=user|timestamp|url&aisort=timestamp&aidir=older' => array(
+                       'api.php?action=query&list=allimages&aiprop=user|timestamp|url&' .
+                               'aisort=timestamp&aidir=older' => array(
                                'Simple Use',
                                'Show a list of recently uploaded files similar to Special:NewFiles',
                        ),
-                       'api.php?action=query&generator=allimages&gailimit=4&gaifrom=T&prop=imageinfo' => array(
+                       'api.php?action=query&generator=allimages&gailimit=4&' .
+                               'gaifrom=T&prop=imageinfo' => array(
                                'Using as Generator',
                                'Show info about 4 files starting at the letter "T"',
                        ),
index 47d1bce..ff53d0f 100644 (file)
@@ -54,7 +54,8 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                                $this->dfltNamespace = NS_TEMPLATE;
                                $this->hasNamespace = true;
                                $this->indexTag = 't';
-                               $this->description = 'List all transclusions (pages embedded using {{x}}), including non-existing';
+                               $this->description =
+                                       'List all transclusions (pages embedded using {{x}}), including non-existing';
                                $this->descriptionWhat = 'transclusion';
                                $this->descriptionTargets = 'transcluded titles';
                                $this->descriptionLinking = 'transcluding';
@@ -113,8 +114,10 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                if ( $params['unique'] ) {
                        if ( $fld_ids ) {
                                $this->dieUsage(
-                                       "{$this->getModuleName()} cannot return corresponding page ids in unique {$this->descriptionWhat}s mode",
-                                       'params' );
+                                       "{$this->getModuleName()} cannot return corresponding page " .
+                                               "ids in unique {$this->descriptionWhat}s mode",
+                                       'params'
+                               );
                        }
                        $this->addOption( 'DISTINCT' );
                }
@@ -145,12 +148,15 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                }
 
                // 'continue' always overrides 'from'
-               $from = ( $continue || is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) );
+               $from = $continue || is_null( $params['from'] )
+                       ? null
+                       : $this->titlePartToKey( $params['from'] );
                $to = ( is_null( $params['to'] ) ? null : $this->titlePartToKey( $params['to'] ) );
                $this->addWhereRange( $pfx . $fieldTitle, 'newer', $from, $to );
 
                if ( isset( $params['prefix'] ) ) {
-                       $this->addWhere( $pfx . $fieldTitle . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                       $this->addWhere( $pfx . $fieldTitle .
+                               $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                }
 
                $this->addFields( array( 'pl_title' => $pfx . $fieldTitle ) );
@@ -177,8 +183,9 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                $count = 0;
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                if ( $params['unique'] ) {
                                        $this->setContinueEnumParameter( 'continue', $row->pl_title );
                                } else {
@@ -258,6 +265,7 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                if ( !$this->hasNamespace ) {
                        unset( $allowedParams['namespace'] );
                }
+
                return $allowedParams;
        }
 
@@ -287,6 +295,7 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                if ( !$this->hasNamespace ) {
                        unset( $paramDescription['namespace'] );
                }
+
                return $paramDescription;
        }
 
@@ -309,8 +318,12 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
        public function getPossibleErrors() {
                $m = $this->getModuleName();
                $what = $this->descriptionWhat;
+
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'params', 'info' => "{$m} cannot return corresponding page ids in unique {$what}s mode" ),
+                       array(
+                               'code' => 'params',
+                               'info' => "{$m} cannot return corresponding page ids in unique {$what}s mode"
+                       ),
                ) );
        }
 
@@ -319,20 +332,22 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                $name = $this->getModuleName();
                $what = $this->descriptionWhat;
                $targets = $this->descriptionTargets;
+
                return array(
                        "api.php?action=query&list={$name}&{$p}from=B&{$p}prop=ids|title"
-                                       => "List $targets with page ids they are from, including missing ones. Start at B",
+                               => "List $targets with page ids they are from, including missing ones. Start at B",
                        "api.php?action=query&list={$name}&{$p}unique=&{$p}from=B"
-                                       => "List unique $targets",
+                               => "List unique $targets",
                        "api.php?action=query&generator={$name}&g{$p}unique=&g{$p}from=B"
-                                       => "Gets all $targets, marking the missing ones",
+                               => "Gets all $targets, marking the missing ones",
                        "api.php?action=query&generator={$name}&g{$p}from=B"
-                                       => "Gets pages containing the {$what}s",
+                               => "Gets pages containing the {$what}s",
                );
        }
 
        public function getHelpUrls() {
                $name = ucfirst( $this->getModuleName() );
+
                return "https://www.mediawiki.org/wiki/API:{$name}";
        }
 }
index d47c7b7..6b1d5a2 100644 (file)
@@ -241,10 +241,10 @@ class ApiQueryAllMessages extends ApiQueryBase {
                        'messages' => 'Which messages to output. "*" (default) means all messages',
                        'prop' => 'Which properties to get',
                        'enableparser' => array( 'Set to enable parser, will preprocess the wikitext of message',
-                                                       'Will substitute magic words, handle templates etc.' ),
+                               'Will substitute magic words, handle templates etc.' ),
                        'nocontent' => 'If set, do not include the content of the messages in the output.',
                        'includelocal' => array( "Also include local messages, i.e. messages that don't exist in the software but do exist as a MediaWiki: page.",
-                                                       "This lists all MediaWiki: pages, so it will also list those that aren't 'really' messages such as Common.js",
+                               "This lists all MediaWiki: pages, so it will also list those that aren't 'really' messages such as Common.js",
                        ),
                        'title' => 'Page name to use as context when parsing message (for enableparser option)',
                        'args' => 'Arguments to be substituted into message',
index d95980c..363d657 100644 (file)
@@ -49,7 +49,11 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
         */
        public function executeGenerator( $resultPageSet ) {
                if ( $resultPageSet->isResolvingRedirects() ) {
-                       $this->dieUsage( 'Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params' );
+                       $this->dieUsage(
+                               'Use "gapfilterredir=nonredirects" option instead of "redirects" ' .
+                                       'when using allpages as a generator',
+                               'params'
+                       );
                }
 
                $this->run( $resultPageSet );
@@ -88,7 +92,8 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                $this->addWhereRange( 'page_title', $dir, $from, $to );
 
                if ( isset( $params['prefix'] ) ) {
-                       $this->addWhere( 'page_title' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                       $this->addWhere( 'page_title' .
+                               $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                }
 
                if ( is_null( $resultPageSet ) ) {
@@ -145,7 +150,6 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                        }
 
                        $this->addOption( 'DISTINCT' );
-
                } elseif ( isset( $params['prlevel'] ) ) {
                        $this->dieUsage( 'prlevel may not be used without prtype', 'params' );
                }
@@ -186,8 +190,9 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                $count = 0;
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->page_title );
                                break;
                        }
@@ -291,6 +296,7 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'from' => 'The page title to start enumerating from',
                        'continue' => 'When more results are available, use this to continue',
@@ -303,7 +309,8 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                        'maxsize' => 'Limit to pages with at most this many bytes',
                        'prtype' => 'Limit to protected pages only',
                        'prlevel' => "The protection level (must be used with {$p}prtype= parameter)",
-                       'prfiltercascade' => "Filter protections based on cascadingness (ignored when {$p}prtype isn't set)",
+                       'prfiltercascade'
+                               => "Filter protections based on cascadingness (ignored when {$p}prtype isn't set)",
                        'filterlanglinks' => array(
                                'Filter based on whether a page has langlinks',
                                'Note that this may not consider langlinks added by extensions.',
@@ -334,7 +341,11 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'params', 'info' => 'Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator' ),
+                       array(
+                               'code' => 'params',
+                               'info' => 'Use "gapfilterredir=nonredirects" option instead of ' .
+                                       '"redirects" when using allpages as a generator'
+                       ),
                        array( 'code' => 'params', 'info' => 'prlevel may not be used without prtype' ),
                ) );
        }
@@ -349,9 +360,9 @@ class ApiQueryAllPages extends ApiQueryGeneratorBase {
                                'Using as Generator',
                                'Show info about 4 pages starting at the letter "T"',
                        ),
-                       'api.php?action=query&generator=allpages&gaplimit=2&gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content' => array(
-                               'Show content of first 2 non-redirect pages beginning at "Re"',
-                       )
+                       'api.php?action=query&generator=allpages&gaplimit=2&' .
+                               'gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content'
+                               => array( 'Show content of first 2 non-redirect pages beginning at "Re"' )
                );
        }
 
index 1948a51..748dbaf 100644 (file)
@@ -58,7 +58,8 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        $fld_registration = isset( $prop['registration'] );
                        $fld_implicitgroups = isset( $prop['implicitgroups'] );
                } else {
-                       $fld_blockinfo = $fld_editcount = $fld_groups = $fld_registration = $fld_rights = $fld_implicitgroups = false;
+                       $fld_blockinfo = $fld_editcount = $fld_groups = $fld_registration =
+                               $fld_rights = $fld_implicitgroups = false;
                }
 
                $limit = $params['limit'];
@@ -90,6 +91,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        // no group with the given right(s) exists, no need for a query
                        if ( !count( $groups ) ) {
                                $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), '' );
+
                                return;
                        }
 
@@ -111,7 +113,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        // Filter only users that belong to a given group
                        $this->addTables( 'user_groups', 'ug1' );
                        $this->addJoinConds( array( 'ug1' => array( 'INNER JOIN', array( 'ug1.ug_user=user_id',
-                                       'ug1.ug_group' => $params['group'] ) ) ) );
+                               'ug1.ug_group' => $params['group'] ) ) ) );
                }
 
                if ( !is_null( $params['excludegroup'] ) && count( $params['excludegroup'] ) ) {
@@ -122,12 +124,14 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        if ( count( $params['excludegroup'] ) == 1 ) {
                                $exclude = array( 'ug1.ug_group' => $params['excludegroup'][0] );
                        } else {
-                               $exclude = array( $db->makeList( array( 'ug1.ug_group' => $params['excludegroup'] ), LIST_OR ) );
+                               $exclude = array( $db->makeList(
+                                       array( 'ug1.ug_group' => $params['excludegroup'] ),
+                                       LIST_OR
+                               ) );
                        }
                        $this->addJoinConds( array( 'ug1' => array( 'LEFT OUTER JOIN',
                                array_merge( array( 'ug1.ug_user=user_id' ), $exclude )
-                               )
-                       ) );
+                       ) ) );
                        $this->addWhere( 'ug1.ug_user IS NULL' );
                }
 
@@ -187,12 +191,12 @@ class ApiQueryAllUsers extends ApiQueryBase {
                $lastUser = false;
                $result = $this->getResult();
 
-               //
-               // This loop keeps track of the last entry.
-               // For each new row, if the new row is for different user then the last, the last entry is added to results.
-               // Otherwise, the group of the new row is appended to the last entry.
-               // The setContinue... is more complex because of this, and takes into account the higher sql limit
-               // to make sure all rows that belong to the same user are received.
+               // This loop keeps track of the last entry. For each new row, if the
+               // new row is for different user then the last, the last entry is added
+               // to results. Otherwise, the group of the new row is appended to the
+               // last entry. The setContinue... is more complex because of this, and
+               // takes into account the higher sql limit to make sure all rows that
+               // belong to the same user are received.
 
                foreach ( $res as $row ) {
                        $count++;
@@ -201,7 +205,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                                // Save the last pass's user data
                                if ( is_array( $lastUserData ) ) {
                                        $fit = $result->addValue( array( 'query', $this->getModuleName() ),
-                                                       null, $lastUserData );
+                                               null, $lastUserData );
 
                                        $lastUserData = null;
 
@@ -212,7 +216,8 @@ class ApiQueryAllUsers extends ApiQueryBase {
                                }
 
                                if ( $count > $limit ) {
-                                       // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                                       // We've reached the one extra which shows that there are
+                                       // additional pages to be had. Stop here...
                                        $this->setContinueEnumParameter( 'from', $row->user_name );
                                        break;
                                }
@@ -246,10 +251,13 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        }
 
                        if ( $sqlLimit == $count ) {
-                               // BUG!  database contains group name that User::getAllGroups() does not return
-                               // TODO: should handle this more gracefully
-                               ApiBase::dieDebug( __METHOD__,
-                                       'MediaWiki configuration error: the database contains more user groups than known to User::getAllGroups() function' );
+                               // @todo BUG!  database contains group name that User::getAllGroups() does not return
+                               // Should handle this more gracefully
+                               ApiBase::dieDebug(
+                                       __METHOD__,
+                                       'MediaWiki configuration error: The database contains more ' .
+                                               'user groups than known to User::getAllGroups() function'
+                               );
                        }
 
                        $lastUserObj = User::newFromId( $row->user_id );
@@ -312,6 +320,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
        public function getAllowedParams() {
                $userGroups = User::getAllGroups();
+
                return array(
                        'from' => null,
                        'to' => null,
@@ -360,6 +369,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
        public function getParamDescription() {
                global $wgActiveUserDays;
+
                return array(
                        'from' => 'The user name to start enumerating from',
                        'to' => 'The user name to stop enumerating at',
@@ -367,16 +377,18 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        'dir' => 'Direction to sort in',
                        'group' => 'Limit users to given group name(s)',
                        'excludegroup' => 'Exclude users in given group name(s)',
-                       'rights' => 'Limit users to given right(s) (does not include rights granted by implicit or auto-promoted groups like *, user, or autoconfirmed)',
+                       'rights' => 'Limit users to given right(s) (does not include rights ' .
+                               'granted by implicit or auto-promoted groups like *, user, or autoconfirmed)',
                        'prop' => array(
                                'What pieces of information to include.',
                                ' blockinfo      - Adds the information about a current block on the user',
-                               ' groups         - Lists groups that the user is in. This uses more server resources and may return fewer results than the limit',
+                               ' groups         - Lists groups that the user is in. This uses ' .
+                                       'more server resources and may return fewer results than the limit',
                                ' implicitgroups - Lists all the groups the user is automatically in',
                                ' rights         - Lists rights that the user has',
                                ' editcount      - Adds the edit count of the user',
                                ' registration   - Adds the timestamp of when the user registered if available (may be blank)',
-                               ),
+                       ),
                        'limit' => 'How many total user names to return',
                        'witheditsonly' => 'Only list users who have made edits',
                        'activeusers' => "Only list users active in the last {$wgActiveUserDays} days(s)"
@@ -431,7 +443,10 @@ class ApiQueryAllUsers extends ApiQueryBase {
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'group-excludegroup', 'info' => 'group and excludegroup cannot be used together' ),
+                       array(
+                               'code' => 'group-excludegroup',
+                               'info' => 'group and excludegroup cannot be used together'
+                       ),
                ) );
        }
 
index 2d1089a..bda1e03 100644 (file)
@@ -149,7 +149,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                if ( $this->params['filterredir'] == 'redirects' ) {
                        $this->addWhereFld( 'page_is_redirect', 1 );
                } elseif ( $this->params['filterredir'] == 'nonredirects' && !$this->redirect ) {
-                       // bug 22245 - Check for !redirect, as filtering nonredirects, when getting what links to them is contradictory
+                       // bug 22245 - Check for !redirect, as filtering nonredirects, when
+                       // getting what links to them is contradictory
                        $this->addWhereFld( 'page_is_redirect', 0 );
                }
 
@@ -193,7 +194,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        $redirNs = $t->getNamespace();
                        $redirDBkey = $t->getDBkey();
                        $titleWhere[] = "{$this->bl_title} = " . $db->addQuotes( $redirDBkey ) .
-                                       ( $this->hasNS ? " AND {$this->bl_ns} = {$redirNs}" : '' );
+                               ( $this->hasNS ? " AND {$this->bl_ns} = {$redirNs}" : '' );
                        $allRedirNs[] = $redirNs;
                        $allRedirDBkey[] = $redirDBkey;
                }
@@ -209,14 +210,14 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        $from = $this->redirID;
                        if ( $this->hasNS ) {
                                $this->addWhere( "{$this->bl_ns} $op $ns OR " .
-                                               "({$this->bl_ns} = $ns AND " .
-                                               "({$this->bl_title} $op $title OR " .
-                                               "({$this->bl_title} = $title AND " .
-                                               "{$this->bl_from} $op= $from)))" );
+                                       "({$this->bl_ns} = $ns AND " .
+                                       "({$this->bl_title} $op $title OR " .
+                                       "({$this->bl_title} = $title AND " .
+                                       "{$this->bl_from} $op= $from)))" );
                        } else {
                                $this->addWhere( "{$this->bl_title} $op $title OR " .
-                                               "({$this->bl_title} = $title AND " .
-                                               "{$this->bl_from} $op= $from)" );
+                                       "({$this->bl_title} = $title AND " .
+                                       "{$this->bl_from} $op= $from)" );
                        }
                }
                if ( $this->params['filterredir'] == 'redirects' ) {
@@ -268,8 +269,9 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                $count = 0;
 
                foreach ( $res as $row ) {
-                       if ( ++ $count > $this->params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $this->params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                // Continue string preserved in case the redirect query doesn't pass the limit
                                $this->continueStr = $this->getContinueStr( $row->page_id );
                                break;
@@ -294,7 +296,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        $count = 0;
                        foreach ( $res as $row ) {
                                if ( ++$count > $this->params['limit'] ) {
-                                       // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                                       // We've reached the one extra which shows that there are
+                                       // additional pages to be had. Stop here...
                                        // We need to keep the parent page of this redir in
                                        if ( $this->hasNS ) {
                                                $parentID = $this->pageMap[$row->{$this->bl_ns}][$row->{$this->bl_title}];
@@ -384,7 +387,10 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                $parentID = $this->pageMap[$ns][$row->{$this->bl_title}];
                // Put all the results in an array first
                $this->resultArr[$parentID]['redirlinks'][] = $a;
-               $this->getResult()->setIndexedTagName( $this->resultArr[$parentID]['redirlinks'], $this->bl_code );
+               $this->getResult()->setIndexedTagName(
+                       $this->resultArr[$parentID]['redirlinks'],
+                       $this->bl_code
+               );
        }
 
        protected function processContinue() {
@@ -396,7 +402,10 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
 
                // only image titles are allowed for the root in imageinfo mode
                if ( !$this->hasNS && $this->rootTitle->getNamespace() !== NS_FILE ) {
-                       $this->dieUsage( "The title for {$this->getModuleName()} query must be an image", 'bad_image_title' );
+                       $this->dieUsage(
+                               "The title for {$this->getModuleName()} query must be an image",
+                               'bad_image_title'
+                       );
                }
        }
 
@@ -428,7 +437,6 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        return;
                }
                $this->redirID = $redirID;
-
        }
 
        protected function getContinueStr( $lastPageID ) {
@@ -481,6 +489,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        return $retval;
                }
                $retval['redirect'] = false;
+
                return $retval;
        }
 
@@ -494,11 +503,17 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                );
                if ( $this->getModuleName() != 'embeddedin' ) {
                        return array_merge( $retval, array(
-                               'redirect' => 'If linking page is a redirect, find all pages that link to that redirect as well. Maximum limit is halved.',
-                               'filterredir' => "How to filter for redirects. If set to nonredirects when {$this->bl_code}redirect is enabled, this is only applied to the second level",
-                               'limit' => "How many total pages to return. If {$this->bl_code}redirect is enabled, limit applies to each level separately (which means you may get up to 2 * limit results)."
+                               'redirect' => 'If linking page is a redirect, find all pages ' .
+                                       'that link to that redirect as well. Maximum limit is halved.',
+                               'filterredir' => 'How to filter for redirects. If set to ' .
+                                       "nonredirects when {$this->bl_code}redirect is enabled, " .
+                                       'this is only applied to the second level',
+                               'limit' => 'How many total pages to return. If ' .
+                                       "{$this->bl_code}redirect is enabled, limit applies to each " .
+                                       'level separately (which means you may get up to 2 * limit results).'
                        ) );
                }
+
                return array_merge( $retval, array(
                        'filterredir' => 'How to filter for redirects',
                        'limit' => 'How many total pages to return'
@@ -533,7 +548,10 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                return array_merge( parent::getPossibleErrors(),
                        $this->getTitleOrPageIdErrorMessage(),
                        array(
-                               array( 'code' => 'bad_image_title', 'info' => "The title for {$this->getModuleName()} query must be an image" ),
+                               array(
+                                       'code' => 'bad_image_title',
+                                       'info' => "The title for {$this->getModuleName()} query must be an image"
+                               ),
                        )
                );
        }
index 8668e04..fcd3180 100644 (file)
@@ -131,8 +131,10 @@ abstract class ApiQueryBase extends ApiBase {
        protected function addFieldsIf( $value, $condition ) {
                if ( $condition ) {
                        $this->addFields( $value );
+
                        return true;
                }
+
                return false;
        }
 
@@ -168,8 +170,10 @@ abstract class ApiQueryBase extends ApiBase {
        protected function addWhereIf( $value, $condition ) {
                if ( $condition ) {
                        $this->addWhere( $value );
+
                        return true;
                }
+
                return false;
        }
 
@@ -215,7 +219,9 @@ abstract class ApiQueryBase extends ApiBase {
                if ( $sort ) {
                        $order = $field . ( $isDirNewer ? '' : ' DESC' );
                        // Append ORDER BY
-                       $optionOrderBy = isset( $this->options['ORDER BY'] ) ? (array)$this->options['ORDER BY'] : array();
+                       $optionOrderBy = isset( $this->options['ORDER BY'] )
+                               ? (array)$this->options['ORDER BY']
+                               : array();
                        $optionOrderBy[] = $order;
                        $this->addOption( 'ORDER BY', $optionOrderBy );
                }
@@ -256,16 +262,37 @@ abstract class ApiQueryBase extends ApiBase {
         * @param string $method Function the query should be attributed to.
         *  You should usually use __METHOD__ here
         * @param array $extraQuery Query data to add but not store in the object
-        *  Format is array( 'tables' => ..., 'fields' => ..., 'where' => ..., 'options' => ..., 'join_conds' => ... )
+        *  Format is array(
+        *    'tables' => ...,
+        *    'fields' => ...,
+        *    'where' => ...,
+        *    'options' => ...,
+        *    'join_conds' => ...
+        *  )
         * @return ResultWrapper
         */
        protected function select( $method, $extraQuery = array() ) {
 
-               $tables = array_merge( $this->tables, isset( $extraQuery['tables'] ) ? (array)$extraQuery['tables'] : array() );
-               $fields = array_merge( $this->fields, isset( $extraQuery['fields'] ) ? (array)$extraQuery['fields'] : array() );
-               $where = array_merge( $this->where, isset( $extraQuery['where'] ) ? (array)$extraQuery['where'] : array() );
-               $options = array_merge( $this->options, isset( $extraQuery['options'] ) ? (array)$extraQuery['options'] : array() );
-               $join_conds = array_merge( $this->join_conds, isset( $extraQuery['join_conds'] ) ? (array)$extraQuery['join_conds'] : array() );
+               $tables = array_merge(
+                       $this->tables,
+                       isset( $extraQuery['tables'] ) ? (array)$extraQuery['tables'] : array()
+               );
+               $fields = array_merge(
+                       $this->fields,
+                       isset( $extraQuery['fields'] ) ? (array)$extraQuery['fields'] : array()
+               );
+               $where = array_merge(
+                       $this->where,
+                       isset( $extraQuery['where'] ) ? (array)$extraQuery['where'] : array()
+               );
+               $options = array_merge(
+                       $this->options,
+                       isset( $extraQuery['options'] ) ? (array)$extraQuery['options'] : array()
+               );
+               $join_conds = array_merge(
+                       $this->join_conds,
+                       isset( $extraQuery['join_conds'] ) ? (array)$extraQuery['join_conds'] : array()
+               );
 
                // getDB has its own profileDBIn/Out calls
                $db = $this->getDB();
@@ -285,13 +312,20 @@ abstract class ApiQueryBase extends ApiBase {
        protected function checkRowCount() {
                $db = $this->getDB();
                $this->profileDBIn();
-               $rowcount = $db->estimateRowCount( $this->tables, $this->fields, $this->where, __METHOD__, $this->options );
+               $rowcount = $db->estimateRowCount(
+                       $this->tables,
+                       $this->fields,
+                       $this->where,
+                       __METHOD__,
+                       $this->options
+               );
                $this->profileDBOut();
 
                global $wgAPIMaxDBRows;
                if ( $rowcount > $wgAPIMaxDBRows ) {
                        return false;
                }
+
                return true;
        }
 
@@ -332,6 +366,7 @@ abstract class ApiQueryBase extends ApiBase {
        protected function addPageSubItems( $pageId, $data ) {
                $result = $this->getResult();
                $result->setIndexedTagName( $data, $this->getModulePrefix() );
+
                return $result->addValue( array( 'query', 'pages', intval( $pageId ) ),
                        $this->getModuleName(),
                        $data );
@@ -356,7 +391,8 @@ abstract class ApiQueryBase extends ApiBase {
                        return false;
                }
                $result->setIndexedTagName_internal( array( 'query', 'pages', $pageId,
-                               $this->getModuleName() ), $elemname );
+                       $this->getModuleName() ), $elemname );
+
                return true;
        }
 
@@ -382,6 +418,7 @@ abstract class ApiQueryBase extends ApiBase {
                if ( is_null( $this->mDb ) ) {
                        $this->mDb = $this->getQuery()->getDB();
                }
+
                return $this->mDb;
        }
 
@@ -419,6 +456,7 @@ abstract class ApiQueryBase extends ApiBase {
                if ( !$t ) {
                        $this->dieUsageMsg( array( 'invalidtitle', $title ) );
                }
+
                return $t->getPrefixedDBkey();
        }
 
@@ -437,6 +475,7 @@ abstract class ApiQueryBase extends ApiBase {
                if ( !$t ) {
                        $this->dieUsageMsg( array( 'invalidtitle', $key ) );
                }
+
                return $t->getPrefixedText();
        }
 
@@ -446,7 +485,7 @@ abstract class ApiQueryBase extends ApiBase {
         * @return string Title part with underscores
         */
        public function titlePartToKey( $titlePart ) {
-               return substr( $this->titleToKey( $titlePart . 'x' ), 0, - 1 );
+               return substr( $this->titleToKey( $titlePart . 'x' ), 0, -1 );
        }
 
        /**
@@ -455,7 +494,7 @@ abstract class ApiQueryBase extends ApiBase {
         * @return string Key part with underscores
         */
        public function keyPartToTitle( $keyPart ) {
-               return substr( $this->keyToTitle( $keyPart . 'x' ), 0, - 1 );
+               return substr( $this->keyToTitle( $keyPart . 'x' ), 0, -1 );
        }
 
        /**
@@ -467,10 +506,10 @@ abstract class ApiQueryBase extends ApiBase {
         */
        public function getDirectionDescription( $p = '', $extraDirText = '' ) {
                return array(
-                               "In which direction to enumerate{$extraDirText}",
-                               " newer          - List oldest first. Note: {$p}start has to be before {$p}end.",
-                               " older          - List newest first (default). Note: {$p}start has to be later than {$p}end.",
-                       );
+                       "In which direction to enumerate{$extraDirText}",
+                       " newer          - List oldest first. Note: {$p}start has to be before {$p}end.",
+                       " older          - List newest first (default). Note: {$p}start has to be later than {$p}end.",
+               );
        }
 
        /**
@@ -491,6 +530,7 @@ abstract class ApiQueryBase extends ApiBase {
                        }
 
                        $likeQuery = LinkFilter::keepOneWildcard( $likeQuery );
+
                        return 'el_index ' . $db->buildLike( $likeQuery );
                } elseif ( !is_null( $protocol ) ) {
                        return 'el_index ' . $db->buildLike( "$protocol", $db->anyString() );
@@ -507,24 +547,20 @@ abstract class ApiQueryBase extends ApiBase {
         * @return void
         */
        public function showHiddenUsersAddBlockInfo( $showBlockInfo ) {
-               $userCanViewHiddenUsers = $this->getUser()->isAllowed( 'hideuser' );
-
-               if ( $showBlockInfo || !$userCanViewHiddenUsers ) {
-                       $this->addTables( 'ipblocks' );
-                       $this->addJoinConds( array(
-                               'ipblocks' => array( 'LEFT JOIN', 'ipb_user=user_id' ),
-                       ) );
+               $this->addTables( 'ipblocks' );
+               $this->addJoinConds( array(
+                       'ipblocks' => array( 'LEFT JOIN', 'ipb_user=user_id' ),
+               ) );
 
-                       $this->addFields( 'ipb_deleted' );
+               $this->addFields( 'ipb_deleted' );
 
-                       if ( $showBlockInfo ) {
-                               $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry' ) );
-                       }
+               if ( $showBlockInfo ) {
+                       $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry' ) );
+               }
 
-                       // Don't show hidden names
-                       if ( !$userCanViewHiddenUsers ) {
-                               $this->addWhere( 'ipb_deleted = 0 OR ipb_deleted IS NULL' );
-                       }
+               // Don't show hidden names
+               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+                       $this->addWhere( 'ipb_deleted = 0 OR ipb_deleted IS NULL' );
                }
        }
 
@@ -553,6 +589,7 @@ abstract class ApiQueryBase extends ApiBase {
                        array( 'invalidtitle', 'title' ),
                        array( 'invalidtitle', 'key' ),
                ) );
+
                return $errors;
        }
 }
@@ -587,6 +624,7 @@ abstract class ApiQueryGeneratorBase extends ApiQueryBase {
                if ( $this->mGeneratorPageSet !== null ) {
                        return $this->mGeneratorPageSet;
                }
+
                return parent::getPageSet();
        }
 
index e3c27f5..57f76bc 100644 (file)
@@ -72,11 +72,16 @@ class ApiQueryBlocks extends ApiQueryBase {
                $this->addFieldsIf( 'ipb_reason', $fld_reason );
                $this->addFieldsIf( array( 'ipb_range_start', 'ipb_range_end' ), $fld_range );
                $this->addFieldsIf( array( 'ipb_anon_only', 'ipb_create_account', 'ipb_enable_autoblock',
-                                                                       'ipb_block_email', 'ipb_deleted', 'ipb_allow_usertalk' ),
-                                                       $fld_flags );
+                       'ipb_block_email', 'ipb_deleted', 'ipb_allow_usertalk' ),
+                       $fld_flags );
 
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
-               $this->addTimestampWhereRange( 'ipb_timestamp', $params['dir'], $params['start'], $params['end'] );
+               $this->addTimestampWhereRange(
+                       'ipb_timestamp',
+                       $params['dir'],
+                       $params['start'],
+                       $params['end']
+               );
 
                $db = $this->getDB();
 
@@ -107,7 +112,10 @@ class ApiQueryBlocks extends ApiQueryBase {
                        # Check range validity, if it's a CIDR
                        list( $ip, $range ) = IP::parseCIDR( $params['ip'] );
                        if ( $ip !== false && $range !== false && $range < $cidrLimit ) {
-                               $this->dieUsage( "$type CIDR ranges broader than /$cidrLimit are not accepted", 'cidrtoobroad' );
+                               $this->dieUsage(
+                                       "$type CIDR ranges broader than /$cidrLimit are not accepted",
+                                       'cidrtoobroad'
+                               );
                        }
 
                        # Let IP::parseRange handle calculating $upper, instead of duplicating the logic here.
@@ -134,9 +142,9 @@ class ApiQueryBlocks extends ApiQueryBase {
 
                        /* Check for conflicting parameters. */
                        if ( ( isset( $show['account'] ) && isset( $show['!account'] ) )
-                                       || ( isset( $show['ip'] ) && isset( $show['!ip'] ) )
-                                       || ( isset( $show['range'] ) && isset( $show['!range'] ) )
-                                       || ( isset( $show['temp'] ) && isset( $show['!temp'] ) )
+                               || ( isset( $show['ip'] ) && isset( $show['!ip'] ) )
+                               || ( isset( $show['range'] ) && isset( $show['!range'] ) )
+                               || ( isset( $show['temp'] ) && isset( $show['!temp'] ) )
                        ) {
                                $this->dieUsageMsg( 'show' );
                        }
@@ -145,8 +153,10 @@ class ApiQueryBlocks extends ApiQueryBase {
                        $this->addWhereIf( 'ipb_user != 0', isset( $show['account'] ) );
                        $this->addWhereIf( 'ipb_user != 0 OR ipb_range_end > ipb_range_start', isset( $show['!ip'] ) );
                        $this->addWhereIf( 'ipb_user = 0 AND ipb_range_end = ipb_range_start', isset( $show['ip'] ) );
-                       $this->addWhereIf( 'ipb_expiry = ' . $db->addQuotes( $db->getInfinity() ), isset( $show['!temp'] ) );
-                       $this->addWhereIf( 'ipb_expiry != ' . $db->addQuotes( $db->getInfinity() ), isset( $show['temp'] ) );
+                       $this->addWhereIf( 'ipb_expiry = ' .
+                               $db->addQuotes( $db->getInfinity() ), isset( $show['!temp'] ) );
+                       $this->addWhereIf( 'ipb_expiry != ' .
+                               $db->addQuotes( $db->getInfinity() ), isset( $show['temp'] ) );
                        $this->addWhereIf( 'ipb_range_end = ipb_range_start', isset( $show['!range'] ) );
                        $this->addWhereIf( 'ipb_range_end > ipb_range_start', isset( $show['range'] ) );
                }
@@ -309,6 +319,7 @@ class ApiQueryBlocks extends ApiQueryBase {
        public function getParamDescription() {
                global $wgBlockCIDRLimit;
                $p = $this->getModulePrefix();
+
                return array(
                        'start' => 'The timestamp to start enumerating from',
                        'end' => 'The timestamp to stop enumerating at',
@@ -402,6 +413,7 @@ class ApiQueryBlocks extends ApiQueryBase {
 
        public function getPossibleErrors() {
                global $wgBlockCIDRLimit;
+
                return array_merge( parent::getPossibleErrors(),
                        $this->getRequireOnlyOneParameterErrorMessages( array( 'users', 'ip' ) ),
                        array(
index 5d714f5..c5b12b3 100644 (file)
@@ -98,8 +98,7 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                if ( isset( $show['hidden'] ) && isset( $show['!hidden'] ) ) {
                        $this->dieUsageMsg( 'show' );
                }
-               if ( isset( $show['hidden'] ) || isset( $show['!hidden'] ) || isset( $prop['hidden'] ) )
-               {
+               if ( isset( $show['hidden'] ) || isset( $show['!hidden'] ) || isset( $prop['hidden'] ) ) {
                        $this->addOption( 'STRAIGHT_JOIN' );
                        $this->addTables( array( 'page', 'page_props' ) );
                        $this->addFieldsIf( 'pp_propname', isset( $prop['hidden'] ) );
@@ -126,9 +125,9 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                        $this->addOption( 'ORDER BY', 'cl_to' . $sort );
                } else {
                        $this->addOption( 'ORDER BY', array(
-                                               'cl_from' . $sort,
-                                               'cl_to' . $sort
-                       ));
+                               'cl_from' . $sort,
+                               'cl_to' . $sort
+                       ) );
                }
 
                $res = $this->select( __METHOD__ );
@@ -221,14 +220,16 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
                return array(
                        'prop' => array(
                                'Which additional properties to get for each category',
-                               ' sortkey    - Adds the sortkey (hexadecimal string) and sortkey prefix (human-readable part) for the category',
+                               ' sortkey    - Adds the sortkey (hexadecimal string) and sortkey prefix',
+                               '              (human-readable part) for the category',
                                ' timestamp  - Adds timestamp of when the category was added',
                                ' hidden     - Tags categories that are hidden with __HIDDENCAT__',
                        ),
                        'limit' => 'How many categories to return',
                        'show' => 'Which kind of categories to show',
                        'continue' => 'When more results are available, use this to continue',
-                       'categories' => 'Only list these categories. Useful for checking whether a certain page is in a certain category',
+                       'categories' => 'Only list these categories. Useful for checking ' .
+                               'whether a certain page is in a certain category',
                        'dir' => 'The direction in which to list',
                );
        }
@@ -264,8 +265,10 @@ class ApiQueryCategories extends ApiQueryGeneratorBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=categories&titles=Albert%20Einstein' => 'Get a list of categories [[Albert Einstein]] belongs to',
-                       'api.php?action=query&generator=categories&titles=Albert%20Einstein&prop=info' => 'Get information about all categories used in the [[Albert Einstein]]',
+                       'api.php?action=query&prop=categories&titles=Albert%20Einstein'
+                               => 'Get a list of categories [[Albert Einstein]] belongs to',
+                       'api.php?action=query&generator=categories&titles=Albert%20Einstein&prop=info'
+                               => 'Get information about all categories used in the [[Albert Einstein]]',
                );
        }
 
index a889272..574ef6e 100644 (file)
@@ -45,7 +45,7 @@ class ApiQueryCategoryInfo extends ApiQueryBase {
                $categories = $alltitles[NS_CATEGORY];
 
                $titles = $this->getPageSet()->getGoodTitles() +
-                                       $this->getPageSet()->getMissingTitles();
+                       $this->getPageSet()->getMissingTitles();
                $cattitles = array();
                foreach ( $categories as $c ) {
                        /** @var $t Title */
@@ -63,7 +63,13 @@ class ApiQueryCategoryInfo extends ApiQueryBase {
                                'pp_propname' => 'hiddencat' ) ),
                ) );
 
-               $this->addFields( array( 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files', 'cat_hidden' => 'pp_propname' ) );
+               $this->addFields( array(
+                       'cat_title',
+                       'cat_pages',
+                       'cat_subcats',
+                       'cat_files',
+                       'cat_hidden' => 'pp_propname'
+               ) );
                $this->addWhere( array( 'cat_title' => $cattitles ) );
 
                if ( !is_null( $params['continue'] ) ) {
index 704d108..271558b 100644 (file)
@@ -180,9 +180,11 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                $result = $this->getResult();
                $count = 0;
                foreach ( $rows as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               // TODO: Security issue - if the user has no right to view next title, it will still be shown
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
+                               // @todo Security issue - if the user has no right to view next
+                               // title, it will still be shown
                                if ( $params['sort'] == 'timestamp' ) {
                                        $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->cl_timestamp ) );
                                } else {
@@ -224,7 +226,7 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                                        $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->cl_timestamp );
                                }
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ),
-                                               null, $vals );
+                                       null, $vals );
                                if ( !$fit ) {
                                        if ( $params['sort'] == 'timestamp' ) {
                                                $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->cl_timestamp ) );
@@ -324,14 +326,16 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                global $wgMiserMode;
                $p = $this->getModulePrefix();
                $desc = array(
-                       'title' => "Which category to enumerate (required). Must include Category: prefix. Cannot be used together with {$p}pageid",
+                       'title' => "Which category to enumerate (required). Must include ' .
+                               'Category: prefix. Cannot be used together with {$p}pageid",
                        'pageid' => "Page ID of the category to enumerate. Cannot be used together with {$p}title",
                        'prop' => array(
                                'What pieces of information to include',
                                ' ids           - Adds the page ID',
                                ' title         - Adds the title and namespace ID of the page',
                                ' sortkey       - Adds the sortkey used for sorting in the category (hexadecimal string)',
-                               ' sortkeyprefix - Adds the sortkey prefix used for sorting in the category (human-readable part of the sortkey)',
+                               ' sortkeyprefix - Adds the sortkey prefix used for sorting in the ' .
+                                       'category (human-readable part of the sortkey)',
                                ' type          - Adds the type that the page has been categorised as (page, subcat or file)',
                                ' timestamp     - Adds the timestamp of when the page was included',
                        ),
@@ -341,10 +345,15 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                        'dir' => 'In which direction to sort',
                        'start' => "Timestamp to start listing from. Can only be used with {$p}sort=timestamp",
                        'end' => "Timestamp to end listing at. Can only be used with {$p}sort=timestamp",
-                       'startsortkey' => "Sortkey to start listing from. Must be given in binary format. Can only be used with {$p}sort=sortkey",
-                       'endsortkey' => "Sortkey to end listing at. Must be given in binary format. Can only be used with {$p}sort=sortkey",
-                       'startsortkeyprefix' => "Sortkey prefix to start listing from. Can only be used with {$p}sort=sortkey. Overrides {$p}startsortkey",
-                       'endsortkeyprefix' => "Sortkey prefix to end listing BEFORE (not at, if this value occurs it will not be included!). Can only be used with {$p}sort=sortkey. Overrides {$p}endsortkey",
+                       'startsortkey' => "Sortkey to start listing from. Must be given in ' .
+                               'binary format. Can only be used with {$p}sort=sortkey",
+                       'endsortkey' => "Sortkey to end listing at. Must be given in binary ' .
+                               'format. Can only be used with {$p}sort=sortkey",
+                       'startsortkeyprefix' => "Sortkey prefix to start listing from. Can ' .
+                               'only be used with {$p}sort=sortkey. Overrides {$p}startsortkey",
+                       'endsortkeyprefix' => "Sortkey prefix to end listing BEFORE (not at, ' .
+                               'if this value occurs it will not be included!). Can only be used with ' .
+                               '{$p}sort=sortkey. Overrides {$p}endsortkey",
                        'continue' => 'For large categories, give the value returned from previous query',
                        'limit' => 'The maximum number of pages to return.',
                );
@@ -357,6 +366,7 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
                                "Note that you can use {$p}type=subcat or {$p}type=file instead of {$p}namespace=14 or 6.",
                        );
                }
+
                return $desc;
        }
 
@@ -405,8 +415,10 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&list=categorymembers&cmtitle=Category:Physics' => 'Get first 10 pages in [[Category:Physics]]',
-                       'api.php?action=query&generator=categorymembers&gcmtitle=Category:Physics&prop=info' => 'Get page info about first 10 pages in [[Category:Physics]]',
+                       'api.php?action=query&list=categorymembers&cmtitle=Category:Physics'
+                               => 'Get first 10 pages in [[Category:Physics]]',
+                       'api.php?action=query&generator=categorymembers&gcmtitle=Category:Physics&prop=info'
+                               => 'Get page info about first 10 pages in [[Category:Physics]]',
                );
        }
 
index 8273313..35e78ac 100644 (file)
@@ -39,7 +39,10 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                $user = $this->getUser();
                // Before doing anything at all, let's check permissions
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage( 'You don\'t have permission to view deleted revision information', 'permissiondenied' );
+                       $this->dieUsage(
+                               'You don\'t have permission to view deleted revision information',
+                               'permissiondenied'
+                       );
                }
 
                $db = $this->getDB();
@@ -116,7 +119,10 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
                        // This also means stricter restrictions
                        if ( !$user->isAllowed( 'undelete' ) ) {
-                               $this->dieUsage( 'You don\'t have permission to view deleted revision content', 'permissiondenied' );
+                               $this->dieUsage(
+                                       'You don\'t have permission to view deleted revision content',
+                                       'permissiondenied'
+                               );
                        }
                }
                // Check limits
@@ -152,7 +158,8 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        $this->addWhereRange( 'ar_title', $dir, $from, $to );
 
                        if ( isset( $params['prefix'] ) ) {
-                               $this->addWhere( 'ar_title' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                               $this->addWhere( 'ar_title' .
+                                       $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                        }
                }
 
@@ -172,14 +179,17 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        $ts = $db->addQuotes( $db->timestamp( $cont[2] ) );
                        $op = ( $dir == 'newer' ? '>' : '<' );
                        $this->addWhere( "ar_namespace $op $ns OR " .
-                                       "(ar_namespace = $ns AND " .
-                                       "(ar_title $op $title OR " .
-                                       "(ar_title = $title AND " .
-                                       "ar_timestamp $op= $ts)))" );
+                               "(ar_namespace = $ns AND " .
+                               "(ar_title $op $title OR " .
+                               "(ar_title = $title AND " .
+                               "ar_timestamp $op= $ts)))" );
                }
 
                $this->addOption( 'LIMIT', $limit + 1 );
-               $this->addOption( 'USE INDEX', array( 'archive' => ( $mode == 'user' ? 'usertext_timestamp' : 'name_title_timestamp' ) ) );
+               $this->addOption(
+                       'USE INDEX',
+                       array( 'archive' => ( $mode == 'user' ? 'usertext_timestamp' : 'name_title_timestamp' ) )
+               );
                if ( $mode == 'all' ) {
                        if ( $params['unique'] ) {
                                $this->addOption( 'GROUP BY', 'ar_title' );
@@ -188,7 +198,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                                $this->addOption( 'ORDER BY', array(
                                        'ar_title' . $sort,
                                        'ar_timestamp' . $sort
-                               ));
+                               ) );
                        }
                } else {
                        if ( $mode == 'revs' ) {
@@ -385,12 +395,14 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
        public function getDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'List deleted revisions.',
                        'Operates in three modes:',
                        ' 1) List deleted revisions for the given title(s), sorted by timestamp',
                        ' 2) List deleted contributions for the given user, sorted by timestamp (no titles specified)',
-                       " 3) List all deleted revisions in the given namespace, sorted by title and timestamp (no titles specified, {$p}user not set)",
+                       " 3) List all deleted revisions in the given namespace, sorted by title and timestamp',
+                       '    (no titles specified, {$p}user not set)",
                        'Certain parameters only apply to some modes and are ignored in others.',
                        'For instance, a parameter marked (1) only applies to mode 1 and is ignored in modes 2 and 3',
                );
@@ -398,12 +410,22 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view deleted revision information' ),
-                       array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together' ),
-                       array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view deleted revision content' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You don\'t have permission to view deleted revision information'
+                       ),
+                       array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together'
+                       ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You don\'t have permission to view deleted revision content'
+                       ),
                        array( 'code' => 'badparams', 'info' => "The 'from' parameter cannot be used in modes 1 or 2" ),
                        array( 'code' => 'badparams', 'info' => "The 'to' parameter cannot be used in modes 1 or 2" ),
-                       array( 'code' => 'badparams', 'info' => "The 'prefix' parameter cannot be used in modes 1 or 2" ),
+                       array(
+                               'code' => 'badparams',
+                               'info' => "The 'prefix' parameter cannot be used in modes 1 or 2"
+                       ),
                        array( 'code' => 'badparams', 'info' => "The 'start' parameter cannot be used in mode 3" ),
                        array( 'code' => 'badparams', 'info' => "The 'end' parameter cannot be used in mode 3" ),
                ) );
@@ -411,7 +433,8 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content'
+                       'api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&' .
+                               'drprop=user|comment|content'
                                => 'List the last deleted revisions of Main Page and Talk:Main Page, with content (mode 1)',
                        'api.php?action=query&list=deletedrevs&druser=Bob&drlimit=50'
                                => 'List the last 50 deleted contributions by Bob (mode 2)',
index 0311fa7..1854694 100644 (file)
@@ -95,7 +95,8 @@ class ApiQueryDuplicateFiles extends ApiQueryGeneratorBase {
                        $sha1s[$file->getName()] = $file->getSha1();
                }
 
-               // find all files with the hashes, result format is: array( hash => array( dup1, dup2 ), hash1 => ... )
+               // find all files with the hashes, result format is:
+               // array( hash => array( dup1, dup2 ), hash1 => ... )
                $filesToFindBySha1s = array_unique( array_values( $sha1s ) );
                if ( $params['localonly'] ) {
                        $filesBySha1s = RepoGroup::singleton()->getLocalRepo()->findBySha1s( $filesToFindBySha1s );
index 456e87b..d220817 100644 (file)
@@ -101,8 +101,9 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
                $result = $this->getResult();
                $count = 0;
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'offset', $offset + $limit );
                                break;
                        }
@@ -140,7 +141,7 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
 
                if ( is_null( $resultPageSet ) ) {
                        $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ),
-                                       $this->getModulePrefix() );
+                               $this->getModulePrefix() );
                }
        }
 
@@ -186,6 +187,7 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
                                $protocols[] = substr( $p, 0, strpos( $p, ':' ) );
                        }
                }
+
                return $protocols;
        }
 
@@ -221,7 +223,8 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
                                "Protocol of the URL. If empty and {$p}query set, the protocol is http.",
                                "Leave both this and {$p}query empty to list all external links"
                        ),
-                       'query' => 'Search string without protocol. See [[Special:LinkSearch]]. Leave empty to list all external links',
+                       'query' => 'Search string without protocol. See [[Special:LinkSearch]]. ' .
+                               'Leave empty to list all external links',
                        'namespace' => 'The page namespace(s) to enumerate.',
                        'limit' => 'How many pages to return.',
                        'expandurl' => 'Expand protocol-relative URLs with the canonical protocol',
index 583ef69..5803ea7 100644 (file)
@@ -127,6 +127,7 @@ class ApiQueryExternalLinks extends ApiQueryBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'limit' => 'How many links to return',
                        'offset' => 'When more results are available, use this to continue',
@@ -134,7 +135,8 @@ class ApiQueryExternalLinks extends ApiQueryBase {
                                "Protocol of the URL. If empty and {$p}query set, the protocol is http.",
                                "Leave both this and {$p}query empty to list all external links"
                        ),
-                       'query' => 'Search string without protocol. Useful for checking whether a certain page contains a certain external url',
+                       'query' => 'Search string without protocol. Useful for checking ' .
+                               'whether a certain page contains a certain external url',
                        'expandurl' => 'Expand protocol-relative URLs with the canonical protocol',
                );
        }
@@ -159,7 +161,8 @@ class ApiQueryExternalLinks extends ApiQueryBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=extlinks&titles=Main%20Page' => 'Get a list of external links on the [[Main Page]]',
+                       'api.php?action=query&prop=extlinks&titles=Main%20Page'
+                               => 'Get a list of external links on the [[Main Page]]',
                );
        }
 
index 3a35353..dffe301 100644 (file)
@@ -35,11 +35,7 @@ class ApiQueryFileRepoInfo extends ApiQueryBase {
 
        protected function getInitialisedRepoGroup() {
                $repoGroup = RepoGroup::singleton();
-
-               if ( !$repoGroup->reposInitialised ) {
-                       $repoGroup->initialiseRepos();
-               }
-
+               $repoGroup->initialiseRepos();
                return $repoGroup;
        }
 
@@ -55,7 +51,7 @@ class ApiQueryFileRepoInfo extends ApiQueryBase {
                        $repos[] = array_intersect_key( $repo->getInfo(), $props );
                } );
 
-               $repos[] = array_intersect_key( $repoGroup->localRepo->getInfo(), $props );
+               $repos[] = array_intersect_key( $repoGroup->getLocalRepo()->getInfo(), $props );
 
                $result = $this->getResult();
                $result->setIndexedTagName( $repos, 'repo' );
@@ -86,16 +82,19 @@ class ApiQueryFileRepoInfo extends ApiQueryBase {
                        $props = array_merge( $props, array_keys( $repo->getInfo() ) );
                } );
 
-               return array_values( array_unique( array_merge( $props, array_keys( $repoGroup->localRepo->getInfo() ) ) ) );
+               return array_values( array_unique( array_merge(
+                       $props,
+                       array_keys( $repoGroup->getLocalRepo()->getInfo() )
+               ) ) );
        }
 
        public function getParamDescription() {
-               $p = $this->getModulePrefix();
                return array(
                        'prop' => array(
                                'Which repository properties to get (there may be more available on some wikis):',
                                ' apiurl      - URL to the repository API - helpful for getting image info from the host.',
-                               ' name        - The key of the repository - used in e.g. $wgForeignFileRepos and imageinfo return values.',
+                               ' name        - The key of the repository - used in e.g. ' .
+                                       '$wgForeignFileRepos and imageinfo return values.',
                                ' displayname - The human-readable name of the repository wiki.',
                                ' rooturl     - Root URL for image paths.',
                                ' local       - Whether that repository is the local one or not.',
index f53cd38..f8f4558 100644 (file)
@@ -41,7 +41,10 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $user = $this->getUser();
                // Before doing anything at all, let's check permissions
                if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $this->dieUsage( 'You don\'t have permission to view deleted file information', 'permissiondenied' );
+                       $this->dieUsage(
+                               'You don\'t have permission to view deleted file information',
+                               'permissiondenied'
+                       );
                }
 
                $db = $this->getDB();
@@ -92,7 +95,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $to = ( is_null( $params['to'] ) ? null : $this->titlePartToKey( $params['to'] ) );
                $this->addWhereRange( 'fa_name', $dir, $from, $to );
                if ( isset( $params['prefix'] ) ) {
-                       $this->addWhere( 'fa_name' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
+                       $this->addWhere( 'fa_name' .
+                               $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
                }
 
                $sha1Set = isset( $params['sha1'] );
@@ -137,7 +141,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $result = $this->getResult();
                foreach ( $res as $row ) {
                        if ( ++$count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->fa_name );
                                break;
                        }
@@ -180,8 +185,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                        }
                        if ( $fld_metadata ) {
                                $file['metadata'] = $row->fa_metadata
-                                               ? ApiQueryImageInfo::processMetaData( unserialize( $row->fa_metadata ), $result )
-                                               : null;
+                                       ? ApiQueryImageInfo::processMetaData( unserialize( $row->fa_metadata ), $result )
+                                       : null;
                        }
                        if ( $fld_bitdepth ) {
                                $file['bitdepth'] = $row->fa_bits;
@@ -275,7 +280,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                                ' sha1              - Adds SHA-1 hash for the image',
                                ' timestamp         - Adds timestamp for the uploaded version',
                                ' user              - Adds user who uploaded the image version',
-                               ' size              - Adds the size of the image in bytes and the height, width and page count (if applicable)',
+                               ' size              - Adds the size of the image in bytes and the height, ' .
+                                       'width and page count (if applicable)',
                                ' dimensions        - Alias for size',
                                ' description       - Adds description the image version',
                                ' parseddescription - Parse the description on the version',
@@ -358,10 +364,16 @@ class ApiQueryFilearchive extends ApiQueryBase {
 
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view deleted file information' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You don\'t have permission to view deleted file information'
+                       ),
                        array( 'code' => 'hashsearchdisabled', 'info' => 'Search by hash disabled in Miser Mode' ),
-                       array( 'code' => 'invalidsha1hash', 'info' => 'The SHA1 hash provided is not valid' ),
-                       array( 'code' => 'invalidsha1base36hash', 'info' => 'The SHA1Base36 hash provided is not valid' ),
+                       array( 'code' => 'invalidsha1hash', 'info' => 'The SHA-1 hash provided is not valid' ),
+                       array(
+                               'code' => 'invalidsha1base36hash',
+                               'info' => 'The SHA1Base36 hash provided is not valid'
+                       ),
                ) );
        }
 
index ebae3e7..03a72a6 100644 (file)
@@ -92,14 +92,14 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
                                $this->addOption( 'ORDER BY', array(
                                        'iwl_title' . $sort,
                                        'iwl_from' . $sort
-                               ));
+                               ) );
                        }
                } else {
                        $this->addOption( 'ORDER BY', array(
                                'iwl_prefix' . $sort,
                                'iwl_title' . $sort,
                                'iwl_from' . $sort
-                       ));
+                       ) );
                }
 
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
@@ -111,10 +111,15 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
                $count = 0;
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               // Continue string preserved in case the redirect query doesn't pass the limit
-                               $this->setContinueEnumParameter( 'continue', "{$row->iwl_prefix}|{$row->iwl_title}|{$row->iwl_from}" );
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
+                               // Continue string preserved in case the redirect query doesn't
+                               // pass the limit
+                               $this->setContinueEnumParameter(
+                                       'continue',
+                                       "{$row->iwl_prefix}|{$row->iwl_title}|{$row->iwl_from}"
+                               );
                                break;
                        }
 
@@ -140,7 +145,10 @@ class ApiQueryIWBacklinks extends ApiQueryGeneratorBase {
 
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $entry );
                                if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'continue', "{$row->iwl_prefix}|{$row->iwl_title}|{$row->iwl_from}" );
+                                       $this->setContinueEnumParameter(
+                                               'continue',
+                                               "{$row->iwl_prefix}|{$row->iwl_title}|{$row->iwl_from}"
+                                       );
                                        break;
                                }
                        }
index be53931..be64d36 100644 (file)
@@ -81,9 +81,9 @@ class ApiQueryIWLinks extends ApiQueryBase {
                                $this->addOption( 'ORDER BY', 'iwl_from' . $sort );
                        } else {
                                $this->addOption( 'ORDER BY', array(
-                                               'iwl_from' . $sort,
-                                               'iwl_title' . $sort
-                               ));
+                                       'iwl_from' . $sort,
+                                       'iwl_title' . $sort
+                               ) );
                        }
                } else {
                        // Don't order by iwl_from if it's constant in the WHERE clause
@@ -91,10 +91,10 @@ class ApiQueryIWLinks extends ApiQueryBase {
                                $this->addOption( 'ORDER BY', 'iwl_prefix' . $sort );
                        } else {
                                $this->addOption( 'ORDER BY', array(
-                                               'iwl_from' . $sort,
-                                               'iwl_prefix' . $sort,
-                                               'iwl_title' . $sort
-                               ));
+                                       'iwl_from' . $sort,
+                                       'iwl_prefix' . $sort,
+                                       'iwl_title' . $sort
+                               ) );
                        }
                }
 
@@ -106,7 +106,10 @@ class ApiQueryIWLinks extends ApiQueryBase {
                        if ( ++$count > $params['limit'] ) {
                                // We've reached the one extra which shows that
                                // there are additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter( 'continue', "{$row->iwl_from}|{$row->iwl_prefix}|{$row->iwl_title}" );
+                               $this->setContinueEnumParameter(
+                                       'continue',
+                                       "{$row->iwl_from}|{$row->iwl_prefix}|{$row->iwl_title}"
+                               );
                                break;
                        }
                        $entry = array( 'prefix' => $row->iwl_prefix );
@@ -121,7 +124,10 @@ class ApiQueryIWLinks extends ApiQueryBase {
                        ApiResult::setContent( $entry, $row->iwl_title );
                        $fit = $this->addPageSubItem( $row->iwl_from, $entry );
                        if ( !$fit ) {
-                               $this->setContinueEnumParameter( 'continue', "{$row->iwl_from}|{$row->iwl_prefix}|{$row->iwl_title}" );
+                               $this->setContinueEnumParameter(
+                                       'continue',
+                                       "{$row->iwl_from}|{$row->iwl_prefix}|{$row->iwl_title}"
+                               );
                                break;
                        }
                }
@@ -190,7 +196,8 @@ class ApiQueryIWLinks extends ApiQueryBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=iwlinks&titles=Main%20Page' => 'Get interwiki links from the [[Main Page]]',
+                       'api.php?action=query&prop=iwlinks&titles=Main%20Page'
+                               => 'Get interwiki links from the [[Main Page]]',
                );
        }
 
index 0ea2868..86cba83 100644 (file)
@@ -34,8 +34,9 @@ class ApiQueryImageInfo extends ApiQueryBase {
        private static $transformCount = 0;
 
        public function __construct( $query, $moduleName, $prefix = 'ii' ) {
-               // We allow a subclass to override the prefix, to create a related API module.
-               // Some other parts of MediaWiki construct this with a null $prefix, which used to be ignored when this only took two arguments
+               // We allow a subclass to override the prefix, to create a related API
+               // module. Some other parts of MediaWiki construct this with a null
+               // $prefix, which used to be ignored when this only took two arguments
                if ( is_null( $prefix ) ) {
                        $prefix = 'ii';
                }
@@ -49,6 +50,13 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                $scale = $this->getScale( $params );
 
+               $metadataOpts = array(
+                       'version' => $params['metadataversion'],
+                       'language' => $params['extmetadatalanguage'],
+                       'multilang' => $params['extmetadatamultilang'],
+                       'extmetadatafilter' => $params['extmetadatafilter'],
+               );
+
                $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
                if ( !empty( $pageIds[NS_FILE] ) ) {
                        $titles = array_keys( $pageIds[NS_FILE] );
@@ -146,7 +154,9 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                                        $fit = $this->addPageSubItem( $pageId,
                                                self::getInfo( $img, $prop, $result,
-                                                       $finalThumbParams, $params['metadataversion'] ) );
+                                                       $finalThumbParams, $metadataOpts
+                                               )
+                                       );
                                        if ( !$fit ) {
                                                if ( count( $pageIds[NS_FILE] ) == 1 ) {
                                                        // See the 'the user is screwed' comment above
@@ -167,7 +177,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                /** @var $oldie File */
                                foreach ( $oldies as $oldie ) {
                                        if ( ++$count > $params['limit'] ) {
-                                               // We've reached the extra one which shows that there are additional pages to be had. Stop here...
+                                               // We've reached the extra one which shows that there are
+                                               // additional pages to be had. Stop here...
                                                // Only set a query-continue if there was only one title
                                                if ( count( $pageIds[NS_FILE] ) == 1 ) {
                                                        $this->setContinueEnumParameter( 'start',
@@ -178,7 +189,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                        $fit = self::getTransformCount() < self::TRANSFORM_LIMIT &&
                                                $this->addPageSubItem( $pageId,
                                                        self::getInfo( $oldie, $prop, $result,
-                                                               $finalThumbParams, $params['metadataversion']
+                                                               $finalThumbParams, $metadataOpts
                                                        )
                                                );
                                        if ( !$fit ) {
@@ -259,6 +270,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                if ( !$h ) {
                        $this->setWarning( 'Could not create thumbnail because ' .
                                $image->getName() . ' does not have an associated image handler' );
+
                        return $thumbParams;
                }
 
@@ -270,13 +282,15 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        // handlers.
                        $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
                                . '. Using only width and height' );
+
                        return $thumbParams;
                }
 
                if ( isset( $paramList['width'] ) ) {
                        if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
                                $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
-                                       . "in favor of width value derived from {$p}urlwidth/{$p}urlheight ({$thumbParams['width']})" );
+                                       . "in favor of width value derived from {$p}urlwidth/{$p}urlheight "
+                                       . "({$thumbParams['width']})" );
                        }
                }
 
@@ -296,10 +310,25 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @param array $prop of properties to get (in the keys)
         * @param $result ApiResult object
         * @param array $thumbParams containing 'width' and 'height' items, or null
-        * @param string $version Version of image metadata (for things like jpeg which have different versions).
+        * @param array|bool|string $metadataOpts Options for metadata fetching.
+        *   This is an array consisting of the keys:
+        *    'version': The metadata version for the metadata option
+        *    'language': The language for extmetadata property
+        *    'multilang': Return all translations in extmetadata property
         * @return Array: result array
         */
-       static function getInfo( $file, $prop, $result, $thumbParams = null, $version = 'latest' ) {
+       static function getInfo( $file, $prop, $result, $thumbParams = null, $metadataOpts = false ) {
+               global $wgContLang;
+
+               if ( !$metadataOpts || is_string( $metadataOpts ) ) {
+                       $metadataOpts = array(
+                               'version' => $metadataOpts ?: 'latest',
+                               'language' => $wgContLang,
+                               'multilang' => false,
+                               'extmetadatafilter' => array(),
+                       );
+               }
+               $version = $metadataOpts['version'];
                $vals = array();
                // Timestamp is shown even if the file is revdelete'd in interface
                // so do same here.
@@ -359,6 +388,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                $url = isset( $prop['url'] );
                $sha1 = isset( $prop['sha1'] );
                $meta = isset( $prop['metadata'] );
+               $extmetadata = isset( $prop['extmetadata'] );
                $mime = isset( $prop['mime'] );
                $mediatype = isset( $prop['mediatype'] );
                $archive = isset( $prop['archivename'] );
@@ -366,7 +396,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
                $uploadwarning = isset( $prop['uploadwarning'] );
 
                if ( ( $url || $sha1 || $meta || $mime || $mediatype || $archive || $bitdepth )
-                               && $file->isDeleted( File::DELETED_FILE ) ) {
+                       && $file->isDeleted( File::DELETED_FILE )
+               ) {
                        $vals['filehidden'] = '';
 
                        //Early return, tidier than indenting all following things one level
@@ -417,6 +448,22 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        $vals['metadata'] = $metadata ? self::processMetaData( $metadata, $result ) : null;
                }
 
+               if ( $extmetadata ) {
+                       // Note, this should return an array where all the keys
+                       // start with a letter, and all the values are strings.
+                       // Thus there should be no issue with format=xml.
+                       $format = new FormatMetadata;
+                       $format->setSingleLanguage( !$metadataOpts['multilang'] );
+                       $format->getContext()->setLanguage( $metadataOpts['language'] );
+                       $extmetaArray = $format->fetchExtendedMetadata( $file );
+                       if ( $metadataOpts['extmetadatafilter'] ) {
+                               $extmetaArray = array_intersect_key(
+                                       $extmetaArray, array_flip( $metadataOpts['extmetadatafilter'] )
+                               );
+                       }
+                       $vals['extmetadata'] = $extmetaArray;
+               }
+
                if ( $mime ) {
                        $vals['mime'] = $file->getMimeType();
                }
@@ -471,6 +518,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        }
                }
                $result->setIndexedTagName( $retval, 'metadata' );
+
                return $retval;
        }
 
@@ -487,10 +535,13 @@ class ApiQueryImageInfo extends ApiQueryBase {
                if ( $start === null ) {
                        $start = $img->getTimestamp();
                }
+
                return $img->getOriginalTitle()->getDBkey() . '|' . $start;
        }
 
        public function getAllowedParams() {
+               global $wgContLang;
+
                return array(
                        'prop' => array(
                                ApiBase::PARAM_ISMULTI => true,
@@ -522,6 +573,18 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_DFLT => '1',
                        ),
+                       'extmetadatalanguage' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_DFLT => $wgContLang->getCode(),
+                       ),
+                       'extmetadatamultilang' => array(
+                               ApiBase::PARAM_TYPE => 'boolean',
+                               ApiBase::PARAM_DFLT => false,
+                       ),
+                       'extmetadatafilter' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ),
                        'urlparam' => array(
                                ApiBase::PARAM_DFLT => '',
                                ApiBase::PARAM_TYPE => 'string',
@@ -556,17 +619,22 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'comment' =>        ' comment       - Comment on the version',
                        'parsedcomment' =>  ' parsedcomment - Parse the comment on the version',
                        'url' =>            ' url           - Gives URL to the image and the description page',
-                       'size' =>           ' size          - Adds the size of the image in bytes and the height, width and page count (if applicable)',
-                       'dimensions' =>     ' dimensions    - Alias for size', // For backwards compatibility with Allimages
+                       'size' =>           ' size          - Adds the size of the image in bytes ' .
+                               'and the height, width and page count (if applicable)',
+                       'dimensions' =>     ' dimensions    - Alias for size', // B/C with Allimages
                        'sha1' =>           ' sha1          - Adds SHA-1 hash for the image',
                        'mime' =>           ' mime          - Adds MIME type of the image',
                        'thumbmime' =>      ' thumbmime     - Adds MIME type of the image thumbnail' .
                                ' (requires url and param ' . $modulePrefix . 'urlwidth)',
                        'mediatype' =>      ' mediatype     - Adds the media type of the image',
                        'metadata' =>       ' metadata      - Lists Exif metadata for the version of the image',
-                       'archivename' =>    ' archivename   - Adds the file name of the archive version for non-latest versions',
+                       'extmetadata' =>    ' extmetadata   - Lists formatted metadata combined ' .
+                               'from multiple sources. Results are HTML formatted.',
+                       'archivename' =>    ' archivename   - Adds the file name of the archive ' .
+                               'version for non-latest versions',
                        'bitdepth' =>       ' bitdepth      - Adds the bit depth of the version',
-                       'uploadwarning' =>  ' uploadwarning - Used by the Special:Upload page to get information about an existing file. Not intended for use outside MediaWiki core',
+                       'uploadwarning' =>  ' uploadwarning - Used by the Special:Upload page to ' .
+                               'get information about an existing file. Not intended for use outside MediaWiki core',
                );
        }
 
@@ -590,20 +658,34 @@ class ApiQueryImageInfo extends ApiQueryBase {
         */
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => self::getPropertyDescriptions( array(), $p ),
-                       'urlwidth' => array( "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
+                       'urlwidth' => array(
+                               "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
                                'For performance reasons if this option is used, ' .
-                                       'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.' ),
+                                       'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.'
+                       ),
                        'urlheight' => "Similar to {$p}urlwidth.",
                        'urlparam' => array( "A handler specific parameter string. For example, pdf's ",
                                "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ),
                        'limit' => 'How many image revisions to return per image',
                        'start' => 'Timestamp to start listing from',
                        'end' => 'Timestamp to stop listing at',
-                       'metadataversion' => array( "Version of metadata to use. if 'latest' is specified, use latest version.",
-                                               "Defaults to '1' for backwards compatibility" ),
-                       'continue' => 'If the query response includes a continue value, use it here to get another page of results',
+                       'metadataversion'
+                               => array( "Version of metadata to use. if 'latest' is specified, use latest version.",
+                               "Defaults to '1' for backwards compatibility" ),
+                       'extmetadatalanguage' => array(
+                               'What language to fetch extmetadata in. This affects both which',
+                               'translation to fetch, if multiple are available, as well as how things',
+                               'like numbers and various values are formatted.'
+                       ),
+                       'extmetadatamultilang'
+                               =>'If translations for extmetadata property are available, fetch all of them.',
+                       'extmetadatafilter'
+                               => "If specified and non-empty, only these keys will be returned for {$p}prop=extmetadata",
+                       'continue' => 'If the query response includes a continue value, ' .
+                               'use it here to get another page of results',
                        'localonly' => 'Look only for files in the local repository',
                );
        }
@@ -725,6 +807,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                )
                        ),
                );
+
                return array_diff_key( $props, array_flip( $filter ) );
        }
 
@@ -738,6 +821,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
        public function getPossibleErrors() {
                $p = $this->getModulePrefix();
+
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ),
                        array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ),
@@ -748,7 +832,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
        public function getExamples() {
                return array(
                        'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo',
-                       'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&iiend=20071231235959&iiprop=timestamp|user|url',
+                       'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&' .
+                               'iiend=20071231235959&iiprop=timestamp|user|url',
                );
        }
 
index f2bf0a7..a32fb9e 100644 (file)
@@ -79,9 +79,9 @@ class ApiQueryImages extends ApiQueryGeneratorBase {
                        $this->addOption( 'ORDER BY', 'il_to' . $sort );
                } else {
                        $this->addOption( 'ORDER BY', array(
-                                               'il_from' . $sort,
-                                               'il_to' . $sort
-                       ));
+                               'il_from' . $sort,
+                               'il_to' . $sort
+                       ) );
                }
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
 
@@ -164,7 +164,8 @@ class ApiQueryImages extends ApiQueryGeneratorBase {
                return array(
                        'limit' => 'How many images to return',
                        'continue' => 'When more results are available, use this to continue',
-                       'images' => 'Only list these images. Useful for checking whether a certain page has a certain Image.',
+                       'images' => 'Only list these images. Useful for checking whether a ' .
+                               'certain page has a certain Image.',
                        'dir' => 'The direction in which to list',
                );
        }
@@ -184,8 +185,10 @@ class ApiQueryImages extends ApiQueryGeneratorBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=images&titles=Main%20Page' => 'Get a list of images used in the [[Main Page]]',
-                       'api.php?action=query&generator=images&titles=Main%20Page&prop=info' => 'Get information about all images used in the [[Main Page]]',
+                       'api.php?action=query&prop=images&titles=Main%20Page'
+                               => 'Get a list of images used in the [[Main Page]]',
+                       'api.php?action=query&generator=images&titles=Main%20Page&prop=info'
+                               => 'Get information about all images used in the [[Main Page]]',
                );
        }
 
index 017684e..43b8c0c 100644 (file)
@@ -42,7 +42,8 @@ class ApiQueryInfo extends ApiQueryBase {
        private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
                $pageLatest, $pageLength;
 
-       private $protections, $watched, $watchers, $notificationtimestamps, $talkids, $subjectids, $displaytitles;
+       private $protections, $watched, $watchers, $notificationtimestamps,
+               $talkids, $subjectids, $displaytitles;
        private $showZeroWatchers = false;
 
        private $tokenFunctions;
@@ -104,10 +105,11 @@ class ApiQueryInfo extends ApiQueryBase {
                        'watch' => array( 'ApiQueryInfo', 'getWatchToken' ),
                );
                wfRunHooks( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) );
+
                return $this->tokenFunctions;
        }
 
-       static $cachedTokens = array();
+       static protected $cachedTokens = array();
 
        public static function resetTokenCache() {
                ApiQueryInfo::$cachedTokens = array();
@@ -333,8 +335,8 @@ class ApiQueryInfo extends ApiQueryBase {
                        ), $pageid, $pageInfo );
                        if ( !$fit ) {
                                $this->setContinueEnumParameter( 'continue',
-                                               $title->getNamespace() . '|' .
-                                               $title->getText() );
+                                       $title->getNamespace() . '|' .
+                                       $title->getText() );
                                break;
                        }
                }
@@ -348,7 +350,8 @@ class ApiQueryInfo extends ApiQueryBase {
         */
        private function extractPageInfo( $pageid, $title ) {
                $pageInfo = array();
-               $titleExists = $pageid > 0; //$title->exists() needs pageid, which is not set for all title objects
+               // $title->exists() needs pageid, which is not set for all title objects
+               $titleExists = $pageid > 0;
                $ns = $title->getNamespace();
                $dbkey = $title->getDBkey();
 
@@ -410,7 +413,8 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( $this->fld_notificationtimestamp ) {
                        $pageInfo['notificationtimestamp'] = '';
                        if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
-                               $pageInfo['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] );
+                               $pageInfo['notificationtimestamp'] =
+                                       wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] );
                        }
                }
 
@@ -465,7 +469,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->resetQueryParams();
                        $this->addTables( 'page_restrictions' );
                        $this->addFields( array( 'pr_page', 'pr_type', 'pr_level',
-                                       'pr_expiry', 'pr_cascade' ) );
+                               'pr_expiry', 'pr_cascade' ) );
                        $this->addWhereFld( 'pr_page', array_keys( $this->titles ) );
 
                        $res = $this->select( __METHOD__ );
@@ -556,8 +560,8 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->resetQueryParams();
                        $this->addTables( array( 'page_restrictions', 'page', 'templatelinks' ) );
                        $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
-                                       'page_title', 'page_namespace',
-                                       'tl_title', 'tl_namespace' ) );
+                               'page_title', 'page_namespace',
+                               'tl_title', 'tl_namespace' ) );
                        $this->addWhere( $lb->constructSet( 'tl', $db ) );
                        $this->addWhere( 'pr_page = page_id' );
                        $this->addWhere( 'pr_page = tl_from' );
@@ -580,7 +584,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->resetQueryParams();
                        $this->addTables( array( 'page_restrictions', 'page', 'imagelinks' ) );
                        $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
-                                       'page_title', 'page_namespace', 'il_to' ) );
+                               'page_title', 'page_namespace', 'il_to' ) );
                        $this->addWhere( 'pr_page = page_id' );
                        $this->addWhere( 'pr_page = il_from' );
                        $this->addWhereFld( 'pr_cascade', 1 );
@@ -633,10 +637,10 @@ class ApiQueryInfo extends ApiQueryBase {
                foreach ( $res as $row ) {
                        if ( MWNamespace::isTalk( $row->page_namespace ) ) {
                                $this->talkids[MWNamespace::getSubject( $row->page_namespace )][$row->page_title] =
-                                               intval( $row->page_id );
+                                       intval( $row->page_id );
                        } else {
                                $this->subjectids[MWNamespace::getTalk( $row->page_namespace )][$row->page_title] =
-                                               intval( $row->page_id );
+                                       intval( $row->page_id );
                        }
                }
        }
@@ -697,7 +701,8 @@ class ApiQueryInfo extends ApiQueryBase {
                                $this->watched[$row->wl_namespace][$row->wl_title] = true;
                        }
                        if ( $this->fld_notificationtimestamp ) {
-                               $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
+                               $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] =
+                                       $row->wl_notificationtimestamp;
                        }
                }
        }
@@ -761,6 +766,7 @@ class ApiQueryInfo extends ApiQueryBase {
                if ( !is_null( $params['token'] ) ) {
                        return 'private';
                }
+
                return 'public';
        }
 
index 5bd451b..e6280c8 100644 (file)
@@ -92,14 +92,14 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
                                $this->addOption( 'ORDER BY', array(
                                        'll_title' . $sort,
                                        'll_from' . $sort
-                               ));
+                               ) );
                        }
                } else {
                        $this->addOption( 'ORDER BY', array(
                                'll_lang' . $sort,
                                'll_title' . $sort,
                                'll_from' . $sort
-                       ));
+                       ) );
                }
 
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
@@ -111,10 +111,14 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
                $count = 0;
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               // Continue string preserved in case the redirect query doesn't pass the limit
-                               $this->setContinueEnumParameter( 'continue', "{$row->ll_lang}|{$row->ll_title}|{$row->ll_from}" );
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here... Continue string
+                               // preserved in case the redirect query doesn't pass the limit.
+                               $this->setContinueEnumParameter(
+                                       'continue',
+                                       "{$row->ll_lang}|{$row->ll_title}|{$row->ll_from}"
+                               );
                                break;
                        }
 
@@ -140,7 +144,10 @@ class ApiQueryLangBacklinks extends ApiQueryGeneratorBase {
 
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $entry );
                                if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'continue', "{$row->ll_lang}|{$row->ll_title}|{$row->ll_from}" );
+                                       $this->setContinueEnumParameter(
+                                               'continue',
+                                               "{$row->ll_lang}|{$row->ll_title}|{$row->ll_from}"
+                                       );
                                        break;
                                }
                        }
index aa796e3..a20b855 100644 (file)
@@ -86,9 +86,9 @@ class ApiQueryLangLinks extends ApiQueryBase {
                                $this->addOption( 'ORDER BY', 'll_lang' . $sort );
                        } else {
                                $this->addOption( 'ORDER BY', array(
-                                                       'll_from' . $sort,
-                                                       'll_lang' . $sort
-                               ));
+                                       'll_from' . $sort,
+                                       'll_lang' . $sort
+                               ) );
                        }
                }
 
@@ -182,7 +182,8 @@ class ApiQueryLangLinks extends ApiQueryBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&prop=langlinks&titles=Main%20Page&redirects=' => 'Get interlanguage links from the [[Main Page]]',
+                       'api.php?action=query&prop=langlinks&titles=Main%20Page&redirects='
+                               => 'Get interlanguage links from the [[Main Page]]',
                );
        }
 
index 937f4f1..1eecbe2 100644 (file)
@@ -43,7 +43,8 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                                $this->prefix = 'pl';
                                $this->description = 'link';
                                $this->titlesParam = 'titles';
-                               $this->titlesParamDescription = 'Only list links to these titles. Useful for checking whether a certain page links to a certain title.';
+                               $this->titlesParamDescription = 'Only list links to these titles. Useful ' .
+                                       'for checking whether a certain page links to a certain title.';
                                $this->helpUrl = 'https://www.mediawiki.org/wiki/API:Properties#links_.2F_pl';
                                break;
                        case self::TEMPLATES:
@@ -51,7 +52,8 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                                $this->prefix = 'tl';
                                $this->description = 'template';
                                $this->titlesParam = 'templates';
-                               $this->titlesParamDescription = 'Only list these templates. Useful for checking whether a certain page uses a certain template.';
+                               $this->titlesParamDescription = 'Only list these templates. Useful ' .
+                                       'for checking whether a certain page uses a certain template.';
                                $this->helpUrl = 'https://www.mediawiki.org/wiki/API:Properties#templates_.2F_tl';
                                break;
                        default:
@@ -74,8 +76,7 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
        }
 
        /**
-        * @param $resultPageSet ApiPageSet
-        * @return
+        * @param ApiPageSet $resultPageSet
         */
        private function run( $resultPageSet = null ) {
                if ( $this->getPageSet()->getGoodTitleCount() == 0 ) {
@@ -212,6 +213,7 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
 
        public function getParamDescription() {
                $desc = $this->description;
+
                return array(
                        'namespace' => "Show {$desc}s in this namespace(s) only",
                        'limit' => "How many {$desc}s to return",
@@ -237,10 +239,13 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
        public function getExamples() {
                $desc = $this->description;
                $name = $this->getModuleName();
+
                return array(
                        "api.php?action=query&prop={$name}&titles=Main%20Page" => "Get {$desc}s from the [[Main Page]]",
-                       "api.php?action=query&generator={$name}&titles=Main%20Page&prop=info" => "Get information about the {$desc} pages in the [[Main Page]]",
-                       "api.php?action=query&prop={$name}&titles=Main%20Page&{$this->prefix}namespace=2|10" => "Get {$desc}s from the Main Page in the User and Template namespaces",
+                       "api.php?action=query&generator={$name}&titles=Main%20Page&prop=info"
+                               => "Get information about the {$desc} pages in the [[Main Page]]",
+                       "api.php?action=query&prop={$name}&titles=Main%20Page&{$this->prefix}namespace=2|10"
+                               => "Get {$desc}s from the Main Page in the User and Template namespaces",
                );
        }
 
index 1a2719e..0d2f475 100644 (file)
@@ -84,7 +84,10 @@ class ApiQueryLogEvents extends ApiQueryBase {
                $this->addFieldsIf( array( 'log_id', 'page_id' ), $this->fld_ids );
                $this->addFieldsIf( array( 'log_user', 'log_user_text', 'user_name' ), $this->fld_user );
                $this->addFieldsIf( 'log_user', $this->fld_userid );
-               $this->addFieldsIf( array( 'log_namespace', 'log_title' ), $this->fld_title || $this->fld_parsedcomment );
+               $this->addFieldsIf(
+                       array( 'log_namespace', 'log_title' ),
+                       $this->fld_title || $this->fld_parsedcomment
+               );
                $this->addFieldsIf( 'log_comment', $this->fld_comment || $this->fld_parsedcomment );
                $this->addFieldsIf( 'log_params', $this->fld_details );
 
@@ -96,7 +99,8 @@ class ApiQueryLogEvents extends ApiQueryBase {
 
                if ( !is_null( $params['tag'] ) ) {
                        $this->addTables( 'change_tag' );
-                       $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN', array( 'log_id=ct_log_id' ) ) ) );
+                       $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN',
+                               array( 'log_id=ct_log_id' ) ) ) );
                        $this->addWhereFld( 'ct_tag', $params['tag'] );
                        $index['change_tag'] = 'change_tag_tag_id';
                }
@@ -110,7 +114,12 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        $index['logging'] = 'type_time';
                }
 
-               $this->addTimestampWhereRange( 'log_timestamp', $params['dir'], $params['start'], $params['end'] );
+               $this->addTimestampWhereRange(
+                       'log_timestamp',
+                       $params['dir'],
+                       $params['start'],
+                       $params['end']
+               );
 
                $limit = $params['limit'];
                $this->addOption( 'LIMIT', $limit + 1 );
@@ -168,8 +177,9 @@ class ApiQueryLogEvents extends ApiQueryBase {
                $res = $this->select( __METHOD__ );
                $result = $this->getResult();
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->log_timestamp ) );
                                break;
                        }
@@ -197,7 +207,9 @@ class ApiQueryLogEvents extends ApiQueryBase {
         * @param $legacy bool
         * @return array
         */
-       public static function addLogParams( $result, &$vals, $params, $type, $action, $ts, $legacy = false ) {
+       public static function addLogParams( $result, &$vals, $params, $type,
+               $action, $ts, $legacy = false
+       ) {
                switch ( $type ) {
                        case 'move':
                                if ( $legacy ) {
@@ -285,6 +297,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        $result->setIndexedTagName_recursive( $logParams, 'param' );
                        $vals = array_merge( $vals, $logParams );
                }
+
                return $vals;
        }
 
@@ -392,6 +405,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
 
        public function getAllowedParams() {
                global $wgLogTypes, $wgLogActions, $wgLogActionsHandlers;
+
                return array(
                        'prop' => array(
                                ApiBase::PARAM_ISMULTI => true,
@@ -444,6 +458,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => array(
                                'Which properties to get',
@@ -473,6 +488,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
 
        public function getResultProperties() {
                global $wgLogTypes;
+
                return array(
                        'ids' => array(
                                'logid' => 'integer',
index a23ff06..469b297 100644 (file)
@@ -104,7 +104,7 @@ abstract class ApiQueryORM extends ApiQueryBase {
        protected function getParams() {
                return array_filter(
                        $this->extractRequestParams(),
-                       function( $prop ) {
+                       function ( $prop ) {
                                return isset( $prop );
                        }
                );
@@ -260,5 +260,4 @@ abstract class ApiQueryORM extends ApiQueryBase {
 
                return array_merge( $this->getTable()->getFieldDescriptions(), $descriptions );
        }
-
 }
index 08c883d..5438175 100644 (file)
@@ -63,7 +63,8 @@ class ApiQueryPagePropNames extends ApiQueryBase {
                $count = 0;
                foreach ( $this->select( __METHOD__ ) as $row ) {
                        if ( ++$count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->pp_propname );
                                break;
                        }
index 2de5710..e51c7ab 100644 (file)
@@ -115,6 +115,7 @@ class ApiQueryPageProps extends ApiQueryBase {
                if ( !$fit ) {
                        $this->setContinueEnumParameter( 'continue', $page );
                }
+
                return $fit;
        }
 
@@ -134,7 +135,8 @@ class ApiQueryPageProps extends ApiQueryBase {
        public function getParamDescription() {
                return array(
                        'continue' => 'When more results are available, use this to continue',
-                       'prop' => 'Only list these props. Useful for checking whether a certain page uses a certain page prop',
+                       'prop' => 'Only list these props. Useful for checking whether a ' .
+                               'certain page uses a certain page prop',
                );
        }
 
index 6f2f02e..e68eb56 100644 (file)
@@ -92,7 +92,8 @@ class ApiQueryPagesWithProp extends ApiQueryGeneratorBase {
                $count = 0;
                foreach ( $this->select( __METHOD__ ) as $row ) {
                        if ( ++$count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->page_id );
                                break;
                        }
@@ -178,8 +179,10 @@ class ApiQueryPagesWithProp extends ApiQueryGeneratorBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=query&list=pageswithprop&pwppropname=displaytitle&pwpprop=ids|title|value' => 'Get first 10 pages using {{DISPLAYTITLE:}}',
-                       'api.php?action=query&generator=pageswithprop&gpwppropname=notoc&prop=info' => 'Get page info about first 10 pages using __NOTOC__',
+                       'api.php?action=query&list=pageswithprop&pwppropname=displaytitle&pwpprop=ids|title|value'
+                               => 'Get first 10 pages using {{DISPLAYTITLE:}}',
+                       'api.php?action=query&generator=pageswithprop&gpwppropname=notoc&prop=info'
+                               => 'Get page info about first 10 pages using __NOTOC__',
                );
        }
 
index 222ad07..ea350ad 100644 (file)
@@ -80,8 +80,9 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
                $titles = array();
 
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->pt_timestamp ) );
                                break;
                        }
@@ -131,7 +132,10 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
                }
 
                if ( is_null( $resultPageSet ) ) {
-                       $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), $this->getModulePrefix() );
+                       $result->setIndexedTagName_internal(
+                               array( 'query', $this->getModuleName() ),
+                               $this->getModulePrefix()
+                       );
                } else {
                        $resultPageSet->populateFromTitles( $titles );
                }
@@ -148,6 +152,7 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
 
        public function getAllowedParams() {
                global $wgRestrictionLevels;
+
                return array(
                        'namespace' => array(
                                ApiBase::PARAM_ISMULTI => true,
@@ -216,6 +221,7 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
 
        public function getResultProperties() {
                global $wgRestrictionLevels;
+
                return array(
                        '' => array(
                                'ns' => 'namespace',
index 79fe049..88af62b 100644 (file)
@@ -126,7 +126,10 @@ class ApiQueryQueryPage extends ApiQueryGeneratorBase {
                        }
                }
                if ( is_null( $resultPageSet ) ) {
-                       $result->setIndexedTagName_internal( array( 'query', $this->getModuleName(), 'results' ), 'page' );
+                       $result->setIndexedTagName_internal(
+                               array( 'query', $this->getModuleName(), 'results' ),
+                               'page'
+                       );
                } else {
                        $resultPageSet->populateFromTitles( $titles );
                }
@@ -138,6 +141,7 @@ class ApiQueryQueryPage extends ApiQueryGeneratorBase {
                if ( $qp->getRestriction() != '' ) {
                        return 'private';
                }
+
                return 'public';
        }
 
index 2754bda..e990386 100644 (file)
@@ -30,9 +30,7 @@
  *
  * @ingroup API
  */
-
 class ApiQueryRandom extends ApiQueryGeneratorBase {
-
        private $pageIDs;
 
        public function __construct( $query, $moduleName ) {
@@ -83,8 +81,8 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
                                // Prevent duplicates
                                if ( !in_array( $row->page_id, $this->pageIDs ) ) {
                                        $fit = $this->getResult()->addValue(
-                                                       array( 'query', $this->getModuleName() ),
-                                                       null, $this->extractRowInfo( $row ) );
+                                               array( 'query', $this->getModuleName() ),
+                                               null, $this->extractRowInfo( $row ) );
                                        if ( !$fit ) {
                                                // We can't really query-continue a random list.
                                                // Return an insanely high value so
@@ -110,14 +108,26 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
                $result = $this->getResult();
                $this->pageIDs = array();
 
-               $this->prepareQuery( wfRandom(), $params['limit'], $params['namespace'], $resultPageSet, $params['redirect'] );
+               $this->prepareQuery(
+                       wfRandom(),
+                       $params['limit'],
+                       $params['namespace'],
+                       $resultPageSet,
+                       $params['redirect']
+               );
                $count = $this->runQuery( $resultPageSet );
                if ( $count < $params['limit'] ) {
                        /* We got too few pages, we probably picked a high value
                         * for page_random. We'll just take the lowest ones, see
                         * also the comment in Title::getRandomTitle()
                         */
-                       $this->prepareQuery( 0, $params['limit'] - $count, $params['namespace'], $resultPageSet, $params['redirect'] );
+                       $this->prepareQuery(
+                               0,
+                               $params['limit'] - $count,
+                               $params['namespace'],
+                               $resultPageSet,
+                               $params['redirect']
+                       );
                        $this->runQuery( $resultPageSet );
                }
 
@@ -131,6 +141,7 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
                $vals = array();
                $vals['id'] = intval( $row->page_id );
                ApiQueryBase::addTitleInfo( $vals, $title );
+
                return $vals;
        }
 
@@ -176,9 +187,12 @@ class ApiQueryRandom extends ApiQueryGeneratorBase {
        public function getDescription() {
                return array(
                        'Get a set of random pages',
-                       'NOTE: Pages are listed in a fixed sequence, only the starting point is random. This means that if, for example, "Main Page" is the first ',
-                       '      random page on your list, "List of fictional monkeys" will *always* be second, "List of people on stamps of Vanuatu" third, etc',
-                       'NOTE: If the number of pages in the namespace is lower than rnlimit, you will get fewer pages. You will not get the same page twice'
+                       'NOTE: Pages are listed in a fixed sequence, only the starting point is random.',
+                       '      This means that if, for example, "Main Page" is the first random page on',
+                       '      your list, "List of fictional monkeys" will *always* be second, "List of',
+                       '      people on stamps of Vanuatu" third, etc',
+                       'NOTE: If the number of pages in the namespace is lower than rnlimit, you will',
+                       '      get fewer pages. You will not get the same page twice'
                );
        }
 
index 6b10bdc..653feab 100644 (file)
@@ -37,9 +37,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        }
 
        private $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
-                       $fld_flags = false, $fld_timestamp = false, $fld_title = false, $fld_ids = false,
-                       $fld_sizes = false, $fld_redirect = false, $fld_patrolled = false, $fld_loginfo = false,
-                       $fld_tags = false, $fld_sha1 = false, $token = array();
+               $fld_flags = false, $fld_timestamp = false, $fld_title = false, $fld_ids = false,
+               $fld_sizes = false, $fld_redirect = false, $fld_patrolled = false, $fld_loginfo = false,
+               $fld_tags = false, $fld_sha1 = false, $token = array();
 
        private $tokenFunctions;
 
@@ -64,6 +64,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        'patrol' => array( 'ApiQueryRecentChanges', 'getPatrolToken' )
                );
                wfRunHooks( 'APIQueryRecentChangesTokens', array( &$this->tokenFunctions ) );
+
                return $this->tokenFunctions;
        }
 
@@ -71,7 +72,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
         * @param  $pageid
         * @param  $title
         * @param $rc RecentChange (optional)
-        * @return bool|String
+        * @return bool|string
         */
        public static function getPatrolToken( $pageid, $title, $rc = null ) {
                global $wgUser;
@@ -80,27 +81,26 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                if ( $rc ) {
                        if ( ( $wgUser->useRCPatrol() && $rc->getAttribute( 'rc_type' ) == RC_EDIT ) ||
-                               ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW ) )
-                       {
-                               $validTokenUser = true;
-                       }
-               } else {
-                       if ( $wgUser->useRCPatrol() || $wgUser->useNPPatrol() ) {
+                               ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW )
+                       ) {
                                $validTokenUser = true;
                        }
+               } elseif ( $wgUser->useRCPatrol() || $wgUser->useNPPatrol() ) {
+                       $validTokenUser = true;
                }
 
                if ( $validTokenUser ) {
                        // The patrol token is always the same, let's exploit that
                        static $cachedPatrolToken = null;
+
                        if ( is_null( $cachedPatrolToken ) ) {
                                $cachedPatrolToken = $wgUser->getEditToken( 'patrol' );
                        }
+
                        return $cachedPatrolToken;
-               } else {
-                       return false;
                }
 
+               return false;
        }
 
        /**
@@ -155,7 +155,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $cont = explode( '|', $params['continue'] );
                        if ( count( $cont ) != 2 ) {
                                $this->dieUsage( 'Invalid continue param. You should pass the ' .
-                                                               'original value returned by the previous query', '_badcontinue' );
+                                       'original value returned by the previous query', '_badcontinue' );
                        }
 
                        $timestamp = $this->getDB()->addQuotes( wfTimestamp( TS_MW, $cont[0] ) );
@@ -187,18 +187,26 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                        /* Check for conflicting parameters. */
                        if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
-                                       || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
-                                       || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
-                                       || ( isset( $show['redirect'] ) && isset( $show['!redirect'] ) )
-                                       || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
+                               || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
+                               || ( isset( $show['redirect'] ) && isset( $show['!redirect'] ) )
+                               || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['patrolled'] ) && isset( $show['unpatrolled'] ) )
+                               || ( isset( $show['!patrolled'] ) && isset( $show['unpatrolled'] ) )
                        ) {
                                $this->dieUsageMsg( 'show' );
                        }
 
                        // Check permissions
-                       if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
+                       if ( isset( $show['patrolled'] )
+                               || isset( $show['!patrolled'] )
+                               || isset( $show['unpatrolled'] )
+                       ) {
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                                       $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
+                                       $this->dieUsage(
+                                               'You need the patrol right to request the patrolled flag',
+                                               'permissiondenied'
+                                       );
                                }
                        }
 
@@ -213,8 +221,21 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
                        $this->addWhereIf( 'page_is_redirect = 1', isset( $show['redirect'] ) );
 
+                       if ( isset( $show['unpatrolled'] ) ) {
+                               // See ChangesList:isUnpatrolled
+                               if ( $user->useRCPatrol() ) {
+                                       $this->addWhere( 'rc_patrolled = 0' );
+                               } elseif ( $user->useNPPatrol() ) {
+                                       $this->addWhere( 'rc_patrolled = 0' );
+                                       $this->addWhereFld( 'rc_type', RC_NEW );
+                               }
+                       }
+
                        // Don't throw log entries out the window here
-                       $this->addWhereIf( 'page_is_redirect = 0 OR page_is_redirect IS NULL', isset( $show['!redirect'] ) );
+                       $this->addWhereIf(
+                               'page_is_redirect = 0 OR page_is_redirect IS NULL',
+                               isset( $show['!redirect'] )
+                       );
                }
 
                if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
@@ -252,7 +273,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $this->initProperties( $prop );
 
                        if ( $this->fld_patrolled && !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                               $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
+                               $this->dieUsage(
+                                       'You need the patrol right to request the patrolled flag',
+                                       'permissiondenied'
+                               );
                        }
 
                        $this->addFields( 'rc_id' );
@@ -264,8 +288,12 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $this->addFieldsIf( array( 'rc_minor', 'rc_type', 'rc_bot' ), $this->fld_flags );
                        $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
                        $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
-                       $this->addFieldsIf( array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ), $this->fld_loginfo );
-                       $showRedirects = $this->fld_redirect || isset( $show['redirect'] ) || isset( $show['!redirect'] );
+                       $this->addFieldsIf(
+                               array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ),
+                               $this->fld_loginfo
+                       );
+                       $showRedirects = $this->fld_redirect || isset( $show['redirect'] )
+                               || isset( $show['!redirect'] );
                }
 
                if ( $this->fld_tags ) {
@@ -276,13 +304,15 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                if ( $this->fld_sha1 ) {
                        $this->addTables( 'revision' );
-                       $this->addJoinConds( array( 'revision' => array( 'LEFT JOIN', array( 'rc_this_oldid=rev_id' ) ) ) );
+                       $this->addJoinConds( array( 'revision' => array( 'LEFT JOIN',
+                               array( 'rc_this_oldid=rev_id' ) ) ) );
                        $this->addFields( array( 'rev_sha1', 'rev_deleted' ) );
                }
 
                if ( $params['toponly'] || $showRedirects ) {
                        $this->addTables( 'page' );
-                       $this->addJoinConds( array( 'page' => array( 'LEFT JOIN', array( 'rc_namespace=page_namespace', 'rc_title=page_title' ) ) ) );
+                       $this->addJoinConds( array( 'page' => array( 'LEFT JOIN',
+                               array( 'rc_namespace=page_namespace', 'rc_title=page_title' ) ) ) );
                        $this->addFields( 'page_is_redirect' );
 
                        if ( $params['toponly'] ) {
@@ -311,9 +341,13 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                /* Iterate through the rows, adding data extracted from them to our query result. */
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter( 'continue', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id );
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
+                               $this->setContinueEnumParameter(
+                                       'continue',
+                                       wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id
+                               );
                                break;
                        }
 
@@ -327,7 +361,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                }
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
                                if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'continue', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id );
+                                       $this->setContinueEnumParameter(
+                                               'continue',
+                                               wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) . '|' . $row->rc_id
+                                       );
                                        break;
                                }
                        } else {
@@ -456,6 +493,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        $vals['patrolled'] = '';
                }
 
+               if ( $this->fld_patrolled && ChangesList::isUnpatrolled( $row, $this->getUser() ) ) {
+                       $vals['unpatrolled'] = '';
+               }
+
                if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) {
                        $vals['logid'] = intval( $row->rc_logid );
                        $vals['logtype'] = $row->rc_log_type;
@@ -516,6 +557,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        foreach ( $type as $t ) {
                                $retval[] = $this->parseRCType( $t );
                        }
+
                        return $retval;
                }
                switch ( $type ) {
@@ -545,6 +587,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        // formatComment() calls wfMessage() among other things
                        return 'anon-public-user-private';
                }
+
                return 'public';
        }
 
@@ -610,7 +653,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                        'redirect',
                                        '!redirect',
                                        'patrolled',
-                                       '!patrolled'
+                                       '!patrolled',
+                                       'unpatrolled'
                                )
                        ),
                        'limit' => array(
@@ -636,6 +680,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'start' => 'The timestamp to start enumerating from',
                        'end' => 'The timestamp to end enumerating',
@@ -655,7 +700,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                ' ids            - Adds the page ID, recent changes ID and the new and old revision ID',
                                ' sizes          - Adds the new and old page length in bytes',
                                ' redirect       - Tags edit if page is a redirect',
-                               ' patrolled      - Tags edits that have been patrolled',
+                               ' patrolled      - Tags patrollable edits as being patrolled or unpatrolled',
                                ' loginfo        - Adds log information (logid, logtype, etc) to log entries',
                                ' tags           - Lists tags for the entry',
                                ' sha1           - Adds the content checksum for entries associated with a revision',
@@ -741,7 +786,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                'redirect' => 'boolean'
                        ),
                        'patrolled' => array(
-                               'patrolled' => 'boolean'
+                               'patrolled' => 'boolean',
+                               'unpatrolled' => 'boolean'
                        ),
                        'loginfo' => array(
                                'logid' => array(
@@ -781,7 +827,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'show' ),
-                       array( 'code' => 'permissiondenied', 'info' => 'You need the patrol right to request the patrolled flag' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You need the patrol right to request the patrolled flag'
+                       ),
                        array( 'code' => 'user-excludeuser', 'info' => 'user and excludeuser cannot be used together' ),
                ) );
        }
index 415288e..86351c0 100644 (file)
  */
 
 /**
- * A query action to enumerate revisions of a given page, or show top revisions of multiple pages.
- * Various pieces of information may be shown - flags, comments, and the actual wiki markup of the rev.
- * In the enumeration mode, ranges of revisions may be requested and filtered.
+ * A query action to enumerate revisions of a given page, or show top revisions
+ * of multiple pages. Various pieces of information may be shown - flags,
+ * comments, and the actual wiki markup of the rev. In the enumeration mode,
+ * ranges of revisions may be requested and filtered.
  *
  * @ingroup API
  */
@@ -40,9 +41,10 @@ class ApiQueryRevisions extends ApiQueryBase {
                parent::__construct( $query, $moduleName, 'rv' );
        }
 
-       private $fld_ids = false, $fld_flags = false, $fld_timestamp = false, $fld_size = false, $fld_sha1 = false,
-                       $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
-                       $fld_content = false, $fld_tags = false, $fld_contentmodel = false;
+       private $fld_ids = false, $fld_flags = false, $fld_timestamp = false,
+               $fld_size = false, $fld_sha1 = false, $fld_comment = false,
+               $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
+               $fld_content = false, $fld_tags = false, $fld_contentmodel = false;
 
        private $tokenFunctions;
 
@@ -65,6 +67,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'rollback' => array( 'ApiQueryRevisions', 'getRollbackToken' )
                );
                wfRunHooks( 'APIQueryRevisionsTokens', array( &$this->tokenFunctions ) );
+
                return $this->tokenFunctions;
        }
 
@@ -79,6 +82,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                if ( !$wgUser->isAllowed( 'rollback' ) ) {
                        return false;
                }
+
                return $wgUser->getEditToken(
                        array( $title->getPrefixedText(), $rev->getUserText() ) );
        }
@@ -91,9 +95,9 @@ class ApiQueryRevisions extends ApiQueryBase {
                // Enumerating revisions on multiple pages make it extremely
                // difficult to manage continuations and require additional SQL indexes
                $enumRevMode = ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ||
-                               !is_null( $params['limit'] ) || !is_null( $params['startid'] ) ||
-                               !is_null( $params['endid'] ) || $params['dir'] === 'newer' ||
-                               !is_null( $params['start'] ) || !is_null( $params['end'] ) );
+                       !is_null( $params['limit'] ) || !is_null( $params['startid'] ) ||
+                       !is_null( $params['endid'] ) || $params['dir'] === 'newer' ||
+                       !is_null( $params['start'] ) || !is_null( $params['end'] ) );
 
                $pageSet = $this->getPageSet();
                $pageCount = $pageSet->getGoodTitleCount();
@@ -105,11 +109,20 @@ class ApiQueryRevisions extends ApiQueryBase {
                }
 
                if ( $revCount > 0 && $enumRevMode ) {
-                       $this->dieUsage( 'The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).', 'revids' );
+                       $this->dieUsage(
+                               'The revids= parameter may not be used with the list options ' .
+                                       '(limit, startid, endid, dirNewer, start, end).',
+                               'revids'
+                       );
                }
 
                if ( $pageCount > 1 && $enumRevMode ) {
-                       $this->dieUsage( 'titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start and end parameters may only be used on a single page.', 'multpages' );
+                       $this->dieUsage(
+                               'titles, pageids or a generator was used to supply multiple pages, ' .
+                                       'but the limit, startid, endid, dirNewer, user, excludeuser, start ' .
+                                       'and end parameters may only be used on a single page.',
+                               'multpages'
+                       );
                }
 
                if ( !is_null( $params['difftotext'] ) ) {
@@ -119,8 +132,12 @@ class ApiQueryRevisions extends ApiQueryBase {
                                $params['diffto'] = 0;
                        }
                        if ( ( !ctype_digit( $params['diffto'] ) || $params['diffto'] < 0 )
-                                       && $params['diffto'] != 'prev' && $params['diffto'] != 'next' ) {
-                               $this->dieUsage( 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"', 'diffto' );
+                               && $params['diffto'] != 'prev' && $params['diffto'] != 'next'
+                       ) {
+                               $this->dieUsage(
+                                       'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"',
+                                       'diffto'
+                               );
                        }
                        // Check whether the revision exists and is readable,
                        // DifferenceEngine returns a rather ambiguous empty
@@ -181,13 +198,17 @@ class ApiQueryRevisions extends ApiQueryBase {
                if ( isset( $prop['tags'] ) ) {
                        $this->fld_tags = true;
                        $this->addTables( 'tag_summary' );
-                       $this->addJoinConds( array( 'tag_summary' => array( 'LEFT JOIN', array( 'rev_id=ts_rev_id' ) ) ) );
+                       $this->addJoinConds(
+                               array( 'tag_summary' => array( 'LEFT JOIN', array( 'rev_id=ts_rev_id' ) ) )
+                       );
                        $this->addFields( 'ts_tags' );
                }
 
                if ( !is_null( $params['tag'] ) ) {
                        $this->addTables( 'change_tag' );
-                       $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) ) );
+                       $this->addJoinConds(
+                               array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) )
+                       );
                        $this->addWhereFld( 'ct_tag', $params['tag'] );
                        $index['change_tag'] = 'change_tag_tag_id';
                }
@@ -349,7 +370,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                        $this->addOption( 'ORDER BY', array(
                                'rev_page',
                                'rev_id'
-                       ));
+                       ) );
 
                        // assumption testing -- we should never get more then $pageCount rows.
                        $limit = $pageCount;
@@ -364,8 +385,9 @@ class ApiQueryRevisions extends ApiQueryBase {
                $res = $this->select( __METHOD__ );
 
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                if ( !$enumRevMode ) {
                                        ApiBase::dieDebug( __METHOD__, 'Got more rows then expected' ); // bug report
                                }
@@ -497,7 +519,10 @@ class ApiQueryRevisions extends ApiQueryBase {
                        if ( $content && $this->section !== false ) {
                                $content = $content->getSection( $this->section, false );
                                if ( !$content ) {
-                                       $this->dieUsage( "There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection' );
+                                       $this->dieUsage(
+                                               "There is no section {$this->section} in r" . $revision->getId(),
+                                               'nosuchsection'
+                                       );
                                }
                        }
                }
@@ -508,7 +533,11 @@ class ApiQueryRevisions extends ApiQueryBase {
                                if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
                                        $t = $content->getNativeData(); # note: don't set $text
 
-                                       $wgParser->startExternalParse( $title, ParserOptions::newFromContext( $this->getContext() ), OT_PREPROCESS );
+                                       $wgParser->startExternalParse(
+                                               $title,
+                                               ParserOptions::newFromContext( $this->getContext() ),
+                                               OT_PREPROCESS
+                                       );
                                        $dom = $wgParser->preprocessToDom( $t );
                                        if ( is_callable( array( $dom, 'saveXML' ) ) ) {
                                                $xml = $dom->saveXML();
@@ -518,8 +547,8 @@ class ApiQueryRevisions extends ApiQueryBase {
                                        $vals['parsetree'] = $xml;
                                } else {
                                        $this->setWarning( "Conversion to XML is supported for wikitext only, " .
-                                                                               $title->getPrefixedDBkey() .
-                                                                               " uses content model " . $content->getModel() );
+                                               $title->getPrefixedDBkey() .
+                                               " uses content model " . $content->getModel() );
                                }
                        }
 
@@ -528,7 +557,11 @@ class ApiQueryRevisions extends ApiQueryBase {
                                if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
                                        $text = $content->getNativeData();
 
-                                       $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
+                                       $text = $wgParser->preprocess(
+                                               $text,
+                                               $title,
+                                               ParserOptions::newFromContext( $this->getContext() )
+                                       );
                                } else {
                                        $this->setWarning( "Template expansion is supported for wikitext only, " .
                                                $title->getPrefixedDBkey() .
@@ -538,7 +571,11 @@ class ApiQueryRevisions extends ApiQueryBase {
                                }
                        }
                        if ( $this->parseContent ) {
-                               $po = $content->getParserOutput( $title, $revision->getId(), ParserOptions::newFromContext( $this->getContext() ) );
+                               $po = $content->getParserOutput(
+                                       $title,
+                                       $revision->getId(),
+                                       ParserOptions::newFromContext( $this->getContext() )
+                               );
                                $text = $po->getText();
                        }
 
@@ -550,7 +587,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                        $name = $title->getPrefixedDBkey();
 
                                        $this->dieUsage( "The requested format {$this->contentFormat} is not supported " .
-                                                                       "for content model $model used by $name", 'badformat' );
+                                               "for content model $model used by $name", 'badformat' );
                                }
 
                                $text = $content->serialize( $format );
@@ -588,15 +625,21 @@ class ApiQueryRevisions extends ApiQueryBase {
                                        $model = $title->getContentModel();
 
                                        if ( $this->contentFormat
-                                               && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat ) ) {
+                                               && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat )
+                                       ) {
 
                                                $name = $title->getPrefixedDBkey();
 
                                                $this->dieUsage( "The requested format {$this->contentFormat} is not supported for " .
-                                                                                       "content model $model used by $name", 'badformat' );
+                                                       "content model $model used by $name", 'badformat' );
                                        }
 
-                                       $difftocontent = ContentHandler::makeContent( $this->difftotext, $title, $model, $this->contentFormat );
+                                       $difftocontent = ContentHandler::makeContent(
+                                               $this->difftotext,
+                                               $title,
+                                               $model,
+                                               $this->contentFormat
+                                       );
 
                                        $engine = $handler->createDifferenceEngine( $context );
                                        $engine->setContent( $content, $difftocontent );
@@ -614,6 +657,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                $vals['diff']['notcached'] = '';
                        }
                }
+
                return $vals;
        }
 
@@ -625,6 +669,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                        // formatComment() calls wfMessage() among other things
                        return 'anon-public-user-private';
                }
+
                return 'public';
        }
 
@@ -700,6 +745,7 @@ class ApiQueryRevisions extends ApiQueryBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => array(
                                'Which properties to get for each revision:',
@@ -733,8 +779,11 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'continue' => 'When more results are available, use this to continue',
                        'diffto' => array( 'Revision ID to diff each revision to.',
                                'Use "prev", "next" and "cur" for the previous, next and current revision respectively' ),
-                       'difftotext' => array( 'Text to diff each revision to. Only diffs a limited number of revisions.',
-                               "Overrides {$p}diffto. If {$p}section is set, only that section will be diffed against this text" ),
+                       'difftotext' => array(
+                               'Text to diff each revision to. Only diffs a limited number of revisions.',
+                               "Overrides {$p}diffto. If {$p}section is set, only that section will be",
+                               'diffed against this text',
+                       ),
                        'tag' => 'Only list revisions tagged with this tag',
                        'contentformat' => 'Serialization format used for difftotext and expected for output of content',
                );
@@ -818,35 +867,50 @@ class ApiQueryRevisions extends ApiQueryBase {
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'nosuchrevid', 'diffto' ),
-                       array( 'code' => 'revids', 'info' => 'The revids= parameter may not be used with the list options '
-                                       . '(limit, startid, endid, dirNewer, start, end).' ),
-                       array( 'code' => 'multpages', 'info' => 'titles, pageids or a generator was used to supply multiple pages, '
+                       array(
+                               'code' => 'revids',
+                               'info' => 'The revids= parameter may not be used with the list options '
+                                       . '(limit, startid, endid, dirNewer, start, end).'
+                       ),
+                       array(
+                               'code' => 'multpages',
+                               'info' => 'titles, pageids or a generator was used to supply multiple pages, '
                                        . ' but the limit, startid, endid, dirNewer, user, excludeuser, '
-                                       . 'start and end parameters may only be used on a single page.' ),
-                       array( 'code' => 'diffto', 'info' => 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"' ),
+                                       . 'start and end parameters may only be used on a single page.'
+                       ),
+                       array(
+                               'code' => 'diffto',
+                               'info' => 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"'
+                       ),
                        array( 'code' => 'badparams', 'info' => 'start and startid cannot be used together' ),
                        array( 'code' => 'badparams', 'info' => 'end and endid cannot be used together' ),
                        array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together' ),
                        array( 'code' => 'nosuchsection', 'info' => 'There is no section section in rID' ),
                        array( 'code' => 'badformat', 'info' => 'The requested serialization format can not be applied '
-                                                                                                       . ' to the page\'s content model' ),
+                               . ' to the page\'s content model' ),
                ) );
        }
 
        public function getExamples() {
                return array(
                        'Get data with content for the last revision of titles "API" and "Main Page"',
-                       '  api.php?action=query&prop=revisions&titles=API|Main%20Page&rvprop=timestamp|user|comment|content',
+                       '  api.php?action=query&prop=revisions&titles=API|Main%20Page&' .
+                               'rvprop=timestamp|user|comment|content',
                        'Get last 5 revisions of the "Main Page"',
-                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&rvprop=timestamp|user|comment',
+                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&' .
+                               'rvprop=timestamp|user|comment',
                        'Get first 5 revisions of the "Main Page"',
-                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&rvprop=timestamp|user|comment&rvdir=newer',
+                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&' .
+                               'rvprop=timestamp|user|comment&rvdir=newer',
                        'Get first 5 revisions of the "Main Page" made after 2006-05-01',
-                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&rvprop=timestamp|user|comment&rvdir=newer&rvstart=20060501000000',
+                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&' .
+                               'rvprop=timestamp|user|comment&rvdir=newer&rvstart=20060501000000',
                        'Get first 5 revisions of the "Main Page" that were not made made by anonymous user "127.0.0.1"',
-                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&rvprop=timestamp|user|comment&rvexcludeuser=127.0.0.1',
+                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&' .
+                               'rvprop=timestamp|user|comment&rvexcludeuser=127.0.0.1',
                        'Get first 5 revisions of the "Main Page" that were made by the user "MediaWiki default"',
-                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&rvprop=timestamp|user|comment&rvuser=MediaWiki%20default',
+                       '  api.php?action=query&prop=revisions&titles=Main%20Page&rvlimit=5&' .
+                               'rvprop=timestamp|user|comment&rvuser=MediaWiki%20default',
                );
        }
 
index 36b5597..4fedebc 100644 (file)
@@ -112,12 +112,12 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                        $totalhits = $matches->getTotalHits();
                        if ( $totalhits !== null ) {
                                $apiResult->addValue( array( 'query', 'searchinfo' ),
-                                               'totalhits', $totalhits );
+                                       'totalhits', $totalhits );
                        }
                }
                if ( isset( $searchInfo['suggestion'] ) && $matches->hasSuggestion() ) {
                        $apiResult->addValue( array( 'query', 'searchinfo' ),
-                                               'suggestion', $matches->getSuggestionQuery() );
+                               'suggestion', $matches->getSuggestionQuery() );
                }
 
                // Add the search results to the result
@@ -127,8 +127,9 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                $result = $matches->next();
 
                while ( $result ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional items to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional items to be had. Stop here...
                                $this->setContinueEnumParameter( 'offset', $params['offset'] + $params['limit'] );
                                break;
                        }
@@ -184,7 +185,7 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
 
                                // Add item to results and see whether it fits
                                $fit = $apiResult->addValue( array( 'query', $this->getModuleName() ),
-                                               null, $vals );
+                                       null, $vals );
                                if ( !$fit ) {
                                        $this->setContinueEnumParameter( 'offset', $params['offset'] + $count - 1 );
                                        break;
@@ -198,8 +199,8 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
 
                if ( is_null( $resultPageSet ) ) {
                        $apiResult->setIndexedTagName_internal( array(
-                                               'query', $this->getModuleName()
-                                       ), 'p' );
+                               'query', $this->getModuleName()
+                       ), 'p' );
                } else {
                        $resultPageSet->populateFromTitles( $titles );
                }
index a776706..1c188da 100644 (file)
@@ -106,7 +106,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                // Abuse siprop as a query-continue parameter
                                // and set it to all unprocessed props
                                $this->setContinueEnumParameter( 'prop', implode( '|',
-                                               array_diff( $params['prop'], $done ) ) );
+                                       array_diff( $params['prop'], $done ) ) );
                                break;
                        }
                        $done[] = $p;
@@ -114,9 +114,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
        }
 
        protected function appendGeneralInfo( $property ) {
-               global $wgContLang,
-                       $wgDisableLangConversion,
-                       $wgDisableTitleConversion;
+               global $wgContLang, $wgDisableLangConversion, $wgDisableTitleConversion;
 
                $data = array();
                $mainPage = Title::newMainPage();
@@ -153,8 +151,12 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                if ( $wgContLang->linkPrefixExtension() ) {
-                       $data['linkprefix'] = wfMessage( 'linkprefix' )->inContentLanguage()->text();
+                       $linkPrefixCharset = $wgContLang->linkPrefixCharset();
+                       $data['linkprefixcharset'] = $linkPrefixCharset;
+                       // For backwards compatability
+                       $data['linkprefix'] = "/^((?>.*[^$linkPrefixCharset]|))(.+)$/sDu";
                } else {
+                       $data['linkprefixcharset'] = '';
                        $data['linkprefix'] = '';
                }
 
@@ -276,6 +278,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'ns' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -299,6 +302,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                sort( $data );
 
                $this->getResult()->setIndexedTagName( $data, 'ns' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -314,6 +318,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        }
                }
                $this->getResult()->setIndexedTagName( $data, 'specialpage' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -330,6 +335,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $arr;
                }
                $this->getResult()->setIndexedTagName( $data, 'magicword' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -357,7 +363,9 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        if ( $row['iw_local'] == '1' ) {
                                $val['local'] = '';
                        }
-                       // $val['trans'] = intval( $row['iw_trans'] ); // should this be exposed?
+                       if ( $row['iw_trans'] == '1' ) {
+                               $val['trans'] = '';
+                       }
                        if ( isset( $langNames[$prefix] ) ) {
                                $val['language'] = $langNames[$prefix];
                        }
@@ -373,6 +381,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'iw' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -382,7 +391,10 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $lb = wfGetLB();
                if ( $includeAll ) {
                        if ( !$wgShowHostnames ) {
-                               $this->dieUsage( 'Cannot view all servers info unless $wgShowHostnames is true', 'includeAllDenied' );
+                               $this->dieUsage(
+                                       'Cannot view all servers info unless $wgShowHostnames is true',
+                                       'includeAllDenied'
+                               );
                        }
 
                        $lags = $lb->getLagTimes();
@@ -404,6 +416,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                $result = $this->getResult();
                $result->setIndexedTagName( $data, 'db' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -444,7 +457,6 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                                if ( $group == 'user' ) {
                                        $arr['number'] = SiteStats::users();
-
                                // '*' and autopromote groups have no size
                                } elseif ( $group !== '*' && !isset( $wgAutopromote[$group] ) ) {
                                        $arr['number'] = SiteStats::numberInGroup( $group );
@@ -470,6 +482,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $result->setIndexedTagName( $data, 'group' );
+
                return $result->addValue( 'query', $property, $data );
        }
 
@@ -481,6 +494,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = array( 'ext' => $ext );
                }
                $this->getResult()->setIndexedTagName( $data, 'fe' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -515,18 +529,19 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                        $ret['url'] = $ext['url'];
                                }
                                if ( isset( $ext['version'] ) ) {
-                                               $ret['version'] = $ext['version'];
+                                       $ret['version'] = $ext['version'];
                                } elseif ( isset( $ext['svn-revision'] ) &&
                                        preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
-                                               $ext['svn-revision'], $m ) )
-                               {
-                                               $ret['version'] = 'r' . $m[1];
+                                               $ext['svn-revision'], $m )
+                               {
+                                       $ret['version'] = 'r' . $m[1];
                                }
                                $data[] = $ret;
                        }
                }
 
                $this->getResult()->setIndexedTagName( $data, 'ext' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -560,6 +575,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $lang;
                }
                $this->getResult()->setIndexedTagName( $data, 'lang' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -579,6 +595,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $skin;
                }
                $this->getResult()->setIndexedTagName( $data, 'skin' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -587,6 +604,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $wgParser->firstCallInit();
                $tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
                $this->getResult()->setIndexedTagName( $tags, 't' );
+
                return $this->getResult()->addValue( 'query', $property, $tags );
        }
 
@@ -595,12 +613,14 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $wgParser->firstCallInit();
                $hooks = $wgParser->getFunctionHooks();
                $this->getResult()->setIndexedTagName( $hooks, 'h' );
+
                return $this->getResult()->addValue( 'query', $property, $hooks );
        }
 
        public function appendVariables( $property ) {
                $variables = MagicWord::getVariableIDs();
                $this->getResult()->setIndexedTagName( $variables, 'v' );
+
                return $this->getResult()->addValue( 'query', $property, $variables );
        }
 
@@ -609,6 +629,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                // Make a copy of the global so we don't try to set the _element key of it - bug 45130
                $protocols = array_values( $wgUrlProtocols );
                $this->getResult()->setIndexedTagName( $protocols, 'p' );
+
                return $this->getResult()->addValue( 'query', $property, $protocols );
        }
 
@@ -633,6 +654,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'hook' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -681,6 +703,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => array(
                                'Which sysinfo properties to get:',
@@ -690,14 +713,14 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                ' specialpagealiases    - List of special page aliases',
                                ' magicwords            - List of magic words and their aliases',
                                ' statistics            - Returns site statistics',
-                               " interwikimap          - Returns interwiki map " .
+                               ' interwikimap          - Returns interwiki map ' .
                                        "(optionally filtered, (optionally localised by using {$p}inlanguagecode))",
                                ' dbrepllag             - Returns database server with the highest replication lag',
                                ' usergroups            - Returns user groups and the associated permissions',
                                ' extensions            - Returns extensions installed on the wiki',
                                ' fileextensions        - Returns list of file extensions allowed to be uploaded',
                                ' rightsinfo            - Returns wiki rights (license) information if available',
-                               " languages             - Returns a list of languages MediaWiki supports" .
+                               ' languages             - Returns a list of languages MediaWiki supports' .
                                        "(optionally localised by using {$p}inlanguagecode)",
                                ' skins                 - Returns a list of all enabled skins',
                                ' extensiontags         - Returns a list of parser extension tags',
@@ -709,7 +732,8 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
                        'showalldb' => 'List all database servers, not just the one lagging the most',
                        'numberingroup' => 'Lists the number of users in user groups',
-                       'inlanguagecode' => 'Language code for localised language names (best effort, use CLDR extension)',
+                       'inlanguagecode' => 'Language code for localised language names ' .
+                               '(best effort, use CLDR extension)',
                );
        }
 
index 6899375..248b3d8 100644 (file)
@@ -60,7 +60,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                                $result->addValue( array( 'query', $this->getModuleName() ), null, $imageInfo );
                                $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), $modulePrefix );
                        }
-               //TODO: update exception handling here to understand current getFile exceptions
+               // @todo Update exception handling here to understand current getFile exceptions
                } catch ( UploadStashNotAvailableException $e ) {
                        $this->dieUsage( "Session not available: " . $e->getMessage(), "nosession" );
                } catch ( UploadStashFileNotFoundException $e ) {
@@ -112,6 +112,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
         */
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => self::getPropertyDescriptions( $this->propertyFilter, $p ),
                        'filekey' => 'Key that identifies a previous upload that was stashed temporarily.',
@@ -134,8 +135,8 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
        public function getExamples() {
                return array(
                        'api.php?action=query&prop=stashimageinfo&siifilekey=124sd34rsdf567',
-                       'api.php?action=query&prop=stashimageinfo&siifilekey=b34edoe3|bceffd4&siiurlwidth=120&siiprop=url',
+                       'api.php?action=query&prop=stashimageinfo&siifilekey=b34edoe3|bceffd4&' .
+                               'siiurlwidth=120&siiprop=url',
                );
        }
-
 }
index 732df9a..33116ce 100644 (file)
@@ -38,7 +38,7 @@ class ApiQueryTags extends ApiQueryBase {
 
        private $limit;
        private $fld_displayname = false, $fld_description = false,
-                       $fld_hitcount = false;
+               $fld_hitcount = false;
 
        public function __construct( $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'tg' );
@@ -97,6 +97,7 @@ class ApiQueryTags extends ApiQueryBase {
 
                if ( ++$count > $this->limit ) {
                        $this->setContinueEnumParameter( 'continue', $tagName );
+
                        return false;
                }
 
@@ -121,6 +122,7 @@ class ApiQueryTags extends ApiQueryBase {
                $fit = $this->result->addValue( array( 'query', $this->getModuleName() ), null, $tag );
                if ( !$fit ) {
                        $this->setContinueEnumParameter( 'continue', $tagName );
+
                        return false;
                }
 
index 9a9be7b..6c7a57d 100644 (file)
@@ -37,8 +37,8 @@ class ApiQueryContributions extends ApiQueryBase {
 
        private $params, $prefixMode, $userprefix, $multiUserMode, $usernames, $parentLens;
        private $fld_ids = false, $fld_title = false, $fld_timestamp = false,
-                       $fld_comment = false, $fld_parsedcomment = false, $fld_flags = false,
-                       $fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
+               $fld_comment = false, $fld_parsedcomment = false, $fld_flags = false,
+               $fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
 
        public function execute() {
                // Parse some parameters
@@ -100,8 +100,9 @@ class ApiQueryContributions extends ApiQueryBase {
 
                // Fetch each row
                foreach ( $res as $row ) {
-                       if ( ++ $count > $limit ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                if ( $this->multiUserMode ) {
                                        $this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
                                } else {
@@ -122,7 +123,10 @@ class ApiQueryContributions extends ApiQueryBase {
                        }
                }
 
-               $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'item' );
+               $this->getResult()->setIndexedTagName_internal(
+                       array( 'query', $this->getModuleName() ),
+                       'item'
+               );
        }
 
        /**
@@ -177,7 +181,8 @@ class ApiQueryContributions extends ApiQueryBase {
                }
                // We only want pages by the specified users.
                if ( $this->prefixMode ) {
-                       $this->addWhere( 'rev_user_text' . $this->getDB()->buildLike( $this->userprefix, $this->getDB()->anyString() ) );
+                       $this->addWhere( 'rev_user_text' .
+                               $this->getDB()->buildLike( $this->userprefix, $this->getDB()->anyString() ) );
                } else {
                        $this->addWhereFld( 'rev_user_text', $this->usernames );
                }
@@ -195,7 +200,8 @@ class ApiQueryContributions extends ApiQueryBase {
                if ( !is_null( $show ) ) {
                        $show = array_flip( $show );
                        if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
-                                       || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) ) ) {
+                               || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                       ) {
                                $this->dieUsageMsg( 'show' );
                        }
 
@@ -220,9 +226,13 @@ class ApiQueryContributions extends ApiQueryBase {
                ) );
 
                if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
-                               $this->fld_patrolled ) {
+                       $this->fld_patrolled
+               ) {
                        if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                               $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
+                               $this->dieUsage(
+                                       'You need the patrol right to request the patrolled flag',
+                                       'permissiondenied'
+                               );
                        }
 
                        // Use a redundant join condition on both
@@ -260,13 +270,17 @@ class ApiQueryContributions extends ApiQueryBase {
 
                if ( $this->fld_tags ) {
                        $this->addTables( 'tag_summary' );
-                       $this->addJoinConds( array( 'tag_summary' => array( 'LEFT JOIN', array( 'rev_id=ts_rev_id' ) ) ) );
+                       $this->addJoinConds(
+                               array( 'tag_summary' => array( 'LEFT JOIN', array( 'rev_id=ts_rev_id' ) ) )
+                       );
                        $this->addFields( 'ts_tags' );
                }
 
                if ( isset( $this->params['tag'] ) ) {
                        $this->addTables( 'change_tag' );
-                       $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) ) );
+                       $this->addJoinConds(
+                               array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) )
+                       );
                        $this->addWhereFld( 'ct_tag', $this->params['tag'] );
                        $index['change_tag'] = 'change_tag_tag_id';
                }
@@ -346,8 +360,13 @@ class ApiQueryContributions extends ApiQueryBase {
                        $vals['size'] = intval( $row->rev_len );
                }
 
-               if ( $this->fld_sizediff && !is_null( $row->rev_len ) && !is_null( $row->rev_parent_id ) ) {
-                       $parentLen = isset( $this->parentLens[$row->rev_parent_id] ) ? $this->parentLens[$row->rev_parent_id] : 0;
+               if ( $this->fld_sizediff
+                       && !is_null( $row->rev_len )
+                       && !is_null( $row->rev_parent_id )
+               ) {
+                       $parentLen = isset( $this->parentLens[$row->rev_parent_id] )
+                               ? $this->parentLens[$row->rev_parent_id]
+                               : 0;
                        $vals['sizediff'] = intval( $row->rev_len - $parentLen );
                }
 
@@ -439,13 +458,17 @@ class ApiQueryContributions extends ApiQueryBase {
        public function getParamDescription() {
                global $wgRCMaxAge;
                $p = $this->getModulePrefix();
+
                return array(
                        'limit' => 'The maximum number of contributions to return',
                        'start' => 'The start timestamp to return from',
                        'end' => 'The end timestamp to return to',
                        'continue' => 'When more results are available, use this to continue',
                        'user' => 'The users to retrieve contributions for',
-                       'userprefix' => "Retrieve contributions for all users whose names begin with this value. Overrides {$p}user",
+                       'userprefix' => array(
+                               "Retrieve contributions for all users whose names begin with this value.",
+                               "Overrides {$p}user",
+                       ),
                        'dir' => $this->getDirectionDescription( $p ),
                        'namespace' => 'Only list contributions in these namespaces',
                        'prop' => array(
@@ -461,8 +484,11 @@ class ApiQueryContributions extends ApiQueryBase {
                                ' patrolled      - Tags patrolled edits',
                                ' tags           - Lists tags for the edit',
                        ),
-                       'show' => array( "Show only items that meet this criteria, e.g. non minor edits only: {$p}show=!minor",
-                                       "NOTE: if {$p}show=patrolled or {$p}show=!patrolled is set, revisions older than \$wgRCMaxAge ($wgRCMaxAge) won't be shown", ),
+                       'show' => array(
+                               "Show only items that meet thse criteria, e.g. non minor edits only: {$p}show=!minor",
+                               "NOTE: If {$p}show=patrolled or {$p}show=!patrolled is set, revisions older than",
+                               "\$wgRCMaxAge ($wgRCMaxAge) won't be shown",
+                       ),
                        'tag' => 'Only list revisions tagged with this tag',
                        'toponly' => 'Only list changes which are the latest revision',
                );
@@ -536,7 +562,10 @@ class ApiQueryContributions extends ApiQueryBase {
                        array( 'code' => 'param_user', 'info' => 'User parameter may not be empty.' ),
                        array( 'code' => 'param_user', 'info' => 'User name user is not valid' ),
                        array( 'show' ),
-                       array( 'code' => 'permissiondenied', 'info' => 'You need the patrol right to request the patrolled flag' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You need the patrol right to request the patrolled flag'
+                       ),
                ) );
        }
 
index 3c85ea6..37cf483 100644 (file)
@@ -152,6 +152,7 @@ class ApiQueryUserInfo extends ApiQueryBase {
                        $result->setIndexedTagName( $acceptLang, 'lang' );
                        $vals['acceptlang'] = $acceptLang;
                }
+
                return $vals;
        }
 
@@ -188,6 +189,7 @@ class ApiQueryUserInfo extends ApiQueryBase {
                                }
                        }
                }
+
                return $retval;
        }
 
@@ -232,7 +234,8 @@ class ApiQueryUserInfo extends ApiQueryBase {
                                '  ratelimits       - Lists all rate limits applying to the current user',
                                '  realname         - Adds the user\'s real name',
                                '  email            - Adds the user\'s email address and email authentication date',
-                               '  acceptlang       - Echoes the Accept-Language header sent by the client in a structured format',
+                               '  acceptlang       - Echoes the Accept-Language header sent by ' .
+                                       'the client in a structured format',
                                '  registrationdate - Adds the user\'s registration date',
                        )
                );
index dccfee6..cd4a8fc 100644 (file)
@@ -58,6 +58,7 @@ class ApiQueryUsers extends ApiQueryBase {
                        'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ),
                );
                wfRunHooks( 'APIQueryUsersTokens', array( &$this->tokenFunctions ) );
+
                return $this->tokenFunctions;
        }
 
@@ -67,6 +68,7 @@ class ApiQueryUsers extends ApiQueryBase {
         */
        public static function getUserrightsToken( $user ) {
                global $wgUser;
+
                // Since the permissions check for userrights is non-trivial,
                // don't bother with it here
                return $wgUser->getEditToken( $user->getName() );
@@ -90,10 +92,10 @@ class ApiQueryUsers extends ApiQueryBase {
                        if ( $n === false || $n === '' ) {
                                $vals = array( 'name' => $u, 'invalid' => '' );
                                $fit = $result->addValue( array( 'query', $this->getModuleName() ),
-                                               null, $vals );
+                                       null, $vals );
                                if ( !$fit ) {
                                        $this->setContinueEnumParameter( 'users',
-                                                       implode( '|', array_diff( $users, $done ) ) );
+                                               implode( '|', array_diff( $users, $done ) ) );
                                        $goodNames = array();
                                        break;
                                }
@@ -244,10 +246,10 @@ class ApiQueryUsers extends ApiQueryBase {
                        }
 
                        $fit = $result->addValue( array( 'query', $this->getModuleName() ),
-                                       null, $data[$u] );
+                               null, $data[$u] );
                        if ( !$fit ) {
                                $this->setContinueEnumParameter( 'users',
-                                               implode( '|', array_diff( $users, $done ) ) );
+                                       implode( '|', array_diff( $users, $done ) ) );
                                break;
                        }
                        $done[] = $u;
@@ -269,11 +271,7 @@ class ApiQueryUsers extends ApiQueryBase {
        }
 
        public function getCacheMode( $params ) {
-               if ( isset( $params['token'] ) ) {
-                       return 'private';
-               } else {
-                       return 'anon-public-user-private';
-               }
+               return isset( $params['token'] ) ? 'private' : 'anon-public-user-private';
        }
 
        public function getAllowedParams() {
@@ -312,7 +310,8 @@ class ApiQueryUsers extends ApiQueryBase {
                                '  rights         - Lists all the rights the user(s) has',
                                '  editcount      - Adds the user\'s edit count',
                                '  registration   - Adds the user\'s registration timestamp',
-                               '  emailable      - Tags if the user can and wants to receive email through [[Special:Emailuser]]',
+                               '  emailable      - Tags if the user can and wants to receive ' .
+                                       'email through [[Special:Emailuser]]',
                                '  gender         - Tags the gender of the user. Returns "male", "female", or "unknown"',
                        ),
                        'users' => 'A list of users to obtain the same information for',
index 22843f5..f9af75a 100644 (file)
@@ -44,9 +44,11 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                $this->run( $resultPageSet );
        }
 
-       private $fld_ids = false, $fld_title = false, $fld_patrol = false, $fld_flags = false,
-                       $fld_timestamp = false, $fld_user = false, $fld_comment = false, $fld_parsedcomment = false, $fld_sizes = false,
-                       $fld_notificationtimestamp = false, $fld_userid = false, $fld_loginfo = false;
+       private $fld_ids = false, $fld_title = false, $fld_patrol = false,
+               $fld_flags = false, $fld_timestamp = false, $fld_user = false,
+               $fld_comment = false, $fld_parsedcomment = false, $fld_sizes = false,
+               $fld_notificationtimestamp = false, $fld_userid = false,
+               $fld_loginfo = false;
 
        /**
         * @param $resultPageSet ApiPageSet
@@ -103,7 +105,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                        $this->addFieldsIf( 'rc_patrolled', $this->fld_patrol );
                        $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
                        $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp );
-                       $this->addFieldsIf( array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ), $this->fld_loginfo );
+                       $this->addFieldsIf(
+                               array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ),
+                               $this->fld_loginfo
+                       );
                } elseif ( $params['allrev'] ) {
                        $this->addFields( 'rc_this_oldid' );
                } else {
@@ -121,7 +126,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                                'wl_user' => $userId,
                                'wl_namespace=rc_namespace',
                                'wl_title=rc_title'
-               ) ) ) );
+                       )
+               ) ) );
 
                $this->addWhere( array(
                        'rc_deleted' => 0,
@@ -144,9 +150,9 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
 
                        /* Check for conflicting parameters. */
                        if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
-                                       || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
-                                       || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
-                                       || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
+                               || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
+                               || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
                        ) {
                                $this->dieUsageMsg( 'show' );
                        }
@@ -155,7 +161,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                        if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
                                $user = $this->getUser();
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
-                                       $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
+                                       $this->dieUsage(
+                                               'You need the patrol right to request the patrolled flag',
+                                               'permissiondenied'
+                                       );
                                }
                        }
 
@@ -185,7 +194,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                }
 
                // This is an index optimization for mysql, as done in the Special:Watchlist page
-               $this->addWhereIf( "rc_timestamp > ''", !isset( $params['start'] ) && !isset( $params['end'] ) && $db->getType() == 'mysql' );
+               $this->addWhereIf(
+                       "rc_timestamp > ''",
+                       !isset( $params['start'] ) && !isset( $params['end'] ) && $db->getType() == 'mysql'
+               );
 
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
 
@@ -194,9 +206,13 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                $res = $this->select( __METHOD__ );
 
                foreach ( $res as $row ) {
-                       if ( ++ $count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
+                       if ( ++$count > $params['limit'] ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
+                               $this->setContinueEnumParameter(
+                                       'start',
+                                       wfTimestamp( TS_ISO_8601, $row->rc_timestamp )
+                               );
                                break;
                        }
 
@@ -205,7 +221,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                                $fit = $this->getResult()->addValue( array( 'query', $this->getModuleName() ), null, $vals );
                                if ( !$fit ) {
                                        $this->setContinueEnumParameter( 'start',
-                                                       wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
+                                               wfTimestamp( TS_ISO_8601, $row->rc_timestamp ) );
                                        break;
                                }
                        } else {
@@ -218,7 +234,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                }
 
                if ( is_null( $resultPageSet ) ) {
-                       $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'item' );
+                       $this->getResult()->setIndexedTagName_internal(
+                               array( 'query', $this->getModuleName() ),
+                               'item'
+                       );
                } elseif ( $params['allrev'] ) {
                        $resultPageSet->populateFromRevisionIDs( $ids );
                } else {
@@ -348,6 +367,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                        foreach ( $type as $t ) {
                                $retval[] = $this->parseRCType( $t );
                        }
+
                        return $retval;
                }
                switch ( $type ) {
@@ -446,6 +466,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'allrev' => 'Include multiple revisions of the same page within given timeframe',
                        'start' => 'The timestamp to start enumerating from',
@@ -482,12 +503,14 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                                ' log            - Log entries',
                        ),
                        'owner' => 'The name of the user whose watchlist you\'d like to access',
-                       'token' => 'Give a security token (settable in preferences) to allow access to another user\'s watchlist'
+                       'token' => 'Give a security token (settable in preferences) to ' .
+                               'allow access to another user\'s watchlist'
                );
        }
 
        public function getResultProperties() {
                global $wgLogTypes;
+
                return array(
                        '' => array(
                                'type' => array(
@@ -574,11 +597,18 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'code' => 'bad_wlowner', 'info' => 'Specified user does not exist' ),
-                       array( 'code' => 'bad_wltoken', 'info' => 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences' ),
+                       array(
+                               'code' => 'bad_wltoken',
+                               'info' => 'Incorrect watchlist token provided -- ' .
+                                       'please set a correct token in Special:Preferences'
+                       ),
                        array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
                        array( 'code' => 'patrol', 'info' => 'patrol property is not available' ),
                        array( 'show' ),
-                       array( 'code' => 'permissiondenied', 'info' => 'You need the patrol right to request the patrolled flag' ),
+                       array(
+                               'code' => 'permissiondenied',
+                               'info' => 'You need the patrol right to request the patrolled flag'
+                       ),
                        array( 'code' => 'user-excludeuser', 'info' => 'user and excludeuser cannot be used together' ),
                ) );
        }
index ea4e724..b53bea1 100644 (file)
@@ -91,7 +91,7 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                        $this->addOption( 'ORDER BY', array(
                                'wl_namespace' . $sort,
                                'wl_title' . $sort
-                       ));
+                       ) );
                }
                $this->addOption( 'LIMIT', $params['limit'] + 1 );
                $res = $this->select( __METHOD__ );
@@ -100,7 +100,8 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                $count = 0;
                foreach ( $res as $row ) {
                        if ( ++$count > $params['limit'] ) {
-                               // We've reached the one extra which shows that there are additional pages to be had. Stop here...
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
                                $this->setContinueEnumParameter( 'continue', $row->wl_namespace . '|' . $row->wl_title );
                                break;
                        }
@@ -109,8 +110,7 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                        if ( is_null( $resultPageSet ) ) {
                                $vals = array();
                                ApiQueryBase::addTitleInfo( $vals, $t );
-                               if ( isset( $prop['changed'] ) && !is_null( $row->wl_notificationtimestamp ) )
-                               {
+                               if ( isset( $prop['changed'] ) && !is_null( $row->wl_notificationtimestamp ) ) {
                                        $vals['changed'] = wfTimestamp( TS_ISO_8601, $row->wl_notificationtimestamp );
                                }
                                $fit = $this->getResult()->addValue( $this->getModuleName(), null, $vals );
@@ -183,7 +183,8 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                        ),
                        'show' => 'Only list items that meet these criteria',
                        'owner' => 'The name of the user whose watchlist you\'d like to access',
-                       'token' => 'Give a security token (settable in preferences) to allow access to another user\'s watchlist',
+                       'token' => 'Give a security token (settable in preferences) to allow ' .
+                               'access to another user\'s watchlist',
                        'dir' => 'Direction to sort the titles and namespaces in',
                );
        }
@@ -212,7 +213,11 @@ class ApiQueryWatchlistRaw extends ApiQueryGeneratorBase {
                        array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
                        array( 'show' ),
                        array( 'code' => 'bad_wlowner', 'info' => 'Specified user does not exist' ),
-                       array( 'code' => 'bad_wltoken', 'info' => 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences' ),
+                       array(
+                               'code' => 'bad_wltoken',
+                               'info' => 'Incorrect watchlist token provided -- ' .
+                                       'please set a correct token in Special:Preferences'
+                       ),
                ) );
        }
 
index 39c114b..e922020 100644 (file)
@@ -26,9 +26,9 @@
 
 /**
  * This class represents the result of the API operations.
- * It simply wraps a nested array() structure, adding some functions to simplify array's modifications.
- * As various modules execute, they add different pieces of information to this result,
- * structuring it as it will be given to the client.
+ * It simply wraps a nested array() structure, adding some functions to simplify
+ * array's modifications. As various modules execute, they add different pieces
+ * of information to this result, structuring it as it will be given to the client.
  *
  * Each subarray may either be a dictionary - key-value pairs with unique keys,
  * or lists, where the items are added using $data[] = $value notation.
@@ -117,6 +117,7 @@ class ApiResult extends ApiBase {
                        // Objects can't always be cast to string
                        $s = strlen( $value );
                }
+
                return $s;
        }
 
@@ -150,14 +151,17 @@ class ApiResult extends ApiBase {
         * @param array $arr to add $value to
         * @param string $name Index of $arr to add $value at
         * @param $value mixed
-        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This parameter used to be
-        *        boolean, and the value of OVERRIDE=1 was specifically chosen so that it would be backwards
-        *        compatible with the new method signature.
+        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP.
+        *    This parameter used to be boolean, and the value of OVERRIDE=1 was
+        *    specifically chosen so that it would be backwards compatible with the
+        *    new method signature.
         *
         * @since 1.21 int $flags replaced boolean $override
         */
        public static function setElement( &$arr, $name, $value, $flags = 0 ) {
-               if ( $arr === null || $name === null || $value === null || !is_array( $arr ) || is_array( $name ) ) {
+               if ( $arr === null || $name === null || $value === null
+                       || !is_array( $arr ) || is_array( $name )
+               ) {
                        ApiBase::dieDebug( __METHOD__, 'Bad parameter' );
                }
 
@@ -176,7 +180,10 @@ class ApiResult extends ApiBase {
                                ApiBase::dieDebug( __METHOD__, "Attempting to merge element $name" );
                        }
                } else {
-                       ApiBase::dieDebug( __METHOD__, "Attempting to add element $name=$value, existing value is {$arr[$name]}" );
+                       ApiBase::dieDebug(
+                               __METHOD__,
+                               "Attempting to add element $name=$value, existing value is {$arr[$name]}"
+                       );
                }
        }
 
@@ -271,9 +278,10 @@ class ApiResult extends ApiBase {
         * @param $path array|string|null
         * @param $name string
         * @param $value mixed
-        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This parameter used to be
-        *        boolean, and the value of OVERRIDE=1 was specifically chosen so that it would be backwards
-        *        compatible with the new method signature.
+        * @param int $flags Zero or more OR-ed flags like OVERRIDE | ADD_ON_TOP. This
+        *    parameter used to be boolean, and the value of OVERRIDE=1 was specifically
+        *    chosen so that it would be backwards compatible with the new method
+        *    signature.
         * @return bool True if $value fits in the result, false if not
         *
         * @since 1.21 int $flags replaced boolean $override
@@ -287,7 +295,8 @@ class ApiResult extends ApiBase {
                        if ( $newsize > $wgAPIMaxResultSize ) {
                                $this->setWarning(
                                        "This result was truncated because it would otherwise be larger than the " .
-                                                       "limit of {$wgAPIMaxResultSize} bytes" );
+                                               "limit of {$wgAPIMaxResultSize} bytes" );
+
                                return false;
                        }
                        $this->mSize = $newsize;
@@ -322,6 +331,7 @@ class ApiResult extends ApiBase {
                        // Add named element
                        self::setElement( $data, $name, $value, $flags );
                }
+
                return true;
        }
 
@@ -394,6 +404,7 @@ class ApiResult extends ApiBase {
                        $result[] = $error;
                }
                $this->setIndexedTagName( $result, $errorType );
+
                return $result;
        }
 
index b9873f4..2a372e4 100644 (file)
@@ -47,7 +47,14 @@ class ApiRollback extends ApiBase {
                $pageObj = WikiPage::factory( $titleObj );
                $summary = $params['summary'];
                $details = array();
-               $retval = $pageObj->doRollback( $this->getRbUser(), $summary, $params['token'], $params['markbot'], $details, $this->getUser() );
+               $retval = $pageObj->doRollback(
+                       $this->getRbUser(),
+                       $summary,
+                       $params['token'],
+                       $params['markbot'],
+                       $details,
+                       $this->getUser()
+               );
 
                if ( $retval ) {
                        // We don't care about multiple errors, just report one of them
@@ -107,11 +114,14 @@ class ApiRollback extends ApiBase {
        public function getParamDescription() {
                return array(
                        'title' => 'Title of the page you want to rollback.',
-                       'user' => 'Name of the user whose edits are to be rolled back. If set incorrectly, you\'ll get a badtoken error.',
-                       'token' => "A rollback token previously retrieved through {$this->getModulePrefix()}prop=revisions",
+                       'user' => 'Name of the user whose edits are to be rolled back. If ' .
+                               'set incorrectly, you\'ll get a badtoken error.',
+                       'token' => 'A rollback token previously retrieved through ' .
+                               "{$this->getModulePrefix()}prop=revisions",
                        'summary' => 'Custom edit summary. If empty, default summary will be used',
                        'markbot' => 'Mark the reverted edits and the revert as bot edits',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, ' .
+                               'use preferences or do not change watch',
                );
        }
 
@@ -130,8 +140,8 @@ class ApiRollback extends ApiBase {
 
        public function getDescription() {
                return array(
-                       'Undo the last edit to the page. If the last user who edited the page made multiple edits in a row,',
-                       'they will all be rolled back'
+                       'Undo the last edit to the page. If the last user who edited the page made',
+                       'multiple edits in a row, they will all be rolled back'
                );
        }
 
@@ -194,7 +204,8 @@ class ApiRollback extends ApiBase {
        public function getExamples() {
                return array(
                        'api.php?action=rollback&title=Main%20Page&user=Catrope&token=123ABC',
-                       'api.php?action=rollback&title=Main%20Page&user=217.121.114.116&token=123ABC&summary=Reverting%20vandalism&markbot=1'
+                       'api.php?action=rollback&title=Main%20Page&user=217.121.114.116&' .
+                               'token=123ABC&summary=Reverting%20vandalism&markbot=1'
                );
        }
 
index d219c91..e01f0fa 100644 (file)
@@ -107,6 +107,7 @@ class ApiRsd extends ApiBase {
                        ),
                );
                wfRunHooks( 'ApiRsdServiceApis', array( &$apis ) );
+
                return $apis;
        }
 
@@ -149,6 +150,7 @@ class ApiRsd extends ApiBase {
                        }
                        $outputData[] = $data;
                }
+
                return $outputData;
        }
 }
index 53a68fd..dc593e5 100644 (file)
@@ -48,7 +48,10 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
                $pageSet = $this->getPageSet();
                if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
-                       $this->dieUsage( "Cannot use 'entirewatchlist' at the same time as '{$pageSet->getDataSource()}'", 'multisource' );
+                       $this->dieUsage(
+                               "Cannot use 'entirewatchlist' at the same time as '{$pageSet->getDataSource()}'",
+                               'multisource'
+                       );
                }
 
                $dbw = wfGetDB( DB_MASTER, 'api' );
@@ -95,7 +98,9 @@ class ApiSetNotificationTimestamp extends ApiBase {
                                __METHOD__
                        );
 
-                       $result['notificationtimestamp'] = ( is_null( $timestamp ) ? '' : wfTimestamp( TS_ISO_8601, $timestamp ) );
+                       $result['notificationtimestamp'] = is_null( $timestamp )
+                               ? ''
+                               : wfTimestamp( TS_ISO_8601, $timestamp );
                } else {
                        // First, log the invalid titles
                        foreach ( $pageSet->getInvalidTitles() as $title ) {
@@ -128,7 +133,9 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
                        // Query the results of our update
                        $timestamps = array();
-                       $res = $dbw->select( 'watchlist', array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
+                       $res = $dbw->select(
+                               'watchlist',
+                               array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
                                array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
                                __METHOD__
                        );
@@ -172,6 +179,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
                if ( !isset( $this->mPageSet ) ) {
                        $this->mPageSet = new ApiPageSet( $this );
                }
+
                return $this->mPageSet;
        }
 
@@ -210,8 +218,8 @@ class ApiSetNotificationTimestamp extends ApiBase {
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
                }
-               return $result;
 
+               return $result;
        }
 
        public function getParamDescription() {
@@ -271,6 +279,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
        public function getPossibleErrors() {
                $ps = $this->getPageSet();
+
                return array_merge(
                        parent::getPossibleErrors(),
                        $ps->getFinalPossibleErrors(),
@@ -279,7 +288,8 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        $this->getRequireOnlyOneParameterErrorMessages(
                                array_merge( array( 'entirewatchlist' ), array_keys( $ps->getFinalParams() ) ) ),
                        array(
-                               array( 'code' => 'notloggedin', 'info' => 'Anonymous users cannot use watchlist change notifications' ),
+                               array( 'code' => 'notloggedin', 'info'
+                               => 'Anonymous users cannot use watchlist change notifications' ),
                                array( 'code' => 'multpages', 'info' => 'torevid may only be used with a single page' ),
                                array( 'code' => 'multpages', 'info' => 'newerthanrevid may only be used with a single page' ),
                        )
@@ -288,9 +298,14 @@ class ApiSetNotificationTimestamp extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=setnotificationtimestamp&entirewatchlist=&token=123ABC' => 'Reset the notification status for the entire watchlist',
-                       'api.php?action=setnotificationtimestamp&titles=Main_page&token=123ABC' => 'Reset the notification status for "Main page"',
-                       'api.php?action=setnotificationtimestamp&titles=Main_page&timestamp=2012-01-01T00:00:00Z&token=123ABC' => 'Set the notification timestamp for "Main page" so all edits since 1 January 2012 are unviewed',
+                       'api.php?action=setnotificationtimestamp&entirewatchlist=&token=123ABC'
+                               => 'Reset the notification status for the entire watchlist',
+                       'api.php?action=setnotificationtimestamp&titles=Main_page&token=123ABC'
+                               => 'Reset the notification status for "Main page"',
+                       'api.php?action=setnotificationtimestamp&titles=Main_page&' .
+                               'timestamp=2012-01-01T00:00:00Z&token=123ABC'
+                               => 'Set the notification timestamp for "Main page" so all edits ' .
+                                       'since 1 January 2012 are unviewed',
                );
        }
 
index d220a5e..6862668 100644 (file)
@@ -67,6 +67,7 @@ class ApiTokens extends ApiBase {
                wfRunHooks( 'ApiTokensGetTokenTypes', array( &$types ) );
                ksort( $types );
                wfProfileOut( __METHOD__ );
+
                return $types;
        }
 
index 6a739a2..dabb8da 100644 (file)
@@ -96,9 +96,12 @@ class ApiUnblock extends ApiBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
-                       'id' => "ID of the block you want to unblock (obtained through list=blocks). Cannot be used together with {$p}user",
-                       'user' => "Username, IP address or IP range you want to unblock. Cannot be used together with {$p}id",
+                       'id' => "ID of the block you want to unblock (obtained through list=blocks). ' .
+                               'Cannot be used together with {$p}user",
+                       'user' => "Username, IP address or IP range you want to unblock. ' .
+                               'Cannot be used together with {$p}id",
                        'token' => "An unblock token previously obtained through prop=info",
                        'reason' => 'Reason for unblock',
                );
index 4bbe568..93cefef 100644 (file)
@@ -122,8 +122,10 @@ class ApiUndelete extends ApiBase {
                        'title' => 'Title of the page you want to restore',
                        'token' => 'An undelete token previously retrieved through list=deletedrevs',
                        'reason' => 'Reason for restoring',
-                       'timestamps' => 'Timestamps of the revisions to restore. If not set, all revisions will be restored.',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'timestamps' => 'Timestamps of the revisions to restore. If not set, all ' .
+                               'revisions will be restored.',
+                       'watchlist' => 'Unconditionally add or remove the page from your ' .
+                               'watchlist, use preferences or do not change watch',
                );
        }
 
@@ -140,8 +142,8 @@ class ApiUndelete extends ApiBase {
 
        public function getDescription() {
                return array(
-                       'Restore certain revisions of a deleted page. A list of deleted revisions (including timestamps) can be',
-                       'retrieved through list=deletedrevs'
+                       'Restore certain revisions of a deleted page. A list of deleted revisions ',
+                       '(including timestamps) can be retrieved through list=deletedrevs'
                );
        }
 
index 467eccf..1a642b9 100644 (file)
@@ -141,6 +141,7 @@ class ApiUpload extends ApiBase {
                        // Stash the file and get stash result
                        return $this->getStashResult( $warnings );
                }
+
                // This is the most common case -- a normal upload with no warnings
                // performUpload will return a formatted properly for the API with status
                return $this->performUpload( $warnings );
@@ -165,6 +166,7 @@ class ApiUpload extends ApiBase {
                } catch ( MWException $e ) {
                        $this->dieUsage( $e->getMessage(), 'stashfailed' );
                }
+
                return $result;
        }
 
@@ -185,6 +187,7 @@ class ApiUpload extends ApiBase {
                } catch ( MWException $e ) {
                        $result['warnings']['stashfailed'] = $e->getMessage();
                }
+
                return $result;
        }
 
@@ -217,6 +220,7 @@ class ApiUpload extends ApiBase {
                                $chunkPath, $chunkSize, $this->mParams['offset'] );
                        if ( !$status->isGood() ) {
                                $this->dieUsage( $status->getWikiText(), 'stashfailed' );
+
                                return array();
                        }
                }
@@ -252,6 +256,7 @@ class ApiUpload extends ApiBase {
                                $status = $this->mUpload->concatenateChunks();
                                if ( !$status->isGood() ) {
                                        $this->dieUsage( $status->getWikiText(), 'stashfailed' );
+
                                        return array();
                                }
 
@@ -265,6 +270,7 @@ class ApiUpload extends ApiBase {
                }
                $result['filekey'] = $filekey;
                $result['offset'] = $this->mParams['offset'] + $chunkSize;
+
                return $result;
        }
 
@@ -287,6 +293,7 @@ class ApiUpload extends ApiBase {
                        wfDebug( __METHOD__ . ' ' . $message . "\n" );
                        throw new MWException( $message );
                }
+
                return $fileKey;
        }
 
@@ -341,6 +348,7 @@ class ApiUpload extends ApiBase {
                        }
                        unset( $progress['status'] ); // remove Status object
                        $this->getResult()->addValue( null, $this->getModuleName(), $progress );
+
                        return false;
                }
 
@@ -357,6 +365,7 @@ class ApiUpload extends ApiBase {
                                $sessionData['sessionkey'] = $this->mParams['statuskey'];
                        }
                        $this->getResult()->addValue( null, $this->getModuleName(), $sessionData );
+
                        return false;
                }
 
@@ -449,9 +458,9 @@ class ApiUpload extends ApiBase {
                if ( $permission !== true ) {
                        if ( !$user->isLoggedIn() ) {
                                $this->dieUsageMsg( array( 'mustbeloggedin', 'upload' ) );
-                       } else {
-                               $this->dieUsageMsg( 'badaccess-groups' );
                        }
+
+                       $this->dieUsageMsg( 'badaccess-groups' );
                }
        }
 
@@ -481,7 +490,7 @@ class ApiUpload extends ApiBase {
                                break;
                        case UploadBase::ILLEGAL_FILENAME:
                                $this->dieRecoverableError( 'illegal-filename', 'filename',
-                                               array( 'filename' => $verification['filtered'] ) );
+                                       array( 'filename' => $verification['filtered'] ) );
                                break;
                        case UploadBase::FILENAME_TOO_LONG:
                                $this->dieRecoverableError( 'filename-toolong', 'filename' );
@@ -521,15 +530,15 @@ class ApiUpload extends ApiBase {
                        case UploadBase::VERIFICATION_ERROR:
                                $this->getResult()->setIndexedTagName( $verification['details'], 'detail' );
                                $this->dieUsage( 'This file did not pass file verification', 'verification-error',
-                                               0, array( 'details' => $verification['details'] ) );
+                                       0, array( 'details' => $verification['details'] ) );
                                break;
                        case UploadBase::HOOK_ABORTED:
                                $this->dieUsage( "The modification you tried to make was aborted by an extension hook",
-                                               'hookaborted', 0, array( 'error' => $verification['error'] ) );
+                                       'hookaborted', 0, array( 'error' => $verification['error'] ) );
                                break;
                        default:
                                $this->dieUsage( 'An unknown error occurred', 'unknown-error',
-                                               0, array( 'code' => $verification['status'] ) );
+                                       0, array( 'code' => $verification['status'] ) );
                                break;
                }
        }
@@ -565,10 +574,13 @@ class ApiUpload extends ApiBase {
                        if ( isset( $warnings['exists'] ) ) {
                                $warning = $warnings['exists'];
                                unset( $warnings['exists'] );
-                               $localFile = isset( $warning['normalizedFile'] ) ? $warning['normalizedFile'] : $warning['file'];
+                               $localFile = isset( $warning['normalizedFile'] )
+                                       ? $warning['normalizedFile']
+                                       : $warning['file'];
                                $warnings[$warning['warning']] = $localFile->getName();
                        }
                }
+
                return $warnings;
        }
 
@@ -587,7 +599,19 @@ class ApiUpload extends ApiBase {
 
                /** @var $file File */
                $file = $this->mUpload->getLocalFile();
-               $watch = $this->getWatchlistValue( $this->mParams['watchlist'], $file->getTitle() );
+
+               // For preferences mode, we want to watch if 'watchdefault' is set or
+               // if the *file* doesn't exist and 'watchcreations' is set. But
+               // getWatchlistValue()'s automatic handling checks if the *title*
+               // exists or not, so we need to check both prefs manually.
+               $watch = $this->getWatchlistValue(
+                       $this->mParams['watchlist'], $file->getTitle(), 'watchdefault'
+               );
+               if ( !$watch && $this->mParams['watchlist'] == 'preferences' && !$file->exists() ) {
+                       $watch = $this->getWatchlistValue(
+                               $this->mParams['watchlist'], $file->getTitle(), 'watchcreations'
+                       );
+               }
 
                // Deprecated parameters
                if ( $this->mParams['watch'] ) {
@@ -637,11 +661,10 @@ class ApiUpload extends ApiBase {
                                                'result' => 'Queued',
                                                'statuskey' => $error[0][1],
                                        );
-                               } else {
-                                       $this->getResult()->setIndexedTagName( $error, 'error' );
-
-                                       $this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
                                }
+
+                               $this->getResult()->setIndexedTagName( $error, 'error' );
+                               $this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
                        }
                        $result['result'] = 'Success';
                }
@@ -729,16 +752,19 @@ class ApiUpload extends ApiBase {
                $params = array(
                        'filename' => 'Target filename',
                        'token' => 'Edit token. You can get one of these through prop=info',
-                       'comment' => 'Upload comment. Also used as the initial page text for new files if "text" is not specified',
+                       'comment' => 'Upload comment. Also used as the initial page text for new ' .
+                               'files if "text" is not specified',
                        'text' => 'Initial page text for new files',
                        'watch' => 'Watch the page',
-                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
+                       'watchlist' => 'Unconditionally add or remove the page from your watchlist, ' .
+                               'use preferences or do not change watch',
                        'ignorewarnings' => 'Ignore any warnings',
                        'file' => 'File contents',
                        'url' => 'URL to fetch the file from',
                        'filekey' => 'Key that identifies a previous upload that was stashed temporarily.',
                        'sessionkey' => 'Same as filekey, maintained for backward compatibility.',
-                       'stash' => 'If set, the server will not add the file to the repository and stash it temporarily.',
+                       'stash' => 'If set, the server will not add the file to the repository ' .
+                               'and stash it temporarily.',
 
                        'chunk' => 'Chunk contents',
                        'offset' => 'Offset of chunk in bytes',
@@ -752,7 +778,6 @@ class ApiUpload extends ApiBase {
                );
 
                return $params;
-
        }
 
        public function getResultProperties() {
@@ -837,7 +862,8 @@ class ApiUpload extends ApiBase {
 
        public function getExamples() {
                return array(
-                       'api.php?action=upload&filename=Wiki.png&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png'
+                       'api.php?action=upload&filename=Wiki.png' .
+                       '&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png'
                                => 'Upload from a URL',
                        'api.php?action=upload&filename=Wiki.png&filekey=filekey&ignorewarnings=1'
                                => 'Complete an upload that failed due to warnings',
index 7d30828..be98a21 100644 (file)
@@ -41,10 +41,10 @@ class ApiUserrights extends ApiBase {
                $form->setContext( $this->getContext() );
                $r['user'] = $user->getName();
                $r['userid'] = $user->getId();
-               list( $r['added'], $r['removed'] ) =
-                       $form->doSaveUserGroups(
-                               $user, (array)$params['add'],
-                               (array)$params['remove'], $params['reason'] );
+               list( $r['added'], $r['removed'] ) = $form->doSaveUserGroups(
+                       $user, (array)$params['add'],
+                       (array)$params['remove'], $params['reason']
+               );
 
                $result = $this->getResult();
                $result->setIndexedTagName( $r['added'], 'group' );
@@ -67,12 +67,11 @@ class ApiUserrights extends ApiBase {
                $status = $form->fetchUser( $params['user'] );
                if ( !$status->isOK() ) {
                        $this->dieStatus( $status );
-               } else {
-                       $user = $status->value;
                }
 
-               $this->mUser = $user;
-               return $user;
+               $this->mUser = $status->value;
+
+               return $status->value;
        }
 
        public function mustBePosted() {
index c7d636a..7ad286f 100644 (file)
@@ -49,21 +49,26 @@ class ApiWatch extends ApiBase {
 
                $res = array( 'title' => $title->getPrefixedText() );
 
-               // Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
+               // Currently unnecessary, code to act as a safeguard against any change
+               // in current behavior of uselang.
                // Copy from ApiParse
                $oldLang = null;
-               if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
+               if ( isset( $params['uselang'] ) &&
+                       $params['uselang'] != $this->getContext()->getLanguage()->getCode()
+               ) {
                        $oldLang = $this->getContext()->getLanguage(); // Backup language
                        $this->getContext()->setLanguage( Language::factory( $params['uselang'] ) );
                }
 
                if ( $params['unwatch'] ) {
                        $res['unwatched'] = '';
-                       $res['message'] = $this->msg( 'removedwatchtext', $title->getPrefixedText() )->title( $title )->parseAsBlock();
+                       $res['message'] = $this->msg( 'removedwatchtext', $title->getPrefixedText() )
+                               ->title( $title )->parseAsBlock();
                        $status = UnwatchAction::doUnwatch( $title, $user );
                } else {
                        $res['watched'] = '';
-                       $res['message'] = $this->msg( 'addedwatchtext', $title->getPrefixedText() )->title( $title )->parseAsBlock();
+                       $res['message'] = $this->msg( 'addedwatchtext', $title->getPrefixedText() )
+                               ->title( $title )->parseAsBlock();
                        $status = WatchAction::doWatch( $title, $user );
                }
 
index 193f20f..d2ec26e 100644 (file)
@@ -48,6 +48,7 @@ class BacklinkCache {
        /**
         * Multi dimensions array representing batches. Keys are:
         *  > (string) links table name
+        *   > (int) batch size
         *    > 'numRows' : Number of rows for this link table
         *    > 'batches' : array( $start, $end )
         *
@@ -107,6 +108,7 @@ class BacklinkCache {
                if ( !self::$cache->has( $dbKey, 'obj', 3600 ) ) {
                        self::$cache->set( $dbKey, 'obj', new self( $title ) );
                }
+
                return self::$cache->get( $dbKey, 'obj' );
        }
 
@@ -148,15 +150,16 @@ class BacklinkCache {
                if ( !isset( $this->db ) ) {
                        $this->db = wfGetDB( DB_SLAVE );
                }
+
                return $this->db;
        }
 
        /**
         * Get the backlinks for a given table. Cached in process memory only.
-        * @param $table String
-        * @param $startId Integer|false
-        * @param $endId Integer|false
-        * @param $max Integer|INF
+        * @param string $table
+        * @param int|bool $startId
+        * @param int|bool $endId
+        * @param int|INF $max
         * @return TitleArrayFromResult
         */
        public function getLinks( $table, $startId = false, $endId = false, $max = INF ) {
@@ -169,16 +172,17 @@ class BacklinkCache {
         * @param $startId Integer|false
         * @param $endId Integer|false
         * @param $max Integer|INF
+        * @param $select string 'all' or 'ids'
         * @return ResultWrapper
         */
-       protected function queryLinks( $table, $startId, $endId, $max ) {
+       protected function queryLinks( $table, $startId, $endId, $max, $select = 'all' ) {
                wfProfileIn( __METHOD__ );
 
                $fromField = $this->getPrefix( $table ) . '_from';
 
                if ( !$startId && !$endId && is_infinite( $max )
-                       && isset( $this->fullResultCache[$table] ) )
-               {
+                       && isset( $this->fullResultCache[$table] )
+               {
                        wfDebug( __METHOD__ . ": got results from cache\n" );
                        $res = $this->fullResultCache[$table];
                } else {
@@ -192,20 +196,34 @@ class BacklinkCache {
                        if ( $endId ) {
                                $conds[] = "$fromField <= " . intval( $endId );
                        }
-                       $options = array( 'STRAIGHT_JOIN', 'ORDER BY' => $fromField );
+                       $options = array( 'ORDER BY' => $fromField );
                        if ( is_finite( $max ) && $max > 0 ) {
                                $options['LIMIT'] = $max;
                        }
 
-                       $res = $this->getDB()->select(
-                               array( $table, 'page' ),
-                               array( 'page_namespace', 'page_title', 'page_id' ),
-                               $conds,
-                               __METHOD__,
-                               $options
-                       );
+                       if ( $select === 'ids' ) {
+                               // Just select from the backlink table and ignore the page JOIN
+                               $res = $this->getDB()->select(
+                                       $table,
+                                       array( $this->getPrefix( $table ) . '_from AS page_id' ),
+                                       array_filter( $conds, function ( $clause ) { // kind of janky
+                                               return !preg_match( '/(\b|=)page_id(\b|=)/', $clause );
+                                       } ),
+                                       __METHOD__,
+                                       $options
+                               );
+                       } else {
+                               // Select from the backlink table and JOIN with page title information
+                               $res = $this->getDB()->select(
+                                       array( $table, 'page' ),
+                                       array( 'page_namespace', 'page_title', 'page_id' ),
+                                       $conds,
+                                       __METHOD__,
+                                       array_merge( array( 'STRAIGHT_JOIN' ), $options )
+                               );
+                       }
 
-                       if ( !$startId && !$endId && $res->numRows() < $max ) {
+                       if ( $select === 'all' && !$startId && !$endId && $res->numRows() < $max ) {
                                // The full results fit within the limit, so cache them
                                $this->fullResultCache[$table] = $res;
                        } else {
@@ -214,6 +232,7 @@ class BacklinkCache {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -255,8 +274,6 @@ class BacklinkCache {
        protected function getConditions( $table ) {
                $prefix = $this->getPrefix( $table );
 
-               // @todo FIXME: imagelinks and categorylinks do not rely on getNamespace,
-               // they could be moved up for nicer case statements
                switch ( $table ) {
                        case 'pagelinks':
                        case 'templatelinks':
@@ -278,15 +295,10 @@ class BacklinkCache {
                                );
                                break;
                        case 'imagelinks':
-                               $conds = array(
-                                       'il_to' => $this->title->getDBkey(),
-                                       'page_id=il_from'
-                               );
-                               break;
                        case 'categorylinks':
                                $conds = array(
-                                       'cl_to' => $this->title->getDBkey(),
-                                       'page_id=cl_from',
+                                       "{$prefix}_to" => $this->title->getDBkey(),
+                                       "page_id={$prefix}_from"
                                );
                                break;
                        default:
@@ -316,11 +328,12 @@ class BacklinkCache {
         * @return integer
         */
        public function getNumLinks( $table, $max = INF ) {
-               global $wgMemc;
+               global $wgMemc, $wgUpdateRowsPerJob;
 
                // 1) try partition cache ...
                if ( isset( $this->partitionCache[$table] ) ) {
                        $entry = reset( $this->partitionCache[$table] );
+
                        return min( $max, $entry['numRows'] );
                }
 
@@ -338,9 +351,17 @@ class BacklinkCache {
                }
 
                // 4) fetch from the database ...
-               $count = $this->getLinks( $table, false, false, $max )->count();
-               if ( $count < $max ) { // full count
-                       $wgMemc->set( $memcKey, $count, self::CACHE_EXPIRY );
+               if ( is_infinite( $max ) ) { // no limit at all
+                       // Use partition() since it will batch the query and skip the JOIN.
+                       // Use $wgUpdateRowsPerJob just to encourage cache reuse for jobs.
+                       $this->partition( $table, $wgUpdateRowsPerJob ); // updates $this->partitionCache
+                       return $this->partitionCache[$table][$wgUpdateRowsPerJob]['numRows'];
+               } else { // probably some sane limit
+                       // Fetch the full title info, since the caller will likely need it next
+                       $count = $this->getLinks( $table, false, false, $max )->count();
+                       if ( $count < $max ) { // full count
+                               $wgMemc->set( $memcKey, $count, self::CACHE_EXPIRY );
+                       }
                }
 
                return min( $max, $count );
@@ -361,6 +382,7 @@ class BacklinkCache {
                // 1) try partition cache ...
                if ( isset( $this->partitionCache[$table][$batchSize] ) ) {
                        wfDebug( __METHOD__ . ": got from partition cache\n" );
+
                        return $this->partitionCache[$table][$batchSize]['batches'];
                }
 
@@ -371,6 +393,7 @@ class BacklinkCache {
                if ( isset( $this->fullResultCache[$table] ) ) {
                        $cacheEntry = $this->partitionResult( $this->fullResultCache[$table], $batchSize );
                        wfDebug( __METHOD__ . ": got from full result cache\n" );
+
                        return $cacheEntry['batches'];
                }
 
@@ -386,6 +409,7 @@ class BacklinkCache {
                if ( is_array( $memcValue ) ) {
                        $cacheEntry = $memcValue;
                        wfDebug( __METHOD__ . ": got from memcached $memcKey\n" );
+
                        return $cacheEntry['batches'];
                }
 
@@ -396,13 +420,13 @@ class BacklinkCache {
                $selectSize = max( $batchSize, 200000 - ( 200000 % $batchSize ) );
                $start = false;
                do {
-                       $res = $this->queryLinks( $table, $start, false, $selectSize );
+                       $res = $this->queryLinks( $table, $start, false, $selectSize, 'ids' );
                        $partitions = $this->partitionResult( $res, $batchSize, false );
                        // Merge the link count and range partitions for this chunk
                        $cacheEntry['numRows'] += $partitions['numRows'];
                        $cacheEntry['batches'] = array_merge( $cacheEntry['batches'], $partitions['batches'] );
                        if ( count( $partitions['batches'] ) ) {
-                               list( $lStart, $lEnd ) = end( $partitions['batches'] );
+                               list( , $lEnd ) = end( $partitions['batches'] );
                                $start = $lEnd + 1; // pick up after this inclusive range
                        }
                } while ( $partitions['numRows'] >= $selectSize );
@@ -420,6 +444,7 @@ class BacklinkCache {
                $wgMemc->set( $memcKey, $cacheEntry['numRows'], self::CACHE_EXPIRY );
 
                wfDebug( __METHOD__ . ": got from database\n" );
+
                return $cacheEntry['batches'];
        }
 
index 32bcdf7..b7d0a7c 100644 (file)
@@ -28,8 +28,8 @@
  * @ingroup Cache
  */
 class DependencyWrapper {
-       var $value;
-       var $deps;
+       private $value;
+       private $deps;
 
        /**
         * Create an instance.
@@ -110,8 +110,8 @@ class DependencyWrapper {
         *    callback was defined.
         */
        static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false,
-               $callbackParams = array(), $deps = array() )
-       {
+               $callbackParams = array(), $deps = array()
+       {
                $obj = $cache->get( $key );
 
                if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) {
@@ -141,14 +141,16 @@ abstract class CacheDependency {
        /**
         * Hook to perform any expensive pre-serialize loading of dependency values.
         */
-       function loadDependencyValues() { }
+       function loadDependencyValues() {
+       }
 }
 
 /**
  * @ingroup Cache
  */
 class FileDependency extends CacheDependency {
-       var $filename, $timestamp;
+       private $filename;
+       private $timestamp;
 
        /**
         * Create a file dependency
@@ -172,6 +174,7 @@ class FileDependency extends CacheDependency {
         */
        function __sleep() {
                $this->loadDependencyValues();
+
                return array( 'filename', 'timestamp' );
        }
 
@@ -198,6 +201,7 @@ class FileDependency extends CacheDependency {
                        } else {
                                # Deleted
                                wfDebug( "Dependency triggered: {$this->filename} deleted.\n" );
+
                                return true;
                        }
                } else {
@@ -205,6 +209,7 @@ class FileDependency extends CacheDependency {
                        if ( $lastmod > $this->timestamp ) {
                                # Modified or created
                                wfDebug( "Dependency triggered: {$this->filename} changed.\n" );
+
                                return true;
                        } else {
                                # Not modified
@@ -214,186 +219,12 @@ class FileDependency extends CacheDependency {
        }
 }
 
-/**
- * @ingroup Cache
- */
-class TitleDependency extends CacheDependency {
-       var $titleObj;
-       var $ns, $dbk;
-       var $touched;
-
-       /**
-        * Construct a title dependency
-        * @param $title Title
-        */
-       function __construct( Title $title ) {
-               $this->titleObj = $title;
-               $this->ns = $title->getNamespace();
-               $this->dbk = $title->getDBkey();
-       }
-
-       function loadDependencyValues() {
-               $this->touched = $this->getTitle()->getTouched();
-       }
-
-       /**
-        * Get rid of bulky Title object for sleep
-        *
-        * @return array
-        */
-       function __sleep() {
-               return array( 'ns', 'dbk', 'touched' );
-       }
-
-       /**
-        * @return Title
-        */
-       function getTitle() {
-               if ( !isset( $this->titleObj ) ) {
-                       $this->titleObj = Title::makeTitle( $this->ns, $this->dbk );
-               }
-
-               return $this->titleObj;
-       }
-
-       /**
-        * @return bool
-        */
-       function isExpired() {
-               $touched = $this->getTitle()->getTouched();
-
-               if ( $this->touched === false ) {
-                       if ( $touched === false ) {
-                               # Still missing
-                               return false;
-                       } else {
-                               # Created
-                               return true;
-                       }
-               } elseif ( $touched === false ) {
-                       # Deleted
-                       return true;
-               } elseif ( $touched > $this->touched ) {
-                       # Updated
-                       return true;
-               } else {
-                       # Unmodified
-                       return false;
-               }
-       }
-}
-
-/**
- * @ingroup Cache
- */
-class TitleListDependency extends CacheDependency {
-       var $linkBatch;
-       var $timestamps;
-
-       /**
-        * Construct a dependency on a list of titles
-        * @param $linkBatch LinkBatch
-        */
-       function __construct( LinkBatch $linkBatch ) {
-               $this->linkBatch = $linkBatch;
-       }
-
-       /**
-        * @return array
-        */
-       function calculateTimestamps() {
-               # Initialise values to false
-               $timestamps = array();
-
-               foreach ( $this->getLinkBatch()->data as $ns => $dbks ) {
-                       if ( count( $dbks ) > 0 ) {
-                               $timestamps[$ns] = array();
-
-                               foreach ( $dbks as $dbk => $value ) {
-                                       $timestamps[$ns][$dbk] = false;
-                               }
-                       }
-               }
-
-               # Do the query
-               if ( count( $timestamps ) ) {
-                       $dbr = wfGetDB( DB_SLAVE );
-                       $where = $this->getLinkBatch()->constructSet( 'page', $dbr );
-                       $res = $dbr->select(
-                               'page',
-                               array( 'page_namespace', 'page_title', 'page_touched' ),
-                               $where,
-                               __METHOD__
-                       );
-
-                       foreach ( $res as $row ) {
-                               $timestamps[$row->page_namespace][$row->page_title] = $row->page_touched;
-                       }
-               }
-
-               return $timestamps;
-       }
-
-       function loadDependencyValues() {
-               $this->timestamps = $this->calculateTimestamps();
-       }
-
-       /**
-        * @return array
-        */
-       function __sleep() {
-               return array( 'timestamps' );
-       }
-
-       /**
-        * @return LinkBatch
-        */
-       function getLinkBatch() {
-               if ( !isset( $this->linkBatch ) ) {
-                       $this->linkBatch = new LinkBatch;
-                       $this->linkBatch->setArray( $this->timestamps );
-               }
-               return $this->linkBatch;
-       }
-
-       /**
-        * @return bool
-        */
-       function isExpired() {
-               $newTimestamps = $this->calculateTimestamps();
-
-               foreach ( $this->timestamps as $ns => $dbks ) {
-                       foreach ( $dbks as $dbk => $oldTimestamp ) {
-                               $newTimestamp = $newTimestamps[$ns][$dbk];
-
-                               if ( $oldTimestamp === false ) {
-                                       if ( $newTimestamp === false ) {
-                                               # Still missing
-                                       } else {
-                                               # Created
-                                               return true;
-                                       }
-                               } elseif ( $newTimestamp === false ) {
-                                       # Deleted
-                                       return true;
-                               } elseif ( $newTimestamp > $oldTimestamp ) {
-                                       # Updated
-                                       return true;
-                               } else {
-                                       # Unmodified
-                               }
-                       }
-               }
-
-               return false;
-       }
-}
-
 /**
  * @ingroup Cache
  */
 class GlobalDependency extends CacheDependency {
-       var $name, $value;
+       private $name;
+       private $value;
 
        function __construct( $name ) {
                $this->name = $name;
@@ -407,6 +238,7 @@ class GlobalDependency extends CacheDependency {
                if ( !isset( $GLOBALS[$this->name] ) ) {
                        return true;
                }
+
                return $GLOBALS[$this->name] != $this->value;
        }
 }
@@ -415,7 +247,8 @@ class GlobalDependency extends CacheDependency {
  * @ingroup Cache
  */
 class ConstantDependency extends CacheDependency {
-       var $name, $value;
+       private $name;
+       private $value;
 
        function __construct( $name ) {
                $this->name = $name;
index d4bf5ee..0c00c6b 100644 (file)
@@ -51,6 +51,7 @@ abstract class FileCacheBase {
         */
        final protected function baseCacheDirectory() {
                global $wgFileCacheDirectory;
+
                return $wgFileCacheDirectory;
        }
 
@@ -91,6 +92,7 @@ abstract class FileCacheBase {
                if ( $this->mCached === null ) {
                        $this->mCached = file_exists( $this->cachePath() );
                }
+
                return $this->mCached;
        }
 
@@ -100,6 +102,7 @@ abstract class FileCacheBase {
         */
        public function cacheTimestamp() {
                $timestamp = filemtime( $this->cachePath() );
+
                return ( $timestamp !== false )
                        ? wfTimestamp( TS_MW, $timestamp )
                        : false;
@@ -120,7 +123,8 @@ abstract class FileCacheBase {
 
                $cachetime = $this->cacheTimestamp();
                $good = ( $timestamp <= $cachetime && $wgCacheEpoch <= $cachetime );
-               wfDebug( __METHOD__ . ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good\n" );
+               wfDebug( __METHOD__ .
+                       ": cachetime $cachetime, touched '{$timestamp}' epoch {$wgCacheEpoch}, good $good\n" );
 
                return $good;
        }
@@ -140,6 +144,7 @@ abstract class FileCacheBase {
        public function fetchText() {
                if ( $this->useGzip() ) {
                        $fh = gzopen( $this->cachePath(), 'rb' );
+
                        return stream_get_contents( $fh );
                } else {
                        return file_get_contents( $this->cachePath() );
@@ -148,6 +153,7 @@ abstract class FileCacheBase {
 
        /**
         * Save and compress text to the cache
+        * @param string $text
         * @return string compressed text
         */
        public function saveText( $text ) {
@@ -165,10 +171,12 @@ abstract class FileCacheBase {
                if ( !file_put_contents( $this->cachePath(), $text, LOCK_EX ) ) {
                        wfDebug( __METHOD__ . "() failed saving " . $this->cachePath() . "\n" );
                        $this->mCached = null;
+
                        return false;
                }
 
                $this->mCached = true;
+
                return $text;
        }
 
@@ -262,6 +270,7 @@ abstract class FileCacheBase {
         */
        public function getMissesRecent() {
                global $wgMemc;
+
                return self::MISS_FACTOR * $wgMemc->get( $this->cacheMissKey() );
        }
 
index a933527..285675d 100644 (file)
@@ -41,10 +41,12 @@ class GenderCache {
                if ( $that === null ) {
                        $that = new self();
                }
+
                return $that;
        }
 
-       protected function __construct() {}
+       protected function __construct() {
+       }
 
        /**
         * Returns the default gender option in this wiki.
@@ -54,6 +56,7 @@ class GenderCache {
                if ( $this->default === null ) {
                        $this->default = User::getDefaultOption( 'gender' );
                }
+
                return $this->default;
        }
 
@@ -77,8 +80,8 @@ class GenderCache {
                                        $this->misses++;
                                        wfDebug( __METHOD__ . ": too many misses, returning default onwards\n" );
                                }
-                               return $this->getDefault();
 
+                               return $this->getDefault();
                        } else {
                                $this->misses++;
                                $this->doQuery( $username, $caller );
@@ -184,6 +187,7 @@ class GenderCache {
                if ( $indexSlash !== false ) {
                        $username = substr( $username, 0, $indexSlash );
                }
+
                // normalize underscore/spaces
                return strtr( $username, '_', ' ' );
        }
diff --git a/includes/cache/HTMLCacheUpdate.php b/includes/cache/HTMLCacheUpdate.php
deleted file mode 100644 (file)
index 992809e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/**
- * HTML cache invalidation of all pages linking to a given title.
- *
- * 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 Cache
- */
-
-/**
- * Class to invalidate the HTML cache of all the pages linking to a given title.
- *
- * @ingroup Cache
- */
-class HTMLCacheUpdate implements DeferrableUpdate {
-       /**
-        * @var Title
-        */
-       public $mTitle;
-
-       public $mTable;
-
-       /**
-        * @param $titleTo
-        * @param $table
-        * @param $start bool
-        * @param $end bool
-        */
-       function __construct( Title $titleTo, $table ) {
-               $this->mTitle = $titleTo;
-               $this->mTable = $table;
-       }
-
-       public function doUpdate() {
-               wfProfileIn( __METHOD__ );
-
-               $job = new HTMLCacheUpdateJob(
-                       $this->mTitle,
-                       array(
-                               'table' => $this->mTable,
-                       ) + Job::newRootJobParams( // "overall" refresh links job info
-                               "htmlCacheUpdate:{$this->mTable}:{$this->mTitle->getPrefixedText()}"
-                       )
-               );
-
-               $count = $this->mTitle->getBacklinkCache()->getNumLinks( $this->mTable, 200 );
-               if ( $count >= 200 ) { // many backlinks
-                       JobQueueGroup::singleton()->push( $job );
-                       JobQueueGroup::singleton()->deduplicateRootJob( $job );
-               } else { // few backlinks ($count might be off even if 0)
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->onTransactionIdle( function() use ( $job ) {
-                               $job->run(); // just do the purge query now
-                       } );
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-}
index ab37911..2629995 100644 (file)
@@ -94,6 +94,7 @@ class HTMLFileCache extends FileCacheBase {
                }
                if ( $wgShowIPinHeader || $wgDebugToolbar ) {
                        wfDebug( "HTML file cache skipped. Either \$wgShowIPinHeader and/or \$wgDebugToolbar on\n" );
+
                        return false;
                }
 
@@ -109,6 +110,7 @@ class HTMLFileCache extends FileCacheBase {
                        } elseif ( $query === 'maxage' || $query === 'smaxage' ) {
                                continue;
                        }
+
                        return false;
                }
                $user = $context->getUser();
@@ -116,6 +118,7 @@ class HTMLFileCache extends FileCacheBase {
                // and extensions for auto-detecting user language.
                $ulang = $context->getLanguage()->getCode();
                $clang = $wgContLang->getCode();
+
                // Check that there are no other sources of variation
                return !$user->getId() && !$user->getNewtalk() && $ulang == $clang;
        }
@@ -185,6 +188,7 @@ class HTMLFileCache extends FileCacheBase {
                        // @todo Ugly wfClientAcceptsGzip() function - use context!
                        if ( wfClientAcceptsGzip() ) {
                                header( 'Content-Encoding: gzip' );
+
                                return $compressed;
                        } else {
                                return $text;
index 48b60aa..1a20ab4 100644 (file)
@@ -31,7 +31,7 @@ class LinkBatch {
        /**
         * 2-d array, first index namespace, second index dbkey, value arbitrary
         */
-       var $data = array();
+       public $data = array();
 
        /**
         * For debugging which method is using this class.
@@ -117,6 +117,7 @@ class LinkBatch {
         */
        public function execute() {
                $linkCache = LinkCache::singleton();
+
                return $this->executeInto( $linkCache );
        }
 
@@ -133,6 +134,7 @@ class LinkBatch {
                $this->doGenderQuery();
                $ids = $this->addResultToCache( $cache, $res );
                wfProfileOut( __METHOD__ );
+
                return $ids;
        }
 
@@ -170,6 +172,7 @@ class LinkBatch {
                                $ids[$title->getPrefixedDBkey()] = 0;
                        }
                }
+
                return $ids;
        }
 
@@ -197,6 +200,7 @@ class LinkBatch {
                }
                $res = $dbr->select( $table, $fields, $conds, $caller );
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -217,6 +221,7 @@ class LinkBatch {
 
                $genderCache = GenderCache::singleton();
                $genderCache->doLinkBatch( $this->data, $this->caller );
+
                return true;
        }
 
index 6ac7e7a..de2a728 100644 (file)
@@ -51,6 +51,7 @@ class LinkCache {
                        return self::$instance;
                }
                self::$instance = new LinkCache;
+
                return self::$instance;
        }
 
@@ -77,6 +78,7 @@ class LinkCache {
        /**
         * General accessor to get/set whether SELECT FOR UPDATE should be used
         *
+        * @param $update
         * @return bool
         */
        public function forUpdate( $update = null ) {
@@ -122,21 +124,24 @@ class LinkCache {
        /**
         * Add a link for the title to the link cache
         *
-        * @param $id Integer: page's ID
-        * @param $title Title object
-        * @param $len Integer: text's length
-        * @param $redir Integer: whether the page is a redirect
-        * @param $revision Integer: latest revision's ID
-        * @param $model Integer: latest revision's content model ID
+        * @param int $id Page's ID
+        * @param Title $title
+        * @param int $len Text's length
+        * @param int $redir Whether the page is a redirect
+        * @param int $revision Latest revision's ID
+        * @param int $model Latest revision's content model ID
         */
-       public function addGoodLinkObj( $id, $title, $len = -1, $redir = null, $revision = false, $model = false ) {
+       public function addGoodLinkObj( $id, $title, $len = -1, $redir = null,
+               $revision = 0, $model = 0
+       ) {
                $dbkey = $title->getPrefixedDBkey();
-               $this->mGoodLinks[$dbkey] = intval( $id );
+               $this->mGoodLinks[$dbkey] = (int)$id;
                $this->mGoodLinkFields[$dbkey] = array(
-                       'length' => intval( $len ),
-                       'redirect' => intval( $redir ),
-                       'revision' => intval( $revision ),
-                       'model' => intval( $model ) );
+                       'length' => (int)$len,
+                       'redirect' => (int)$redir,
+                       'revision' => (int)$revision,
+                       'model' => (int)$model
+               );
        }
 
        /**
@@ -218,16 +223,19 @@ class LinkCache {
                $key = $nt->getPrefixedDBkey();
                if ( $this->isBadLink( $key ) || $nt->isExternal() ) {
                        wfProfileOut( __METHOD__ );
+
                        return 0;
                }
                $id = $this->getGoodLinkID( $key );
                if ( $id != 0 ) {
                        wfProfileOut( __METHOD__ );
+
                        return $id;
                }
 
                if ( $key === '' ) {
                        wfProfileOut( __METHOD__ );
+
                        return 0;
                }
 
@@ -262,6 +270,7 @@ class LinkCache {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $id;
        }
 
index 1bfd17b..ccb94a2 100644 (file)
@@ -36,19 +36,19 @@ define( 'MW_LC_VERSION', 2 );
  */
 class LocalisationCache {
        /** Configuration associative array */
-       var $conf;
+       private $conf;
 
        /**
         * True if recaching should only be done on an explicit call to recache().
         * Setting this reduces the overhead of cache freshness checking, which
         * requires doing a stat() for every extension i18n file.
         */
-       var $manualRecache = false;
+       private $manualRecache = false;
 
        /**
         * True to treat all files as expired until they are regenerated by this object.
         */
-       var $forceRecache = false;
+       private $forceRecache = false;
 
        /**
         * The cache data. 3-d array, where the first key is the language code,
@@ -56,14 +56,14 @@ class LocalisationCache {
         * an item specific subkey index. Some items are not arrays and so for those
         * items, there are no subkeys.
         */
-       var $data = array();
+       protected $data = array();
 
        /**
         * The persistent store object. An instance of LCStore.
         *
         * @var LCStore
         */
-       var $store;
+       private $store;
 
        /**
         * A 2-d associative array, code/key, where presence indicates that the item
@@ -72,32 +72,32 @@ class LocalisationCache {
         * For split items, if set, this indicates that all of the subitems have been
         * loaded.
         */
-       var $loadedItems = array();
+       private $loadedItems = array();
 
        /**
         * A 3-d associative array, code/key/subkey, where presence indicates that
         * the subitem is loaded. Only used for the split items, i.e. messages.
         */
-       var $loadedSubitems = array();
+       private $loadedSubitems = array();
 
        /**
         * An array where presence of a key indicates that that language has been
         * initialised. Initialisation includes checking for cache expiry and doing
         * any necessary updates.
         */
-       var $initialisedLangs = array();
+       private $initialisedLangs = array();
 
        /**
         * An array mapping non-existent pseudo-languages to fallback languages. This
         * is filled by initShallowFallback() when data is requested from a language
         * that lacks a Messages*.php file.
         */
-       var $shallowFallbacks = array();
+       private $shallowFallbacks = array();
 
        /**
         * An array where the keys are codes that have been recached by this instance.
         */
-       var $recachedLangs = array();
+       private $recachedLangs = array();
 
        /**
         * All item keys
@@ -106,7 +106,7 @@ class LocalisationCache {
                'fallback', 'namespaceNames', 'bookstoreList',
                'magicWords', 'messages', 'rtl', 'capitalizeAllNouns', 'digitTransformTable',
                'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension',
-               'linkTrail', 'namespaceAliases',
+               'linkTrail', 'linkPrefixCharset', 'namespaceAliases',
                'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
                'defaultDateFormat', 'extraUserToggles', 'specialPageAliases',
                'imageFiles', 'preloadedMessages', 'namespaceGenderAliases',
@@ -158,7 +158,7 @@ class LocalisationCache {
         * Associative array of cached plural rules. The key is the language code,
         * the value is an array of plural rules for that language.
         */
-       var $pluralRules = null;
+       private $pluralRules = null;
 
        /**
         * Associative array of cached plural rule types. The key is the language
@@ -172,9 +172,9 @@ class LocalisationCache {
         * example, {{plural:count|wordform1|wordform2|wordform3}}, rather than
         * {{plural:count|one=wordform1|two=wordform2|many=wordform3}}.
         */
-       var $pluralRuleTypes = null;
+       private $pluralRuleTypes = null;
 
-       var $mergeableKeys = null;
+       private $mergeableKeys = null;
 
        /**
         * Constructor.
@@ -195,16 +195,16 @@ class LocalisationCache {
                        switch ( $conf['store'] ) {
                                case 'files':
                                case 'file':
-                                       $storeClass = 'LCStore_CDB';
+                                       $storeClass = 'LCStoreCDB';
                                        break;
                                case 'db':
-                                       $storeClass = 'LCStore_DB';
+                                       $storeClass = 'LCStoreDB';
                                        break;
                                case 'accel':
-                                       $storeClass = 'LCStore_Accel';
+                                       $storeClass = 'LCStoreAccel';
                                        break;
                                case 'detect':
-                                       $storeClass = $wgCacheDirectory ? 'LCStore_CDB' : 'LCStore_DB';
+                                       $storeClass = $wgCacheDirectory ? 'LCStoreCDB' : 'LCStoreDB';
                                        break;
                                default:
                                        throw new MWException(
@@ -241,6 +241,7 @@ class LocalisationCache {
                                self::$magicWordKeys
                        ) );
                }
+
                return isset( $this->mergeableKeys[$key] );
        }
 
@@ -276,7 +277,8 @@ class LocalisationCache {
         */
        public function getSubitem( $code, $key, $subkey ) {
                if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
-                        !isset( $this->loadedItems[$code][$key] ) ) {
+                       !isset( $this->loadedItems[$code][$key] )
+               ) {
                        wfProfileIn( __METHOD__ . '-load' );
                        $this->loadSubitem( $code, $key, $subkey );
                        wfProfileOut( __METHOD__ . '-load' );
@@ -331,6 +333,7 @@ class LocalisationCache {
 
                if ( isset( $this->shallowFallbacks[$code] ) ) {
                        $this->loadItem( $this->shallowFallbacks[$code], $key );
+
                        return;
                }
 
@@ -358,6 +361,7 @@ class LocalisationCache {
        protected function loadSubitem( $code, $key, $subkey ) {
                if ( !in_array( $key, self::$splitKeys ) ) {
                        $this->loadItem( $code, $key );
+
                        return;
                }
 
@@ -367,12 +371,14 @@ class LocalisationCache {
 
                // Check to see if initLanguage() loaded it for us
                if ( isset( $this->loadedItems[$code][$key] ) ||
-                        isset( $this->loadedSubitems[$code][$key][$subkey] ) ) {
+                       isset( $this->loadedSubitems[$code][$key][$subkey] )
+               ) {
                        return;
                }
 
                if ( isset( $this->shallowFallbacks[$code] ) ) {
                        $this->loadSubitem( $this->shallowFallbacks[$code], $key, $subkey );
+
                        return;
                }
 
@@ -391,15 +397,17 @@ class LocalisationCache {
        public function isExpired( $code ) {
                if ( $this->forceRecache && !isset( $this->recachedLangs[$code] ) ) {
                        wfDebug( __METHOD__ . "($code): forced reload\n" );
+
                        return true;
                }
 
                $deps = $this->store->get( $code, 'deps' );
                $keys = $this->store->get( $code, 'list' );
                $preload = $this->store->get( $code, 'preload' );
-               // Different keys may expire separately, at least in LCStore_Accel
+               // Different keys may expire separately, at least in LCStoreAccel
                if ( $deps === null || $keys === null || $preload === null ) {
                        wfDebug( __METHOD__ . "($code): cache missing, need to make one\n" );
+
                        return true;
                }
 
@@ -411,6 +419,7 @@ class LocalisationCache {
                        if ( !$dep instanceof CacheDependency || $dep->isExpired() ) {
                                wfDebug( __METHOD__ . "($code): cache for $code expired due to " .
                                        get_class( $dep ) . "\n" );
+
                                return true;
                        }
                }
@@ -433,6 +442,7 @@ class LocalisationCache {
                # If the code is of the wrong form for a Messages*.php file, do a shallow fallback
                if ( !Language::isValidBuiltInCode( $code ) ) {
                        $this->initShallowFallback( $code, 'en' );
+
                        return;
                }
 
@@ -445,6 +455,7 @@ class LocalisationCache {
                        } else {
                                $this->initShallowFallback( $code, 'en' );
                        }
+
                        return;
                }
 
@@ -458,6 +469,7 @@ class LocalisationCache {
                                                'Please run maintenance/rebuildLocalisationCache.php.' );
                                }
                                $this->initShallowFallback( $code, 'en' );
+
                                return;
                        } else {
                                throw new MWException( 'Invalid or missing localisation cache.' );
@@ -511,6 +523,7 @@ class LocalisationCache {
                        throw new MWException( __METHOD__ . ": Invalid file type: $_fileType" );
                }
                wfProfileOut( __METHOD__ );
+
                return $data;
        }
 
@@ -527,8 +540,10 @@ class LocalisationCache {
                        $compiledRules = CLDRPluralRuleEvaluator::compile( $rules );
                } catch ( CLDRPluralRuleError $e ) {
                        wfDebugLog( 'l10n', $e->getMessage() . "\n" );
+
                        return array();
                }
+
                return $compiledRules;
        }
 
@@ -616,6 +631,7 @@ class LocalisationCache {
                $fileName = Language::getMessagesFileName( $code );
                if ( !file_exists( $fileName ) ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
 
@@ -633,6 +649,7 @@ class LocalisationCache {
                $deps['plurals-mw'] = new FileDependency( "$IP/languages/data/plurals-mediawiki.xml" );
 
                wfProfileOut( __METHOD__ );
+
                return $data;
        }
 
@@ -747,7 +764,6 @@ class LocalisationCache {
                        foreach ( $data as $key => $value ) {
                                $this->mergeItem( $key, $coreData[$key], $value );
                        }
-
                }
 
                # Fill in the fallback if it's not there already
@@ -885,7 +901,7 @@ class LocalisationCache {
                # Clear out the MessageBlobStore
                # HACK: If using a null (i.e. disabled) storage backend, we
                # can't write to the MessageBlobStore either
-               if ( !$this->store instanceof LCStore_Null ) {
+               if ( !$this->store instanceof LCStoreNull ) {
                        MessageBlobStore::clear();
                }
 
@@ -950,7 +966,7 @@ class LocalisationCache {
         * Disable the storage backend
         */
        public function disableBackend() {
-               $this->store = new LCStore_Null;
+               $this->store = new LCStoreNull;
                $this->manualRecache = false;
        }
 }
@@ -1005,9 +1021,9 @@ interface LCStore {
  * This will work if one of XCache, WinCache or APC cacher is configured.
  * (See ObjectCache.php)
  */
-class LCStore_Accel implements LCStore {
-       var $currentLang;
-       var $keys;
+class LCStoreAccel implements LCStore {
+       private $currentLang;
+       private $keys;
 
        public function __construct() {
                $this->cache = wfGetCache( CACHE_ACCEL );
@@ -1016,6 +1032,7 @@ class LCStore_Accel implements LCStore {
        public function get( $code, $key ) {
                $k = wfMemcKey( 'l10n', $code, 'k', $key );
                $r = $this->cache->get( $k );
+
                return $r === false ? null : $r;
        }
 
@@ -1053,16 +1070,16 @@ class LCStore_Accel implements LCStore {
  * LCStore implementation which uses the standard DB functions to store data.
  * This will work on any MediaWiki installation.
  */
-class LCStore_DB implements LCStore {
-       var $currentLang;
-       var $writesDone = false;
+class LCStoreDB implements LCStore {
+       private $currentLang;
+       private $writesDone = false;
 
        /**
         * @var DatabaseBase
         */
-       var $dbw;
-       var $batch;
-       var $readOnly = false;
+       private $dbw;
+       private $batch;
+       private $readOnly = false;
 
        public function get( $code, $key ) {
                if ( $this->writesDone ) {
@@ -1096,6 +1113,7 @@ class LCStore_DB implements LCStore {
                        if ( $this->dbw->wasReadOnlyError() ) {
                                $this->readOnly = true;
                                $this->dbw->rollback( __METHOD__ );
+
                                return;
                        } else {
                                throw $e;
@@ -1155,8 +1173,11 @@ class LCStore_DB implements LCStore {
  *
  * See Cdb.php and http://cr.yp.to/cdb.html
  */
-class LCStore_CDB implements LCStore {
-       var $readers, $writer, $currentLang, $directory;
+class LCStoreCDB implements LCStore {
+       private $readers;
+       private $writer;
+       private $currentLang;
+       private $directory;
 
        function __construct( $conf = array() ) {
                global $wgCacheDirectory;
@@ -1172,21 +1193,30 @@ class LCStore_CDB implements LCStore {
                if ( !isset( $this->readers[$code] ) ) {
                        $fileName = $this->getFileName( $code );
 
-                       if ( !file_exists( $fileName ) ) {
-                               $this->readers[$code] = false;
-                       } else {
-                               $this->readers[$code] = CdbReader::open( $fileName );
+                       $this->readers[$code] = false;
+                       if ( file_exists( $fileName ) ) {
+                               try {
+                                       $this->readers[$code] = CdbReader::open( $fileName );
+                               } catch ( CdbException $e ) {
+                                       wfDebug( __METHOD__ . ": unable to open cdb file for reading" );
+                               }
                        }
                }
 
                if ( !$this->readers[$code] ) {
                        return null;
                } else {
-                       $value = $this->readers[$code]->get( $key );
-
+                       $value = false;
+                       try {
+                               $value = $this->readers[$code]->get( $key );
+                       } catch ( CdbException $e ) {
+                               wfDebug( __METHOD__ . ": CdbException caught, error message was "
+                                       . $e->getMessage() );
+                       }
                        if ( $value === false ) {
                                return null;
                        }
+
                        return unserialize( $value );
                }
        }
@@ -1204,13 +1234,21 @@ class LCStore_CDB implements LCStore {
                        $this->readers[$code]->close();
                }
 
-               $this->writer = CdbWriter::open( $this->getFileName( $code ) );
+               try {
+                       $this->writer = CdbWriter::open( $this->getFileName( $code ) );
+               } catch ( CdbException $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
                $this->currentLang = $code;
        }
 
        public function finishWrite() {
                // Close the writer
-               $this->writer->close();
+               try {
+                       $this->writer->close();
+               } catch ( CdbException $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
                $this->writer = null;
                unset( $this->readers[$this->currentLang] );
                $this->currentLang = null;
@@ -1220,13 +1258,18 @@ class LCStore_CDB implements LCStore {
                if ( is_null( $this->writer ) ) {
                        throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
                }
-               $this->writer->set( $key, serialize( $value ) );
+               try {
+                       $this->writer->set( $key, serialize( $value ) );
+               } catch ( CdbException $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
        }
 
        protected function getFileName( $code ) {
                if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
                        throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
                }
+
                return "{$this->directory}/l10n_cache-$code.cdb";
        }
 }
@@ -1234,38 +1277,43 @@ class LCStore_CDB implements LCStore {
 /**
  * Null store backend, used to avoid DB errors during install
  */
-class LCStore_Null implements LCStore {
+class LCStoreNull implements LCStore {
        public function get( $code, $key ) {
                return null;
        }
 
-       public function startWrite( $code ) {}
-       public function finishWrite() {}
-       public function set( $key, $value ) {}
+       public function startWrite( $code ) {
+       }
+
+       public function finishWrite() {
+       }
+
+       public function set( $key, $value ) {
+       }
 }
 
 /**
  * A localisation cache optimised for loading large amounts of data for many
  * languages. Used by rebuildLocalisationCache.php.
  */
-class LocalisationCache_BulkLoad extends LocalisationCache {
+class LocalisationCacheBulkLoad extends LocalisationCache {
        /**
         * A cache of the contents of data files.
         * Core files are serialized to avoid using ~1GB of RAM during a recache.
         */
-       var $fileCache = array();
+       private $fileCache = array();
 
        /**
         * Most recently used languages. Uses the linked-list aspect of PHP hashtables
         * to keep the most recently used language codes at the end of the array, and
         * the language codes that are ready to be deleted at the beginning.
         */
-       var $mruLangs = array();
+       private $mruLangs = array();
 
        /**
         * Maximum number of languages that may be loaded into $this->data
         */
-       var $maxLoadedLangs = 10;
+       private $maxLoadedLangs = 10;
 
        /**
         * @param $fileName
@@ -1301,6 +1349,7 @@ class LocalisationCache_BulkLoad extends LocalisationCache {
        public function getItem( $code, $key ) {
                unset( $this->mruLangs[$code] );
                $this->mruLangs[$code] = true;
+
                return parent::getItem( $code, $key );
        }
 
@@ -1313,6 +1362,7 @@ class LocalisationCache_BulkLoad extends LocalisationCache {
        public function getSubitem( $code, $key, $subkey ) {
                unset( $this->mruLangs[$code] );
                $this->mruLangs[$code] = true;
+
                return parent::getSubitem( $code, $key, $subkey );
        }
 
diff --git a/includes/cache/MapCacheLRU.php b/includes/cache/MapCacheLRU.php
new file mode 100644 (file)
index 0000000..3539d8f
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Per-process memory cache for storing items.
+ *
+ * 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 Cache
+ */
+
+/**
+ * Handles a simple LRU key/value map with a maximum number of entries
+ *
+ * Use ProcessCacheLRU if hierarchical purging is needed or objects can become stale
+ *
+ * @see ProcessCacheLRU
+ * @ingroup Cache
+ */
+class MapCacheLRU {
+       /** @var Array */
+       protected $cache = array(); // (key => value)
+
+       protected $maxCacheKeys; // integer; max entries
+
+       /**
+        * @param $maxKeys integer Maximum number of entries allowed (min 1).
+        * @throws MWException When $maxCacheKeys is not an int or =< 0.
+        */
+       public function __construct( $maxKeys ) {
+               if ( !is_int( $maxKeys ) || $maxKeys < 1 ) {
+                       throw new MWException( __METHOD__ . " must be given an integer and >= 1" );
+               }
+               $this->maxCacheKeys = $maxKeys;
+       }
+
+       /**
+        * Set a key/value pair.
+        * This will prune the cache if it gets too large based on LRU.
+        * If the item is already set, it will be pushed to the top of the cache.
+        *
+        * @param $key string
+        * @param $value mixed
+        * @return void
+        */
+       public function set( $key, $value ) {
+               if ( isset( $this->cache[$key] ) ) {
+                       $this->ping( $key ); // push to top
+               } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
+                       reset( $this->cache );
+                       $evictKey = key( $this->cache );
+                       unset( $this->cache[$evictKey] );
+               }
+               $this->cache[$key] = $value;
+       }
+
+       /**
+        * Get the value for a key.
+        * This returns null if the key is not set.
+        * If the item is already set, it will be pushed to the top of the cache.
+        *
+        * @param $key string
+        * @param $prop string
+        * @return mixed
+        */
+       public function get( $key ) {
+               if ( isset( $this->cache[$key] ) ) {
+                       $this->ping( $key ); // push to top
+                       return $this->cache[$key];
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Clear one or several cache entries, or all cache entries
+        *
+        * @param $keys string|Array
+        * @return void
+        */
+       public function clear( $keys = null ) {
+               if ( $keys === null ) {
+                       $this->cache = array();
+               } else {
+                       foreach ( (array)$keys as $key ) {
+                               unset( $this->cache[$key] );
+                       }
+               }
+       }
+
+       /**
+        * Push an entry to the top of the cache
+        *
+        * @param $key string
+        */
+       protected function ping( $key ) {
+               $item = $this->cache[$key];
+               unset( $this->cache[$key] );
+               $this->cache[$key] = $item;
+       }
+}
index a92c87f..8b52728 100644 (file)
@@ -110,6 +110,7 @@ class MessageCache {
                                $wgMsgCacheExpiry
                        );
                }
+
                return self::$instance;
        }
 
@@ -147,6 +148,7 @@ class MessageCache {
                        $this->mParserOptions = new ParserOptions;
                        $this->mParserOptions->setEditSection( false );
                }
+
                return $this->mParserOptions;
        }
 
@@ -179,9 +181,11 @@ class MessageCache {
                                $serialized .= fread( $file, 100000 );
                        }
                        fclose( $file );
+
                        return unserialize( $serialized );
                } else {
                        fclose( $file );
+
                        return false; // Wrong hash
                }
        }
@@ -201,6 +205,7 @@ class MessageCache {
 
                if ( !$file ) {
                        wfDebug( "Unable to open local cache file for writing\n" );
+
                        return;
                }
 
@@ -253,6 +258,7 @@ class MessageCache {
                                wfDebug( __METHOD__ . ": disabled\n" );
                                $shownDisabled = true;
                        }
+
                        return true;
                }
 
@@ -415,6 +421,7 @@ class MessageCache {
                $info = implode( ', ', $where );
                wfDebug( __METHOD__ . ": Loading $code... $info\n" );
                wfProfileOut( __METHOD__ );
+
                return $success;
        }
 
@@ -502,6 +509,7 @@ class MessageCache {
                $cache['VERSION'] = MSG_CACHE_VERSION;
                $cache['EXPIRY'] = wfTimestamp( TS_MW, time() + $this->mExpiry );
                wfProfileOut( __METHOD__ );
+
                return $cache;
        }
 
@@ -517,6 +525,7 @@ class MessageCache {
 
                if ( $this->mDisable ) {
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -584,6 +593,7 @@ class MessageCache {
                if ( wfTimestampNow() >= $cache['EXPIRY'] ) {
                        return true;
                }
+
                return false;
        }
 
@@ -617,6 +627,7 @@ class MessageCache {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $success;
        }
 
@@ -689,7 +700,8 @@ class MessageCache {
         *                   "msg/lang".
         *
         * @throws MWException when given an invalid key
-        * @return string|bool False if the message doesn't exist, otherwise the message (which can be empty)
+        * @return string|bool False if the message doesn't exist, otherwise the
+        *   message (which can be empty)
         */
        function get( $key, $useDB = true, $langcode = true, $isFullKey = false ) {
                global $wgContLang;
@@ -726,7 +738,12 @@ class MessageCache {
 
                // Loop through each language in the fallback list until we find something useful
                $lang = wfGetLangObj( $langcode );
-               $message = $this->getMessageFromFallbackChain( $lang, $lckey, $uckey, !$this->mDisable && $useDB );
+               $message = $this->getMessageFromFallbackChain(
+                       $lang,
+                       $lckey,
+                       $uckey,
+                       !$this->mDisable && $useDB
+               );
 
                // If we still have no message, maybe the key was in fact a full key so try that
                if ( $message === false ) {
@@ -804,7 +821,8 @@ class MessageCache {
                        return $message;
                }
 
-               list( $fallbackChain, $siteFallbackChain ) = Language::getFallbacksIncludingSiteLanguage( $langcode );
+               list( $fallbackChain, $siteFallbackChain ) =
+                       Language::getFallbacksIncludingSiteLanguage( $langcode );
 
                // Next try checking the database for all of the fallback languages of the requested language.
                if ( $useDB ) {
@@ -897,11 +915,13 @@ class MessageCache {
                if ( $entry ) {
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
                                $this->mCache[$code][$title] = $entry;
+
                                // The message exists, so make sure a string
                                // is returned.
                                return (string)substr( $entry, 1 );
                        } elseif ( $entry === '!NONEXISTENT' ) {
                                $this->mCache[$code][$title] = '!NONEXISTENT';
+
                                return false;
                        } else {
                                # Corrupt/obsolete entry, delete it
@@ -983,6 +1003,7 @@ class MessageCache {
                        $this->mInParser = false;
                        $popts->setUserLang( $userlang );
                }
+
                return $message;
        }
 
@@ -1003,6 +1024,7 @@ class MessageCache {
                                $this->mParser = clone $wgParser;
                        }
                }
+
                return $this->mParser;
        }
 
@@ -1043,6 +1065,7 @@ class MessageCache {
                $this->mInParser = false;
 
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -1085,6 +1108,7 @@ class MessageCache {
                }
 
                $message = implode( '/', $pieces );
+
                return array( $message, $lang );
        }
 
@@ -1109,6 +1133,7 @@ class MessageCache {
                unset( $cache['EXPIRY'] );
                // Remove any !NONEXISTENT keys
                $cache = array_diff( $cache, array( '!NONEXISTENT' ) );
+
                // Keys may appear with a capital first letter. lcfirst them.
                return array_map( array( $wgContLang, 'lcfirst' ), array_keys( $cache ) );
        }
index 76c76f3..786d74a 100644 (file)
@@ -79,6 +79,7 @@ class ProcessCacheLRU {
                if ( isset( $this->cache[$key][$prop] ) ) {
                        return ( $maxAge <= 0 || ( time() - $this->cacheTimes[$key][$prop] ) <= $maxAge );
                }
+
                return false;
        }
 
index 2ad7b85..3ace396 100644 (file)
@@ -80,8 +80,10 @@ class ResourceFileCache extends FileCacheBase {
                        } elseif ( $query === 'debug' && $val === 'false' ) {
                                continue;
                        }
+
                        return false;
                }
+
                return true; // cacheable
        }
 
@@ -104,6 +106,7 @@ class ResourceFileCache extends FileCacheBase {
                                $this->getMissesRecent() >= self::MISS_THRESHOLD // many misses
                        );
                }
+
                return $this->mCacheWorthy;
        }
 }
diff --git a/includes/cache/SquidUpdate.php b/includes/cache/SquidUpdate.php
deleted file mode 100644 (file)
index 71afeba..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-/**
- * Squid cache purging.
- *
- * 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 Cache
- */
-
-/**
- * Handles purging appropriate Squid URLs given a title (or titles)
- * @ingroup Cache
- */
-class SquidUpdate {
-
-       /**
-        * Collection of URLs to purge.
-        * @var array
-        */
-       protected $urlArr;
-
-       /**
-        * @param array $urlArr Collection of URLs to purge
-        * @param bool|int $maxTitles Maximum number of unique URLs to purge
-        */
-       public function __construct( $urlArr = array(), $maxTitles = false ) {
-               global $wgMaxSquidPurgeTitles;
-               if ( $maxTitles === false ) {
-                       $maxTitles = $wgMaxSquidPurgeTitles;
-               }
-
-               // Remove duplicate URLs from list
-               $urlArr = array_unique( $urlArr );
-               if ( count( $urlArr ) > $maxTitles ) {
-                       // Truncate to desired maximum URL count
-                       $urlArr = array_slice( $urlArr, 0, $maxTitles );
-               }
-               $this->urlArr = $urlArr;
-       }
-
-       /**
-        * Create a SquidUpdate from the given Title object.
-        *
-        * The resulting SquidUpdate will purge the given Title's URLs as well as
-        * the pages that link to it. Capped at $wgMaxSquidPurgeTitles total URLs.
-        *
-        * @param Title $title
-        * @return SquidUpdate
-        */
-       public static function newFromLinksTo( Title $title ) {
-               global $wgMaxSquidPurgeTitles;
-               wfProfileIn( __METHOD__ );
-
-               # Get a list of URLs linking to this page
-               $dbr = wfGetDB( DB_SLAVE );
-               $res = $dbr->select( array( 'links', 'page' ),
-                       array( 'page_namespace', 'page_title' ),
-                       array(
-                               'pl_namespace' => $title->getNamespace(),
-                               'pl_title' => $title->getDBkey(),
-                               'pl_from=page_id' ),
-                       __METHOD__ );
-               $blurlArr = $title->getSquidURLs();
-               if ( $res->numRows() <= $wgMaxSquidPurgeTitles ) {
-                       foreach ( $res as $BL ) {
-                               $tobj = Title::makeTitle( $BL->page_namespace, $BL->page_title );
-                               $blurlArr[] = $tobj->getInternalURL();
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return new SquidUpdate( $blurlArr );
-       }
-
-       /**
-        * Create a SquidUpdate from an array of Title objects, or a TitleArray object
-        *
-        * @param array $titles
-        * @param array $urlArr
-        * @return SquidUpdate
-        */
-       public static function newFromTitles( $titles, $urlArr = array() ) {
-               global $wgMaxSquidPurgeTitles;
-               $i = 0;
-               foreach ( $titles as $title ) {
-                       $urlArr[] = $title->getInternalURL();
-                       if ( $i++ > $wgMaxSquidPurgeTitles ) {
-                               break;
-                       }
-               }
-               return new SquidUpdate( $urlArr );
-       }
-
-       /**
-        * @param Title $title
-        * @return SquidUpdate
-        */
-       public static function newSimplePurge( Title $title ) {
-               $urlArr = $title->getSquidURLs();
-               return new SquidUpdate( $urlArr );
-       }
-
-       /**
-        * Purges the list of URLs passed to the constructor.
-        */
-       public function doUpdate() {
-               self::purge( $this->urlArr );
-       }
-
-       /**
-        * Purges a list of Squids defined in $wgSquidServers.
-        * $urlArr should contain the full URLs to purge as values
-        * (example: $urlArr[] = 'http://my.host/something')
-        * XXX report broken Squids per mail or log
-        *
-        * @param array $urlArr List of full URLs to purge
-        */
-       public static function purge( $urlArr ) {
-               global $wgSquidServers, $wgHTCPRouting;
-
-               if ( !$urlArr ) {
-                       return;
-               }
-
-               wfDebugLog( 'squid', __METHOD__ . ': ' . implode( ' ', $urlArr ) . "\n" );
-
-               if ( $wgHTCPRouting ) {
-                       self::HTCPPurge( $urlArr );
-               }
-
-               wfProfileIn( __METHOD__ );
-
-               // Remove duplicate URLs
-               $urlArr = array_unique( $urlArr );
-               // Maximum number of parallel connections per squid
-               $maxSocketsPerSquid = 8;
-               // Number of requests to send per socket
-               // 400 seems to be a good tradeoff, opening a socket takes a while
-               $urlsPerSocket = 400;
-               $socketsPerSquid = ceil( count( $urlArr ) / $urlsPerSocket );
-               if ( $socketsPerSquid > $maxSocketsPerSquid ) {
-                       $socketsPerSquid = $maxSocketsPerSquid;
-               }
-
-               $pool = new SquidPurgeClientPool;
-               $chunks = array_chunk( $urlArr, ceil( count( $urlArr ) / $socketsPerSquid ) );
-               foreach ( $wgSquidServers as $server ) {
-                       foreach ( $chunks as $chunk ) {
-                               $client = new SquidPurgeClient( $server );
-                               foreach ( $chunk as $url ) {
-                                       $client->queuePurge( $url );
-                               }
-                               $pool->addClient( $client );
-                       }
-               }
-               $pool->run();
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Send Hyper Text Caching Protocol (HTCP) CLR requests.
-        *
-        * @throws MWException
-        * @param array $urlArr Collection of URLs to purge
-        */
-       public static function HTCPPurge( $urlArr ) {
-               global $wgHTCPRouting, $wgHTCPMulticastTTL;
-               wfProfileIn( __METHOD__ );
-
-               // HTCP CLR operation
-               $htcpOpCLR = 4;
-
-               // @todo FIXME: PHP doesn't support these socket constants (include/linux/in.h)
-               if ( !defined( "IPPROTO_IP" ) ) {
-                       define( "IPPROTO_IP", 0 );
-                       define( "IP_MULTICAST_LOOP", 34 );
-                       define( "IP_MULTICAST_TTL", 33 );
-               }
-
-               // pfsockopen doesn't work because we need set_sock_opt
-               $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
-               if ( ! $conn ) {
-                       $errstr = socket_strerror( socket_last_error() );
-                       wfDebugLog( 'squid', __METHOD__ .
-                               ": Error opening UDP socket: $errstr\n" );
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               // Set socket options
-               socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_LOOP, 0 );
-               if ( $wgHTCPMulticastTTL != 1 ) {
-                       // Set multicast time to live (hop count) option on socket
-                       socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_TTL,
-                               $wgHTCPMulticastTTL );
-               }
-
-               // Remove duplicate URLs from collection
-               $urlArr = array_unique( $urlArr );
-               foreach ( $urlArr as $url ) {
-                       if ( !is_string( $url ) ) {
-                               wfProfileOut( __METHOD__ );
-                               throw new MWException( 'Bad purge URL' );
-                       }
-                       $url = self::expand( $url );
-                       $conf = self::getRuleForURL( $url, $wgHTCPRouting );
-                       if ( !$conf ) {
-                               wfDebugLog( 'squid', __METHOD__ .
-                                       "No HTCP rule configured for URL {$url} , skipping\n" );
-                               continue;
-                       }
-
-                       if ( isset( $conf['host'] ) && isset( $conf['port'] ) ) {
-                               // Normalize single entries
-                               $conf = array( $conf );
-                       }
-                       foreach ( $conf as $subconf ) {
-                               if ( !isset( $subconf['host'] ) || !isset( $subconf['port'] ) ) {
-                                       wfProfileOut( __METHOD__ );
-                                       throw new MWException( "Invalid HTCP rule for URL $url\n" );
-                               }
-                       }
-
-                       // Construct a minimal HTCP request diagram
-                       // as per RFC 2756
-                       // Opcode 'CLR', no response desired, no auth
-                       $htcpTransID = rand();
-
-                       $htcpSpecifier = pack( 'na4na*na8n',
-                               4, 'HEAD', strlen( $url ), $url,
-                               8, 'HTTP/1.0', 0 );
-
-                       $htcpDataLen = 8 + 2 + strlen( $htcpSpecifier );
-                       $htcpLen = 4 + $htcpDataLen + 2;
-
-                       // Note! Squid gets the bit order of the first
-                       // word wrong, wrt the RFC. Apparently no other
-                       // implementation exists, so adapt to Squid
-                       $htcpPacket = pack( 'nxxnCxNxxa*n',
-                               $htcpLen, $htcpDataLen, $htcpOpCLR,
-                               $htcpTransID, $htcpSpecifier, 2 );
-
-                       wfDebugLog( 'squid', __METHOD__ .
-                               "Purging URL $url via HTCP\n" );
-                       foreach ( $conf as $subconf ) {
-                               socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
-                                       $subconf['host'], $subconf['port'] );
-                       }
-               }
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Expand local URLs to fully-qualified URLs using the internal protocol
-        * and host defined in $wgInternalServer. Input that's already fully-
-        * qualified will be passed through unchanged.
-        *
-        * This is used to generate purge URLs that may be either local to the
-        * main wiki or include a non-native host, such as images hosted on a
-        * second internal server.
-        *
-        * Client functions should not need to call this.
-        *
-        * @param string $url
-        * @return string
-        */
-       public static function expand( $url ) {
-               return wfExpandUrl( $url, PROTO_INTERNAL );
-       }
-
-       /**
-        * Find the HTCP routing rule to use for a given URL.
-        * @param string $url URL to match
-        * @param array $rules Array of rules, see $wgHTCPRouting for format and behavior
-        * @return mixed Element of $rules that matched, or false if nothing matched
-        */
-       private static function getRuleForURL( $url, $rules ) {
-               foreach ( $rules as $regex => $routing ) {
-                       if ( $regex === '' || preg_match( $regex, $url ) ) {
-                               return $routing;
-                       }
-               }
-               return false;
-       }
-}
index 6085f58..cea3bf2 100644 (file)
@@ -36,10 +36,12 @@ class UserCache {
                if ( $instance === null ) {
                        $instance = new self();
                }
+
                return $instance;
        }
 
-       protected function __construct() {}
+       protected function __construct() {
+       }
 
        /**
         * Get a property of a user based on their user ID
@@ -53,6 +55,7 @@ class UserCache {
                        wfDebug( __METHOD__ . ": querying DB for prop '$prop' for user ID '$userId'.\n" );
                        $this->doQuery( array( $userId ) ); // cache miss
                }
+
                return isset( $this->cache[$userId][$prop] )
                        ? $this->cache[$userId][$prop]
                        : false; // user does not exist?
@@ -63,6 +66,7 @@ class UserCache {
         *
         * @param integer $userId
         * @param string $ip
+        * @return string
         * @since 1.22
         */
        public function getUserName( $userId, $ip ) {
index bf800c4..a9c3a67 100644 (file)
  */
 
 class ChangesList extends ContextSource {
-
        /**
         * @var Skin
         */
        public $skin;
 
        protected $watchlist = false;
-
+       protected $lastdate;
        protected $message;
+       protected $rc_cache;
+       protected $rcCacheIndex;
+       protected $rclistOpen;
+       protected $rcMoveIndex;
 
        /**
         * Changeslist constructor
         *
-        * @param $obj Skin or IContextSource
+        * @param Skin|IContextSource $obj
         */
        public function __construct( $obj ) {
                if ( $obj instanceof IContextSource ) {
@@ -49,25 +52,12 @@ class ChangesList extends ContextSource {
                $this->preCacheMessages();
        }
 
-       /**
-        * Fetch an appropriate changes list class for the main context
-        * This first argument used to be an User object.
-        *
-        * @deprecated in 1.18; use newFromContext() instead
-        * @param string|User $unused Unused
-        * @return ChangesList|EnhancedChangesList|OldChangesList derivative
-        */
-       public static function newFromUser( $unused ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               return self::newFromContext( RequestContext::getMain() );
-       }
-
        /**
         * Fetch an appropriate changes list class for the specified context
         * Some users might want to use an enhanced list format, for instance
         *
-        * @param $context IContextSource to use
-        * @return ChangesList|EnhancedChangesList|OldChangesList derivative
+        * @param IContextSource $context
+        * @return ChangesList derivative
         */
        public static function newFromContext( IContextSource $context ) {
                $user = $context->getUser();
@@ -75,6 +65,7 @@ class ChangesList extends ContextSource {
                $list = null;
                if ( wfRunHooks( 'FetchChangesList', array( $user, &$sk, &$list ) ) ) {
                        $new = $context->getRequest()->getBool( 'enhanced', $user->getOption( 'usenewrc' ) );
+
                        return $new ? new EnhancedChangesList( $context ) : new OldChangesList( $context );
                } else {
                        return $list;
@@ -108,7 +99,7 @@ class ChangesList extends ContextSource {
         * Returns the appropriate flags for new page, minor change and patrolling
         * @param array $flags Associative array of 'flag' => Bool
         * @param string $nothing to use for empty space
-        * @return String
+        * @return string
         */
        public function recentChangesFlags( $flags, $nothing = '&#160;' ) {
                global $wgRecentChangesFlags;
@@ -118,6 +109,7 @@ class ChangesList extends ContextSource {
                                ? self::flag( $flag )
                                : $nothing;
                }
+
                return $f;
        }
 
@@ -128,7 +120,7 @@ class ChangesList extends ContextSource {
         * "!" respectively, plus it will have an appropriate title and class.
         *
         * @param string $flag One key of $wgRecentChangesFlags
-        * @return String: Raw HTML
+        * @return string Raw HTML
         */
        public static function flag( $flag ) {
                static $flagInfos = null;
@@ -153,14 +145,14 @@ class ChangesList extends ContextSource {
                        $flag = $map[$flag];
                }
 
-               return "<abbr class='" . $flagInfos[$flag]['class'] . "' title='" . $flagInfos[$flag]['title'] . "'>" .
-                       $flagInfos[$flag]['letter'] .
+               return "<abbr class='" . $flagInfos[$flag]['class'] . "' title='" .
+                       $flagInfos[$flag]['title'] . "'>" . $flagInfos[$flag]['letter'] .
                        '</abbr>';
        }
 
        /**
         * Returns text for the start of the tabular part of RC
-        * @return String
+        * @return string
         */
        public function beginRecentChangesList() {
                $this->rc_cache = array();
@@ -169,15 +161,16 @@ class ChangesList extends ContextSource {
                $this->lastdate = '';
                $this->rclistOpen = false;
                $this->getOutput()->addModuleStyles( 'mediawiki.special.changeslist' );
+
                return '';
        }
 
        /**
         * Show formatted char difference
-        * @param $old Integer: bytes
-        * @param $new Integer: bytes
-        * @param $context IContextSource context to use
-        * @return String
+        * @param int $old Number of bytes
+        * @param int $new Number of bytes
+        * @param IContextSource $context
+        * @return string
         */
        public static function showCharacterDifference( $old, $new, IContextSource $context = null ) {
                global $wgRCChangedSizeThreshold, $wgMiserMode;
@@ -211,12 +204,10 @@ class ChangesList extends ContextSource {
 
                if ( $szdiff === 0 ) {
                        $formattedSizeClass = 'mw-plusminus-null';
-               }
-               if ( $szdiff > 0 ) {
+               } elseif ( $szdiff > 0 ) {
                        $formattedSize = '+' . $formattedSize;
                        $formattedSizeClass = 'mw-plusminus-pos';
-               }
-               if ( $szdiff < 0 ) {
+               } else {
                        $formattedSizeClass = 'mw-plusminus-neg';
                }
 
@@ -326,7 +317,9 @@ class ChangesList extends ContextSource {
                                'action' => 'history'
                        )
                );
-               $s .= $this->msg( 'parentheses' )->rawParams( $diffhist )->escaped() . ' <span class="mw-changeslist-separator">. .</span> ';
+               // @todo FIXME: Hard coded ". .". Is there a message for this? Should there be?
+               $s .= $this->msg( 'parentheses' )->rawParams( $diffhist )->escaped() .
+                       ' <span class="mw-changeslist-separator">. .</span> ';
        }
 
        /**
@@ -366,8 +359,12 @@ class ChangesList extends ContextSource {
         * @return string HTML fragment
         */
        public function getTimestamp( $rc ) {
+               // @todo FIXME: Hard coded ". .". Is there a message for this? Should there be?
                return $this->message['semicolon-separator'] . '<span class="mw-changeslist-date">' .
-                       $this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() ) . '</span> <span class="mw-changeslist-separator">. .</span> ';
+                       $this->getLanguage()->userTime(
+                               $rc->mAttribs['rc_timestamp'],
+                               $this->getUser()
+                       ) . '</span> <span class="mw-changeslist-separator">. .</span> ';
        }
 
        /**
@@ -388,7 +385,8 @@ class ChangesList extends ContextSource {
         */
        public function insertUserRelatedLinks( &$s, &$rc ) {
                if ( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
-                       $s .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
+                       $s .= ' <span class="history-deleted">' .
+                               $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
                } else {
                        $s .= $this->getLanguage()->getDirMark() . Linker::userLink( $rc->mAttribs['rc_user'],
                                $rc->mAttribs['rc_user_text'] );
@@ -407,6 +405,7 @@ class ChangesList extends ContextSource {
                $formatter->setContext( $this->getContext() );
                $formatter->setShowUserToolLinks( true );
                $mark = $this->getLanguage()->getDirMark();
+
                return $formatter->getActionText() . " $mark" . $formatter->getComment();
        }
 
@@ -418,11 +417,13 @@ class ChangesList extends ContextSource {
        public function insertComment( $rc ) {
                if ( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) {
                        if ( $this->isDeleted( $rc, Revision::DELETED_COMMENT ) ) {
-                               return ' <span class="history-deleted">' . $this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
+                               return ' <span class="history-deleted">' .
+                                       $this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
                        } else {
                                return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
                        }
                }
+
                return '';
        }
 
@@ -442,14 +443,17 @@ class ChangesList extends ContextSource {
 
        /**
         * Returns the string which indicates the number of watching users
+        * @param int $count Number of user watching a page
         * @return string
         */
        protected function numberofWatchingusers( $count ) {
                static $cache = array();
                if ( $count > 0 ) {
                        if ( !isset( $cache[$count] ) ) {
-                               $cache[$count] = $this->msg( 'number_of_watching_users_RCview' )->numParams( $count )->escaped();
+                               $cache[$count] = $this->msg( 'number_of_watching_users_RCview' )
+                                       ->numParams( $count )->escaped();
                        }
+
                        return $cache[$count];
                } else {
                        return '';
@@ -458,9 +462,9 @@ class ChangesList extends ContextSource {
 
        /**
         * Determine if said field of a revision is hidden
-        * @param $rc RCCacheEntry
-        * @param $field Integer: one of DELETED_* bitfield constants
-        * @return Boolean
+        * @param RCCacheEntry|RecentChange $rc
+        * @param int $field One of DELETED_* bitfield constants
+        * @return bool
         */
        public static function isDeleted( $rc, $field ) {
                return ( $rc->mAttribs['rc_deleted'] & $field ) == $field;
@@ -469,10 +473,10 @@ class ChangesList extends ContextSource {
        /**
         * Determine if the current user is allowed to view a particular
         * field of this revision, if it's marked as deleted.
-        * @param $rc RCCacheEntry
-        * @param $field Integer
-        * @param $user User object to check, or null to use $wgUser
-        * @return Boolean
+        * @param RCCacheEntry|RecentChange $rc
+        * @param int $field
+        * @param User $user User object to check, or null to use $wgUser
+        * @return bool
         */
        public static function userCan( $rc, $field, User $user = null ) {
                if ( $rc->mAttribs['rc_type'] == RC_LOG ) {
@@ -501,12 +505,16 @@ class ChangesList extends ContextSource {
         * @param $rc RecentChange
         */
        public function insertRollback( &$s, &$rc ) {
-               if ( $rc->mAttribs['rc_type'] == RC_EDIT && $rc->mAttribs['rc_this_oldid'] && $rc->mAttribs['rc_cur_id'] ) {
+               if ( $rc->mAttribs['rc_type'] == RC_EDIT
+                       && $rc->mAttribs['rc_this_oldid']
+                       && $rc->mAttribs['rc_cur_id']
+               ) {
                        $page = $rc->getTitle();
                        /** Check for rollback and edit permissions, disallow special pages, and only
-                         * show a link on the top-most revision */
-                       if ( $this->getUser()->isAllowed( 'rollback' ) && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid'] )
-                       {
+                        * show a link on the top-most revision */
+                       if ( $this->getUser()->isAllowed( 'rollback' )
+                               && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid']
+                       ) {
                                $rev = new Revision( array(
                                        'title' => $page,
                                        'id' => $rc->mAttribs['rc_this_oldid'],
@@ -529,7 +537,10 @@ class ChangesList extends ContextSource {
                        return;
                }
 
-               list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow( $rc->mAttribs['ts_tags'], 'changeslist' );
+               list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow(
+                       $rc->mAttribs['ts_tags'],
+                       'changeslist'
+               );
                $classes = array_merge( $classes, $newClasses );
                $s .= ' ' . $tagSummary;
        }
@@ -539,14 +550,32 @@ class ChangesList extends ContextSource {
        }
 
        protected function showAsUnpatrolled( RecentChange $rc ) {
-               $unpatrolled = false;
-               if ( !$rc->mAttribs['rc_patrolled'] ) {
-                       if ( $this->getUser()->useRCPatrol() ) {
-                               $unpatrolled = true;
-                       } elseif ( $this->getUser()->useNPPatrol() && $rc->mAttribs['rc_type'] == RC_NEW ) {
-                               $unpatrolled = true;
+               return self::isUnpatrolled( $rc, $this->getUser() );
+       }
+
+       /**
+        * @param object|RecentChange $rc Database row from recentchanges or a RecentChange object
+        * @param User $user
+        * @return bool
+        */
+       public static function isUnpatrolled( $rc, User $user ) {
+               if ( $rc instanceof RecentChange ) {
+                       $isPatrolled = $rc->mAttribs['rc_patrolled'];
+                       $rcType = $rc->mAttribs['rc_type'];
+               } else {
+                       $isPatrolled = $rc->rc_patrolled;
+                       $rcType = $rc->rc_type;
+               }
+
+               if ( !$isPatrolled ) {
+                       if ( $user->useRCPatrol() ) {
+                               return true;
+                       }
+                       if ( $user->useNPPatrol() && $rcType == RC_NEW ) {
+                               return true;
                        }
                }
-               return $unpatrolled;
+
+               return false;
        }
 }
index 433adb3..1727da0 100644 (file)
@@ -42,8 +42,10 @@ class EnhancedChangesList extends ChangesList {
                        'jquery.makeCollapsible',
                        'mediawiki.icon',
                ) );
+
                return '';
        }
+
        /**
         * Format a line for enhanced recentchange (aka with javascript and block of lines).
         *
@@ -55,14 +57,14 @@ class EnhancedChangesList extends ChangesList {
        public function recentChangesLine( &$baseRC, $watched = false ) {
                wfProfileIn( __METHOD__ );
 
-               # Create a specialised object
-               $rc = RCCacheEntry::newFromParent( $baseRC );
-
-               $curIdEq = array( 'curid' => $rc->mAttribs['rc_cur_id'] );
-
                # If it's a new day, add the headline and flush the cache
-               $date = $this->getLanguage()->userDate( $rc->mAttribs['rc_timestamp'], $this->getUser() );
+               $date = $this->getLanguage()->userDate(
+                       $baseRC->mAttribs['rc_timestamp'],
+                       $this->getUser()
+               );
+
                $ret = '';
+
                if ( $date != $this->lastdate ) {
                        # Process current cache
                        $ret = $this->recentChangesBlock();
@@ -71,53 +73,62 @@ class EnhancedChangesList extends ChangesList {
                        $this->lastdate = $date;
                }
 
+               # Create a specialised object
+               $cacheEntry = RCCacheEntry::newFromParent( $baseRC );
+
+               $curIdEq = array( 'curid' => $cacheEntry->mAttribs['rc_cur_id'] );
+
                # Should patrol-related stuff be shown?
-               $rc->unpatrolled = $this->showAsUnpatrolled( $rc );
+               $cacheEntry->unpatrolled = $this->showAsUnpatrolled( $cacheEntry );
 
                $showdifflinks = true;
+
                # Make article link
-               $type = $rc->mAttribs['rc_type'];
-               $logType = $rc->mAttribs['rc_log_type'];
+               $type = $cacheEntry->mAttribs['rc_type'];
+               $logType = $cacheEntry->mAttribs['rc_log_type'];
+
                // Page moves, very old style, not supported anymore
                if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
                // New unpatrolled pages
-               } elseif ( $rc->unpatrolled && $type == RC_NEW ) {
-                       $clink = Linker::linkKnown( $rc->getTitle() );
+               } elseif ( $cacheEntry->unpatrolled && $type == RC_NEW ) {
+                       $clink = Linker::linkKnown( $cacheEntry->getTitle() );
                // Log entries
                } elseif ( $type == RC_LOG ) {
                        if ( $logType ) {
                                $logtitle = SpecialPage::getTitleFor( 'Log', $logType );
                                $logpage = new LogPage( $logType );
                                $logname = $logpage->getName()->escaped();
-                               $clink = $this->msg( 'parentheses' )->rawParams( Linker::linkKnown( $logtitle, $logname ) )->escaped();
+                               $clink = $this->msg( 'parentheses' )
+                                       ->rawParams( Linker::linkKnown( $logtitle, $logname ) )->escaped();
                        } else {
-                               $clink = Linker::link( $rc->getTitle() );
+                               $clink = Linker::link( $cacheEntry->getTitle() );
                        }
                        $watched = false;
                // Log entries (old format) and special pages
-               } elseif ( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
+               } elseif ( $cacheEntry->mAttribs['rc_namespace'] == NS_SPECIAL ) {
                        wfDebug( "Unexpected special page in recentchanges\n" );
                        $clink = '';
                // Edits
                } else {
-                       $clink = Linker::linkKnown( $rc->getTitle() );
+                       $clink = Linker::linkKnown( $cacheEntry->getTitle() );
                }
 
                # Don't show unusable diff links
-               if ( !ChangesList::userCan( $rc, Revision::DELETED_TEXT, $this->getUser() ) ) {
+               if ( !ChangesList::userCan( $cacheEntry, Revision::DELETED_TEXT, $this->getUser() ) ) {
                        $showdifflinks = false;
                }
 
-               $time = $this->getLanguage()->userTime( $rc->mAttribs['rc_timestamp'], $this->getUser() );
-               $rc->watched = $watched;
-               $rc->link = $clink;
-               $rc->timestamp = $time;
-               $rc->numberofWatchingusers = $baseRC->numberofWatchingusers;
+               $time = $this->getLanguage()->userTime( $cacheEntry->mAttribs['rc_timestamp'], $this->getUser() );
+
+               $cacheEntry->watched = $watched;
+               $cacheEntry->link = $clink;
+               $cacheEntry->timestamp = $time;
+               $cacheEntry->numberofWatchingusers = $baseRC->numberofWatchingusers;
 
                # Make "cur" and "diff" links.  Do not use link(), it is too slow if
                # called too many times (50% of CPU time on RecentChanges!).
-               $thisOldid = $rc->mAttribs['rc_this_oldid'];
-               $lastOldid = $rc->mAttribs['rc_last_oldid'];
+               $thisOldid = $cacheEntry->mAttribs['rc_this_oldid'];
+               $lastOldid = $cacheEntry->mAttribs['rc_last_oldid'];
 
                $querycur = $curIdEq + array( 'diff' => '0', 'oldid' => $thisOldid );
                $querydiff = $curIdEq + array( 'diff' => $thisOldid, 'oldid' => $lastOldid );
@@ -129,13 +140,13 @@ class EnhancedChangesList extends ChangesList {
                        if ( $type != RC_NEW ) {
                                $curLink = $this->message['cur'];
                        } else {
-                               $curUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querycur ) );
+                               $curUrl = htmlspecialchars( $cacheEntry->getTitle()->getLinkURL( $querycur ) );
                                $curLink = "<a href=\"$curUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>";
                        }
                        $diffLink = $this->message['diff'];
                } else {
-                       $diffUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querydiff ) );
-                       $curUrl = htmlspecialchars( $rc->getTitle()->getLinkURL( $querycur ) );
+                       $diffUrl = htmlspecialchars( $cacheEntry->getTitle()->getLinkURL( $querydiff ) );
+                       $curUrl = htmlspecialchars( $cacheEntry->getTitle()->getLinkURL( $querycur ) );
                        $diffLink = "<a href=\"$diffUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['diff']}</a>";
                        $curLink = "<a href=\"$curUrl\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>";
                }
@@ -146,29 +157,38 @@ class EnhancedChangesList extends ChangesList {
                } elseif ( in_array( $type, array( RC_LOG, RC_MOVE, RC_MOVE_OVER_REDIRECT ) ) ) {
                        $lastLink = $this->message['last'];
                } else {
-                       $lastLink = Linker::linkKnown( $rc->getTitle(), $this->message['last'],
+                       $lastLink = Linker::linkKnown( $cacheEntry->getTitle(), $this->message['last'],
                                array(), $curIdEq + array( 'diff' => $thisOldid, 'oldid' => $lastOldid ) );
                }
 
                # Make user links
-               if ( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
-                       $rc->userlink = ' <span class="history-deleted">' . $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
+               if ( $this->isDeleted( $cacheEntry, Revision::DELETED_USER ) ) {
+                       $cacheEntry->userlink = ' <span class="history-deleted">' .
+                               $this->msg( 'rev-deleted-user' )->escaped() . '</span>';
                } else {
-                       $rc->userlink = Linker::userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
-                       $rc->usertalklink = Linker::userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
+                       $cacheEntry->userlink = Linker::userLink(
+                               $cacheEntry->mAttribs['rc_user'],
+                               $cacheEntry->mAttribs['rc_user_text']
+                       );
+
+                       $cacheEntry->usertalklink = Linker::userToolLinks(
+                               $cacheEntry->mAttribs['rc_user'],
+                               $cacheEntry->mAttribs['rc_user_text']
+                       );
                }
 
-               $rc->lastlink = $lastLink;
-               $rc->curlink = $curLink;
-               $rc->difflink = $diffLink;
+               $cacheEntry->lastlink = $lastLink;
+               $cacheEntry->curlink = $curLink;
+               $cacheEntry->difflink = $diffLink;
 
                # Put accumulated information into the cache, for later display
                # Page moves go on their own line
-               $title = $rc->getTitle();
+               $title = $cacheEntry->getTitle();
                $secureName = $title->getPrefixedDBkey();
+
                if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) {
                        # Use an @ character to prevent collision with page names
-                       $this->rc_cache['@@' . ( $this->rcMoveIndex++ )] = array( $rc );
+                       $this->rc_cache['@@' . ( $this->rcMoveIndex++ )] = array( $cacheEntry );
                } else {
                        # Logs are grouped by type
                        if ( $type == RC_LOG ) {
@@ -178,7 +198,7 @@ class EnhancedChangesList extends ChangesList {
                                $this->rc_cache[$secureName] = array();
                        }
 
-                       array_push( $this->rc_cache[$secureName], $rc );
+                       array_push( $this->rc_cache[$secureName], $cacheEntry );
                }
 
                wfProfileOut( __METHOD__ );
@@ -200,10 +220,10 @@ class EnhancedChangesList extends ChangesList {
                if ( $block[0]->mAttribs['rc_log_type'] ) {
                        # Log entry
                        $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-'
-                                       . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
+                               . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
                } else {
                        $classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns'
-                                       . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
+                               . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
                }
                $classes[] = $block[0]->watched && $block[0]->mAttribs['rc_timestamp'] >= $block[0]->watched
                        ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
@@ -268,7 +288,9 @@ class EnhancedChangesList extends ChangesList {
                        $text = $userlink;
                        $text .= $this->getLanguage()->getDirMark();
                        if ( $count > 1 ) {
-                               $text .= ' ' . $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->formatNum( $count ) . '×' )->escaped();
+                               // @todo FIXME: Hardcoded '×'. Should be a message.
+                               $formattedCount = $this->getLanguage()->formatNum( $count ) . '×';
+                               $text .= ' ' . $this->msg( 'parentheses' )->rawParams( $formattedCount )->escaped();
                        }
                        array_push( $users, $text );
                }
@@ -278,7 +300,8 @@ class EnhancedChangesList extends ChangesList {
                                implode( $this->message['semicolon-separator'], $users )
                        )->escaped() . '</span>';
 
-               $tl = '<span class="mw-collapsible-toggle mw-collapsible-arrow mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
+               $tl = '<span class="mw-collapsible-toggle mw-collapsible-arrow ' .
+                       'mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>';
                $r .= "<td>$tl</td>";
 
                # Main line
@@ -294,7 +317,8 @@ class EnhancedChangesList extends ChangesList {
 
                # Article link
                if ( $namehidden ) {
-                       $r .= ' <span class="history-deleted">' . $this->msg( 'rev-deleted-event' )->escaped() . '</span>';
+                       $r .= ' <span class="history-deleted">' .
+                               $this->msg( 'rev-deleted-event' )->escaped() . '</span>';
                } elseif ( $allLogs ) {
                        $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
                } else {
@@ -409,6 +433,7 @@ class EnhancedChangesList extends ChangesList {
 
                $r .= $users;
                $r .= $this->numberofWatchingusers( $block[0]->numberofWatchingusers );
+               $r .= '</td></tr>';
 
                # Sub-entries
                foreach ( $block as $rcObj ) {
@@ -443,11 +468,11 @@ class EnhancedChangesList extends ChangesList {
                        } else {
 
                                $link = Linker::linkKnown(
-                                               $rcObj->getTitle(),
-                                               $rcObj->timestamp,
-                                               array(),
-                                               $params
-                                       );
+                                       $rcObj->getTitle(),
+                                       $rcObj->timestamp,
+                                       array(),
+                                       $params
+                               );
                                if ( $this->isDeleted( $rcObj, Revision::DELETED_TEXT ) ) {
                                        $link = '<span class="history-deleted">' . $link . '</span> ';
                                }
@@ -455,7 +480,11 @@ class EnhancedChangesList extends ChangesList {
                        $r .= $link . '</span>';
 
                        if ( !$type == RC_LOG || $type == RC_NEW ) {
-                               $r .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->curlink . $this->message['pipe-separator'] . $rcObj->lastlink )->escaped();
+                               $r .= ' ' . $this->msg( 'parentheses' )->rawParams(
+                                       $rcObj->curlink .
+                                               $this->message['pipe-separator'] .
+                                               $rcObj->lastlink
+                               )->escaped();
                        }
                        $r .= ' <span class="mw-changeslist-separator">. .</span> ';
 
@@ -504,6 +533,7 @@ class EnhancedChangesList extends ChangesList {
                $encUrl = htmlspecialchars( $wgStylePath . '/common/images/Arr_' . $dir . '.png' );
                $encAlt = htmlspecialchars( $alt );
                $encTitle = htmlspecialchars( $title );
+
                return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" title=\"$encTitle\" />";
        }
 
@@ -514,6 +544,7 @@ class EnhancedChangesList extends ChangesList {
         */
        protected function sideArrow() {
                $dir = $this->getLanguage()->isRTL() ? 'l' : 'r';
+
                return $this->arrow( $dir, '+', $this->msg( 'rc-enhanced-expand' )->text() );
        }
 
@@ -552,10 +583,10 @@ class EnhancedChangesList extends ChangesList {
                if ( $logType ) {
                        # Log entry
                        $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-'
-                                       . $logType . '-' . $rcObj->mAttribs['rc_title'] );
+                               . $logType . '-' . $rcObj->mAttribs['rc_title'] );
                } else {
                        $classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' .
-                                       $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
+                               $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] );
                }
                $classes[] = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched
                        ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched';
@@ -580,19 +611,21 @@ class EnhancedChangesList extends ChangesList {
                        $logPage = new LogPage( $logType );
                        $logTitle = SpecialPage::getTitleFor( 'Log', $logType );
                        $logName = $logPage->getName()->escaped();
-                       $r .= $this->msg( 'parentheses' )->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped();
+                       $r .= $this->msg( 'parentheses' )
+                               ->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped();
                } else {
                        $this->insertArticleLink( $r, $rcObj, $rcObj->unpatrolled, $rcObj->watched );
                }
                # Diff and hist links
                if ( $type != RC_LOG ) {
                        $query['action'] = 'history';
-                       $r .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown(
-                               $rcObj->getTitle(),
-                               $this->message['hist'],
-                               array(),
-                               $query
-                       ) )->escaped();
+                       $r .= ' ' . $this->msg( 'parentheses' )
+                               ->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown(
+                                       $rcObj->getTitle(),
+                                       $this->message['hist'],
+                                       array(),
+                                       $query
+                               ) )->escaped();
                }
                $r .= ' <span class="mw-changeslist-separator">. .</span> ';
                # Character diff
@@ -630,7 +663,7 @@ class EnhancedChangesList extends ChangesList {
         * @return string
         */
        protected function recentChangesBlock() {
-               if ( count ( $this->rc_cache ) == 0 ) {
+               if ( count( $this->rc_cache ) == 0 ) {
                        return '';
                }
 
@@ -658,5 +691,4 @@ class EnhancedChangesList extends ChangesList {
        public function endRecentChangesList() {
                return $this->recentChangesBlock() . parent::endRecentChangesList();
        }
-
 }
index a7fe934..56630a6 100644 (file)
  * @file
  */
 class OldChangesList extends ChangesList {
-
        /**
         * Format a line using the old system (aka without any javascript).
         *
-        * @param $rc RecentChange, passed by reference
+        * @param RecentChange $rc Passed by reference
         * @param bool $watched (default false)
         * @param int $linenumber (default null)
         *
@@ -116,15 +115,18 @@ class OldChangesList extends ChangesList {
                }
 
                if ( $this->watchlist ) {
-                       $classes[] = Sanitizer::escapeClass( 'watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+                       $classes[] = Sanitizer::escapeClass( 'watchlist-' .
+                               $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
                }
 
                if ( !wfRunHooks( 'OldChangesListRecentChangesLine', array( &$this, &$s, $rc, &$classes ) ) ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
 
                wfProfileOut( __METHOD__ );
+
                return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $s . "</li>\n";
        }
 }
index 9aef3d3..271dd4a 100644 (file)
  * @file
  */
 class RCCacheEntry extends RecentChange {
-       var $secureName, $link;
-       var $curlink, $difflink, $lastlink, $usertalklink, $versionlink;
-       var $userlink, $timestamp, $watched;
+       public $curlink;
+       public $difflink;
+       public $lastlink;
+       public $link;
+       public $timestamp;
+       public $unpatrolled;
+       public $userlink;
+       public $usertalklink;
+       public $watched;
 
        /**
         * @param $rc RecentChange
@@ -30,6 +36,7 @@ class RCCacheEntry extends RecentChange {
                $rc2 = new RCCacheEntry;
                $rc2->mAttribs = $rc->mAttribs;
                $rc2->mExtra = $rc->mExtra;
+
                return $rc2;
        }
 }
index 980bd0a..0ef71c4 100644 (file)
  * mAttribs:
  *  rc_id           id of the row in the recentchanges table
  *  rc_timestamp    time the entry was made
- *  rc_cur_time     timestamp on the cur row
  *  rc_namespace    namespace #
  *  rc_title        non-prefixed db key
  *  rc_type         is new entry, used to determine whether updating is necessary
+ *  rc_source       string representation of change source
  *  rc_minor        is minor
  *  rc_cur_id       page_id of associated page entry
  *  rc_user         user id who made the entry
  * @todo document functions and variables
  */
 class RecentChange {
-       var $mAttribs = array(), $mExtra = array();
+       // Constants for the rc_source field.  Extensions may also have
+       // their own source constants.
+       const SRC_EDIT = 'mw.edit';
+       const SRC_NEW = 'mw.new';
+       const SRC_LOG = 'mw.log';
+       const SRC_EXTERNAL = 'mw.external'; // obsolete
+
+       public $mAttribs = array();
+       public $mExtra = array();
 
        /**
         * @var Title
         */
-       var $mTitle = false;
+       public $mTitle = false;
 
        /**
         * @var User
         */
        private $mPerformer = false;
 
+       public $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentchangeslinked
+       public $notificationtimestamp;
+
        /**
-        * @var Title
+        * @var int Line number of recent change. Default -1.
         */
-       var $mMovedToTitle = false;
-       var $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentchangeslinked
-       var $notificationtimestamp;
+       public $counter = -1;
 
        # Factory methods
 
@@ -92,10 +101,12 @@ class RecentChange {
        public static function newFromRow( $row ) {
                $rc = new RecentChange;
                $rc->loadFromRow( $row );
+
                return $rc;
        }
 
        /**
+        * No uses left in Gerrit on 2013-11-19.
         * @deprecated in 1.22
         * @param $row
         * @return RecentChange
@@ -106,6 +117,7 @@ class RecentChange {
                $rc->loadFromCurRow( $row );
                $rc->notificationtimestamp = false;
                $rc->numberofWatchingusers = false;
+
                return $rc;
        }
 
@@ -146,7 +158,6 @@ class RecentChange {
                return array(
                        'rc_id',
                        'rc_timestamp',
-                       'rc_cur_time',
                        'rc_user',
                        'rc_user_text',
                        'rc_namespace',
@@ -159,6 +170,7 @@ class RecentChange {
                        'rc_this_oldid',
                        'rc_last_oldid',
                        'rc_type',
+                       'rc_source',
                        'rc_patrolled',
                        'rc_ip',
                        'rc_old_len',
@@ -195,6 +207,7 @@ class RecentChange {
                if ( $this->mTitle === false ) {
                        $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
                }
+
                return $this->mTitle;
        }
 
@@ -211,6 +224,7 @@ class RecentChange {
                                $this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
                        }
                }
+
                return $this->mPerformer;
        }
 
@@ -244,7 +258,6 @@ class RecentChange {
 
                # Fixup database timestamps
                $this->mAttribs['rc_timestamp'] = $dbw->timestamp( $this->mAttribs['rc_timestamp'] );
-               $this->mAttribs['rc_cur_time'] = $dbw->timestamp( $this->mAttribs['rc_cur_time'] );
                $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
 
                ## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
@@ -313,7 +326,7 @@ class RecentChange {
                        'add_interwiki_prefix' => $wgRC2UDPInterwikiPrefix,
                );
 
-               return $engine->send( $feed, $line );
+               $engine->send( $feed, $line );
        }
 
        /**
@@ -340,6 +353,7 @@ class RecentChange {
                                continue;
                        }
 
+                       /** @var $formatter RCFeedFormatter */
                        $formatter = new $feed['formatter']();
                        $line = $formatter->getLine( $feed, $this, $actionComment );
 
@@ -350,7 +364,8 @@ class RecentChange {
        /**
         * Gets the stream engine object for a given URI from $wgRCEngines
         *
-        * @param $uri string URI to get the engine object for
+        * @param string $uri URI to get the engine object for
+        * @throws MWException
         * @return object The engine object
         */
        private static function getEngine( $uri ) {
@@ -373,6 +388,7 @@ class RecentChange {
         */
        public static function cleanupForIRC( $text ) {
                wfDeprecated( __METHOD__, '1.22' );
+
                return IRCColourfulRCFeedFormatter::cleanupForIRC( $text );
        }
 
@@ -393,13 +409,15 @@ class RecentChange {
                if ( !$change instanceof RecentChange ) {
                        return null;
                }
+
                return $change->doMarkPatrolled( $wgUser, $auto );
        }
 
        /**
         * Mark this RecentChange as patrolled
         *
-        * NOTE: Can also return 'rcpatroldisabled', 'hookaborted' and 'markedaspatrollederror-noautopatrol' as errors
+        * NOTE: Can also return 'rcpatroldisabled', 'hookaborted' and
+        * 'markedaspatrollederror-noautopatrol' as errors
         * @param $user User object doing the action
         * @param $auto Boolean: for automatic patrol
         * @return array of permissions errors, see Title::getUserPermissionsErrors()
@@ -420,7 +438,9 @@ class RecentChange {
                }
                // Users without the 'autopatrol' right can't patrol their
                // own revisions
-               if ( $user->getName() == $this->getAttribute( 'rc_user_text' ) && !$user->isAllowed( 'autopatrol' ) ) {
+               if ( $user->getName() == $this->getAttribute( 'rc_user_text' )
+                       && !$user->isAllowed( 'autopatrol' )
+               ) {
                        $errors[] = array( 'markedaspatrollederror-noautopatrol' );
                }
                if ( $errors ) {
@@ -435,6 +455,7 @@ class RecentChange {
                // Log this patrol event
                PatrolLog::record( $this, $auto, $user );
                wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
+
                return array();
        }
 
@@ -457,6 +478,7 @@ class RecentChange {
                // Invalidate the page cache after the page has been patrolled
                // to make sure that the Patrol link isn't visible any longer!
                $this->getTitle()->invalidateCache();
+
                return $dbw->affectedRows();
        }
 
@@ -484,39 +506,40 @@ class RecentChange {
                $rc->mTitle = $title;
                $rc->mPerformer = $user;
                $rc->mAttribs = array(
-                       'rc_timestamp'  => $timestamp,
-                       'rc_cur_time'   => $timestamp,
-                       'rc_namespace'  => $title->getNamespace(),
-                       'rc_title'      => $title->getDBkey(),
-                       'rc_type'       => RC_EDIT,
-                       'rc_minor'      => $minor ? 1 : 0,
-                       'rc_cur_id'     => $title->getArticleID(),
-                       'rc_user'       => $user->getId(),
-                       'rc_user_text'  => $user->getName(),
-                       'rc_comment'    => $comment,
+                       'rc_timestamp' => $timestamp,
+                       'rc_namespace' => $title->getNamespace(),
+                       'rc_title' => $title->getDBkey(),
+                       'rc_type' => RC_EDIT,
+                       'rc_source' => self::SRC_EDIT,
+                       'rc_minor' => $minor ? 1 : 0,
+                       'rc_cur_id' => $title->getArticleID(),
+                       'rc_user' => $user->getId(),
+                       'rc_user_text' => $user->getName(),
+                       'rc_comment' => $comment,
                        'rc_this_oldid' => $newId,
                        'rc_last_oldid' => $oldId,
-                       'rc_bot'        => $bot ? 1 : 0,
-                       'rc_ip'         => self::checkIPAddress( $ip ),
-                       'rc_patrolled'  => intval( $patrol ),
-                       'rc_new'        => 0,  # obsolete
-                       'rc_old_len'    => $oldSize,
-                       'rc_new_len'    => $newSize,
-                       'rc_deleted'    => 0,
-                       'rc_logid'      => 0,
-                       'rc_log_type'   => null,
+                       'rc_bot' => $bot ? 1 : 0,
+                       'rc_ip' => self::checkIPAddress( $ip ),
+                       'rc_patrolled' => intval( $patrol ),
+                       'rc_new' => 0, # obsolete
+                       'rc_old_len' => $oldSize,
+                       'rc_new_len' => $newSize,
+                       'rc_deleted' => 0,
+                       'rc_logid' => 0,
+                       'rc_log_type' => null,
                        'rc_log_action' => '',
-                       'rc_params'     => ''
+                       'rc_params' => ''
                );
 
                $rc->mExtra = array(
                        'prefixedDBkey' => $title->getPrefixedDBkey(),
                        'lastTimestamp' => $lastTimestamp,
-                       'oldSize'       => $oldSize,
-                       'newSize'       => $newSize,
-                       'pageStatus'   => 'changed'
+                       'oldSize' => $oldSize,
+                       'newSize' => $newSize,
+                       'pageStatus' => 'changed'
                );
                $rc->save();
+
                return $rc;
        }
 
@@ -543,29 +566,29 @@ class RecentChange {
                $rc->mTitle = $title;
                $rc->mPerformer = $user;
                $rc->mAttribs = array(
-                       'rc_timestamp'      => $timestamp,
-                       'rc_cur_time'       => $timestamp,
-                       'rc_namespace'      => $title->getNamespace(),
-                       'rc_title'          => $title->getDBkey(),
-                       'rc_type'           => RC_NEW,
-                       'rc_minor'          => $minor ? 1 : 0,
-                       'rc_cur_id'         => $title->getArticleID(),
-                       'rc_user'           => $user->getId(),
-                       'rc_user_text'      => $user->getName(),
-                       'rc_comment'        => $comment,
-                       'rc_this_oldid'     => $newId,
-                       'rc_last_oldid'     => 0,
-                       'rc_bot'            => $bot ? 1 : 0,
-                       'rc_ip'             => self::checkIPAddress( $ip ),
-                       'rc_patrolled'      => intval( $patrol ),
-                       'rc_new'            => 1, # obsolete
-                       'rc_old_len'        => 0,
-                       'rc_new_len'        => $size,
-                       'rc_deleted'        => 0,
-                       'rc_logid'          => 0,
-                       'rc_log_type'       => null,
-                       'rc_log_action'     => '',
-                       'rc_params'         => ''
+                       'rc_timestamp' => $timestamp,
+                       'rc_namespace' => $title->getNamespace(),
+                       'rc_title' => $title->getDBkey(),
+                       'rc_type' => RC_NEW,
+                       'rc_source' => self::SRC_NEW,
+                       'rc_minor' => $minor ? 1 : 0,
+                       'rc_cur_id' => $title->getArticleID(),
+                       'rc_user' => $user->getId(),
+                       'rc_user_text' => $user->getName(),
+                       'rc_comment' => $comment,
+                       'rc_this_oldid' => $newId,
+                       'rc_last_oldid' => 0,
+                       'rc_bot' => $bot ? 1 : 0,
+                       'rc_ip' => self::checkIPAddress( $ip ),
+                       'rc_patrolled' => intval( $patrol ),
+                       'rc_new' => 1, # obsolete
+                       'rc_old_len' => 0,
+                       'rc_new_len' => $size,
+                       'rc_deleted' => 0,
+                       'rc_logid' => 0,
+                       'rc_log_type' => null,
+                       'rc_log_action' => '',
+                       'rc_params' => ''
                );
 
                $rc->mExtra = array(
@@ -576,6 +599,7 @@ class RecentChange {
                        'pageStatus' => 'created'
                );
                $rc->save();
+
                return $rc;
        }
 
@@ -595,9 +619,10 @@ class RecentChange {
         * @return bool
         */
        public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip, $type,
-               $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' )
-       {
+               $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = ''
+       {
                global $wgLogRestrictions;
+
                # Don't add private logs to RC!
                if ( isset( $wgLogRestrictions[$type] ) && $wgLogRestrictions[$type] != '*' ) {
                        return false;
@@ -605,6 +630,7 @@ class RecentChange {
                $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
                        $target, $logComment, $params, $newId, $actionCommentIRC );
                $rc->save();
+
                return true;
        }
 
@@ -652,38 +678,39 @@ class RecentChange {
                $rc->mTitle = $target;
                $rc->mPerformer = $user;
                $rc->mAttribs = array(
-                       'rc_timestamp'  => $timestamp,
-                       'rc_cur_time'   => $timestamp,
-                       'rc_namespace'  => $target->getNamespace(),
-                       'rc_title'      => $target->getDBkey(),
-                       'rc_type'       => RC_LOG,
-                       'rc_minor'      => 0,
-                       'rc_cur_id'     => $target->getArticleID(),
-                       'rc_user'       => $user->getId(),
-                       'rc_user_text'  => $user->getName(),
-                       'rc_comment'    => $logComment,
+                       'rc_timestamp' => $timestamp,
+                       'rc_namespace' => $target->getNamespace(),
+                       'rc_title' => $target->getDBkey(),
+                       'rc_type' => RC_LOG,
+                       'rc_source' => self::SRC_LOG,
+                       'rc_minor' => 0,
+                       'rc_cur_id' => $target->getArticleID(),
+                       'rc_user' => $user->getId(),
+                       'rc_user_text' => $user->getName(),
+                       'rc_comment' => $logComment,
                        'rc_this_oldid' => 0,
                        'rc_last_oldid' => 0,
-                       'rc_bot'        => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
-                       'rc_ip'         => self::checkIPAddress( $ip ),
-                       'rc_patrolled'  => 1,
-                       'rc_new'        => 0, # obsolete
-                       'rc_old_len'    => null,
-                       'rc_new_len'    => null,
-                       'rc_deleted'    => 0,
-                       'rc_logid'      => $newId,
-                       'rc_log_type'   => $type,
+                       'rc_bot' => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
+                       'rc_ip' => self::checkIPAddress( $ip ),
+                       'rc_patrolled' => 1,
+                       'rc_new' => 0, # obsolete
+                       'rc_old_len' => null,
+                       'rc_new_len' => null,
+                       'rc_deleted' => 0,
+                       'rc_logid' => $newId,
+                       'rc_log_type' => $type,
                        'rc_log_action' => $action,
-                       'rc_params'     => $params
+                       'rc_params' => $params
                );
 
                $rc->mExtra = array(
                        'prefixedDBkey' => $title->getPrefixedDBkey(),
                        'lastTimestamp' => 0,
                        'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
-                       'pageStatus'    => $pageStatus,
+                       'pageStatus' => $pageStatus,
                        'actionCommentIRC' => $actionCommentIRC
                );
+
                return $rc;
        }
 
@@ -701,14 +728,13 @@ class RecentChange {
        /**
         * Makes a pseudo-RC entry from a cur row
         *
-        * @deprected in 1.22
+        * @deprecated in 1.22
         * @param $row
         */
        public function loadFromCurRow( $row ) {
                wfDeprecated( __METHOD__, '1.22' );
                $this->mAttribs = array(
                        'rc_timestamp' => wfTimestamp( TS_MW, $row->rev_timestamp ),
-                       'rc_cur_time' => $row->rev_timestamp,
                        'rc_user' => $row->rev_user,
                        'rc_user_text' => $row->rev_user_text,
                        'rc_namespace' => $row->page_namespace,
@@ -716,6 +742,7 @@ class RecentChange {
                        'rc_comment' => $row->rev_comment,
                        'rc_minor' => $row->rev_minor_edit ? 1 : 0,
                        'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
+                       'rc_source' => $row->page_is_new ? self::SRC_NEW : self::SRC_EDIT,
                        'rc_cur_id' => $row->page_id,
                        'rc_this_oldid' => $row->rev_id,
                        'rc_last_oldid' => isset( $row->rc_last_oldid ) ? $row->rc_last_oldid : 0,
@@ -769,6 +796,7 @@ class RecentChange {
                } else {
                        $trail = '';
                }
+
                return $trail;
        }
 
@@ -789,6 +817,7 @@ class RecentChange {
                if ( $old === null || $new === null ) {
                        return '';
                }
+
                return ChangesList::showCharacterDifference( $old, $new );
        }
 
@@ -803,7 +832,7 @@ class RecentChange {
 
                $method = __METHOD__;
                $dbw = wfGetDB( DB_MASTER );
-               $dbw->onTransactionIdle( function() use ( $dbw, $method ) {
+               $dbw->onTransactionIdle( function () use ( $dbw, $method ) {
                        global $wgRCMaxAge;
 
                        $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
@@ -819,7 +848,8 @@ class RecentChange {
                global $wgRequest;
                if ( $ip ) {
                        if ( !IP::isIPAddress( $ip ) ) {
-                               throw new MWException( "Attempt to write \"" . $ip . "\" as an IP address into recent changes" );
+                               throw new MWException( "Attempt to write \"" . $ip .
+                                       "\" as an IP address into recent changes" );
                        }
                } else {
                        $ip = $wgRequest->getIP();
@@ -827,6 +857,7 @@ class RecentChange {
                                $ip = '';
                        }
                }
+
                return $ip;
        }
 
@@ -841,6 +872,7 @@ class RecentChange {
         */
        public static function isInRCLifespan( $timestamp, $tolerance = 0 ) {
                global $wgRCMaxAge;
+
                return wfTimestamp( TS_UNIX, $timestamp ) > time() - $tolerance - $wgRCMaxAge;
        }
 }
index ef71b18..537deac 100644 (file)
@@ -52,15 +52,15 @@ class RedisConnectionPool {
        protected $serializer;
        /** @} */
 
-       /** @var integer Current idle pool size */
+       /** @var int Current idle pool size */
        protected $idlePoolSize = 0;
 
-       /** @var Array (server name => ((connection info array),...) */
+       /** @var array (server name => ((connection info array),...) */
        protected $connections = array();
-       /** @var Array (server name => UNIX timestamp) */
+       /** @var array (server name => UNIX timestamp) */
        protected $downServers = array();
 
-       /** @var Array (pool ID => RedisConnectionPool) */
+       /** @var array (pool ID => RedisConnectionPool) */
        protected static $instances = array();
 
        /** integer; seconds to cache servers as "down". */
@@ -68,6 +68,7 @@ class RedisConnectionPool {
 
        /**
         * @param array $options
+        * @throws MWException
         */
        protected function __construct( array $options ) {
                if ( !class_exists( 'Redis' ) ) {
@@ -89,8 +90,8 @@ class RedisConnectionPool {
        }
 
        /**
-        * @param $options Array
-        * @return Array
+        * @param array $options
+        * @return array
         */
        protected static function applyDefaultConfig( array $options ) {
                if ( !isset( $options['connectTimeout'] ) ) {
@@ -102,11 +103,12 @@ class RedisConnectionPool {
                if ( !isset( $options['password'] ) ) {
                        $options['password'] = null;
                }
+
                return $options;
        }
 
        /**
-        * @param $options Array
+        * @param array $options
         * $options include:
         *   - connectTimeout : The timeout for new connections, in seconds.
         *                      Optional, default is 1 second.
@@ -127,6 +129,7 @@ class RedisConnectionPool {
                        self::$instances[$id] = new self( $options );
                        wfDebug( "Creating a new " . __CLASS__ . " instance with id $id." );
                }
+
                return self::$instances[$id];
        }
 
@@ -151,6 +154,7 @@ class RedisConnectionPool {
                                // Server is dead
                                wfDebug( "server $server is marked down for another " .
                                        ( $this->downServers[$server] - $now ) . " seconds, can't get connection" );
+
                                return false;
                        }
                }
@@ -161,6 +165,7 @@ class RedisConnectionPool {
                                if ( $connection['free'] ) {
                                        $connection['free'] = false;
                                        --$this->idlePoolSize;
+
                                        return new RedisConnRef( $this, $server, $connection['conn'] );
                                }
                        }
@@ -195,6 +200,7 @@ class RedisConnectionPool {
                                wfDebugLog( 'redis', "Could not connect to server $server" );
                                // Mark server down for some time to avoid further timeouts
                                $this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
+
                                return false;
                        }
                        if ( $this->password !== null ) {
@@ -205,12 +211,14 @@ class RedisConnectionPool {
                } catch ( RedisException $e ) {
                        $this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
                        wfDebugLog( 'redis', "Redis exception: " . $e->getMessage() . "\n" );
+
                        return false;
                }
 
                if ( $conn ) {
                        $conn->setOption( Redis::OPT_SERIALIZER, $this->serializer );
                        $this->connections[$server][] = array( 'conn' => $conn, 'free' => false );
+
                        return new RedisConnRef( $this, $server, $conn );
                } else {
                        return false;
@@ -220,9 +228,9 @@ class RedisConnectionPool {
        /**
         * Mark a connection to a server as free to return to the pool
         *
-        * @param $server string
-        * @param $conn Redis
-        * @return boolean
+        * @param string $server
+        * @param Redis $conn
+        * @return bool
         */
        public function freeConnection( $server, Redis $conn ) {
                $found = false;
@@ -242,15 +250,13 @@ class RedisConnectionPool {
 
        /**
         * Close any extra idle connections if there are more than the limit
-        *
-        * @return void
         */
        protected function closeExcessIdleConections() {
                if ( $this->idlePoolSize <= count( $this->connections ) ) {
                        return; // nothing to do (no more connections than servers)
                }
 
-               foreach ( $this->connections as $server => &$serverConnections ) {
+               foreach ( $this->connections as &$serverConnections ) {
                        foreach ( $serverConnections as $key => &$connection ) {
                                if ( $connection['free'] ) {
                                        unset( $serverConnections[$key] );
@@ -268,10 +274,9 @@ class RedisConnectionPool {
         * not. The safest response for us is to explicitly destroy the connection
         * object and let it be reopened during the next request.
         *
-        * @param $server string
-        * @param $cref RedisConnRef
-        * @param $e RedisException
-        * @return void
+        * @param string $server
+        * @param RedisConnRef $cref
+        * @param RedisException $e
         */
        public function handleException( $server, RedisConnRef $cref, RedisException $e ) {
                wfDebugLog( 'redis', "Redis exception on server $server: " . $e->getMessage() . "\n" );
@@ -283,11 +288,52 @@ class RedisConnectionPool {
                        }
                }
        }
+
+       /**
+        * Re-send an AUTH request to the redis server (useful after disconnects).
+        *
+        * This works around an upstream bug in phpredis. phpredis hides disconnects by transparently
+        * reconnecting, but it neglects to re-authenticate the new connection. To the user of the
+        * phpredis client API this manifests as a seemingly random tendency of connections to lose
+        * their authentication status.
+        *
+        * This method is for internal use only.
+        *
+        * @see https://github.com/nicolasff/phpredis/issues/403
+        *
+        * @param string $server
+        * @param Redis $conn
+        * @return bool Success
+        */
+       public function reauthenticateConnection( $server, Redis $conn ) {
+               if ( $this->password !== null ) {
+                       if ( !$conn->auth( $this->password ) ) {
+                               wfDebugLog( 'redis', "Authentication error connecting to $server" );
+
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Make sure connections are closed for sanity
+        */
+       function __destruct() {
+               foreach ( $this->connections as $server => &$serverConnections ) {
+                       foreach ( $serverConnections as $key => &$connection ) {
+                               $connection['conn']->close();
+                       }
+               }
+       }
 }
 
 /**
  * Helper class to handle automatically marking connectons as reusable (via RAII pattern)
  *
+ * This class simply wraps the Redis class and can be used the same way
+ *
  * @ingroup Redis
  * @since 1.21
  */
@@ -298,11 +344,12 @@ class RedisConnRef {
        protected $conn;
 
        protected $server; // string
+       protected $lastError; // string
 
        /**
-        * @param $pool RedisConnectionPool
-        * @param $server string
-        * @param $conn Redis
+        * @param RedisConnectionPool $pool
+        * @param string $server
+        * @param Redis $conn
         */
        public function __construct( RedisConnectionPool $pool, $server, Redis $conn ) {
                $this->pool = $pool;
@@ -310,8 +357,37 @@ class RedisConnRef {
                $this->conn = $conn;
        }
 
+       /**
+        * @return string
+        * @since 1.23
+        */
+       public function getServer() {
+               return $this->server;
+       }
+
+       public function getLastError() {
+               return $this->lastError;
+       }
+
+       public function clearLastError() {
+               $this->lastError = null;
+       }
+
        public function __call( $name, $arguments ) {
-               return call_user_func_array( array( $this->conn, $name ), $arguments );
+               $conn = $this->conn; // convenience
+
+               $conn->clearLastError();
+               $res = call_user_func_array( array( $conn, $name ), $arguments );
+               if ( preg_match( '/^ERR operation not permitted\b/', $conn->getLastError() ) ) {
+                       $this->pool->reauthenticateConnection( $this->server, $conn );
+                       $conn->clearLastError();
+                       $res = call_user_func_array( array( $conn, $name ), $arguments );
+                       wfDebugLog( 'redis', "Used automatic re-authentication for method '$name'." );
+               }
+
+               $this->lastError = $conn->getLastError() ?: $this->lastError;
+
+               return $res;
        }
 
        /**
@@ -324,10 +400,21 @@ class RedisConnRef {
        public function luaEval( $script, array $params, $numKeys ) {
                $sha1 = sha1( $script ); // 40 char hex
                $conn = $this->conn; // convenience
+               $server = $this->server; // convenience
 
                // Try to run the server-side cached copy of the script
                $conn->clearLastError();
                $res = $conn->evalSha( $sha1, $params, $numKeys );
+               // If we got a permission error reply that means that (a) we are not in
+               // multi()/pipeline() and (b) some connection problem likely occured. If
+               // the password the client gave was just wrong, an exception should have
+               // been thrown back in getConnection() previously.
+               if ( preg_match( '/^ERR operation not permitted\b/', $conn->getLastError() ) ) {
+                       $this->pool->reauthenticateConnection( $server, $conn );
+                       $conn->clearLastError();
+                       $res = $conn->eval( $script, $params, $numKeys );
+                       wfDebugLog( 'redis', "Used automatic re-authentication for Lua script $sha1." );
+               }
                // If the script is not in cache, use eval() to retry and cache it
                if ( preg_match( '/^NOSCRIPT/', $conn->getLastError() ) ) {
                        $conn->clearLastError();
@@ -336,14 +423,16 @@ class RedisConnRef {
                }
 
                if ( $conn->getLastError() ) { // script bug?
-                       wfDebugLog( 'redis', "Lua script error: " . $conn->getLastError() );
+                       wfDebugLog( 'redis', "Lua script error on server $server: " . $conn->getLastError() );
                }
 
+               $this->lastError = $conn->getLastError() ?: $this->lastError;
+
                return $res;
        }
 
        /**
-        * @param RedisConnRef $conn
+        * @param Redis $conn
         * @return bool
         */
        public function isConnIdentical( Redis $conn ) {
index 137efb8..e1b1f01 100644 (file)
@@ -32,7 +32,6 @@
  * @ingroup Content
  */
 abstract class AbstractContent implements Content {
-
        /**
         * Name of the content model this Content object represents.
         * Use with CONTENT_MODEL_XXX constants
@@ -264,7 +263,7 @@ abstract class AbstractContent implements Content {
                                break;
                        }
                        // Redirects to some special pages are not permitted
-                       if ( $newtitle instanceOf Title && $newtitle->isValidRedirectTarget() ) {
+                       if ( $newtitle instanceof Title && $newtitle->isValidRedirectTarget() ) {
                                // The new title passes the checks, so make that our current
                                // title so that further recursion can be checked
                                $title = $newtitle;
@@ -273,6 +272,7 @@ abstract class AbstractContent implements Content {
                                break;
                        }
                }
+
                return $titles;
        }
 
@@ -293,6 +293,7 @@ abstract class AbstractContent implements Content {
         */
        public function getUltimateRedirectTarget() {
                $titles = $this->getRedirectChain();
+
                return $titles ? array_pop( $titles ) : null;
        }
 
@@ -394,15 +395,16 @@ abstract class AbstractContent implements Content {
         *    database after deletion.
         */
        public function getDeletionUpdates( WikiPage $page,
-               ParserOutput $parserOutput = null )
-       {
+               ParserOutput $parserOutput = null
+       {
                return array(
                        new LinksDeletionUpdate( $page ),
                );
        }
 
        /**
-        * This default implementation always returns false. Subclasses may override this to supply matching logic.
+        * This default implementation always returns false. Subclasses may override
+        * this to supply matching logic.
         *
         * @see Content::matchMagicWord
         *
@@ -422,8 +424,8 @@ abstract class AbstractContent implements Content {
         * This base implementation calls the hook ConvertContent to enable custom conversions.
         * Subclasses may override this to implement conversion for "their" content model.
         *
-        * @param string  $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string  $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
+        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
+        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
         * not allowed, full round-trip conversion is expected to work without losing information.
         *
         * @return Content|bool A content object with the content model $toModel, or false if
@@ -439,6 +441,7 @@ abstract class AbstractContent implements Content {
                $result = false;
 
                wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) );
+
                return $result;
        }
 }
index 5a90e09..da49ced 100644 (file)
@@ -32,7 +32,6 @@
  * @ingroup Content
  */
 interface Content {
-
        /**
         * @since 1.21
         *
@@ -267,6 +266,7 @@ interface Content {
        public function getParserOutput( Title $title,
                $revId = null,
                ParserOptions $options = null, $generateHtml = true );
+
        // TODO: make RenderOutput and RenderOptions base classes
 
        /**
@@ -362,7 +362,8 @@ interface Content {
         *
         * @param Title $target the new redirect target
         *
-        * @return Content a new Content object with the updated redirect (or $this if this Content object isn't a redirect)
+        * @return Content a new Content object with the updated redirect (or $this
+        *   if this Content object isn't a redirect)
         */
        public function updateRedirect( Title $target );
 
@@ -437,22 +438,22 @@ interface Content {
         * This may be used to check the content's consistency with global state. This function should
         * NOT write any information to the database.
         *
-        * Note that this method will usually be called inside the same transaction bracket that will be used
-        * to save the new revision.
+        * Note that this method will usually be called inside the same transaction
+        * bracket that will be used to save the new revision.
         *
-        * Note that this method is called before any update to the page table is performed. This means that
-        * $page may not yet know a page ID.
+        * Note that this method is called before any update to the page table is
+        * performed. This means that $page may not yet know a page ID.
         *
         * @since 1.21
         *
         * @param WikiPage $page The page to be saved.
-        * @param int      $flags bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
-        * @param int      $baseRevId the ID of the current revision
-        * @param User     $user
+        * @param int $flags bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
+        * @param int $baseRevId the ID of the current revision
+        * @param User $user
         *
-        * @return Status A status object indicating whether the content was successfully prepared for saving.
-        *                If the returned status indicates an error, a rollback will be performed and the
-        *                transaction aborted.
+        * @return Status A status object indicating whether the content was
+        *   successfully prepared for saving. If the returned status indicates
+        *   an error, a rollback will be performed and the transaction aborted.
         *
         * @see see WikiPage::doEditContent()
         */
@@ -491,17 +492,16 @@ interface Content {
         * Converts this content object into another content object with the given content model,
         * if that is possible.
         *
-        * @param string  $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string  $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
+        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
+        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
         * not allowed, full round-trip conversion is expected to work without losing information.
         *
         * @return Content|bool A content object with the content model $toModel, or false if
         * that conversion is not supported.
         */
        public function convert( $toModel, $lossy = '' );
-
-               // TODO: ImagePage and CategoryPage interfere with per-content action handlers
-       // TODO: nice&sane integration of GeSHi syntax highlighting
+       // @todo ImagePage and CategoryPage interfere with per-content action handlers
+       // @todo nice&sane integration of GeSHi syntax highlighting
        //   [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
        //   config to set the class which handles syntax highlighting
        //   [12:00] <vvv> And default it to a DummyHighlighter
index 2a92e23..1abe1fa 100644 (file)
@@ -31,7 +31,6 @@
  * @ingroup Content
  */
 class MWContentSerializationException extends MWException {
-
 }
 
 /**
@@ -54,7 +53,6 @@ class MWContentSerializationException extends MWException {
  * @ingroup Content
  */
 abstract class ContentHandler {
-
        /**
         * Switch for enabling deprecation warnings. Used by ContentHandler::deprecated()
         * and ContentHandler::runLegacyHooks().
@@ -145,8 +143,8 @@ abstract class ContentHandler {
         *    not be unserialized using $format.
         */
        public static function makeContent( $text, Title $title = null,
-               $modelId = null, $format = null )
-       {
+               $modelId = null, $format = null
+       {
                if ( is_null( $modelId ) ) {
                        if ( is_null( $title ) ) {
                                throw new MWException( "Must provide a Title object or a content model ID." );
@@ -156,6 +154,7 @@ abstract class ContentHandler {
                }
 
                $handler = ContentHandler::getForModelID( $modelId );
+
                return $handler->unserializeContent( $text, $format );
        }
 
@@ -259,6 +258,7 @@ abstract class ContentHandler {
         */
        public static function getForTitle( Title $title ) {
                $modelId = $title->getContentModel();
+
                return ContentHandler::getForModelID( $modelId );
        }
 
@@ -273,13 +273,14 @@ abstract class ContentHandler {
         */
        public static function getForContent( Content $content ) {
                $modelId = $content->getModel();
+
                return ContentHandler::getForModelID( $modelId );
        }
 
        /**
-        * @var Array A Cache of ContentHandler instances by model id
+        * @var array A Cache of ContentHandler instances by model id
         */
-       static $handlers;
+       protected static $handlers;
 
        /**
         * Returns the ContentHandler singleton for the given model ID. Use the
@@ -330,14 +331,16 @@ abstract class ContentHandler {
                        $handler = new $class( $modelId );
 
                        if ( !( $handler instanceof ContentHandler ) ) {
-                               throw new MWException( "$class from \$wgContentHandlers is not compatible with ContentHandler" );
+                               throw new MWException( "$class from \$wgContentHandlers is not " .
+                                       "compatible with ContentHandler" );
                        }
                }
 
                wfDebugLog( 'ContentHandler', 'Created handler for ' . $modelId
-                                       . ': ' . get_class( $handler ) );
+                       . ': ' . get_class( $handler ) );
 
                ContentHandler::$handlers[$modelId] = $handler;
+
                return ContentHandler::$handlers[$modelId];
        }
 
@@ -350,10 +353,12 @@ abstract class ContentHandler {
         * @param string $name The content model ID, as given by a CONTENT_MODEL_XXX
         *    constant or returned by Revision::getContentModel().
         *
-        * @return string The content format's localized name.
+        * @return string The content model's localized name.
         * @throws MWException if the model id isn't known.
         */
        public static function getLocalizedName( $name ) {
+               // Messages: content-model-wikitext, content-model-text,
+               // content-model-javascript, content-model-css
                $key = "content-model-$name";
 
                $msg = wfMessage( $key );
@@ -378,6 +383,7 @@ abstract class ContentHandler {
                }
 
                $formats = array_unique( $formats );
+
                return $formats;
        }
 
@@ -596,16 +602,18 @@ abstract class ContentHandler {
        /**
         * Get the language in which the content of the given page is written.
         *
-        * This default implementation just returns $wgContLang (except for pages in the MediaWiki namespace)
+        * This default implementation just returns $wgContLang (except for pages
+        * in the MediaWiki namespace)
         *
-        * Note that the pages language is not cacheable, since it may in some cases depend on user settings.
+        * Note that the pages language is not cacheable, since it may in some
+        * cases depend on user settings.
         *
         * Also note that the page language may or may not depend on the actual content of the page,
         * that is, this method may load the content in order to determine the language.
         *
         * @since 1.21
         *
-        * @param Title        $title the page to determine the language for.
+        * @param Title $title the page to determine the language for.
         * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
         *
         * @return Language the page's language
@@ -621,6 +629,7 @@ abstract class ContentHandler {
                }
 
                wfRunHooks( 'PageContentLanguage', array( $title, &$pageLang, $wgLang ) );
+
                return wfGetLangObj( $pageLang );
        }
 
@@ -639,7 +648,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Title        $title the page to determine the language for.
+        * @param Title $title the page to determine the language for.
         * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
         *
         * @return Language the page's language for viewing
@@ -733,15 +742,15 @@ abstract class ContentHandler {
                if ( is_object( $rt ) ) {
                        if ( !is_object( $ot )
                                || !$rt->equals( $ot )
-                               || $ot->getFragment() != $rt->getFragment() )
-                       {
+                               || $ot->getFragment() != $rt->getFragment()
+                       {
                                $truncatedtext = $newContent->getTextForSummary(
                                        250
-                                               - strlen( wfMessage( 'autoredircomment' )->inContentLanguage()->text() )
-                                               - strlen( $rt->getFullText() ) );
+                                       - strlen( wfMessage( 'autoredircomment' )->inContentLanguage()->text() )
+                                       - strlen( $rt->getFullText() ) );
 
                                return wfMessage( 'autoredircomment', $rt->getFullText() )
-                                               ->rawParams( $truncatedtext )->inContentLanguage()->text();
+                                       ->rawParams( $truncatedtext )->inContentLanguage()->text();
                        }
                }
 
@@ -754,7 +763,7 @@ abstract class ContentHandler {
                                200 - strlen( wfMessage( 'autosumm-new' )->inContentLanguage()->text() ) );
 
                        return wfMessage( 'autosumm-new' )->rawParams( $truncatedtext )
-                                       ->inContentLanguage()->text();
+                               ->inContentLanguage()->text();
                }
 
                // Blanking auto-summaries
@@ -762,15 +771,15 @@ abstract class ContentHandler {
                        return wfMessage( 'autosumm-blank' )->inContentLanguage()->text();
                } elseif ( !empty( $oldContent )
                        && $oldContent->getSize() > 10 * $newContent->getSize()
-                       && $newContent->getSize() < 500 )
-               {
+                       && $newContent->getSize() < 500
+               {
                        // Removing more than 90% of the article
 
                        $truncatedtext = $newContent->getTextForSummary(
                                200 - strlen( wfMessage( 'autosumm-replace' )->inContentLanguage()->text() ) );
 
                        return wfMessage( 'autosumm-replace' )->rawParams( $truncatedtext )
-                                       ->inContentLanguage()->text();
+                               ->inContentLanguage()->text();
                }
 
                // If we reach this point, there's no applicable auto-summary for our
@@ -907,6 +916,10 @@ abstract class ContentHandler {
                $undo_content = $undo->getContent();
                $undoafter_content = $undoafter->getContent();
 
+               if ( !$undo_content || !$undoafter_content ) {
+                       return false; // no content to undo
+               }
+
                $this->checkModelID( $cur_content->getModel() );
                $this->checkModelID( $undo_content->getModel() );
                $this->checkModelID( $undoafter_content->getModel() );
@@ -998,11 +1011,11 @@ abstract class ContentHandler {
         * Logs a deprecation warning, visible if $wgDevelopmentWarnings, but only if
         * self::$enableDeprecationWarnings is set to true.
         *
-        * @param string      $func The name of the deprecated function
-        * @param string      $version The version since the method is deprecated. Usually 1.21
-        *                    for ContentHandler related stuff.
-        * @param string|bool $component: Component to which the function belongs.
-        *                                If false, it is assumed the function is in MediaWiki core.
+        * @param string $func The name of the deprecated function
+        * @param string $version The version since the method is deprecated. Usually 1.21
+        *   for ContentHandler related stuff.
+        * @param string|bool $component : Component to which the function belongs.
+        *   If false, it is assumed the function is in MediaWiki core.
         *
         * @see ContentHandler::$enableDeprecationWarnings
         * @see wfDeprecated
@@ -1031,7 +1044,8 @@ abstract class ContentHandler {
         * @see ContentHandler::$enableDeprecationWarnings
         */
        public static function runLegacyHooks( $event, $args = array(),
-                       $warn = null ) {
+               $warn = null
+       ) {
 
                if ( $warn === null ) {
                        $warn = self::$enableDeprecationWarnings;
@@ -1073,7 +1087,8 @@ abstract class ContentHandler {
 
                        wfRestoreWarnings();
 
-                       wfWarn( "Using obsolete hook $event via ContentHandler::runLegacyHooks()! Handlers: " . implode( ', ', $handlerInfo ), 2 );
+                       wfWarn( "Using obsolete hook $event via ContentHandler::runLegacyHooks()! Handlers: " .
+                               implode( ', ', $handlerInfo ), 2 );
                }
 
                // convert Content objects to text
index cb5a349..7becabb 100644 (file)
@@ -28,7 +28,6 @@
  * @ingroup Content
  */
 class CssContentHandler extends TextContentHandler {
-
        public function __construct( $modelId = CONTENT_MODEL_CSS ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_CSS ) );
        }
@@ -46,6 +45,8 @@ class CssContentHandler extends TextContentHandler {
        /**
         * Returns the english language, because CSS is english, and should be handled as such.
         *
+        * @param Title $title
+        * @param Content $content
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
@@ -57,6 +58,8 @@ class CssContentHandler extends TextContentHandler {
        /**
         * Returns the english language, because CSS is english, and should be handled as such.
         *
+        * @param Title $title
+        * @param Content $content
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
index 33fa917..064c422 100644 (file)
@@ -28,7 +28,6 @@
  * @todo make ScriptContentHandler base class, do highlighting stuff there?
  */
 class JavaScriptContentHandler extends TextContentHandler {
-
        public function __construct( $modelId = CONTENT_MODEL_JAVASCRIPT ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_JAVASCRIPT ) );
        }
@@ -46,6 +45,8 @@ class JavaScriptContentHandler extends TextContentHandler {
        /**
         * Returns the english language, because JS is english, and should be handled as such.
         *
+        * @param Title $title
+        * @param Content $content
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
@@ -57,6 +58,8 @@ class JavaScriptContentHandler extends TextContentHandler {
        /**
         * Returns the english language, because JS is english, and should be handled as such.
         *
+        * @param Title $title
+        * @param Content $content
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
index b36b670..e780846 100644 (file)
  * @ingroup Content
  */
 class MessageContent extends AbstractContent {
-
        /**
         * @var Message
         */
        protected $mMessage;
 
        /**
-        * @param Message|String $msg    A Message object, or a message key
-        * @param array|null     $params An optional array of message parameters
+        * @param Message|String $msg A Message object, or a message key
+        * @param array|null $params An optional array of message parameters
         */
        public function __construct( $msg, $params = null ) {
                # XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
@@ -130,6 +129,7 @@ class MessageContent extends AbstractContent {
        /**
         * @see Content::isCountable
         *
+        * @param bool $hasLinks
         * @return bool false
         */
        public function isCountable( $hasLinks = null ) {
@@ -139,6 +139,10 @@ class MessageContent extends AbstractContent {
        /**
         * @see Content::getParserOutput
         *
+        * @param Title $title
+        * @param int $revId Optional revision ID
+        * @param ParserOptions $options
+        * @param bool $generateHtml Wether to generate HTML
         * @return ParserOutput
         */
        public function getParserOutput(
@@ -153,6 +157,7 @@ class MessageContent extends AbstractContent {
                }
 
                $po = new ParserOutput( $html );
+
                return $po;
        }
 }
index f66dacd..d03d61e 100644 (file)
  * @ingroup Content
  */
 class TextContent extends AbstractContent {
-
        public function __construct( $text, $model_id = CONTENT_MODEL_TEXT ) {
                parent::__construct( $model_id );
 
                if ( $text === null || $text === false ) {
                        wfWarn( "TextContent constructed with \$text = " . var_export( $text, true ) . "! "
-                                       . "This may indicate an error in the caller's scope." );
+                               . "This may indicate an error in the caller's scope." );
 
                        $text = '';
                }
@@ -74,6 +73,7 @@ class TextContent extends AbstractContent {
         */
        public function getSize() {
                $text = $this->getNativeData();
+
                return strlen( $text );
        }
 
@@ -107,6 +107,7 @@ class TextContent extends AbstractContent {
         */
        public function getNativeData() {
                $text = $this->mText;
+
                return $text;
        }
 
@@ -156,14 +157,14 @@ class TextContent extends AbstractContent {
        /**
         * Diff this content object with another content object.
         *
-        * @since 1.21diff
+        * @since 1.21
         *
         * @param $that Content: The other content object to compare this content
         * object to.
         * @param $lang Language: The language object to use for text segmentation.
         *    If not given, $wgContentLang is used.
         *
-        * @return DiffResult: A diff representing the changes that would have to be
+        * @return Diff A diff representing the changes that would have to be
         *    made to this content object to make it equal to $that.
         */
        public function diff( Content $that, Language $lang = null ) {
@@ -178,13 +179,14 @@ class TextContent extends AbstractContent {
                }
 
                $otext = $this->getNativeData();
-               $ntext = $this->getNativeData();
+               $ntext = $that->getNativeData();
 
                # Note: Use native PHP diff, external engines don't give us abstract output
                $ota = explode( "\n", $lang->segmentForDiff( $otext ) );
                $nta = explode( "\n", $lang->segmentForDiff( $ntext ) );
 
                $diff = new Diff( $ota, $nta );
+
                return $diff;
        }
 
@@ -224,6 +226,7 @@ class TextContent extends AbstractContent {
                }
 
                $po->setText( $html );
+
                return $po;
        }
 
@@ -259,8 +262,8 @@ class TextContent extends AbstractContent {
         * This implementation provides lossless conversion between content models based
         * on TextContent.
         *
-        * @param string  $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string  $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
+        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
+        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
         * not allowed, full round-trip conversion is expected to work without losing information.
         *
         * @return Content|bool A content object with the content model $toModel, or false if
index e7f41e1..94b5c57 100644 (file)
  * @ingroup Content
  */
 class TextContentHandler extends ContentHandler {
-
-       public function __construct( $modelId = CONTENT_MODEL_TEXT, $formats = array( CONTENT_FORMAT_TEXT ) ) {
+       // @codingStandardsIgnoreStart bug 57585
+       public function __construct( $modelId = CONTENT_MODEL_TEXT,
+               $formats = array( CONTENT_FORMAT_TEXT )
+       ) {
                parent::__construct( $modelId, $formats );
        }
+       // @codingStandardsIgnoreEnd
 
        /**
         * Returns the content's text as-is.
@@ -43,6 +46,7 @@ class TextContentHandler extends ContentHandler {
         */
        public function serializeContent( Content $content, $format = null ) {
                $this->checkFormat( $format );
+
                return $content->getNativeData();
        }
 
@@ -83,6 +87,7 @@ class TextContentHandler extends ContentHandler {
                }
 
                $mergedContent = $this->unserializeContent( $result, $format );
+
                return $mergedContent;
        }
 
index 26337db..1f96bdc 100644 (file)
@@ -31,7 +31,6 @@
  * @ingroup Content
  */
 class WikitextContent extends TextContent {
-
        public function __construct( $text ) {
                parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
        }
@@ -73,11 +72,14 @@ class WikitextContent extends TextContent {
 
                if ( $section === '' ) {
                        wfProfileOut( __METHOD__ );
+
                        return $with; # XXX: copy first?
-               } if ( $section == 'new' ) {
+               }
+
+               if ( $section == 'new' ) {
                        # Inserting a new section
                        $subject = $sectionTitle ? wfMessage( 'newsectionheaderdefaultlevel' )
-                               ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
+                                       ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
                        if ( wfRunHooks( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
                                $text = strlen( trim( $oldtext ) ) > 0
                                        ? "{$oldtext}\n\n{$subject}{$text}"
@@ -93,6 +95,7 @@ class WikitextContent extends TextContent {
                $newContent = new WikitextContent( $text );
 
                wfProfileOut( __METHOD__ );
+
                return $newContent;
        }
 
@@ -183,14 +186,16 @@ class WikitextContent extends TextContent {
                                if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
                                        return null;
                                }
+
                                return $title;
                        }
                }
+
                return null;
        }
 
        /**
-        * @see   Content::updateRedirect()
+        * @see Content::updateRedirect()
         *
         * This implementation replaces the first link on the page with the given new target
         * if this Content object is a redirect. Otherwise, this method returns $this.
@@ -199,7 +204,8 @@ class WikitextContent extends TextContent {
         *
         * @param Title $target
         *
-        * @return Content a new Content object with the updated redirect (or $this if this Content object isn't a redirect)
+        * @return Content a new Content object with the updated redirect (or $this
+        *   if this Content object isn't a redirect)
         */
        public function updateRedirect( Title $target ) {
                if ( !$this->isRedirect() ) {
@@ -220,7 +226,7 @@ class WikitextContent extends TextContent {
         * Returns true if this content is not a redirect, and this content's text
         * is countable according to the criteria defined by $wgArticleCountMethod.
         *
-        * @param bool $hasLinks  if it is known whether this content contains
+        * @param bool $hasLinks if it is known whether this content contains
         *    links, provide this information here, to avoid redundant parsing to
         *    find out (default: null).
         * @param $title Title: (default: null)
@@ -298,6 +304,7 @@ class WikitextContent extends TextContent {
                }
 
                $po = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId );
+
                return $po;
        }
 
index b1b461f..1e8fd05 100644 (file)
@@ -29,7 +29,6 @@
  * @ingroup Content
  */
 class WikitextContentHandler extends TextContentHandler {
-
        public function __construct( $modelId = CONTENT_MODEL_WIKITEXT ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_WIKITEXT ) );
        }
@@ -72,7 +71,9 @@ class WikitextContentHandler extends TextContentHandler {
                }
 
                $mwRedir = MagicWord::get( 'redirect' );
-               $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $optionalColon . $destination->getFullText() . ']]';
+               $redirectText = $mwRedir->getSynonym( 0 ) .
+                       ' [[' . $optionalColon . $destination->getFullText() . ']]';
+
                if ( $text != '' ) {
                        $redirectText .= "\n" . $text;
                }
index e13cfa8..0a3f18f 100644 (file)
@@ -41,9 +41,11 @@ abstract class ContextSource implements IContextSource {
        public function getContext() {
                if ( $this->context === null ) {
                        $class = get_class( $this );
-                       wfDebug( __METHOD__ . " ($class): called and \$context is null. Using RequestContext::getMain() for sanity\n" );
+                       wfDebug( __METHOD__ . " ($class): called and \$context is null. " .
+                               "Using RequestContext::getMain() for sanity\n" );
                        $this->context = RequestContext::getMain();
                }
+
                return $this->context;
        }
 
@@ -130,6 +132,7 @@ abstract class ContextSource implements IContextSource {
         */
        public function getLang() {
                wfDeprecated( __METHOD__, '1.19' );
+
                return $this->getLanguage();
        }
 
@@ -162,6 +165,7 @@ abstract class ContextSource implements IContextSource {
         */
        public function msg( /* $args */ ) {
                $args = func_get_args();
+
                return call_user_func_array( array( $this->getContext(), 'msg' ), $args );
        }
 
index fd9bf96..e96269d 100644 (file)
@@ -99,6 +99,7 @@ class DerivativeContext extends ContextSource {
         * Set the Title object
         *
         * @param Title $t
+        * @throws MWException
         */
        public function setTitle( $t ) {
                if ( $t !== null && !$t instanceof Title ) {
@@ -298,6 +299,7 @@ class DerivativeContext extends ContextSource {
         */
        public function msg() {
                $args = func_get_args();
+
                return call_user_func_array( 'wfMessage', $args )->setContext( $this );
        }
 }
index 01ec57c..04879e2 100644 (file)
@@ -82,6 +82,7 @@ class RequestContext implements IContextSource {
                        global $wgRequest; # fallback to $wg till we can improve this
                        $this->request = $wgRequest;
                }
+
                return $this->request;
        }
 
@@ -89,6 +90,7 @@ class RequestContext implements IContextSource {
         * Set the Title object
         *
         * @param Title $t
+        * @throws MWException
         */
        public function setTitle( $t ) {
                if ( $t !== null && !$t instanceof Title ) {
@@ -109,6 +111,7 @@ class RequestContext implements IContextSource {
                        global $wgTitle; # fallback to $wg till we can improve this
                        $this->title = $wgTitle;
                }
+
                return $this->title;
        }
 
@@ -169,6 +172,7 @@ class RequestContext implements IContextSource {
                        }
                        $this->wikipage = WikiPage::factory( $title );
                }
+
                return $this->wikipage;
        }
 
@@ -188,6 +192,7 @@ class RequestContext implements IContextSource {
                if ( $this->output === null ) {
                        $this->output = new OutputPage( $this );
                }
+
                return $this->output;
        }
 
@@ -209,6 +214,7 @@ class RequestContext implements IContextSource {
                if ( $this->user === null ) {
                        $this->user = User::newFromSession( $this->getRequest() );
                }
+
                return $this->user;
        }
 
@@ -269,6 +275,7 @@ class RequestContext implements IContextSource {
         */
        public function getLang() {
                wfDeprecated( __METHOD__, '1.19' );
+
                return $this->getLanguage();
        }
 
@@ -364,6 +371,7 @@ class RequestContext implements IContextSource {
                        $this->skin->setContext( $this );
                        wfProfileOut( __METHOD__ . '-createskin' );
                }
+
                return $this->skin;
        }
 
@@ -377,6 +385,7 @@ class RequestContext implements IContextSource {
         */
        public function msg() {
                $args = func_get_args();
+
                return call_user_func_array( 'wfMessage', $args )->setContext( $this );
        }
 
@@ -392,6 +401,7 @@ class RequestContext implements IContextSource {
                if ( $instance === null ) {
                        $instance = new self;
                }
+
                return $instance;
        }
 
@@ -446,7 +456,7 @@ class RequestContext implements IContextSource {
                        $user = User::newFromName( $params['ip'], false );
                }
 
-               $importSessionFunction = function( User $user, array $params ) {
+               $importSessionFunction = function ( User $user, array $params ) {
                        global $wgRequest, $wgUser;
 
                        $context = RequestContext::getMain();
@@ -482,7 +492,7 @@ class RequestContext implements IContextSource {
                $importSessionFunction( $user, $params );
 
                // Set callback to save and close the new session and reload the old one
-               return new ScopedCallback( function() use ( $importSessionFunction, $oUser, $oParams ) {
+               return new ScopedCallback( function () use ( $importSessionFunction, $oUser, $oParams ) {
                        $importSessionFunction( $oUser, $oParams );
                } );
        }
@@ -510,6 +520,7 @@ class RequestContext implements IContextSource {
                        $context->setRequest( new FauxRequest( $request ) );
                }
                $context->user = User::newFromName( '127.0.0.1', false );
+
                return $context;
        }
 }
index 6c009de..a9f7b7f 100644 (file)
@@ -28,7 +28,6 @@
  * @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.
@@ -58,6 +57,7 @@ abstract class DBAccessBase implements IDBAccessObject {
         */
        protected function getConnection( $id, $groups = array() ) {
                $loadBalancer = wfGetLB( $this->wiki );
+
                return $loadBalancer->getConnection( $id, $groups, $this->wiki );
        }
 
@@ -68,7 +68,7 @@ abstract class DBAccessBase implements IDBAccessObject {
         *
         * @since 1.21
         *
-        * @param DatabaseBase  $db the database connection to release.
+        * @param DatabaseBase $db the database connection to release.
         */
        protected function releaseConnection( DatabaseBase $db ) {
                if ( $this->wiki !== false ) {
index de5e72c..3d1f453 100644 (file)
@@ -83,6 +83,7 @@ class ChronologyProtector {
                $info = $lb->parentInfo();
                if ( !$db || !$db->doneWrites() ) {
                        wfDebug( __METHOD__ . ": LB {$info['id']}, no writes done\n" );
+
                        return;
                }
                $pos = $db->getMasterPos();
index 819925c..1e01d29 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 class CloneDatabase {
-
        /**
         * Table prefix for cloning
         * @var String
@@ -66,8 +65,8 @@ class CloneDatabase {
         * @param $dropCurrentTables bool
         */
        public function __construct( DatabaseBase $db, array $tablesToClone,
-               $newTablePrefix, $oldTablePrefix = '', $dropCurrentTables = true )
-       {
+               $newTablePrefix, $oldTablePrefix = '', $dropCurrentTables = true
+       {
                $this->db = $db;
                $this->tablesToClone = $tablesToClone;
                $this->newTablePrefix = $newTablePrefix;
@@ -98,7 +97,9 @@ class CloneDatabase {
                        self::changePrefix( $this->newTablePrefix );
                        $newTableName = $this->db->tableName( $tbl, 'raw' );
 
-                       if ( $this->dropCurrentTables && !in_array( $this->db->getType(), array( 'postgres', 'oracle' ) ) ) {
+                       if ( $this->dropCurrentTables
+                               && !in_array( $this->db->getType(), array( 'postgres', 'oracle' ) )
+                       ) {
                                $this->db->dropTable( $tbl, __METHOD__ );
                                wfDebug( __METHOD__ . " dropping {$newTableName}\n", true );
                                //Dropping the oldTable because the prefix was changed
index 5f175a4..7275bd9 100644 (file)
@@ -208,7 +208,8 @@ interface DatabaseType {
  * Interface for classes that implement or wrap DatabaseBase
  * @ingroup Database
  */
-interface IDatabase {}
+interface IDatabase {
+}
 
 /**
  * Database abstraction object
@@ -243,7 +244,6 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        protected $mTablePrefix;
        protected $mFlags;
        protected $mForeign;
-       protected $mTrxLevel = 0;
        protected $mErrorCount = 0;
        protected $mLBInfo = array();
        protected $mFakeSlaveLag = null, $mFakeMaster = false;
@@ -256,6 +256,14 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
        protected $delimiter = ';';
 
+       /**
+        * Either 1 if a transaction is active or 0 otherwise.
+        * The other Trx fields may not be meaningfull if this is 0.
+        *
+        * @var int
+        */
+       protected $mTrxLevel = 0;
+
        /**
         * Remembers the function name given for starting the most recent transaction via begin().
         * Used to provide additional context for error reporting.
@@ -281,12 +289,32 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         */
        private $mTrxAutomatic = false;
 
+       /**
+        * Array of levels of atomicity within transactions
+        *
+        * @var SplStack
+        */
+       private $mTrxAtomicLevels;
+
+       /**
+        * Record if the current transaction was started implicitly by DatabaseBase::startAtomic
+        *
+        * @var Bool
+        */
+       private $mTrxAutomaticAtomic = false;
+
        /**
         * @since 1.21
         * @var file handle for upgrade
         */
        protected $fileHandle = null;
 
+       /**
+        * @since 1.22
+        * @var Process cache of VIEWs names in the database
+        */
+       protected $allViews = null;
+
 # ------------------------------------------------------------------------------
 # Accessors
 # ------------------------------------------------------------------------------
@@ -371,16 +399,15 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        }
 
        /**
-        * Gets or sets the current transaction level.
+        * Gets the current transaction level.
         *
         * Historically, transactions were allowed to be "nested". This is no
         * longer supported, so this function really only returns a boolean.
         *
-        * @param int $level An integer (0 or 1), or omitted to leave it unchanged.
         * @return int The previous value
         */
-       public function trxLevel( $level = null ) {
-               return wfSetVar( $this->mTrxLevel, $level );
+       public function trxLevel() {
+               return $this->mTrxLevel;
        }
 
        /**
@@ -600,7 +627,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        /**
         * Clear a flag for this connection
         *
-        * @param $flag: same as setFlag()'s $flag param
+        * @param $flag : same as setFlag()'s $flag param
         */
        public function clearFlag( $flag ) {
                global $wgDebugDBTransactions;
@@ -613,7 +640,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        /**
         * Returns a boolean whether the flag $flag is set for this connection
         *
-        * @param $flag: same as setFlag()'s $flag param
+        * @param $flag : same as setFlag()'s $flag param
         * @return Boolean
         */
        public function getFlag( $flag ) {
@@ -667,28 +694,37 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * connection object, by specifying no parameters to __construct(). This
         * feature is deprecated and should be removed.
         *
-        * FIXME: The long list of formal parameters here is not really appropriate
-        * for MySQL, and not at all appropriate for any other DBMS. It should be
-        * replaced by named parameters as in DatabaseBase::factory().
-        *
         * DatabaseBase subclasses should not be constructed directly in external
         * code. DatabaseBase::factory() should be used instead.
         *
-        * @param string $server database server host
-        * @param string $user database user name
-        * @param string $password database user password
-        * @param string $dbName database name
-        * @param $flags
-        * @param string $tablePrefix database table prefixes. By default use the prefix gave in LocalSettings.php
-        * @param bool $foreign disable some operations specific to local databases
+        * @param array Parameters passed from DatabaseBase::factory()
         */
-       function __construct( $server = false, $user = false, $password = false, $dbName = false,
-               $flags = 0, $tablePrefix = 'get from global', $foreign = false
-       ) {
+       function __construct( $params = null ) {
                global $wgDBprefix, $wgCommandLineMode, $wgDebugDBTransactions;
 
-               $this->mFlags = $flags;
+               $this->mTrxAtomicLevels = new SplStack;
+
+               if ( is_array( $params ) ) { // MW 1.22
+                       $server = $params['host'];
+                       $user = $params['user'];
+                       $password = $params['password'];
+                       $dbName = $params['dbname'];
+                       $flags = $params['flags'];
+                       $tablePrefix = $params['tablePrefix'];
+                       $foreign = $params['foreign'];
+               } else { // legacy calling pattern
+                       wfDeprecated( __METHOD__ . " method called without parameter array.", "1.23" );
+                       $args = func_get_args();
+                       $server = isset( $args[0] ) ? $args[0] : false;
+                       $user = isset( $args[1] ) ? $args[1] : false;
+                       $password = isset( $args[2] ) ? $args[2] : false;
+                       $dbName = isset( $args[3] ) ? $args[3] : false;
+                       $flags = isset( $args[4] ) ? $args[4] : 0;
+                       $tablePrefix = isset( $args[5] ) ? $args[5] : 'get from global';
+                       $foreign = isset( $args[6] ) ? $args[6] : false;
+               }
 
+               $this->mFlags = $flags;
                if ( $this->mFlags & DBO_DEFAULT ) {
                        if ( $wgCommandLineMode ) {
                                $this->mFlags &= ~DBO_TRX;
@@ -723,13 +759,14 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * not restored on unserialize.
         */
        public function __sleep() {
-               throw new MWException( 'Database serialization may cause problems, since the connection is not restored on wakeup.' );
+               throw new MWException( 'Database serialization may cause problems, since ' .
+                       'the connection is not restored on wakeup.' );
        }
 
        /**
         * Given a DB type, construct the name of the appropriate child class of
         * DatabaseBase. This is designed to replace all of the manual stuff like:
-        *      $class = 'Database' . ucfirst( strtolower( $dbType ) );
+        *    $class = 'Database' . ucfirst( strtolower( $dbType ) );
         * as well as validate against the canonical list of DB types we have
         *
         * This factory function is mostly useful for when you need to connect to a
@@ -749,11 +786,11 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         */
        final public static function factory( $dbType, $p = array() ) {
                $canonicalDBTypes = array(
-                       'mysql'    => array( 'mysqli', 'mysql' ),
+                       'mysql' => array( 'mysqli', 'mysql' ),
                        'postgres' => array(),
-                       'sqlite'   => array(),
-                       'oracle'   => array(),
-                       'mssql'    => array(),
+                       'sqlite' => array(),
+                       'oracle' => array(),
+                       'mssql' => array(),
                );
 
                $driver = false;
@@ -785,15 +822,17 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
                $class = 'Database' . ucfirst( $driver );
                if ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) {
-                       return new $class(
-                               isset( $p['host'] ) ? $p['host'] : false,
-                               isset( $p['user'] ) ? $p['user'] : false,
-                               isset( $p['password'] ) ? $p['password'] : false,
-                               isset( $p['dbname'] ) ? $p['dbname'] : false,
-                               isset( $p['flags'] ) ? $p['flags'] : 0,
-                               isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global',
-                               isset( $p['foreign'] ) ? $p['foreign'] : false
+                       $params = array(
+                               'host' => isset( $p['host'] ) ? $p['host'] : false,
+                               'user' => isset( $p['user'] ) ? $p['user'] : false,
+                               'password' => isset( $p['password'] ) ? $p['password'] : false,
+                               'dbname' => isset( $p['dbname'] ) ? $p['dbname'] : false,
+                               'flags' => isset( $p['flags'] ) ? $p['flags'] : 0,
+                               'tablePrefix' => isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global',
+                               'foreign' => isset( $p['foreign'] ) ? $p['foreign'] : false
                        );
+
+                       return new $class( $params );
                } else {
                        return null;
                }
@@ -816,6 +855,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( $this->mPHPError ) {
                        $error = preg_replace( '!\[<a.*</a>\]!', '', $this->mPHPError );
                        $error = preg_replace( '!^.*?:\s?(.*)$!', '$1', $error );
+
                        return $error;
                } else {
                        return false;
@@ -855,6 +895,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
                        $ret = $this->closeConnection();
                        $this->mConn = false;
+
                        return $ret;
                } else {
                        return true;
@@ -951,8 +992,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
                # If DBO_TRX is set, start a transaction
                if ( ( $this->mFlags & DBO_TRX ) && !$this->mTrxLevel &&
-                       $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK' )
-               {
+                       $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK'
+               {
                        # Avoid establishing transactions for SHOW and SET statements too -
                        # that would delay transaction initializations to once connection
                        # is really used by application
@@ -1008,9 +1049,9 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                # Try reconnecting if the connection was lost
                if ( false === $ret && $this->wasErrorReissuable() ) {
                        # Transaction is gone, like it or not
+                       $hadTrx = $this->mTrxLevel; // possible lost transaction
+                       wfDebug( "Connection lost, reconnecting...\n" );
                        $this->mTrxLevel = 0;
-                       $this->mTrxIdleCallbacks = array(); // cancel
-                       $this->mTrxPreCommitCallbacks = array(); // cancel
                        wfDebug( "Connection lost, reconnecting...\n" );
 
                        if ( $this->ping() ) {
@@ -1023,7 +1064,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                        # Not a database error to lose a transaction after a minute or two
                                        wfLogDBError( "Connection lost and reconnected after {$elapsed}s, query: $sqlx\n" );
                                }
-                               $ret = $this->doQuery( $commentedSql );
+                               if ( !$hadTrx ) {
+                                       # Should be safe to silently retry
+                                       $ret = $this->doQuery( $commentedSql );
+                               }
                        } else {
                                wfDebug( "Failed\n" );
                        }
@@ -1061,7 +1105,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        wfDebug( "SQL ERROR (ignored): $error\n" );
                        $this->ignoreErrors( $ignore );
                } else {
-                       $sql1line = str_replace( "\n", "\\n", $sql );
+                       $sql1line = mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 );
                        wfLogDBError( "$fname\t{$this->mServer}\t$errno\t$error\t$sql1line\n" );
                        wfDebug( "SQL ERROR: " . $error . "\n" );
                        throw new DBQueryError( $this, $error, $errno, $sql, $fname );
@@ -1159,9 +1203,15 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                return $arg;
                        case '&':
                                # return $this->addQuotes( file_get_contents( $arg ) );
-                               throw new DBUnexpectedError( $this, '& mode is not implemented. If it\'s really needed, uncomment the line above.' );
+                               throw new DBUnexpectedError(
+                                       $this,
+                                       '& mode is not implemented. If it\'s really needed, uncomment the line above.'
+                               );
                        default:
-                               throw new DBUnexpectedError( $this, 'Received invalid match. This should never happen!' );
+                               throw new DBUnexpectedError(
+                                       $this,
+                                       'Received invalid match. This should never happen!'
+                               );
                }
        }
 
@@ -1323,6 +1373,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                : $options['HAVING'];
                        $sql .= ' HAVING ' . $having;
                }
+
                return $sql;
        }
 
@@ -1339,8 +1390,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        $ob = is_array( $options['ORDER BY'] )
                                ? implode( ',', $options['ORDER BY'] )
                                : $options['ORDER BY'];
+
                        return ' ORDER BY ' . $ob;
                }
+
                return '';
        }
 
@@ -1507,8 +1560,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @see DatabaseBase::select()
         */
        public function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
-               $options = array(), $join_conds = array() )
-       {
+               $options = array(), $join_conds = array()
+       {
                if ( is_array( $vars ) ) {
                        $vars = implode( ',', $this->fieldNamesWithAlias( $vars ) );
                }
@@ -1572,8 +1625,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @return object|bool
         */
        public function selectRow( $table, $vars, $conds, $fname = __METHOD__,
-               $options = array(), $join_conds = array() )
-       {
+               $options = array(), $join_conds = array()
+       {
                $options = (array)$options;
                $options['LIMIT'] = 1;
                $res = $this->select( $table, $vars, $conds, $fname, $options, $join_conds );
@@ -1612,8 +1665,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @return Integer: row count
         */
        public function estimateRowCount( $table, $vars = '*', $conds = '',
-               $fname = __METHOD__, $options = array() )
-       {
+               $fname = __METHOD__, $options = array()
+       {
                $rows = 0;
                $res = $this->select( $table, array( 'rowcount' => 'COUNT(*)' ), $conds, $fname, $options );
 
@@ -1866,7 +1919,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @param $table  String name of the table to UPDATE. This will be passed through
         *                DatabaseBase::tableName().
         *
-        * @param array $values  An array of values to SET. For each array element,
+        * @param array $values An array of values to SET. For each array element,
         *                the key gives the field name, and the value gives the data
         *                to set that field to. The data will be quoted by
         *                DatabaseBase::addQuotes().
@@ -2040,6 +2093,30 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                return 'CONCAT(' . implode( ',', $stringList ) . ')';
        }
 
+       /**
+        * Build a GROUP_CONCAT or equivalent statement for a query.
+        *
+        * This is useful for combining a field for several rows into a single string.
+        * NULL values will not appear in the output, duplicated values will appear,
+        * and the resulting delimiter-separated values have no defined sort order.
+        * Code using the results may need to use the PHP unique() or sort() methods.
+        *
+        * @param string $delim Glue to bind the results together
+        * @param string|array $table Table name
+        * @param string $field Field name
+        * @param string|array $conds Conditions
+        * @param string|array $join_conds Join conditions
+        * @return String SQL text
+        * @since 1.23
+        */
+       public function buildGroupConcatField(
+               $delim, $table, $field, $conds = '', $join_conds = array()
+       ) {
+               $fld = "GROUP_CONCAT($field SEPARATOR " . $this->addQuotes( $delim ) . ')';
+
+               return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
+       }
+
        /**
         * Change the current database
         *
@@ -2054,6 +2131,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                # if your database engine supports a concept similar to MySQL's
                # databases you may as well.
                $this->mDBname = $db;
+
                return true;
        }
 
@@ -2121,7 +2199,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        list( $table ) = $dbDetails;
                        if ( $wgSharedDB !== null # We have a shared database
                                && $this->mForeign == false # We're not working on a foreign database
-                               && !$this->isQuotedIdentifier( $table ) # Paranoia check to prevent shared tables listing '`table`'
+                               && !$this->isQuotedIdentifier( $table ) # Prevent shared tables listing '`table`'
                                && in_array( $table, $wgSharedTables ) # A shared table is selected
                        ) {
                                $database = $wgSharedDB;
@@ -2223,6 +2301,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        }
                        $retval[] = $this->tableNameWithAlias( $table, $alias );
                }
+
                return $retval;
        }
 
@@ -2256,6 +2335,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        }
                        $retval[] = $this->fieldNameWithAlias( $field, $alias );
                }
+
                return $retval;
        }
 
@@ -2400,13 +2480,17 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        }
 
        /**
-        * LIKE statement wrapper, receives a variable-length argument list with parts of pattern to match
-        * containing either string literals that will be escaped or tokens returned by anyChar() or anyString().
-        * Alternatively, the function could be provided with an array of aforementioned parameters.
+        * LIKE statement wrapper, receives a variable-length argument list with
+        * parts of pattern to match containing either string literals that will be
+        * escaped or tokens returned by anyChar() or anyString(). Alternatively,
+        * the function could be provided with an array of aforementioned
+        * parameters.
         *
-        * Example: $dbr->buildLike( 'My_page_title/', $dbr->anyString() ) returns a LIKE clause that searches
-        * for subpages of 'My page title'.
-        * Alternatively: $pattern = array( 'My_page_title/', $dbr->anyString() ); $query .= $dbr->buildLike( $pattern );
+        * Example: $dbr->buildLike( 'My_page_title/', $dbr->anyString() ) returns
+        * a LIKE clause that searches for subpages of 'My page title'.
+        * Alternatively:
+        *   $pattern = array( 'My_page_title/', $dbr->anyString() );
+        *   $query .= $dbr->buildLike( $pattern );
         *
         * @since 1.16
         * @return String: fully built LIKE statement
@@ -2689,8 +2773,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @throws DBUnexpectedError
         */
        public function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds,
-               $fname = __METHOD__ )
-       {
+               $fname = __METHOD__
+       {
                if ( !$conds ) {
                        throw new DBUnexpectedError( $this,
                                'DatabaseBase::deleteJoin() called with empty $conds' );
@@ -2801,8 +2885,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         */
        public function insertSelect( $destTable, $srcTable, $varMap, $conds,
                $fname = __METHOD__,
-               $insertOptions = array(), $selectOptions = array() )
-       {
+               $insertOptions = array(), $selectOptions = array()
+       {
                $destTable = $this->tableName( $destTable );
 
                if ( is_array( $insertOptions ) ) {
@@ -2861,6 +2945,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( !is_numeric( $limit ) ) {
                        throw new DBUnexpectedError( $this, "Invalid non-numeric limit passed to limitResult()\n" );
                }
+
                return "$sql LIMIT "
                        . ( ( is_numeric( $offset ) && $offset != 0 ) ? "{$offset}," : "" )
                        . "{$limit} ";
@@ -2885,6 +2970,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         */
        public function unionQueries( $sqls, $all ) {
                $glue = $all ? ') UNION ALL (' : ') UNION (';
+
                return '(' . implode( $glue, $sqls ) . ')';
        }
 
@@ -2901,6 +2987,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( is_array( $cond ) ) {
                        $cond = $this->makeList( $cond, LIST_AND );
                }
+
                return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
        }
 
@@ -3021,9 +3108,11 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( $tries <= 0 ) {
                        $this->rollback( __METHOD__ );
                        $this->reportQueryError( $error, $errno, $sql, $fname );
+
                        return false;
                } else {
                        $this->commit( __METHOD__ );
+
                        return $retVal;
                }
        }
@@ -3048,15 +3137,18 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        if ( $wait > $timeout * 1e6 ) {
                                wfDebug( "Fake slave timed out waiting for $pos ($wait us)\n" );
                                wfProfileOut( __METHOD__ );
+
                                return -1;
                        } elseif ( $wait > 0 ) {
                                wfDebug( "Fake slave waiting $wait us\n" );
                                usleep( $wait );
                                wfProfileOut( __METHOD__ );
+
                                return 1;
                        } else {
                                wfDebug( "Fake slave up to date ($wait us)\n" );
                                wfProfileOut( __METHOD__ );
+
                                return 0;
                        }
                }
@@ -3076,6 +3168,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( !is_null( $this->mFakeSlaveLag ) ) {
                        $pos = new MySQLMasterPos( 'fake', microtime( true ) - $this->mFakeSlaveLag );
                        wfDebug( __METHOD__ . ": fake slave pos = $pos\n" );
+
                        return $pos;
                } else {
                        # Stub
@@ -3154,7 +3247,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                        $this->clearFlag( DBO_TRX ); // make each query its own transaction
                                        call_user_func( $phpCallback );
                                        $this->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
-                               } catch ( Exception $e ) {}
+                               } catch ( Exception $e ) {
+                               }
                        }
                } while ( count( $this->mTrxIdleCallbacks ) );
 
@@ -3177,7 +3271,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                try {
                                        list( $phpCallback ) = $callback;
                                        call_user_func( $phpCallback );
-                               } catch ( Exception $e ) {}
+                               } catch ( Exception $e ) {
+                               }
                        }
                } while ( count( $this->mTrxPreCommitCallbacks ) );
 
@@ -3187,22 +3282,91 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
        }
 
        /**
-        * Begin a transaction. If a transaction is already in progress, that transaction will be committed before the
-        * new transaction is started.
+        * Begin an atomic section of statements
+        *
+        * If a transaction has been started already, just keep track of the given
+        * section name to make sure the transaction is not committed pre-maturely.
+        * This function can be used in layers (with sub-sections), so use a stack
+        * to keep track of the different atomic sections. If there is no transaction,
+        * start one implicitly.
+        *
+        * The goal of this function is to create an atomic section of SQL queries
+        * without having to start a new transaction if it already exists.
         *
-        * Note that when the DBO_TRX flag is set (which is usually the case for web requests, but not for maintenance scripts),
-        * any previous database query will have started a transaction automatically.
+        * Atomic sections are more strict than transactions. With transactions,
+        * attempting to begin a new transaction when one is already running results
+        * in MediaWiki issuing a brief warning and doing an implicit commit. All
+        * atomic levels *must* be explicitly closed using DatabaseBase::endAtomic(),
+        * and any database transactions cannot be began or committed until all atomic
+        * levels are closed. There is no such thing as implicitly opening or closing
+        * an atomic section.
         *
-        * Nesting of transactions is not supported. Attempts to nest transactions will cause a warning, unless the current
-        * transaction was started automatically because of the DBO_TRX flag.
+        * @since 1.23
+        * @param string $fname
+        * @throws DBError
+        */
+       final public function startAtomic( $fname = __METHOD__ ) {
+               if ( !$this->mTrxLevel ) {
+                       $this->begin( $fname );
+                       $this->mTrxAutomatic = true;
+                       $this->mTrxAutomaticAtomic = true;
+               }
+
+               $this->mTrxAtomicLevels->push( $fname );
+       }
+
+       /**
+        * Ends an atomic section of SQL statements
+        *
+        * Ends the next section of atomic SQL statements and commits the transaction
+        * if necessary.
+        *
+        * @since 1.23
+        * @see DatabaseBase::startAtomic
+        * @param string $fname
+        * @throws DBError
+        */
+       final public function endAtomic( $fname = __METHOD__ ) {
+               if ( !$this->mTrxLevel ) {
+                       throw new DBUnexpectedError( $this, 'No atomic transaction is open.' );
+               }
+               if ( $this->mTrxAtomicLevels->isEmpty() ||
+                       $this->mTrxAtomicLevels->pop() !== $fname
+               ) {
+                       throw new DBUnexpectedError( $this, 'Invalid atomic section ended.' );
+               }
+
+               if ( $this->mTrxAtomicLevels->isEmpty() && $this->mTrxAutomaticAtomic ) {
+                       $this->commit( $fname, 'flush' );
+               }
+       }
+
+       /**
+        * Begin a transaction. If a transaction is already in progress,
+        * that transaction will be committed before the new transaction is started.
+        *
+        * Note that when the DBO_TRX flag is set (which is usually the case for web
+        * requests, but not for maintenance scripts), any previous database query
+        * will have started a transaction automatically.
+        *
+        * Nesting of transactions is not supported. Attempts to nest transactions
+        * will cause a warning, unless the current transaction was started
+        * automatically because of the DBO_TRX flag.
         *
         * @param $fname string
+        * @throws DBError
         */
        final public function begin( $fname = __METHOD__ ) {
                global $wgDebugDBTransactions;
 
                if ( $this->mTrxLevel ) { // implicit commit
-                       if ( !$this->mTrxAutomatic ) {
+                       if ( !$this->mTrxAtomicLevels->isEmpty() ) {
+                               // If the current transaction was an automatic atomic one, then we definitely have
+                               // a problem. Same if there is any unclosed atomic level.
+                               throw new DBUnexpectedError( $this,
+                                       "Attempted to start explicit transaction when atomic levels are still open."
+                               );
+                       } elseif ( !$this->mTrxAutomatic ) {
                                // We want to warn about inadvertently nested begin/commit pairs, but not about
                                // auto-committing implicit transactions that were started by query() via DBO_TRX
                                $msg = "$fname: Transaction already in progress (from {$this->mTrxFname}), " .
@@ -3231,6 +3395,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                $this->mTrxFname = $fname;
                $this->mTrxDoneWrites = false;
                $this->mTrxAutomatic = false;
+               $this->mTrxAutomaticAtomic = false;
+               $this->mTrxAtomicLevels = new SplStack;
+               $this->mTrxIdleCallbacks = array();
+               $this->mTrxPreCommitCallbacks = array();
        }
 
        /**
@@ -3251,12 +3419,21 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * Nesting of transactions is not supported.
         *
         * @param $fname string
-        * @param string $flush Flush flag, set to 'flush' to disable warnings about explicitly committing implicit
-        *        transactions, or calling commit when no transaction is in progress.
-        *        This will silently break any ongoing explicit transaction. Only set the flush flag if you are sure
-        *        that it is safe to ignore these warnings in your context.
+        * @param string $flush Flush flag, set to 'flush' to disable warnings about
+        *   explicitly committing implicit transactions, or calling commit when no
+        *   transaction is in progress. This will silently break any ongoing
+        *   explicit transaction. Only set the flush flag if you are sure that it
+        *   is safe to ignore these warnings in your context.
         */
        final public function commit( $fname = __METHOD__, $flush = '' ) {
+               if ( !$this->mTrxAtomicLevels->isEmpty() ) {
+                       // There are still atomic sections open. This cannot be ignored
+                       throw new DBUnexpectedError(
+                               $this,
+                               "Attempted to commit transaction while atomic sections are still open"
+                       );
+               }
+
                if ( $flush != 'flush' ) {
                        if ( !$this->mTrxLevel ) {
                                wfWarn( "$fname: No transaction to commit, something got out of sync!" );
@@ -3276,7 +3453,6 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( $this->mTrxDoneWrites ) {
                        Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
                }
-               $this->mTrxDoneWrites = false;
                $this->runOnTransactionIdleCallbacks();
        }
 
@@ -3308,10 +3484,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                $this->doRollback( $fname );
                $this->mTrxIdleCallbacks = array(); // cancel
                $this->mTrxPreCommitCallbacks = array(); // cancel
+               $this->mTrxAtomicLevels = new SplStack;
                if ( $this->mTrxDoneWrites ) {
                        Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
                }
-               $this->mTrxDoneWrites = false;
        }
 
        /**
@@ -3360,6 +3536,40 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                throw new MWException( 'DatabaseBase::listTables is not implemented in descendant class' );
        }
 
+       /**
+        * Reset the views process cache set by listViews()
+        * @since 1.22
+        */
+       final public function clearViewsCache() {
+               $this->allViews = null;
+       }
+
+       /**
+        * Lists all the VIEWs in the database
+        *
+        * For caching purposes the list of all views should be stored in
+        * $this->allViews. The process cache can be cleared with clearViewsCache()
+        *
+        * @param string $prefix Only show VIEWs with this prefix, eg. unit_test_
+        * @param string $fname Name of calling function
+        * @throws MWException
+        * @since 1.22
+        */
+       public function listViews( $prefix = null, $fname = __METHOD__ ) {
+               throw new MWException( 'DatabaseBase::listViews is not implemented in descendant class' );
+       }
+
+       /**
+        * Differentiates between a TABLE and a VIEW
+        *
+        * @param $name string: Name of the database-structure to test.
+        * @throws MWException
+        * @since 1.22
+        */
+       public function isView( $name ) {
+               throw new MWException( 'DatabaseBase::isView is not implemented in descendant class' );
+       }
+
        /**
         * Convert a timestamp in one of the formats accepted by wfTimestamp()
         * to the format used for inserting into timestamp fields in this DBMS.
@@ -3502,8 +3712,9 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @param bool|callable $lineCallback Optional function called before reading each line
         * @param bool|callable $resultCallback Optional function called for each MySQL result
         * @param bool|string $fname Calling function name or false if name should be
-        *      generated dynamically using $filename
-        * @param bool|callable $inputCallback Callback: Optional function called for each complete line sent
+        *   generated dynamically using $filename
+        * @param bool|callable $inputCallback Callback: Optional function called
+        *   for each complete line sent
         * @throws MWException
         * @throws Exception|MWException
         * @return bool|string
@@ -3525,8 +3736,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
                try {
                        $error = $this->sourceStream( $fp, $lineCallback, $resultCallback, $fname, $inputCallback );
-               }
-               catch ( MWException $e ) {
+               } catch ( MWException $e ) {
                        fclose( $fp );
                        throw $e;
                }
@@ -3580,8 +3790,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * @return bool|string
         */
        public function sourceStream( $fp, $lineCallback = false, $resultCallback = false,
-               $fname = __METHOD__, $inputCallback = false )
-       {
+               $fname = __METHOD__, $inputCallback = false
+       {
                $cmd = '';
 
                while ( !feof( $fp ) ) {
@@ -3619,6 +3829,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
 
                                        if ( false === $res ) {
                                                $err = $this->lastError();
+
                                                return "Query \"{$cmd}\" failed with error code \"$err\".\n";
                                        }
                                }
@@ -3644,6 +3855,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                                return true;
                        }
                }
+
                return false;
        }
 
@@ -3674,6 +3886,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        // replace /*$var*/
                        $ins = str_replace( '/*$' . $var . '*/', $this->strencode( $value ), $ins );
                }
+
                return $ins;
        }
 
@@ -3827,6 +4040,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( $this->cascadingDeletes() ) {
                        $sql .= " CASCADE";
                }
+
                return $this->query( $sql, $fName );
        }
 
@@ -3906,11 +4120,10 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( count( $this->mTrxIdleCallbacks ) || count( $this->mTrxPreCommitCallbacks ) ) {
                        $callers = array();
                        foreach ( $this->mTrxIdleCallbacks as $callbackInfo ) {
-                               $callers[] = $callbackInfo[0];
-
+                               $callers[] = $callbackInfo[1];
                        }
                        $callers = implode( ', ', $callers );
-                       trigger_error( "DB transaction  callbacks still pending (from $callers)." );
+                       trigger_error( "DB transaction callbacks still pending (from $callers)." );
                }
        }
 }
index da391d7..8be8530 100644 (file)
@@ -26,7 +26,6 @@
  * @ingroup Database
  */
 class DBError extends MWException {
-
        /**
         * @var DatabaseBase
         */
@@ -66,8 +65,7 @@ class DBError extends MWException {
                $s = $this->getHTMLContent();
 
                if ( $wgShowDBErrorBacktrace ) {
-                       $s .= '<p>Backtrace:</p><p>' .
-                               nl2br( htmlspecialchars( $this->getTraceAsString() ) ) . '</p>';
+                       $s .= '<p>Backtrace:</p><pre>' . htmlspecialchars( $this->getTraceAsString() ) . '</pre>';
                }
 
                return $s;
@@ -130,32 +128,32 @@ class DBConnectionError extends DBError {
                } else {
                        $message = $fallback;
                }
+
                return wfMsgReplaceArgs( $message, $args );
        }
 
        /**
-        * @return bool
+        * @return boolean
         */
-       function getLogMessage() {
-               # Don't send to the exception log
+       function isLoggable() {
+               // Don't send to the exception log, already in dberror log
                return false;
        }
 
-       /**
-        * @return string
-        */
-       function getPageTitle() {
-               return $this->msg( 'dberr-header', 'This wiki has a problem' );
-       }
-
        /**
         * @return string
         */
        function getHTML() {
                global $wgShowDBErrorBacktrace, $wgShowHostnames, $wgShowSQLErrors;
 
-               $sorry = htmlspecialchars( $this->msg( 'dberr-problems', "Sorry!\nThis site is experiencing technical difficulties." ) );
-               $again = htmlspecialchars( $this->msg( 'dberr-again', 'Try waiting a few minutes and reloading.' ) );
+               $sorry = htmlspecialchars( $this->msg(
+                       'dberr-problems',
+                       'Sorry! This site is experiencing technical difficulties.'
+               ) );
+               $again = htmlspecialchars( $this->msg(
+                       'dberr-again',
+                       'Try waiting a few minutes and reloading.'
+               ) );
 
                if ( $wgShowHostnames || $wgShowSQLErrors ) {
                        $info = str_replace(
@@ -163,23 +161,25 @@ class DBConnectionError extends DBError {
                                htmlspecialchars( $this->msg( 'dberr-info', '(Cannot contact the database server: $1)' ) )
                        );
                } else {
-                       $info = htmlspecialchars( $this->msg( 'dberr-info-hidden', '(Cannot contact the database server)' ) );
+                       $info = htmlspecialchars( $this->msg(
+                               'dberr-info-hidden',
+                               '(Cannot contact the database server)'
+                       ) );
                }
 
                # No database access
                MessageCache::singleton()->disable();
 
-               $text = "<h1>$sorry</h1><p>$again</p><p><small>$info</small></p>";
+               $html = "<h1>$sorry</h1><p>$again</p><p><small>$info</small></p>";
 
                if ( $wgShowDBErrorBacktrace ) {
-                       $text .= '<p>Backtrace:</p><p>' .
-                               nl2br( htmlspecialchars( $this->getTraceAsString() ) ) . '</p>';
+                       $html .= '<p>Backtrace:</p><pre>' . htmlspecialchars( $this->getTraceAsString() ) . '</pre>';
                }
 
-               $text .= '<hr />';
-               $text .= $this->searchForm();
+               $html .= '<hr />';
+               $html .= $this->searchForm();
 
-               return $text;
+               return $html;
        }
 
        protected function getTextContent() {
@@ -195,22 +195,23 @@ class DBConnectionError extends DBError {
        public function reportHTML() {
                global $wgUseFileCache;
 
-               # Check whether we can serve a file-cached copy of the page with the error underneath
+               // Check whether we can serve a file-cached copy of the page with the error underneath
                if ( $wgUseFileCache ) {
                        try {
                                $cache = $this->fileCachedPage();
-                               # Cached version on file system?
+                               // Cached version on file system?
                                if ( $cache !== null ) {
-                                       # Hack: extend the body for error messages
+                                       // Hack: extend the body for error messages
                                        $cache = str_replace( array( '</html>', '</body>' ), '', $cache );
-                                       # Add cache notice...
-                                       $cache .= '<div style="color:red;font-size:150%;font-weight:bold;">' .
+                                       // Add cache notice...
+                                       $cache .= '<div style="border:1px solid #ffd0d0;padding:1em;">' .
                                                htmlspecialchars( $this->msg( 'dberr-cachederror',
-                                                       'This is a cached copy of the requested page, and may not be up to date. ' ) ) .
+                                                       'This is a cached copy of the requested page, and may not be up to date.' ) ) .
                                                '</div>';
 
-                                       # Output cached page with notices on bottom and re-close body
+                                       // Output cached page with notices on bottom and re-close body
                                        echo "{$cache}<hr />{$this->getHTML()}</body></html>";
+
                                        return;
                                }
                        } catch ( MWException $e ) {
@@ -218,7 +219,7 @@ class DBConnectionError extends DBError {
                        }
                }
 
-               # We can't, cough and die in the usual fashion
+               // We can't, cough and die in the usual fashion
                parent::reportHTML();
        }
 
@@ -228,8 +229,14 @@ class DBConnectionError extends DBError {
        function searchForm() {
                global $wgSitename, $wgCanonicalServer, $wgRequest;
 
-               $usegoogle = htmlspecialchars( $this->msg( 'dberr-usegoogle', 'You can try searching via Google in the meantime.' ) );
-               $outofdate = htmlspecialchars( $this->msg( 'dberr-outofdate', 'Note that their indexes of our content may be out of date.' ) );
+               $usegoogle = htmlspecialchars( $this->msg(
+                       'dberr-usegoogle',
+                       'You can try searching via Google in the meantime.'
+               ) );
+               $outofdate = htmlspecialchars( $this->msg(
+                       'dberr-outofdate',
+                       'Note that their indexes of our content may be out of date.'
+               ) );
                $googlesearch = htmlspecialchars( $this->msg( 'searchbutton', 'Search' ) );
 
                $search = htmlspecialchars( $wgRequest->getVal( 'search' ) );
@@ -239,8 +246,8 @@ class DBConnectionError extends DBError {
 
                $trygoogle = <<<EOT
 <div style="margin: 1.5em">$usegoogle<br />
-<small>$outofdate</small></div>
-<!-- SiteSearch Google -->
+<small>$outofdate</small>
+</div>
 <form method="get" action="//www.google.com/search" id="googlesearch">
        <input type="hidden" name="domains" value="$server" />
        <input type="hidden" name="num" value="50" />
@@ -249,13 +256,13 @@ class DBConnectionError extends DBError {
 
        <input type="text" name="q" size="31" maxlength="255" value="$search" />
        <input type="submit" name="btnG" value="$googlesearch" />
-  <div>
-       <input type="radio" name="sitesearch" id="gwiki" value="$server" checked="checked" /><label for="gwiki">$sitename</label>
-       <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
-  </div>
+       <p>
+               <label><input type="radio" name="sitesearch" value="$server" checked="checked" />$sitename</label>
+               <label><input type="radio" name="sitesearch" value="" />WWW</label>
+       </p>
 </form>
-<!-- SiteSearch Google -->
 EOT;
+
                return $trygoogle;
        }
 
@@ -266,15 +273,17 @@ EOT;
                global $wgTitle, $wgOut, $wgRequest;
 
                if ( $wgOut->isDisabled() ) {
-                       return ''; // Done already?
+                       // Done already?
+                       return '';
                }
 
-               if ( $wgTitle ) { // use $wgTitle if we managed to set it
+               if ( $wgTitle ) {
+                       // use $wgTitle if we managed to set it
                        $t = $wgTitle->getPrefixedDBkey();
                } else {
-                       # Fallback to the raw title URL param. We can't use the Title
-                       # class is it may hit the interwiki table and give a DB error.
-                       # We may get a cache miss due to not sanitizing the title though.
+                       // Fallback to the raw title URL param. We can't use the Title
+                       // class is it may hit the interwiki table and give a DB error.
+                       // We may get a cache miss due to not sanitizing the title though.
                        $t = str_replace( ' ', '_', $wgRequest->getVal( 'title' ) );
                        if ( $t == '' ) { // fallback to main page
                                $t = Title::newFromText(
@@ -305,7 +314,9 @@ class DBQueryError extends DBError {
         * @param $fname string
         */
        function __construct( DatabaseBase $db, $error, $errno, $sql, $fname ) {
-               $message = "A database error has occurred. Did you forget to run maintenance/update.php after upgrading?  See: https://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
+               $message = "A database error has occurred. Did you forget to run " .
+                       "maintenance/update.php after upgrading?  See: " .
+                       "https://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
                        "Query: $sql\n" .
                        "Function: $fname\n" .
                        "Error: $errno $error\n";
@@ -318,15 +329,15 @@ class DBQueryError extends DBError {
        }
 
        /**
-        * @return bool
+        * @return boolean
         */
-       function getLogMessage() {
-               # Don't send to the exception log
+       function isLoggable() {
+               // Don't send to the exception log, already in dberror log
                return false;
        }
 
        /**
-        * @return String
+        * @return string
         */
        function getPageTitle() {
                return $this->msg( 'databaseerror', 'Database error' );
@@ -416,12 +427,13 @@ This may indicate a bug in the software.',
                        'databaseerror-function' => 'Function: $1',
                        'databaseerror-error' => 'Error: $1',
                );
+
                return $messages[$key];
        }
-
 }
 
 /**
  * @ingroup Database
  */
-class DBUnexpectedError extends DBError {}
+class DBUnexpectedError extends DBError {
+}
index 240a097..5a5eab1 100644 (file)
@@ -78,12 +78,16 @@ class DatabaseMssql extends DatabaseBase {
        function open( $server, $user, $password, $dbName ) {
                # Test for driver support, to avoid suppressed fatal error
                if ( !function_exists( 'sqlsrv_connect' ) ) {
-                       throw new DBConnectionError( $this, "MS Sql Server Native (sqlsrv) functions missing. You can download the driver from: http://go.microsoft.com/fwlink/?LinkId=123470\n" );
+                       throw new DBConnectionError(
+                               $this,
+                               "MS Sql Server Native (sqlsrv) functions missing. You can download " .
+                                       "the driver from: http://go.microsoft.com/fwlink/?LinkId=123470\n" );
                }
 
                global $wgDBport;
 
-               if ( !strlen( $user ) ) { # e.g. the class is being loaded
+               # e.g. the class is being loaded
+               if ( !strlen( $user ) ) {
                        return;
                }
 
@@ -102,9 +106,11 @@ class DatabaseMssql extends DatabaseBase {
 
                // Start NT Auth Hack
                // Quick and dirty work around to provide NT Auth designation support.
-               // Current solution requires installer to know to input 'ntauth' for both username and password
-               // to trigger connection via NT Auth. - ugly, ugly, ugly
-               // TO-DO: Make this better and add NT Auth choice to MW installer when SQL Server option is chosen.
+               // Current solution requires installer to know to input 'ntauth' for
+               // both username and password to trigger connection via NT Auth. Ugly,
+               // ugly, ugly!
+               // @todo Make this better and add NT Auth choice to MW installer when
+               // SQL Server option is chosen.
                $ntAuthUserTest = strtolower( $user );
                $ntAuthPassTest = strtolower( $password );
 
@@ -123,12 +129,15 @@ class DatabaseMssql extends DatabaseBase {
 
                if ( $this->mConn === false ) {
                        wfDebug( "DB connection error\n" );
-                       wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" );
+                       wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " .
+                               substr( $password, 0, 3 ) . "...\n" );
                        wfDebug( $this->lastError() . "\n" );
+
                        return false;
                }
 
                $this->mOpened = true;
+
                return $this->mConn;
        }
 
@@ -145,10 +154,11 @@ class DatabaseMssql extends DatabaseBase {
                wfDebug( "SQL: [$sql]\n" );
                $this->offset = 0;
 
-               // several extensions seem to think that all databases support limits via LIMIT N after the WHERE clause
-               // well, MSSQL uses SELECT TOP N, so to catch any of those extensions we'll do a quick check for a LIMIT
-               // clause and pass $sql through $this->LimitToTopN() which parses the limit clause and passes the result to
-               // $this->limitResult();
+               // several extensions seem to think that all databases support limits
+               // via LIMIT N after the WHERE clause well, MSSQL uses SELECT TOP N,
+               // so to catch any of those extensions we'll do a quick check for a
+               // LIMIT clause and pass $sql through $this->LimitToTopN() which parses
+               // the limit clause and passes the result to $this->limitResult();
                if ( preg_match( '/\bLIMIT\s*/i', $sql ) ) {
                        // massage LIMIT -> TopN
                        $sql = $this->LimitToTopN( $sql );
@@ -163,7 +173,9 @@ class DatabaseMssql extends DatabaseBase {
                // perform query
                $stmt = sqlsrv_query( $this->mConn, $sql );
                if ( $stmt == false ) {
-                       $message = "A database error has occurred. Did you forget to run maintenance/update.php after upgrading?  See: http://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
+                       $message = "A database error has occurred. Did you forget " .
+                               "to run maintenance/update.php after upgrading?  See: " .
+                               "http://www.mediawiki.org/wiki/Manual:Upgrading#Run_the_update_script\n" .
                                "Query: " . htmlentities( $sql ) . "\n" .
                                "Function: " . __METHOD__ . "\n";
                        // process each error (our driver will give us an array of errors unlike other providers)
@@ -176,9 +188,11 @@ class DatabaseMssql extends DatabaseBase {
                // remember number of rows affected
                $this->mAffectedRows = sqlsrv_rows_affected( $stmt );
 
-               // if it is a SELECT statement, or an insert with a request to output something we want to return a row.
+               // if it is a SELECT statement, or an insert with a request to output
+               // something we want to return a row.
                if ( ( preg_match( '#\bSELECT\s#i', $sql ) ) ||
-                       ( preg_match( '#\bINSERT\s#i', $sql ) && preg_match( '#\bOUTPUT\s+INSERTED\b#i', $sql ) ) ) {
+                       ( preg_match( '#\bINSERT\s#i', $sql ) && preg_match( '#\bOUTPUT\s+INSERTED\b#i', $sql ) )
+               ) {
                        // this is essentially a rowset, but Mediawiki calls these 'result'
                        // the rowset owns freeing the statement
                        $res = new MssqlResult( $stmt );
@@ -186,6 +200,7 @@ class DatabaseMssql extends DatabaseBase {
                        // otherwise we simply return it was successful, failure throws an exception
                        $res = true;
                }
+
                return $res;
        }
 
@@ -201,6 +216,7 @@ class DatabaseMssql extends DatabaseBase {
                        $res = $res->result;
                }
                $row = $res->fetch( 'OBJECT' );
+
                return $row;
        }
 
@@ -216,6 +232,7 @@ class DatabaseMssql extends DatabaseBase {
                } else {
                        $strRet = "No errors found";
                }
+
                return $strRet;
        }
 
@@ -224,6 +241,7 @@ class DatabaseMssql extends DatabaseBase {
                        $res = $res->result;
                }
                $row = $res->fetch( SQLSRV_FETCH_BOTH );
+
                return $row;
        }
 
@@ -231,6 +249,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return ( $res ) ? $res->numrows() : 0;
        }
 
@@ -238,6 +257,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return ( $res ) ? $res->numfields() : 0;
        }
 
@@ -245,6 +265,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return ( $res ) ? $res->fieldname( $n ) : 0;
        }
 
@@ -260,6 +281,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return ( $res ) ? $res->seek( $row ) : false;
        }
 
@@ -291,21 +313,26 @@ class DatabaseMssql extends DatabaseBase {
         * @param $vars    Mixed: array or string, field name(s) to be retrieved
         * @param $conds   Mixed: array or string, condition(s) for WHERE
         * @param $fname   String: calling function name (use __METHOD__) for logs/profiling
-        * @param array $options associative array of options (e.g. array('GROUP BY' => 'page_title')),
-        *                 see Database::makeSelectOptions code for list of supported stuff
-        * @param $join_conds Array: Associative array of table join conditions (optional)
-        *                                                 (e.g. array( 'page' => array('LEFT JOIN','page_latest=rev_id') )
-        * @return Mixed: database result resource (feed to Database::fetchObject or whatever), or false on failure
+        * @param array $options associative array of options (e.g.
+        *   array('GROUP BY' => 'page_title')), see Database::makeSelectOptions
+        *   code for list of supported stuff
+        * @param $join_conds Array: Associative array of table join conditions
+        *   (optional) (e.g. array( 'page' => array('LEFT JOIN','page_latest=rev_id') )
+        * @return Mixed: database result resource (feed to Database::fetchObject
+        *   or whatever), or false on failure
         */
-       function select( $table, $vars, $conds = '', $fname = __METHOD__, $options = array(), $join_conds = array() )
-       {
+       function select( $table, $vars, $conds = '', $fname = __METHOD__,
+               $options = array(), $join_conds = array()
+       ) {
                $sql = $this->selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
                if ( isset( $options['EXPLAIN'] ) ) {
                        sqlsrv_query( $this->mConn, "SET SHOWPLAN_ALL ON;" );
                        $ret = $this->query( $sql, $fname );
                        sqlsrv_query( $this->mConn, "SET SHOWPLAN_ALL OFF;" );
+
                        return $ret;
                }
+
                return $this->query( $sql, $fname );
        }
 
@@ -316,16 +343,19 @@ class DatabaseMssql extends DatabaseBase {
         * @param $vars    Mixed:  Array or string, field name(s) to be retrieved
         * @param $conds   Mixed:  Array or string, condition(s) for WHERE
         * @param $fname   String: Calling function name (use __METHOD__) for logs/profiling
-        * @param array $options  Associative array of options (e.g. array('GROUP BY' => 'page_title')),
+        * @param array $options Associative array of options (e.g. array('GROUP BY' => 'page_title')),
         *                 see Database::makeSelectOptions code for list of supported stuff
         * @param $join_conds Array: Associative array of table join conditions (optional)
         *                    (e.g. array( 'page' => array('LEFT JOIN','page_latest=rev_id') )
         * @return string, the SQL text
         */
-       function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__, $options = array(), $join_conds = array() ) {
+       function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
+               $options = array(), $join_conds = array()
+       ) {
                if ( isset( $options['EXPLAIN'] ) ) {
                        unset( $options['EXPLAIN'] );
                }
+
                return parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
        }
 
@@ -337,8 +367,11 @@ class DatabaseMssql extends DatabaseBase {
         * Takes same arguments as Database::select()
         * @return int
         */
-       function estimateRowCount( $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array() ) {
-               $options['EXPLAIN'] = true;// http://msdn2.microsoft.com/en-us/library/aa259203.aspx
+       function estimateRowCount( $table, $vars = '*', $conds = '',
+               $fname = __METHOD__, $options = array()
+       ) {
+               // http://msdn2.microsoft.com/en-us/library/aa259203.aspx
+               $options['EXPLAIN'] = true;
                $res = $this->select( $table, $vars, $conds, $fname, $options );
 
                $rows = -1;
@@ -348,6 +381,7 @@ class DatabaseMssql extends DatabaseBase {
                                $rows = $row['EstimateRows'];
                        }
                }
+
                return $rows;
        }
 
@@ -357,8 +391,9 @@ class DatabaseMssql extends DatabaseBase {
         * @return array|bool|null
         */
        function indexInfo( $table, $index, $fname = __METHOD__ ) {
-               # This does not return the same info as MYSQL would, but that's OK because MediaWiki never uses the
-               # returned value except to check for the existance of indexes.
+               # This does not return the same info as MYSQL would, but that's OK
+               # because MediaWiki never uses the returned value except to check for
+               # the existance of indexes.
                $sql = "sp_helpindex '" . $table . "'";
                $res = $this->query( $sql, $fname );
                if ( !$res ) {
@@ -383,6 +418,7 @@ class DatabaseMssql extends DatabaseBase {
                                }
                        }
                }
+
                return empty( $result ) ? false : $result;
        }
 
@@ -413,16 +449,20 @@ class DatabaseMssql extends DatabaseBase {
 
                $table = $this->tableName( $table );
 
-               if ( !( isset( $arrToInsert[0] ) && is_array( $arrToInsert[0] ) ) ) {// Not multi row
-                       $arrToInsert = array( 0 => $arrToInsert );// make everything multi row compatible
+               if ( !( isset( $arrToInsert[0] ) && is_array( $arrToInsert[0] ) ) ) { // Not multi row
+                       $arrToInsert = array( 0 => $arrToInsert ); // make everything multi row compatible
                }
 
                $allOk = true;
 
                // We know the table we're inserting into, get its identity column
                $identity = null;
-               $tableRaw = preg_replace( '#\[([^\]]*)\]#', '$1', $table ); // strip matching square brackets from table name
-               $res = $this->doQuery( "SELECT NAME AS idColumn FROM SYS.IDENTITY_COLUMNS WHERE OBJECT_NAME(OBJECT_ID)='{$tableRaw}'" );
+               // strip matching square brackets from table name
+               $tableRaw = preg_replace( '#\[([^\]]*)\]#', '$1', $table );
+               $res = $this->doQuery(
+                       "SELECT NAME AS idColumn FROM SYS.IDENTITY_COLUMNS " .
+                               "WHERE OBJECT_NAME(OBJECT_ID)='{$tableRaw}'"
+               );
                if ( $res && $res->numrows() ) {
                        // There is an identity for this table.
                        $identity = array_pop( $res->fetch( SQLSRV_FETCH_ASSOC ) );
@@ -430,7 +470,8 @@ class DatabaseMssql extends DatabaseBase {
                unset( $res );
 
                foreach ( $arrToInsert as $a ) {
-                       // start out with empty identity column, this is so we can return it as a result of the insert logic
+                       // start out with empty identity column, this is so we can return
+                       // it as a result of the insert logic
                        $sqlPre = '';
                        $sqlPost = '';
                        $identityClause = '';
@@ -444,14 +485,15 @@ class DatabaseMssql extends DatabaseBase {
                                                        // there is a value being passed to us, we need to turn on and off inserted identity
                                                        $sqlPre = "SET IDENTITY_INSERT $table ON;";
                                                        $sqlPost = ";SET IDENTITY_INSERT $table OFF;";
-
                                                } else {
                                                        // we can't insert NULL into an identity column, so remove the column from the insert.
                                                        unset( $a[$k] );
                                                }
                                        }
                                }
-                               $identityClause = "OUTPUT INSERTED.$identity "; // we want to output an identity column as result
+
+                               // we want to output an identity column as result
+                               $identityClause = "OUTPUT INSERTED.$identity ";
                        }
 
                        $keys = array_keys( $a );
@@ -469,7 +511,8 @@ class DatabaseMssql extends DatabaseBase {
                        // translate MySQL INSERT IGNORE to something SQL Server can use
                        // example:
                        // MySQL: INSERT IGNORE INTO user_groups (ug_user,ug_group) VALUES ('1','sysop')
-                       // MSSQL: IF NOT EXISTS (SELECT * FROM user_groups WHERE ug_user = '1') INSERT INTO user_groups (ug_user,ug_group) VALUES ('1','sysop')
+                       // MSSQL: IF NOT EXISTS (SELECT * FROM user_groups WHERE ug_user = '1')
+                       //        INSERT INTO user_groups (ug_user,ug_group) VALUES ('1','sysop')
                        if ( $ignoreClause ) {
                                $prival = $a[$keys[0]];
                                $sqlPre .= "IF NOT EXISTS (SELECT * FROM $table WHERE $keys[0] = '$prival')";
@@ -520,19 +563,19 @@ class DatabaseMssql extends DatabaseBase {
                        }
                        $allOk = false;
                }
+
                return $allOk;
        }
 
        /**
         * INSERT SELECT wrapper
         * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
-        * Source items may be literals rather than field names, but strings should be quoted with Database::addQuotes()
-        * $conds may be "*" to copy the whole table
-        * srcTable may be an array of tables.
+        * Source items may be literals rather than field names, but strings should
+        * be quoted with Database::addQuotes().
         * @param string $destTable
-        * @param array|string $srcTable
+        * @param array|string $srcTable May be an array of tables.
         * @param array $varMap
-        * @param array $conds
+        * @param array $conds May be "*" to copy the whole table.
         * @param string $fname
         * @param array $insertOptions
         * @param array $selectOptions
@@ -541,15 +584,25 @@ class DatabaseMssql extends DatabaseBase {
         */
        function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
                $insertOptions = array(), $selectOptions = array() ) {
-               $ret = parent::insertSelect( $destTable, $srcTable, $varMap, $conds, $fname, $insertOptions, $selectOptions );
+               $ret = parent::insertSelect(
+                       $destTable,
+                       $srcTable,
+                       $varMap,
+                       $conds,
+                       $fname,
+                       $insertOptions,
+                       $selectOptions
+               );
 
                if ( $ret === false ) {
                        throw new DBQueryError( $this, $this->getErrors(), $this->lastErrno(), /*$sql*/ '', $fname );
                } elseif ( $ret != null ) {
                        // remember number of rows affected
                        $this->mAffectedRows = sqlsrv_rows_affected( $ret );
+
                        return $ret;
                }
+
                return null;
        }
 
@@ -559,14 +612,19 @@ class DatabaseMssql extends DatabaseBase {
         */
        function nextSequenceValue( $seqName ) {
                if ( !$this->tableExists( 'sequence_' . $seqName ) ) {
-                       sqlsrv_query( $this->mConn, "CREATE TABLE [sequence_$seqName] (id INT NOT NULL IDENTITY PRIMARY KEY, junk varchar(10) NULL)" );
+                       sqlsrv_query(
+                               $this->mConn,
+                               "CREATE TABLE [sequence_$seqName] (id INT NOT NULL IDENTITY PRIMARY KEY, junk varchar(10) NULL)"
+                       );
                }
                sqlsrv_query( $this->mConn, "INSERT INTO [sequence_$seqName] (junk) VALUES ('')" );
                $ret = sqlsrv_query( $this->mConn, "SELECT TOP 1 id FROM [sequence_$seqName] ORDER BY id DESC" );
-               $row = sqlsrv_fetch_array( $ret, SQLSRV_FETCH_ASSOC );// KEEP ASSOC THERE, weird weird bug dealing with the return value if you don't
+               // KEEP ASSOC THERE, weird weird bug dealing with the return value if you don't
+               $row = sqlsrv_fetch_array( $ret, SQLSRV_FETCH_ASSOC );
 
                sqlsrv_free_stmt( $ret );
                $this->mInsertId = $row['id'];
+
                return $row['id'];
        }
 
@@ -579,6 +637,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( $ret !== false ) {
                        $row = sqlsrv_fetch_array( $ret );
                        sqlsrv_free_stmt( $ret );
+
                        return $row['id'];
                } else {
                        return $this->nextSequenceValue( $seqName );
@@ -596,6 +655,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( strtolower( $row['DATA_TYPE'] ) != 'text' ) {
                        $size = $row['CHARACTER_MAXIMUM_LENGTH'];
                }
+
                return $size;
        }
 
@@ -622,13 +682,16 @@ class DatabaseMssql extends DatabaseBase {
                                        ) as sub2
                                ) AS sub3
                                WHERE line3 BETWEEN ' . ( $offset + 1 ) . ' AND ' . ( $offset + $limit );
+
                        return $sql;
                }
        }
 
-       // If there is a limit clause, parse it, strip it, and pass the remaining sql through limitResult()
-       // with the appropriate parameters. Not the prettiest solution, but better than building a whole new parser.
-       // This exists becase there are still too many extensions that don't use dynamic sql generation.
+       // If there is a limit clause, parse it, strip it, and pass the remaining
+       // SQL through limitResult() with the appropriate parameters. Not the
+       // prettiest solution, but better than building a whole new parser. This
+       // exists becase there are still too many extensions that don't use dynamic
+       // sql generation.
        function LimitToTopN( $sql ) {
                // Matches: LIMIT {[offset,] row_count | row_count OFFSET offset}
                $pattern = '/\bLIMIT\s+((([0-9]+)\s*,\s*)?([0-9]+)(\s+OFFSET\s+([0-9]+))?)/i';
@@ -637,13 +700,15 @@ class DatabaseMssql extends DatabaseBase {
                        $row_count = $matches[4];
                        // offset = $matches[3] OR $matches[6]
                        $offset = $matches[3] or
-                               $offset = $matches[6] or
-                               $offset = false;
+                       $offset = $matches[6] or
+                       $offset = false;
 
                        // strip the matching LIMIT clause out
                        $sql = str_replace( $matches[0], '', $sql );
+
                        return $this->limitResult( $sql, $row_count, $offset );
                }
+
                return $sql;
        }
 
@@ -667,6 +732,7 @@ class DatabaseMssql extends DatabaseBase {
                if ( isset( $server_info['SQLServerVersion'] ) ) {
                        $version = $server_info['SQLServerVersion'];
                }
+
                return $version;
        }
 
@@ -675,6 +741,7 @@ class DatabaseMssql extends DatabaseBase {
                        WHERE table_type='BASE TABLE' AND table_name = '$table'" );
                if ( $res === false ) {
                        print "Error in tableExists query: " . $this->getErrors();
+
                        return false;
                }
                if ( sqlsrv_fetch( $res ) ) {
@@ -694,6 +761,7 @@ class DatabaseMssql extends DatabaseBase {
                        WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
                if ( $res === false ) {
                        print "Error in fieldExists query: " . $this->getErrors();
+
                        return false;
                }
                if ( sqlsrv_fetch( $res ) ) {
@@ -709,12 +777,14 @@ class DatabaseMssql extends DatabaseBase {
                        WHERE TABLE_NAME = '$table' AND COLUMN_NAME = '$field'" );
                if ( $res === false ) {
                        print "Error in fieldInfo query: " . $this->getErrors();
+
                        return false;
                }
                $meta = $this->fetchRow( $res );
                if ( $meta ) {
                        return new MssqlField( $meta );
                }
+
                return false;
        }
 
@@ -759,9 +829,11 @@ class DatabaseMssql extends DatabaseBase {
                        throw new MWException( "The identifier '$identifier' is too long (max. 128)" );
                }
                if ( ( strpos( $identifier, '[' ) !== false ) || ( strpos( $identifier, ']' ) !== false ) ) {
-                       // It may be allowed if you quoted with double quotation marks, but that would break if QUOTED_IDENTIFIER is OFF
+                       // It may be allowed if you quoted with double quotation marks, but
+                       // that would break if QUOTED_IDENTIFIER is OFF
                        throw new MWException( "You can't use square brackers in the identifier '$identifier'" );
                }
+
                return "[$identifier]";
        }
 
@@ -825,13 +897,13 @@ class DatabaseMssql extends DatabaseBase {
        }
 
        function encodeBlob( $b ) {
-       // we can't have zero's and such, this is a simple encoding to make sure we don't barf
+               // we can't have zero's and such, this is a simple encoding to make sure we don't barf
                return base64_encode( $b );
        }
 
        function decodeBlob( $b ) {
-       // we can't have zero's and such, this is a simple encoding to make sure we don't barf
-       return base64_decode( $b );
+               // we can't have zero's and such, this is a simple encoding to make sure we don't barf
+               return base64_decode( $b );
        }
 
        /**
@@ -868,6 +940,7 @@ class DatabaseMssql extends DatabaseBase {
                // We can't separate explicit JOIN clauses with ',', use ' ' for those
                $straightJoins = !empty( $ret ) ? implode( ',', $ret ) : "";
                $otherJoins = !empty( $retJOIN ) ? implode( ' ', $retJOIN ) : "";
+
                // Compile our final table clause
                return implode( ' ', array( $straightJoins, $otherJoins ) );
        }
@@ -951,7 +1024,6 @@ class DatabaseMssql extends DatabaseBase {
        public function getInfinity() {
                return '3000-01-31 00:00:00.000';
        }
-
 } // end DatabaseMssql class
 
 /**
@@ -961,6 +1033,7 @@ class DatabaseMssql extends DatabaseBase {
  */
 class MssqlField implements Field {
        private $name, $tablename, $default, $max_length, $nullable, $type;
+
        function __construct( $info ) {
                $this->name = $info['COLUMN_NAME'];
                $this->tablename = $info['TABLE_NAME'];
@@ -996,8 +1069,9 @@ class MssqlField implements Field {
 }
 
 /**
- * The MSSQL PHP driver doesn't support sqlsrv_num_rows, so we recall all rows into an array and maintain our
- * own cursor index into that array...This is similar to the way the Oracle driver handles this same issue
+ * The MSSQL PHP driver doesn't support sqlsrv_num_rows, so we recall all rows
+ * into an array and maintain our own cursor index into that array... This is
+ * similar to the way the Oracle driver handles this same issue
  *
  * @ingroup Database
  */
@@ -1014,11 +1088,11 @@ class MssqlResult {
                foreach ( $rows as $row ) {
                        if ( $row !== null ) {
                                foreach ( $row as $k => $v ) {
-                                       if ( is_object( $v ) && method_exists( $v, 'format' ) ) {// DateTime Object
+                                       if ( is_object( $v ) && method_exists( $v, 'format' ) ) { // DateTime Object
                                                $row[$k] = $v->format( "Y-m-d\TH:i:s\Z" );
                                        }
                                }
-                               $this->mRows[] = $row;// read results into memory, cursors are not supported
+                               $this->mRows[] = $row; // read results into memory, cursors are not supported
                        }
                }
                $this->mRowCount = count( $this->mRows );
@@ -1036,6 +1110,7 @@ class MssqlResult {
                                }
                        }
                }
+
                return $obj;
        }
 
@@ -1067,6 +1142,7 @@ class MssqlResult {
                }
 
                $this->mCursor++;
+
                return $ret;
        }
 
@@ -1088,6 +1164,7 @@ class MssqlResult {
 
        public function fieldname( $nr ) {
                $arrKeys = array_keys( $this->mRows[0] );
+
                return $arrKeys[$nr];
        }
 
@@ -1193,6 +1270,7 @@ class MssqlResult {
                        default:
                                $strType = $intType;
                }
+
                return $strType;
        }
 
index 956bb69..e253f91 100644 (file)
@@ -28,7 +28,6 @@
  * @see Database
  */
 class DatabaseMysql extends DatabaseMysqlBase {
-
        /**
         * @param $sql string
         * @return resource
@@ -39,6 +38,7 @@ class DatabaseMysql extends DatabaseMysqlBase {
                } else {
                        $ret = mysql_unbuffered_query( $sql, $this->mConn );
                }
+
                return $ret;
        }
 
@@ -46,7 +46,10 @@ class DatabaseMysql extends DatabaseMysqlBase {
                # Fail now
                # Otherwise we get a suppressed fatal error, which is very hard to track down
                if ( !extension_loaded( 'mysql' ) ) {
-                       throw new DBConnectionError( $this, "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
+                       throw new DBConnectionError(
+                               $this,
+                               "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n"
+                       );
                }
 
                $connFlags = 0;
@@ -80,6 +83,17 @@ class DatabaseMysql extends DatabaseMysqlBase {
                return $conn;
        }
 
+       /**
+        * @return bool
+        */
+       protected function mysqlSetCharset( $charset ) {
+               if ( function_exists( 'mysql_set_charset' ) ) {
+                       return mysql_set_charset( $charset, $this->mConn );
+               } else {
+                       return $this->query( 'SET NAMES ' . $charset, __METHOD__ );
+               }
+       }
+
        /**
         * @return bool
         */
@@ -118,6 +132,7 @@ class DatabaseMysql extends DatabaseMysqlBase {
         */
        function selectDB( $db ) {
                $this->mDBname = $db;
+
                return mysql_select_db( $db, $this->mConn );
        }
 
index 49579b6..61b9a17 100644 (file)
@@ -76,6 +76,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                } catch ( Exception $ex ) {
                        wfProfileOut( "dbconnect-$server" );
                        wfProfileOut( __METHOD__ );
+                       $this->restoreErrorHandler();
                        throw $ex;
                }
                $error = $this->restoreErrorHandler();
@@ -93,6 +94,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
 
                        wfProfileOut( __METHOD__ );
+
                        return $this->reportConnectionError( $error );
                }
 
@@ -106,6 +108,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                        "from client host " . wfHostname() . "\n" );
 
                                wfProfileOut( __METHOD__ );
+
                                return $this->reportConnectionError( "Error selecting database $dbName" );
                        }
                }
@@ -113,18 +116,25 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                // Tell the server we're communicating with it in UTF-8.
                // This may engage various charset conversions.
                if ( $wgDBmysql5 ) {
-                       $this->query( 'SET NAMES utf8', __METHOD__ );
+                       $this->mysqlSetCharset( 'utf8' );
                } else {
-                       $this->query( 'SET NAMES binary', __METHOD__ );
+                       $this->mysqlSetCharset( 'binary' );
                }
                // Set SQL mode, default is turning them all off, can be overridden or skipped with null
                if ( is_string( $wgSQLMode ) ) {
                        $mode = $this->addQuotes( $wgSQLMode );
-                       $this->query( "SET sql_mode = $mode", __METHOD__ );
+                       // Use doQuery() to avoid opening implicit transactions (DBO_TRX)
+                       $success = $this->doQuery( "SET sql_mode = $mode", __METHOD__ );
+                       if ( !$success ) {
+                               wfLogDBError( "Error setting sql_mode to $mode on server {$this->mServer}" );
+                               wfProfileOut( __METHOD__ );
+                               return $this->reportConnectionError( "Error setting sql_mode to $mode" );
+                       }
                }
 
                $this->mOpened = true;
                wfProfileOut( __METHOD__ );
+
                return true;
        }
 
@@ -137,6 +147,14 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        abstract protected function mysqlConnect( $realServer );
 
+       /**
+        * Set the character set of the MySQL link
+        *
+        * @param string $charset
+        * @return bool
+        */
+       abstract protected function mysqlSetCharset( $charset );
+
        /**
         * @param $res ResultWrapper
         * @throws DBUnexpectedError
@@ -180,8 +198,12 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                // these are the only errors mysql_fetch_object can cause.
                // See http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html.
                if ( $errno == 2000 || $errno == 2013 ) {
-                       throw new DBUnexpectedError( $this, 'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() ) );
+                       throw new DBUnexpectedError(
+                               $this,
+                               'Error in fetchObject(): ' . htmlspecialchars( $this->lastError() )
+                       );
                }
+
                return $row;
        }
 
@@ -212,8 +234,12 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                // these are the only errors mysql_fetch_array can cause.
                // See http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-row.html.
                if ( $errno == 2000 || $errno == 2013 ) {
-                       throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) );
+                       throw new DBUnexpectedError(
+                               $this,
+                               'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() )
+                       );
                }
+
                return $row;
        }
 
@@ -237,6 +263,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                wfSuppressWarnings();
                $n = $this->mysqlNumRows( $res );
                wfRestoreWarnings();
+
                // Unfortunately, mysql_num_rows does not reset the last errno.
                // We are not checking for any errors here, since
                // these are no errors mysql_num_rows can cause.
@@ -261,6 +288,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return $this->mysqlNumFields( $res );
        }
 
@@ -281,6 +309,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return $this->mysqlFieldName( $res, $n );
        }
 
@@ -302,6 +331,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return $this->mysqlDataSeek( $res, $row );
        }
 
@@ -332,6 +362,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( $error ) {
                        $error .= ' (' . $this->mServer . ')';
                }
+
                return $error;
        }
 
@@ -366,7 +397,9 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         * @param $options string|array
         * @return int
         */
-       public function estimateRowCount( $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array() ) {
+       public function estimateRowCount( $table, $vars = '*', $conds = '',
+               $fname = __METHOD__, $options = array()
+       ) {
                $options['EXPLAIN'] = true;
                $res = $this->select( $table, $vars, $conds, $fname, $options );
                if ( $res === false ) {
@@ -380,6 +413,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                foreach ( $res as $plan ) {
                        $rows *= $plan->rows > 0 ? $plan->rows : 1; // avoid resetting to zero
                }
+
                return $rows;
        }
 
@@ -401,6 +435,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                return new MySQLField( $meta );
                        }
                }
+
                return false;
        }
 
@@ -443,6 +478,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                $result[] = $row;
                        }
                }
+
                return empty( $result ) ? false : $result;
        }
 
@@ -458,6 +494,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        $this->ping();
                        $sQuoted = $this->mysqlRealEscapeString( $s );
                }
+
                return $sQuoted;
        }
 
@@ -471,7 +508,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        public function addIdentifierQuotes( $s ) {
                // Characters in the range \u0001-\uFFFF are valid in a quoted identifier
                // Remove NUL bytes and escape backticks by doubling
-               return '`' . str_replace( array( "\0", '`' ), array( '', '``' ), $s )  . '`';
+               return '`' . str_replace( array( "\0", '`' ), array( '', '``' ), $s ) . '`';
        }
 
        /**
@@ -495,6 +532,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $this->mOpened = false;
                $this->mConn = false;
                $this->open( $this->mServer, $this->mUser, $this->mPassword, $this->mDBname );
+
                return true;
        }
 
@@ -515,6 +553,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        function getLag() {
                if ( !is_null( $this->mFakeSlaveLag ) ) {
                        wfDebug( "getLag: fake slave lagged {$this->mFakeSlaveLag} seconds\n" );
+
                        return $this->mFakeSlaveLag;
                }
 
@@ -568,7 +607,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                $row->State != 'Waiting to reconnect after a failed master event read' &&
                                $row->State != 'Reconnecting after a failed master event read' &&
                                $row->State != 'Registering slave on master'
-                               ) {
+                       ) {
                                # This is it, return the time (except -ve)
                                if ( $row->Time > 0x7fffffff ) {
                                        return false;
@@ -577,6 +616,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                }
                        }
                }
+
                return false;
        }
 
@@ -600,6 +640,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( !is_null( $this->mFakeSlaveLag ) ) {
                        $status = parent::masterPosWait( $pos, $timeout );
                        wfProfileOut( __METHOD__ );
+
                        return $status;
                }
 
@@ -618,6 +659,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $status;
        }
 
@@ -635,7 +677,10 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $row = $this->fetchObject( $res );
 
                if ( $row ) {
-                       $pos = isset( $row->Exec_master_log_pos ) ? $row->Exec_master_log_pos : $row->Exec_Master_Log_Pos;
+                       $pos = isset( $row->Exec_master_log_pos )
+                               ? $row->Exec_master_log_pos
+                               : $row->Exec_Master_Log_Pos;
+
                        return new MySQLMasterPos( $row->Relay_Master_Log_File, $pos );
                } else {
                        return false;
@@ -701,6 +746,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        $this->delimiter = $m[1];
                        $newLine = '';
                }
+
                return parent::streamStatementEnd( $sql, $newLine );
        }
 
@@ -716,6 +762,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $lockName = $this->addQuotes( $lockName );
                $result = $this->query( "SELECT IS_FREE_LOCK($lockName) AS lockstatus", $method );
                $row = $this->fetchObject( $result );
+
                return ( $row->lockstatus == 1 );
        }
 
@@ -734,12 +781,14 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        return true;
                } else {
                        wfDebug( __METHOD__ . " failed to acquire lock\n" );
+
                        return false;
                }
        }
 
        /**
-        * FROM MYSQL DOCS: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock
+        * FROM MYSQL DOCS:
+        * http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_release-lock
         * @param $lockName string
         * @param $method string
         * @return bool
@@ -748,6 +797,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $lockName = $this->addQuotes( $lockName );
                $result = $this->query( "SELECT RELEASE_LOCK($lockName) as lockstatus", $method );
                $row = $this->fetchObject( $result );
+
                return ( $row->lockstatus == 1 );
        }
 
@@ -763,8 +813,8 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
                foreach ( $write as $table ) {
                        $tbl = $this->tableName( $table ) .
-                                       ( $lowPriority ? ' LOW_PRIORITY' : '' ) .
-                                       ' WRITE';
+                               ( $lowPriority ? ' LOW_PRIORITY' : '' ) .
+                               ' WRITE';
                        $items[] = $tbl;
                }
                foreach ( $read as $table ) {
@@ -772,6 +822,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                }
                $sql = "LOCK TABLES " . implode( ',', $items );
                $this->query( $sql, $method );
+
                return true;
        }
 
@@ -781,6 +832,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        public function unlockTables( $method ) {
                $this->query( "UNLOCK TABLES", $method );
+
                return true;
        }
 
@@ -878,6 +930,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        function getServerUptime() {
                $vars = $this->getMysqlStatus( 'Uptime' );
+
                return (int)$vars['Uptime'];
        }
 
@@ -966,6 +1019,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                if ( !$this->tableExists( $tableName, $fName ) ) {
                        return false;
                }
+
                return $this->query( "DROP TABLE IF EXISTS " . $this->tableName( $tableName ), $fName );
        }
 
@@ -975,7 +1029,12 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        protected function getDefaultSchemaVars() {
                $vars = parent::getDefaultSchemaVars();
                $vars['wgDBTableOptions'] = str_replace( 'TYPE', 'ENGINE', $GLOBALS['wgDBTableOptions'] );
-               $vars['wgDBTableOptions'] = str_replace( 'CHARSET=mysql4', 'CHARSET=binary', $vars['wgDBTableOptions'] );
+               $vars['wgDBTableOptions'] = str_replace(
+                       'CHARSET=mysql4',
+                       'CHARSET=binary',
+                       $vars['wgDBTableOptions']
+               );
+
                return $vars;
        }
 
@@ -996,9 +1055,56 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                return $status;
        }
 
-}
+       /**
+        * Lists VIEWs in the database
+        *
+        * @param string $prefix Only show VIEWs with this prefix, eg.
+        * unit_test_, or $wgDBprefix. Default: null, would return all views.
+        * @param string $fname Name of calling function
+        * @return array
+        * @since 1.22
+        */
+       public function listViews( $prefix = null, $fname = __METHOD__ ) {
 
+               if ( !isset( $this->allViews ) ) {
 
+                       // The name of the column containing the name of the VIEW
+                       $propertyName = 'Tables_in_' . $this->mDBname;
+
+                       // Query for the VIEWS
+                       $result = $this->query( 'SHOW FULL TABLES WHERE TABLE_TYPE = "VIEW"' );
+                       $this->allViews = array();
+                       while ( ( $row = $this->fetchRow( $result ) ) !== false ) {
+                               array_push( $this->allViews, $row[$propertyName] );
+                       }
+               }
+
+               if ( is_null( $prefix ) || $prefix === '' ) {
+                       return $this->allViews;
+               }
+
+               $filteredViews = array();
+               foreach ( $this->allViews as $viewName ) {
+                       // Does the name of this VIEW start with the table-prefix?
+                       if ( strpos( $viewName, $prefix ) === 0 ) {
+                               array_push( $filteredViews, $viewName );
+                       }
+               }
+
+               return $filteredViews;
+       }
+
+       /**
+        * Differentiates between a TABLE and a VIEW.
+        *
+        * @param $name string: Name of the TABLE/VIEW to test
+        * @return bool
+        * @since 1.22
+        */
+       public function isView( $name, $prefix = null ) {
+               return in_array( $name, $this->listViews( $prefix ) );
+       }
+}
 
 /**
  * Utility class.
@@ -1094,12 +1200,14 @@ class MySQLMasterPos implements DBMasterPos {
                if ( preg_match( '!\.(\d+)/(\d+)$!', (string)$this, $m ) ) {
                        return array( (int)$m[1], (int)$m[2] );
                }
+
                return false;
        }
 
        function hasReached( MySQLMasterPos $pos ) {
                $thisPos = $this->getCoordinates();
                $thatPos = $pos->getCoordinates();
+
                return ( $thisPos && $thatPos && $thisPos >= $thatPos );
        }
 }
index 7761abe..9f18da3 100644 (file)
@@ -29,7 +29,6 @@
  * @see Database
  */
 class DatabaseMysqli extends DatabaseMysqlBase {
-
        /**
         * @param $sql string
         * @return resource
@@ -40,6 +39,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                } else {
                        $ret = $this->mConn->query( $sql, MYSQLI_USE_RESULT );
                }
+
                return $ret;
        }
 
@@ -70,8 +70,8 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                                usleep( 1000 );
                        }
                        if ( $mysqli->real_connect( $realServer, $this->mUser,
-                               $this->mPassword, $this->mDBname, null, null, $connFlags ) )
-                       {
+                               $this->mPassword, $this->mDBname, null, null, $connFlags )
+                       {
                                return $mysqli;
                        }
                }
@@ -79,6 +79,17 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                return false;
        }
 
+       /**
+        * @return bool
+        */
+       protected function mysqlSetCharset( $charset ) {
+               if ( method_exists( $this->mConn, 'set_charset' ) ) {
+                       return $this->mConn->set_charset( $charset );
+               } else {
+                       return $this->query( 'SET NAMES ' . $charset, __METHOD__ );
+               }
+       }
+
        /**
         * @return bool
         */
@@ -117,6 +128,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
         */
        function selectDB( $db ) {
                $this->mDBname = $db;
+
                return $this->mConn->select_db( $db );
        }
 
@@ -129,6 +141,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
 
        protected function mysqlFreeResult( $res ) {
                $res->free_result();
+
                return true;
        }
 
@@ -137,6 +150,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                if ( $object === null ) {
                        return false;
                }
+
                return $object;
        }
 
@@ -145,6 +159,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                if ( $array === null ) {
                        return false;
                }
+
                return $array;
        }
 
@@ -163,11 +178,13 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                $field->unique_key = $field->flags & MYSQLI_UNIQUE_KEY_FLAG;
                $field->multiple_key = $field->flags & MYSQLI_MULTIPLE_KEY_FLAG;
                $field->binary = $field->flags & MYSQLI_BINARY_FLAG;
+
                return $field;
        }
 
        protected function mysqlFieldName( $res, $n ) {
                $field = $res->fetch_field_direct( $n );
+
                return $field->name;
        }
 
@@ -176,7 +193,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        }
 
        protected function mysqlError( $conn = null ) {
-               if ($conn === null) {
+               if ( $conn === null ) {
                        return mysqli_connect_error();
                } else {
                        return $conn->error;
@@ -190,5 +207,4 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        protected function mysqlPing() {
                return $this->mConn->ping();
        }
-
 }
index fbaa4da..10715e4 100644 (file)
@@ -57,10 +57,12 @@ class ORAResult {
        function __construct( &$db, $stmt, $unique = false ) {
                $this->db =& $db;
 
-               if ( ( $this->nrows = oci_fetch_all( $stmt, $this->rows, 0, - 1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM ) ) === false ) {
+               $this->nrows = oci_fetch_all( $stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM );
+               if ( $this->nrows === false ) {
                        $e = oci_error( $stmt );
                        $db->reportQueryError( $e['message'], $e['code'], '', __METHOD__ );
                        $this->free();
+
                        return;
                }
 
@@ -121,6 +123,7 @@ class ORAResult {
                        $ret[$lc] = $v;
                        $ret[$k] = $v;
                }
+
                return $ret;
        }
 }
@@ -196,12 +199,27 @@ class DatabaseOracle extends DatabaseBase {
 
        var $mFieldInfoCache = array();
 
-       function __construct( $server = false, $user = false, $password = false, $dbName = false,
-               $flags = 0, $tablePrefix = 'get from global' )
-       {
+       function __construct( $p = null ) {
                global $wgDBprefix;
-               $tablePrefix = $tablePrefix == 'get from global' ? strtoupper( $wgDBprefix ) : strtoupper( $tablePrefix );
-               parent::__construct( $server, $user, $password, $dbName, $flags, $tablePrefix );
+
+               if ( !is_array( $p ) ) { // legacy calling pattern
+                       wfDeprecated( __METHOD__ . " method called without parameter array.", "1.22" );
+                       $args = func_get_args();
+                       $p = array(
+                               'host' => isset( $args[0] ) ? $args[0] : false,
+                               'user' => isset( $args[1] ) ? $args[1] : false,
+                               'password' => isset( $args[2] ) ? $args[2] : false,
+                               'dbname' => isset( $args[3] ) ? $args[3] : false,
+                               'flags' => isset( $args[4] ) ? $args[4] : 0,
+                               'tablePrefix' => isset( $args[5] ) ? $args[5] : 'get from global',
+                               'foreign' => isset( $args[6] ) ? $args[6] : false
+                       );
+               }
+               if ( $p['tablePrefix'] == 'get from global' ) {
+                       $p['tablePrefix'] = $wgDBprefix;
+               }
+               $p['tablePrefix'] = strtoupper( $p['tablePrefix'] );
+               parent::__construct( $p );
                wfRunHooks( 'DatabaseOraclePostInit', array( $this ) );
        }
 
@@ -220,21 +238,27 @@ class DatabaseOracle extends DatabaseBase {
        function cascadingDeletes() {
                return true;
        }
+
        function cleanupTriggers() {
                return true;
        }
+
        function strictIPs() {
                return true;
        }
+
        function realTimestamps() {
                return true;
        }
+
        function implicitGroupby() {
                return false;
        }
+
        function implicitOrderby() {
                return false;
        }
+
        function searchableIPs() {
                return true;
        }
@@ -251,7 +275,11 @@ class DatabaseOracle extends DatabaseBase {
        function open( $server, $user, $password, $dbName ) {
                global $wgDBOracleDRCP;
                if ( !function_exists( 'oci_connect' ) ) {
-                       throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" );
+                       throw new DBConnectionError(
+                               $this,
+                               "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n " .
+                                       "(Note: if you recently installed PHP, you may need to restart your webserver\n " .
+                                       "and database)\n" );
                }
 
                $this->close();
@@ -285,11 +313,29 @@ class DatabaseOracle extends DatabaseBase {
 
                wfSuppressWarnings();
                if ( $this->mFlags & DBO_PERSISTENT ) {
-                       $this->mConn = oci_pconnect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode );
+                       $this->mConn = oci_pconnect(
+                               $this->mUser,
+                               $this->mPassword,
+                               $this->mServer,
+                               $this->defaultCharset,
+                               $session_mode
+                       );
                } elseif ( $this->mFlags & DBO_DEFAULT ) {
-                       $this->mConn = oci_new_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode );
+                       $this->mConn = oci_new_connect(
+                               $this->mUser,
+                               $this->mPassword,
+                               $this->mServer,
+                               $this->defaultCharset,
+                               $session_mode
+                       );
                } else {
-                       $this->mConn = oci_connect( $this->mUser, $this->mPassword, $this->mServer, $this->defaultCharset, $session_mode );
+                       $this->mConn = oci_connect(
+                               $this->mUser,
+                               $this->mPassword,
+                               $this->mServer,
+                               $this->defaultCharset,
+                               $session_mode
+                       );
                }
                wfRestoreWarnings();
 
@@ -308,6 +354,7 @@ class DatabaseOracle extends DatabaseBase {
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\'' );
                $this->doQuery( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=\'.,\'' );
+
                return $this->mConn;
        }
 
@@ -343,13 +390,20 @@ class DatabaseOracle extends DatabaseBase {
                // you have to select data from plan table after explain
                $explain_id = MWTimestamp::getLocalInstance()->format( 'dmYHis' );
 
-               $sql = preg_replace( '/^EXPLAIN /', 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR', $sql, 1, $explain_count );
+               $sql = preg_replace(
+                       '/^EXPLAIN /',
+                       'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR',
+                       $sql,
+                       1,
+                       $explain_count
+               );
 
                wfSuppressWarnings();
 
                if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
                        $e = oci_error( $this->mConn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                        return false;
                }
 
@@ -357,6 +411,7 @@ class DatabaseOracle extends DatabaseBase {
                        $e = oci_error( $stmt );
                        if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
                                $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                                return false;
                        }
                }
@@ -364,11 +419,13 @@ class DatabaseOracle extends DatabaseBase {
                wfRestoreWarnings();
 
                if ( $explain_count > 0 ) {
-                       return $this->doQuery( 'SELECT id, cardinality "ROWS" FROM plan_table WHERE statement_id = \'' . $explain_id . '\'' );
+                       return $this->doQuery( 'SELECT id, cardinality "ROWS" FROM plan_table ' .
+                               'WHERE statement_id = \'' . $explain_id . '\'' );
                } elseif ( oci_statement_type( $stmt ) == 'SELECT' ) {
                        return new ORAResult( $this, $stmt, $union_unique );
                } else {
                        $this->mAffectedRows = oci_num_rows( $stmt );
+
                        return true;
                }
        }
@@ -443,6 +500,7 @@ class DatabaseOracle extends DatabaseBase {
                } else {
                        $e = oci_error( $this->mConn );
                }
+
                return $e['message'];
        }
 
@@ -452,6 +510,7 @@ class DatabaseOracle extends DatabaseBase {
                } else {
                        $e = oci_error( $this->mConn );
                }
+
                return $e['code'];
        }
 
@@ -509,6 +568,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( is_numeric( $col ) ) {
                        $bind = $val;
                        $val = null;
+
                        return $bind;
                } elseif ( $includeCol ) {
                        $bind = "$col = ";
@@ -559,6 +619,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
                        $e = oci_error( $this->mConn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                        return false;
                }
                foreach ( $row as $col => &$val ) {
@@ -581,6 +642,7 @@ class DatabaseOracle extends DatabaseBase {
                                if ( oci_bind_by_name( $stmt, ":$col", $val, -1, SQLT_CHR ) === false ) {
                                        $e = oci_error( $stmt );
                                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                                        return false;
                                }
                        } else {
@@ -595,10 +657,10 @@ class DatabaseOracle extends DatabaseBase {
 
                                if ( $col_type == 'BLOB' ) {
                                        $lob[$col]->writeTemporary( $val, OCI_TEMP_BLOB );
-                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_BLOB );
+                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_BLOB );
                                } else {
                                        $lob[$col]->writeTemporary( $val, OCI_TEMP_CLOB );
-                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_CLOB );
+                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_CLOB );
                                }
                        }
                }
@@ -609,6 +671,7 @@ class DatabaseOracle extends DatabaseBase {
                        $e = oci_error( $stmt );
                        if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
                                $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                                return false;
                        } else {
                                $this->mAffectedRows = oci_num_rows( $stmt );
@@ -633,8 +696,8 @@ class DatabaseOracle extends DatabaseBase {
        }
 
        function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
-               $insertOptions = array(), $selectOptions = array() )
-       {
+               $insertOptions = array(), $selectOptions = array()
+       {
                $destTable = $this->tableName( $destTable );
                if ( !is_array( $selectOptions ) ) {
                        $selectOptions = array( $selectOptions );
@@ -647,8 +710,8 @@ class DatabaseOracle extends DatabaseBase {
                }
 
                if ( ( $sequenceData = $this->getSequenceData( $destTable ) ) !== false &&
-                               !isset( $varMap[$sequenceData['column']] ) )
-               {
+                       !isset( $varMap[$sequenceData['column']] )
+               {
                        $varMap[$sequenceData['column']] = 'GET_SEQUENCE_VALUE(\'' . $sequenceData['sequence'] . '\')';
                }
 
@@ -699,8 +762,10 @@ class DatabaseOracle extends DatabaseBase {
 
        function tableNameInternal( $name ) {
                $name = $this->tableName( $name );
+
                return preg_replace( '/.*\.(.*)/', '$1', $name );
        }
+
        /**
         * Return the next in a sequence, save the value for retrieval via insertId()
         * @return null
@@ -709,6 +774,7 @@ class DatabaseOracle extends DatabaseBase {
                $res = $this->query( "SELECT $seqName.nextval FROM dual" );
                $row = $this->fetchRow( $res );
                $this->mInsertId = $row[0];
+
                return $this->mInsertId;
        }
 
@@ -719,13 +785,18 @@ class DatabaseOracle extends DatabaseBase {
        private function getSequenceData( $table ) {
                if ( $this->sequenceData == null ) {
                        $result = $this->doQuery( "SELECT lower(asq.sequence_name),
-                                  lower(atc.table_name),
-                                  lower(atc.column_name)
-                         FROM all_sequences asq, all_tab_columns atc
-                        WHERE decode(atc.table_name, '{$this->mTablePrefix}MWUSER', '{$this->mTablePrefix}USER', atc.table_name) || '_' ||
-                                  atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
-                          AND asq.sequence_owner = upper('{$this->mDBname}')
-                          AND atc.owner = upper('{$this->mDBname}')" );
+                               lower(atc.table_name),
+                               lower(atc.column_name)
+                       FROM all_sequences asq, all_tab_columns atc
+                       WHERE decode(
+                                       atc.table_name,
+                                       '{$this->mTablePrefix}MWUSER',
+                                       '{$this->mTablePrefix}USER',
+                                       atc.table_name
+                               ) || '_' ||
+                               atc.column_name || '_SEQ' = '{$this->mTablePrefix}' || asq.sequence_name
+                               AND asq.sequence_owner = upper('{$this->mDBname}')
+                               AND atc.owner = upper('{$this->mDBname}')" );
 
                        while ( ( $row = $result->fetchRow() ) !== false ) {
                                $this->sequenceData[$row[1]] = array(
@@ -735,12 +806,14 @@ class DatabaseOracle extends DatabaseBase {
                        }
                }
                $table = strtolower( $this->removeIdentifierQuotes( $this->tableName( $table ) ) );
+
                return ( isset( $this->sequenceData[$table] ) ) ? $this->sequenceData[$table] : false;
        }
 
        # Returns the size of a text field, or -1 for "unlimited"
        function textFieldSize( $table, $field ) {
                $fieldInfoData = $this->fieldInfo( $table, $field );
+
                return $fieldInfoData->maxLength();
        }
 
@@ -748,6 +821,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( $offset === false ) {
                        $offset = 0;
                }
+
                return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < (1 + $limit + $offset)";
        }
 
@@ -759,19 +833,24 @@ class DatabaseOracle extends DatabaseBase {
                if ( $b instanceof Blob ) {
                        $b = $b->fetch();
                }
+
                return $b;
        }
 
        function unionQueries( $sqls, $all ) {
                $glue = ' UNION ALL ';
-               return 'SELECT * ' . ( $all ? '' : '/* UNION_UNIQUE */ ' ) . 'FROM (' . implode( $glue, $sqls ) . ')';
+
+               return 'SELECT * ' . ( $all ? '' : '/* UNION_UNIQUE */ ' ) .
+                       'FROM (' . implode( $glue, $sqls ) . ')';
        }
 
        function wasDeadlock() {
                return $this->lastErrno() == 'OCI-00060';
        }
 
-       function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = __METHOD__ ) {
+       function duplicateTableStructure( $oldName, $newName, $temporary = false,
+               $fname = __METHOD__
+       ) {
                $temporary = $temporary ? 'TRUE' : 'FALSE';
 
                $newName = strtoupper( $newName );
@@ -781,7 +860,8 @@ class DatabaseOracle extends DatabaseBase {
                $oldPrefix = substr( $oldName, 0, strlen( $oldName ) - strlen( $tabName ) );
                $newPrefix = strtoupper( $this->mTablePrefix );
 
-               return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', '$oldPrefix', '$newPrefix', $temporary ); END;" );
+               return $this->doQuery( "BEGIN DUPLICATE_TABLE( '$tabName', " .
+                       "'$oldPrefix', '$newPrefix', $temporary ); END;" );
        }
 
        function listTables( $prefix = null, $fname = __METHOD__ ) {
@@ -791,7 +871,8 @@ class DatabaseOracle extends DatabaseBase {
                }
 
                $owner = strtoupper( $this->mDBname );
-               $result = $this->doQuery( "SELECT table_name FROM all_tables WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
+               $result = $this->doQuery( "SELECT table_name FROM all_tables " .
+                       "WHERE owner='$owner' AND table_name NOT LIKE '%!_IDX\$_' ESCAPE '!' $listWhere" );
 
                // dirty code ... i know
                $endArray = array();
@@ -854,10 +935,14 @@ class DatabaseOracle extends DatabaseBase {
         */
        function getServerVersion() {
                //better version number, fallback on driver
-               $rset = $this->doQuery( 'SELECT version FROM product_component_version WHERE UPPER(product) LIKE \'ORACLE DATABASE%\'' );
+               $rset = $this->doQuery(
+                       'SELECT version FROM product_component_version ' .
+                               'WHERE UPPER(product) LIKE \'ORACLE DATABASE%\''
+               );
                if ( !( $row = $rset->fetchRow() ) ) {
                        return oci_server_version( $this->mConn );
                }
+
                return $row['version'];
        }
 
@@ -878,6 +963,7 @@ class DatabaseOracle extends DatabaseBase {
                } else {
                        $count = 0;
                }
+
                return $count != 0;
        }
 
@@ -898,6 +984,7 @@ class DatabaseOracle extends DatabaseBase {
                }
 
                $res->free();
+
                return $exists;
        }
 
@@ -932,10 +1019,15 @@ class DatabaseOracle extends DatabaseBase {
                        $tableWhere = '= \'' . $table . '\'';
                }
 
-               $fieldInfoStmt = oci_parse( $this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name ' . $tableWhere . ' and column_name = \'' . $field . '\'' );
+               $fieldInfoStmt = oci_parse(
+                       $this->mConn,
+                       'SELECT * FROM wiki_field_info_full WHERE table_name ' .
+                               $tableWhere . ' and column_name = \'' . $field . '\''
+               );
                if ( oci_execute( $fieldInfoStmt, $this->execFlags() ) === false ) {
                        $e = oci_error( $fieldInfoStmt );
                        $this->reportQueryError( $e['message'], $e['code'], 'fieldInfo QUERY', __METHOD__ );
+
                        return false;
                }
                $res = new ORAResult( $this, $fieldInfoStmt );
@@ -954,6 +1046,7 @@ class DatabaseOracle extends DatabaseBase {
                        $this->mFieldInfoCache["$table.$field"] = $fieldInfoTemp;
                }
                $res->free();
+
                return $fieldInfoTemp;
        }
 
@@ -967,6 +1060,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( is_array( $table ) ) {
                        throw new DBUnexpectedError( $this, 'DatabaseOracle::fieldInfo called with table array!' );
                }
+
                return $this->fieldInfoMulti( $table, $field );
        }
 
@@ -1003,7 +1097,7 @@ class DatabaseOracle extends DatabaseBase {
 
                $replacements = array();
 
-               while ( ! feof( $fp ) ) {
+               while ( !feof( $fp ) ) {
                        if ( $lineCallback ) {
                                call_user_func( $lineCallback );
                        }
@@ -1013,7 +1107,7 @@ class DatabaseOracle extends DatabaseBase {
                        if ( $sl < 0 ) {
                                continue;
                        }
-                       if ( '-' == $line { 0 } && '-' == $line { 1 } ) {
+                       if ( '-' == $line[0] && '-' == $line[1] ) {
                                continue;
                        }
 
@@ -1027,7 +1121,7 @@ class DatabaseOracle extends DatabaseBase {
                                        $dollarquote = true;
                                }
                        } elseif ( !$dollarquote ) {
-                               if ( ';' == $line { $sl } && ( $sl < 2 || ';' != $line { $sl - 1 } ) ) {
+                               if ( ';' == $line[$sl] && ( $sl < 2 || ';' != $line[$sl - 1] ) ) {
                                        $done = true;
                                        $line = substr( $line, 0, $sl );
                                }
@@ -1060,6 +1154,7 @@ class DatabaseOracle extends DatabaseBase {
 
                                        if ( false === $res ) {
                                                $err = $this->lastError();
+
                                                return "Query \"{$cmd}\" failed with error code \"$err\".\n";
                                        }
                                }
@@ -1068,6 +1163,7 @@ class DatabaseOracle extends DatabaseBase {
                                $done = false;
                        }
                }
+
                return true;
        }
 
@@ -1086,8 +1182,10 @@ class DatabaseOracle extends DatabaseBase {
                        if ( $e['code'] != '1435' ) {
                                $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
                        }
+
                        return false;
                }
+
                return true;
        }
 
@@ -1100,6 +1198,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( isset( $wgContLang->mLoaded ) && $wgContLang->mLoaded ) {
                        $s = $wgContLang->checkTitleEncoding( $s );
                }
+
                return "'" . $this->strencode( $s ) . "'";
        }
 
@@ -1107,6 +1206,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( !$this->getFlag( DBO_DDLMODE ) ) {
                        $s = '/*Q*/' . $s;
                }
+
                return $s;
        }
 
@@ -1145,13 +1245,17 @@ class DatabaseOracle extends DatabaseBase {
                                $conds2[$col] = $val;
                        }
                }
+
                return $conds2;
        }
 
-       function selectRow( $table, $vars, $conds, $fname = __METHOD__, $options = array(), $join_conds = array() ) {
+       function selectRow( $table, $vars, $conds, $fname = __METHOD__,
+               $options = array(), $join_conds = array()
+       ) {
                if ( is_array( $conds ) ) {
                        $conds = $this->wrapConditionsForWhere( $table, $conds );
                }
+
                return parent::selectRow( $table, $vars, $conds, $fname, $options, $join_conds );
        }
 
@@ -1188,7 +1292,7 @@ class DatabaseOracle extends DatabaseBase {
                        $startOpts .= 'DISTINCT';
                }
 
-               if ( isset( $options['USE INDEX'] ) && ! is_array( $options['USE INDEX'] ) ) {
+               if ( isset( $options['USE INDEX'] ) && !is_array( $options['USE INDEX'] ) ) {
                        $useIndex = $this->useIndexClause( $options['USE INDEX'] );
                } else {
                        $useIndex = '';
@@ -1205,18 +1309,29 @@ class DatabaseOracle extends DatabaseBase {
                // all deletions on these tables have transactions so final failure rollbacks these updates
                $table = $this->tableName( $table );
                if ( $table == $this->tableName( 'user' ) ) {
-                               $this->update( 'archive', array( 'ar_user' => 0 ), array( 'ar_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'ipblocks', array( 'ipb_user' => 0 ), array( 'ipb_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'image', array( 'img_user' => 0 ), array( 'img_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'oldimage', array( 'oi_user' => 0 ), array( 'oi_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'filearchive', array( 'fa_deleted_user' => 0 ), array( 'fa_deleted_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'filearchive', array( 'fa_user' => 0 ), array( 'fa_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'uploadstash', array( 'us_user' => 0 ), array( 'us_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'recentchanges', array( 'rc_user' => 0 ), array( 'rc_user' => $conds['user_id'] ), $fname );
-                               $this->update( 'logging', array( 'log_user' => 0 ), array( 'log_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'archive', array( 'ar_user' => 0 ),
+                               array( 'ar_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'ipblocks', array( 'ipb_user' => 0 ),
+                               array( 'ipb_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'image', array( 'img_user' => 0 ),
+                               array( 'img_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'oldimage', array( 'oi_user' => 0 ),
+                               array( 'oi_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'filearchive', array( 'fa_deleted_user' => 0 ),
+                               array( 'fa_deleted_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'filearchive', array( 'fa_user' => 0 ),
+                               array( 'fa_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'uploadstash', array( 'us_user' => 0 ),
+                               array( 'us_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'recentchanges', array( 'rc_user' => 0 ),
+                               array( 'rc_user' => $conds['user_id'] ), $fname );
+                       $this->update( 'logging', array( 'log_user' => 0 ),
+                               array( 'log_user' => $conds['user_id'] ), $fname );
                } elseif ( $table == $this->tableName( 'image' ) ) {
-                               $this->update( 'oldimage', array( 'oi_name' => 0 ), array( 'oi_name' => $conds['img_name'] ), $fname );
+                       $this->update( 'oldimage', array( 'oi_name' => 0 ),
+                               array( 'oi_name' => $conds['img_name'] ), $fname );
                }
+
                return parent::delete( $table, $conds, $fname );
        }
 
@@ -1247,6 +1362,7 @@ class DatabaseOracle extends DatabaseBase {
                if ( ( $this->mLastResult = $stmt = oci_parse( $this->mConn, $sql ) ) === false ) {
                        $e = oci_error( $this->mConn );
                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                        return false;
                }
                foreach ( $values as $col => &$val ) {
@@ -1268,6 +1384,7 @@ class DatabaseOracle extends DatabaseBase {
                                if ( oci_bind_by_name( $stmt, ":$col", $val ) === false ) {
                                        $e = oci_error( $stmt );
                                        $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                                        return false;
                                }
                        } else {
@@ -1278,10 +1395,10 @@ class DatabaseOracle extends DatabaseBase {
 
                                if ( $col_type == 'BLOB' ) {
                                        $lob[$col]->writeTemporary( $val );
-                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, SQLT_BLOB );
+                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, SQLT_BLOB );
                                } else {
                                        $lob[$col]->writeTemporary( $val );
-                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], - 1, OCI_B_CLOB );
+                                       oci_bind_by_name( $stmt, ":$col", $lob[$col], -1, OCI_B_CLOB );
                                }
                        }
                }
@@ -1292,6 +1409,7 @@ class DatabaseOracle extends DatabaseBase {
                        $e = oci_error( $stmt );
                        if ( !$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1' ) {
                                $this->reportQueryError( $e['message'], $e['code'], $sql, __METHOD__ );
+
                                return false;
                        } else {
                                $this->mAffectedRows = oci_num_rows( $stmt );
@@ -1339,6 +1457,14 @@ class DatabaseOracle extends DatabaseBase {
                return $this->mServer;
        }
 
+       public function buildGroupConcatField(
+               $delim, $table, $field, $conds = '', $join_conds = array()
+       ) {
+               $fld = "LISTAGG($field," . $this->addQuotes( $delim ) . ") WITHIN GROUP (ORDER BY $field)";
+
+               return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
+       }
+
        public function getSearchEngine() {
                return 'SearchOracle';
        }
@@ -1346,5 +1472,4 @@ class DatabaseOracle extends DatabaseBase {
        public function getInfinity() {
                return '31-12-2030 12:00:00.000000';
        }
-
 } // end DatabaseOracle class
index e564a16..cfa2074 100644 (file)
@@ -79,6 +79,7 @@ SQL;
                $n->conname = $row->conname;
                $n->has_default = ( $row->atthasdef === 't' );
                $n->default = $row->adsrc;
+
                return $n;
        }
 
@@ -113,6 +114,7 @@ SQL;
        function conname() {
                return $this->conname;
        }
+
        /**
         * @since 1.19
         */
@@ -123,7 +125,6 @@ SQL;
                        return false;
                }
        }
-
 }
 
 /**
@@ -181,7 +182,6 @@ class PostgresTransactionState {
                                        }
                                        $old = next( $this->mCurrentState );
                                        $new = next( $this->mNewState );
-
                                }
                        }
                }
@@ -224,8 +224,8 @@ class SavepointPostgres {
                $this->didbegin = false;
                /* If we are not in a transaction, we need to be for savepoint trickery */
                if ( !$dbw->trxLevel() ) {
-                               $dbw->begin( "FOR SAVEPOINT" );
-                               $this->didbegin = true;
+                       $dbw->begin( "FOR SAVEPOINT" );
+                       $this->didbegin = true;
                }
        }
 
@@ -247,10 +247,10 @@ class SavepointPostgres {
                global $wgDebugDBTransactions;
                if ( $this->dbw->doQuery( $keyword . " " . $this->id ) !== false ) {
                        if ( $wgDebugDBTransactions ) {
-                               wfDebug( sprintf ( $msg_ok, $this->id ) );
+                               wfDebug( sprintf( $msg_ok, $this->id ) );
                        }
                } else {
-                       wfDebug( sprintf ( $msg_failed, $this->id ) );
+                       wfDebug( sprintf( $msg_failed, $this->id ) );
                }
        }
 
@@ -296,32 +296,42 @@ class DatabasePostgres extends DatabaseBase {
        function cascadingDeletes() {
                return true;
        }
+
        function cleanupTriggers() {
                return true;
        }
+
        function strictIPs() {
                return true;
        }
+
        function realTimestamps() {
                return true;
        }
+
        function implicitGroupby() {
                return false;
        }
+
        function implicitOrderby() {
                return false;
        }
+
        function searchableIPs() {
                return true;
        }
+
        function functionalIndexes() {
                return true;
        }
 
        function hasConstraint( $name ) {
-               $SQL = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n WHERE c.connamespace = n.oid AND conname = '" .
-                               pg_escape_string( $this->mConn, $name ) . "' AND n.nspname = '" . pg_escape_string( $this->mConn, $this->getCoreSchema() ) . "'";
+               $SQL = "SELECT 1 FROM pg_catalog.pg_constraint c, pg_catalog.pg_namespace n " .
+                       "WHERE c.connamespace = n.oid AND conname = '" .
+                       pg_escape_string( $this->mConn, $name ) . "' AND n.nspname = '" .
+                       pg_escape_string( $this->mConn, $this->getCoreSchema() ) . "'";
                $res = $this->doQuery( $SQL );
+
                return $this->numRows( $res );
        }
 
@@ -337,7 +347,12 @@ class DatabasePostgres extends DatabaseBase {
        function open( $server, $user, $password, $dbName ) {
                # Test for Postgres support, to avoid suppressed fatal error
                if ( !function_exists( 'pg_connect' ) ) {
-                       throw new DBConnectionError( $this, "Postgres functions missing, have you compiled PHP with the --with-pgsql option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" );
+                       throw new DBConnectionError(
+                               $this,
+                               "Postgres functions missing, have you compiled PHP with the --with-pgsql\n" .
+                               "option? (Note: if you recently installed PHP, you may need to restart your\n" .
+                               "webserver and database)\n"
+                       );
                }
 
                global $wgDBport;
@@ -370,12 +385,20 @@ class DatabasePostgres extends DatabaseBase {
                $this->connectString = $this->makeConnectionString( $connectVars, PGSQL_CONNECT_FORCE_NEW );
                $this->close();
                $this->installErrorHandler();
-               $this->mConn = pg_connect( $this->connectString );
+
+               try {
+                       $this->mConn = pg_connect( $this->connectString );
+               } catch ( Exception $ex ) {
+                       $this->restoreErrorHandler();
+                       throw $ex;
+               }
+
                $phpError = $this->restoreErrorHandler();
 
                if ( !$this->mConn ) {
                        wfDebug( "DB connection error\n" );
-                       wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" );
+                       wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " .
+                               substr( $password, 0, 3 ) . "...\n" );
                        wfDebug( $this->lastError() . "\n" );
                        throw new DBConnectionError( $this, str_replace( "\n", ' ', $phpError ) );
                }
@@ -421,6 +444,7 @@ class DatabasePostgres extends DatabaseBase {
                foreach ( $vars as $name => $value ) {
                        $s .= "$name='" . str_replace( "'", "\\'", $value ) . "' ";
                }
+
                return $s;
        }
 
@@ -447,24 +471,28 @@ class DatabasePostgres extends DatabaseBase {
                if ( pg_result_error( $this->mLastResult ) ) {
                        return false;
                }
+
                return $this->mLastResult;
        }
 
        protected function dumpError() {
-               $diags = array( PGSQL_DIAG_SEVERITY,
-                               PGSQL_DIAG_SQLSTATE,
-                               PGSQL_DIAG_MESSAGE_PRIMARY,
-                               PGSQL_DIAG_MESSAGE_DETAIL,
-                               PGSQL_DIAG_MESSAGE_HINT,
-                               PGSQL_DIAG_STATEMENT_POSITION,
-                               PGSQL_DIAG_INTERNAL_POSITION,
-                               PGSQL_DIAG_INTERNAL_QUERY,
-                               PGSQL_DIAG_CONTEXT,
-                               PGSQL_DIAG_SOURCE_FILE,
-                               PGSQL_DIAG_SOURCE_LINE,
-                               PGSQL_DIAG_SOURCE_FUNCTION );
+               $diags = array(
+                       PGSQL_DIAG_SEVERITY,
+                       PGSQL_DIAG_SQLSTATE,
+                       PGSQL_DIAG_MESSAGE_PRIMARY,
+                       PGSQL_DIAG_MESSAGE_DETAIL,
+                       PGSQL_DIAG_MESSAGE_HINT,
+                       PGSQL_DIAG_STATEMENT_POSITION,
+                       PGSQL_DIAG_INTERNAL_POSITION,
+                       PGSQL_DIAG_INTERNAL_QUERY,
+                       PGSQL_DIAG_CONTEXT,
+                       PGSQL_DIAG_SOURCE_FILE,
+                       PGSQL_DIAG_SOURCE_LINE,
+                       PGSQL_DIAG_SOURCE_FUNCTION
+               );
                foreach ( $diags as $d ) {
-                       wfDebug( sprintf( "PgSQL ERROR(%d): %s\n", $d, pg_result_error_field( $this->mLastResult, $d ) ) );
+                       wfDebug( sprintf( "PgSQL ERROR(%d): %s\n",
+                               $d, pg_result_error_field( $this->mLastResult, $d ) ) );
                }
        }
 
@@ -474,6 +502,7 @@ class DatabasePostgres extends DatabaseBase {
                        /* Check for constraint violation */
                        if ( $errno === '23505' ) {
                                parent::reportQueryError( $error, $errno, $sql, $fname, $tempIgnore );
+
                                return;
                        }
                }
@@ -510,8 +539,12 @@ class DatabasePostgres extends DatabaseBase {
                # @todo hashar: not sure if the following test really trigger if the object
                #          fetching failed.
                if ( pg_last_error( $this->mConn ) ) {
-                       throw new DBUnexpectedError( $this, 'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) ) );
+                       throw new DBUnexpectedError(
+                               $this,
+                               'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) )
+                       );
                }
+
                return $row;
        }
 
@@ -523,8 +556,12 @@ class DatabasePostgres extends DatabaseBase {
                $row = pg_fetch_array( $res );
                wfRestoreWarnings();
                if ( pg_last_error( $this->mConn ) ) {
-                       throw new DBUnexpectedError( $this, 'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) ) );
+                       throw new DBUnexpectedError(
+                               $this,
+                               'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) )
+                       );
                }
+
                return $row;
        }
 
@@ -536,8 +573,12 @@ class DatabasePostgres extends DatabaseBase {
                $n = pg_num_rows( $res );
                wfRestoreWarnings();
                if ( pg_last_error( $this->mConn ) ) {
-                       throw new DBUnexpectedError( $this, 'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) ) );
+                       throw new DBUnexpectedError(
+                               $this,
+                               'SQL error: ' . htmlspecialchars( pg_last_error( $this->mConn ) )
+                       );
                }
+
                return $n;
        }
 
@@ -545,6 +586,7 @@ class DatabasePostgres extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return pg_num_fields( $res );
        }
 
@@ -552,6 +594,7 @@ class DatabasePostgres extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return pg_field_name( $res, $n );
        }
 
@@ -569,6 +612,7 @@ class DatabasePostgres extends DatabaseBase {
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return pg_result_seek( $res, $row );
        }
 
@@ -583,6 +627,7 @@ class DatabasePostgres extends DatabaseBase {
                        return 'No database connection';
                }
        }
+
        function lastErrno() {
                if ( $this->mLastResult ) {
                        return pg_result_error_field( $this->mLastResult, PGSQL_DIAG_SQLSTATE );
@@ -599,6 +644,7 @@ class DatabasePostgres extends DatabaseBase {
                if ( empty( $this->mLastResult ) ) {
                        return 0;
                }
+
                return pg_affected_rows( $this->mLastResult );
        }
 
@@ -610,7 +656,9 @@ class DatabasePostgres extends DatabaseBase {
         * Takes same arguments as Database::select()
         * @return int
         */
-       function estimateRowCount( $table, $vars = '*', $conds = '', $fname = __METHOD__, $options = array() ) {
+       function estimateRowCount( $table, $vars = '*', $conds = '',
+               $fname = __METHOD__, $options = array()
+       ) {
                $options['EXPLAIN'] = true;
                $res = $this->select( $table, $vars, $conds, $fname, $options );
                $rows = -1;
@@ -621,6 +669,7 @@ class DatabasePostgres extends DatabaseBase {
                                $rows = $count[1];
                        }
                }
+
                return $rows;
        }
 
@@ -640,6 +689,7 @@ class DatabasePostgres extends DatabaseBase {
                                return $row;
                        }
                }
+
                return false;
        }
 
@@ -702,6 +752,7 @@ __INDEXATTR__;
                } else {
                        return null;
                }
+
                return $a;
        }
 
@@ -717,6 +768,7 @@ __INDEXATTR__;
                foreach ( $res as $row ) {
                        return true;
                }
+
                return false;
        }
 
@@ -844,15 +896,15 @@ __INDEXATTR__;
        /**
         * INSERT SELECT wrapper
         * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
-        * Source items may be literals rather then field names, but strings should be quoted with Database::addQuotes()
+        * Source items may be literals rather then field names, but strings should
+        * be quoted with Database::addQuotes()
         * $conds may be "*" to copy the whole table
         * srcTable may be an array of tables.
         * @todo FIXME: Implement this a little better (seperate select/insert)?
         * @return bool
         */
        function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = __METHOD__,
-               $insertOptions = array(), $selectOptions = array() )
-       {
+               $insertOptions = array(), $selectOptions = array() ) {
                $destTable = $this->tableName( $destTable );
 
                if ( !is_array( $insertOptions ) ) {
@@ -882,8 +934,8 @@ __INDEXATTR__;
                }
 
                $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
-                               " SELECT $startOpts " . implode( ',', $varMap ) .
-                               " FROM $srcTable $useIndex";
+                       " SELECT $startOpts " . implode( ',', $varMap ) .
+                       " FROM $srcTable $useIndex";
 
                if ( $conds != '*' ) {
                        $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
@@ -939,6 +991,7 @@ __INDEXATTR__;
                $res = $this->query( "SELECT nextval('$safeseq')" );
                $row = $this->fetchRow( $res );
                $this->mInsertId = $row[0];
+
                return $this->mInsertId;
        }
 
@@ -951,6 +1004,7 @@ __INDEXATTR__;
                $res = $this->query( "SELECT currval('$safeseq')" );
                $row = $this->fetchRow( $res );
                $currval = $row[0];
+
                return $currval;
        }
 
@@ -968,6 +1022,7 @@ __INDEXATTR__;
                } else {
                        $size = $row->size;
                }
+
                return $size;
        }
 
@@ -982,7 +1037,9 @@ __INDEXATTR__;
        function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = __METHOD__ ) {
                $newName = $this->addIdentifierQuotes( $newName );
                $oldName = $this->addIdentifierQuotes( $oldName );
-               return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName (LIKE $oldName INCLUDING DEFAULTS)", $fname );
+
+               return $this->query( 'CREATE ' . ( $temporary ? 'TEMPORARY ' : '' ) . " TABLE $newName " .
+                       "(LIKE $oldName INCLUDING DEFAULTS)", $fname );
        }
 
        function listTables( $prefix = null, $fname = __METHOD__ ) {
@@ -1037,8 +1094,8 @@ __INDEXATTR__;
                                        $text, $match, 0, $offset );
                                $offset += strlen( $match[0] );
                                $output[] = ( '"' != $match[1][0]
-                                               ? $match[1]
-                                               : stripcslashes( substr( $match[1], 1, -1 ) ) );
+                                       ? $match[1]
+                                       : stripcslashes( substr( $match[1], 1, -1 ) ) );
                                if ( '},' == $match[3] ) {
                                        return $output;
                                }
@@ -1046,6 +1103,7 @@ __INDEXATTR__;
                                $offset = $this->pg_array_parse( $text, $output, $limit, $offset + 1 );
                        }
                } while ( $limit > $offset );
+
                return $output;
        }
 
@@ -1073,6 +1131,7 @@ __INDEXATTR__;
        function getCurrentSchema() {
                $res = $this->query( "SELECT current_schema()", __METHOD__ );
                $row = $this->fetchRow( $res );
+
                return $row[0];
        }
 
@@ -1090,7 +1149,9 @@ __INDEXATTR__;
                $res = $this->query( "SELECT current_schemas(false)", __METHOD__ );
                $row = $this->fetchRow( $res );
                $schemas = array();
+
                /* PHP pgsql support does not support array type, "{a,b}" string is returned */
+
                return $this->pg_array_parse( $row[0], $schemas );
        }
 
@@ -1106,7 +1167,9 @@ __INDEXATTR__;
        function getSearchPath() {
                $res = $this->query( "SHOW search_path", __METHOD__ );
                $row = $this->fetchRow( $res );
+
                /* PostgreSQL returns SHOW values as strings */
+
                return explode( ",", $row[0] );
        }
 
@@ -1148,14 +1211,15 @@ __INDEXATTR__;
                                 */
                                $search_path = $this->getSearchPath();
                                array_unshift( $search_path,
-                                       $this->addIdentifierQuotes( $desired_schema ));
+                                       $this->addIdentifierQuotes( $desired_schema ) );
                                $this->setSearchPath( $search_path );
                                $this->mCoreSchema = $desired_schema;
                                wfDebug( "Schema \"" . $desired_schema . "\" added to the search path\n" );
                        }
                } else {
                        $this->mCoreSchema = $this->getCurrentSchema();
-                       wfDebug( "Schema \"" . $desired_schema . "\" not found, using current \"" . $this->mCoreSchema . "\"\n" );
+                       wfDebug( "Schema \"" . $desired_schema . "\" not found, using current \"" .
+                               $this->mCoreSchema . "\"\n" );
                }
                /* Commit SET otherwise it will be rollbacked on error or IGNORE SELECT */
                $this->commit( __METHOD__ );
@@ -1188,6 +1252,7 @@ __INDEXATTR__;
                                $this->numeric_version = pg_parameter_status( $this->mConn, 'server_version' );
                        }
                }
+
                return $this->numeric_version;
        }
 
@@ -1211,6 +1276,7 @@ __INDEXATTR__;
                        . "AND c.relkind IN ('" . implode( "','", $types ) . "')";
                $res = $this->query( $SQL );
                $count = $res ? $res->numRows() : 0;
+
                return (bool)$count;
        }
 
@@ -1246,6 +1312,7 @@ SQL;
                        return null;
                }
                $rows = $res->numRows();
+
                return $rows;
        }
 
@@ -1257,12 +1324,13 @@ SQL;
                                'schemaname' => $this->getCoreSchema()
                        )
                );
+
                return $exists === $rule;
        }
 
        function constraintExists( $table, $constraint ) {
                $SQL = sprintf( "SELECT 1 FROM information_schema.table_constraints " .
-                               "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
+                       "WHERE constraint_schema = %s AND table_name = %s AND constraint_name = %s",
                        $this->addQuotes( $this->getCoreSchema() ),
                        $this->addQuotes( $table ),
                        $this->addQuotes( $constraint )
@@ -1272,6 +1340,7 @@ SQL;
                        return null;
                }
                $rows = $res->numRows();
+
                return $rows;
        }
 
@@ -1282,6 +1351,7 @@ SQL;
        function schemaExists( $schema ) {
                $exists = $this->selectField( '"pg_catalog"."pg_namespace"', 1,
                        array( 'nspname' => $schema ), __METHOD__ );
+
                return (bool)$exists;
        }
 
@@ -1292,6 +1362,7 @@ SQL;
        function roleExists( $roleName ) {
                $exists = $this->selectField( '"pg_catalog"."pg_roles"', 1,
                        array( 'rolname' => $roleName ), __METHOD__ );
+
                return (bool)$exists;
        }
 
@@ -1307,6 +1378,7 @@ SQL;
                if ( $res instanceof ResultWrapper ) {
                        $res = $res->result;
                }
+
                return pg_field_type( $res, $index );
        }
 
@@ -1322,6 +1394,7 @@ SQL;
                if ( $b instanceof Blob ) {
                        $b = $b->fetch();
                }
+
                return pg_unescape_bytea( $b );
        }
 
@@ -1341,6 +1414,7 @@ SQL;
                } elseif ( $s instanceof Blob ) {
                        return "'" . $s->fetch( $s ) . "'";
                }
+
                return "'" . pg_escape_string( $this->mConn, $s ) . "'";
        }
 
@@ -1424,6 +1498,14 @@ SQL;
                return implode( ' || ', $stringList );
        }
 
+       public function buildGroupConcatField(
+               $delimiter, $table, $field, $conds = '', $options = array(), $join_conds = array()
+       ) {
+               $fld = "array_to_string(array_agg($field)," . $this->addQuotes( $delimiter ) . ')';
+
+               return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
+       }
+
        public function getSearchEngine() {
                return 'SearchPostgres';
        }
@@ -1433,11 +1515,11 @@ SQL;
                if ( substr( $newLine, 0, 4 ) == '$mw$' ) {
                        if ( $this->delimiter ) {
                                $this->delimiter = false;
-                       }
-                       else {
+                       } else {
                                $this->delimiter = ';';
                        }
                }
+
                return parent::streamStatementEnd( $sql, $newLine );
        }
 
@@ -1455,6 +1537,7 @@ SQL;
                $result = $this->query( "SELECT (CASE(pg_try_advisory_lock($key))
                        WHEN 'f' THEN 'f' ELSE pg_advisory_unlock($key) END) AS lockstatus", $method );
                $row = $this->fetchObject( $result );
+
                return ( $row->lockstatus === 't' );
        }
 
@@ -1478,11 +1561,13 @@ SQL;
                        }
                }
                wfDebug( __METHOD__ . " failed to acquire lock\n" );
+
                return false;
        }
 
        /**
-        * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKSFROM PG DOCS: http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
+        * See http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKSFROM
+        * PG DOCS: http://www.postgresql.org/docs/8.2/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
         * @param $lockName string
         * @param $method string
         * @return bool
@@ -1491,6 +1576,7 @@ SQL;
                $key = $this->addQuotes( $this->bigintFromLockName( $lockName ) );
                $result = $this->query( "SELECT pg_advisory_unlock($key) as lockstatus", $method );
                $row = $this->fetchObject( $result );
+
                return ( $row->lockstatus === 't' );
        }
 
index 4a51226..89f0818 100644 (file)
@@ -26,7 +26,6 @@
  * @ingroup Database
  */
 class DatabaseSqlite extends DatabaseBase {
-
        private static $fulltextEnabled = null;
 
        var $mAffectedRows;
@@ -39,23 +38,30 @@ class DatabaseSqlite extends DatabaseBase {
         */
        protected $mConn;
 
-       /**
-        * Constructor.
-        * Parameters $server, $user and $password are not used.
-        * @param $server string
-        * @param $user string
-        * @param $password string
-        * @param $dbName string
-        * @param $flags int
-        */
-       function __construct( $server = false, $user = false, $password = false, $dbName = false, $flags = 0 ) {
-               $this->mName = $dbName;
-               parent::__construct( $server, $user, $password, $dbName, $flags );
+       function __construct( $p = null ) {
+               global $wgSharedDB;
+
+               if ( !is_array( $p ) ) { // legacy calling pattern
+                       wfDeprecated( __METHOD__ . " method called without parameter array.", "1.22" );
+                       $args = func_get_args();
+                       $p = array(
+                               'host' => isset( $args[0] ) ? $args[0] : false,
+                               'user' => isset( $args[1] ) ? $args[1] : false,
+                               'password' => isset( $args[2] ) ? $args[2] : false,
+                               'dbname' => isset( $args[3] ) ? $args[3] : false,
+                               'flags' => isset( $args[4] ) ? $args[4] : 0,
+                               'tablePrefix' => isset( $args[5] ) ? $args[5] : 'get from global',
+                               'foreign' => isset( $args[6] ) ? $args[6] : false
+                       );
+               }
+               $this->mName = $p['dbname'];
+               parent::__construct( $p );
                // parent doesn't open when $user is false, but we can work with $dbName
-               if ( $dbName && !$this->isOpen() ) {
-                       global $wgSharedDB;
-                       if ( $this->open( $server, $user, $password, $dbName ) && $wgSharedDB ) {
-                               $this->attachDatabase( $wgSharedDB );
+               if ( $p['dbname'] && !$this->isOpen() ) {
+                       if ( $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] ) ) {
+                               if ( $wgSharedDB ) {
+                                       $this->attachDatabase( $wgSharedDB );
+                               }
                        }
                }
        }
@@ -97,6 +103,7 @@ class DatabaseSqlite extends DatabaseBase {
                        throw new DBConnectionError( $this, "SQLite database not accessible" );
                }
                $this->openFile( $fileName );
+
                return $this->mConn;
        }
 
@@ -130,6 +137,7 @@ class DatabaseSqlite extends DatabaseBase {
                        $this->mConn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
                        # Enforce LIKE to be case sensitive, just like MySQL
                        $this->query( 'PRAGMA case_sensitive_like = 1' );
+
                        return true;
                }
        }
@@ -140,6 +148,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        protected function closeConnection() {
                $this->mConn = null;
+
                return true;
        }
 
@@ -167,6 +176,7 @@ class DatabaseSqlite extends DatabaseBase {
                                self::$fulltextEnabled = stristr( $row['sql'], 'fts' ) !== false;
                        }
                }
+
                return self::$fulltextEnabled;
        }
 
@@ -188,6 +198,7 @@ class DatabaseSqlite extends DatabaseBase {
                        $cachedResult = 'FTS3';
                }
                $db->close();
+
                return $cachedResult;
        }
 
@@ -195,8 +206,10 @@ class DatabaseSqlite extends DatabaseBase {
         * Attaches external database to our connection, see http://sqlite.org/lang_attach.html
         * for details.
         *
-        * @param string $name database name to be used in queries like SELECT foo FROM dbname.table
-        * @param string $file database file name. If omitted, will be generated using $name and $wgSQLiteDataDir
+        * @param string $name database name to be used in queries like
+        *   SELECT foo FROM dbname.table
+        * @param string $file database file name. If omitted, will be generated
+        *   using $name and $wgSQLiteDataDir
         * @param string $fname calling function name
         *
         * @return ResultWrapper
@@ -207,6 +220,7 @@ class DatabaseSqlite extends DatabaseBase {
                        $file = self::generateFileName( $wgSQLiteDataDir, $name );
                }
                $file = $this->addQuotes( $file );
+
                return $this->query( "ATTACH DATABASE $file AS $name", $fname );
        }
 
@@ -237,6 +251,7 @@ class DatabaseSqlite extends DatabaseBase {
                        $this->mAffectedRows = $r->rowCount();
                        $res = new ResultWrapper( $this, $r->fetchAll() );
                }
+
                return $res;
        }
 
@@ -274,6 +289,7 @@ class DatabaseSqlite extends DatabaseBase {
 
                        return $obj;
                }
+
                return false;
        }
 
@@ -290,8 +306,10 @@ class DatabaseSqlite extends DatabaseBase {
                $cur = current( $r );
                if ( is_array( $cur ) ) {
                        next( $r );
+
                        return $cur;
                }
+
                return false;
        }
 
@@ -304,6 +322,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function numRows( $res ) {
                $r = $res instanceof ResultWrapper ? $res->result : $res;
+
                return count( $r );
        }
 
@@ -313,6 +332,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function numFields( $res ) {
                $r = $res instanceof ResultWrapper ? $res->result : $res;
+
                return is_array( $r ) ? count( $r[0] ) : 0;
        }
 
@@ -325,8 +345,10 @@ class DatabaseSqlite extends DatabaseBase {
                $r = $res instanceof ResultWrapper ? $res->result : $res;
                if ( is_array( $r ) ) {
                        $keys = array_keys( $r[0] );
+
                        return $keys[$n];
                }
+
                return false;
        }
 
@@ -342,6 +364,7 @@ class DatabaseSqlite extends DatabaseBase {
                if ( strpos( $name, 'sqlite_' ) === 0 ) {
                        return $name;
                }
+
                return str_replace( '"', '', parent::tableName( $name, $format ) );
        }
 
@@ -392,6 +415,7 @@ class DatabaseSqlite extends DatabaseBase {
                        return "Cannot return last error, no db connection";
                }
                $e = $this->mConn->errorInfo();
+
                return isset( $e[2] ) ? $e[2] : '';
        }
 
@@ -403,6 +427,7 @@ class DatabaseSqlite extends DatabaseBase {
                        return "Cannot return last error, no db connection";
                } else {
                        $info = $this->mConn->errorInfo();
+
                        return $info[1];
                }
        }
@@ -434,6 +459,7 @@ class DatabaseSqlite extends DatabaseBase {
                foreach ( $res as $row ) {
                        $info[] = $row->name;
                }
+
                return $info;
        }
 
@@ -460,6 +486,7 @@ class DatabaseSqlite extends DatabaseBase {
                }
                $firstPart = substr( $row->sql, 0, $indexPos );
                $options = explode( ' ', $firstPart );
+
                return in_array( 'UNIQUE', $options );
        }
 
@@ -476,6 +503,7 @@ class DatabaseSqlite extends DatabaseBase {
                                $options[$k] = '';
                        }
                }
+
                return parent::makeSelectOptions( $options );
        }
 
@@ -485,6 +513,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function makeUpdateOptions( $options ) {
                $options = self::fixIgnore( $options );
+
                return parent::makeUpdateOptions( $options );
        }
 
@@ -499,6 +528,7 @@ class DatabaseSqlite extends DatabaseBase {
                                $options[$k] = 'OR IGNORE';
                        }
                }
+
                return $options;
        }
 
@@ -508,6 +538,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function makeInsertOptions( $options ) {
                $options = self::fixIgnore( $options );
+
                return parent::makeInsertOptions( $options );
        }
 
@@ -586,6 +617,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function unionQueries( $sqls, $all ) {
                $glue = $all ? ' UNION ALL ' : ' UNION ';
+
                return implode( $glue, $sqls );
        }
 
@@ -622,6 +654,7 @@ class DatabaseSqlite extends DatabaseBase {
         */
        function getServerVersion() {
                $ver = $this->mConn->getAttribute( PDO::ATTR_SERVER_VERSION );
+
                return $ver;
        }
 
@@ -629,7 +662,9 @@ class DatabaseSqlite extends DatabaseBase {
         * @return string User-friendly database information
         */
        public function getServerInfo() {
-               return wfMessage( self::getFulltextSearchModule() ? 'sqlite-has-fts' : 'sqlite-no-fts', $this->getServerVersion() )->text();
+               return wfMessage( self::getFulltextSearchModule()
+                       ? 'sqlite-has-fts'
+                       : 'sqlite-no-fts', $this->getServerVersion() )->text();
        }
 
        /**
@@ -649,6 +684,7 @@ class DatabaseSqlite extends DatabaseBase {
                                return new SQLiteField( $row, $tableName );
                        }
                }
+
                return false;
        }
 
@@ -689,7 +725,7 @@ class DatabaseSqlite extends DatabaseBase {
         * @return string
         */
        function strencode( $s ) {
-               return substr( $this->addQuotes( $s ), 1, - 1 );
+               return substr( $this->addQuotes( $s ), 1, -1 );
        }
 
        /**
@@ -708,6 +744,7 @@ class DatabaseSqlite extends DatabaseBase {
                if ( $b instanceof Blob ) {
                        $b = $b->fetch();
                }
+
                return $b;
        }
 
@@ -741,6 +778,7 @@ class DatabaseSqlite extends DatabaseBase {
                if ( count( $params ) > 0 && is_array( $params[0] ) ) {
                        $params = $params[0];
                }
+
                return parent::buildLike( $params ) . "ESCAPE '\' ";
        }
 
@@ -758,6 +796,7 @@ class DatabaseSqlite extends DatabaseBase {
        public function deadlockLoop( /*...*/ ) {
                $args = func_get_args();
                $function = array_shift( $args );
+
                return call_user_func_array( $function, $args );
        }
 
@@ -777,7 +816,11 @@ class DatabaseSqlite extends DatabaseBase {
                        // INT -> INTEGER
                        $s = preg_replace( '/\b(tiny|small|medium|big|)int(\s*\(\s*\d+\s*\)|\b)/i', 'INTEGER', $s );
                        // floating point types -> REAL
-                       $s = preg_replace( '/\b(float|double(\s+precision)?)(\s*\(\s*\d+\s*(,\s*\d+\s*)?\)|\b)/i', 'REAL', $s );
+                       $s = preg_replace(
+                               '/\b(float|double(\s+precision)?)(\s*\(\s*\d+\s*(,\s*\d+\s*)?\)|\b)/i',
+                               'REAL',
+                               $s
+                       );
                        // varchar -> TEXT
                        $s = preg_replace( '/\b(var)?char\s*\(.*?\)/i', 'TEXT', $s );
                        // TEXT normalization
@@ -803,7 +846,11 @@ class DatabaseSqlite extends DatabaseBase {
                        $s = preg_replace( '/\(\d+\)/', '', $s );
                        // No FULLTEXT
                        $s = preg_replace( '/\bfulltext\b/i', '', $s );
+               } elseif ( preg_match( '/^\s*DROP INDEX/i', $s ) ) {
+                       // DROP INDEX is database-wide, not table-specific, so no ON <table> clause.
+                       $s = preg_replace( '/\sON\s+[^\s]*/i', '', $s );
                }
+
                return $s;
        }
 
@@ -818,6 +865,14 @@ class DatabaseSqlite extends DatabaseBase {
                return '(' . implode( ') || (', $stringList ) . ')';
        }
 
+       public function buildGroupConcatField(
+               $delim, $table, $field, $conds = '', $join_conds = array()
+       ) {
+               $fld = "group_concat($field," . $this->addQuotes( $delim ) . ')';
+
+               return '(' . $this->selectSQLText( $table, $fld, $conds, null, array(), $join_conds ) . ')';
+       }
+
        /**
         * @throws MWException
         * @param $oldName
@@ -827,13 +882,19 @@ class DatabaseSqlite extends DatabaseBase {
         * @return bool|ResultWrapper
         */
        function duplicateTableStructure( $oldName, $newName, $temporary = false, $fname = __METHOD__ ) {
-               $res = $this->query( "SELECT sql FROM sqlite_master WHERE tbl_name=" . $this->addQuotes( $oldName ) . " AND type='table'", $fname );
+               $res = $this->query( "SELECT sql FROM sqlite_master WHERE tbl_name=" .
+                       $this->addQuotes( $oldName ) . " AND type='table'", $fname );
                $obj = $this->fetchObject( $res );
                if ( !$obj ) {
                        throw new MWException( "Couldn't retrieve structure for table $oldName" );
                }
                $sql = $obj->sql;
-               $sql = preg_replace( '/(?<=\W)"?' . preg_quote( trim( $this->addIdentifierQuotes( $oldName ), '"' ) ) . '"?(?=\W)/', $this->addIdentifierQuotes( $newName ), $sql, 1 );
+               $sql = preg_replace(
+                       '/(?<=\W)"?' . preg_quote( trim( $this->addIdentifierQuotes( $oldName ), '"' ) ) . '"?(?=\W)/',
+                       $this->addIdentifierQuotes( $newName ),
+                       $sql,
+                       1
+               );
                if ( $temporary ) {
                        if ( preg_match( '/^\\s*CREATE\\s+VIRTUAL\\s+TABLE\b/i', $sql ) ) {
                                wfDebug( "Table $oldName is virtual, can't create a temporary duplicate.\n" );
@@ -841,6 +902,7 @@ class DatabaseSqlite extends DatabaseBase {
                                $sql = str_replace( 'CREATE TABLE', 'CREATE TEMPORARY TABLE', $sql );
                        }
                }
+
                return $this->query( $sql, $fname );
        }
 
@@ -869,13 +931,11 @@ class DatabaseSqlite extends DatabaseBase {
                                if ( strpos( $table, 'sqlite_' ) !== 0 ) {
                                        $endArray[] = $table;
                                }
-
                        }
                }
 
                return $endArray;
        }
-
 } // end DatabaseSqlite class
 
 /**
@@ -895,6 +955,7 @@ class DatabaseSqliteStandalone extends DatabaseSqlite {
  */
 class SQLiteField implements Field {
        private $info, $tableName;
+
        function __construct( $info, $tableName ) {
                $this->info = $info;
                $this->tableName = $tableName;
@@ -915,6 +976,7 @@ class SQLiteField implements Field {
                                return str_replace( "''", "'", $this->info->dflt_value );
                        }
                }
+
                return $this->info->dflt_value;
        }
 
@@ -928,5 +990,4 @@ class SQLiteField implements Field {
        function type() {
                return $this->info->type;
        }
-
 } // end SQLiteField
index de58bab..de5be08 100644 (file)
@@ -187,6 +187,7 @@ class ResultWrapper implements Iterator {
                if ( is_null( $this->currentRow ) ) {
                        $this->next();
                }
+
                return $this->currentRow;
        }
 
@@ -203,6 +204,7 @@ class ResultWrapper implements Iterator {
        function next() {
                $this->pos++;
                $this->currentRow = $this->fetchObject();
+
                return $this->currentRow;
        }
 
@@ -277,8 +279,9 @@ class FakeResultWrapper extends ResultWrapper {
 }
 
 /**
- * Used by DatabaseBase::buildLike() to represent characters that have special meaning in SQL LIKE clauses
- * and thus need no escaping. Don't instantiate it manually, use DatabaseBase::anyChar() and anyString() instead.
+ * Used by DatabaseBase::buildLike() to represent characters that have special
+ * meaning in SQL LIKE clauses and thus need no escaping. Don't instantiate it
+ * manually, use DatabaseBase::anyChar() and anyString() instead.
  */
 class LikeMatch {
        private $str;
index 3941179..21ae808 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 interface IORMRow {
-
        /**
         * Load the specified fields from the database.
         *
@@ -268,5 +267,4 @@ interface IORMRow {
         * @return IORMTable
         */
        public function getTable();
-
 }
index 3686565..9e9c526 100644 (file)
@@ -28,7 +28,6 @@
  */
 
 interface IORMTable {
-
        /**
         * Returns the name of the database table objects of this type are stored in.
         *
@@ -63,8 +62,9 @@ interface IORMTable {
         * * array
         * * blob
         *
-        * TODO: get rid of the id field. Every row instance needs to have
-        * one so this is just causing hassle at various locations by requiring an extra check for field name.
+        * @todo Get rid of the id field. Every row instance needs to have one so
+        *   this is just causing hassle at various locations by requiring an extra
+        *   check for field name.
         *
         * @since 1.20
         *
@@ -110,7 +110,7 @@ interface IORMTable {
         * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode)
         */
        public function select( $fields = null, array $conditions = array(),
-                                                       array $options = array(), $functionName = null );
+               array $options = array(), $functionName = null );
 
        /**
         * Selects the the specified fields of the records matching the provided
@@ -126,7 +126,7 @@ interface IORMTable {
         * @return array of self
         */
        public function selectObjects( $fields = null, array $conditions = array(),
-                                                                  array $options = array(), $functionName = null );
+               array $options = array(), $functionName = null );
 
        /**
         * Do the actual select.
@@ -142,7 +142,7 @@ interface IORMTable {
         * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode)
         */
        public function rawSelect( $fields = null, array $conditions = array(),
-                                                          array $options = array(), $functionName = null );
+               array $options = array(), $functionName = null );
 
        /**
         * Selects the the specified fields of the records matching the provided
@@ -167,7 +167,7 @@ interface IORMTable {
         * @return array of array
         */
        public function selectFields( $fields = null, array $conditions = array(),
-                                                                 array $options = array(), $collapse = true, $functionName = null );
+               array $options = array(), $collapse = true, $functionName = null );
 
        /**
         * Selects the the specified fields of the first matching record.
@@ -183,7 +183,7 @@ interface IORMTable {
         * @return IORMRow|bool False on failure
         */
        public function selectRow( $fields = null, array $conditions = array(),
-                                                          array $options = array(), $functionName = null );
+               array $options = array(), $functionName = null );
 
        /**
         * Selects the the specified fields of the records matching the provided
@@ -199,7 +199,7 @@ interface IORMTable {
         * @return ResultWrapper
         */
        public function rawSelectRow( array $fields, array $conditions = array(),
-                                                                 array $options = array(), $functionName = null );
+               array $options = array(), $functionName = null );
 
        /**
         * Selects the the specified fields of the first record matching the provided
@@ -219,7 +219,7 @@ interface IORMTable {
         * @return mixed|array|bool False on failure
         */
        public function selectFieldsRow( $fields = null, array $conditions = array(),
-                                                                        array $options = array(), $collapse = true, $functionName = null );
+               array $options = array(), $collapse = true, $functionName = null );
 
        /**
         * Returns if there is at least one record matching the provided conditions.
@@ -316,14 +316,16 @@ interface IORMTable {
         *
         * @since 1.20
         *
-        * @return String|bool The target wiki, in a form that  LBFactory understands (or false if the local wiki is used)
+        * @return String|bool The target wiki, in a form that LBFactory
+        *   understands (or false if the local wiki is used)
         */
        public function getTargetWiki();
 
        /**
         * Set the ID of the any foreign wiki to use as a target for database operations
         *
-        * @param string|bool $wiki The target wiki, in a form that  LBFactory understands (or false if the local wiki shall be used)
+        * @param string|bool $wiki The target wiki, in a form that LBFactory
+        *   understands (or false if the local wiki shall be used)
         *
         * @since 1.20
         */
@@ -513,5 +515,4 @@ interface IORMTable {
         * @return boolean
         */
        public function canHaveField( $name );
-
 }
index 16c43a0..6e377ff 100644 (file)
@@ -26,7 +26,6 @@
  * @ingroup Database
  */
 abstract class LBFactory {
-
        /**
         * @var LBFactory
         */
@@ -52,6 +51,7 @@ abstract class LBFactory {
                        $class = $wgLBFactoryConf['class'];
                        self::$instance = new $class( $wgLBFactoryConf );
                }
+
                return self::$instance;
        }
 
@@ -210,13 +210,13 @@ class LBFactory_Simple extends LBFactory {
                                'type' => $wgDBtype,
                                'load' => 1,
                                'flags' => $flags
-                       ));
+                       ) );
                }
 
                return new LoadBalancer( array(
                        'servers' => $servers,
                        'masterWaitTimeout' => $wgMasterWaitTimeout
-               ));
+               ) );
        }
 
        /**
@@ -229,6 +229,7 @@ class LBFactory_Simple extends LBFactory {
                        $this->mainLB->parentInfo( array( 'id' => 'main' ) );
                        $this->chronProt->initLB( $this->mainLB );
                }
+
                return $this->mainLB;
        }
 
@@ -243,9 +244,10 @@ class LBFactory_Simple extends LBFactory {
                if ( !isset( $wgExternalServers[$cluster] ) ) {
                        throw new MWException( __METHOD__ . ": Unknown cluster \"$cluster\"" );
                }
+
                return new LoadBalancer( array(
                        'servers' => $wgExternalServers[$cluster]
-               ));
+               ) );
        }
 
        /**
@@ -259,6 +261,7 @@ class LBFactory_Simple extends LBFactory {
                        $this->extLBs[$cluster]->parentInfo( array( 'id' => "ext-$cluster" ) );
                        $this->chronProt->initLB( $this->extLBs[$cluster] );
                }
+
                return $this->extLBs[$cluster];
        }
 
@@ -325,6 +328,7 @@ class LBFactory_Fake extends LBFactory {
  */
 class DBAccessError extends MWException {
        function __construct() {
-               parent::__construct( "Mediawiki tried to access the database via wfGetDB(). This is not allowed." );
+               parent::__construct( "Mediawiki tried to access the database via wfGetDB(). " .
+                       "This is not allowed." );
        }
 }
index 3043946..a37a560 100644 (file)
  * Configuration:
  *     sectionsByDB                A map of database names to section names
  *
- *     sectionLoads                A 2-d map. For each section, gives a map of server names to load ratios.
- *                                 For example: array( 'section1' => array( 'db1' => 100, 'db2' => 100 ) )
+ *     sectionLoads                A 2-d map. For each section, gives a map of server names to
+ *                                 load ratios. For example:
+ *                                 array(
+ *                                     'section1' => array(
+ *                                         'db1' => 100,
+ *                                         'db2' => 100
+ *                                     )
+ *                                 )
  *
- *     serverTemplate              A server info associative array as documented for $wgDBservers. The host,
- *                                 hostName and load entries will be overridden.
+ *     serverTemplate              A server info associative array as documented for $wgDBservers.
+ *                                 The host, hostName and load entries will be overridden.
  *
- *     groupLoadsBySection         A 3-d map giving server load ratios for each section and group. For example:
- *                                 array( 'section1' => array( 'group1' => array( 'db1' => 100, 'db2' => 100 ) ) )
+ *     groupLoadsBySection         A 3-d map giving server load ratios for each section and group.
+ *                                 For example:
+ *                                 array(
+ *                                     'section1' => array(
+ *                                         'group1' => array(
+ *                                             'db1' => 100,
+ *                                             'db2' => 100
+ *                                         )
+ *                                     )
+ *                                 )
  *
  *     groupLoadsByDB              A 3-d map giving server load ratios by DB name.
  *
  *
  *     externalLoads               A map of external storage cluster name to server load map
  *
- *     externalTemplateOverrides   A set of server info keys overriding serverTemplate for external storage
+ *     externalTemplateOverrides   A set of server info keys overriding serverTemplate for external
+ *                                 storage
  *
- *     templateOverridesByServer   A 2-d map overriding serverTemplate and externalTemplateOverrides on a
- *                                 server-by-server basis. Applies to both core and external storage.
+ *     templateOverridesByServer   A 2-d map overriding serverTemplate and
+ *                                 externalTemplateOverrides on a server-by-server basis. Applies
+ *                                 to both core and external storage.
  *
  *     templateOverridesByCluster  A 2-d map overriding the server info by external storage cluster
  *
  *     masterTemplateOverrides     An override array for all master servers.
  *
- *     readOnlyBySection           A map of section name to read-only message. Missing or false for read/write.
+ *     readOnlyBySection           A map of section name to read-only message.
+ *                                 Missing or false for read/write.
  *
  * @ingroup Database
  */
@@ -117,6 +134,7 @@ class LBFactory_Multi extends LBFactory {
                }
                $this->lastSection = $section;
                $this->lastWiki = $wiki;
+
                return $section;
        }
 
@@ -131,10 +149,16 @@ class LBFactory_Multi extends LBFactory {
                if ( isset( $this->groupLoadsByDB[$dbName] ) ) {
                        $groupLoads = $this->groupLoadsByDB[$dbName];
                }
+
                if ( isset( $this->groupLoadsBySection[$section] ) ) {
                        $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] );
                }
-               return $this->newLoadBalancer( $this->serverTemplate, $this->sectionLoads[$section], $groupLoads );
+
+               return $this->newLoadBalancer(
+                       $this->serverTemplate,
+                       $this->sectionLoads[$section],
+                       $groupLoads
+               );
        }
 
        /**
@@ -149,6 +173,7 @@ class LBFactory_Multi extends LBFactory {
                        $this->chronProt->initLB( $lb );
                        $this->mainLBs[$section] = $lb;
                }
+
                return $this->mainLBs[$section];
        }
 
@@ -169,6 +194,7 @@ class LBFactory_Multi extends LBFactory {
                if ( isset( $this->templateOverridesByCluster[$cluster] ) ) {
                        $template = $this->templateOverridesByCluster[$cluster] + $template;
                }
+
                return $this->newLoadBalancer( $template, $this->externalLoads[$cluster], array() );
        }
 
@@ -183,6 +209,7 @@ class LBFactory_Multi extends LBFactory {
                        $this->extLBs[$cluster]->parentInfo( array( 'id' => "ext-$cluster" ) );
                        $this->chronProt->initLB( $this->extLBs[$cluster] );
                }
+
                return $this->extLBs[$cluster];
        }
 
@@ -200,7 +227,8 @@ class LBFactory_Multi extends LBFactory {
                $lb = new LoadBalancer( array(
                        'servers' => $servers,
                        'masterWaitTimeout' => $wgMasterWaitTimeout
-               ));
+               ) );
+
                return $lb;
        }
 
@@ -245,6 +273,7 @@ class LBFactory_Multi extends LBFactory {
                        $serverInfo['load'] = $load;
                        $servers[] = $serverInfo;
                }
+
                return $servers;
        }
 
@@ -260,6 +289,7 @@ class LBFactory_Multi extends LBFactory {
                                $reindexed[$server][$group] = $load;
                        }
                }
+
                return $reindexed;
        }
 
@@ -271,6 +301,7 @@ class LBFactory_Multi extends LBFactory {
        function getDBNameAndPrefix( $wiki = false ) {
                if ( $wiki === false ) {
                        global $wgDBname, $wgDBprefix;
+
                        return array( $wgDBname, $wgDBprefix );
                } else {
                        return wfSplitWikiID( $wiki );
index 857109d..9967cc0 100644 (file)
@@ -101,6 +101,7 @@ class LoadBalancer {
                        $class = $this->mLoadMonitorClass;
                        $this->mLoadMonitor = new $class( $this );
                }
+
                return $this->mLoadMonitor;
        }
 
@@ -212,6 +213,7 @@ class LoadBalancer {
                                # No loads for this group, return false and the caller can use some other group
                                wfDebug( __METHOD__ . ": no loads for group $group\n" );
                                wfProfileOut( __METHOD__ );
+
                                return false;
                        }
                } else {
@@ -255,6 +257,7 @@ class LoadBalancer {
                                        # wants us to return false.
                                        wfDebugLog( 'connect', __METHOD__ . ": pickRandom() returned false\n" );
                                        wfProfileOut( __METHOD__ );
+
                                        return false;
                                }
 
@@ -329,6 +332,7 @@ class LoadBalancer {
                        }
                }
                wfProfileOut( __METHOD__ );
+
                return $i;
        }
 
@@ -342,6 +346,7 @@ class LoadBalancer {
                wfDebug( __METHOD__ . ": waiting $t us\n" );
                usleep( $t );
                wfProfileOut( __METHOD__ );
+
                return $t;
        }
 
@@ -372,8 +377,11 @@ class LoadBalancer {
        public function waitForAll( $pos ) {
                wfProfileIn( __METHOD__ );
                $this->mWaitForPos = $pos;
-               for ( $i = 1; $i < count( $this->mServers ); $i++ ) {
-                       $this->doWait( $i, true );
+               $serverCount = count( $this->mServers );
+               for ( $i = 1; $i < $serverCount; $i++ ) {
+                       if ( $this->mLoads[$i] > 0 ) {
+                               $this->doWait( $i, true );
+                       }
                }
                wfProfileOut( __METHOD__ );
        }
@@ -391,6 +399,7 @@ class LoadBalancer {
                                return reset( $conns[$i] );
                        }
                }
+
                return false;
        }
 
@@ -406,11 +415,13 @@ class LoadBalancer {
                if ( !$conn ) {
                        if ( !$open ) {
                                wfDebug( __METHOD__ . ": no connection open\n" );
+
                                return false;
                        } else {
                                $conn = $this->openConnection( $index, '' );
                                if ( !$conn ) {
                                        wfDebug( __METHOD__ . ": failed to open connection\n" );
+
                                        return false;
                                }
                        }
@@ -422,9 +433,11 @@ class LoadBalancer {
                if ( $result == -1 || is_null( $result ) ) {
                        # Timed out waiting for slave, use master instead
                        wfDebug( __METHOD__ . ": Timed out waiting for slave #$index pos {$this->mWaitForPos}\n" );
+
                        return false;
                } else {
                        wfDebug( __METHOD__ . ": Done\n" );
+
                        return true;
                }
        }
@@ -445,10 +458,12 @@ class LoadBalancer {
 
                if ( $i == DB_LAST ) {
                        wfProfileOut( __METHOD__ );
-                       throw new MWException( 'Attempt to call ' . __METHOD__ . ' with deprecated server index DB_LAST' );
+                       throw new MWException( 'Attempt to call ' . __METHOD__ .
+                               ' with deprecated server index DB_LAST' );
                } elseif ( $i === null || $i === false ) {
                        wfProfileOut( __METHOD__ );
-                       throw new MWException( 'Attempt to call ' . __METHOD__ . ' with invalid server index' );
+                       throw new MWException( 'Attempt to call ' . __METHOD__ .
+                               ' with invalid server index' );
                }
 
                if ( $wiki === wfWikiID() ) {
@@ -485,6 +500,7 @@ class LoadBalancer {
                        if ( $i === false ) {
                                $this->mLastError = 'No working slave server: ' . $this->mLastError;
                                wfProfileOut( __METHOD__ );
+
                                return $this->reportConnectionError();
                        }
                }
@@ -493,10 +509,12 @@ class LoadBalancer {
                $conn = $this->openConnection( $i, $wiki );
                if ( !$conn ) {
                        wfProfileOut( __METHOD__ );
+
                        return $this->reportConnectionError();
                }
 
                wfProfileOut( __METHOD__ );
+
                return $conn;
        }
 
@@ -520,6 +538,7 @@ class LoadBalancer {
                }
                if ( $serverIndex === null || $refCount === null ) {
                        wfDebug( __METHOD__ . ": this connection was not opened as a foreign connection\n" );
+
                        /**
                         * This can happen in code like:
                         *   foreach ( $dbs as $db ) {
@@ -530,10 +549,12 @@ class LoadBalancer {
                         * When a connection to the local DB is opened in this way, reuseConnection()
                         * should be ignored
                         */
+
                        return;
                }
                if ( $this->mConns['foreignUsed'][$serverIndex][$wiki] !== $conn ) {
-                       throw new MWException( __METHOD__ . ": connection not found, has the connection been freed already?" );
+                       throw new MWException( __METHOD__ . ": connection not found, has " .
+                               "the connection been freed already?" );
                }
                $conn->setLBInfo( 'foreignPoolRefCount', --$refCount );
                if ( $refCount <= 0 ) {
@@ -596,6 +617,7 @@ class LoadBalancer {
                if ( $wiki !== false ) {
                        $conn = $this->openForeignConnection( $i, $wiki );
                        wfProfileOut( __METHOD__ );
+
                        return $conn;
                }
                if ( isset( $this->mConns['local'][$i][0] ) ) {
@@ -614,6 +636,7 @@ class LoadBalancer {
                        }
                }
                wfProfileOut( __METHOD__ );
+
                return $conn;
        }
 
@@ -688,6 +711,7 @@ class LoadBalancer {
                        $conn->setLBInfo( 'foreignPoolRefCount', $refCount + 1 );
                }
                wfProfileOut( __METHOD__ );
+
                return $conn;
        }
 
@@ -702,6 +726,7 @@ class LoadBalancer {
                if ( !is_integer( $index ) ) {
                        return false;
                }
+
                return (bool)$this->getAnyOpenConnection( $index );
        }
 
@@ -741,6 +766,7 @@ class LoadBalancer {
                if ( isset( $server['fakeMaster'] ) ) {
                        $db->setFakeMaster( true );
                }
+
                return $db;
        }
 
@@ -762,6 +788,7 @@ class LoadBalancer {
                        wfLogDBError( "Connection error: {$this->mLastError} ({$server})\n" );
                        $conn->reportConnectionError( "{$this->mLastError} ({$server})" ); // throws DBConnectionError
                }
+
                return false; /* not reached */
        }
 
@@ -831,7 +858,8 @@ class LoadBalancer {
        }
 
        /**
-        * Sets the server info structure for the given index. Entry at index $i is created if it doesn't exist
+        * Sets the server info structure for the given index. Entry at index $i
+        * is created if it doesn't exist
         * @param $i
         * @param $serverInfo
         */
@@ -848,17 +876,21 @@ class LoadBalancer {
                # master (however unlikely that may be), then we can fetch the position from the slave.
                $masterConn = $this->getAnyOpenConnection( 0 );
                if ( !$masterConn ) {
-                       for ( $i = 1; $i < count( $this->mServers ); $i++ ) {
+                       $serverCount = count( $this->mServers );
+                       for ( $i = 1; $i < $serverCount; $i++ ) {
                                $conn = $this->getAnyOpenConnection( $i );
                                if ( $conn ) {
                                        wfDebug( "Master pos fetched from slave\n" );
+
                                        return $conn->getSlavePos();
                                }
                        }
                } else {
                        wfDebug( "Master pos fetched from master\n" );
+
                        return $masterConn->getMasterPos();
                }
+
                return false;
        }
 
@@ -974,6 +1006,7 @@ class LoadBalancer {
                        return $this->mAllowLagged;
                }
                $this->mAllowLagged = $mode;
+
                return $this->mAllowLagged;
        }
 
@@ -991,6 +1024,7 @@ class LoadBalancer {
                                }
                        }
                }
+
                return $success;
        }
 
@@ -1044,6 +1078,7 @@ class LoadBalancer {
                                }
                        }
                }
+
                return array( $host, $maxLag, $maxIndex );
        }
 
@@ -1068,6 +1103,7 @@ class LoadBalancer {
                        $this->mLagTimes = $this->getLoadMonitor()->getLagTimes(
                                array_keys( $this->mServers ), $wiki );
                }
+
                return $this->mLagTimes;
        }
 
@@ -1135,6 +1171,7 @@ class DBConnRef implements IDatabase {
                        list( $db, $groups, $wiki ) = $this->params;
                        $this->conn = $this->lb->getConnection( $db, $groups, $wiki );
                }
+
                return call_user_func_array( array( $this->conn, $name ), $arguments );
        }
 
index 519e2df..b293531 100644 (file)
@@ -36,9 +36,9 @@ interface LoadMonitor {
 
        /**
         * Perform pre-connection load ratio adjustment.
-        * @param $loads array
-        * @param string $group the selected query group
-        * @param $wiki String
+        * @param array $loads
+        * @param string|bool $group the selected query group. Default: false
+        * @param string|bool $wiki Default: false
         */
        function scaleLoads( &$loads, $group = false, $wiki = false );
 
@@ -71,6 +71,10 @@ interface LoadMonitor {
        function getLagTimes( $serverIndexes, $wiki );
 }
 
+/**
+ * @todo FIXME: Should be  LoadMonitorNull per naming conventions.
+ * PHP CodeSniffer Squiz.Classes.ValidClassName.NotCamelCaps
+ */
 class LoadMonitor_Null implements LoadMonitor {
        function __construct( $parent ) {
        }
@@ -96,13 +100,14 @@ class LoadMonitor_Null implements LoadMonitor {
  * Uses memcached to cache the replication lag for a short time
  *
  * @ingroup Database
+ * @todo FIXME: Should be  LoadMonitorMySQL per naming conventions.
+ * PHP CodeSniffer Squiz.Classes.ValidClassName.NotCamelCaps
  */
 class LoadMonitor_MySQL implements LoadMonitor {
-
        /**
         * @var LoadBalancer
         */
-       var $parent;
+       public $parent;
 
        /**
         * @param LoadBalancer $parent
@@ -149,6 +154,7 @@ class LoadMonitor_MySQL implements LoadMonitor {
                        if ( mt_rand( 0, $chance ) != 0 ) {
                                unset( $times['timestamp'] ); // hide from caller
                                wfProfileOut( __METHOD__ );
+
                                return $times;
                        }
                        wfIncrStats( 'lag_cache_miss_expired' );
@@ -159,13 +165,14 @@ class LoadMonitor_MySQL implements LoadMonitor {
                # Cache key missing or expired
                if ( $wgMemc->add( "$memcKey:lock", 1, 10 ) ) {
                        # Let this process alone update the cache value
-                       $unlocker = new ScopedCallback( function() use ( $wgMemc, $memcKey ) {
+                       $unlocker = new ScopedCallback( function () use ( $wgMemc, $memcKey ) {
                                $wgMemc->delete( $memcKey );
                        } );
                } elseif ( is_array( $times ) ) {
                        # Could not acquire lock but an old cache exists, so use it
                        unset( $times['timestamp'] ); // hide from caller
                        wfProfileOut( __METHOD__ );
+
                        return $times;
                }
 
@@ -186,6 +193,7 @@ class LoadMonitor_MySQL implements LoadMonitor {
                unset( $times['timestamp'] ); // hide from caller
 
                wfProfileOut( __METHOD__ );
+
                return $times;
        }
 
@@ -202,6 +210,7 @@ class LoadMonitor_MySQL implements LoadMonitor {
                if ( $status['Threads_running'] > $threshold ) {
                        $server = $conn->getProperty( 'mServer' );
                        wfLogDBError( "LB backoff from $server - Threads_running = {$status['Threads_running']}\n" );
+
                        return $status['Threads_connected'];
                } else {
                        return 0;
index 077eab0..e8104b6 100644 (file)
@@ -27,5 +27,4 @@
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
  */
 interface ORMIterator extends Iterator {
-
 }
index 160033c..e4efc01 100644 (file)
@@ -30,7 +30,6 @@
  */
 
 class ORMResult implements ORMIterator {
-
        /**
         * @var ResultWrapper
         */
@@ -119,5 +118,4 @@ class ORMResult implements ORMIterator {
        public function valid() {
                return $this->current !== false;
        }
-
 }
index 5ce3794..1d11202 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 class ORMRow implements IORMRow {
-
        /**
         * The fields of the object.
         * field name (w/o prefix) => value
@@ -130,8 +129,10 @@ class ORMRow implements IORMRow {
 
                        if ( $result !== false ) {
                                $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
+
                                return true;
                        }
+
                        return false;
                }
 
@@ -232,8 +233,7 @@ class ORMRow implements IORMRow {
         * @return boolean
         */
        public function hasIdField() {
-               return $this->hasField( 'id' )
-                       && !is_null( $this->getField( 'id' ) );
+               return $this->hasField( 'id' ) && !is_null( $this->getField( 'id' ) );
        }
 
        /**
@@ -252,7 +252,7 @@ class ORMRow implements IORMRow {
                                $value = $this->fields[$name];
 
                                // Skip null id fields so that the DBMS can set the default.
-                               if ( $name === 'id' && is_null ( $value ) ) {
+                               if ( $name === 'id' && is_null( $value ) ) {
                                        continue;
                                }
 
@@ -456,8 +456,9 @@ class ORMRow implements IORMRow {
 
        /**
         * Before removal of an object happens, @see beforeRemove gets called.
-        * This method loads the fields of which the names have been returned by this one (or all fields if null is returned).
-        * This allows for loading info needed after removal to get rid of linked data and the like.
+        * This method loads the fields of which the names have been returned by
+        * this one (or all fields if null is returned). This allows for loading
+        * info needed after removal to get rid of linked data and the like.
         *
         * @since 1.20
         *
@@ -552,7 +553,6 @@ class ORMRow implements IORMRow {
         * @param array|string|null $summaryFields
         */
        public function loadSummaryFields( $summaryFields = null ) {
-
        }
 
        /**
@@ -590,5 +590,4 @@ class ORMRow implements IORMRow {
        public function getTable() {
                return $this->table;
        }
-
 }
index 5f6723b..e47bc67 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 class ORMTable extends DBAccessBase implements IORMTable {
-
        /**
         * Cache for instances, used by the singleton method.
         *
@@ -96,7 +95,9 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @param string|null $rowClass
         * @param string $fieldPrefix
         */
-       public function __construct( $tableName = '', array $fields = array(), array $defaults = array(), $rowClass = null, $fieldPrefix = '' ) {
+       public function __construct( $tableName = '', array $fields = array(),
+               array $defaults = array(), $rowClass = null, $fieldPrefix = ''
+       ) {
                $this->tableName = $tableName;
                $this->fields = $fields;
                $this->defaults = $defaults;
@@ -201,8 +202,10 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @return ORMResult
         */
        public function select( $fields = null, array $conditions = array(),
-                                                       array $options = array(), $functionName = null ) {
+               array $options = array(), $functionName = null
+       ) {
                $res = $this->rawSelect( $fields, $conditions, $options, $functionName );
+
                return new ORMResult( $this, $res );
        }
 
@@ -221,7 +224,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @throws DBQueryError if the query failed (even if the database was in ignoreErrors mode).
         */
        public function selectObjects( $fields = null, array $conditions = array(),
-                                                                  array $options = array(), $functionName = null ) {
+               array $options = array(), $functionName = null
+       ) {
                $result = $this->selectFields( $fields, $conditions, $options, false, $functionName );
 
                $objects = array();
@@ -239,19 +243,19 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @since 1.20
         *
         * @param null|string|array $fields
-        * @param array             $conditions
-        * @param array             $options
-        * @param null|string       $functionName
+        * @param array $conditions
+        * @param array $options
+        * @param null|string $functionName
         *
         * @return ResultWrapper
         * @throws DBQueryError if the quey failed (even if the database was in ignoreErrors mode).
         */
        public function rawSelect( $fields = null, array $conditions = array(),
-                                                          array $options = array(), $functionName = null ) {
+               array $options = array(), $functionName = null
+       ) {
                if ( is_null( $fields ) ) {
                        $fields = array_keys( $this->getFields() );
-               }
-               else {
+               } else {
                        $fields = (array)$fields;
                }
 
@@ -313,7 +317,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @return array of array
         */
        public function selectFields( $fields = null, array $conditions = array(),
-                                                                 array $options = array(), $collapse = true, $functionName = null ) {
+               array $options = array(), $collapse = true, $functionName = null
+       ) {
                $objects = array();
 
                $result = $this->rawSelect( $fields, $conditions, $options, $functionName );
@@ -325,8 +330,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
                if ( $collapse ) {
                        if ( count( $fields ) === 1 ) {
                                $objects = array_map( 'array_shift', $objects );
-                       }
-                       elseif ( count( $fields ) === 2 ) {
+                       } elseif ( count( $fields ) === 2 ) {
                                $o = array();
 
                                foreach ( $objects as $object ) {
@@ -354,7 +358,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @return IORMRow|bool False on failure
         */
        public function selectRow( $fields = null, array $conditions = array(),
-                                                          array $options = array(), $functionName = null ) {
+               array $options = array(), $functionName = null
+       ) {
                $options['LIMIT'] = 1;
 
                $objects = $this->select( $fields, $conditions, $options, $functionName );
@@ -376,7 +381,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @return ResultWrapper
         */
        public function rawSelectRow( array $fields, array $conditions = array(),
-                                                                 array $options = array(), $functionName = null ) {
+               array $options = array(), $functionName = null
+       ) {
                $dbr = $this->getReadDbConnection();
 
                $result = $dbr->selectRow(
@@ -388,6 +394,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
                );
 
                $this->releaseConnection( $dbr );
+
                return $result;
        }
 
@@ -409,7 +416,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         * @return mixed|array|bool False on failure
         */
        public function selectFieldsRow( $fields = null, array $conditions = array(),
-                                                                        array $options = array(), $collapse = true, $functionName = null ) {
+               array $options = array(), $collapse = true, $functionName = null
+       ) {
                $options['LIMIT'] = 1;
 
                $objects = $this->selectFields( $fields, $conditions, $options, $collapse, $functionName );
@@ -491,6 +499,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
                ) !== false; // DatabaseBase::delete does not always return true for success as documented...
 
                $this->releaseConnection( $dbw );
+
                return $result;
        }
 
@@ -535,7 +544,9 @@ class ORMTable extends DBAccessBase implements IORMTable {
                        }
 
                        if ( $setDefaults && $hasDefault ) {
-                               $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
+                               $default = is_array( $defaults[$field] )
+                                       ? implode( '|', $defaults[$field] )
+                                       : $defaults[$field];
                                $params[$field][ApiBase::PARAM_DFLT] = $default;
                        }
                }
@@ -568,7 +579,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Set the database ID to use for read operations, use DB_XXX constants or an index to the load balancer setup.
+        * Set the database ID to use for read operations, use DB_XXX constants or
+        *   an index to the load balancer setup.
         *
         * @param integer $db
         *
@@ -583,7 +595,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
         *
         * @since 1.20
         *
-        * @return String|bool The target wiki, in a form that  LBFactory understands (or false if the local wiki is used)
+        * @return String|bool The target wiki, in a form that LBFactory understands
+        *   (or false if the local wiki is used)
         */
        public function getTargetWiki() {
                return $this->wiki;
@@ -592,7 +605,8 @@ class ORMTable extends DBAccessBase implements IORMTable {
        /**
         * Set the ID of the any foreign wiki to use as a target for database operations
         *
-        * @param string|bool $wiki The target wiki, in a form that  LBFactory understands (or false if the local wiki shall be used)
+        * @param string|bool $wiki The target wiki, in a form that  LBFactory
+        *   understands (or false if the local wiki shall be used)
         *
         * @since 1.20
         */
@@ -638,9 +652,11 @@ class ORMTable extends DBAccessBase implements IORMTable {
         *
         * @since 1.20
         */
+       // @codingStandardsIgnoreStart Suppress "useless method overriding" sniffer warning
        public function releaseConnection( DatabaseBase $db ) {
                parent::releaseConnection( $db ); // just make it public
        }
+       // @codingStandardsIgnoreEnd
 
        /**
         * Update the records matching the provided conditions by
@@ -665,6 +681,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
                ) !== false; // DatabaseBase::update does not always return true for success as documented...
 
                $this->releaseConnection( $dbw );
+
                return $result;
        }
 
@@ -711,8 +728,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
                                if ( is_array( $value ) ) {
                                        $field = $value[0];
                                        $value = $value[1];
-                               }
-                               else {
+                               } else {
                                        $value = explode( ' ', $value, 2 );
                                        $value[0] = $this->getPrefixedField( $value[0] );
                                        $prefixedValues[] = implode( ' ', $value );
@@ -1103,5 +1119,4 @@ class ORMTable extends DBAccessBase implements IORMTable {
 
                return $success;
        }
-
 }
index 6e9ccc4..d0f8916 100644 (file)
@@ -31,7 +31,6 @@
  * @since 1.19
  */
 class MWDebug {
-
        /**
         * Log lines
         *
@@ -185,7 +184,9 @@ class MWDebug {
         *    MWDebug::deprecated() (Added in 1.20).
         * @return mixed
         */
-       public static function deprecated( $function, $version = false, $component = false, $callerOffset = 2 ) {
+       public static function deprecated( $function, $version = false,
+               $component = false, $callerOffset = 2
+       ) {
                $callerDescription = self::getCallerDescription( $callerOffset );
                $callerFunc = $callerDescription['func'];
 
@@ -227,7 +228,11 @@ class MWDebug {
 
                if ( $sendToLog ) {
                        global $wgDevelopmentWarnings; // we could have a more specific $wgDeprecationWarnings setting.
-                       self::sendWarning( $msg, $callerDescription, $wgDevelopmentWarnings ? E_USER_DEPRECATED : false );
+                       self::sendWarning(
+                               $msg,
+                               $callerDescription,
+                               $wgDevelopmentWarnings ? E_USER_DEPRECATED : false
+                       );
                }
 
                if ( self::$enabled ) {
@@ -445,10 +450,15 @@ class MWDebug {
                                $display = "\xc2\xa0";
                        }
 
-                       if ( !$ident && $diff < 0 && substr( $display, 0, 9 ) != 'Entering ' && substr( $display, 0, 8 ) != 'Exiting ' ) {
+                       if ( !$ident
+                               && $diff < 0
+                               && substr( $display, 0, 9 ) != 'Entering '
+                               && substr( $display, 0, 8 ) != 'Exiting '
+                       ) {
                                $ident = $curIdent;
                                $diff = 0;
-                               $display = '<span style="background:yellow;">' . nl2br( htmlspecialchars( $display ) ) . '</span>';
+                               $display = '<span style="background:yellow;">' .
+                                       nl2br( htmlspecialchars( $display ) ) . '</span>';
                        } else {
                                $display = nl2br( htmlspecialchars( $display ) );
                        }
@@ -460,7 +470,7 @@ class MWDebug {
                        } else {
                                $ret .= str_repeat( "<ul><li>\n", $diff );
                        }
-                       $ret .= "<tt>$display</tt>\n";
+                       $ret .= "<code>$display</code>\n";
 
                        $curIdent = $ident;
                }
@@ -517,6 +527,7 @@ class MWDebug {
 
                global $wgVersion, $wgRequestTime;
                $request = $context->getRequest();
+
                return array(
                        'mwVersion' => $wgVersion,
                        'phpVersion' => PHP_VERSION,
diff --git a/includes/deferred/CallableUpdate.php b/includes/deferred/CallableUpdate.php
new file mode 100644 (file)
index 0000000..f0569dd
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * Deferrable Update for closure/callback
+ */
+class MWCallableUpdate implements DeferrableUpdate {
+       /**
+        * @var closure/callback
+        */
+       private $callback;
+
+       /**
+        * @param callable $callback
+        * @throws MWException
+        */
+       public function __construct( $callback ) {
+               if ( !is_callable( $callback ) ) {
+                       throw new MWException( 'Not a valid callback/closure!' );
+               }
+               $this->callback = $callback;
+       }
+
+       /**
+        * Run the update
+        */
+       public function doUpdate() {
+               call_user_func( $this->callback );
+       }
+}
diff --git a/includes/deferred/DataUpdate.php b/includes/deferred/DataUpdate.php
new file mode 100644 (file)
index 0000000..986a1f7
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/**
+ * Base code for update jobs that do something with some secondary
+ * data extracted from article.
+ *
+ * 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
+ */
+
+/**
+ * Abstract base class for update jobs that do something with some secondary
+ * data extracted from article.
+ *
+ * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
+ *        a transaction will automatically be wrapped around the update. If need be,
+ *        subclasses can override the beginTransaction() and commitTransaction() methods.
+ */
+abstract class DataUpdate implements DeferrableUpdate {
+       /**
+        * Constructor
+        */
+       public function __construct() {
+               # noop
+       }
+
+       /**
+        * Begin an appropriate transaction, if any.
+        * This default implementation does nothing.
+        */
+       public function beginTransaction() {
+               //noop
+       }
+
+       /**
+        * Commit the transaction started via beginTransaction, if any.
+        * This default implementation does nothing.
+        */
+       public function commitTransaction() {
+               //noop
+       }
+
+       /**
+        * Abort / roll back the transaction started via beginTransaction, if any.
+        * This default implementation does nothing.
+        */
+       public function rollbackTransaction() {
+               //noop
+       }
+
+       /**
+        * Convenience method, calls doUpdate() on every DataUpdate in the array.
+        *
+        * This methods supports transactions logic by first calling beginTransaction()
+        * on all updates in the array, then calling doUpdate() on each, and, if all goes well,
+        * then calling commitTransaction() on each update. If an error occurs,
+        * rollbackTransaction() will be called on any update object that had beginTransaction()
+        * called but not yet commitTransaction().
+        *
+        * This allows for limited transactional logic across multiple backends for storing
+        * secondary data.
+        *
+        * @param array $updates a list of DataUpdate instances
+        * @throws Exception|null
+        */
+       public static function runUpdates( $updates ) {
+               if ( empty( $updates ) ) {
+                       return; # nothing to do
+               }
+
+               $open_transactions = array();
+               $exception = null;
+
+               /**
+                * @var $update DataUpdate
+                * @var $trans DataUpdate
+                */
+
+               try {
+                       // begin transactions
+                       foreach ( $updates as $update ) {
+                               $update->beginTransaction();
+                               $open_transactions[] = $update;
+                       }
+
+                       // do work
+                       foreach ( $updates as $update ) {
+                               $update->doUpdate();
+                       }
+
+                       // commit transactions
+                       while ( count( $open_transactions ) > 0 ) {
+                               $trans = array_pop( $open_transactions );
+                               $trans->commitTransaction();
+                       }
+               } catch ( Exception $ex ) {
+                       $exception = $ex;
+                       wfDebug( "Caught exception, will rethrow after rollback: " . $ex->getMessage() );
+               }
+
+               // rollback remaining transactions
+               while ( count( $open_transactions ) > 0 ) {
+                       $trans = array_pop( $open_transactions );
+                       $trans->rollbackTransaction();
+               }
+
+               if ( $exception ) {
+                       throw $exception; // rethrow after cleanup
+               }
+       }
+}
diff --git a/includes/deferred/DeferredUpdates.php b/includes/deferred/DeferredUpdates.php
new file mode 100644 (file)
index 0000000..5cf0d2b
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Interface and manager for deferred updates.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Interface that deferrable updates should implement. Basically required so we
+ * can validate input on DeferredUpdates::addUpdate()
+ *
+ * @since 1.19
+ */
+interface DeferrableUpdate {
+       /**
+        * Perform the actual work
+        */
+       function doUpdate();
+}
+
+/**
+ * Class for managing the deferred updates.
+ *
+ * @since 1.19
+ */
+class DeferredUpdates {
+       /**
+        * Store of updates to be deferred until the end of the request.
+        */
+       private static $updates = array();
+
+       /**
+        * Add an update to the deferred list
+        * @param DeferrableUpdate $update Some object that implements doUpdate()
+        */
+       public static function addUpdate( DeferrableUpdate $update ) {
+               array_push( self::$updates, $update );
+       }
+
+       /**
+        * HTMLCacheUpdates are the most common deferred update people use. This
+        * is a shortcut method for that.
+        * @see HTMLCacheUpdate::__construct()
+        * @param Title $title
+        * @param string $table
+        */
+       public static function addHTMLCacheUpdate( $title, $table ) {
+               self::addUpdate( new HTMLCacheUpdate( $title, $table ) );
+       }
+
+       /**
+        * Add a callable update.  In a lot of cases, we just need a callback/closure,
+        * defining a new DeferrableUpdate object is not necessary
+        * @see MWCallableUpdate::__construct()
+        * @param callable $callable
+        */
+       public static function addCallableUpdate( $callable ) {
+               self::addUpdate( new MWCallableUpdate( $callable ) );
+       }
+
+       /**
+        * Do any deferred updates and clear the list
+        *
+        * @param string $commit set to 'commit' to commit after every update to
+        *   prevent lock contention
+        */
+       public static function doUpdates( $commit = '' ) {
+               global $wgDeferredUpdateList;
+
+               wfProfileIn( __METHOD__ );
+
+               $updates = array_merge( $wgDeferredUpdateList, self::$updates );
+
+               // No need to get master connections in case of empty updates array
+               if ( !count( $updates ) ) {
+                       wfProfileOut( __METHOD__ );
+
+                       return;
+               }
+
+               $dbw = false;
+               $doCommit = $commit == 'commit';
+               if ( $doCommit ) {
+                       $dbw = wfGetDB( DB_MASTER );
+               }
+
+               /** @var DeferrableUpdate $update */
+               foreach ( $updates as $update ) {
+                       try {
+                               $update->doUpdate();
+
+                               if ( $doCommit && $dbw->trxLevel() ) {
+                                       $dbw->commit( __METHOD__, 'flush' );
+                               }
+                       } catch ( MWException $e ) {
+                               // We don't want exceptions thrown during deferred updates to
+                               // be reported to the user since the output is already sent.
+                               // Instead we just log them.
+                               if ( !$e instanceof ErrorPageError ) {
+                                       MWExceptionHandler::logException( $e );
+                               }
+                       }
+               }
+
+               self::clearPendingUpdates();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Clear all pending updates without performing them. Generally, you don't
+        * want or need to call this. Unit tests need it though.
+        */
+       public static function clearPendingUpdates() {
+               global $wgDeferredUpdateList;
+               $wgDeferredUpdateList = self::$updates = array();
+       }
+}
diff --git a/includes/deferred/HTMLCacheUpdate.php b/includes/deferred/HTMLCacheUpdate.php
new file mode 100644 (file)
index 0000000..0713a05
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * HTML cache invalidation of all pages linking to a given title.
+ *
+ * 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 Cache
+ */
+
+/**
+ * Class to invalidate the HTML cache of all the pages linking to a given title.
+ *
+ * @ingroup Cache
+ */
+class HTMLCacheUpdate implements DeferrableUpdate {
+       /** @var Title */
+       public $mTitle;
+
+       /** @var string */
+       public $mTable;
+
+       /**
+        * @param Title $titleTo
+        * @param string $table
+        */
+       function __construct( Title $titleTo, $table ) {
+               $this->mTitle = $titleTo;
+               $this->mTable = $table;
+       }
+
+       public function doUpdate() {
+               wfProfileIn( __METHOD__ );
+
+               $job = new HTMLCacheUpdateJob(
+                       $this->mTitle,
+                       array(
+                               'table' => $this->mTable,
+                       ) + Job::newRootJobParams( // "overall" refresh links job info
+                               "htmlCacheUpdate:{$this->mTable}:{$this->mTitle->getPrefixedText()}"
+                       )
+               );
+
+               $count = $this->mTitle->getBacklinkCache()->getNumLinks( $this->mTable, 200 );
+               if ( $count >= 200 ) { // many backlinks
+                       JobQueueGroup::singleton()->push( $job );
+                       JobQueueGroup::singleton()->deduplicateRootJob( $job );
+               } else { // few backlinks ($count might be off even if 0)
+                       $dbw = wfGetDB( DB_MASTER );
+                       $dbw->onTransactionIdle( function () use ( $job ) {
+                               $job->run(); // just do the purge query now
+                       } );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+}
diff --git a/includes/deferred/LinksUpdate.php b/includes/deferred/LinksUpdate.php
new file mode 100644 (file)
index 0000000..9cd7708
--- /dev/null
@@ -0,0 +1,942 @@
+<?php
+/**
+ * Updater for link tracking tables after a page edit.
+ *
+ * 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
+ */
+
+/**
+ * See docs/deferred.txt
+ *
+ * @todo document (e.g. one-sentence top-level class description).
+ */
+class LinksUpdate extends SqlDataUpdate {
+       // @todo make members protected, but make sure extensions don't break
+
+       /** @var int Page ID of the article linked from */
+       public $mId;
+
+       /** @var Title object of the article linked from */
+       public $mTitle;
+
+       /** @var ParserOutput */
+       public $mParserOutput;
+
+       /** @var array Map of title strings to IDs for the links in the document */
+       public $mLinks;
+
+       /** @var array DB keys of the images used, in the array key only */
+       public $mImages;
+
+       /** @var array Map of title strings to IDs for the template references, including broken ones */
+       public $mTemplates;
+
+       /** @var array URLs of external links, array key only */
+       public $mExternals;
+
+       /** @var array Map of category names to sort keys */
+       public $mCategories;
+
+       /** @var array ap of language codes to titles */
+       public $mInterlangs;
+
+       /** @var array Map of arbitrary name to value */
+       public $mProperties;
+
+       /** @var DatabaseBase Database connection reference */
+       public $mDb;
+
+       /** @var array SELECT options to be used */
+       public $mOptions;
+
+       /** @var bool Whether to queue jobs for recursive updates */
+       public $mRecursive;
+
+       /**
+        * @var null|array Added links if calculated.
+        */
+       private $linkInsertions = null;
+
+       /**
+        * @var null|array Deleted links if calculated.
+        */
+       private $linkDeletions = null;
+
+       /**
+        * Constructor
+        *
+        * @param Title $title Title of the page we're updating
+        * @param ParserOutput $parserOutput Output from a full parse of this page
+        * @param bool $recursive Queue jobs for recursive updates?
+        * @throws MWException
+        */
+       function __construct( $title, $parserOutput, $recursive = true ) {
+               parent::__construct( false ); // no implicit transaction
+
+               if ( !( $title instanceof Title ) ) {
+                       throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
+                               "Please see Article::editUpdates() for an invocation example.\n" );
+               }
+
+               if ( !( $parserOutput instanceof ParserOutput ) ) {
+                       throw new MWException( "The calling convention to LinksUpdate::__construct() has changed. " .
+                               "Please see WikiPage::doEditUpdates() for an invocation example.\n" );
+               }
+
+               $this->mTitle = $title;
+               $this->mId = $title->getArticleID();
+
+               if ( !$this->mId ) {
+                       throw new MWException( "The Title object did not provide an article " .
+                               "ID. Perhaps the page doesn't exist?" );
+               }
+
+               $this->mParserOutput = $parserOutput;
+
+               $this->mLinks = $parserOutput->getLinks();
+               $this->mImages = $parserOutput->getImages();
+               $this->mTemplates = $parserOutput->getTemplates();
+               $this->mExternals = $parserOutput->getExternalLinks();
+               $this->mCategories = $parserOutput->getCategories();
+               $this->mProperties = $parserOutput->getProperties();
+               $this->mInterwikis = $parserOutput->getInterwikiLinks();
+
+               # Convert the format of the interlanguage links
+               # I didn't want to change it in the ParserOutput, because that array is passed all
+               # the way back to the skin, so either a skin API break would be required, or an
+               # inefficient back-conversion.
+               $ill = $parserOutput->getLanguageLinks();
+               $this->mInterlangs = array();
+               foreach ( $ill as $link ) {
+                       list( $key, $title ) = explode( ':', $link, 2 );
+                       $this->mInterlangs[$key] = $title;
+               }
+
+               foreach ( $this->mCategories as &$sortkey ) {
+                       # If the sortkey is longer then 255 bytes,
+                       # it truncated by DB, and then doesn't get
+                       # matched when comparing existing vs current
+                       # categories, causing bug 25254.
+                       # Also. substr behaves weird when given "".
+                       if ( $sortkey !== '' ) {
+                               $sortkey = substr( $sortkey, 0, 255 );
+                       }
+               }
+
+               $this->mRecursive = $recursive;
+
+               wfRunHooks( 'LinksUpdateConstructed', array( &$this ) );
+       }
+
+       /**
+        * Update link tables with outgoing links from an updated article
+        */
+       public function doUpdate() {
+               wfRunHooks( 'LinksUpdate', array( &$this ) );
+               $this->doIncrementalUpdate();
+               wfRunHooks( 'LinksUpdateComplete', array( &$this ) );
+       }
+
+       protected function doIncrementalUpdate() {
+               wfProfileIn( __METHOD__ );
+
+               # Page links
+               $existing = $this->getExistingLinks();
+               $this->linkDeletions = $this->getLinkDeletions( $existing );
+               $this->linkInsertions = $this->getLinkInsertions( $existing );
+               $this->incrTableUpdate( 'pagelinks', 'pl', $this->linkDeletions, $this->linkInsertions );
+
+               # Image links
+               $existing = $this->getExistingImages();
+
+               $imageDeletes = $this->getImageDeletions( $existing );
+               $this->incrTableUpdate( 'imagelinks', 'il', $imageDeletes,
+                       $this->getImageInsertions( $existing ) );
+
+               # Invalidate all image description pages which had links added or removed
+               $imageUpdates = $imageDeletes + array_diff_key( $this->mImages, $existing );
+               $this->invalidateImageDescriptions( $imageUpdates );
+
+               # External links
+               $existing = $this->getExistingExternals();
+               $this->incrTableUpdate( 'externallinks', 'el', $this->getExternalDeletions( $existing ),
+                       $this->getExternalInsertions( $existing ) );
+
+               # Language links
+               $existing = $this->getExistingInterlangs();
+               $this->incrTableUpdate( 'langlinks', 'll', $this->getInterlangDeletions( $existing ),
+                       $this->getInterlangInsertions( $existing ) );
+
+               # Inline interwiki links
+               $existing = $this->getExistingInterwikis();
+               $this->incrTableUpdate( 'iwlinks', 'iwl', $this->getInterwikiDeletions( $existing ),
+                       $this->getInterwikiInsertions( $existing ) );
+
+               # Template links
+               $existing = $this->getExistingTemplates();
+               $this->incrTableUpdate( 'templatelinks', 'tl', $this->getTemplateDeletions( $existing ),
+                       $this->getTemplateInsertions( $existing ) );
+
+               # Category links
+               $existing = $this->getExistingCategories();
+
+               $categoryDeletes = $this->getCategoryDeletions( $existing );
+
+               $this->incrTableUpdate( 'categorylinks', 'cl', $categoryDeletes,
+                       $this->getCategoryInsertions( $existing ) );
+
+               # Invalidate all categories which were added, deleted or changed (set symmetric difference)
+               $categoryInserts = array_diff_assoc( $this->mCategories, $existing );
+               $categoryUpdates = $categoryInserts + $categoryDeletes;
+               $this->invalidateCategories( $categoryUpdates );
+               $this->updateCategoryCounts( $categoryInserts, $categoryDeletes );
+
+               # Page properties
+               $existing = $this->getExistingProperties();
+
+               $propertiesDeletes = $this->getPropertyDeletions( $existing );
+
+               $this->incrTableUpdate( 'page_props', 'pp', $propertiesDeletes,
+                       $this->getPropertyInsertions( $existing ) );
+
+               # Invalidate the necessary pages
+               $changed = $propertiesDeletes + array_diff_assoc( $this->mProperties, $existing );
+               $this->invalidateProperties( $changed );
+
+               # Refresh links of all pages including this page
+               # This will be in a separate transaction
+               if ( $this->mRecursive ) {
+                       $this->queueRecursiveJobs();
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Queue recursive jobs for this page
+        *
+        * Which means do LinksUpdate on all templates
+        * that include the current page, using the job queue.
+        */
+       function queueRecursiveJobs() {
+               self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
+       }
+
+       /**
+        * Queue a RefreshLinks job for any table.
+        *
+        * @param Title $title Title to do job for
+        * @param string $table Table to use (e.g. 'templatelinks')
+        */
+       public static function queueRecursiveJobsForTable( Title $title, $table ) {
+               wfProfileIn( __METHOD__ );
+               if ( $title->getBacklinkCache()->hasLinks( $table ) ) {
+                       $job = new RefreshLinksJob(
+                               $title,
+                               array(
+                                       'table'     => $table,
+                                       'recursive' => true,
+                               ) + Job::newRootJobParams( // "overall" refresh links job info
+                                       "refreshlinks:{$table}:{$title->getPrefixedText()}"
+                               )
+                       );
+                       JobQueueGroup::singleton()->push( $job );
+                       JobQueueGroup::singleton()->deduplicateRootJob( $job );
+               }
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @param $cats
+        */
+       function invalidateCategories( $cats ) {
+               $this->invalidatePages( NS_CATEGORY, array_keys( $cats ) );
+       }
+
+       /**
+        * Update all the appropriate counts in the category table.
+        * @param array $added Associative array of category name => sort key
+        * @param array $deleted Associative array of category name => sort key
+        */
+       function updateCategoryCounts( $added, $deleted ) {
+               $a = WikiPage::factory( $this->mTitle );
+               $a->updateCategoryCounts(
+                       array_keys( $added ), array_keys( $deleted )
+               );
+       }
+
+       /**
+        * @param $images
+        */
+       function invalidateImageDescriptions( $images ) {
+               $this->invalidatePages( NS_FILE, array_keys( $images ) );
+       }
+
+       /**
+        * Update a table by doing a delete query then an insert query
+        * @param string $table Table name
+        * @param string $prefix Field name prefix
+        * @param array $deletions
+        * @param array $insertions Rows to insert
+        */
+       function incrTableUpdate( $table, $prefix, $deletions, $insertions ) {
+               if ( $table == 'page_props' ) {
+                       $fromField = 'pp_page';
+               } else {
+                       $fromField = "{$prefix}_from";
+               }
+               $where = array( $fromField => $this->mId );
+               if ( $table == 'pagelinks' || $table == 'templatelinks' || $table == 'iwlinks' ) {
+                       if ( $table == 'iwlinks' ) {
+                               $baseKey = 'iwl_prefix';
+                       } else {
+                               $baseKey = "{$prefix}_namespace";
+                       }
+                       $clause = $this->mDb->makeWhereFrom2d( $deletions, $baseKey, "{$prefix}_title" );
+                       if ( $clause ) {
+                               $where[] = $clause;
+                       } else {
+                               $where = false;
+                       }
+               } else {
+                       if ( $table == 'langlinks' ) {
+                               $toField = 'll_lang';
+                       } elseif ( $table == 'page_props' ) {
+                               $toField = 'pp_propname';
+                       } else {
+                               $toField = $prefix . '_to';
+                       }
+                       if ( count( $deletions ) ) {
+                               $where[] = "$toField IN (" . $this->mDb->makeList( array_keys( $deletions ) ) . ')';
+                       } else {
+                               $where = false;
+                       }
+               }
+               if ( $where ) {
+                       $this->mDb->delete( $table, $where, __METHOD__ );
+               }
+               if ( count( $insertions ) ) {
+                       $this->mDb->insert( $table, $insertions, __METHOD__, 'IGNORE' );
+                       wfRunHooks( 'LinksUpdateAfterInsert', array( $this, $table, $insertions ) );
+               }
+       }
+
+       /**
+        * Get an array of pagelinks insertions for passing to the DB
+        * Skips the titles specified by the 2-D array $existing
+        * @param array $existing
+        * @return array
+        */
+       private function getLinkInsertions( $existing = array() ) {
+               $arr = array();
+               foreach ( $this->mLinks as $ns => $dbkeys ) {
+                       $diffs = isset( $existing[$ns] )
+                               ? array_diff_key( $dbkeys, $existing[$ns] )
+                               : $dbkeys;
+                       foreach ( $diffs as $dbk => $id ) {
+                               $arr[] = array(
+                                       'pl_from' => $this->mId,
+                                       'pl_namespace' => $ns,
+                                       'pl_title' => $dbk
+                               );
+                       }
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of template insertions. Like getLinkInsertions()
+        * @param array $existing
+        * @return array
+        */
+       private function getTemplateInsertions( $existing = array() ) {
+               $arr = array();
+               foreach ( $this->mTemplates as $ns => $dbkeys ) {
+                       $diffs = isset( $existing[$ns] ) ? array_diff_key( $dbkeys, $existing[$ns] ) : $dbkeys;
+                       foreach ( $diffs as $dbk => $id ) {
+                               $arr[] = array(
+                                       'tl_from' => $this->mId,
+                                       'tl_namespace' => $ns,
+                                       'tl_title' => $dbk
+                               );
+                       }
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of image insertions
+        * Skips the names specified in $existing
+        * @param array $existing
+        * @return array
+        */
+       private function getImageInsertions( $existing = array() ) {
+               $arr = array();
+               $diffs = array_diff_key( $this->mImages, $existing );
+               foreach ( $diffs as $iname => $dummy ) {
+                       $arr[] = array(
+                               'il_from' => $this->mId,
+                               'il_to' => $iname
+                       );
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of externallinks insertions. Skips the names specified in $existing
+        * @param array $existing
+        * @return array
+        */
+       private function getExternalInsertions( $existing = array() ) {
+               $arr = array();
+               $diffs = array_diff_key( $this->mExternals, $existing );
+               foreach ( $diffs as $url => $dummy ) {
+                       foreach ( wfMakeUrlIndexes( $url ) as $index ) {
+                               $arr[] = array(
+                                       'el_from' => $this->mId,
+                                       'el_to' => $url,
+                                       'el_index' => $index,
+                               );
+                       }
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of category insertions
+        *
+        * @param array $existing mapping existing category names to sort keys. If both
+        * match a link in $this, the link will be omitted from the output
+        *
+        * @return array
+        */
+       private function getCategoryInsertions( $existing = array() ) {
+               global $wgContLang, $wgCategoryCollation;
+               $diffs = array_diff_assoc( $this->mCategories, $existing );
+               $arr = array();
+               foreach ( $diffs as $name => $prefix ) {
+                       $nt = Title::makeTitleSafe( NS_CATEGORY, $name );
+                       $wgContLang->findVariantLink( $name, $nt, true );
+
+                       if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
+                               $type = 'subcat';
+                       } elseif ( $this->mTitle->getNamespace() == NS_FILE ) {
+                               $type = 'file';
+                       } else {
+                               $type = 'page';
+                       }
+
+                       # Treat custom sortkeys as a prefix, so that if multiple
+                       # things are forced to sort as '*' or something, they'll
+                       # sort properly in the category rather than in page_id
+                       # order or such.
+                       $sortkey = Collation::singleton()->getSortKey(
+                               $this->mTitle->getCategorySortkey( $prefix ) );
+
+                       $arr[] = array(
+                               'cl_from' => $this->mId,
+                               'cl_to' => $name,
+                               'cl_sortkey' => $sortkey,
+                               'cl_timestamp' => $this->mDb->timestamp(),
+                               'cl_sortkey_prefix' => $prefix,
+                               'cl_collation' => $wgCategoryCollation,
+                               'cl_type' => $type,
+                       );
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of interlanguage link insertions
+        *
+        * @param array $existing mapping existing language codes to titles
+        *
+        * @return array
+        */
+       private function getInterlangInsertions( $existing = array() ) {
+               $diffs = array_diff_assoc( $this->mInterlangs, $existing );
+               $arr = array();
+               foreach ( $diffs as $lang => $title ) {
+                       $arr[] = array(
+                               'll_from' => $this->mId,
+                               'll_lang' => $lang,
+                               'll_title' => $title
+                       );
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of page property insertions
+        * @param array $existing
+        * @return array
+        */
+       function getPropertyInsertions( $existing = array() ) {
+               $diffs = array_diff_assoc( $this->mProperties, $existing );
+               $arr = array();
+               foreach ( $diffs as $name => $value ) {
+                       $arr[] = array(
+                               'pp_page' => $this->mId,
+                               'pp_propname' => $name,
+                               'pp_value' => $value,
+                       );
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of interwiki insertions for passing to the DB
+        * Skips the titles specified by the 2-D array $existing
+        * @param array $existing
+        * @return array
+        */
+       private function getInterwikiInsertions( $existing = array() ) {
+               $arr = array();
+               foreach ( $this->mInterwikis as $prefix => $dbkeys ) {
+                       $diffs = isset( $existing[$prefix] )
+                               ? array_diff_key( $dbkeys, $existing[$prefix] )
+                               : $dbkeys;
+
+                       foreach ( $diffs as $dbk => $id ) {
+                               $arr[] = array(
+                                       'iwl_from' => $this->mId,
+                                       'iwl_prefix' => $prefix,
+                                       'iwl_title' => $dbk
+                               );
+                       }
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Given an array of existing links, returns those links which are not in $this
+        * and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getLinkDeletions( $existing ) {
+               $del = array();
+               foreach ( $existing as $ns => $dbkeys ) {
+                       if ( isset( $this->mLinks[$ns] ) ) {
+                               $del[$ns] = array_diff_key( $existing[$ns], $this->mLinks[$ns] );
+                       } else {
+                               $del[$ns] = $existing[$ns];
+                       }
+               }
+
+               return $del;
+       }
+
+       /**
+        * Given an array of existing templates, returns those templates which are not in $this
+        * and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getTemplateDeletions( $existing ) {
+               $del = array();
+               foreach ( $existing as $ns => $dbkeys ) {
+                       if ( isset( $this->mTemplates[$ns] ) ) {
+                               $del[$ns] = array_diff_key( $existing[$ns], $this->mTemplates[$ns] );
+                       } else {
+                               $del[$ns] = $existing[$ns];
+                       }
+               }
+
+               return $del;
+       }
+
+       /**
+        * Given an array of existing images, returns those images which are not in $this
+        * and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getImageDeletions( $existing ) {
+               return array_diff_key( $existing, $this->mImages );
+       }
+
+       /**
+        * Given an array of existing external links, returns those links which are not
+        * in $this and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getExternalDeletions( $existing ) {
+               return array_diff_key( $existing, $this->mExternals );
+       }
+
+       /**
+        * Given an array of existing categories, returns those categories which are not in $this
+        * and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getCategoryDeletions( $existing ) {
+               return array_diff_assoc( $existing, $this->mCategories );
+       }
+
+       /**
+        * Given an array of existing interlanguage links, returns those links which are not
+        * in $this and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getInterlangDeletions( $existing ) {
+               return array_diff_assoc( $existing, $this->mInterlangs );
+       }
+
+       /**
+        * Get array of properties which should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       function getPropertyDeletions( $existing ) {
+               return array_diff_assoc( $existing, $this->mProperties );
+       }
+
+       /**
+        * Given an array of existing interwiki links, returns those links which are not in $this
+        * and thus should be deleted.
+        * @param array $existing
+        * @return array
+        */
+       private function getInterwikiDeletions( $existing ) {
+               $del = array();
+               foreach ( $existing as $prefix => $dbkeys ) {
+                       if ( isset( $this->mInterwikis[$prefix] ) ) {
+                               $del[$prefix] = array_diff_key( $existing[$prefix], $this->mInterwikis[$prefix] );
+                       } else {
+                               $del[$prefix] = $existing[$prefix];
+                       }
+               }
+
+               return $del;
+       }
+
+       /**
+        * Get an array of existing links, as a 2-D array
+        *
+        * @return array
+        */
+       private function getExistingLinks() {
+               $res = $this->mDb->select( 'pagelinks', array( 'pl_namespace', 'pl_title' ),
+                       array( 'pl_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       if ( !isset( $arr[$row->pl_namespace] ) ) {
+                               $arr[$row->pl_namespace] = array();
+                       }
+                       $arr[$row->pl_namespace][$row->pl_title] = 1;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing templates, as a 2-D array
+        *
+        * @return array
+        */
+       private function getExistingTemplates() {
+               $res = $this->mDb->select( 'templatelinks', array( 'tl_namespace', 'tl_title' ),
+                       array( 'tl_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       if ( !isset( $arr[$row->tl_namespace] ) ) {
+                               $arr[$row->tl_namespace] = array();
+                       }
+                       $arr[$row->tl_namespace][$row->tl_title] = 1;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing images, image names in the keys
+        *
+        * @return array
+        */
+       private function getExistingImages() {
+               $res = $this->mDb->select( 'imagelinks', array( 'il_to' ),
+                       array( 'il_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       $arr[$row->il_to] = 1;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing external links, URLs in the keys
+        *
+        * @return array
+        */
+       private function getExistingExternals() {
+               $res = $this->mDb->select( 'externallinks', array( 'el_to' ),
+                       array( 'el_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       $arr[$row->el_to] = 1;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing categories, with the name in the key and sort key in the value.
+        *
+        * @return array
+        */
+       private function getExistingCategories() {
+               $res = $this->mDb->select( 'categorylinks', array( 'cl_to', 'cl_sortkey_prefix' ),
+                       array( 'cl_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       $arr[$row->cl_to] = $row->cl_sortkey_prefix;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing interlanguage links, with the language code in the key and the
+        * title in the value.
+        *
+        * @return array
+        */
+       private function getExistingInterlangs() {
+               $res = $this->mDb->select( 'langlinks', array( 'll_lang', 'll_title' ),
+                       array( 'll_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       $arr[$row->ll_lang] = $row->ll_title;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing inline interwiki links, as a 2-D array
+        * @return array (prefix => array(dbkey => 1))
+        */
+       protected function getExistingInterwikis() {
+               $res = $this->mDb->select( 'iwlinks', array( 'iwl_prefix', 'iwl_title' ),
+                       array( 'iwl_from' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       if ( !isset( $arr[$row->iwl_prefix] ) ) {
+                               $arr[$row->iwl_prefix] = array();
+                       }
+                       $arr[$row->iwl_prefix][$row->iwl_title] = 1;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Get an array of existing categories, with the name in the key and sort key in the value.
+        *
+        * @return array of property names and values
+        */
+       private function getExistingProperties() {
+               $res = $this->mDb->select( 'page_props', array( 'pp_propname', 'pp_value' ),
+                       array( 'pp_page' => $this->mId ), __METHOD__, $this->mOptions );
+               $arr = array();
+               foreach ( $res as $row ) {
+                       $arr[$row->pp_propname] = $row->pp_value;
+               }
+
+               return $arr;
+       }
+
+       /**
+        * Return the title object of the page being updated
+        * @return Title
+        */
+       public function getTitle() {
+               return $this->mTitle;
+       }
+
+       /**
+        * Returns parser output
+        * @since 1.19
+        * @return ParserOutput
+        */
+       public function getParserOutput() {
+               return $this->mParserOutput;
+       }
+
+       /**
+        * Return the list of images used as generated by the parser
+        * @return array
+        */
+       public function getImages() {
+               return $this->mImages;
+       }
+
+       /**
+        * Invalidate any necessary link lists related to page property changes
+        * @param array $changed
+        */
+       private function invalidateProperties( $changed ) {
+               global $wgPagePropLinkInvalidations;
+
+               foreach ( $changed as $name => $value ) {
+                       if ( isset( $wgPagePropLinkInvalidations[$name] ) ) {
+                               $inv = $wgPagePropLinkInvalidations[$name];
+                               if ( !is_array( $inv ) ) {
+                                       $inv = array( $inv );
+                               }
+                               foreach ( $inv as $table ) {
+                                       $update = new HTMLCacheUpdate( $this->mTitle, $table );
+                                       $update->doUpdate();
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Fetch page links added by this LinksUpdate.  Only available after the update is complete.
+        * @since 1.22
+        * @return null|array of Titles
+        */
+       public function getAddedLinks() {
+               if ( $this->linkInsertions === null ) {
+                       return null;
+               }
+               $result = array();
+               foreach ( $this->linkInsertions as $insertion ) {
+                       $result[] = Title::makeTitle( $insertion['pl_namespace'], $insertion['pl_title'] );
+               }
+
+               return $result;
+       }
+
+       /**
+        * Fetch page links removed by this LinksUpdate.  Only available after the update is complete.
+        * @since 1.22
+        * @return null|array of Titles
+        */
+       public function getRemovedLinks() {
+               if ( $this->linkDeletions === null ) {
+                       return null;
+               }
+               $result = array();
+               foreach ( $this->linkDeletions as $ns => $titles ) {
+                       foreach ( $titles as $title => $unused ) {
+                               $result[] = Title::makeTitle( $ns, $title );
+                       }
+               }
+
+               return $result;
+       }
+}
+
+/**
+ * Update object handling the cleanup of links tables after a page was deleted.
+ **/
+class LinksDeletionUpdate extends SqlDataUpdate {
+       /** @var WikiPage The WikiPage that was deleted */
+       protected $mPage;
+
+       /**
+        * Constructor
+        *
+        * @param WikiPage $page Page we are updating
+        * @throws MWException
+        */
+       function __construct( WikiPage $page ) {
+               parent::__construct( false ); // no implicit transaction
+
+               $this->mPage = $page;
+
+               if ( !$page->exists() ) {
+                       throw new MWException( "Page ID not known, perhaps the page doesn't exist?" );
+               }
+       }
+
+       /**
+        * Do some database updates after deletion
+        */
+       public function doUpdate() {
+               $title = $this->mPage->getTitle();
+               $id = $this->mPage->getId();
+
+               # Delete restrictions for it
+               $this->mDb->delete( 'page_restrictions', array( 'pr_page' => $id ), __METHOD__ );
+
+               # Fix category table counts
+               $cats = array();
+               $res = $this->mDb->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
+
+               foreach ( $res as $row ) {
+                       $cats[] = $row->cl_to;
+               }
+
+               $this->mPage->updateCategoryCounts( array(), $cats );
+
+               # If using cascading deletes, we can skip some explicit deletes
+               if ( !$this->mDb->cascadingDeletes() ) {
+                       # Delete outgoing links
+                       $this->mDb->delete( 'pagelinks', array( 'pl_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'imagelinks', array( 'il_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'categorylinks', array( 'cl_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'templatelinks', array( 'tl_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'externallinks', array( 'el_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'langlinks', array( 'll_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'iwlinks', array( 'iwl_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'redirect', array( 'rd_from' => $id ), __METHOD__ );
+                       $this->mDb->delete( 'page_props', array( 'pp_page' => $id ), __METHOD__ );
+               }
+
+               # If using cleanup triggers, we can skip some manual deletes
+               if ( !$this->mDb->cleanupTriggers() ) {
+                       # Clean up recentchanges entries...
+                       $this->mDb->delete( 'recentchanges',
+                               array( 'rc_type != ' . RC_LOG,
+                                       'rc_namespace' => $title->getNamespace(),
+                                       'rc_title' => $title->getDBkey() ),
+                               __METHOD__ );
+                       $this->mDb->delete( 'recentchanges',
+                               array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
+                               __METHOD__ );
+               }
+       }
+
+       /**
+        * Update all the appropriate counts in the category table.
+        * @param array $added Associative array of category name => sort key
+        * @param array $deleted Associative array of category name => sort key
+        */
+       function updateCategoryCounts( $added, $deleted ) {
+               $a = WikiPage::factory( $this->mTitle );
+               $a->updateCategoryCounts(
+                       array_keys( $added ), array_keys( $deleted )
+               );
+       }
+}
diff --git a/includes/deferred/SearchUpdate.php b/includes/deferred/SearchUpdate.php
new file mode 100644 (file)
index 0000000..7ca4158
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+/**
+ * Search index updater
+ *
+ * See deferred.txt
+ *
+ * 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 Search
+ */
+
+/**
+ * Database independant search index updater
+ *
+ * @ingroup Search
+ */
+class SearchUpdate implements DeferrableUpdate {
+       /** @var int Page id being updated */
+       private $id = 0;
+
+       /** @var Title Title we're updating */
+       private $title;
+
+       /** @var Content|false Content of the page (not text) */
+       private $content;
+
+       /**
+        * Constructor
+        *
+        * @param int $id Page id to update
+        * @param Title|string $title Title of page to update
+        * @param Content|string|bool $c Content of the page to update. Default: false.
+        *  If a Content object, text will be gotten from it. String is for back-compat.
+        *  Passing false tells the backend to just update the title, not the content
+        */
+       public function __construct( $id, $title, $c = false ) {
+               if ( is_string( $title ) ) {
+                       $nt = Title::newFromText( $title );
+               } else {
+                       $nt = $title;
+               }
+
+               if ( $nt ) {
+                       $this->id = $id;
+                       // is_string() check is back-compat for ApprovedRevs
+                       if ( is_string( $c ) ) {
+                               $this->content = new TextContent( $c );
+                       } else {
+                               $this->content = $c ?: false;
+                       }
+                       $this->title = $nt;
+               } else {
+                       wfDebug( "SearchUpdate object created with invalid title '$title'\n" );
+               }
+       }
+
+       /**
+        * Perform actual update for the entry
+        */
+       public function doUpdate() {
+               global $wgDisableSearchUpdate;
+
+               if ( $wgDisableSearchUpdate || !$this->id ) {
+                       return;
+               }
+
+               wfProfileIn( __METHOD__ );
+
+               $page = WikiPage::newFromId( $this->id, WikiPage::READ_LATEST );
+               $indexTitle = Title::indexTitle( $this->title->getNamespace(), $this->title->getText() );
+
+               foreach ( SearchEngine::getSearchTypes() as $type ) {
+                       $search = SearchEngine::create( $type );
+                       if ( !$search->supports( 'search-update' ) ) {
+                               continue;
+                       }
+
+                       $normalTitle = $search->normalizeText( $indexTitle );
+
+                       if ( $page === null ) {
+                               $search->delete( $this->id, $normalTitle );
+                               continue;
+                       } elseif ( $this->content === false ) {
+                               $search->updateTitle( $this->id, $normalTitle );
+                               continue;
+                       }
+
+                       $text = $search->getTextFromContent( $this->title, $this->content );
+                       if ( !$search->textAlreadyUpdatedForIndex() ) {
+                               $text = self::updateText( $text );
+                       }
+
+                       # Perform the actual update
+                       $search->update( $this->id, $normalTitle, $search->normalizeText( $text ) );
+               }
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Clean text for indexing. Only really suitable for indexing in databases.
+        * If you're using a real search engine, you'll probably want to override
+        * this behavior and do something nicer with the original wikitext.
+        */
+       public static function updateText( $text ) {
+               global $wgContLang;
+
+               # Language-specific strip/conversion
+               $text = $wgContLang->normalizeForSearch( $text );
+               $lc = SearchEngine::legalSearchChars() . '&#;';
+
+               wfProfileIn( __METHOD__ . '-regexps' );
+               $text = preg_replace( "/<\\/?\\s*[A-Za-z][^>]*?>/",
+                       ' ', $wgContLang->lc( " " . $text . " " ) ); # Strip HTML markup
+               $text = preg_replace( "/(^|\\n)==\\s*([^\\n]+)\\s*==(\\s)/sD",
+                       "\\1\\2 \\2 \\2\\3", $text ); # Emphasize headings
+
+               # Strip external URLs
+               $uc = "A-Za-z0-9_\\/:.,~%\\-+&;#?!=()@\\x80-\\xFF";
+               $protos = "http|https|ftp|mailto|news|gopher";
+               $pat = "/(^|[^\\[])({$protos}):[{$uc}]+([^{$uc}]|$)/";
+               $text = preg_replace( $pat, "\\1 \\3", $text );
+
+               $p1 = "/([^\\[])\\[({$protos}):[{$uc}]+]/";
+               $p2 = "/([^\\[])\\[({$protos}):[{$uc}]+\\s+([^\\]]+)]/";
+               $text = preg_replace( $p1, "\\1 ", $text );
+               $text = preg_replace( $p2, "\\1 \\3 ", $text );
+
+               # Internal image links
+               $pat2 = "/\\[\\[image:([{$uc}]+)\\.(gif|png|jpg|jpeg)([^{$uc}])/i";
+               $text = preg_replace( $pat2, " \\1 \\3", $text );
+
+               $text = preg_replace( "/([^{$lc}])([{$lc}]+)]]([a-z]+)/",
+                       "\\1\\2 \\2\\3", $text ); # Handle [[game]]s
+
+               # Strip all remaining non-search characters
+               $text = preg_replace( "/[^{$lc}]+/", " ", $text );
+
+               # Handle 's, s'
+               #
+               #   $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
+               #   $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
+               #
+               # These tail-anchored regexps are insanely slow. The worst case comes
+               # when Japanese or Chinese text (ie, no word spacing) is written on
+               # a wiki configured for Western UTF-8 mode. The Unicode characters are
+               # expanded to hex codes and the "words" are very long paragraph-length
+               # monstrosities. On a large page the above regexps may take over 20
+               # seconds *each* on a 1GHz-level processor.
+               #
+               # Following are reversed versions which are consistently fast
+               # (about 3 milliseconds on 1GHz-level processor).
+               #
+               $text = strrev( preg_replace( "/ s'([{$lc}]+)/", " s'\\1 \\1", strrev( $text ) ) );
+               $text = strrev( preg_replace( "/ 's([{$lc}]+)/", " s\\1", strrev( $text ) ) );
+
+               # Strip wiki '' and '''
+               $text = preg_replace( "/''[']*/", " ", $text );
+               wfProfileOut( __METHOD__ . '-regexps' );
+
+               return $text;
+       }
+}
diff --git a/includes/deferred/SiteStatsUpdate.php b/includes/deferred/SiteStatsUpdate.php
new file mode 100644 (file)
index 0000000..7bfafee
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Class for handling updates to the site_stats table
+ */
+class SiteStatsUpdate implements DeferrableUpdate {
+       /** @var int */
+       protected $views = 0;
+
+       /** @var int */
+       protected $edits = 0;
+
+       /** @var int */
+       protected $pages = 0;
+
+       /** @var int */
+       protected $articles = 0;
+
+       /** @var int */
+       protected $users = 0;
+
+       /** @var int */
+       protected $images = 0;
+
+       // @todo deprecate this constructor
+       function __construct( $views, $edits, $good, $pages = 0, $users = 0 ) {
+               $this->views = $views;
+               $this->edits = $edits;
+               $this->articles = $good;
+               $this->pages = $pages;
+               $this->users = $users;
+       }
+
+       /**
+        * @param array $deltas
+        * @return SiteStatsUpdate
+        */
+       public static function factory( array $deltas ) {
+               $update = new self( 0, 0, 0 );
+
+               $fields = array( 'views', 'edits', 'pages', 'articles', 'users', 'images' );
+               foreach ( $fields as $field ) {
+                       if ( isset( $deltas[$field] ) && $deltas[$field] ) {
+                               $update->$field = $deltas[$field];
+                       }
+               }
+
+               return $update;
+       }
+
+       public function doUpdate() {
+               global $wgSiteStatsAsyncFactor;
+
+               $rate = $wgSiteStatsAsyncFactor; // convenience
+               // If set to do so, only do actual DB updates 1 every $rate times.
+               // The other times, just update "pending delta" values in memcached.
+               if ( $rate && ( $rate < 0 || mt_rand( 0, $rate - 1 ) != 0 ) ) {
+                       $this->doUpdatePendingDeltas();
+               } else {
+                       // Need a separate transaction because this a global lock
+                       wfGetDB( DB_MASTER )->onTransactionIdle( array( $this, 'tryDBUpdateInternal' ) );
+               }
+       }
+
+       /**
+        * Do not call this outside of SiteStatsUpdate
+        */
+       public function tryDBUpdateInternal() {
+               global $wgSiteStatsAsyncFactor;
+
+               $dbw = wfGetDB( DB_MASTER );
+               $lockKey = wfMemcKey( 'site_stats' ); // prepend wiki ID
+               $pd = array();
+               if ( $wgSiteStatsAsyncFactor ) {
+                       // Lock the table so we don't have double DB/memcached updates
+                       if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
+                               || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout
+                       ) {
+                               $this->doUpdatePendingDeltas();
+
+                               return;
+                       }
+                       $pd = $this->getPendingDeltas();
+                       // Piggy-back the async deltas onto those of this stats update....
+                       $this->views += ( $pd['ss_total_views']['+'] - $pd['ss_total_views']['-'] );
+                       $this->edits += ( $pd['ss_total_edits']['+'] - $pd['ss_total_edits']['-'] );
+                       $this->articles += ( $pd['ss_good_articles']['+'] - $pd['ss_good_articles']['-'] );
+                       $this->pages += ( $pd['ss_total_pages']['+'] - $pd['ss_total_pages']['-'] );
+                       $this->users += ( $pd['ss_users']['+'] - $pd['ss_users']['-'] );
+                       $this->images += ( $pd['ss_images']['+'] - $pd['ss_images']['-'] );
+               }
+
+               // Build up an SQL query of deltas and apply them...
+               $updates = '';
+               $this->appendUpdate( $updates, 'ss_total_views', $this->views );
+               $this->appendUpdate( $updates, 'ss_total_edits', $this->edits );
+               $this->appendUpdate( $updates, 'ss_good_articles', $this->articles );
+               $this->appendUpdate( $updates, 'ss_total_pages', $this->pages );
+               $this->appendUpdate( $updates, 'ss_users', $this->users );
+               $this->appendUpdate( $updates, 'ss_images', $this->images );
+               if ( $updates != '' ) {
+                       $dbw->update( 'site_stats', array( $updates ), array(), __METHOD__ );
+               }
+
+               if ( $wgSiteStatsAsyncFactor ) {
+                       // Decrement the async deltas now that we applied them
+                       $this->removePendingDeltas( $pd );
+                       // Commit the updates and unlock the table
+                       $dbw->unlock( $lockKey, __METHOD__ );
+               }
+       }
+
+       /**
+        * @param DatabaseBase $dbw
+        * @return bool|mixed
+        */
+       public static function cacheUpdate( $dbw ) {
+               global $wgActiveUserDays;
+               $dbr = wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow' ) );
+               # Get non-bot users than did some recent action other than making accounts.
+               # If account creation is included, the number gets inflated ~20+ fold on enwiki.
+               $activeUsers = $dbr->selectField(
+                       'recentchanges',
+                       'COUNT( DISTINCT rc_user_text )',
+                       array(
+                               'rc_user != 0',
+                               'rc_bot' => 0,
+                               'rc_log_type != ' . $dbr->addQuotes( 'newusers' ) . ' OR rc_log_type IS NULL',
+                               'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX )
+                                       - $wgActiveUserDays * 24 * 3600 ) ),
+                       ),
+                       __METHOD__
+               );
+               $dbw->update(
+                       'site_stats',
+                       array( 'ss_active_users' => intval( $activeUsers ) ),
+                       array( 'ss_row_id' => 1 ),
+                       __METHOD__
+               );
+
+               return $activeUsers;
+       }
+
+       protected function doUpdatePendingDeltas() {
+               $this->adjustPending( 'ss_total_views', $this->views );
+               $this->adjustPending( 'ss_total_edits', $this->edits );
+               $this->adjustPending( 'ss_good_articles', $this->articles );
+               $this->adjustPending( 'ss_total_pages', $this->pages );
+               $this->adjustPending( 'ss_users', $this->users );
+               $this->adjustPending( 'ss_images', $this->images );
+       }
+
+       /**
+        * @param string $sql
+        * @param string $field
+        * @param int $delta
+        */
+       protected function appendUpdate( &$sql, $field, $delta ) {
+               if ( $delta ) {
+                       if ( $sql ) {
+                               $sql .= ',';
+                       }
+                       if ( $delta < 0 ) {
+                               $sql .= "$field=$field-" . abs( $delta );
+                       } else {
+                               $sql .= "$field=$field+" . abs( $delta );
+                       }
+               }
+       }
+
+       /**
+        * @param string $type
+        * @param string $sign ('+' or '-')
+        * @return string
+        */
+       private function getTypeCacheKey( $type, $sign ) {
+               return wfMemcKey( 'sitestatsupdate', 'pendingdelta', $type, $sign );
+       }
+
+       /**
+        * Adjust the pending deltas for a stat type.
+        * Each stat type has two pending counters, one for increments and decrements
+        * @param string $type
+        * @param int $delta Delta (positive or negative)
+        */
+       protected function adjustPending( $type, $delta ) {
+               global $wgMemc;
+
+               if ( $delta < 0 ) { // decrement
+                       $key = $this->getTypeCacheKey( $type, '-' );
+               } else { // increment
+                       $key = $this->getTypeCacheKey( $type, '+' );
+               }
+
+               $magnitude = abs( $delta );
+               if ( !$wgMemc->incr( $key, $magnitude ) ) { // not there?
+                       if ( !$wgMemc->add( $key, $magnitude ) ) { // race?
+                               $wgMemc->incr( $key, $magnitude );
+                       }
+               }
+       }
+
+       /**
+        * Get pending delta counters for each stat type
+        * @return array Positive and negative deltas for each type
+        */
+       protected function getPendingDeltas() {
+               global $wgMemc;
+
+               $pending = array();
+               foreach ( array( 'ss_total_views', 'ss_total_edits',
+                       'ss_good_articles', 'ss_total_pages', 'ss_users', 'ss_images' ) as $type
+               ) {
+                       // Get pending increments and pending decrements
+                       $pending[$type]['+'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '+' ) );
+                       $pending[$type]['-'] = (int)$wgMemc->get( $this->getTypeCacheKey( $type, '-' ) );
+               }
+
+               return $pending;
+       }
+
+       /**
+        * Reduce pending delta counters after updates have been applied
+        * @param array $pd Result of getPendingDeltas(), used for DB update
+        */
+       protected function removePendingDeltas( array $pd ) {
+               global $wgMemc;
+
+               foreach ( $pd as $type => $deltas ) {
+                       foreach ( $deltas as $sign => $magnitude ) {
+                               // Lower the pending counter now that we applied these changes
+                               $wgMemc->decr( $this->getTypeCacheKey( $type, $sign ), $magnitude );
+                       }
+               }
+       }
+}
diff --git a/includes/deferred/SqlDataUpdate.php b/includes/deferred/SqlDataUpdate.php
new file mode 100644 (file)
index 0000000..09d18c4
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+/**
+ * Base code for update jobs that put some secondary data extracted
+ * from article content into the database.
+ *
+ * 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
+ */
+
+/**
+ * Abstract base class for update jobs that put some secondary data extracted
+ * from article content into the database.
+ *
+ * @note: subclasses should NOT start or commit transactions in their doUpdate() method,
+ *        a transaction will automatically be wrapped around the update. Starting another
+ *        one would break the outer transaction bracket. If need be, subclasses can override
+ *        the beginTransaction() and commitTransaction() methods.
+ */
+abstract class SqlDataUpdate extends DataUpdate {
+       /** @var DatabaseBase Database connection reference */
+       protected $mDb;
+
+       /** @var array SELECT options to be used (array) */
+       protected $mOptions;
+
+       /** @var bool Whether a transaction is open on this object (internal use only!) */
+       private $mHasTransaction;
+
+       /** @var  bool Whether this update should be wrapped in a transaction */
+       protected $mUseTransaction;
+
+       /**
+        * Constructor
+        *
+        * @param bool $withTransaction whether this update should be wrapped in a
+        *   transaction (default: true). A transaction is only started if no
+        *   transaction is already in progress, see beginTransaction() for details.
+        */
+       public function __construct( $withTransaction = true ) {
+               global $wgAntiLockFlags;
+
+               parent::__construct();
+
+               if ( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) {
+                       $this->mOptions = array();
+               } else {
+                       $this->mOptions = array( 'FOR UPDATE' );
+               }
+
+               // @todo Get connection only when it's needed? Make sure that doesn't
+               // break anything, especially transactions!
+               $this->mDb = wfGetDB( DB_MASTER );
+
+               $this->mWithTransaction = $withTransaction;
+               $this->mHasTransaction = false;
+       }
+
+       /**
+        * Begin a database transaction, if $withTransaction was given as true in
+        * the constructor for this SqlDataUpdate.
+        *
+        * Because nested transactions are not supported by the Database class,
+        * this implementation checks Database::trxLevel() and only opens a
+        * transaction if none is already active.
+        */
+       public function beginTransaction() {
+               if ( !$this->mWithTransaction ) {
+                       return;
+               }
+
+               // NOTE: nested transactions are not supported, only start a transaction if none is open
+               if ( $this->mDb->trxLevel() === 0 ) {
+                       $this->mDb->begin( get_class( $this ) . '::beginTransaction' );
+                       $this->mHasTransaction = true;
+               }
+       }
+
+       /**
+        * Commit the database transaction started via beginTransaction (if any).
+        */
+       public function commitTransaction() {
+               if ( $this->mHasTransaction ) {
+                       $this->mDb->commit( get_class( $this ) . '::commitTransaction' );
+                       $this->mHasTransaction = false;
+               }
+       }
+
+       /**
+        * Abort the database transaction started via beginTransaction (if any).
+        */
+       public function abortTransaction() {
+               if ( $this->mHasTransaction ) { //XXX: actually... maybe always?
+                       $this->mDb->rollback( get_class( $this ) . '::abortTransaction' );
+                       $this->mHasTransaction = false;
+               }
+       }
+
+       /**
+        * Invalidate the cache of a list of pages from a single namespace.
+        * This is intended for use by subclasses.
+        *
+        * @param int $namespace Namespace number
+        * @param array $dbkeys
+        */
+       protected function invalidatePages( $namespace, array $dbkeys ) {
+               if ( $dbkeys === array() ) {
+                       return;
+               }
+
+               /**
+                * Determine which pages need to be updated
+                * This is necessary to prevent the job queue from smashing the DB with
+                * large numbers of concurrent invalidations of the same page
+                */
+               $now = $this->mDb->timestamp();
+               $ids = array();
+               $res = $this->mDb->select( 'page', array( 'page_id' ),
+                       array(
+                               'page_namespace' => $namespace,
+                               'page_title' => $dbkeys,
+                               'page_touched < ' . $this->mDb->addQuotes( $now )
+                       ), __METHOD__
+               );
+
+               foreach ( $res as $row ) {
+                       $ids[] = $row->page_id;
+               }
+
+               if ( $ids === array() ) {
+                       return;
+               }
+
+               /**
+                * Do the update
+                * We still need the page_touched condition, in case the row has changed since
+                * the non-locking select above.
+                */
+               $this->mDb->update( 'page', array( 'page_touched' => $now ),
+                       array(
+                               'page_id' => $ids,
+                               'page_touched < ' . $this->mDb->addQuotes( $now )
+                       ), __METHOD__
+               );
+       }
+}
diff --git a/includes/deferred/SquidUpdate.php b/includes/deferred/SquidUpdate.php
new file mode 100644 (file)
index 0000000..bac9f10
--- /dev/null
@@ -0,0 +1,305 @@
+<?php
+/**
+ * Squid cache purging.
+ *
+ * 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 Cache
+ */
+
+/**
+ * Handles purging appropriate Squid URLs given a title (or titles)
+ * @ingroup Cache
+ */
+class SquidUpdate {
+       /**
+        * Collection of URLs to purge.
+        * @var array
+        */
+       protected $urlArr;
+
+       /**
+        * @param array $urlArr Collection of URLs to purge
+        * @param bool|int $maxTitles Maximum number of unique URLs to purge
+        */
+       public function __construct( $urlArr = array(), $maxTitles = false ) {
+               global $wgMaxSquidPurgeTitles;
+               if ( $maxTitles === false ) {
+                       $maxTitles = $wgMaxSquidPurgeTitles;
+               }
+
+               // Remove duplicate URLs from list
+               $urlArr = array_unique( $urlArr );
+               if ( count( $urlArr ) > $maxTitles ) {
+                       // Truncate to desired maximum URL count
+                       $urlArr = array_slice( $urlArr, 0, $maxTitles );
+               }
+               $this->urlArr = $urlArr;
+       }
+
+       /**
+        * Create a SquidUpdate from the given Title object.
+        *
+        * The resulting SquidUpdate will purge the given Title's URLs as well as
+        * the pages that link to it. Capped at $wgMaxSquidPurgeTitles total URLs.
+        *
+        * @param Title $title
+        * @return SquidUpdate
+        */
+       public static function newFromLinksTo( Title $title ) {
+               global $wgMaxSquidPurgeTitles;
+               wfProfileIn( __METHOD__ );
+
+               # Get a list of URLs linking to this page
+               $dbr = wfGetDB( DB_SLAVE );
+               $res = $dbr->select( array( 'links', 'page' ),
+                       array( 'page_namespace', 'page_title' ),
+                       array(
+                               'pl_namespace' => $title->getNamespace(),
+                               'pl_title' => $title->getDBkey(),
+                               'pl_from=page_id' ),
+                       __METHOD__ );
+               $blurlArr = $title->getSquidURLs();
+               if ( $res->numRows() <= $wgMaxSquidPurgeTitles ) {
+                       foreach ( $res as $BL ) {
+                               $tobj = Title::makeTitle( $BL->page_namespace, $BL->page_title );
+                               $blurlArr[] = $tobj->getInternalURL();
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+
+               return new SquidUpdate( $blurlArr );
+       }
+
+       /**
+        * Create a SquidUpdate from an array of Title objects, or a TitleArray object
+        *
+        * @param array $titles
+        * @param array $urlArr
+        * @return SquidUpdate
+        */
+       public static function newFromTitles( $titles, $urlArr = array() ) {
+               global $wgMaxSquidPurgeTitles;
+               $i = 0;
+               /** @var Title $title */
+               foreach ( $titles as $title ) {
+                       $urlArr[] = $title->getInternalURL();
+                       if ( $i++ > $wgMaxSquidPurgeTitles ) {
+                               break;
+                       }
+               }
+
+               return new SquidUpdate( $urlArr );
+       }
+
+       /**
+        * @param Title $title
+        * @return SquidUpdate
+        */
+       public static function newSimplePurge( Title $title ) {
+               $urlArr = $title->getSquidURLs();
+
+               return new SquidUpdate( $urlArr );
+       }
+
+       /**
+        * Purges the list of URLs passed to the constructor.
+        */
+       public function doUpdate() {
+               self::purge( $this->urlArr );
+       }
+
+       /**
+        * Purges a list of Squids defined in $wgSquidServers.
+        * $urlArr should contain the full URLs to purge as values
+        * (example: $urlArr[] = 'http://my.host/something')
+        * XXX report broken Squids per mail or log
+        *
+        * @param array $urlArr List of full URLs to purge
+        */
+       public static function purge( $urlArr ) {
+               global $wgSquidServers, $wgHTCPRouting;
+
+               if ( !$urlArr ) {
+                       return;
+               }
+
+               wfDebugLog( 'squid', __METHOD__ . ': ' . implode( ' ', $urlArr ) . "\n" );
+
+               if ( $wgHTCPRouting ) {
+                       self::HTCPPurge( $urlArr );
+               }
+
+               wfProfileIn( __METHOD__ );
+
+               // Remove duplicate URLs
+               $urlArr = array_unique( $urlArr );
+               // Maximum number of parallel connections per squid
+               $maxSocketsPerSquid = 8;
+               // Number of requests to send per socket
+               // 400 seems to be a good tradeoff, opening a socket takes a while
+               $urlsPerSocket = 400;
+               $socketsPerSquid = ceil( count( $urlArr ) / $urlsPerSocket );
+               if ( $socketsPerSquid > $maxSocketsPerSquid ) {
+                       $socketsPerSquid = $maxSocketsPerSquid;
+               }
+
+               $pool = new SquidPurgeClientPool;
+               $chunks = array_chunk( $urlArr, ceil( count( $urlArr ) / $socketsPerSquid ) );
+               foreach ( $wgSquidServers as $server ) {
+                       foreach ( $chunks as $chunk ) {
+                               $client = new SquidPurgeClient( $server );
+                               foreach ( $chunk as $url ) {
+                                       $client->queuePurge( $url );
+                               }
+                               $pool->addClient( $client );
+                       }
+               }
+               $pool->run();
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Send Hyper Text Caching Protocol (HTCP) CLR requests.
+        *
+        * @throws MWException
+        * @param array $urlArr Collection of URLs to purge
+        */
+       public static function HTCPPurge( $urlArr ) {
+               global $wgHTCPRouting, $wgHTCPMulticastTTL;
+               wfProfileIn( __METHOD__ );
+
+               // HTCP CLR operation
+               $htcpOpCLR = 4;
+
+               // @todo FIXME: PHP doesn't support these socket constants (include/linux/in.h)
+               if ( !defined( "IPPROTO_IP" ) ) {
+                       define( "IPPROTO_IP", 0 );
+                       define( "IP_MULTICAST_LOOP", 34 );
+                       define( "IP_MULTICAST_TTL", 33 );
+               }
+
+               // pfsockopen doesn't work because we need set_sock_opt
+               $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
+               if ( !$conn ) {
+                       $errstr = socket_strerror( socket_last_error() );
+                       wfDebugLog( 'squid', __METHOD__ .
+                               ": Error opening UDP socket: $errstr\n" );
+                       wfProfileOut( __METHOD__ );
+
+                       return;
+               }
+
+               // Set socket options
+               socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_LOOP, 0 );
+               if ( $wgHTCPMulticastTTL != 1 ) {
+                       // Set multicast time to live (hop count) option on socket
+                       socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_TTL,
+                               $wgHTCPMulticastTTL );
+               }
+
+               // Remove duplicate URLs from collection
+               $urlArr = array_unique( $urlArr );
+               foreach ( $urlArr as $url ) {
+                       if ( !is_string( $url ) ) {
+                               wfProfileOut( __METHOD__ );
+                               throw new MWException( 'Bad purge URL' );
+                       }
+                       $url = self::expand( $url );
+                       $conf = self::getRuleForURL( $url, $wgHTCPRouting );
+                       if ( !$conf ) {
+                               wfDebugLog( 'squid', __METHOD__ .
+                                       "No HTCP rule configured for URL {$url} , skipping\n" );
+                               continue;
+                       }
+
+                       if ( isset( $conf['host'] ) && isset( $conf['port'] ) ) {
+                               // Normalize single entries
+                               $conf = array( $conf );
+                       }
+                       foreach ( $conf as $subconf ) {
+                               if ( !isset( $subconf['host'] ) || !isset( $subconf['port'] ) ) {
+                                       wfProfileOut( __METHOD__ );
+                                       throw new MWException( "Invalid HTCP rule for URL $url\n" );
+                               }
+                       }
+
+                       // Construct a minimal HTCP request diagram
+                       // as per RFC 2756
+                       // Opcode 'CLR', no response desired, no auth
+                       $htcpTransID = rand();
+
+                       $htcpSpecifier = pack( 'na4na*na8n',
+                               4, 'HEAD', strlen( $url ), $url,
+                               8, 'HTTP/1.0', 0 );
+
+                       $htcpDataLen = 8 + 2 + strlen( $htcpSpecifier );
+                       $htcpLen = 4 + $htcpDataLen + 2;
+
+                       // Note! Squid gets the bit order of the first
+                       // word wrong, wrt the RFC. Apparently no other
+                       // implementation exists, so adapt to Squid
+                       $htcpPacket = pack( 'nxxnCxNxxa*n',
+                               $htcpLen, $htcpDataLen, $htcpOpCLR,
+                               $htcpTransID, $htcpSpecifier, 2 );
+
+                       wfDebugLog( 'squid', __METHOD__ .
+                               "Purging URL $url via HTCP\n" );
+                       foreach ( $conf as $subconf ) {
+                               socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
+                                       $subconf['host'], $subconf['port'] );
+                       }
+               }
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Expand local URLs to fully-qualified URLs using the internal protocol
+        * and host defined in $wgInternalServer. Input that's already fully-
+        * qualified will be passed through unchanged.
+        *
+        * This is used to generate purge URLs that may be either local to the
+        * main wiki or include a non-native host, such as images hosted on a
+        * second internal server.
+        *
+        * Client functions should not need to call this.
+        *
+        * @param string $url
+        * @return string
+        */
+       public static function expand( $url ) {
+               return wfExpandUrl( $url, PROTO_INTERNAL );
+       }
+
+       /**
+        * Find the HTCP routing rule to use for a given URL.
+        * @param string $url URL to match
+        * @param array $rules Array of rules, see $wgHTCPRouting for format and behavior
+        * @return mixed Element of $rules that matched, or false if nothing matched
+        */
+       private static function getRuleForURL( $url, $rules ) {
+               foreach ( $rules as $regex => $routing ) {
+                       if ( $regex === '' || preg_match( $regex, $url ) ) {
+                               return $routing;
+                       }
+               }
+
+               return false;
+       }
+}
diff --git a/includes/deferred/ViewCountUpdate.php b/includes/deferred/ViewCountUpdate.php
new file mode 100644 (file)
index 0000000..ddd2e09
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Update for the 'page_counter' field
+ *
+ * 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
+ */
+
+/**
+ * Update for the 'page_counter' field, when $wgDisableCounters is false.
+ *
+ * Depending on $wgHitcounterUpdateFreq, this will directly increment the
+ * 'page_counter' field or use the 'hitcounter' table and then collect the data
+ * from that table to update the 'page_counter' field in a batch operation.
+ */
+class ViewCountUpdate implements DeferrableUpdate {
+       /** @var int Page ID to increment the view count */
+       protected $id;
+
+       /**
+        * Constructor
+        *
+        * @param int $id Page ID to increment the view count
+        */
+       public function __construct( $id ) {
+               $this->id = intval( $id );
+       }
+
+       /**
+        * Run the update
+        */
+       public function doUpdate() {
+               global $wgHitcounterUpdateFreq;
+
+               $dbw = wfGetDB( DB_MASTER );
+
+               if ( $wgHitcounterUpdateFreq <= 1 || $dbw->getType() == 'sqlite' ) {
+                       $dbw->update(
+                               'page', array( 'page_counter = page_counter + 1' ),
+                               array( 'page_id' => $this->id ),
+                               __METHOD__
+                       );
+
+                       return;
+               }
+
+               # Not important enough to warrant an error page in case of failure
+               try {
+                       $dbw->insert( 'hitcounter', array( 'hc_id' => $this->id ), __METHOD__ );
+                       $checkfreq = intval( $wgHitcounterUpdateFreq / 25 + 1 );
+                       if ( rand() % $checkfreq == 0 && $dbw->lastErrno() == 0 ) {
+                               $this->collect();
+                       }
+               } catch ( DBError $e ) {
+               }
+       }
+
+       protected function collect() {
+               global $wgHitcounterUpdateFreq;
+
+               $dbw = wfGetDB( DB_MASTER );
+
+               $rown = $dbw->selectField( 'hitcounter', 'COUNT(*)', array(), __METHOD__ );
+
+               if ( $rown < $wgHitcounterUpdateFreq ) {
+                       return;
+               }
+
+               wfProfileIn( __METHOD__ . '-collect' );
+               $old_user_abort = ignore_user_abort( true );
+
+               $dbw->lockTables( array(), array( 'hitcounter' ), __METHOD__, false );
+
+               $dbType = $dbw->getType();
+               $tabletype = $dbType == 'mysql' ? "ENGINE=HEAP " : '';
+               $hitcounterTable = $dbw->tableName( 'hitcounter' );
+               $acchitsTable = $dbw->tableName( 'acchits' );
+               $pageTable = $dbw->tableName( 'page' );
+
+               $dbw->query( "CREATE TEMPORARY TABLE $acchitsTable $tabletype AS " .
+                       "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable " .
+                       'GROUP BY hc_id', __METHOD__ );
+               $dbw->delete( 'hitcounter', '*', __METHOD__ );
+               $dbw->unlockTables( __METHOD__ );
+
+               if ( $dbType == 'mysql' ) {
+                       $dbw->query( "UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n " .
+                               'WHERE page_id = hc_id', __METHOD__ );
+               } else {
+                       $dbw->query( "UPDATE $pageTable SET page_counter=page_counter + hc_n " .
+                               "FROM $acchitsTable WHERE page_id = hc_id", __METHOD__ );
+               }
+               $dbw->query( "DROP TABLE $acchitsTable", __METHOD__ );
+
+               ignore_user_abort( $old_user_abort );
+               wfProfileOut( __METHOD__ . '-collect' );
+       }
+}
diff --git a/includes/diff/ArrayDiffFormatter.php b/includes/diff/ArrayDiffFormatter.php
new file mode 100644 (file)
index 0000000..331ce7d
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Portions taken from phpwiki-1.3.3.
+ *
+ * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
+ * You may copy this code freely under the conditions of the GPL.
+ *
+ * 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 DifferenceEngine
+ */
+
+/**
+ * A pseudo-formatter that just passes along the Diff::$edits array
+ * @ingroup DifferenceEngine
+ */
+class ArrayDiffFormatter extends DiffFormatter {
+       /**
+        * @param $diff
+        * @return array
+        */
+       public function format( $diff ) {
+               $oldline = 1;
+               $newline = 1;
+               $retval = array();
+               foreach ( $diff->edits as $edit ) {
+                       switch ( $edit->type ) {
+                               case 'add':
+                                       foreach ( $edit->closing as $l ) {
+                                               $retval[] = array(
+                                                       'action' => 'add',
+                                                       'new' => $l,
+                                                       'newline' => $newline++
+                                               );
+                                       }
+                                       break;
+                               case 'delete':
+                                       foreach ( $edit->orig as $l ) {
+                                               $retval[] = array(
+                                                       'action' => 'delete',
+                                                       'old' => $l,
+                                                       'oldline' => $oldline++,
+                                               );
+                                       }
+                                       break;
+                               case 'change':
+                                       foreach ( $edit->orig as $i => $l ) {
+                                               $retval[] = array(
+                                                       'action' => 'change',
+                                                       'old' => $l,
+                                                       'new' => isset( $edit->closing[$i] ) ? $edit->closing[$i] : null,
+                                                       'oldline' => $oldline++,
+                                                       'newline' => $newline++,
+                                               );
+                                       }
+                                       break;
+                               case 'copy':
+                                       $oldline += count( $edit->orig );
+                                       $newline += count( $edit->orig );
+                       }
+               }
+
+               return $retval;
+       }
+}
index 298d724..f80a4ad 100644 (file)
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp {
-       var $type;
-       var $orig;
-       var $closing;
+abstract class DiffOp {
+       public $type;
+       public $orig;
+       public $closing;
 
-       function reverse() {
-               trigger_error( 'pure virtual', E_USER_ERROR );
-       }
+       abstract public function reverse();
 
        /**
         * @return int
@@ -59,8 +57,8 @@ class _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Copy extends _DiffOp {
-       var $type = 'copy';
+class DiffOpCopy extends DiffOp {
+       public $type = 'copy';
 
        function __construct( $orig, $closing = false ) {
                if ( !is_array( $closing ) ) {
@@ -71,10 +69,10 @@ class _DiffOp_Copy extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Copy
+        * @return DiffOpCopy
         */
        function reverse() {
-               return new _DiffOp_Copy( $this->closing, $this->orig );
+               return new DiffOpCopy( $this->closing, $this->orig );
        }
 }
 
@@ -83,8 +81,8 @@ class _DiffOp_Copy extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Delete extends _DiffOp {
-       var $type = 'delete';
+class DiffOpDelete extends DiffOp {
+       public $type = 'delete';
 
        function __construct( $lines ) {
                $this->orig = $lines;
@@ -92,10 +90,10 @@ class _DiffOp_Delete extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Add
+        * @return DiffOpAdd
         */
        function reverse() {
-               return new _DiffOp_Add( $this->orig );
+               return new DiffOpAdd( $this->orig );
        }
 }
 
@@ -104,8 +102,8 @@ class _DiffOp_Delete extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Add extends _DiffOp {
-       var $type = 'add';
+class DiffOpAdd extends DiffOp {
+       public $type = 'add';
 
        function __construct( $lines ) {
                $this->closing = $lines;
@@ -113,10 +111,10 @@ class _DiffOp_Add extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Delete
+        * @return DiffOpDelete
         */
        function reverse() {
-               return new _DiffOp_Delete( $this->closing );
+               return new DiffOpDelete( $this->closing );
        }
 }
 
@@ -125,8 +123,8 @@ class _DiffOp_Add extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Change extends _DiffOp {
-       var $type = 'change';
+class DiffOpChange extends DiffOp {
+       public $type = 'change';
 
        function __construct( $orig, $closing ) {
                $this->orig = $orig;
@@ -134,10 +132,10 @@ class _DiffOp_Change extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Change
+        * @return DiffOpChange
         */
        function reverse() {
-               return new _DiffOp_Change( $this->closing, $this->orig );
+               return new DiffOpChange( $this->closing, $this->orig );
        }
 }
 
@@ -146,14 +144,14 @@ class _DiffOp_Change extends _DiffOp {
  *
  * The algorithm used here is mostly lifted from the perl module
  * Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
- *      http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
+ *     http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
  *
  * More ideas are taken from:
- *      http://www.ics.uci.edu/~eppstein/161/960229.html
+ *     http://www.ics.uci.edu/~eppstein/161/960229.html
  *
  * Some ideas are (and a bit of code) are from from analyze.c, from GNU
  * diffutils-2.7, which can be found at:
- *      ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
+ *     ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
  *
  * closingly, some ideas (subdivision by NCHUNKS > 2, and some optimizations)
  * are my own.
@@ -165,8 +163,7 @@ class _DiffOp_Change extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffEngine {
-
+class DiffEngine {
        const MAX_XREF_LENGTH = 10000;
 
        protected $xchanged, $ychanged;
@@ -187,11 +184,11 @@ class _DiffEngine {
                wfProfileIn( __METHOD__ );
 
                // Diff and store locally
-               $this->diff_local( $from_lines, $to_lines );
+               $this->diffLocal( $from_lines, $to_lines );
 
                // Merge edits when possible
-               $this->_shift_boundaries( $from_lines, $this->xchanged, $this->ychanged );
-               $this->_shift_boundaries( $to_lines, $this->ychanged, $this->xchanged );
+               $this->shiftBoundaries( $from_lines, $this->xchanged, $this->ychanged );
+               $this->shiftBoundaries( $to_lines, $this->ychanged, $this->xchanged );
 
                // Compute the edit operations.
                $n_from = count( $from_lines );
@@ -206,12 +203,13 @@ class _DiffEngine {
                        // Skip matching "snake".
                        $copy = array();
                        while ( $xi < $n_from && $yi < $n_to
-                       && !$this->xchanged[$xi] && !$this->ychanged[$yi] ) {
+                               && !$this->xchanged[$xi] && !$this->ychanged[$yi]
+                       ) {
                                $copy[] = $from_lines[$xi++];
                                ++$yi;
                        }
                        if ( $copy ) {
-                               $edits[] = new _DiffOp_Copy( $copy );
+                               $edits[] = new DiffOpCopy( $copy );
                        }
 
                        // Find deletes & adds.
@@ -226,14 +224,15 @@ class _DiffEngine {
                        }
 
                        if ( $delete && $add ) {
-                               $edits[] = new _DiffOp_Change( $delete, $add );
+                               $edits[] = new DiffOpChange( $delete, $add );
                        } elseif ( $delete ) {
-                               $edits[] = new _DiffOp_Delete( $delete );
+                               $edits[] = new DiffOpDelete( $delete );
                        } elseif ( $add ) {
-                               $edits[] = new _DiffOp_Add( $add );
+                               $edits[] = new DiffOpAdd( $add );
                        }
                }
                wfProfileOut( __METHOD__ );
+
                return $edits;
        }
 
@@ -241,7 +240,7 @@ class _DiffEngine {
         * @param $from_lines
         * @param $to_lines
         */
-       function diff_local( $from_lines, $to_lines ) {
+       private function diffLocal( $from_lines, $to_lines ) {
                global $wgExternalDiffEngine;
                wfProfileIn( __METHOD__ );
 
@@ -282,21 +281,21 @@ class _DiffEngine {
 
                        // Ignore lines which do not exist in both files.
                        for ( $xi = $skip; $xi < $n_from - $endskip; $xi++ ) {
-                               $xhash[$this->_line_hash( $from_lines[$xi] )] = 1;
+                               $xhash[$this->lineHash( $from_lines[$xi] )] = 1;
                        }
 
                        for ( $yi = $skip; $yi < $n_to - $endskip; $yi++ ) {
                                $line = $to_lines[$yi];
-                               if ( ( $this->ychanged[$yi] = empty( $xhash[$this->_line_hash( $line )] ) ) ) {
+                               if ( ( $this->ychanged[$yi] = empty( $xhash[$this->lineHash( $line )] ) ) ) {
                                        continue;
                                }
-                               $yhash[$this->_line_hash( $line )] = 1;
+                               $yhash[$this->lineHash( $line )] = 1;
                                $this->yv[] = $line;
                                $this->yind[] = $yi;
                        }
                        for ( $xi = $skip; $xi < $n_from - $endskip; $xi++ ) {
                                $line = $from_lines[$xi];
-                               if ( ( $this->xchanged[$xi] = empty( $yhash[$this->_line_hash( $line )] ) ) ) {
+                               if ( ( $this->xchanged[$xi] = empty( $yhash[$this->lineHash( $line )] ) ) ) {
                                        continue;
                                }
                                $this->xv[] = $line;
@@ -304,7 +303,7 @@ class _DiffEngine {
                        }
 
                        // Find the LCS.
-                       $this->_compareseq( 0, count( $this->xv ), 0, count( $this->yv ) );
+                       $this->compareSeq( 0, count( $this->xv ), 0, count( $this->yv ) );
                }
                wfProfileOut( __METHOD__ );
        }
@@ -314,7 +313,7 @@ class _DiffEngine {
         * @param $line string
         * @return string
         */
-       function _line_hash( $line ) {
+       private function lineHash( $line ) {
                if ( strlen( $line ) > self::MAX_XREF_LENGTH ) {
                        return md5( $line );
                } else {
@@ -345,7 +344,7 @@ class _DiffEngine {
         * @param $nchunks
         * @return array
         */
-       function _diag( $xoff, $xlim, $yoff, $ylim, $nchunks ) {
+       private function diag( $xoff, $xlim, $yoff, $ylim, $nchunks ) {
                $flip = false;
 
                if ( $xlim - $xoff > $ylim - $yoff ) {
@@ -375,28 +374,31 @@ class _DiffEngine {
                for ( $chunk = 0; $chunk < $nchunks; $chunk++ ) {
                        if ( $chunk > 0 ) {
                                for ( $i = 0; $i <= $this->lcs; $i++ ) {
-                                       $ymids[$i][$chunk -1] = $this->seq[$i];
+                                       $ymids[$i][$chunk - 1] = $this->seq[$i];
                                }
                        }
 
-                       $x1 = $xoff + (int)( ( $numer + ( $xlim -$xoff ) * $chunk ) / $nchunks );
+                       $x1 = $xoff + (int)( ( $numer + ( $xlim - $xoff ) * $chunk ) / $nchunks );
                        for ( ; $x < $x1; $x++ ) {
                                $line = $flip ? $this->yv[$x] : $this->xv[$x];
                                if ( empty( $ymatches[$line] ) ) {
                                        continue;
                                }
+
+                               $k = 0;
                                $matches = $ymatches[$line];
                                reset( $matches );
                                while ( list( , $y ) = each( $matches ) ) {
                                        if ( empty( $this->in_seq[$y] ) ) {
-                                               $k = $this->_lcs_pos( $y );
+                                               $k = $this->lcsPos( $y );
                                                assert( '$k > 0' );
-                                               $ymids[$k] = $ymids[$k -1];
+                                               $ymids[$k] = $ymids[$k - 1];
                                                break;
                                        }
                                }
+
                                while ( list( , $y ) = each( $matches ) ) {
-                                       if ( $y > $this->seq[$k -1] ) {
+                                       if ( $y > $this->seq[$k - 1] ) {
                                                assert( '$y < $this->seq[$k]' );
                                                // Optimization: this is a common case:
                                                //      next match is just replacing previous match.
@@ -404,9 +406,9 @@ class _DiffEngine {
                                                $this->seq[$k] = $y;
                                                $this->in_seq[$y] = 1;
                                        } elseif ( empty( $this->in_seq[$y] ) ) {
-                                               $k = $this->_lcs_pos( $y );
+                                               $k = $this->lcsPos( $y );
                                                assert( '$k > 0' );
-                                               $ymids[$k] = $ymids[$k -1];
+                                               $ymids[$k] = $ymids[$k - 1];
                                        }
                                }
                        }
@@ -428,11 +430,12 @@ class _DiffEngine {
         * @param $ypos
         * @return int
         */
-       function _lcs_pos( $ypos ) {
+       private function lcsPos( $ypos ) {
                $end = $this->lcs;
                if ( $end == 0 || $ypos > $this->seq[$end] ) {
                        $this->seq[++$this->lcs] = $ypos;
                        $this->in_seq[$ypos] = 1;
+
                        return $this->lcs;
                }
 
@@ -451,6 +454,7 @@ class _DiffEngine {
                $this->in_seq[$this->seq[$end]] = false;
                $this->seq[$end] = $ypos;
                $this->in_seq[$ypos] = 1;
+
                return $end;
        }
 
@@ -470,7 +474,7 @@ class _DiffEngine {
         * @param $yoff
         * @param $ylim
         */
-       function _compareseq( $xoff, $xlim, $yoff, $ylim ) {
+       private function compareSeq( $xoff, $xlim, $yoff, $ylim ) {
                // Slide down the bottom initial diagonal.
                while ( $xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff] ) {
                        ++$xoff;
@@ -479,7 +483,8 @@ class _DiffEngine {
 
                // Slide up the top initial diagonal.
                while ( $xlim > $xoff && $ylim > $yoff
-               && $this->xv[$xlim - 1] == $this->yv[$ylim - 1] ) {
+                       && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]
+               ) {
                        --$xlim;
                        --$ylim;
                }
@@ -491,7 +496,7 @@ class _DiffEngine {
                        // $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
                        // $nchunks = max(2,min(8,(int)$nchunks));
                        $nchunks = min( 7, $xlim - $xoff, $ylim - $yoff ) + 1;
-                       list( $lcs, $seps ) = $this->_diag( $xoff, $xlim, $yoff, $ylim, $nchunks );
+                       list( $lcs, $seps ) = $this->diag( $xoff, $xlim, $yoff, $ylim, $nchunks );
                }
 
                if ( $lcs == 0 ) {
@@ -508,7 +513,7 @@ class _DiffEngine {
                        reset( $seps );
                        $pt1 = $seps[0];
                        while ( $pt2 = next( $seps ) ) {
-                               $this->_compareseq( $pt1[0], $pt2[0], $pt1[1], $pt2[1] );
+                               $this->compareSeq( $pt1[0], $pt2[0], $pt1[1], $pt2[1] );
                                $pt1 = $pt2;
                        }
                }
@@ -527,7 +532,7 @@ class _DiffEngine {
         *
         * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
         */
-       function _shift_boundaries( $lines, &$changed, $other_changed ) {
+       private function shiftBoundaries( $lines, &$changed, $other_changed ) {
                wfProfileIn( __METHOD__ );
                $i = 0;
                $j = 0;
@@ -552,7 +557,7 @@ class _DiffEngine {
                                $j++;
                        }
 
-                       while ( $i < $len && ! $changed[$i] ) {
+                       while ( $i < $len && !$changed[$i] ) {
                                assert( '$j < $other_len && ! $other_changed[$j]' );
                                $i++;
                                $j++;
@@ -654,20 +659,19 @@ class _DiffEngine {
  * @ingroup DifferenceEngine
  */
 class Diff {
-       var $edits;
+       public $edits;
 
        /**
         * Constructor.
         * Computes diff between sequences of strings.
         *
         * @param $from_lines array An array of strings.
-        *                (Typically these are lines from a file.)
+        *   Typically these are lines from a file.
         * @param $to_lines array An array of strings.
         */
        function __construct( $from_lines, $to_lines ) {
-               $eng = new _DiffEngine;
+               $eng = new DiffEngine;
                $this->edits = $eng->diff( $from_lines, $to_lines );
-               // $this->_check($from_lines, $to_lines);
        }
 
        /**
@@ -675,17 +679,19 @@ class Diff {
         *
         * SYNOPSIS:
         *
-        *      $diff = new Diff($lines1, $lines2);
-        *      $rev = $diff->reverse();
+        *    $diff = new Diff($lines1, $lines2);
+        *    $rev = $diff->reverse();
         * @return Object A Diff object representing the inverse of the
-        *                                original diff.
+        *   original diff.
         */
        function reverse() {
                $rev = $this;
                $rev->edits = array();
+               /** @var DiffOp $edit */
                foreach ( $this->edits as $edit ) {
                        $rev->edits[] = $edit->reverse();
                }
+
                return $rev;
        }
 
@@ -700,6 +706,7 @@ class Diff {
                                return false;
                        }
                }
+
                return true;
        }
 
@@ -717,6 +724,7 @@ class Diff {
                                $lcs += count( $edit->orig );
                        }
                }
+
                return $lcs;
        }
 
@@ -736,6 +744,7 @@ class Diff {
                                array_splice( $lines, count( $lines ), 0, $edit->orig );
                        }
                }
+
                return $lines;
        }
 
@@ -755,44 +764,8 @@ class Diff {
                                array_splice( $lines, count( $lines ), 0, $edit->closing );
                        }
                }
-               return $lines;
-       }
 
-       /**
-        * Check a Diff for validity.
-        *
-        * This is here only for debugging purposes.
-        * @param $from_lines
-        * @param $to_lines
-        */
-       function _check( $from_lines, $to_lines ) {
-               wfProfileIn( __METHOD__ );
-               if ( serialize( $from_lines ) != serialize( $this->orig() ) ) {
-                       trigger_error( "Reconstructed original doesn't match", E_USER_ERROR );
-               }
-               if ( serialize( $to_lines ) != serialize( $this->closing() ) ) {
-                       trigger_error( "Reconstructed closing doesn't match", E_USER_ERROR );
-               }
-
-               $rev = $this->reverse();
-               if ( serialize( $to_lines ) != serialize( $rev->orig() ) ) {
-                       trigger_error( "Reversed original doesn't match", E_USER_ERROR );
-               }
-               if ( serialize( $from_lines ) != serialize( $rev->closing() ) ) {
-                       trigger_error( "Reversed closing doesn't match", E_USER_ERROR );
-               }
-
-               $prevtype = 'none';
-               foreach ( $this->edits as $edit ) {
-                       if ( $prevtype == $edit->type ) {
-                               trigger_error( 'Edit sequence is non-optimal', E_USER_ERROR );
-                       }
-                       $prevtype = $edit->type;
-               }
-
-               $lcs = $this->lcs();
-               trigger_error( 'Diff okay: LCS = ' . $lcs, E_USER_NOTICE );
-               wfProfileOut( __METHOD__ );
+               return $lines;
        }
 }
 
@@ -812,18 +785,18 @@ class MappedDiff extends Diff {
         * changes in white-space.
         *
         * @param $from_lines array An array of strings.
-        *      (Typically these are lines from a file.)
+        *   Typically these are lines from a file.
         *
         * @param $to_lines array An array of strings.
         *
         * @param $mapped_from_lines array This array should
-        *      have the same size number of elements as $from_lines.
-        *      The elements in $mapped_from_lines and
-        *      $mapped_to_lines are what is actually compared
-        *      when computing the diff.
+        *   have the same size number of elements as $from_lines.
+        *   The elements in $mapped_from_lines and
+        *   $mapped_to_lines are what is actually compared
+        *   when computing the diff.
         *
         * @param $mapped_to_lines array This array should
-        *      have the same number of elements as $to_lines.
+        *   have the same number of elements as $to_lines.
         */
        function __construct( $from_lines, $to_lines,
                $mapped_from_lines, $mapped_to_lines ) {
@@ -835,7 +808,8 @@ class MappedDiff extends Diff {
                parent::__construct( $mapped_from_lines, $mapped_to_lines );
 
                $xi = $yi = 0;
-               for ( $i = 0; $i < count( $this->edits ); $i++ ) {
+               $editCount = count( $this->edits );
+               for ( $i = 0; $i < $editCount; $i++ ) {
                        $orig = &$this->edits[$i]->orig;
                        if ( is_array( $orig ) ) {
                                $orig = array_slice( $from_lines, $xi, count( $orig ) );
@@ -852,363 +826,61 @@ class MappedDiff extends Diff {
        }
 }
 
-/**
- * A class to format Diffs
- *
- * This class formats the diff in classic diff format.
- * It is intended that this class be customized via inheritance,
- * to obtain fancier outputs.
- * @todo document
- * @private
- * @ingroup DifferenceEngine
- */
-class DiffFormatter {
-       /**
-        * Number of leading context "lines" to preserve.
-        *
-        * This should be left at zero for this class, but subclasses
-        * may want to set this to other values.
-        */
-       var $leading_context_lines = 0;
-
-       /**
-        * Number of trailing context "lines" to preserve.
-        *
-        * This should be left at zero for this class, but subclasses
-        * may want to set this to other values.
-        */
-       var $trailing_context_lines = 0;
-
-       /**
-        * Format a diff.
-        *
-        * @param $diff Diff A Diff object.
-        * @return string The formatted output.
-        */
-       function format( $diff ) {
-               wfProfileIn( __METHOD__ );
-
-               $xi = $yi = 1;
-               $block = false;
-               $context = array();
-
-               $nlead = $this->leading_context_lines;
-               $ntrail = $this->trailing_context_lines;
-
-               $this->_start_diff();
-
-               foreach ( $diff->edits as $edit ) {
-                       if ( $edit->type == 'copy' ) {
-                               if ( is_array( $block ) ) {
-                                       if ( count( $edit->orig ) <= $nlead + $ntrail ) {
-                                               $block[] = $edit;
-                                       } else {
-                                               if ( $ntrail ) {
-                                                       $context = array_slice( $edit->orig, 0, $ntrail );
-                                                       $block[] = new _DiffOp_Copy( $context );
-                                               }
-                                               $this->_block( $x0, $ntrail + $xi - $x0,
-                                                       $y0, $ntrail + $yi - $y0,
-                                                       $block );
-                                               $block = false;
-                                       }
-                               }
-                               $context = $edit->orig;
-                       } else {
-                               if ( !is_array( $block ) ) {
-                                       $context = array_slice( $context, count( $context ) - $nlead );
-                                       $x0 = $xi - count( $context );
-                                       $y0 = $yi - count( $context );
-                                       $block = array();
-                                       if ( $context ) {
-                                               $block[] = new _DiffOp_Copy( $context );
-                                       }
-                               }
-                               $block[] = $edit;
-                       }
-
-                       if ( $edit->orig ) {
-                               $xi += count( $edit->orig );
-                       }
-                       if ( $edit->closing ) {
-                               $yi += count( $edit->closing );
-                       }
-               }
-
-               if ( is_array( $block ) ) {
-                       $this->_block( $x0, $xi - $x0,
-                               $y0, $yi - $y0,
-                               $block );
-               }
-
-               $end = $this->_end_diff();
-               wfProfileOut( __METHOD__ );
-               return $end;
-       }
-
-       /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
-        * @param $edits
-        */
-       function _block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
-               wfProfileIn( __METHOD__ );
-               $this->_start_block( $this->_block_header( $xbeg, $xlen, $ybeg, $ylen ) );
-               foreach ( $edits as $edit ) {
-                       if ( $edit->type == 'copy' ) {
-                               $this->_context( $edit->orig );
-                       } elseif ( $edit->type == 'add' ) {
-                               $this->_added( $edit->closing );
-                       } elseif ( $edit->type == 'delete' ) {
-                               $this->_deleted( $edit->orig );
-                       } elseif ( $edit->type == 'change' ) {
-                               $this->_changed( $edit->orig, $edit->closing );
-                       } else {
-                               trigger_error( 'Unknown edit type', E_USER_ERROR );
-                       }
-               }
-               $this->_end_block();
-               wfProfileOut( __METHOD__ );
-       }
-
-       function _start_diff() {
-               ob_start();
-       }
-
-       /**
-        * @return string
-        */
-       function _end_diff() {
-               $val = ob_get_contents();
-               ob_end_clean();
-               return $val;
-       }
-
-       /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
-        * @return string
-        */
-       function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
-               if ( $xlen > 1 ) {
-                       $xbeg .= ',' . ( $xbeg + $xlen - 1 );
-               }
-               if ( $ylen > 1 ) {
-                       $ybeg .= ',' . ( $ybeg + $ylen - 1 );
-               }
-
-               return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
-       }
-
-       function _start_block( $header ) {
-               echo $header . "\n";
-       }
-
-       function _end_block() {
-       }
-
-       /**
-        * @param $lines
-        * @param $prefix string
-        */
-       function _lines( $lines, $prefix = ' ' ) {
-               foreach ( $lines as $line ) {
-                       echo "$prefix $line\n";
-               }
-       }
-
-       /**
-        * @param $lines
-        */
-       function _context( $lines ) {
-               $this->_lines( $lines );
-       }
-
-       /**
-        * @param $lines
-        */
-       function _added( $lines ) {
-               $this->_lines( $lines, '>' );
-       }
-
-       /**
-        * @param $lines
-        */
-       function _deleted( $lines ) {
-               $this->_lines( $lines, '<' );
-       }
-
-       /**
-        * @param $orig
-        * @param $closing
-        */
-       function _changed( $orig, $closing ) {
-               $this->_deleted( $orig );
-               echo "---\n";
-               $this->_added( $closing );
-       }
-}
-
-/**
- * A formatter that outputs unified diffs
- * @ingroup DifferenceEngine
- */
-class UnifiedDiffFormatter extends DiffFormatter {
-       var $leading_context_lines = 2;
-       var $trailing_context_lines = 2;
-
-       /**
-        * @param $lines
-        */
-       function _added( $lines ) {
-               $this->_lines( $lines, '+' );
-       }
-
-       /**
-        * @param $lines
-        */
-       function _deleted( $lines ) {
-               $this->_lines( $lines, '-' );
-       }
-
-       /**
-        * @param $orig
-        * @param $closing
-        */
-       function _changed( $orig, $closing ) {
-               $this->_deleted( $orig );
-               $this->_added( $closing );
-       }
-
-       /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
-        * @return string
-        */
-       function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
-               return "@@ -$xbeg,$xlen +$ybeg,$ylen @@";
-       }
-}
-
-/**
- * A pseudo-formatter that just passes along the Diff::$edits array
- * @ingroup DifferenceEngine
- */
-class ArrayDiffFormatter extends DiffFormatter {
-
-       /**
-        * @param $diff
-        * @return array
-        */
-       function format( $diff ) {
-               $oldline = 1;
-               $newline = 1;
-               $retval = array();
-               foreach ( $diff->edits as $edit ) {
-                       switch ( $edit->type ) {
-                               case 'add':
-                                       foreach ( $edit->closing as $l ) {
-                                               $retval[] = array(
-                                                       'action' => 'add',
-                                                       'new' => $l,
-                                                       'newline' => $newline++
-                                               );
-                                       }
-                                       break;
-                               case 'delete':
-                                       foreach ( $edit->orig as $l ) {
-                                               $retval[] = array(
-                                                       'action' => 'delete',
-                                                       'old' => $l,
-                                                       'oldline' => $oldline++,
-                                               );
-                                       }
-                                       break;
-                               case 'change':
-                                       foreach ( $edit->orig as $i => $l ) {
-                                               $retval[] = array(
-                                                       'action' => 'change',
-                                                       'old' => $l,
-                                                       'new' => isset( $edit->closing[$i] ) ? $edit->closing[$i] : null,
-                                                       'oldline' => $oldline++,
-                                                       'newline' => $newline++,
-                                               );
-                                       }
-                                       break;
-                               case 'copy':
-                                       $oldline += count( $edit->orig );
-                                       $newline += count( $edit->orig );
-                       }
-               }
-               return $retval;
-       }
-}
-
 /**
  * Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
  */
 
-define( 'NBSP', '&#160;' ); // iso-8859-x non-breaking space.
-
 /**
  * @todo document
  * @private
  * @ingroup DifferenceEngine
  */
-class _HWLDF_WordAccumulator {
-       function __construct() {
-               $this->_lines = array();
-               $this->_line = '';
-               $this->_group = '';
-               $this->_tag = '';
-       }
+class HWLDFWordAccumulator {
+       private $lines = array();
+       private $line = '';
+       private $group = '';
+       private $tag = '';
 
        /**
         * @param $new_tag
         */
-       function _flushGroup( $new_tag ) {
-               if ( $this->_group !== '' ) {
-                       if ( $this->_tag == 'ins' ) {
-                               $this->_line .= '<ins class="diffchange diffchange-inline">' .
-                                               htmlspecialchars( $this->_group ) . '</ins>';
-                       } elseif ( $this->_tag == 'del' ) {
-                               $this->_line .= '<del class="diffchange diffchange-inline">' .
-                                               htmlspecialchars( $this->_group ) . '</del>';
+       private function flushGroup( $new_tag ) {
+               if ( $this->group !== '' ) {
+                       if ( $this->tag == 'ins' ) {
+                               $this->line .= '<ins class="diffchange diffchange-inline">' .
+                                       htmlspecialchars( $this->group ) . '</ins>';
+                       } elseif ( $this->tag == 'del' ) {
+                               $this->line .= '<del class="diffchange diffchange-inline">' .
+                                       htmlspecialchars( $this->group ) . '</del>';
                        } else {
-                               $this->_line .= htmlspecialchars( $this->_group );
+                               $this->line .= htmlspecialchars( $this->group );
                        }
                }
-               $this->_group = '';
-               $this->_tag = $new_tag;
+               $this->group = '';
+               $this->tag = $new_tag;
        }
 
        /**
         * @param $new_tag
         */
-       function _flushLine( $new_tag ) {
-               $this->_flushGroup( $new_tag );
-               if ( $this->_line != '' ) {
-                       array_push( $this->_lines, $this->_line );
+       private function flushLine( $new_tag ) {
+               $this->flushGroup( $new_tag );
+               if ( $this->line != '' ) {
+                       array_push( $this->lines, $this->line );
                } else {
                        # make empty lines visible by inserting an NBSP
-                       array_push( $this->_lines, NBSP );
+                       array_push( $this->lines, '&#160;' );
                }
-               $this->_line = '';
+               $this->line = '';
        }
 
        /**
         * @param $words
         * @param $tag string
         */
-       function addWords( $words, $tag = '' ) {
-               if ( $tag != $this->_tag ) {
-                       $this->_flushGroup( $tag );
+       public function addWords( $words, $tag = '' ) {
+               if ( $tag != $this->tag ) {
+                       $this->flushGroup( $tag );
                }
 
                foreach ( $words as $word ) {
@@ -1217,20 +889,21 @@ class _HWLDF_WordAccumulator {
                                continue;
                        }
                        if ( $word[0] == "\n" ) {
-                               $this->_flushLine( $tag );
+                               $this->flushLine( $tag );
                                $word = substr( $word, 1 );
                        }
                        assert( '!strstr( $word, "\n" )' );
-                       $this->_group .= $word;
+                       $this->group .= $word;
                }
        }
 
        /**
         * @return array
         */
-       function getLines() {
-               $this->_flushLine( '~done' );
-               return $this->_lines;
+       public function getLines() {
+               $this->flushLine( '~done' );
+
+               return $this->lines;
        }
 }
 
@@ -1249,11 +922,11 @@ class WordLevelDiff extends MappedDiff {
        function __construct( $orig_lines, $closing_lines ) {
                wfProfileIn( __METHOD__ );
 
-               list( $orig_words, $orig_stripped ) = $this->_split( $orig_lines );
-               list( $closing_words, $closing_stripped ) = $this->_split( $closing_lines );
+               list( $orig_words, $orig_stripped ) = $this->split( $orig_lines );
+               list( $closing_words, $closing_stripped ) = $this->split( $closing_lines );
 
                parent::__construct( $orig_words, $closing_words,
-               $orig_stripped, $closing_stripped );
+                       $orig_stripped, $closing_stripped );
                wfProfileOut( __METHOD__ );
        }
 
@@ -1261,7 +934,7 @@ class WordLevelDiff extends MappedDiff {
         * @param $lines
         * @return array
         */
-       function _split( $lines ) {
+       private function split( $lines ) {
                wfProfileIn( __METHOD__ );
 
                $words = array();
@@ -1282,8 +955,8 @@ class WordLevelDiff extends MappedDiff {
                        } else {
                                $m = array();
                                if ( preg_match_all( '/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
-                                       $line, $m ) )
-                               {
+                                       $line, $m )
+                               {
                                        foreach ( $m[0] as $word ) {
                                                $words[] = $word;
                                        }
@@ -1294,15 +967,16 @@ class WordLevelDiff extends MappedDiff {
                        }
                }
                wfProfileOut( __METHOD__ );
+
                return array( $words, $stripped );
        }
 
        /**
         * @return array
         */
-       function orig() {
+       public function orig() {
                wfProfileIn( __METHOD__ );
-               $orig = new _HWLDF_WordAccumulator;
+               $orig = new HWLDFWordAccumulator;
 
                foreach ( $this->edits as $edit ) {
                        if ( $edit->type == 'copy' ) {
@@ -1313,15 +987,16 @@ class WordLevelDiff extends MappedDiff {
                }
                $lines = $orig->getLines();
                wfProfileOut( __METHOD__ );
+
                return $lines;
        }
 
        /**
         * @return array
         */
-       function closing() {
+       public function closing() {
                wfProfileIn( __METHOD__ );
-               $closing = new _HWLDF_WordAccumulator;
+               $closing = new HWLDFWordAccumulator;
 
                foreach ( $this->edits as $edit ) {
                        if ( $edit->type == 'copy' ) {
@@ -1332,164 +1007,7 @@ class WordLevelDiff extends MappedDiff {
                }
                $lines = $closing->getLines();
                wfProfileOut( __METHOD__ );
-               return $lines;
-       }
-}
-
-/**
- * Wikipedia Table style diff formatter.
- * @todo document
- * @private
- * @ingroup DifferenceEngine
- */
-class TableDiffFormatter extends DiffFormatter {
-       function __construct() {
-               $this->leading_context_lines = 2;
-               $this->trailing_context_lines = 2;
-       }
 
-       /**
-        * @static
-        * @param $msg
-        * @return mixed
-        */
-       public static function escapeWhiteSpace( $msg ) {
-               $msg = preg_replace( '/^ /m', '&#160; ', $msg );
-               $msg = preg_replace( '/ $/m', ' &#160;', $msg );
-               $msg = preg_replace( '/  /', '&#160; ', $msg );
-               return $msg;
-       }
-
-       /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
-        * @return string
-        */
-       function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
-               $r = '<tr><td colspan="2" class="diff-lineno"><!--LINE ' . $xbeg . "--></td>\n" .
-                       '<td colspan="2" class="diff-lineno"><!--LINE ' . $ybeg . "--></td></tr>\n";
-               return $r;
-       }
-
-       /**
-        * @param $header
-        */
-       function _start_block( $header ) {
-               echo $header;
-       }
-
-       function _end_block() {
-       }
-
-       function _lines( $lines, $prefix = ' ', $color = 'white' ) {
-       }
-
-       /**
-        * HTML-escape parameter before calling this
-        * @param $line
-        * @return string
-        */
-       function addedLine( $line ) {
-               return $this->wrapLine( '+', 'diff-addedline', $line );
-       }
-
-       /**
-        * HTML-escape parameter before calling this
-        * @param $line
-        * @return string
-        */
-       function deletedLine( $line ) {
-               return $this->wrapLine( '−', 'diff-deletedline', $line );
-       }
-
-       /**
-        * HTML-escape parameter before calling this
-        * @param $line
-        * @return string
-        */
-       function contextLine( $line ) {
-               return $this->wrapLine( '&#160;', 'diff-context', $line );
-       }
-
-       /**
-        * @param $marker
-        * @param $class
-        * @param $line
-        * @return string
-        */
-       private function wrapLine( $marker, $class, $line ) {
-               if ( $line !== '' ) {
-                       // The <div> wrapper is needed for 'overflow: auto' style to scroll properly
-                       $line = Xml::tags( 'div', null, $this->escapeWhiteSpace( $line ) );
-               }
-               return "<td class='diff-marker'>$marker</td><td class='$class'>$line</td>";
-       }
-
-       /**
-        * @return string
-        */
-       function emptyLine() {
-               return '<td colspan="2">&#160;</td>';
-       }
-
-       /**
-        * @param $lines array
-        */
-       function _added( $lines ) {
-               foreach ( $lines as $line ) {
-                       echo '<tr>' . $this->emptyLine() .
-                       $this->addedLine( '<ins class="diffchange">' .
-                       htmlspecialchars( $line ) . '</ins>' ) . "</tr>\n";
-               }
-       }
-
-       /**
-        * @param $lines
-        */
-       function _deleted( $lines ) {
-               foreach ( $lines as $line ) {
-                       echo '<tr>' . $this->deletedLine( '<del class="diffchange">' .
-                       htmlspecialchars( $line ) . '</del>' ) .
-                       $this->emptyLine() . "</tr>\n";
-               }
-       }
-
-       /**
-        * @param $lines
-        */
-       function _context( $lines ) {
-               foreach ( $lines as $line ) {
-                       echo '<tr>' .
-                       $this->contextLine( htmlspecialchars( $line ) ) .
-                       $this->contextLine( htmlspecialchars( $line ) ) . "</tr>\n";
-               }
-       }
-
-       /**
-        * @param $orig
-        * @param $closing
-        */
-       function _changed( $orig, $closing ) {
-               wfProfileIn( __METHOD__ );
-
-               $diff = new WordLevelDiff( $orig, $closing );
-               $del = $diff->orig();
-               $add = $diff->closing();
-
-               # Notice that WordLevelDiff returns HTML-escaped output.
-               # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
-
-               while ( $line = array_shift( $del ) ) {
-                       $aline = array_shift( $add );
-                       echo '<tr>' . $this->deletedLine( $line ) .
-                       $this->addedLine( $aline ) . "</tr>\n";
-               }
-               foreach ( $add as $line ) {     # If any leftovers
-                       echo '<tr>' . $this->emptyLine() .
-                       $this->addedLine( $line ) . "</tr>\n";
-               }
-               wfProfileOut( __METHOD__ );
+               return $lines;
        }
 }
diff --git a/includes/diff/DiffFormatter.php b/includes/diff/DiffFormatter.php
new file mode 100644 (file)
index 0000000..d9e1c95
--- /dev/null
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Base for diff rendering classes. Portions taken from phpwiki-1.3.3.
+ *
+ * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
+ * You may copy this code freely under the conditions of the GPL.
+ *
+ * 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 DifferenceEngine
+ */
+
+/**
+ * Base class for diff formatters
+ *
+ * This class formats the diff in classic diff format.
+ * It is intended that this class be customized via inheritance,
+ * to obtain fancier outputs.
+ * @todo document
+ * @ingroup DifferenceEngine
+ */
+abstract class DiffFormatter {
+       /** @var int Number of leading context "lines" to preserve.
+        *
+        * This should be left at zero for this class, but subclasses
+        * may want to set this to other values.
+        */
+       protected $leadingContextLines = 0;
+
+       /** @var int Number of trailing context "lines" to preserve.
+        *
+        * This should be left at zero for this class, but subclasses
+        * may want to set this to other values.
+        */
+       protected $trailingContextLines = 0;
+
+       /**
+        * Format a diff.
+        *
+        * @param $diff Diff A Diff object.
+        * @return string The formatted output.
+        */
+       public function format( $diff ) {
+               wfProfileIn( __METHOD__ );
+
+               $xi = $yi = 1;
+               $block = false;
+               $context = array();
+
+               $nlead = $this->leadingContextLines;
+               $ntrail = $this->trailingContextLines;
+
+               $this->startDiff();
+
+               // Initialize $x0 and $y0 to prevent IDEs from getting confused.
+               $x0 = $y0 = 0;
+               foreach ( $diff->edits as $edit ) {
+                       if ( $edit->type == 'copy' ) {
+                               if ( is_array( $block ) ) {
+                                       if ( count( $edit->orig ) <= $nlead + $ntrail ) {
+                                               $block[] = $edit;
+                                       } else {
+                                               if ( $ntrail ) {
+                                                       $context = array_slice( $edit->orig, 0, $ntrail );
+                                                       $block[] = new DiffOpCopy( $context );
+                                               }
+                                               $this->block( $x0, $ntrail + $xi - $x0,
+                                                       $y0, $ntrail + $yi - $y0,
+                                                       $block );
+                                               $block = false;
+                                       }
+                               }
+                               $context = $edit->orig;
+                       } else {
+                               if ( !is_array( $block ) ) {
+                                       $context = array_slice( $context, count( $context ) - $nlead );
+                                       $x0 = $xi - count( $context );
+                                       $y0 = $yi - count( $context );
+                                       $block = array();
+                                       if ( $context ) {
+                                               $block[] = new DiffOpCopy( $context );
+                                       }
+                               }
+                               $block[] = $edit;
+                       }
+
+                       if ( $edit->orig ) {
+                               $xi += count( $edit->orig );
+                       }
+                       if ( $edit->closing ) {
+                               $yi += count( $edit->closing );
+                       }
+               }
+
+               if ( is_array( $block ) ) {
+                       $this->block( $x0, $xi - $x0,
+                               $y0, $yi - $y0,
+                               $block );
+               }
+
+               $end = $this->endDiff();
+               wfProfileOut( __METHOD__ );
+
+               return $end;
+       }
+
+       /**
+        * @param int $xbeg
+        * @param int $xlen
+        * @param int $ybeg
+        * @param int $ylen
+        * @param $edits
+        * @throws MWException
+        */
+       protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
+               wfProfileIn( __METHOD__ );
+               $this->startBlock( $this->blockHeader( $xbeg, $xlen, $ybeg, $ylen ) );
+               foreach ( $edits as $edit ) {
+                       if ( $edit->type == 'copy' ) {
+                               $this->context( $edit->orig );
+                       } elseif ( $edit->type == 'add' ) {
+                               $this->added( $edit->closing );
+                       } elseif ( $edit->type == 'delete' ) {
+                               $this->deleted( $edit->orig );
+                       } elseif ( $edit->type == 'change' ) {
+                               $this->changed( $edit->orig, $edit->closing );
+                       } else {
+                               throw new MWException( "Unknown edit type: {$edit->type}" );
+                       }
+               }
+               $this->endBlock();
+               wfProfileOut( __METHOD__ );
+       }
+
+       protected function startDiff() {
+               ob_start();
+       }
+
+       /**
+        * @return string
+        */
+       protected function endDiff() {
+               $val = ob_get_contents();
+               ob_end_clean();
+
+               return $val;
+       }
+
+       /**
+        * @param $xbeg
+        * @param $xlen
+        * @param $ybeg
+        * @param $ylen
+        * @return string
+        */
+       protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
+               if ( $xlen > 1 ) {
+                       $xbeg .= ',' . ( $xbeg + $xlen - 1 );
+               }
+               if ( $ylen > 1 ) {
+                       $ybeg .= ',' . ( $ybeg + $ylen - 1 );
+               }
+
+               return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
+       }
+
+       protected function startBlock( $header ) {
+               echo $header . "\n";
+       }
+
+       protected function endBlock() {
+       }
+
+       /**
+        * @param $lines
+        * @param $prefix string
+        */
+       protected function lines( $lines, $prefix = ' ' ) {
+               foreach ( $lines as $line ) {
+                       echo "$prefix $line\n";
+               }
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function context( $lines ) {
+               $this->lines( $lines );
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function added( $lines ) {
+               $this->lines( $lines, '>' );
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function deleted( $lines ) {
+               $this->lines( $lines, '<' );
+       }
+
+       /**
+        * @param $orig
+        * @param $closing
+        */
+       protected function changed( $orig, $closing ) {
+               $this->deleted( $orig );
+               echo "---\n";
+               $this->added( $closing );
+       }
+}
index e436f58..6e74f2c 100644 (file)
@@ -34,60 +34,79 @@ define( 'MW_DIFF_VERSION', '1.11a' );
  * @ingroup DifferenceEngine
  */
 class DifferenceEngine extends ContextSource {
-       /**#@+
-        * @private
-        */
-       var $mOldid, $mNewid;
-       var $mOldTags, $mNewTags;
-       /**
-        * @var Content
-        */
-       var $mOldContent, $mNewContent;
+       /** @var int */
+       public $mOldid;
+
+       /** @var int */
+       public $mNewid;
+
+       private $mOldTags;
+       private $mNewTags;
+
+       /** @var Content */
+       public $mOldContent;
+
+       /** @var Content */
+       public $mNewContent;
+
+       /** @var Language */
        protected $mDiffLang;
 
-       /**
-        * @var Title
-        */
-       var $mOldPage, $mNewPage;
+       /** @var  Title */
+       public $mOldPage;
 
-       /**
-        * @var Revision
-        */
-       var $mOldRev, $mNewRev;
-       private $mRevisionsIdsLoaded = false; // Have the revisions IDs been loaded
-       var $mRevisionsLoaded = false; // Have the revisions been loaded
-       var $mTextLoaded = 0; // How many text blobs have been loaded, 0, 1 or 2?
-       var $mCacheHit = false; // Was the diff fetched from cache?
+       /** @var  Title */
+       public $mNewPage;
+
+       /** @var Revision */
+       public $mOldRev;
+
+       /** @var  Revision */
+       public $mNewRev;
+
+       /** @var bool Have the revisions IDs been loaded */
+       private $mRevisionsIdsLoaded = false;
+
+       /** @var bool Have the revisions been loaded */
+       public $mRevisionsLoaded = false;
+
+       /** @var int How many text blobs have been loaded, 0, 1 or 2? */
+       public $mTextLoaded = 0;
+
+       /** @var bool Was the diff fetched from cache? */
+       public $mCacheHit = false;
 
        /**
         * Set this to true to add debug info to the HTML output.
         * Warning: this may cause RSS readers to spuriously mark articles as "new"
         * (bug 20601)
         */
-       var $enableDebugComment = false;
+       public $enableDebugComment = false;
 
-       // If true, line X is not displayed when X is 1, for example to increase
-       // readability and conserve space with many small diffs.
+       /** @var bool  If true, line X is not displayed when X is 1, for example
+        *    to increase readability and conserve space with many small diffs.
+        */
        protected $mReducedLineNumbers = false;
 
-       // Link to action=markpatrolled
+       /** @var string Link to action=markpatrolled  */
        protected $mMarkPatrolledLink = null;
 
-       protected $unhide = false; # show rev_deleted content if allowed
+       /** @var bool Show rev_deleted content if allowed */
+       protected $unhide = false;
        /**#@-*/
 
        /**
         * Constructor
         * @param $context IContextSource context to use, anything else will be ignored
         * @param $old Integer old ID we want to show and diff with.
-        * @param $new String either 'prev' or 'next'.
+        * @param $new String|int either revision ID or 'prev' or 'next'. Default: 0.
         * @param $rcid Integer Deprecated, no longer used!
         * @param $refreshCache boolean If set, refreshes the diff cache
         * @param $unhide boolean If set, allow viewing deleted revs
         */
        function __construct( $context = null, $old = 0, $new = 0, $rcid = 0,
-               $refreshCache = false, $unhide = false )
-       {
+               $refreshCache = false, $unhide = false
+       {
                if ( $context instanceof IContextSource ) {
                        $this->setContext( $context );
                }
@@ -115,6 +134,7 @@ class DifferenceEngine extends ContextSource {
                        # Default language in which the diff text is written.
                        $this->mDiffLang = $this->getTitle()->getPageLanguage();
                }
+
                return $this->mDiffLang;
        }
 
@@ -130,6 +150,7 @@ class DifferenceEngine extends ContextSource {
         */
        function getOldid() {
                $this->loadRevisionIds();
+
                return $this->mOldid;
        }
 
@@ -138,6 +159,7 @@ class DifferenceEngine extends ContextSource {
         */
        function getNewid() {
                $this->loadRevisionIds();
+
                return $this->mNewid;
        }
 
@@ -157,12 +179,14 @@ class DifferenceEngine extends ContextSource {
                        if ( $row ) {
                                $rev = Revision::newFromArchiveRow( $row );
                                $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
+
                                return SpecialPage::getTitleFor( 'Undelete' )->getFullURL( array(
                                        'target' => $title->getPrefixedText(),
                                        'timestamp' => $rev->getTimestamp()
-                               ));
+                               ) );
                        }
                }
+
                return false;
        }
 
@@ -212,6 +236,7 @@ class DifferenceEngine extends ContextSource {
                if ( !$this->loadRevisionData() ) {
                        $this->showMissingRevision();
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -227,7 +252,6 @@ class DifferenceEngine extends ContextSource {
                }
 
                $rollback = '';
-               $undoLink = '';
 
                $query = array();
                # Carry over 'diffonly' param via navigation links
@@ -259,8 +283,8 @@ class DifferenceEngine extends ContextSource {
                                $out->setPageTitle( $this->msg( 'difference-title', $this->mNewPage->getPrefixedText() ) );
                                $samePage = true;
                        } else {
-                               $out->setPageTitle( $this->msg( 'difference-title-multipage', $this->mOldPage->getPrefixedText(),
-                                       $this->mNewPage->getPrefixedText() ) );
+                               $out->setPageTitle( $this->msg( 'difference-title-multipage',
+                                       $this->mOldPage->getPrefixedText(), $this->mNewPage->getPrefixedText() ) );
                                $out->addSubtitle( $this->msg( 'difference-multipage' ) );
                                $samePage = false;
                        }
@@ -273,12 +297,16 @@ class DifferenceEngine extends ContextSource {
                                                $rollback = '&#160;&#160;&#160;' . $rollbackLink;
                                        }
                                }
-                               if ( !$this->mOldRev->isDeleted( Revision::DELETED_TEXT ) && !$this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) {
+
+                               if ( !$this->mOldRev->isDeleted( Revision::DELETED_TEXT ) &&
+                                       !$this->mNewRev->isDeleted( Revision::DELETED_TEXT )
+                               ) {
                                        $undoLink = Html::element( 'a', array(
                                                        'href' => $this->mNewPage->getLocalURL( array(
                                                                'action' => 'edit',
                                                                'undoafter' => $this->mOldid,
-                                                               'undo' => $this->mNewid ) ),
+                                                               'undo' => $this->mNewid
+                                                       ) ),
                                                        'title' => Linker::titleAttrib( 'undo' )
                                                ),
                                                $this->msg( 'editundo' )->text()
@@ -311,9 +339,9 @@ class DifferenceEngine extends ContextSource {
 
                        $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $oldRevisionHeader . '</strong></div>' .
                                '<div id="mw-diff-otitle2">' .
-                                       Linker::revUserTools( $this->mOldRev, !$this->unhide ) . '</div>' .
+                               Linker::revUserTools( $this->mOldRev, !$this->unhide ) . '</div>' .
                                '<div id="mw-diff-otitle3">' . $oldminor .
-                                       Linker::revComment( $this->mOldRev, !$diffOnly, !$this->unhide ) . $ldel . '</div>' .
+                               Linker::revComment( $this->mOldRev, !$diffOnly, !$this->unhide ) . $ldel . '</div>' .
                                '<div id="mw-diff-otitle5">' . $oldChangeTags[0] . '</div>' .
                                '<div id="mw-diff-otitle4">' . $prevlink . '</div>';
 
@@ -359,14 +387,15 @@ class DifferenceEngine extends ContextSource {
                foreach ( $revisionTools as $tool ) {
                        $formattedRevisionTools[] = $this->msg( 'parentheses' )->rawParams( $tool )->escaped();
                }
-               $newRevisionHeader = $this->getRevisionHeader( $this->mNewRev, 'complete' ) . ' ' . implode( ' ', $formattedRevisionTools );
+               $newRevisionHeader = $this->getRevisionHeader( $this->mNewRev, 'complete' ) .
+                       ' ' . implode( ' ', $formattedRevisionTools );
                $newChangeTags = ChangeTags::formatSummaryRow( $this->mNewTags, 'diff' );
 
                $newHeader = '<div id="mw-diff-ntitle1"><strong>' . $newRevisionHeader . '</strong></div>' .
                        '<div id="mw-diff-ntitle2">' . Linker::revUserTools( $this->mNewRev, !$this->unhide ) .
-                               " $rollback</div>" .
+                       " $rollback</div>" .
                        '<div id="mw-diff-ntitle3">' . $newminor .
-                               Linker::revComment( $this->mNewRev, !$diffOnly, !$this->unhide ) . $rdel . '</div>' .
+                       Linker::revComment( $this->mNewRev, !$diffOnly, !$this->unhide ) . $rdel . '</div>' .
                        '<div id="mw-diff-ntitle5">' . $newChangeTags[0] . '</div>' .
                        '<div id="mw-diff-ntitle4">' . $nextlink . $this->markPatrolledLink() . '</div>';
 
@@ -390,9 +419,13 @@ class DifferenceEngine extends ContextSource {
                                        array( $msg ) );
                        } else {
                                # Give explanation and add a link to view the diff...
-                               $link = $this->getTitle()->getFullURL( $this->getRequest()->appendQueryValue( 'unhide', '1', true ) );
+                               $query = $this->getRequest()->appendQueryValue( 'unhide', '1', true );
+                               $link = $this->getTitle()->getFullURL( $query );
                                $msg = $suppressed ? 'rev-suppressed-unhide-diff' : 'rev-deleted-unhide-diff';
-                               $out->wrapWikiMsg( "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n", array( $msg, $link ) );
+                               $out->wrapWikiMsg(
+                                       "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n",
+                                       array( $msg, $link )
+                               );
                        }
                # Otherwise, output a regular diff...
                } else {
@@ -400,7 +433,9 @@ class DifferenceEngine extends ContextSource {
                        $notice = '';
                        if ( $deleted ) {
                                $msg = $suppressed ? 'rev-suppressed-diff-view' : 'rev-deleted-diff-view';
-                               $notice = "<div id='mw-$msg' class='mw-warning plainlinks'>\n" . $this->msg( $msg )->parse() . "</div>\n";
+                               $notice = "<div id='mw-$msg' class='mw-warning plainlinks'>\n" .
+                                       $this->msg( $msg )->parse() .
+                                       "</div>\n";
                        }
                        $this->showDiff( $oldHeader, $newHeader, $notice );
                        if ( !$diffOnly ) {
@@ -491,6 +526,7 @@ class DifferenceEngine extends ContextSource {
                if ( $link !== '' ) {
                        $link = '&#160;&#160;&#160;' . $link . ' ';
                }
+
                return $link;
        }
 
@@ -505,6 +541,7 @@ class DifferenceEngine extends ContextSource {
                $out->addHTML( "<hr class='diff-hr' />
                <h2 class='diff-currentversion-title'>{$revHeader}</h2>\n" );
                # Page content may be handled by a hooked call instead...
+               # @codingStandardsIgnoreStart Ignoring long lines.
                if ( wfRunHooks( 'ArticleContentOnDiff', array( $this, $out ) ) ) {
                        $this->loadNewText();
                        $out->setRevisionId( $this->mNewid );
@@ -560,6 +597,8 @@ class DifferenceEngine extends ContextSource {
                                }
                        }
                }
+               # @codingStandardsIgnoreEnd
+
                # Add redundant patrol link on bottom...
                $out->addHTML( $this->markPatrolledLink() );
 
@@ -574,6 +613,7 @@ class DifferenceEngine extends ContextSource {
                }
 
                $parserOutput = $page->getParserOutput( $parserOptions, $rev->getId() );
+
                return $parserOutput;
        }
 
@@ -581,16 +621,22 @@ class DifferenceEngine extends ContextSource {
         * Get the diff text, send it to the OutputPage object
         * Returns false if the diff could not be generated, otherwise returns true
         *
+        * @param string|bool $otitle Header for old text or false
+        * @param string|bool $ntitle Header for new text or false
+        * @param string $notice HTML between diff header and body
+        *
         * @return bool
         */
        function showDiff( $otitle, $ntitle, $notice = '' ) {
                $diff = $this->getDiff( $otitle, $ntitle, $notice );
                if ( $diff === false ) {
                        $this->showMissingRevision();
+
                        return false;
                } else {
                        $this->showDiffStyle();
                        $this->getOutput()->addHTML( $diff );
+
                        return true;
                }
        }
@@ -614,14 +660,17 @@ class DifferenceEngine extends ContextSource {
                $body = $this->getDiffBody();
                if ( $body === false ) {
                        return false;
-               } else {
-                       $multi = $this->getMultiNotice();
-                       // Display a message when the diff is empty
-                       if ( $body === '' ) {
-                               $notice .= '<div class="mw-diff-empty">' . $this->msg( 'diff-empty' )->parse() . "</div>\n";
-                       }
-                       return $this->addHeader( $body, $otitle, $ntitle, $multi, $notice );
                }
+
+               $multi = $this->getMultiNotice();
+               // Display a message when the diff is empty
+               if ( $body === '' ) {
+                       $notice .= '<div class="mw-diff-empty">' .
+                               $this->msg( 'diff-empty' )->parse() .
+                               "</div>\n";
+               }
+
+               return $this->addHeader( $body, $otitle, $ntitle, $multi, $notice );
        }
 
        /**
@@ -636,26 +685,34 @@ class DifferenceEngine extends ContextSource {
                // Check if the diff should be hidden from this user
                if ( !$this->loadRevisionData() ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
-               } elseif ( $this->mOldRev && !$this->mOldRev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
+               } elseif ( $this->mOldRev &&
+                       !$this->mOldRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+               ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
-               } elseif ( $this->mNewRev && !$this->mNewRev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
+               } elseif ( $this->mNewRev &&
+                       !$this->mNewRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+               ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
                // Short-circuit
                if ( $this->mOldRev === false || ( $this->mOldRev && $this->mNewRev
-                       && $this->mOldRev->getID() == $this->mNewRev->getID() ) )
-               {
+                       && $this->mOldRev->getID() == $this->mNewRev->getID() )
+               {
                        wfProfileOut( __METHOD__ );
+
                        return '';
                }
                // Cacheable?
                $key = false;
                if ( $this->mOldid && $this->mNewid ) {
-                       $key = wfMemcKey( 'diff', 'version', MW_DIFF_VERSION,
-                               'oldid', $this->mOldid, 'newid', $this->mNewid );
+                       $key = $this->getDiffBodyCacheKey();
+
                        // Try cache
                        if ( !$this->mRefreshCache ) {
                                $difftext = $wgMemc->get( $key );
@@ -664,6 +721,7 @@ class DifferenceEngine extends ContextSource {
                                        $difftext = $this->localiseLineNumbers( $difftext );
                                        $difftext .= "\n<!-- diff cache key $key -->\n";
                                        wfProfileOut( __METHOD__ );
+
                                        return $difftext;
                                }
                        } // don't try to load but save the result
@@ -673,6 +731,7 @@ class DifferenceEngine extends ContextSource {
                // Loadtext is permission safe, this just clears out the diff
                if ( !$this->loadText() ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
 
@@ -692,9 +751,26 @@ class DifferenceEngine extends ContextSource {
                        $difftext = $this->localiseLineNumbers( $difftext );
                }
                wfProfileOut( __METHOD__ );
+
                return $difftext;
        }
 
+       /**
+        * Returns the cache key for diff body text or content.
+        *
+        * @return string
+        * @since 1.23
+        * @throws MWException
+        */
+       protected function getDiffBodyCacheKey() {
+               if ( !$this->mOldid || !$this->mNewid ) {
+                       throw new MWException( 'mOldid and mNewid must be set to get diff cache key.' );
+               }
+
+               return wfMemcKey( 'diff', 'version', MW_DIFF_VERSION,
+                       'oldid', $this->mOldid, 'newid', $this->mNewid );
+       }
+
        /**
         * Generate a diff, no caching.
         *
@@ -715,8 +791,8 @@ class DifferenceEngine extends ContextSource {
         */
        function generateContentDiffBody( Content $old, Content $new ) {
                if ( !( $old instanceof TextContent ) ) {
-                       throw new MWException( "Diff not implemented for " . get_class( $old ) . "; "
-                                       . "override generateContentDiffBody to fix this." );
+                       throw new MWException( "Diff not implemented for " . get_class( $old ) . "; " .
+                               "override generateContentDiffBody to fix this." );
                }
 
                if ( !( $new instanceof TextContent ) ) {
@@ -764,9 +840,10 @@ class DifferenceEngine extends ContextSource {
                if ( $wgExternalDiffEngine == 'wikidiff' && function_exists( 'wikidiff_do_diff' ) ) {
                        # For historical reasons, external diff engine expects
                        # input text to be HTML-escaped already
-                       $otext = htmlspecialchars ( $wgContLang->segmentForDiff( $otext ) );
-                       $ntext = htmlspecialchars ( $wgContLang->segmentForDiff( $ntext ) );
+                       $otext = htmlspecialchars( $wgContLang->segmentForDiff( $otext ) );
+                       $ntext = htmlspecialchars( $wgContLang->segmentForDiff( $ntext ) );
                        wfProfileOut( __METHOD__ );
+
                        return $wgContLang->unsegmentForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) ) .
                        $this->debug( 'wikidiff1' );
                }
@@ -779,6 +856,7 @@ class DifferenceEngine extends ContextSource {
                        $text .= $this->debug( 'wikidiff2' );
                        wfProfileOut( 'wikidiff2_do_diff' );
                        wfProfileOut( __METHOD__ );
+
                        return $text;
                }
                if ( $wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false ) {
@@ -790,11 +868,13 @@ class DifferenceEngine extends ContextSource {
                        $tempFile1 = fopen( $tempName1, "w" );
                        if ( !$tempFile1 ) {
                                wfProfileOut( __METHOD__ );
+
                                return false;
                        }
                        $tempFile2 = fopen( $tempName2, "w" );
                        if ( !$tempFile2 ) {
                                wfProfileOut( __METHOD__ );
+
                                return false;
                        }
                        fwrite( $tempFile1, $otext );
@@ -809,6 +889,7 @@ class DifferenceEngine extends ContextSource {
                        unlink( $tempName1 );
                        unlink( $tempName2 );
                        wfProfileOut( __METHOD__ );
+
                        return $difftext;
                }
 
@@ -818,13 +899,17 @@ class DifferenceEngine extends ContextSource {
                $diffs = new Diff( $ota, $nta );
                $formatter = new TableDiffFormatter();
                $difftext = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ) .
-               wfProfileOut( __METHOD__ );
+                       wfProfileOut( __METHOD__ );
+
                return $difftext;
        }
 
        /**
         * Generate a debug comment indicating diff generating time,
         * server node, and generator backend.
+        *
+        * @param String $generator : What diff engine was used
+        *
         * @return string
         */
        protected function debug( $generator = "internal" ) {
@@ -837,27 +922,32 @@ class DifferenceEngine extends ContextSource {
                        $data[] = wfHostname();
                }
                $data[] = wfTimestamp( TS_DB );
+
                return "<!-- diff generator: " .
-               implode( " ",
-               array_map(
-                                       "htmlspecialchars",
-               $data ) ) .
+                       implode( " ", array_map( "htmlspecialchars", $data ) ) .
                        " -->\n";
        }
 
        /**
         * Replace line numbers with the text in the user's language
+        *
+        * @param String $text
+        *
         * @return mixed
         */
        function localiseLineNumbers( $text ) {
-               return preg_replace_callback( '/<!--LINE (\d+)-->/',
-               array( &$this, 'localiseLineNumbersCb' ), $text );
+               return preg_replace_callback(
+                       '/<!--LINE (\d+)-->/',
+                       array( &$this, 'localiseLineNumbersCb' ),
+                       $text
+               );
        }
 
        function localiseLineNumbersCb( $matches ) {
                if ( $matches[1] === '1' && $this->mReducedLineNumbers ) {
                        return '';
                }
+
                return $this->msg( 'lineno' )->numParams( $matches[1] )->escaped();
        }
 
@@ -885,8 +975,10 @@ class DifferenceEngine extends ContextSource {
                if ( $nEdits > 0 ) {
                        $limit = 100; // use diff-multi-manyusers if too many users
                        $numUsers = $this->mNewPage->countAuthorsBetween( $oldRev, $newRev, $limit );
+
                        return self::intermediateEditsMsg( $nEdits, $numUsers, $limit );
                }
+
                return ''; // nothing
        }
 
@@ -904,6 +996,7 @@ class DifferenceEngine extends ContextSource {
                } else {
                        $msg = 'diff-multi';
                }
+
                return wfMessage( $msg )->numParams( $numEdits, $numUsers )->parse();
        }
 
@@ -945,11 +1038,16 @@ class DifferenceEngine extends ContextSource {
                                $editQuery['oldid'] = $rev->getID();
                        }
 
-                       $msg = $this->msg( $title->quickUserCan( 'edit', $user ) ? 'editold' : 'viewsourceold' )->escaped();
+                       $key = $title->quickUserCan( 'edit', $user ) ? 'editold' : 'viewsourceold';
+                       $msg = $this->msg( $key )->escaped();
                        $header .= ' ' . $this->msg( 'parentheses' )->rawParams(
                                Linker::linkKnown( $title, $msg, array(), $editQuery ) )->plain();
                        if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
-                               $header = Html::rawElement( 'span', array( 'class' => 'history-deleted' ), $header );
+                               $header = Html::rawElement(
+                                       'span',
+                                       array( 'class' => 'history-deleted' ),
+                                       $header
+                               );
                        }
                } else {
                        $header = Html::rawElement( 'span', array( 'class' => 'history-deleted' ), $header );
@@ -961,6 +1059,13 @@ class DifferenceEngine extends ContextSource {
        /**
         * Add the header to a diff body
         *
+        * @param string $diff Diff body
+        * @param string $otitle Old revision header
+        * @param string $ntitle New revision header
+        * @param string $multi Notice telling user that there are intermediate
+        *   revisions between the ones being compared
+        * @param string $notice Other notices, e.g. that user is viewing deleted content
+        *
         * @return string
         */
        function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
@@ -998,7 +1103,8 @@ class DifferenceEngine extends ContextSource {
                }
 
                if ( $multi != '' ) {
-                       $header .= "<tr><td colspan='{$multiColspan}' style='text-align: center;' class='diff-multi'>{$multi}</td></tr>";
+                       $header .= "<tr><td colspan='{$multiColspan}' style='text-align: center;' " .
+                               "class='diff-multi'>{$multi}</td></tr>";
                }
                if ( $notice != '' ) {
                        $header .= "<tr><td colspan='{$multiColspan}' style='text-align: center;'>{$notice}</td></tr>";
@@ -1041,6 +1147,33 @@ class DifferenceEngine extends ContextSource {
                $this->mDiffLang = wfGetLangObj( $lang );
        }
 
+       /**
+        * Maps a revision pair definition as accepted by DifferenceEngine constructor
+        * to a pair of actual integers representing revision ids.
+        *
+        * @param int $old Revision id, e.g. from URL parameter 'oldid'
+        * @param int|string $new Revision id or strings 'next' or 'prev', e.g. from URL parameter 'diff'
+        * @return array Array of two revision ids, older first, later second.
+        *     Zero signifies invalid argument passed.
+        *     false signifies that there is no previous/next revision ($old is the oldest/newest one).
+        */
+       public function mapDiffPrevNext( $old, $new ) {
+               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 );
+               } 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 );
+               } else {
+                       $oldid = intval( $old );
+                       $newid = intval( $new );
+               }
+
+               return array( $oldid, $newid );
+       }
+
        /**
         * Load revision IDs
         */
@@ -1054,26 +1187,17 @@ class DifferenceEngine extends ContextSource {
                $old = $this->mOldid;
                $new = $this->mNewid;
 
-               if ( $new === 'prev' ) {
-                       # Show diff between revision $old and the previous one.
-                       # Get previous one from DB.
-                       $this->mNewid = intval( $old );
-                       $this->mOldid = $this->getTitle()->getPreviousRevisionID( $this->mNewid );
-               } elseif ( $new === 'next' ) {
-                       # Show diff between revision $old and the next one.
-                       # Get next one from DB.
-                       $this->mOldid = intval( $old );
-                       $this->mNewid = $this->getTitle()->getNextRevisionID( $this->mOldid );
-                       if ( $this->mNewid === false ) {
-                               # if no result, NewId points to the newest old revision. The only newer
-                               # revision is cur, which is "0".
-                               $this->mNewid = 0;
-                       }
-               } else {
-                       $this->mOldid = intval( $old );
-                       $this->mNewid = intval( $new );
-                       wfRunHooks( 'NewDifferenceEngine', array( $this->getTitle(), &$this->mOldid, &$this->mNewid, $old, $new ) );
+               list( $this->mOldid, $this->mNewid ) = self::mapDiffPrevNext( $old, $new );
+               if ( $new === 'next' && $this->mNewid === false ) {
+                       # if no result, NewId points to the newest old revision. The only newer
+                       # revision is cur, which is "0".
+                       $this->mNewid = 0;
                }
+
+               wfRunHooks(
+                       'NewDifferenceEngine',
+                       array( $this->getTitle(), &$this->mOldid, &$this->mNewid, $old, $new )
+               );
        }
 
        /**
@@ -1099,9 +1223,15 @@ class DifferenceEngine extends ContextSource {
                $this->loadRevisionIds();
 
                // Load the new revision object
-               $this->mNewRev = $this->mNewid
-                       ? Revision::newFromId( $this->mNewid )
-                       : Revision::newFromTitle( $this->getTitle(), false, Revision::READ_NORMAL );
+               if ( $this->mNewid ) {
+                       $this->mNewRev = Revision::newFromId( $this->mNewid );
+               } else {
+                       $this->mNewRev = Revision::newFromTitle(
+                               $this->getTitle(),
+                               false,
+                               Revision::READ_NORMAL
+                       );
+               }
 
                if ( !$this->mNewRev instanceof Revision ) {
                        return false;
diff --git a/includes/diff/TableDiffFormatter.php b/includes/diff/TableDiffFormatter.php
new file mode 100644 (file)
index 0000000..5f28627
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/**
+ * Portions taken from phpwiki-1.3.3.
+ *
+ * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
+ * You may copy this code freely under the conditions of the GPL.
+ *
+ * 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 DifferenceEngine
+ */
+
+/**
+ * MediaWiki default table style diff formatter
+ * @todo document
+ * @private
+ * @ingroup DifferenceEngine
+ */
+class TableDiffFormatter extends DiffFormatter {
+       function __construct() {
+               $this->leadingContextLines = 2;
+               $this->trailingContextLines = 2;
+       }
+
+       /**
+        * @static
+        * @param $msg
+        * @return mixed
+        */
+       public static function escapeWhiteSpace( $msg ) {
+               $msg = preg_replace( '/^ /m', '&#160; ', $msg );
+               $msg = preg_replace( '/ $/m', ' &#160;', $msg );
+               $msg = preg_replace( '/  /', '&#160; ', $msg );
+
+               return $msg;
+       }
+
+       /**
+        * @param $xbeg
+        * @param $xlen
+        * @param $ybeg
+        * @param $ylen
+        * @return string
+        */
+       protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
+               $r = '<tr><td colspan="2" class="diff-lineno"><!--LINE ' . $xbeg . "--></td>\n" .
+                       '<td colspan="2" class="diff-lineno"><!--LINE ' . $ybeg . "--></td></tr>\n";
+
+               return $r;
+       }
+
+       /**
+        * @param $header
+        */
+       protected function startBlock( $header ) {
+               echo $header;
+       }
+
+       protected function endBlock() {
+       }
+
+       protected function lines( $lines, $prefix = ' ', $color = 'white' ) {
+       }
+
+       /**
+        * HTML-escape parameter before calling this
+        * @param $line
+        * @return string
+        */
+       protected function addedLine( $line ) {
+               return $this->wrapLine( '+', 'diff-addedline', $line );
+       }
+
+       /**
+        * HTML-escape parameter before calling this
+        * @param $line
+        * @return string
+        */
+       protected function deletedLine( $line ) {
+               return $this->wrapLine( '−', 'diff-deletedline', $line );
+       }
+
+       /**
+        * HTML-escape parameter before calling this
+        * @param $line
+        * @return string
+        */
+       protected function contextLine( $line ) {
+               return $this->wrapLine( '&#160;', 'diff-context', $line );
+       }
+
+       /**
+        * @param $marker
+        * @param $class
+        * @param $line
+        * @return string
+        */
+       protected function wrapLine( $marker, $class, $line ) {
+               if ( $line !== '' ) {
+                       // The <div> wrapper is needed for 'overflow: auto' style to scroll properly
+                       $line = Xml::tags( 'div', null, $this->escapeWhiteSpace( $line ) );
+               }
+
+               return "<td class='diff-marker'>$marker</td><td class='$class'>$line</td>";
+       }
+
+       /**
+        * @return string
+        */
+       protected function emptyLine() {
+               return '<td colspan="2">&#160;</td>';
+       }
+
+       /**
+        * @param $lines array
+        */
+       protected function added( $lines ) {
+               foreach ( $lines as $line ) {
+                       echo '<tr>' . $this->emptyLine() .
+                               $this->addedLine( '<ins class="diffchange">' .
+                                       htmlspecialchars( $line ) . '</ins>' ) . "</tr>\n";
+               }
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function deleted( $lines ) {
+               foreach ( $lines as $line ) {
+                       echo '<tr>' . $this->deletedLine( '<del class="diffchange">' .
+                                       htmlspecialchars( $line ) . '</del>' ) .
+                               $this->emptyLine() . "</tr>\n";
+               }
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function context( $lines ) {
+               foreach ( $lines as $line ) {
+                       echo '<tr>' .
+                               $this->contextLine( htmlspecialchars( $line ) ) .
+                               $this->contextLine( htmlspecialchars( $line ) ) . "</tr>\n";
+               }
+       }
+
+       /**
+        * @param $orig
+        * @param $closing
+        */
+       protected function changed( $orig, $closing ) {
+               wfProfileIn( __METHOD__ );
+
+               $diff = new WordLevelDiff( $orig, $closing );
+               $del = $diff->orig();
+               $add = $diff->closing();
+
+               # Notice that WordLevelDiff returns HTML-escaped output.
+               # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
+
+               while ( $line = array_shift( $del ) ) {
+                       $aline = array_shift( $add );
+                       echo '<tr>' . $this->deletedLine( $line ) .
+                               $this->addedLine( $aline ) . "</tr>\n";
+               }
+               foreach ( $add as $line ) { # If any leftovers
+                       echo '<tr>' . $this->emptyLine() .
+                               $this->addedLine( $line ) . "</tr>\n";
+               }
+               wfProfileOut( __METHOD__ );
+       }
+}
diff --git a/includes/diff/UnifiedDiffFormatter.php b/includes/diff/UnifiedDiffFormatter.php
new file mode 100644 (file)
index 0000000..0a86ccc
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Portions taken from phpwiki-1.3.3.
+ *
+ * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
+ * You may copy this code freely under the conditions of the GPL.
+ *
+ * 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 DifferenceEngine
+ */
+
+/**
+ * A formatter that outputs unified diffs
+ * @ingroup DifferenceEngine
+ */
+class UnifiedDiffFormatter extends DiffFormatter {
+       /** @var int */
+       protected $leadingContextLines = 2;
+
+       /** @var int */
+       protected $trailingContextLines = 2;
+
+       /**
+        * @param $lines
+        */
+       protected function added( $lines ) {
+               $this->lines( $lines, '+' );
+       }
+
+       /**
+        * @param $lines
+        */
+       protected function deleted( $lines ) {
+               $this->lines( $lines, '-' );
+       }
+
+       /**
+        * @param $orig
+        * @param $closing
+        */
+       protected function changed( $orig, $closing ) {
+               $this->deleted( $orig );
+               $this->added( $closing );
+       }
+
+       /**
+        * @param $xbeg
+        * @param $xlen
+        * @param $ybeg
+        * @param $ylen
+        * @return string
+        */
+       protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
+               return "@@ -$xbeg,$xlen +$ybeg,$ylen @@";
+       }
+}
index ea6f6e5..7c019b0 100644 (file)
@@ -138,8 +138,9 @@ class WikiDiff3 {
                         */
                        $max = min( $this->m, $this->n );
                        for ( $forwardBound = 0; $forwardBound < $max
-                                       && $this->from[$forwardBound] === $this->to[$forwardBound];
-                                       ++$forwardBound ) {
+                               && $this->from[$forwardBound] === $this->to[$forwardBound];
+                               ++$forwardBound
+                       ) {
                                $this->removed[$forwardBound] = $this->added[$forwardBound] = false;
                        }
 
@@ -147,7 +148,8 @@ class WikiDiff3 {
                        $backBoundL2 = $this->n - 1;
 
                        while ( $backBoundL1 >= $forwardBound && $backBoundL2 >= $forwardBound
-                                       && $this->from[$backBoundL1] === $this->to[$backBoundL2] ) {
+                               && $this->from[$backBoundL1] === $this->to[$backBoundL2]
+                       ) {
                                $this->removed[$backBoundL1--] = $this->added[$backBoundL2--] = false;
                        }
 
@@ -156,8 +158,14 @@ class WikiDiff3 {
                        $snake = array( 0, 0, 0 );
 
                        $this->length = $forwardBound + $this->m - $backBoundL1 - 1
-                               + $this->lcs_rec( $forwardBound, $backBoundL1,
-                               $forwardBound, $backBoundL2, $V, $snake );
+                               + $this->lcs_rec(
+                                       $forwardBound,
+                                       $backBoundL1,
+                                       $forwardBound,
+                                       $backBoundL2,
+                                       $V,
+                                       $snake
+                       );
                }
 
                $this->m = $m;
@@ -189,8 +197,9 @@ class WikiDiff3 {
                while ( $xi < $this->m || $yi < $this->n ) {
                        // Matching "snake".
                        while ( $xi < $this->m && $yi < $this->n
-                                       && !$this->removed[$xi]
-                                       && !$this->added[$yi] ) {
+                               && !$this->removed[$xi]
+                               && !$this->added[$yi]
+                       ) {
                                ++$xi;
                                ++$yi;
                        }
@@ -206,10 +215,10 @@ class WikiDiff3 {
                        }
 
                        if ( $xi > $xstart || $yi > $ystart ) {
-                               $ranges[] = new RangeDifference( $xstart, $xi,
-                                                               $ystart, $yi );
+                               $ranges[] = new RangeDifference( $xstart, $xi, $ystart, $yi );
                        }
                }
+
                return $ranges;
        }
 
@@ -220,7 +229,7 @@ class WikiDiff3 {
                }
 
                $d = $this->find_middle_snake( $bottoml1, $topl1, $bottoml2,
-                                                       $topl2, $V, $snake );
+                       $topl2, $V, $snake );
 
                // need to store these so we don't lose them when they're
                // overwritten by the recursion
@@ -236,9 +245,9 @@ class WikiDiff3 {
                if ( $d > 1 ) {
                        return $len
                        + $this->lcs_rec( $bottoml1, $startx - 1, $bottoml2,
-                                                       $starty - 1, $V, $snake )
+                               $starty - 1, $V, $snake )
                        + $this->lcs_rec( $startx + $len, $topl1, $starty + $len,
-                                                       $topl2, $V, $snake );
+                               $topl2, $V, $snake );
                } elseif ( $d == 1 ) {
                        /*
                         * In this case the sequences differ by exactly 1 line. We have
@@ -250,8 +259,10 @@ class WikiDiff3 {
                                $this->removed[$bottoml1 + $i] =
                                        $this->added[$bottoml2 + $i] = false;
                        }
+
                        return $max + $len;
                }
+
                return $len;
        }
 
@@ -263,8 +274,8 @@ class WikiDiff3 {
                $snake0 = &$snake[0];
                $snake1 = &$snake[1];
                $snake2 = &$snake[2];
-               $bottoml1_min_1 = $bottoml1 -1;
-               $bottoml2_min_1 = $bottoml2 -1;
+               $bottoml1_min_1 = $bottoml1 - 1;
+               $bottoml2_min_1 = $bottoml2 - 1;
                $N = $topl1 - $bottoml1_min_1;
                $M = $topl2 - $bottoml2_min_1;
                $delta = $N - $M;
@@ -307,7 +318,8 @@ class WikiDiff3 {
                                // compute forward furthest reaching paths
                                for ( $k = $start_diag; $k <= $end_diag; $k += 2 ) {
                                        if ( $k == -$d || ( $k < $d
-                                                       && $V0[$limit_min_1 + $k] < $V0[$limit_plus_1 + $k] ) ) {
+                                                       && $V0[$limit_min_1 + $k] < $V0[$limit_plus_1 + $k] )
+                                       ) {
                                                $x = $V0[$limit_plus_1 + $k];
                                        } else {
                                                $x = $V0[$limit_min_1 + $k] + 1;
@@ -320,12 +332,13 @@ class WikiDiff3 {
                                                ++$absx;
                                                ++$absy;
                                        }
-                                       $x = $absx -$bottoml1;
+                                       $x = $absx - $bottoml1;
 
-                                       $snake2 = $absx -$snake0;
+                                       $snake2 = $absx - $snake0;
                                        $V0[$limit + $k] = $x;
                                        if ( $k >= $delta - $d + 1 && $k <= $delta + $d - 1
-                                                       && $x >= $V1[$limit + $k - $delta] ) {
+                                               && $x >= $V1[$limit + $k - $delta]
+                                       ) {
                                                return 2 * $d - 1;
                                        }
 
@@ -345,7 +358,8 @@ class WikiDiff3 {
                                // compute backward furthest reaching paths
                                for ( $k = $start_diag; $k <= $end_diag; $k += 2 ) {
                                        if ( $k == $d
-                                       || ( $k != -$d && $V1[$limit_min_1 + $k] < $V1[$limit_plus_1 + $k] ) ) {
+                                               || ( $k != -$d && $V1[$limit_min_1 + $k] < $V1[$limit_plus_1 + $k] )
+                                       ) {
                                                $x = $V1[$limit_min_1 + $k];
                                        } else {
                                                $x = $V1[$limit_plus_1 + $k] - 1;
@@ -355,7 +369,8 @@ class WikiDiff3 {
 
                                        $snake2 = 0;
                                        while ( $x > 0 && $y > 0
-                                       && $from[$x + $bottoml1_min_1] === $to[$y + $bottoml2_min_1] ) {
+                                               && $from[$x + $bottoml1_min_1] === $to[$y + $bottoml2_min_1]
+                                       ) {
                                                --$x;
                                                --$y;
                                                ++$snake2;
@@ -380,7 +395,8 @@ class WikiDiff3 {
                                // compute forward furthest reaching paths
                                for ( $k = $start_diag; $k <= $end_diag; $k += 2 ) {
                                        if ( $k == -$d
-                                       || ( $k < $d && $V0[$limit_min_1 + $k] < $V0[$limit_plus_1 + $k] ) ) {
+                                               || ( $k < $d && $V0[$limit_min_1 + $k] < $V0[$limit_plus_1 + $k] )
+                                       ) {
                                                $x = $V0[$limit_plus_1 + $k];
                                        } else {
                                                $x = $V0[$limit_min_1 + $k] + 1;
@@ -393,14 +409,14 @@ class WikiDiff3 {
                                                ++$absx;
                                                ++$absy;
                                        }
-                                       $x = $absx -$bottoml1;
-                                       $snake2 = $absx -$snake0;
+                                       $x = $absx - $bottoml1;
+                                       $snake2 = $absx - $snake0;
                                        $V0[$limit + $k] = $x;
 
                                        // check to see if we can cut down the diagonal range
                                        if ( $x >= $N && $end_forward > $k - 1 ) {
                                                $end_forward = $k - 1;
-                                       } elseif ( $absy -$bottoml2 >= $M ) {
+                                       } elseif ( $absy - $bottoml2 >= $M ) {
                                                $start_forward = $k + 1;
                                                $value_to_add_forward = 0;
                                        }
@@ -413,7 +429,8 @@ class WikiDiff3 {
                                // compute backward furthest reaching paths
                                for ( $k = $start_diag; $k <= $end_diag; $k += 2 ) {
                                        if ( $k == $d
-                                       || ( $k != -$d && $V1[$limit_min_1 + $k] < $V1[$limit_plus_1 + $k] ) ) {
+                                               || ( $k != -$d && $V1[$limit_min_1 + $k] < $V1[$limit_plus_1 + $k] )
+                                       ) {
                                                $x = $V1[$limit_min_1 + $k];
                                        } else {
                                                $x = $V1[$limit_plus_1 + $k] - 1;
@@ -423,7 +440,8 @@ class WikiDiff3 {
 
                                        $snake2 = 0;
                                        while ( $x > 0 && $y > 0
-                                                       && $from[$x + $bottoml1_min_1] === $to[$y + $bottoml2_min_1] ) {
+                                               && $from[$x + $bottoml1_min_1] === $to[$y + $bottoml2_min_1]
+                                       ) {
                                                --$x;
                                                --$y;
                                                ++$snake2;
@@ -431,9 +449,11 @@ class WikiDiff3 {
                                        $V1[$limit + $k] = $x;
 
                                        if ( $k >= -$delta - $d && $k <= $d - $delta
-                                                       && $x <= $V0[$limit + $k + $delta] ) {
+                                               && $x <= $V0[$limit + $k + $delta]
+                                       ) {
                                                $snake0 = $bottoml1 + $x;
                                                $snake1 = $bottoml2 + $y;
+
                                                return 2 * $d;
                                        }
 
@@ -460,6 +480,7 @@ class WikiDiff3 {
                $snake2 = 0;
                wfDebug( "Computing the LCS is too expensive. Using a heuristic.\n" );
                $this->heuristicUsed = true;
+
                return 5; /*
                * HACK: since we didn't really finish the LCS computation
                * we don't really know the length of the SES. We don't do
@@ -554,11 +575,11 @@ class WikiDiff3 {
        public function getLcsLength() {
                if ( $this->heuristicUsed && !$this->lcsLengthCorrectedForHeuristic ) {
                        $this->lcsLengthCorrectedForHeuristic = true;
-                       $this->length = $this->m -array_sum( $this->added );
+                       $this->length = $this->m - array_sum( $this->added );
                }
+
                return $this->length;
        }
-
 }
 
 /**
@@ -568,13 +589,22 @@ class WikiDiff3 {
  * @ingroup DifferenceEngine
  */
 class RangeDifference {
-
+       /** @var int */
        public $leftstart;
+
+       /** @var int */
        public $leftend;
+
+       /** @var int */
        public $leftlength;
 
+       /** @var int */
        public $rightstart;
+
+       /** @var int */
        public $rightend;
+
+       /** @var int */
        public $rightlength;
 
        function __construct( $leftstart, $leftend, $rightstart, $rightend ) {
index 462b0b9..9e9d976 100644 (file)
@@ -59,6 +59,7 @@ class ExternalStore {
                }
 
                $class = 'ExternalStore' . ucfirst( $proto );
+
                // Any custom modules should be added to $wgAutoLoadClasses for on-demand loading
                return class_exists( $class ) ? new $class( $params ) : false;
        }
@@ -120,6 +121,7 @@ class ExternalStore {
                                $retval[$url] = false;
                        }
                }
+
                return $retval;
        }
 
index 46a8937..b7e5469 100644 (file)
@@ -37,11 +37,12 @@ class ExternalStoreDB extends ExternalStoreMedium {
         */
        public function fetchFromURL( $url ) {
                list( $cluster, $id, $itemID ) = $this->parseURL( $url );
-               $ret =& $this->fetchBlob( $cluster, $id, $itemID );
+               $ret = $this->fetchBlob( $cluster, $id, $itemID );
 
                if ( $itemID !== false && $ret !== false ) {
                        return $ret->getItem( $itemID );
                }
+
                return $ret;
        }
 
@@ -66,6 +67,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
                $ret = array();
                foreach ( $batched as $cluster => $batchByCluster ) {
                        $res = $this->batchFetchBlobs( $cluster, $batchByCluster );
+                       /** @var HistoryBlob $blob */
                        foreach ( $res as $id => $blob ) {
                                foreach ( $batchByCluster[$id] as $itemID ) {
                                        $url = $inverseUrlMap[$cluster][$id][$itemID];
@@ -77,6 +79,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
                                }
                        }
                }
+
                return $ret;
        }
 
@@ -96,6 +99,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
                if ( $dbw->getFlag( DBO_TRX ) ) {
                        $dbw->commit( __METHOD__ );
                }
+
                return "DB://$cluster/$id";
        }
 
@@ -105,7 +109,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param string $cluster cluster name
         * @return LoadBalancer object
         */
-       function &getLoadBalancer( $cluster ) {
+       function getLoadBalancer( $cluster ) {
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
 
                return wfGetLBFactory()->getExternalLB( $cluster, $wiki );
@@ -117,11 +121,11 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param string $cluster cluster name
         * @return DatabaseBase object
         */
-       function &getSlave( $cluster ) {
+       function getSlave( $cluster ) {
                global $wgDefaultExternalStore;
 
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
-               $lb =& $this->getLoadBalancer( $cluster );
+               $lb = $this->getLoadBalancer( $cluster );
 
                if ( !in_array( "DB://" . $cluster, (array)$wgDefaultExternalStore ) ) {
                        wfDebug( "read only external store" );
@@ -139,9 +143,10 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param string $cluster cluster name
         * @return DatabaseBase object
         */
-       function &getMaster( $cluster ) {
+       function getMaster( $cluster ) {
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
-               $lb =& $this->getLoadBalancer( $cluster );
+               $lb = $this->getLoadBalancer( $cluster );
+
                return $lb->getConnection( DB_MASTER, array(), $wiki );
        }
 
@@ -151,11 +156,12 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param $db DatabaseBase
         * @return String: table name ('blobs' by default)
         */
-       function getTable( &$db ) {
+       function getTable( $db ) {
                $table = $db->getLBInfo( 'blobs table' );
                if ( is_null( $table ) ) {
                        $table = 'blobs';
                }
+
                return $table;
        }
 
@@ -169,7 +175,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @return mixed
         * @private
         */
-       function &fetchBlob( $cluster, $id, $itemID ) {
+       function fetchBlob( $cluster, $id, $itemID ) {
                /**
                 * One-step cache variable to hold base blobs; operations that
                 * pull multiple revisions may often pull multiple times from
@@ -182,20 +188,21 @@ class ExternalStoreDB extends ExternalStoreMedium {
                if ( isset( $externalBlobCache[$cacheID] ) ) {
                        wfDebugLog( 'ExternalStoreDB-cache',
                                "ExternalStoreDB::fetchBlob cache hit on $cacheID\n" );
+
                        return $externalBlobCache[$cacheID];
                }
 
                wfDebugLog( 'ExternalStoreDB-cache',
                        "ExternalStoreDB::fetchBlob cache miss on $cacheID\n" );
 
-               $dbr =& $this->getSlave( $cluster );
+               $dbr = $this->getSlave( $cluster );
                $ret = $dbr->selectField( $this->getTable( $dbr ),
                        'blob_text', array( 'blob_id' => $id ), __METHOD__ );
                if ( $ret === false ) {
                        wfDebugLog( 'ExternalStoreDB',
                                "ExternalStoreDB::fetchBlob master fallback on $cacheID\n" );
                        // Try the master
-                       $dbw =& $this->getMaster( $cluster );
+                       $dbw = $this->getMaster( $cluster );
                        $ret = $dbw->selectField( $this->getTable( $dbw ),
                                'blob_text', array( 'blob_id' => $id ), __METHOD__ );
                        if ( $ret === false ) {
@@ -208,7 +215,8 @@ class ExternalStoreDB extends ExternalStoreMedium {
                        $ret = unserialize( $ret );
                }
 
-               $externalBlobCache = array( $cacheID => &$ret );
+               $externalBlobCache = array( $cacheID => $ret );
+
                return $ret;
        }
 
@@ -217,7 +225,8 @@ class ExternalStoreDB extends ExternalStoreMedium {
         *
         * @param string $cluster A cluster name valid for use with LBFactory
         * @param array $ids A map from the blob_id's to look for to the requested itemIDs in the blobs
-        * @return array A map from the blob_id's requested to their content.  Unlocated ids are not represented
+        * @return array A map from the blob_id's requested to their content.
+        *   Unlocated ids are not represented
         */
        function batchFetchBlobs( $cluster, array $ids ) {
                $dbr = $this->getSlave( $cluster );
@@ -248,6 +257,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
                                " master on '$cluster' failed locating items: " .
                                implode( ',', array_keys( $ids ) ) . "\n" );
                }
+
                return $ret;
        }
 
@@ -274,6 +284,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
 
        protected function parseURL( $url ) {
                $path = explode( '/', $url );
+
                return array(
                        $path[2], // cluster
                        $path[3], // id
index 02bdcb5..a526df6 100644 (file)
@@ -61,9 +61,10 @@ abstract class ExternalStoreMedium {
                        // Dont return when false to allow for simpler implementations.
                        // errored urls are handled in ExternalStore::batchFetchFromURLs
                        if ( $data !== false ) {
-                               $retval[$urls] = $data;
+                               $retval[$url] = $data;
                        }
                }
+
                return $retval;
        }
 
index aa48679..f329b73 100644 (file)
@@ -43,6 +43,7 @@ class ExternalStoreMwstore extends ExternalStoreMedium {
                        // backends should at least have "read-after-create" consistency.
                        return $be->getFileContents( array( 'src' => $url ) );
                }
+
                return false;
        }
 
@@ -63,9 +64,10 @@ class ExternalStoreMwstore extends ExternalStoreMedium {
                }
                $blobs = array();
                foreach ( $pathsByBackend as $backendName => $paths ) {
-                       $be = FileBackendGroup::get( $backendName );
+                       $be = FileBackendGroup::singleton()->get( $backendName );
                        $blobs = $blobs + $be->getFileContentsMulti( array( 'srcs' => $paths ) );
                }
+
                return $blobs;
        }
 
@@ -90,6 +92,7 @@ class ExternalStoreMwstore extends ExternalStoreMedium {
                                return $url;
                        }
                }
+
                return false;
        }
 }
index 8f0a133..3a0aa97 100644 (file)
  * @ingroup FileBackend
  */
 class FSFile {
-       protected $path; // path to file
-       protected $sha1Base36; // file SHA-1 in base 36
+       /** @var string Path to file */
+       protected $path;
+
+       /** @var string File SHA-1 in base 36  */
+       protected $sha1Base36;
 
        /**
         * Sets up the file object
@@ -82,6 +85,7 @@ class FSFile {
                if ( $timestamp !== false ) {
                        $timestamp = wfTimestamp( TS_MW, $timestamp );
                }
+
                return $timestamp;
        }
 
@@ -98,7 +102,7 @@ class FSFile {
         * Get an associative array containing information about
         * a file with the given storage path.
         *
-        * @param Mixed $ext: the file extension, or true to extract it from the filename.
+        * @param mixed $ext The file extension, or true to extract it from the filename.
         *             Set it to false to ignore the extension.
         *
         * @return array
@@ -147,13 +151,14 @@ class FSFile {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $info;
        }
 
        /**
         * Placeholder file properties to use for files that don't exist
         *
-        * @return Array
+        * @return array
         */
        public static function placeholderProps() {
                $info = array();
@@ -165,6 +170,7 @@ class FSFile {
                $info['width'] = 0;
                $info['height'] = 0;
                $info['bits'] = 0;
+
                return $info;
        }
 
@@ -172,7 +178,7 @@ class FSFile {
         * Exract image size information
         *
         * @param array $gis
-        * @return Array
+        * @return array
         */
        protected function extractImageSizeInfo( array $gis ) {
                $info = array();
@@ -184,6 +190,7 @@ class FSFile {
                } else {
                        $info['bits'] = 0;
                }
+
                return $info;
        }
 
@@ -202,6 +209,7 @@ class FSFile {
 
                if ( $this->sha1Base36 !== null && !$recache ) {
                        wfProfileOut( __METHOD__ );
+
                        return $this->sha1Base36;
                }
 
@@ -214,6 +222,7 @@ class FSFile {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $this->sha1Base36;
        }
 
@@ -225,6 +234,7 @@ class FSFile {
         */
        public static function extensionFromPath( $path ) {
                $i = strrpos( $path, '.' );
+
                return strtolower( $i ? substr( $path, $i + 1 ) : '' );
        }
 
@@ -232,12 +242,13 @@ class FSFile {
         * Get an associative array containing information about a file in the local filesystem.
         *
         * @param string $path absolute local filesystem path
-        * @param Mixed $ext: the file extension, or true to extract it from the filename.
-        *             Set it to false to ignore the extension.
+        * @param mixed $ext The file extension, or true to extract it from the filename.
+        *   Set it to false to ignore the extension.
         * @return array
         */
        public static function getPropsFromPath( $path, $ext = true ) {
                $fsFile = new self( $path );
+
                return $fsFile->getProps( $ext );
        }
 
@@ -253,6 +264,7 @@ class FSFile {
         */
        public static function getSha1Base36FromPath( $path ) {
                $fsFile = new self( $path );
+
                return $fsFile->getSha1Base36();
        }
 }
index 6d64216..8438919 100644 (file)
  * @since 1.19
  */
 class FSFileBackend extends FileBackendStore {
-       protected $basePath; // string; directory holding the container directories
-       /** @var Array Map of container names to root paths */
-       protected $containerPaths = array(); // for custom container paths
-       protected $fileMode; // integer; file permission mode
-       protected $fileOwner; // string; required OS username to own files
-       protected $currentUser; // string; OS username running this script
-
-       /** @var Array */
+       /** @var string Directory holding the container directories */
+       protected $basePath;
+
+       /** @var array Map of container names to root paths for custom container paths */
+       protected $containerPaths = array();
+
+       /** @var int File permission mode */
+       protected $fileMode;
+
+       /** @var string Required OS username to own files */
+       protected $fileOwner;
+
+       /** @var string OS username running this script */
+       protected $currentUser;
+
+       /** @var array */
        protected $hadWarningErrors = array();
 
        /**
@@ -90,6 +98,7 @@ class FSFileBackend extends FileBackendStore {
                                return $relStoragePath;
                        }
                }
+
                return null;
        }
 
@@ -125,6 +134,7 @@ class FSFileBackend extends FileBackendStore {
                } elseif ( isset( $this->basePath ) ) {
                        return "{$this->basePath}/{$fullCont}";
                }
+
                return null; // no container base path defined
        }
 
@@ -144,6 +154,7 @@ class FSFileBackend extends FileBackendStore {
                if ( $relPath != '' ) {
                        $fsPath .= "/{$relPath}";
                }
+
                return $fsPath;
        }
 
@@ -174,6 +185,7 @@ class FSFileBackend extends FileBackendStore {
                $dest = $this->resolveToFSPath( $params['dst'] );
                if ( $dest === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -181,6 +193,7 @@ class FSFileBackend extends FileBackendStore {
                        $tempFile = TempFSFile::factory( 'create_', 'tmp' );
                        if ( !$tempFile ) {
                                $status->fatal( 'backend-fail-create', $params['dst'] );
+
                                return $status;
                        }
                        $this->trapWarnings();
@@ -188,6 +201,7 @@ class FSFileBackend extends FileBackendStore {
                        $this->untrapWarnings();
                        if ( $bytes === false ) {
                                $status->fatal( 'backend-fail-create', $params['dst'] );
+
                                return $status;
                        }
                        $cmd = implode( ' ', array(
@@ -203,6 +217,7 @@ class FSFileBackend extends FileBackendStore {
                        $this->untrapWarnings();
                        if ( $bytes === false ) {
                                $status->fatal( 'backend-fail-create', $params['dst'] );
+
                                return $status;
                        }
                        $this->chmod( $dest );
@@ -214,7 +229,7 @@ class FSFileBackend extends FileBackendStore {
        /**
         * @see FSFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseCreate( $errors, Status $status, array $params, $cmd ) {
+       protected function getResponseCreate( $errors, Status $status, array $params, $cmd ) {
                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                        $status->fatal( 'backend-fail-create', $params['dst'] );
                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -227,6 +242,7 @@ class FSFileBackend extends FileBackendStore {
                $dest = $this->resolveToFSPath( $params['dst'] );
                if ( $dest === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -248,6 +264,7 @@ class FSFileBackend extends FileBackendStore {
                                        trigger_error( __METHOD__ . ": copy() failed but returned true." );
                                }
                                $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
+
                                return $status;
                        }
                        $this->chmod( $dest );
@@ -259,7 +276,7 @@ class FSFileBackend extends FileBackendStore {
        /**
         * @see FSFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseStore( $errors, Status $status, array $params, $cmd ) {
+       protected function getResponseStore( $errors, Status $status, array $params, $cmd ) {
                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                        $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -272,12 +289,14 @@ class FSFileBackend extends FileBackendStore {
                $source = $this->resolveToFSPath( $params['src'] );
                if ( $source === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
                $dest = $this->resolveToFSPath( $params['dst'] );
                if ( $dest === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -285,6 +304,7 @@ class FSFileBackend extends FileBackendStore {
                        if ( empty( $params['ignoreMissingSource'] ) ) {
                                $status->fatal( 'backend-fail-copy', $params['src'] );
                        }
+
                        return $status; // do nothing; either OK or bad status
                }
 
@@ -308,6 +328,7 @@ class FSFileBackend extends FileBackendStore {
                                        trigger_error( __METHOD__ . ": copy() failed but returned true." );
                                }
                                $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+
                                return $status;
                        }
                        $this->chmod( $dest );
@@ -319,7 +340,7 @@ class FSFileBackend extends FileBackendStore {
        /**
         * @see FSFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseCopy( $errors, Status $status, array $params, $cmd ) {
+       protected function getResponseCopy( $errors, Status $status, array $params, $cmd ) {
                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                        $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -332,12 +353,14 @@ class FSFileBackend extends FileBackendStore {
                $source = $this->resolveToFSPath( $params['src'] );
                if ( $source === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
                $dest = $this->resolveToFSPath( $params['dst'] );
                if ( $dest === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -345,6 +368,7 @@ class FSFileBackend extends FileBackendStore {
                        if ( empty( $params['ignoreMissingSource'] ) ) {
                                $status->fatal( 'backend-fail-move', $params['src'] );
                        }
+
                        return $status; // do nothing; either OK or bad status
                }
 
@@ -362,6 +386,7 @@ class FSFileBackend extends FileBackendStore {
                        clearstatcache(); // file no longer at source
                        if ( !$ok ) {
                                $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
+
                                return $status;
                        }
                }
@@ -372,7 +397,7 @@ class FSFileBackend extends FileBackendStore {
        /**
         * @see FSFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseMove( $errors, Status $status, array $params, $cmd ) {
+       protected function getResponseMove( $errors, Status $status, array $params, $cmd ) {
                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                        $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
@@ -385,6 +410,7 @@ class FSFileBackend extends FileBackendStore {
                $source = $this->resolveToFSPath( $params['src'] );
                if ( $source === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
@@ -392,6 +418,7 @@ class FSFileBackend extends FileBackendStore {
                        if ( empty( $params['ignoreMissingSource'] ) ) {
                                $status->fatal( 'backend-fail-delete', $params['src'] );
                        }
+
                        return $status; // do nothing; either OK or bad status
                }
 
@@ -407,6 +434,7 @@ class FSFileBackend extends FileBackendStore {
                        $this->untrapWarnings();
                        if ( !$ok ) {
                                $status->fatal( 'backend-fail-delete', $params['src'] );
+
                                return $status;
                        }
                }
@@ -417,13 +445,19 @@ class FSFileBackend extends FileBackendStore {
        /**
         * @see FSFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseDelete( $errors, Status $status, array $params, $cmd ) {
+       protected function getResponseDelete( $errors, Status $status, array $params, $cmd ) {
                if ( $errors !== '' && !( wfIsWindows() && $errors[0] === " " ) ) {
                        $status->fatal( 'backend-fail-delete', $params['src'] );
                        trigger_error( "$cmd\n$errors", E_USER_WARNING ); // command output
                }
        }
 
+       /**
+        * @param string $fullCont
+        * @param $dirRel
+        * @param array $params
+        * @return Status
+        */
        protected function doPrepareInternal( $fullCont, $dirRel, array $params ) {
                $status = Status::newGood();
                list( , $shortCont, ) = FileBackend::splitStoragePath( $params['dir'] );
@@ -444,6 +478,7 @@ class FSFileBackend extends FileBackendStore {
                if ( is_dir( $dir ) && !$existed ) {
                        $status->merge( $this->doSecureInternal( $fullCont, $dirRel, $params ) );
                }
+
                return $status;
        }
 
@@ -471,6 +506,7 @@ class FSFileBackend extends FileBackendStore {
                                $status->fatal( 'backend-fail-create', "{$storeDir}/.htaccess" );
                        }
                }
+
                return $status;
        }
 
@@ -498,6 +534,7 @@ class FSFileBackend extends FileBackendStore {
                        }
                        $this->untrapWarnings();
                }
+
                return $status;
        }
 
@@ -511,6 +548,7 @@ class FSFileBackend extends FileBackendStore {
                        rmdir( $dir ); // remove directory if empty
                }
                $this->untrapWarnings();
+
                return $status;
        }
 
@@ -557,7 +595,10 @@ class FSFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::getDirectoryListInternal()
-        * @return Array|null
+        * @param string $fullCont
+        * @param string $dirRel
+        * @param array $params
+        * @return array|null
         */
        public function getDirectoryListInternal( $fullCont, $dirRel, array $params ) {
                list( , $shortCont, ) = FileBackend::splitStoragePath( $params['dir'] );
@@ -566,17 +607,23 @@ class FSFileBackend extends FileBackendStore {
                $exists = is_dir( $dir );
                if ( !$exists ) {
                        wfDebug( __METHOD__ . "() given directory does not exist: '$dir'\n" );
+
                        return array(); // nothing under this dir
                } elseif ( !is_readable( $dir ) ) {
                        wfDebug( __METHOD__ . "() given directory is unreadable: '$dir'\n" );
+
                        return null; // bad permissions?
                }
+
                return new FSFileBackendDirList( $dir, $params );
        }
 
        /**
         * @see FileBackendStore::getFileListInternal()
-        * @return Array|FSFileBackendFileList|null
+        * @param string $fullCont
+        * @param string $dirRel
+        * @param array $params
+        * @return array|FSFileBackendFileList|null
         */
        public function getFileListInternal( $fullCont, $dirRel, array $params ) {
                list( , $shortCont, ) = FileBackend::splitStoragePath( $params['dir'] );
@@ -585,11 +632,14 @@ class FSFileBackend extends FileBackendStore {
                $exists = is_dir( $dir );
                if ( !$exists ) {
                        wfDebug( __METHOD__ . "() given directory does not exist: '$dir'\n" );
+
                        return array(); // nothing under this dir
                } elseif ( !is_readable( $dir ) ) {
                        wfDebug( __METHOD__ . "() given directory is unreadable: '$dir'\n" );
+
                        return null; // bad permissions?
                }
+
                return new FSFileBackendFileList( $dir, $params );
        }
 
@@ -662,7 +712,7 @@ class FSFileBackend extends FileBackendStore {
 
                foreach ( $fileOpHandles as $index => $fileOpHandle ) {
                        $status = Status::newGood();
-                       $function = '_getResponse' . $fileOpHandle->call;
+                       $function = 'getResponse' . $fileOpHandle->call;
                        $this->$function( $errs[$index], $status, $fileOpHandle->params, $fileOpHandle->cmd );
                        $statuses[$index] = $status;
                        if ( $status->isOK() && $fileOpHandle->chmodPath ) {
@@ -718,8 +768,6 @@ class FSFileBackend extends FileBackendStore {
 
        /**
         * Listen for E_WARNING errors and track whether any happen
-        *
-        * @return void
         */
        protected function trapWarnings() {
                $this->hadWarningErrors[] = false; // push to stack
@@ -737,7 +785,7 @@ class FSFileBackend extends FileBackendStore {
        }
 
        /**
-        * @param integer $errno
+        * @param int $errno
         * @param string $errstr
         * @return bool
         * @access private
@@ -745,6 +793,7 @@ class FSFileBackend extends FileBackendStore {
        public function handleWarning( $errno, $errstr ) {
                wfDebugLog( 'FSFileBackend', $errstr ); // more detailed error logging
                $this->hadWarningErrors[count( $this->hadWarningErrors ) - 1] = true;
+
                return true; // suppress from PHP handler
        }
 }
@@ -761,7 +810,7 @@ class FSFileOpHandle extends FileBackendStoreOpHandle {
         * @param array $params
         * @param string $call
         * @param string $cmd
-        * @param integer|null $chmodPath
+        * @param int|null $chmodPath
         */
        public function __construct(
                FSFileBackend $backend, array $params, $call, $cmd, $chmodPath = null
@@ -784,9 +833,14 @@ class FSFileOpHandle extends FileBackendStoreOpHandle {
 abstract class FSFileBackendList implements Iterator {
        /** @var Iterator */
        protected $iter;
-       protected $suffixStart; // integer
-       protected $pos = 0; // integer
-       /** @var Array */
+
+       /** @var int */
+       protected $suffixStart;
+
+       /** @var int */
+       protected $pos = 0;
+
+       /** @var array */
        protected $params = array();
 
        /**
@@ -823,6 +877,7 @@ abstract class FSFileBackendList implements Iterator {
                        # RecursiveDirectoryIterator extends FilesystemIterator.
                        # FilesystemIterator::SKIP_DOTS default is inconsistent in PHP 5.3.x.
                        $flags = FilesystemIterator::CURRENT_AS_SELF | FilesystemIterator::SKIP_DOTS;
+
                        return new RecursiveIteratorIterator(
                                new RecursiveDirectoryIterator( $dir, $flags ),
                                RecursiveIteratorIterator::CHILD_FIRST // include dirs
@@ -832,7 +887,7 @@ abstract class FSFileBackendList implements Iterator {
 
        /**
         * @see Iterator::key()
-        * @return integer
+        * @return int
         */
        public function key() {
                return $this->pos;
@@ -848,7 +903,7 @@ abstract class FSFileBackendList implements Iterator {
 
        /**
         * @see Iterator::next()
-        * @return void
+        * @throws FileBackendError
         */
        public function next() {
                try {
@@ -862,7 +917,7 @@ abstract class FSFileBackendList implements Iterator {
 
        /**
         * @see Iterator::rewind()
-        * @return void
+        * @throws FileBackendError
         */
        public function rewind() {
                $this->pos = 0;
@@ -885,13 +940,14 @@ abstract class FSFileBackendList implements Iterator {
        /**
         * Filter out items by advancing to the next ones
         */
-       protected function filterViaNext() {}
+       protected function filterViaNext() {
+       }
 
        /**
         * Return only the relative path and normalize slashes to FileBackend-style.
         * Uses the "real path" since the suffix is based upon that.
         *
-        * @param string $path
+        * @param string $dir
         * @return string
         */
        protected function getRelPath( $dir ) {
@@ -899,6 +955,7 @@ abstract class FSFileBackendList implements Iterator {
                if ( $path === false ) {
                        $path = $dir;
                }
+
                return strtr( substr( $path, $this->suffixStart ), '\\', '/' );
        }
 }
index f586578..a6eda18 100644 (file)
  * For legacy reasons, the FSFileBackend class allows manually setting the paths of
  * containers to ones that do not respect the "wiki ID".
  *
- * In key/value stores, the container is the only hierarchy (the rest is emulated).
+ * In key/value (object) stores, containers are the only hierarchy (the rest is emulated).
  * FS-based backends are somewhat more restrictive due to the existence of real
  * directory files; a regular file cannot have the same name as a directory. Other
  * backends with virtual directories may not have this limitation. Callers should
  * store files in such a way that no files and directories are under the same path.
  *
+ * In general, this class allows for callers to access storage through the same
+ * interface, without regard to the underlying storage system. However, calling code
+ * must follow certain patterns and be aware of certain things to ensure compatibility:
+ *   - a) Always call prepare() on the parent directory before trying to put a file there;
+ *        key/value stores only need the container to exist first, but filesystems need
+ *        all the parent directories to exist first (prepare() is aware of all this)
+ *   - b) Always call clean() on a directory when it might become empty to avoid empty
+ *        directory buildup on filesystems; key/value stores never have empty directories,
+ *        so doing this helps preserve consistency in both cases
+ *   - c) Likewise, do not rely on the existence of empty directories for anything;
+ *        calling directoryExists() on a path that prepare() was previously called on
+ *        will return false for key/value stores if there are no files under that path
+ *   - d) Never alter the resulting FSFile returned from getLocalReference(), as it could
+ *        either be a copy of the source file in /tmp or the original source file itself
+ *   - e) Use a file layout that results in never attempting to store files over directories
+ *        or directories over files; key/value stores allow this but filesystems do not
+ *   - f) Use ASCII file names (e.g. base32, IDs, hashes) to avoid Unicode issues in Windows
+ *   - g) Do not assume that move operations are atomic (difficult with key/value stores)
+ *   - h) Do not assume that file stat or read operations always have immediate consistency;
+ *        various methods have a "latest" flag that should always be used if up-to-date
+ *        information is required (this trades performance for correctness as needed)
+ *   - i) Do not assume that directory listings have immediate consistency
+ *
  * Methods of subclasses should avoid throwing exceptions at all costs.
  * As a corollary, external dependencies should be kept to a minimum.
  *
  * @since 1.19
  */
 abstract class FileBackend {
-       protected $name; // string; unique backend name
-       protected $wikiId; // string; unique wiki name
-       protected $readOnly; // string; read-only explanation message
-       protected $parallelize; // string; when to do operations in parallel
-       protected $concurrency; // integer; how many operations can be done in parallel
+       /** @var string Unique backend name */
+       protected $name;
+
+       /** @var string Unique wiki name */
+       protected $wikiId;
+
+       /** @var string Read-only explanation message */
+       protected $readOnly;
+
+       /** @var string When to do operations in parallel */
+       protected $parallelize;
+
+       /** @var int How many operations can be done in parallel */
+       protected $concurrency;
 
        /** @var LockManager */
        protected $lockManager;
+
        /** @var FileJournal */
        protected $fileJournal;
 
@@ -75,7 +108,7 @@ abstract class FileBackend {
         * Create a new backend instance from configuration.
         * This should only be called from within FileBackendGroup.
         *
-        * $config includes:
+        * @param array $config Parameters include:
         *   - name        : The unique name of this backend.
         *                   This should consist of alphanumberic, '-', and '_' characters.
         *                   This name should not be changed after use (e.g. with journaling).
@@ -93,8 +126,6 @@ abstract class FileBackend {
         *   - parallelize : When to do file operations in parallel (when possible).
         *                   Allowed values are "implicit", "explicit" and "off".
         *   - concurrency : How many file operations can be done in parallel.
-        *
-        * @param array $config
         * @throws MWException
         */
        public function __construct( array $config ) {
@@ -671,8 +702,7 @@ abstract class FileBackend {
         * otherwise safe from modification from other processes. Normally,
         * the file will be a new temp file, which should be adequate.
         *
-        * @param array $params Operation parameters
-        * $params include:
+        * @param array $params Operation parameters, include:
         *   - srcs        : ordered source storage paths (e.g. chunk1, chunk2, ...)
         *   - dst         : file system path to 0-byte temp file
         *   - parallelize : try to do operations in parallel when possible
@@ -691,8 +721,7 @@ abstract class FileBackend {
         * However, setting them is not guaranteed to actually do anything.
         * Additional server configuration may be needed to achieve the desired effect.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir            : storage directory
         *   - noAccess       : try to deny file access (since 1.20)
         *   - noListing      : try to deny file listing (since 1.20)
@@ -721,8 +750,7 @@ abstract class FileBackend {
         * This is not guaranteed to actually make files or listings publically hidden.
         * Additional server configuration may be needed to achieve the desired effect.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir            : storage directory
         *   - noAccess       : try to deny file access
         *   - noListing      : try to deny file listing
@@ -752,8 +780,7 @@ abstract class FileBackend {
         * This is not guaranteed to actually make files or listings publically viewable.
         * Additional server configuration may be needed to achieve the desired effect.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir            : storage directory
         *   - access         : try to allow file access
         *   - listing        : try to allow file listing
@@ -779,8 +806,7 @@ abstract class FileBackend {
         * Backends using key/value stores may do nothing unless the directory
         * is that of an empty container, in which case it will be deleted.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir            : storage directory
         *   - recursive      : recursively delete empty subdirectories first (since 1.20)
         *   - bypassReadOnly : allow writes in read-only mode (since 1.20)
@@ -807,12 +833,13 @@ abstract class FileBackend {
         * @return ScopedCallback|null
         */
        final protected function getScopedPHPBehaviorForOps() {
-               if ( php_sapi_name() != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
+               if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
                        $old = ignore_user_abort( true ); // avoid half-finished operations
-                       return new ScopedCallback( function() use ( $old ) {
+                       return new ScopedCallback( function () use ( $old ) {
                                ignore_user_abort( $old );
                        } );
                }
+
                return null;
        }
 
@@ -820,8 +847,7 @@ abstract class FileBackend {
         * Check if a file exists at a storage path in the backend.
         * This returns false if only a directory exists at the path.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return bool|null Returns null on failure
@@ -831,8 +857,7 @@ abstract class FileBackend {
        /**
         * Get the last-modified timestamp of the file at a storage path.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return string|bool TS_MW timestamp or false on failure
@@ -843,8 +868,7 @@ abstract class FileBackend {
         * Get the contents of a file at a storage path in the backend.
         * This should be avoided for potentially large files.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return string|bool Returns false on failure
@@ -863,12 +887,11 @@ abstract class FileBackend {
         *
         * @see FileBackend::getFileContents()
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - srcs        : list of source storage paths
         *   - latest      : use the latest available data
         *   - parallelize : try to do operations in parallel when possible
-        * @return Array Map of (path name => string or false on failure)
+        * @return array Map of (path name => string or false on failure)
         * @since 1.20
         */
        abstract public function getFileContentsMulti( array $params );
@@ -876,11 +899,10 @@ abstract class FileBackend {
        /**
         * Get the size (bytes) of a file at a storage path in the backend.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
-        * @return integer|bool Returns false on failure
+        * @return int|bool Returns false on failure
         */
        abstract public function getFileSize( array $params );
 
@@ -892,19 +914,17 @@ abstract class FileBackend {
         *   - size   : the file size (bytes)
         * Additional values may be included for internal use only.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
-        * @return Array|bool|null Returns null on failure
+        * @return array|bool|null Returns null on failure
         */
        abstract public function getFileStat( array $params );
 
        /**
         * Get a SHA-1 hash of the file at a storage path in the backend.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return string|bool Hash string or false on failure
@@ -915,11 +935,10 @@ abstract class FileBackend {
         * Get the properties of the file at a storage path in the backend.
         * This gives the result of FSFile::getProps() on a local copy of the file.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
-        * @return Array Returns FSFile::placeholderProps() on failure
+        * @return array Returns FSFile::placeholderProps() on failure
         */
        abstract public function getFileProps( array $params );
 
@@ -930,8 +949,7 @@ abstract class FileBackend {
         * will be sent if streaming began, while none will be sent otherwise.
         * Implementations should flush the output buffer before sending data.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src     : source storage path
         *   - headers : list of additional HTTP headers to send on success
         *   - latest  : use the latest available data
@@ -952,8 +970,7 @@ abstract class FileBackend {
         * In that later case, there are copies of the file that must stay in sync.
         * Additionally, further calls to this function may return the same file.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return FSFile|null Returns null on failure
@@ -972,12 +989,11 @@ abstract class FileBackend {
         *
         * @see FileBackend::getLocalReference()
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - srcs        : list of source storage paths
         *   - latest      : use the latest available data
         *   - parallelize : try to do operations in parallel when possible
-        * @return Array Map of (path name => FSFile or null on failure)
+        * @return array Map of (path name => FSFile or null on failure)
         * @since 1.20
         */
        abstract public function getLocalReferenceMulti( array $params );
@@ -987,8 +1003,7 @@ abstract class FileBackend {
         * The temporary copy will have the same file extension as the source.
         * Temporary files may be purged when the file object falls out of scope.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src    : source storage path
         *   - latest : use the latest available data
         * @return TempFSFile|null Returns null on failure
@@ -1007,12 +1022,11 @@ abstract class FileBackend {
         *
         * @see FileBackend::getLocalCopy()
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - srcs        : list of source storage paths
         *   - latest      : use the latest available data
         *   - parallelize : try to do operations in parallel when possible
-        * @return Array Map of (path name => TempFSFile or null on failure)
+        * @return array Map of (path name => TempFSFile or null on failure)
         * @since 1.20
         */
        abstract public function getLocalCopyMulti( array $params );
@@ -1027,8 +1041,7 @@ abstract class FileBackend {
         * Otherwise, one would need to use getLocalReference(), which involves loading
         * the entire file on to local disk.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - src : source storage path
         *   - ttl : lifetime (seconds) if pre-authenticated; default is 1 day
         * @return string|null
@@ -1043,8 +1056,7 @@ abstract class FileBackend {
         *
         * Storage backends with eventual consistency might return stale data.
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir : storage directory
         * @return bool|null Returns null on failure
         * @since 1.20
@@ -1063,8 +1075,7 @@ abstract class FileBackend {
         *
         * Failures during iteration can result in FileBackendError exceptions (since 1.22).
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir     : storage directory
         *   - topOnly : only return direct child dirs of the directory
         * @return Traversable|Array|null Returns null on failure
@@ -1080,8 +1091,7 @@ abstract class FileBackend {
         *
         * Failures during iteration can result in FileBackendError exceptions (since 1.22).
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir : storage directory
         * @return Traversable|Array|null Returns null on failure
         * @since 1.20
@@ -1102,8 +1112,7 @@ abstract class FileBackend {
         *
         * Failures during iteration can result in FileBackendError exceptions (since 1.22).
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir        : storage directory
         *   - topOnly    : only return direct child files of the directory (since 1.20)
         *   - adviseStat : set to true if stat requests will be made on the files (since 1.22)
@@ -1119,8 +1128,7 @@ abstract class FileBackend {
         *
         * Failures during iteration can result in FileBackendError exceptions (since 1.22).
         *
-        * @param array $params
-        * $params include:
+        * @param array $params Parameters include:
         *   - dir        : storage directory
         *   - adviseStat : set to true if stat requests will be made on the files (since 1.22)
         * @return Traversable|Array|null Returns null on failure
@@ -1135,18 +1143,18 @@ abstract class FileBackend {
         * This should be used when stat calls will be made on a known list of a many files.
         *
         * @param array $paths Storage paths
-        * @return void
         */
-       public function preloadCache( array $paths ) {}
+       public function preloadCache( array $paths ) {
+       }
 
        /**
         * Invalidate any in-process file stat and property cache.
         * If $paths is given, then only the cache for those files will be cleared.
         *
         * @param array $paths Storage paths (optional)
-        * @return void
         */
-       public function clearCache( array $paths = null ) {}
+       public function clearCache( array $paths = null ) {
+       }
 
        /**
         * Lock the files at the given storage paths in the backend.
@@ -1155,11 +1163,12 @@ abstract class FileBackend {
         * Callers should consider using getScopedFileLocks() instead.
         *
         * @param array $paths Storage paths
-        * @param integer $type LockManager::LOCK_* constant
+        * @param int $type LockManager::LOCK_* constant
         * @return Status
         */
        final public function lockFiles( array $paths, $type ) {
                $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
+
                return $this->lockManager->lock( $paths, $type );
        }
 
@@ -1167,11 +1176,12 @@ abstract class FileBackend {
         * Unlock the files at the given storage paths in the backend.
         *
         * @param array $paths Storage paths
-        * @param integer $type LockManager::LOCK_* constant
+        * @param int $type LockManager::LOCK_* constant
         * @return Status
         */
        final public function unlockFiles( array $paths, $type ) {
                $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
+
                return $this->lockManager->unlock( $paths, $type );
        }
 
@@ -1186,7 +1196,7 @@ abstract class FileBackend {
         * @see ScopedLock::factory()
         *
         * @param array $paths List of storage paths or map of lock types to path lists
-        * @param integer|string $type LockManager::LOCK_* constant or "mixed"
+        * @param int|string $type LockManager::LOCK_* constant or "mixed"
         * @param Status $status Status to update on lock/unlock
         * @return ScopedLock|null Returns null on failure
         */
@@ -1198,6 +1208,7 @@ abstract class FileBackend {
                } else {
                        $paths = array_map( 'FileBackend::normalizeStoragePath', $paths );
                }
+
                return ScopedLock::factory( $this->lockManager, $paths, $type, $status );
        }
 
@@ -1214,7 +1225,7 @@ abstract class FileBackend {
         *
         * @param array $ops List of file operations to FileBackend::doOperations()
         * @param Status $status Status to update on lock/unlock
-        * @return Array List of ScopedFileLocks or null values
+        * @return array List of ScopedFileLocks or null values
         * @since 1.20
         */
        abstract public function getScopedLocksForOps( array $ops, Status $status );
@@ -1267,7 +1278,7 @@ abstract class FileBackend {
         * This does not do any path normalization or traversal checks.
         *
         * @param string $storagePath
-        * @return Array (backend, container, rel object) or (null, null, null)
+        * @return array (backend, container, rel object) or (null, null, null)
         */
        final public static function splitStoragePath( $storagePath ) {
                if ( self::isStoragePath( $storagePath ) ) {
@@ -1281,6 +1292,7 @@ abstract class FileBackend {
                                }
                        }
                }
+
                return array( null, null, null );
        }
 
@@ -1301,6 +1313,7 @@ abstract class FileBackend {
                                        : "mwstore://{$backend}/{$container}";
                        }
                }
+
                return null;
        }
 
@@ -1315,6 +1328,7 @@ abstract class FileBackend {
        final public static function parentStoragePath( $storagePath ) {
                $storagePath = dirname( $storagePath );
                list( , , $rel ) = self::splitStoragePath( $storagePath );
+
                return ( $rel === null ) ? null : $storagePath;
        }
 
@@ -1326,6 +1340,7 @@ abstract class FileBackend {
         */
        final public static function extensionFromPath( $path ) {
                $i = strrpos( $path, '.' );
+
                return strtolower( $i ? substr( $path, $i + 1 ) : '' );
        }
 
@@ -1395,6 +1410,7 @@ abstract class FileBackend {
                                return null;
                        }
                }
+
                return $path;
        }
 }
@@ -1403,4 +1419,5 @@ abstract class FileBackend {
  * @ingroup FileBackend
  * @since 1.22
  */
-class FileBackendError extends MWException {}
+class FileBackendError extends MWException {
+}
index be8a207..491424b 100644 (file)
  * @since 1.19
  */
 class FileBackendGroup {
-       /**
-        * @var FileBackendGroup
-        */
+       /** @var FileBackendGroup */
        protected static $instance = null;
 
-       /** @var Array (name => ('class' => string, 'config' => array, 'instance' => object)) */
+       /** @var array (name => ('class' => string, 'config' => array, 'instance' => object)) */
        protected $backends = array();
 
-       protected function __construct() {}
+       protected function __construct() {
+       }
 
        /**
         * @return FileBackendGroup
@@ -47,13 +46,12 @@ class FileBackendGroup {
                        self::$instance = new self();
                        self::$instance->initFromGlobals();
                }
+
                return self::$instance;
        }
 
        /**
         * Destroy the singleton instance
-        *
-        * @return void
         */
        public static function destroySingleton() {
                self::$instance = null;
@@ -61,8 +59,6 @@ class FileBackendGroup {
 
        /**
         * Register file backends from the global variables
-        *
-        * @return void
         */
        protected function initFromGlobals() {
                global $wgLocalFileRepo, $wgForeignFileRepos, $wgFileBackends;
@@ -116,8 +112,7 @@ class FileBackendGroup {
        /**
         * Register an array of file backend configurations
         *
-        * @param Array $configs
-        * @return void
+        * @param array $configs
         * @throws MWException
         */
        protected function register( array $configs ) {
@@ -159,6 +154,7 @@ class FileBackendGroup {
                        $config = $this->backends[$name]['config'];
                        $this->backends[$name]['instance'] = new $class( $config );
                }
+
                return $this->backends[$name]['instance'];
        }
 
@@ -166,7 +162,7 @@ class FileBackendGroup {
         * Get the config array for a backend object with a given name
         *
         * @param string $name
-        * @return Array
+        * @return array
         * @throws MWException
         */
        public function config( $name ) {
@@ -174,6 +170,7 @@ class FileBackendGroup {
                        throw new MWException( "No backend defined with the name `$name`." );
                }
                $class = $this->backends[$name]['class'];
+
                return array( 'class' => $class ) + $this->backends[$name]['config'];
        }
 
@@ -188,6 +185,7 @@ class FileBackendGroup {
                if ( $backend !== null && isset( $this->backends[$backend] ) ) {
                        return $this->get( $backend );
                }
+
                return null;
        }
 }
index 97584a7..b3c46c6 100644 (file)
  * @since 1.19
  */
 class FileBackendMultiWrite extends FileBackend {
-       /** @var Array Prioritized list of FileBackendStore objects */
-       protected $backends = array(); // array of (backend index => backends)
-       protected $masterIndex = -1; // integer; index of master backend
-       protected $syncChecks = 0; // integer; bitfield
-       protected $autoResync = false; // boolean
+       /** @var array Prioritized list of FileBackendStore objects.
+        * array of (backend index => backends)
+        */
+       protected $backends = array();
+
+       /** @var int Index of master backend  */
+       protected $masterIndex = -1;
+
+       /** @var int Bitfield */
+       protected $syncChecks = 0;
+
+       /** @var string|bool */
+       protected $autoResync = false;
 
-       /** @var Array */
+       /** @var array */
        protected $noPushDirConts = array();
-       protected $noPushQuickOps = false; // boolean
+
+       /** @var bool */
+       protected $noPushQuickOps = false;
 
        /* Possible internal backend consistency checks */
        const CHECK_SIZE = 1;
@@ -81,7 +91,7 @@ class FileBackendMultiWrite extends FileBackend {
         *   - noPushQuickOps : (hack) Only apply doQuickOperations() to the master backend.
         *   - noPushDirConts : (hack) Only apply directory functions to the master backend.
         *
-        * @param Array $config
+        * @param array $config
         * @throws MWException
         */
        public function __construct( array $config ) {
@@ -167,6 +177,7 @@ class FileBackendMultiWrite extends FileBackend {
                        // Try to resync the clone backends to the master on the spot...
                        if ( !$this->autoResync || !$this->resyncFiles( $relevantPaths )->isOK() ) {
                                $status->merge( $syncStatus );
+
                                return $status; // abort
                        }
                }
@@ -321,8 +332,8 @@ class FileBackendMultiWrite extends FileBackend {
                                        // already synced; nothing to do
                                } elseif ( $mSha1 !== false ) { // file is in master
                                        if ( $this->autoResync === 'conservative'
-                                               && $cStat && $cStat['mtime'] > $mStat['mtime'] )
-                                       {
+                                               && $cStat && $cStat['mtime'] > $mStat['mtime']
+                                       {
                                                $status->fatal( 'backend-fail-synced', $path );
                                                continue; // don't rollback data
                                        }
@@ -348,7 +359,7 @@ class FileBackendMultiWrite extends FileBackend {
         * Get a list of file storage paths to read or write for a list of operations
         *
         * @param array $ops Same format as doOperations()
-        * @return Array List of storage paths to files (does not include directories)
+        * @return array List of storage paths to files (does not include directories)
         */
        protected function fileStoragePathsForOps( array $ops ) {
                $paths = array();
@@ -357,8 +368,8 @@ class FileBackendMultiWrite extends FileBackend {
                                // For things like copy/move/delete with "ignoreMissingSource" and there
                                // is no source file, nothing should happen and there should be no errors.
                                if ( empty( $op['ignoreMissingSource'] )
-                                       || $this->fileExists( array( 'src' => $op['src'] ) ) )
-                               {
+                                       || $this->fileExists( array( 'src' => $op['src'] ) )
+                               {
                                        $paths[] = $op['src'];
                                }
                        }
@@ -369,6 +380,7 @@ class FileBackendMultiWrite extends FileBackend {
                                $paths[] = $op['dst'];
                        }
                }
+
                return array_values( array_unique( array_filter( $paths, 'FileBackend::isStoragePath' ) ) );
        }
 
@@ -378,7 +390,7 @@ class FileBackendMultiWrite extends FileBackend {
         *
         * @param array $ops List of file operation arrays
         * @param FileBackendStore $backend
-        * @return Array
+        * @return array
         */
        protected function substOpBatchPaths( array $ops, FileBackendStore $backend ) {
                $newOps = array(); // operations
@@ -391,6 +403,7 @@ class FileBackendMultiWrite extends FileBackend {
                        }
                        $newOps[] = $newOp;
                }
+
                return $newOps;
        }
 
@@ -399,10 +412,11 @@ class FileBackendMultiWrite extends FileBackend {
         *
         * @param array $ops File operation array
         * @param FileBackendStore $backend
-        * @return Array
+        * @return array
         */
        protected function substOpPaths( array $ops, FileBackendStore $backend ) {
                $newOps = $this->substOpBatchPaths( array( $ops ), $backend );
+
                return $newOps[0];
        }
 
@@ -411,7 +425,7 @@ class FileBackendMultiWrite extends FileBackend {
         *
         * @param array|string $paths List of paths or single string path
         * @param FileBackendStore $backend
-        * @return Array|string
+        * @return array|string
         */
        protected function substPaths( $paths, FileBackendStore $backend ) {
                return preg_replace(
@@ -425,7 +439,7 @@ class FileBackendMultiWrite extends FileBackend {
         * Substitute the backend of internal storage paths with the proxy backend's name
         *
         * @param array|string $paths List of paths or single string path
-        * @return Array|string
+        * @return array|string
         */
        protected function unsubstPaths( $paths ) {
                return preg_replace(
@@ -456,6 +470,7 @@ class FileBackendMultiWrite extends FileBackend {
                $status->success = $masterStatus->success;
                $status->successCount = $masterStatus->successCount;
                $status->failCount = $masterStatus->failCount;
+
                return $status;
        }
 
@@ -465,6 +480,7 @@ class FileBackendMultiWrite extends FileBackend {
         */
        protected function replicateContainerDirChanges( $path ) {
                list( , $shortCont, ) = self::splitStoragePath( $path );
+
                return !in_array( $shortCont, $this->noPushDirConts );
        }
 
@@ -477,6 +493,7 @@ class FileBackendMultiWrite extends FileBackend {
                                $status->merge( $backend->doPrepare( $realParams ) );
                        }
                }
+
                return $status;
        }
 
@@ -489,6 +506,7 @@ class FileBackendMultiWrite extends FileBackend {
                                $status->merge( $backend->doSecure( $realParams ) );
                        }
                }
+
                return $status;
        }
 
@@ -501,6 +519,7 @@ class FileBackendMultiWrite extends FileBackend {
                                $status->merge( $backend->doPublish( $realParams ) );
                        }
                }
+
                return $status;
        }
 
@@ -513,32 +532,38 @@ class FileBackendMultiWrite extends FileBackend {
                                $status->merge( $backend->doClean( $realParams ) );
                        }
                }
+
                return $status;
        }
 
        public function concatenate( array $params ) {
                // We are writing to an FS file, so we don't need to do this per-backend
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->concatenate( $realParams );
        }
 
        public function fileExists( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->fileExists( $realParams );
        }
 
        public function getFileTimestamp( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileTimestamp( $realParams );
        }
 
        public function getFileSize( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileSize( $realParams );
        }
 
        public function getFileStat( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileStat( $realParams );
        }
 
@@ -550,21 +575,25 @@ class FileBackendMultiWrite extends FileBackend {
                foreach ( $contentsM as $path => $data ) {
                        $contents[$this->unsubstPaths( $path )] = $data;
                }
+
                return $contents;
        }
 
        public function getFileSha1Base36( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileSha1Base36( $realParams );
        }
 
        public function getFileProps( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileProps( $realParams );
        }
 
        public function streamFile( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->streamFile( $realParams );
        }
 
@@ -576,6 +605,7 @@ class FileBackendMultiWrite extends FileBackend {
                foreach ( $fsFilesM as $path => $fsFile ) {
                        $fsFiles[$this->unsubstPaths( $path )] = $fsFile;
                }
+
                return $fsFiles;
        }
 
@@ -587,26 +617,31 @@ class FileBackendMultiWrite extends FileBackend {
                foreach ( $tempFilesM as $path => $tempFile ) {
                        $tempFiles[$this->unsubstPaths( $path )] = $tempFile;
                }
+
                return $tempFiles;
        }
 
        public function getFileHttpUrl( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileHttpUrl( $realParams );
        }
 
        public function directoryExists( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->directoryExists( $realParams );
        }
 
        public function getDirectoryList( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getDirectoryList( $realParams );
        }
 
        public function getFileList( array $params ) {
                $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] );
+
                return $this->backends[$this->masterIndex]->getFileList( $realParams );
        }
 
@@ -627,6 +662,7 @@ class FileBackendMultiWrite extends FileBackend {
                        LockManager::LOCK_UW => $this->unsubstPaths( $paths[LockManager::LOCK_UW] ),
                        LockManager::LOCK_EX => $this->unsubstPaths( $paths[LockManager::LOCK_EX] )
                );
+
                // Actually acquire the locks
                return array( $this->getScopedFileLocks( $pbPaths, 'mixed', $status ) );
        }
index 0921e99..2fe51c0 100644 (file)
@@ -43,7 +43,7 @@ abstract class FileBackendStore extends FileBackend {
        /** @var ProcessCacheLRU Map of paths to large (RAM/disk) cache items */
        protected $expensiveCache;
 
-       /** @var Array Map of container names to sharding config */
+       /** @var array Map of container names to sharding config */
        protected $shardViaHashLevels = array();
 
        /** @var callback Method to get the MIME type of files */
@@ -52,7 +52,7 @@ abstract class FileBackendStore extends FileBackend {
        protected $maxFileSize = 4294967296; // integer bytes (4GiB)
 
        const CACHE_TTL = 10; // integer; TTL in seconds for process cache entries
-       const CACHE_CHEAP_SIZE = 300; // integer; max entries in "cheap cache"
+       const CACHE_CHEAP_SIZE = 500; // integer; max entries in "cheap cache"
        const CACHE_EXPENSIVE_SIZE = 5; // integer; max entries in "expensive cache"
 
        /**
@@ -68,9 +68,9 @@ abstract class FileBackendStore extends FileBackend {
                parent::__construct( $config );
                $this->mimeCallback = isset( $config['mimeCallback'] )
                        ? $config['mimeCallback']
-                       : function( $storagePath, $content, $fsPath ) {
+                       : function ( $storagePath, $content, $fsPath ) {
                                // @TODO: handle the case of extension-less files using the contents
-                               return StreamFile::contentTypeFromPath( $storagePath ) ?: 'unknown/unknown';
+                               return StreamFile::contentTypeFromPath( $storagePath ) ? : 'unknown/unknown';
                        };
                $this->memCache = new EmptyBagOStuff(); // disabled by default
                $this->cheapCache = new ProcessCacheLRU( self::CACHE_CHEAP_SIZE );
@@ -82,7 +82,7 @@ abstract class FileBackendStore extends FileBackend {
         * medium restrictions and basic performance constraints.
         * Do not call this function from places outside FileBackend and FileOp.
         *
-        * @return integer Bytes
+        * @return int Bytes
         */
        final public function maxFileSizeInternal() {
                return $this->maxFileSize;
@@ -129,11 +129,13 @@ abstract class FileBackendStore extends FileBackend {
                                $this->deleteFileCache( $params['dst'] ); // persistent cache
                        }
                }
+
                return $status;
        }
 
        /**
         * @see FileBackendStore::createInternal()
+        * @param array $params
         * @return Status
         */
        abstract protected function doCreateInternal( array $params );
@@ -168,11 +170,13 @@ abstract class FileBackendStore extends FileBackend {
                                $this->deleteFileCache( $params['dst'] ); // persistent cache
                        }
                }
+
                return $status;
        }
 
        /**
         * @see FileBackendStore::storeInternal()
+        * @param array $params
         * @return Status
         */
        abstract protected function doStoreInternal( array $params );
@@ -203,11 +207,13 @@ abstract class FileBackendStore extends FileBackend {
                if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) {
                        $this->deleteFileCache( $params['dst'] ); // persistent cache
                }
+
                return $status;
        }
 
        /**
         * @see FileBackendStore::copyInternal()
+        * @param array $params
         * @return Status
         */
        abstract protected function doCopyInternal( array $params );
@@ -236,6 +242,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::deleteInternal()
+        * @param array $params
         * @return Status
         */
        abstract protected function doDeleteInternal( array $params );
@@ -267,11 +274,13 @@ abstract class FileBackendStore extends FileBackend {
                if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) {
                        $this->deleteFileCache( $params['dst'] ); // persistent cache
                }
+
                return $status;
        }
 
        /**
         * @see FileBackendStore::moveInternal()
+        * @param array $params
         * @return Status
         */
        protected function doMoveInternal( array $params ) {
@@ -285,6 +294,7 @@ abstract class FileBackendStore extends FileBackend {
                        $status->merge( $this->deleteInternal( array( 'src' => $params['src'] ) ) );
                        $status->setResult( true, $status->value ); // ignore delete() errors
                }
+
                return $status;
        }
 
@@ -311,11 +321,13 @@ abstract class FileBackendStore extends FileBackend {
                } else {
                        $status = Status::newGood(); // nothing to do
                }
+
                return $status;
        }
 
        /**
         * @see FileBackendStore::describeInternal()
+        * @param array $params
         * @return Status
         */
        protected function doDescribeInternal( array $params ) {
@@ -355,6 +367,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::concatenate()
+        * @param array $params
         * @return Status
         */
        protected function doConcatenate( array $params ) {
@@ -368,6 +381,7 @@ abstract class FileBackendStore extends FileBackend {
                wfRestoreWarnings();
                if ( !$ok ) { // not present or not empty
                        $status->fatal( 'backend-fail-opentemp', $tmpPath );
+
                        return $status;
                }
 
@@ -378,6 +392,7 @@ abstract class FileBackendStore extends FileBackend {
                                $fsFile = $this->getLocalReference( array( 'src' => $path ) );
                                if ( !$fsFile ) { // retry failed?
                                        $status->fatal( 'backend-fail-read', $path );
+
                                        return $status;
                                }
                        }
@@ -388,6 +403,7 @@ abstract class FileBackendStore extends FileBackend {
                $tmpHandle = fopen( $tmpPath, 'ab' );
                if ( $tmpHandle === false ) {
                        $status->fatal( 'backend-fail-opentemp', $tmpPath );
+
                        return $status;
                }
 
@@ -398,6 +414,7 @@ abstract class FileBackendStore extends FileBackend {
                        if ( $sourceHandle === false ) {
                                fclose( $tmpHandle );
                                $status->fatal( 'backend-fail-read', $virtualSource );
+
                                return $status;
                        }
                        // Append chunk to file (pass chunk size to avoid magic quotes)
@@ -405,12 +422,14 @@ abstract class FileBackendStore extends FileBackend {
                                fclose( $sourceHandle );
                                fclose( $tmpHandle );
                                $status->fatal( 'backend-fail-writetemp', $tmpPath );
+
                                return $status;
                        }
                        fclose( $sourceHandle );
                }
                if ( !fclose( $tmpHandle ) ) {
                        $status->fatal( 'backend-fail-closetemp', $tmpPath );
+
                        return $status;
                }
 
@@ -426,6 +445,7 @@ abstract class FileBackendStore extends FileBackend {
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dir'] );
+
                        return $status; // invalid storage path
                }
 
@@ -444,6 +464,9 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::doPrepare()
+        * @param $container
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doPrepareInternal( $container, $dir, array $params ) {
@@ -457,6 +480,7 @@ abstract class FileBackendStore extends FileBackend {
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dir'] );
+
                        return $status; // invalid storage path
                }
 
@@ -475,6 +499,9 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::doSecure()
+        * @param $container
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doSecureInternal( $container, $dir, array $params ) {
@@ -488,6 +515,7 @@ abstract class FileBackendStore extends FileBackend {
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dir'] );
+
                        return $status; // invalid storage path
                }
 
@@ -506,6 +534,9 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::doPublish()
+        * @param $container
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doPublishInternal( $container, $dir, array $params ) {
@@ -531,6 +562,7 @@ abstract class FileBackendStore extends FileBackend {
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dir'] );
+
                        return $status; // invalid storage path
                }
 
@@ -558,6 +590,9 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::doClean()
+        * @param $container
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doCleanInternal( $container, $dir, array $params ) {
@@ -567,18 +602,21 @@ abstract class FileBackendStore extends FileBackend {
        final public function fileExists( array $params ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
+
                return ( $stat === null ) ? null : (bool)$stat; // null => failure
        }
 
        final public function getFileTimestamp( array $params ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
+
                return $stat ? $stat['mtime'] : false;
        }
 
        final public function getFileSize( array $params ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
+
                return $stat ? $stat['size'] : false;
        }
 
@@ -606,11 +644,9 @@ abstract class FileBackendStore extends FileBackend {
                                }
                        }
                }
-               wfProfileIn( __METHOD__ . '-miss' );
                wfProfileIn( __METHOD__ . '-miss-' . $this->name );
                $stat = $this->doGetFileStat( $params );
                wfProfileOut( __METHOD__ . '-miss-' . $this->name );
-               wfProfileOut( __METHOD__ . '-miss' );
                if ( is_array( $stat ) ) { // file exists
                        $stat['latest'] = $latest;
                        $this->cheapCache->set( $path, 'stat', $stat );
@@ -627,6 +663,7 @@ abstract class FileBackendStore extends FileBackend {
                } else { // an error occurred
                        wfDebug( __METHOD__ . ": Could not stat file $path.\n" );
                }
+
                return $stat;
        }
 
@@ -646,7 +683,8 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::getFileContentsMulti()
-        * @return Array
+        * @param array $params
+        * @return array
         */
        protected function doGetFileContentsMulti( array $params ) {
                $contents = array();
@@ -655,6 +693,7 @@ abstract class FileBackendStore extends FileBackend {
                        $contents[$path] = $fsFile ? file_get_contents( $fsFile->getPath() ) : false;
                        wfRestoreWarnings();
                }
+
                return $contents;
        }
 
@@ -673,17 +712,17 @@ abstract class FileBackendStore extends FileBackend {
                                return $stat['hash'];
                        }
                }
-               wfProfileIn( __METHOD__ . '-miss' );
                wfProfileIn( __METHOD__ . '-miss-' . $this->name );
                $hash = $this->doGetFileSha1Base36( $params );
                wfProfileOut( __METHOD__ . '-miss-' . $this->name );
-               wfProfileOut( __METHOD__ . '-miss' );
                $this->cheapCache->set( $path, 'sha1', array( 'hash' => $hash, 'latest' => $latest ) );
+
                return $hash;
        }
 
        /**
         * @see FileBackendStore::getFileSha1Base36()
+        * @param array $params
         * @return bool|string
         */
        protected function doGetFileSha1Base36( array $params ) {
@@ -699,6 +738,7 @@ abstract class FileBackendStore extends FileBackend {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
                $fsFile = $this->getLocalReference( $params );
                $props = $fsFile ? $fsFile->getProps() : FSFile::placeholderProps();
+
                return $props;
        }
 
@@ -738,7 +778,8 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::getLocalReferenceMulti()
-        * @return Array
+        * @param array $params
+        * @return array
         */
        protected function doGetLocalReferenceMulti( array $params ) {
                return $this->doGetLocalCopyMulti( $params );
@@ -755,12 +796,14 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::getLocalCopyMulti()
-        * @return Array
+        * @param array $params
+        * @return array
         */
        abstract protected function doGetLocalCopyMulti( array $params );
 
        /**
         * @see FileBackend::getFileHttpUrl()
+        * @param array $params
         * @return string|null
         */
        public function getFileHttpUrl( array $params ) {
@@ -782,11 +825,9 @@ abstract class FileBackendStore extends FileBackend {
                if ( $res == StreamFile::NOT_MODIFIED ) {
                        // do nothing; client cache is up to date
                } elseif ( $res == StreamFile::READY_STREAM ) {
-                       wfProfileIn( __METHOD__ . '-send' );
                        wfProfileIn( __METHOD__ . '-send-' . $this->name );
                        $status = $this->doStreamFile( $params );
                        wfProfileOut( __METHOD__ . '-send-' . $this->name );
-                       wfProfileOut( __METHOD__ . '-send' );
                        if ( !$status->isOK() ) {
                                // Per bug 41113, nasty things can happen if bad cache entries get
                                // stuck in cache. It's also possible that this error can come up
@@ -804,6 +845,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::streamFile()
+        * @param array $params
         * @return Status
         */
        protected function doStreamFile( array $params ) {
@@ -839,6 +881,7 @@ abstract class FileBackendStore extends FileBackend {
                                        $res = null; // if we don't find anything, it is indeterminate
                                }
                        }
+
                        return $res;
                }
        }
@@ -865,6 +908,7 @@ abstract class FileBackendStore extends FileBackend {
                        wfDebug( __METHOD__ . ": iterating over all container shards.\n" );
                        // File listing spans multiple containers/shards
                        list( , $shortCont, ) = self::splitStoragePath( $params['dir'] );
+
                        return new FileBackendStoreShardDirIterator( $this,
                                $fullCont, $dir, $this->getContainerSuffixes( $shortCont ), $params );
                }
@@ -894,6 +938,7 @@ abstract class FileBackendStore extends FileBackend {
                        wfDebug( __METHOD__ . ": iterating over all container shards.\n" );
                        // File listing spans multiple containers/shards
                        list( , $shortCont, ) = self::splitStoragePath( $params['dir'] );
+
                        return new FileBackendStoreShardFileIterator( $this,
                                $fullCont, $dir, $this->getContainerSuffixes( $shortCont ), $params );
                }
@@ -919,7 +964,7 @@ abstract class FileBackendStore extends FileBackend {
         * An exception is thrown if an unsupported operation is requested.
         *
         * @param array $ops Same format as doOperations()
-        * @return Array List of FileOp objects
+        * @return array List of FileOp objects
         * @throws MWException
         */
        final public function getOperationsInternal( array $ops ) {
@@ -959,7 +1004,7 @@ abstract class FileBackendStore extends FileBackend {
         * normalized.
         *
         * @param array $performOps List of FileOp objects
-        * @return Array (LockManager::LOCK_UW => path list, LockManager::LOCK_EX => path list)
+        * @return array (LockManager::LOCK_UW => path list, LockManager::LOCK_EX => path list)
         */
        final public function getPathsToLockForOpsInternal( array $performOps ) {
                // Build up a list of files to lock...
@@ -981,6 +1026,7 @@ abstract class FileBackendStore extends FileBackend {
 
        public function getScopedLocksForOps( array $ops, Status $status ) {
                $paths = $this->getPathsToLockForOpsInternal( $this->getOperationsInternal( $ops ) );
+
                return array( $this->getScopedFileLocks( $paths, 'mixed', $status ) );
        }
 
@@ -1035,7 +1081,7 @@ abstract class FileBackendStore extends FileBackend {
                // Clear any file cache entries
                $this->clearCache();
 
-               $supportedOps = array( 'create', 'store', 'copy', 'move', 'delete', 'null' );
+               $supportedOps = array( 'create', 'store', 'copy', 'move', 'delete', 'describe', 'null' );
                $async = ( $this->parallelize === 'implicit' && count( $ops ) > 1 );
                $maxConcurrency = $this->concurrency; // throttle
 
@@ -1086,9 +1132,10 @@ abstract class FileBackendStore extends FileBackend {
         * The resulting Status object fields will correspond
         * to the order in which the handles where given.
         *
-        * @param array $handles List of FileBackendStoreOpHandle objects
-        * @return Array Map of Status objects
+        * @param array $fileOpHandles
         * @throws MWException
+        * @internal param array $handles List of FileBackendStoreOpHandle objects
+        * @return array Map of Status objects
         */
        final public function executeOpHandlesInternal( array $fileOpHandles ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
@@ -1103,6 +1150,7 @@ abstract class FileBackendStore extends FileBackend {
                foreach ( $fileOpHandles as $fileOpHandle ) {
                        $fileOpHandle->closeResources();
                }
+
                return $res;
        }
 
@@ -1110,12 +1158,13 @@ abstract class FileBackendStore extends FileBackend {
         * @see FileBackendStore::executeOpHandlesInternal()
         * @param array $fileOpHandles
         * @throws MWException
-        * @return Array List of corresponding Status objects
+        * @return array List of corresponding Status objects
         */
        protected function doExecuteOpHandlesInternal( array $fileOpHandles ) {
-               foreach ( $fileOpHandles as $fileOpHandle ) { // OK if empty
+               if ( count( $fileOpHandles ) ) {
                        throw new MWException( "This backend supports no asynchronous operations." );
                }
+
                return array();
        }
 
@@ -1126,7 +1175,7 @@ abstract class FileBackendStore extends FileBackend {
         * specific errors, especially in the middle of batch file operations.
         *
         * @param array $op Same format as doOperation()
-        * @return Array
+        * @return array
         */
        protected function stripInvalidHeadersFromOp( array $op ) {
                static $longs = array( 'Content-Disposition' );
@@ -1141,6 +1190,7 @@ abstract class FileBackendStore extends FileBackend {
                                }
                        }
                }
+
                return $op;
        }
 
@@ -1178,9 +1228,9 @@ abstract class FileBackendStore extends FileBackend {
         * @see FileBackend::clearCache()
         *
         * @param array $paths Storage paths (optional)
-        * @return void
         */
-       protected function doClearCache( array $paths = null ) {}
+       protected function doClearCache( array $paths = null ) {
+       }
 
        /**
         * Is this a key/value store where directories are just virtual?
@@ -1218,7 +1268,7 @@ abstract class FileBackendStore extends FileBackend {
         * be scanned by looking in all the container shards.
         *
         * @param string $storagePath
-        * @return Array (container, path, container suffix) or (null, null, null) if invalid
+        * @return array (container, path, container suffix) or (null, null, null) if invalid
         */
        final protected function resolveStoragePath( $storagePath ) {
                list( $backend, $container, $relPath ) = self::splitStoragePath( $storagePath );
@@ -1242,6 +1292,7 @@ abstract class FileBackendStore extends FileBackend {
                                }
                        }
                }
+
                return array( null, null, null );
        }
 
@@ -1258,13 +1309,14 @@ abstract class FileBackendStore extends FileBackend {
         * @see FileBackendStore::resolveStoragePath()
         *
         * @param string $storagePath
-        * @return Array (container, path) or (null, null) if invalid
+        * @return array (container, path) or (null, null) if invalid
         */
        final protected function resolveStoragePathReal( $storagePath ) {
                list( $container, $relPath, $cShard ) = $this->resolveStoragePath( $storagePath );
                if ( $cShard !== null && substr( $relPath, -1 ) !== '/' ) {
                        return array( $container, $relPath );
                }
+
                return array( null, null );
        }
 
@@ -1299,8 +1351,10 @@ abstract class FileBackendStore extends FileBackend {
                        if ( preg_match( "!^(?:[^/]{2,}/)*$hashDirRegex(?:/|$)!", $relPath, $m ) ) {
                                return '.' . implode( '', array_slice( $m, 1 ) );
                        }
+
                        return null; // failed to match
                }
+
                return ''; // no sharding
        }
 
@@ -1314,6 +1368,7 @@ abstract class FileBackendStore extends FileBackend {
         */
        final public function isSingleShardPathInternal( $storagePath ) {
                list( , , $shard ) = $this->resolveStoragePath( $storagePath );
+
                return ( $shard !== null );
        }
 
@@ -1323,7 +1378,7 @@ abstract class FileBackendStore extends FileBackend {
         * the container are required to be hashed accordingly.
         *
         * @param string $container
-        * @return Array (integer levels, integer base, repeat flag) or (0, 0, false)
+        * @return array (integer levels, integer base, repeat flag) or (0, 0, false)
         */
        final protected function getContainerHashLevels( $container ) {
                if ( isset( $this->shardViaHashLevels[$container] ) ) {
@@ -1336,6 +1391,7 @@ abstract class FileBackendStore extends FileBackend {
                                }
                        }
                }
+
                return array( 0, 0, false ); // no sharding
        }
 
@@ -1343,7 +1399,7 @@ abstract class FileBackendStore extends FileBackend {
         * Get a list of full container shard suffixes for a container
         *
         * @param string $container
-        * @return Array
+        * @return array
         */
        final protected function getContainerSuffixes( $container ) {
                $shards = array();
@@ -1354,6 +1410,7 @@ abstract class FileBackendStore extends FileBackend {
                                $shards[] = '.' . wfBaseConvert( $index, 10, $base, $digits );
                        }
                }
+
                return $shards;
        }
 
@@ -1412,7 +1469,6 @@ abstract class FileBackendStore extends FileBackend {
         *
         * @param string $container Resolved container name
         * @param array $val Information to cache
-        * @return void
         */
        final protected function setContainerCache( $container, array $val ) {
                $this->memCache->add( $this->containerCacheKey( $container ), $val, 14 * 86400 );
@@ -1423,7 +1479,6 @@ abstract class FileBackendStore extends FileBackend {
         * The cache key is salted for a while to prevent race conditions.
         *
         * @param string $container Resolved container name
-        * @return void
         */
        final protected function deleteContainerCache( $container ) {
                if ( !$this->memCache->set( $this->containerCacheKey( $container ), 'PURGED', 300 ) ) {
@@ -1436,8 +1491,7 @@ abstract class FileBackendStore extends FileBackend {
         * used in a list of container names, storage paths, or FileOp objects.
         * This loads the persistent cache values into the process cache.
         *
-        * @param Array $items
-        * @return void
+        * @param array $items
         */
        final protected function primeContainerCache( array $items ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
@@ -1480,9 +1534,9 @@ abstract class FileBackendStore extends FileBackend {
         * Only containers that actually exist should appear in the map.
         *
         * @param array $containerInfo Map of resolved container names to cached info
-        * @return void
         */
-       protected function doPrimeContainerCache( array $containerInfo ) {}
+       protected function doPrimeContainerCache( array $containerInfo ) {
+       }
 
        /**
         * Get the cache key for a file path
@@ -1501,7 +1555,6 @@ abstract class FileBackendStore extends FileBackend {
         *
         * @param string $path Storage path
         * @param array $val Stat information to cache
-        * @return void
         */
        final protected function setFileCache( $path, array $val ) {
                $path = FileBackend::normalizeStoragePath( $path );
@@ -1520,7 +1573,6 @@ abstract class FileBackendStore extends FileBackend {
         * a file is created at a path were there was none before.
         *
         * @param string $path Storage path
-        * @return void
         */
        final protected function deleteFileCache( $path ) {
                $path = FileBackend::normalizeStoragePath( $path );
@@ -1538,7 +1590,6 @@ abstract class FileBackendStore extends FileBackend {
         * This loads the persistent cache values into the process cache.
         *
         * @param array $items List of storage paths or FileOps
-        * @return void
         */
        final protected function primeFileCache( array $items ) {
                $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
@@ -1581,7 +1632,7 @@ abstract class FileBackendStore extends FileBackend {
         * Set the 'concurrency' option from a list of operation options
         *
         * @param array $opts Map of operation options
-        * @return Array
+        * @return array
         */
        final protected function setConcurrencyFlags( array $opts ) {
                $opts['concurrency'] = 1; // off
@@ -1594,6 +1645,7 @@ abstract class FileBackendStore extends FileBackend {
                                $opts['concurrency'] = $this->concurrency;
                        }
                }
+
                return $opts;
        }
 
@@ -1619,19 +1671,17 @@ abstract class FileBackendStore extends FileBackend {
  * passed to FileBackendStore::executeOpHandlesInternal().
  */
 abstract class FileBackendStoreOpHandle {
-       /** @var Array */
+       /** @var array */
        public $params = array(); // params to caller functions
        /** @var FileBackendStore */
        public $backend;
-       /** @var Array */
+       /** @var array */
        public $resourcesToClose = array();
 
        public $call; // string; name that identifies the function called
 
        /**
         * Close all open file handles
-        *
-        * @return void
         */
        public function closeResources() {
                array_map( 'fclose', $this->resourcesToClose );
@@ -1647,13 +1697,17 @@ abstract class FileBackendStoreOpHandle {
 abstract class FileBackendStoreShardListIterator extends FilterIterator {
        /** @var FileBackendStore */
        protected $backend;
-       /** @var Array */
+
+       /** @var array */
        protected $params;
 
-       protected $container; // string; full container name
-       protected $directory; // string; resolved relative path
+       /** @var string Full container name */
+       protected $container;
+
+       /** @var string Resolved relative path */
+       protected $directory;
 
-       /** @var Array */
+       /** @var array */
        protected $multiShardPaths = array(); // (rel path => 1)
 
        /**
@@ -1689,6 +1743,7 @@ abstract class FileBackendStoreShardListIterator extends FilterIterator {
                        return false;
                } else {
                        $this->multiShardPaths[$rel] = 1;
+
                        return true;
                }
        }
index fe83308..538d9b4 100644 (file)
  * @since 1.19
  */
 abstract class FileOp {
-       /** @var Array */
+       /** @var array */
        protected $params = array();
+
        /** @var FileBackendStore */
        protected $backend;
 
-       protected $state = self::STATE_NEW; // integer
-       protected $failed = false; // boolean
-       protected $async = false; // boolean
-       protected $batchId; // string
+       /** @var int */
+       protected $state = self::STATE_NEW;
+
+       /** @var bool */
+       protected $failed = false;
+
+       /** @var bool */
+       protected $async = false;
+
+       /** @var string */
+       protected $batchId;
 
-       protected $doOperation = true; // boolean; operation is not a no-op
-       protected $sourceSha1; // string
-       protected $overwriteSameCase; // boolean
-       protected $destExists; // boolean
+       /** @var bool Operation is not a no-op */
+       protected $doOperation = true;
+
+       /** @var string */
+       protected $sourceSha1;
+
+       /** @var bool */
+       protected $overwriteSameCase;
+
+       /** @var bool */
+       protected $destExists;
 
        /* Object life-cycle */
        const STATE_NEW = 1;
@@ -58,47 +73,29 @@ abstract class FileOp {
         * Build a new batch file operation transaction
         *
         * @param FileBackendStore $backend
-        * @param Array $params
+        * @param array $params
         * @throws MWException
         */
        final public function __construct( FileBackendStore $backend, array $params ) {
                $this->backend = $backend;
-               list( $required, $optional ) = $this->allowedParams();
-               // @todo normalizeAnyStoragePaths() calls are overzealous, use a parameter list
+               list( $required, $optional, $paths ) = $this->allowedParams();
                foreach ( $required as $name ) {
                        if ( isset( $params[$name] ) ) {
-                               // Normalize paths so the paths to the same file have the same string
-                               $this->params[$name] = self::normalizeAnyStoragePaths( $params[$name] );
+                               $this->params[$name] = $params[$name];
                        } else {
                                throw new MWException( "File operation missing parameter '$name'." );
                        }
                }
                foreach ( $optional as $name ) {
                        if ( isset( $params[$name] ) ) {
-                               // Normalize paths so the paths to the same file have the same string
-                               $this->params[$name] = self::normalizeAnyStoragePaths( $params[$name] );
+                               $this->params[$name] = $params[$name];
                        }
                }
-               $this->params = $params;
-       }
-
-       /**
-        * Normalize $item or anything in $item that is a valid storage path
-        *
-        * @param string $item|array
-        * @return string|Array
-        */
-       protected function normalizeAnyStoragePaths( $item ) {
-               if ( is_array( $item ) ) {
-                       $res = array();
-                       foreach ( $item as $k => $v ) {
-                               $k = self::normalizeIfValidStoragePath( $k );
-                               $v = self::normalizeIfValidStoragePath( $v );
-                               $res[$k] = $v;
+               foreach ( $paths as $name ) {
+                       if ( isset( $this->params[$name] ) ) {
+                               // Normalize paths so the paths to the same file have the same string
+                               $this->params[$name] = self::normalizeIfValidStoragePath( $this->params[$name] );
                        }
-                       return $res;
-               } else {
-                       return self::normalizeIfValidStoragePath( $item );
                }
        }
 
@@ -111,8 +108,10 @@ abstract class FileOp {
        protected static function normalizeIfValidStoragePath( $path ) {
                if ( FileBackend::isStoragePath( $path ) ) {
                        $res = FileBackend::normalizeStoragePath( $path );
+
                        return ( $res !== null ) ? $res : $path;
                }
+
                return $path;
        }
 
@@ -120,7 +119,6 @@ abstract class FileOp {
         * Set the batch UUID this operation belongs to
         *
         * @param string $batchId
-        * @return void
         */
        final public function setBatchId( $batchId ) {
                $this->batchId = $batchId;
@@ -148,7 +146,7 @@ abstract class FileOp {
        /**
         * Get a new empty predicates array for precheck()
         *
-        * @return Array
+        * @return array
         */
        final public static function newPredicates() {
                return array( 'exists' => array(), 'sha1' => array() );
@@ -157,7 +155,7 @@ abstract class FileOp {
        /**
         * Get a new empty dependency tracking array for paths read/written to
         *
-        * @return Array
+        * @return array
         */
        final public static function newDependencies() {
                return array( 'read' => array(), 'write' => array() );
@@ -167,18 +165,19 @@ abstract class FileOp {
         * Update a dependency tracking array to account for this operation
         *
         * @param array $deps Prior path reads/writes; format of FileOp::newPredicates()
-        * @return Array
+        * @return array
         */
        final public function applyDependencies( array $deps ) {
                $deps['read'] += array_fill_keys( $this->storagePathsRead(), 1 );
                $deps['write'] += array_fill_keys( $this->storagePathsChanged(), 1 );
+
                return $deps;
        }
 
        /**
         * Check if this operation changes files listed in $paths
         *
-        * @param array $paths Prior path reads/writes; format of FileOp::newPredicates()
+        * @param array $deps Prior path reads/writes; format of FileOp::newPredicates()
         * @return boolean
         */
        final public function dependsOn( array $deps ) {
@@ -192,6 +191,7 @@ abstract class FileOp {
                                return true; // "flow" dependency
                        }
                }
+
                return false;
        }
 
@@ -200,7 +200,7 @@ abstract class FileOp {
         *
         * @param array $oPredicates Pre-op info about files (format of FileOp::newPredicates)
         * @param array $nPredicates Post-op info about files (format of FileOp::newPredicates)
-        * @return Array
+        * @return array
         */
        final public function getJournalEntries( array $oPredicates, array $nPredicates ) {
                if ( !$this->doOperation ) {
@@ -232,6 +232,7 @@ abstract class FileOp {
                                );
                        }
                }
+
                return array_merge( $nullEntries, $updateEntries, $deleteEntries );
        }
 
@@ -240,7 +241,7 @@ abstract class FileOp {
         * This must update $predicates for each path that the op can change
         * except when a failing status object is returned.
         *
-        * @param Array $predicates
+        * @param array $predicates
         * @return Status
         */
        final public function precheck( array &$predicates ) {
@@ -252,10 +253,12 @@ abstract class FileOp {
                if ( !$status->isOK() ) {
                        $this->failed = true;
                }
+
                return $status;
        }
 
        /**
+        * @param array $predicates
         * @return Status
         */
        protected function doPrecheck( array &$predicates ) {
@@ -283,6 +286,7 @@ abstract class FileOp {
                } else { // no-op
                        $status = Status::newGood();
                }
+
                return $status;
        }
 
@@ -302,23 +306,24 @@ abstract class FileOp {
                $this->async = true;
                $result = $this->attempt();
                $this->async = false;
+
                return $result;
        }
 
        /**
         * Get the file operation parameters
         *
-        * @return Array (required params list, optional params list)
+        * @return array (required params list, optional params list, list of params that are paths)
         */
        protected function allowedParams() {
-               return array( array(), array() );
+               return array( array(), array(), array() );
        }
 
        /**
         * Adjust params to FileBackendStore internal file calls
         *
-        * @param Array $params
-        * @return Array (required params list, optional params list)
+        * @param array $params
+        * @return array (required params list, optional params list)
         */
        protected function setFlags( array $params ) {
                return array( 'async' => $this->async ) + $params;
@@ -327,7 +332,7 @@ abstract class FileOp {
        /**
         * Get a list of storage paths read from for this operation
         *
-        * @return Array
+        * @return array
         */
        public function storagePathsRead() {
                return array();
@@ -336,7 +341,7 @@ abstract class FileOp {
        /**
         * Get a list of storage paths written to for this operation
         *
-        * @return Array
+        * @return array
         */
        public function storagePathsChanged() {
                return array();
@@ -347,7 +352,7 @@ abstract class FileOp {
         * Also set the destExists, overwriteSameCase and sourceSha1 member variables.
         * A bad status will be returned if there is no chance it can be overwritten.
         *
-        * @param Array $predicates
+        * @param array $predicates
         * @return Status
         */
        protected function precheckDestExistence( array $predicates ) {
@@ -373,12 +378,15 @@ abstract class FileOp {
                                } else {
                                        $this->overwriteSameCase = true; // OK
                                }
+
                                return $status; // do nothing; either OK or bad status
                        } else {
                                $status->fatal( 'backend-fail-alreadyexists', $this->params['dst'] );
+
                                return $status;
                        }
                }
+
                return $status;
        }
 
@@ -396,7 +404,7 @@ abstract class FileOp {
         * Check if a file will exist in storage when this operation is attempted
         *
         * @param string $source Storage path
-        * @param Array $predicates
+        * @param array $predicates
         * @return bool
         */
        final protected function fileExists( $source, array $predicates ) {
@@ -404,6 +412,7 @@ abstract class FileOp {
                        return $predicates['exists'][$source]; // previous op assures this
                } else {
                        $params = array( 'src' => $source, 'latest' => true );
+
                        return $this->backend->fileExists( $params );
                }
        }
@@ -412,7 +421,7 @@ abstract class FileOp {
         * Get the SHA-1 of a file in storage when this operation is attempted
         *
         * @param string $source Storage path
-        * @param Array $predicates
+        * @param array $predicates
         * @return string|bool False on failure
         */
        final protected function fileSha1( $source, array $predicates ) {
@@ -422,6 +431,7 @@ abstract class FileOp {
                        return false; // previous op assures this
                } else {
                        $params = array( 'src' => $source, 'latest' => true );
+
                        return $this->backend->getFileSha1Base36( $params );
                }
        }
@@ -439,7 +449,6 @@ abstract class FileOp {
         * Log a file operation failure and preserve any temp files
         *
         * @param string $action
-        * @return void
         */
        final public function logFailure( $action ) {
                $params = $this->params;
@@ -459,8 +468,11 @@ abstract class FileOp {
  */
 class CreateFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'content', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'headers' ) );
+               return array(
+                       array( 'content', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'headers' ),
+                       array( 'dst' )
+               );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -470,11 +482,13 @@ class CreateFileOp extends FileOp {
                        $status->fatal( 'backend-fail-maxsize',
                                $this->params['dst'], $this->backend->maxFileSizeInternal() );
                        $status->fatal( 'backend-fail-create', $this->params['dst'] );
+
                        return $status;
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-create', $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -485,6 +499,7 @@ class CreateFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -493,6 +508,7 @@ class CreateFileOp extends FileOp {
                        // Create the file at the destination
                        return $this->backend->createInternal( $this->setFlags( $this->params ) );
                }
+
                return Status::newGood();
        }
 
@@ -511,8 +527,11 @@ class CreateFileOp extends FileOp {
  */
 class StoreFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'headers' ) );
+               return array(
+                       array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'headers' ),
+                       array( 'src', 'dst' )
+               );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -520,17 +539,20 @@ class StoreFileOp extends FileOp {
                // Check if the source file exists on the file system
                if ( !is_file( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                        return $status;
                // Check if the source file is too big
                } elseif ( filesize( $this->params['src'] ) > $this->backend->maxFileSizeInternal() ) {
                        $status->fatal( 'backend-fail-maxsize',
                                $this->params['dst'], $this->backend->maxFileSizeInternal() );
                        $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -541,6 +563,7 @@ class StoreFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -549,6 +572,7 @@ class StoreFileOp extends FileOp {
                        // Store the file at the destination
                        return $this->backend->storeInternal( $this->setFlags( $this->params ) );
                }
+
                return Status::newGood();
        }
 
@@ -559,6 +583,7 @@ class StoreFileOp extends FileOp {
                if ( $hash !== false ) {
                        $hash = wfBaseConvert( $hash, 16, 36, 31 );
                }
+
                return $hash;
        }
 
@@ -573,8 +598,11 @@ class StoreFileOp extends FileOp {
  */
 class CopyFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ) );
+               return array(
+                       array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ),
+                       array( 'src', 'dst' )
+               );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -586,15 +614,18 @@ class CopyFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
-               // Check if a file can be placed/changed at the destination
+                       // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-copy', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -605,6 +636,7 @@ class CopyFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -613,7 +645,7 @@ class CopyFileOp extends FileOp {
                        $status = Status::newGood(); // nothing to do
                } elseif ( $this->params['src'] === $this->params['dst'] ) {
                        // Just update the destination file headers
-                       $headers = $this->getParam( 'headers' ) ?: array();
+                       $headers = $this->getParam( 'headers' ) ? : array();
                        $status = $this->backend->describeInternal( $this->setFlags( array(
                                'src' => $this->params['dst'], 'headers' => $headers
                        ) ) );
@@ -621,6 +653,7 @@ class CopyFileOp extends FileOp {
                        // Copy the file to the destination
                        $status = $this->backend->copyInternal( $this->setFlags( $this->params ) );
                }
+
                return $status;
        }
 
@@ -639,8 +672,11 @@ class CopyFileOp extends FileOp {
  */
 class MoveFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ) );
+               return array(
+                       array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'headers' ),
+                       array( 'src', 'dst' )
+               );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -652,15 +688,18 @@ class MoveFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-move', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -673,6 +712,7 @@ class MoveFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -697,6 +737,7 @@ class MoveFileOp extends FileOp {
                        // Move the file to the destination
                        $status = $this->backend->moveInternal( $this->setFlags( $this->params ) );
                }
+
                return $status;
        }
 
@@ -715,7 +756,7 @@ class MoveFileOp extends FileOp {
  */
 class DeleteFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'src' ), array( 'ignoreMissingSource' ) );
+               return array( array( 'src' ), array( 'ignoreMissingSource' ), array( 'src' ) );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -727,20 +768,24 @@ class DeleteFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
                // Check if a file can be placed/changed at the source
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['src'] );
                        $status->fatal( 'backend-fail-delete', $this->params['src'] );
+
                        return $status;
                }
                // Update file existence predicates
                $predicates['exists'][$this->params['src']] = false;
                $predicates['sha1'][$this->params['src']] = false;
+
                return $status; // safe to call attempt()
        }
 
@@ -760,7 +805,7 @@ class DeleteFileOp extends FileOp {
  */
 class DescribeFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'src' ), array( 'headers' ) );
+               return array( array( 'src' ), array( 'headers' ), array( 'src' ) );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -768,11 +813,13 @@ class DescribeFileOp extends FileOp {
                // Check if the source file exists
                if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
                        $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                        return $status;
                // Check if a file can be placed/changed at the source
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['src'] );
                        $status->fatal( 'backend-fail-describe', $this->params['src'] );
+
                        return $status;
                }
                // Update file existence predicates
@@ -780,6 +827,7 @@ class DescribeFileOp extends FileOp {
                        $this->fileExists( $this->params['src'], $predicates );
                $predicates['sha1'][$this->params['src']] =
                        $this->fileSha1( $this->params['src'], $predicates );
+
                return $status; // safe to call attempt()
        }
 
@@ -796,4 +844,5 @@ class DescribeFileOp extends FileOp {
 /**
  * Placeholder operation that has no params and does nothing
  */
-class NullFileOp extends FileOp {}
+class NullFileOp extends FileOp {
+}
index 785c0bc..32b65ba 100644 (file)
@@ -62,6 +62,7 @@ class FileOpBatch {
                if ( $n > self::MAX_BATCH_SIZE ) {
                        $status->fatal( 'backend-fail-batchsize', $n, self::MAX_BATCH_SIZE );
                        wfProfileOut( __METHOD__ );
+
                        return $status;
                }
 
@@ -108,6 +109,7 @@ class FileOpBatch {
                                ++$status->failCount;
                                if ( !$ignoreErrors ) {
                                        wfProfileOut( __METHOD__ );
+
                                        return $status; // abort
                                }
                        }
@@ -122,6 +124,7 @@ class FileOpBatch {
                        $subStatus = $journal->logChangeBatch( $entries, $batchId );
                        if ( !$subStatus->isOK() ) {
                                wfProfileOut( __METHOD__ );
+
                                return $subStatus; // abort
                        }
                }
@@ -134,6 +137,7 @@ class FileOpBatch {
                self::runParallelBatches( $pPerformOps, $status );
 
                wfProfileOut( __METHOD__ );
+
                return $status;
        }
 
@@ -145,7 +149,7 @@ class FileOpBatch {
         * within any given sub-batch do not depend on each other.
         * This will abort remaining ops on failure.
         *
-        * @param Array $pPerformOps
+        * @param array $pPerformOps
         * @param Status $status
         * @return bool Success
         */
@@ -199,6 +203,7 @@ class FileOpBatch {
                                }
                        }
                }
+
                return $status;
        }
 }
index db090a9..dc2995f 100644 (file)
  * @since 1.19
  */
 class SwiftFileBackend extends FileBackendStore {
-       /** @var CF_Authentication */
-       protected $auth; // Swift authentication handler
-       protected $authTTL; // integer seconds
-       protected $swiftTempUrlKey; // string; shared secret value for making temp urls
-       protected $swiftAnonUser; // string; username to handle unauthenticated requests
-       protected $swiftUseCDN; // boolean; whether CloudFiles CDN is enabled
-       protected $swiftCDNExpiry; // integer; how long to cache things in the CDN
-       protected $swiftCDNPurgable; // boolean; whether object CDN purging is enabled
+       /** @var CF_Authentication Swift authentication handler */
+       protected $auth;
+
+       /** @var int TTL in seconds */
+       protected $authTTL;
+
+       /** @var string Shared secret value for making temp URLs */
+       protected $swiftTempUrlKey;
+
+       /** @var string Username to handle unauthenticated requests */
+       protected $swiftAnonUser;
+
+       /** @var bool Whether CloudFiles CDN is enabled */
+       protected $swiftUseCDN;
+
+       /** @var int How long to cache things in the CDN */
+       protected $swiftCDNExpiry;
+
+       /** @var bool Whether object CDN purging is enabled */
+       protected $swiftCDNPurgable;
 
        // Rados Gateway specific options
-       protected $rgwS3AccessKey; // string; S3 access key
-       protected $rgwS3SecretKey; // string; S3 authentication key
+       /** @var string S3 access key */
+       protected $rgwS3AccessKey;
+
+       /** @var string S3 authentication key */
+       protected $rgwS3SecretKey;
 
-       /** @var CF_Connection */
-       protected $conn; // Swift connection handle
-       protected $sessionStarted = 0; // integer UNIX timestamp
+       /** @var CF_Connection Swift connection handle*/
+       protected $conn;
+
+       /** @var int UNIX timestamp */
+       protected $sessionStarted = 0;
 
        /** @var CloudFilesException */
        protected $connException;
-       protected $connErrorTime = 0; // UNIX timestamp
+
+       /** @var int UNIX timestamp */
+       protected $connErrorTime = 0;
 
        /** @var BagOStuff */
        protected $srvCache;
@@ -153,7 +172,8 @@ class SwiftFileBackend extends FileBackendStore {
                        } else {
                                try { // look for APC, XCache, WinCache, ect...
                                        $this->srvCache = ObjectCache::newAccelerator( array() );
-                               } catch ( Exception $e ) {}
+                               } catch ( Exception $e ) {
+                               }
                        }
                }
                $this->srvCache = $this->srvCache ? $this->srvCache : new EmptyBagOStuff();
@@ -161,7 +181,10 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::resolveContainerPath()
-        * @return null
+        * @param string $container
+        * @param string $relStoragePath
+        * @return string|null Returns null when the URL encoded storage path is
+        *   longer than 1024 characters or not UTF-8 encoded.
         */
        protected function resolveContainerPath( $container, $relStoragePath ) {
                if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) { // mb_string required by CF
@@ -169,6 +192,7 @@ class SwiftFileBackend extends FileBackendStore {
                } elseif ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
                        return null; // too long for Swift
                }
+
                return $relStoragePath;
        }
 
@@ -180,6 +204,7 @@ class SwiftFileBackend extends FileBackendStore {
 
                try {
                        $this->getContainer( $container );
+
                        return true; // container exists
                } catch ( NoSuchContainerException $e ) {
                } catch ( CloudFilesException $e ) { // some other exception?
@@ -198,6 +223,7 @@ class SwiftFileBackend extends FileBackendStore {
                if ( isset( $headers['Content-Disposition'] ) ) {
                        $headers['Content-Disposition'] = $this->truncDisp( $headers['Content-Disposition'] );
                }
+
                return $headers;
        }
 
@@ -216,6 +242,7 @@ class SwiftFileBackend extends FileBackendStore {
                                break; // too long; sigh
                        }
                }
+
                return $res;
        }
 
@@ -225,6 +252,7 @@ class SwiftFileBackend extends FileBackendStore {
                list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
                if ( $dstRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -233,9 +261,11 @@ class SwiftFileBackend extends FileBackendStore {
                        $dContObj = $this->getContainer( $dstCont );
                } catch ( NoSuchContainerException $e ) {
                        $status->fatal( 'backend-fail-create', $params['dst'] );
+
                        return $status;
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -279,7 +309,7 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * @see SwiftFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseCreate( CF_Async_Op $cfOp, Status $status, array $params ) {
+       protected function getResponseCreate( CF_Async_Op $cfOp, Status $status, array $params ) {
                try {
                        $cfOp->getLastResponse();
                } catch ( BadContentTypeException $e ) {
@@ -293,6 +323,7 @@ class SwiftFileBackend extends FileBackendStore {
                list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
                if ( $dstRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -301,9 +332,11 @@ class SwiftFileBackend extends FileBackendStore {
                        $dContObj = $this->getContainer( $dstCont );
                } catch ( NoSuchContainerException $e ) {
                        $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+
                        return $status;
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -313,6 +346,7 @@ class SwiftFileBackend extends FileBackendStore {
                wfRestoreWarnings();
                if ( $sha1Hash === false ) { // source doesn't exist?
                        $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
+
                        return $status;
                }
                $sha1Hash = wfBaseConvert( $sha1Hash, 16, 36, 31 );
@@ -363,7 +397,7 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * @see SwiftFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseStore( CF_Async_Op $cfOp, Status $status, array $params ) {
+       protected function getResponseStore( CF_Async_Op $cfOp, Status $status, array $params ) {
                try {
                        $cfOp->getLastResponse();
                } catch ( BadContentTypeException $e ) {
@@ -379,12 +413,14 @@ class SwiftFileBackend extends FileBackendStore {
                list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                if ( $srcRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
                list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
                if ( $dstRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -396,9 +432,11 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( empty( $params['ignoreMissingSource'] ) || isset( $sContObj ) ) {
                                $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
                        }
+
                        return $status;
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -434,7 +472,7 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * @see SwiftFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseCopy( CF_Async_Op $cfOp, Status $status, array $params ) {
+       protected function getResponseCopy( CF_Async_Op $cfOp, Status $status, array $params ) {
                try {
                        $cfOp->getLastResponse();
                } catch ( NoSuchObjectException $e ) { // source object does not exist
@@ -448,12 +486,14 @@ class SwiftFileBackend extends FileBackendStore {
                list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                if ( $srcRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
                list( $dstCont, $dstRel ) = $this->resolveStoragePathReal( $params['dst'] );
                if ( $dstRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
+
                        return $status;
                }
 
@@ -465,9 +505,11 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( empty( $params['ignoreMissingSource'] ) || isset( $sContObj ) ) {
                                $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] );
                        }
+
                        return $status;
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -506,7 +548,7 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * @see SwiftFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseMove( CF_Async_Op $cfOp, Status $status, array $params ) {
+       protected function getResponseMove( CF_Async_Op $cfOp, Status $status, array $params ) {
                try {
                        $cfOp->getLastResponse();
                } catch ( NoSuchObjectException $e ) { // source object does not exist
@@ -520,6 +562,7 @@ class SwiftFileBackend extends FileBackendStore {
                list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                if ( $srcRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
@@ -554,7 +597,7 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * @see SwiftFileBackend::doExecuteOpHandlesInternal()
         */
-       protected function _getResponseDelete( CF_Async_Op $cfOp, Status $status, array $params ) {
+       protected function getResponseDelete( CF_Async_Op $cfOp, Status $status, array $params ) {
                try {
                        $cfOp->getLastResponse();
                } catch ( NoSuchContainerException $e ) {
@@ -572,6 +615,7 @@ class SwiftFileBackend extends FileBackendStore {
                list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                if ( $srcRel === null ) {
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+
                        return $status;
                }
 
@@ -605,12 +649,14 @@ class SwiftFileBackend extends FileBackendStore {
                // (a) Check if container already exists
                try {
                        $this->getContainer( $fullCont );
+
                        // NoSuchContainerException not thrown: container must exist
                        return $status; // already exists
                } catch ( NoSuchContainerException $e ) {
                        // NoSuchContainerException thrown: container does not exist
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -631,6 +677,7 @@ class SwiftFileBackend extends FileBackendStore {
                        // CDN not enabled; nothing to see here
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -639,6 +686,9 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::doSecureInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doSecureInternal( $fullCont, $dir, array $params ) {
@@ -674,6 +724,9 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::doPublishInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
         * @return Status
         */
        protected function doPublishInternal( $fullCont, $dir, array $params ) {
@@ -727,6 +780,7 @@ class SwiftFileBackend extends FileBackendStore {
                        return $status; // ok, nothing to do
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -740,6 +794,7 @@ class SwiftFileBackend extends FileBackendStore {
                                return $status; // race? consistency delay?
                        } catch ( CloudFilesException $e ) { // some other exception?
                                $this->handleException( $e, $status, __METHOD__, $params );
+
                                return $status;
                        }
                }
@@ -759,8 +814,8 @@ class SwiftFileBackend extends FileBackendStore {
                        $srcObj = $contObj->get_object( $srcRel, $this->headersFromParams( $params ) );
                        $this->addMissingMetadata( $srcObj, $params['src'] );
                        $stat = array(
-                               // Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT" to TS_MW
-                               'mtime' => wfTimestamp( TS_MW, $srcObj->last_modified ),
+                               // Convert various random Swift dates to TS_MW
+                               'mtime' => $this->convertSwiftDate( $srcObj->last_modified, TS_MW ),
                                'size' => (int)$srcObj->content_length,
                                'sha1' => $srcObj->getMetadataValue( 'Sha1base36' )
                        );
@@ -774,6 +829,22 @@ class SwiftFileBackend extends FileBackendStore {
                return $stat;
        }
 
+       /**
+        * Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT"/"2013-05-11T07:37:27.678360Z".
+        * Dates might also come in like "2013-05-11T07:37:27.678360" from Swift listings,
+        * missing the timezone suffix (though Ceph RGW does not appear to have this bug).
+        *
+        * @param string $ts
+        * @param int $format Output format (TS_* constant)
+        * @return string
+        * @throws MWException
+        */
+       protected function convertSwiftDate( $ts, $format = TS_MW ) {
+               $timestamp = new MWTimestamp( $ts );
+
+               return $timestamp->getTimestamp( $format );
+       }
+
        /**
         * Fill in any missing object metadata and save it to Swift
         *
@@ -798,6 +869,7 @@ class SwiftFileBackend extends FileBackendStore {
                                        $obj->setMetadataValues( array( 'Sha1base36' => $hash ) );
                                        $obj->sync_metadata(); // save to Swift
                                        wfProfileOut( __METHOD__ );
+
                                        return true; // success
                                }
                        }
@@ -805,6 +877,7 @@ class SwiftFileBackend extends FileBackendStore {
                trigger_error( "Unable to set SHA-1 metadata for $path", E_USER_WARNING );
                $obj->setMetadataValues( array( 'Sha1base36' => false ) );
                wfProfileOut( __METHOD__ );
+
                return false; // failed
        }
 
@@ -878,12 +951,16 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::doDirectoryExists()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
         * @return bool|null
         */
        protected function doDirectoryExists( $fullCont, $dir, array $params ) {
                try {
                        $container = $this->getContainer( $fullCont );
                        $prefix = ( $dir == '' ) ? null : "{$dir}/";
+
                        return ( count( $container->list_objects( 1, null, $prefix ) ) > 0 );
                } catch ( NoSuchContainerException $e ) {
                        return false;
@@ -897,6 +974,9 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::getDirectoryListInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
         * @return SwiftFileBackendDirList
         */
        public function getDirectoryListInternal( $fullCont, $dir, array $params ) {
@@ -905,6 +985,9 @@ class SwiftFileBackend extends FileBackendStore {
 
        /**
         * @see FileBackendStore::getFileListInternal()
+        * @param string $fullCont
+        * @param string $dir
+        * @param array $params
         * @return SwiftFileBackendFileList
         */
        public function getFileListInternal( $fullCont, $dir, array $params ) {
@@ -916,10 +999,10 @@ class SwiftFileBackend extends FileBackendStore {
         *
         * @param string $fullCont Resolved container name
         * @param string $dir Resolved storage directory with no trailing slash
-        * @param string|null $after Storage path of file to list items after
-        * @param integer $limit Max number of items to list
+        * @param string|null $after Resolved container relative path to list items after
+        * @param int $limit Max number of items to list
         * @param array $params Parameters for getDirectoryList()
-        * @return Array List of resolved paths of directories directly under $dir
+        * @return array List of container relative resolved paths of directories directly under $dir
         * @throws FileBackendError
         */
        public function getDirListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
@@ -991,14 +1074,14 @@ class SwiftFileBackend extends FileBackendStore {
         *
         * @param string $fullCont Resolved container name
         * @param string $dir Resolved storage directory with no trailing slash
-        * @param string|null $after Storage path of file to list items after
-        * @param integer $limit Max number of items to list
+        * @param string|null $after Resolved container relative path of file to list items after
+        * @param int $limit Max number of items to list
         * @param array $params Parameters for getDirectoryList()
-        * @return Array List of resolved paths of files under $dir
+        * @return array List of resolved container relative paths of files under $dir
         * @throws FileBackendError
         */
        public function getFileListPageInternal( $fullCont, $dir, &$after, $limit, array $params ) {
-               $files = array();
+               $files = array(); // list of (path, stat array or null) entries
                if ( $after === INF ) {
                        return $files; // nothing more
                }
@@ -1007,38 +1090,34 @@ class SwiftFileBackend extends FileBackendStore {
                try {
                        $container = $this->getContainer( $fullCont );
                        $prefix = ( $dir == '' ) ? null : "{$dir}/";
+
+                       // $objects will contain a list of unfiltered names or CF_Object items
                        // Non-recursive: only list files right under $dir
-                       if ( !empty( $params['topOnly'] ) ) { // files and dirs
+                       if ( !empty( $params['topOnly'] ) ) {
                                if ( !empty( $params['adviseStat'] ) ) {
-                                       $limit = min( $limit, self::CACHE_CHEAP_SIZE );
                                        // Note: get_objects() does not include directories
-                                       $objects = $this->loadObjectListing( $params, $dir,
-                                               $container->get_objects( $limit, $after, $prefix, null, '/' ) );
-                                       $files = $objects;
+                                       $objects = $container->get_objects( $limit, $after, $prefix, null, '/' );
                                } else {
+                                       // Note: list_objects() includes directories here
                                        $objects = $container->list_objects( $limit, $after, $prefix, null, '/' );
-                                       foreach ( $objects as $object ) { // files and directories
-                                               if ( substr( $object, -1 ) !== '/' ) {
-                                                       $files[] = $object; // directories end in '/'
-                                               }
-                                       }
                                }
+                               $files = $this->buildFileObjectListing( $params, $dir, $objects );
                        // Recursive: list all files under $dir and its subdirs
-                       } else { // files
+                       } else {
+                               // Note: get_objects()/list_objects() here only return file objects
                                if ( !empty( $params['adviseStat'] ) ) {
-                                       $limit = min( $limit, self::CACHE_CHEAP_SIZE );
-                                       $objects = $this->loadObjectListing( $params, $dir,
-                                               $container->get_objects( $limit, $after, $prefix ) );
+                                       $objects = $container->get_objects( $limit, $after, $prefix );
                                } else {
                                        $objects = $container->list_objects( $limit, $after, $prefix );
                                }
-                               $files = $objects;
+                               $files = $this->buildFileObjectListing( $params, $dir, $objects );
                        }
                        // Page on the unfiltered object listing (what is returned may be filtered)
                        if ( count( $objects ) < $limit ) {
                                $after = INF; // avoid a second RTT
                        } else {
                                $after = end( $objects ); // update last item
+                               $after = is_object( $after ) ? $after->name : $after;
                        }
                } catch ( NoSuchContainerException $e ) {
                } catch ( CloudFilesException $e ) { // some other exception?
@@ -1051,34 +1130,42 @@ class SwiftFileBackend extends FileBackendStore {
        }
 
        /**
-        * Load a list of objects that belong under $dir into stat cache
-        * and return a list of the names of the objects in the same order.
+        * Build a list of file objects, filtering out any directories
+        * and extracting any stat info if provided in $objects (for CF_Objects)
         *
         * @param array $params Parameters for getDirectoryList()
         * @param string $dir Resolved container directory path
-        * @param array $cfObjects List of CF_Object items
-        * @return array List of object names
+        * @param array $objects List of CF_Object items or object names
+        * @return array List of (names,stat array or null) entries
         */
-       private function loadObjectListing( array $params, $dir, array $cfObjects ) {
+       private function buildFileObjectListing( array $params, $dir, array $objects ) {
                $names = array();
-               $storageDir = rtrim( $params['dir'], '/' );
-               $suffixStart = ( $dir === '' ) ? 0 : strlen( $dir ) + 1; // size of "path/to/dir/"
-               // Iterate over the list *backwards* as this primes the stat cache, which is LRU.
-               // If this fills the cache and the caller stats an uncached file before stating
-               // the ones on the listing, there would be zero cache hits if this went forwards.
-               for ( end( $cfObjects ); key( $cfObjects ) !== null; prev( $cfObjects ) ) {
-                       $object = current( $cfObjects );
-                       $path = "{$storageDir}/" . substr( $object->name, $suffixStart );
-                       $val = array(
-                               // Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT" to TS_MW
-                               'mtime'  => wfTimestamp( TS_MW, $object->last_modified ),
-                               'size'   => (int)$object->content_length,
-                               'latest' => false // eventually consistent
-                       );
-                       $this->cheapCache->set( $path, 'stat', $val );
-                       $names[] = $object->name;
+               foreach ( $objects as $object ) {
+                       if ( is_object( $object ) ) {
+                               $stat = array(
+                                       // Convert various random Swift dates to TS_MW
+                                       'mtime' => $this->convertSwiftDate( $object->last_modified, TS_MW ),
+                                       'size' => (int)$object->content_length,
+                                       'latest' => false // eventually consistent
+                               );
+                               $names[] = array( $object->name, $stat );
+                       } elseif ( substr( $object, -1 ) !== '/' ) {
+                               // Omit directories, which end in '/' in listings
+                               $names[] = array( $object, null );
+                       }
                }
-               return array_reverse( $names ); // keep the paths in original order
+
+               return $names;
+       }
+
+       /**
+        * Do not call this function outside of SwiftFileBackendFileList
+        *
+        * @param string $path Storage path
+        * @param array $val Stat value
+        */
+       public function loadListingStatInternal( $path, array $val ) {
+               $this->cheapCache->set( $path, 'stat', $val );
        }
 
        protected function doGetFileSha1base36( array $params ) {
@@ -1089,6 +1176,7 @@ class SwiftFileBackend extends FileBackendStore {
                                $this->clearCache( array( $params['src'] ) );
                                $stat = $this->getFileStat( $params );
                        }
+
                        return $stat['sha1'];
                } else {
                        return false;
@@ -1107,9 +1195,11 @@ class SwiftFileBackend extends FileBackendStore {
                        $cont = $this->getContainer( $srcCont );
                } catch ( NoSuchContainerException $e ) {
                        $status->fatal( 'backend-fail-stream', $params['src'] );
+
                        return $status;
                } catch ( CloudFilesException $e ) { // some other exception?
                        $this->handleException( $e, $status, __METHOD__, $params );
+
                        return $status;
                }
 
@@ -1197,8 +1287,8 @@ class SwiftFileBackend extends FileBackendStore {
 
        public function getFileHttpUrl( array $params ) {
                if ( $this->swiftTempUrlKey != '' ||
-                       ( $this->rgwS3AccessKey != '' && $this->rgwS3SecretKey != '' ) )
-               {
+                       ( $this->rgwS3AccessKey != '' && $this->rgwS3SecretKey != '' )
+               {
                        list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                        if ( $srcRel === null ) {
                                return null; // invalid path
@@ -1221,6 +1311,7 @@ class SwiftFileBackend extends FileBackendStore {
                                                $this->rgwS3SecretKey,
                                                true // raw
                                        ) );
+
                                        // See http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html.
                                        // Note: adding a newline for empty CanonicalizedAmzHeaders does not work.
                                        return wfAppendQuery(
@@ -1237,6 +1328,7 @@ class SwiftFileBackend extends FileBackendStore {
                                $this->handleException( $e, null, __METHOD__, $params );
                        }
                }
+
                return null;
        }
 
@@ -1250,13 +1342,14 @@ class SwiftFileBackend extends FileBackendStore {
         * $params is currently only checked for a 'latest' flag.
         *
         * @param array $params
-        * @return Array
+        * @return array
         */
        protected function headersFromParams( array $params ) {
                $hdrs = array();
                if ( !empty( $params['latest'] ) ) {
                        $hdrs[] = 'X-Newest: true';
                }
+
                return $hdrs;
        }
 
@@ -1272,7 +1365,7 @@ class SwiftFileBackend extends FileBackendStore {
                $cfOps = $batch->execute();
                foreach ( $cfOps as $index => $cfOp ) {
                        $status = Status::newGood();
-                       $function = '_getResponse' . $fileOpHandles[$index]->call;
+                       $function = 'getResponse' . $fileOpHandles[$index]->call;
                        try { // catch exceptions; update status
                                $this->$function( $cfOp, $status, $fileOpHandles[$index]->params );
                                $this->purgeCDNCache( $fileOpHandles[$index]->affectedObjects );
@@ -1289,7 +1382,13 @@ class SwiftFileBackend extends FileBackendStore {
        /**
         * Set read/write permissions for a Swift container.
         *
-        * $readGrps is a list of the possible criteria for a request to have
+        * @see http://swift.openstack.org/misc.html#acls
+        *
+        * In general, we don't allow listings to end-users. It's not useful, isn't well-defined
+        * (lists are truncated to 10000 item with no way to page), and is just a performance risk.
+        *
+        * @param CF_Container $contObj Swift container
+        * @param array $readGrps List of the possible criteria for a request to have
         * access to read a container. Each item is one of the following formats:
         *   - account:user        : Grants access if the request is by the given user
         *   - ".r:<regex>"        : Grants access if the request is from a referrer host that
@@ -1297,19 +1396,9 @@ class SwiftFileBackend extends FileBackendStore {
         *                           Setting this to '*' effectively makes a container public.
         *   -".rlistings:<regex>" : Grants access if the request is from a referrer host that
         *                           matches the expression and the request is for a listing.
-        *
-        * $writeGrps is a list of the possible criteria for a request to have
+        * @param array $writeGrps A list of the possible criteria for a request to have
         * access to write to a container. Each item is of the following format:
         *   - account:user       : Grants access if the request is by the given user
-        *
-        * @see http://swift.openstack.org/misc.html#acls
-        *
-        * In general, we don't allow listings to end-users. It's not useful, isn't well-defined
-        * (lists are truncated to 10000 item with no way to page), and is just a performance risk.
-        *
-        * @param CF_Container $contObj Swift container
-        * @param array $readGrps List of read access routes
-        * @param array $writeGrps List of write access routes
         * @return Status
         */
        protected function setContainerAccess(
@@ -1333,7 +1422,6 @@ class SwiftFileBackend extends FileBackendStore {
         * This is for Rackspace/Akamai CDNs.
         *
         * @param array $objects List of CF_Object items
-        * @return void
         */
        public function purgeCDNCache( array $objects ) {
                if ( $this->swiftUseCDN && $this->swiftCDNPurgable ) {
@@ -1395,13 +1483,12 @@ class SwiftFileBackend extends FileBackendStore {
                        }
                        $this->conn = new CF_Connection( $this->auth );
                }
+
                return $this->conn;
        }
 
        /**
         * Close the connection to the Swift proxy
-        *
-        * @return void
         */
        protected function closeConnection() {
                if ( $this->conn ) {
@@ -1448,6 +1535,7 @@ class SwiftFileBackend extends FileBackendStore {
                                );
                        }
                }
+
                return $this->connContainerCache->get( $container, 'obj' );
        }
 
@@ -1469,7 +1557,6 @@ class SwiftFileBackend extends FileBackendStore {
         * Delete a Swift container
         *
         * @param string $container Container name
-        * @return void
         * @throws CloudFilesException
         */
        protected function deleteContainer( $container ) {
@@ -1496,10 +1583,9 @@ class SwiftFileBackend extends FileBackendStore {
         * This also sets the Status object to have a fatal error.
         *
         * @param Exception $e
-        * @param Status $status|null
+        * @param Status $status null
         * @param string $func
         * @param array $params
-        * @return void
         */
        protected function handleException( Exception $e, $status, $func, array $params ) {
                if ( $status instanceof Status ) {
@@ -1529,7 +1615,8 @@ class SwiftFileBackend extends FileBackendStore {
 class SwiftFileOpHandle extends FileBackendStoreOpHandle {
        /** @var CF_Async_Op */
        public $cfOp;
-       /** @var Array */
+
+       /** @var array */
        public $affectedObjects = array();
 
        /**
@@ -1556,18 +1643,29 @@ class SwiftFileOpHandle extends FileBackendStoreOpHandle {
  * @ingroup FileBackend
  */
 abstract class SwiftFileBackendList implements Iterator {
-       /** @var Array */
+       /** @var array List of path or (path,stat array) entries */
        protected $bufferIter = array();
-       protected $bufferAfter = null; // string; list items *after* this path
-       protected $pos = 0; // integer
-       /** @var Array */
+
+       /** @var string List items *after* this path */
+       protected $bufferAfter = null;
+
+       /** @var int */
+       protected $pos = 0;
+
+       /** @var array */
        protected $params = array();
 
        /** @var SwiftFileBackend */
        protected $backend;
-       protected $container; // string; container name
-       protected $dir; // string; storage directory
-       protected $suffixStart; // integer
+
+       /** @var string Container name */
+       protected $container;
+
+       /** @var string Storage directory */
+       protected $dir;
+
+       /** @var int */
+       protected $suffixStart;
 
        const PAGE_SIZE = 9000; // file listing buffer size
 
@@ -1594,7 +1692,7 @@ abstract class SwiftFileBackendList implements Iterator {
 
        /**
         * @see Iterator::key()
-        * @return integer
+        * @return int
         */
        public function key() {
                return $this->pos;
@@ -1602,7 +1700,6 @@ abstract class SwiftFileBackendList implements Iterator {
 
        /**
         * @see Iterator::next()
-        * @return void
         */
        public function next() {
                // Advance to the next file in the page
@@ -1619,7 +1716,6 @@ abstract class SwiftFileBackendList implements Iterator {
 
        /**
         * @see Iterator::rewind()
-        * @return void
         */
        public function rewind() {
                $this->pos = 0;
@@ -1646,10 +1742,10 @@ abstract class SwiftFileBackendList implements Iterator {
         *
         * @param string $container Resolved container name
         * @param string $dir Resolved path relative to container
-        * @param string $after|null
-        * @param integer $limit
+        * @param string $after null
+        * @param int $limit
         * @param array $params
-        * @return Traversable|Array
+        * @return Traversable|array
         */
        abstract protected function pageFromList( $container, $dir, &$after, $limit, array $params );
 }
@@ -1668,7 +1764,12 @@ class SwiftFileBackendDirList extends SwiftFileBackendList {
 
        /**
         * @see SwiftFileBackendList::pageFromList()
-        * @return Array
+        * @param string $container
+        * @param string $dir
+        * @param string $after
+        * @param int $limit
+        * @param array $params
+        * @return array
         */
        protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
                return $this->backend->getDirListPageInternal( $container, $dir, $after, $limit, $params );
@@ -1684,12 +1785,24 @@ class SwiftFileBackendFileList extends SwiftFileBackendList {
         * @return string|bool String (relative path) or false
         */
        public function current() {
-               return substr( current( $this->bufferIter ), $this->suffixStart );
+               list( $path, $stat ) = current( $this->bufferIter );
+               $relPath = substr( $path, $this->suffixStart );
+               if ( is_array( $stat ) ) {
+                       $storageDir = rtrim( $this->params['dir'], '/' );
+                       $this->backend->loadListingStatInternal( "$storageDir/$relPath", $stat );
+               }
+
+               return $relPath;
        }
 
        /**
         * @see SwiftFileBackendList::pageFromList()
-        * @return Array
+        * @param string $container
+        * @param string $dir
+        * @param string $after
+        * @param int $limit
+        * @param array $params
+        * @return array
         */
        protected function pageFromList( $container, $dir, &$after, $limit, array $params ) {
                return $this->backend->getFileListPageInternal( $container, $dir, $after, $limit, $params );
index 8266e42..611fab9 100644 (file)
  * @ingroup FileBackend
  */
 class TempFSFile extends FSFile {
-       protected $canDelete = false; // bool; garbage collect the temp file
+       /** @var bool Garbage collect the temp file */
+       protected $canDelete = false;
 
-       /** @var Array of active temp files to purge on shutdown */
+       /** @var array Active temp files to purge on shutdown */
        protected static $instances = array();
 
        /**
@@ -56,12 +57,14 @@ class TempFSFile extends FSFile {
                        }
                        if ( $attempt >= 5 ) {
                                wfProfileOut( __METHOD__ );
+
                                return null; // give up
                        }
                }
                $tmpFile = new self( $path );
                $tmpFile->canDelete = true; // safely instantiated
                wfProfileOut( __METHOD__ );
+
                return $tmpFile;
        }
 
@@ -75,13 +78,14 @@ class TempFSFile extends FSFile {
                wfSuppressWarnings();
                $ok = unlink( $this->path );
                wfRestoreWarnings();
+
                return $ok;
        }
 
        /**
         * Clean up the temporary file only after an object goes out of scope
         *
-        * @param Object $object
+        * @param stdClass $object
         * @return TempFSFile This object
         */
        public function bind( $object ) {
@@ -92,6 +96,7 @@ class TempFSFile extends FSFile {
                        }
                        $object->tempFSFileReferences[] = $this;
                }
+
                return $this;
        }
 
@@ -102,6 +107,7 @@ class TempFSFile extends FSFile {
         */
        public function preserve() {
                $this->canDelete = false;
+
                return $this;
        }
 
@@ -112,6 +118,7 @@ class TempFSFile extends FSFile {
         */
        public function autocollect() {
                $this->canDelete = true;
+
                return $this;
        }
 
index 9250aa5..4f64f02 100644 (file)
@@ -34,10 +34,9 @@ class DBFileJournal extends FileJournal {
 
        /**
         * Construct a new instance from configuration.
-        * $config includes:
-        *     'wiki' : wiki name to use for LoadBalancer
         *
-        * @param $config Array
+        * @param array $config Includes:
+        *     'wiki' : wiki name to use for LoadBalancer
         */
        protected function __construct( array $config ) {
                parent::__construct( $config );
@@ -47,6 +46,8 @@ class DBFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::logChangeBatch()
+        * @param array $entries
+        * @param string $batchId
         * @return Status
         */
        protected function doLogChangeBatch( array $entries, $batchId ) {
@@ -56,6 +57,7 @@ class DBFileJournal extends FileJournal {
                        $dbw = $this->getMasterDB();
                } catch ( DBError $e ) {
                        $status->fatal( 'filejournal-fail-dbconnect', $this->backend );
+
                        return $status;
                }
 
@@ -80,6 +82,7 @@ class DBFileJournal extends FileJournal {
                        }
                } catch ( DBError $e ) {
                        $status->fatal( 'filejournal-fail-dbquery', $this->backend );
+
                        return $status;
                }
 
@@ -88,7 +91,7 @@ class DBFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetCurrentPosition()
-        * @return integer|false
+        * @return bool|mixed The value from the field, or false on failure.
         */
        protected function doGetCurrentPosition() {
                $dbw = $this->getMasterDB();
@@ -101,13 +104,14 @@ class DBFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetPositionAtTime()
-        * @param $time integer|string timestamp
-        * @return integer|false
+        * @param int|string $time Timestamp
+        * @return bool|mixed The value from the field, or false on failure.
         */
        protected function doGetPositionAtTime( $time ) {
                $dbw = $this->getMasterDB();
 
                $encTimestamp = $dbw->addQuotes( $dbw->timestamp( $time ) );
+
                return $dbw->selectField( 'filejournal', 'fj_id',
                        array( 'fj_backend' => $this->backend, "fj_timestamp <= $encTimestamp" ),
                        __METHOD__,
@@ -117,8 +121,9 @@ class DBFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetChangeEntries()
-        * @return Array
-        * @throws DBError
+        * @param int $start
+        * @param int $limit
+        * @return array
         */
        protected function doGetChangeEntries( $start, $limit ) {
                $dbw = $this->getMasterDB();
@@ -179,6 +184,7 @@ class DBFileJournal extends FileJournal {
                        $this->dbw = $lb->getConnection( DB_MASTER, array(), $this->wiki );
                        $this->dbw->clearFlag( DBO_TRX );
                }
+
                return $this->dbw;
        }
 }
index a1b7a45..3ab9f5d 100644 (file)
  * @since 1.20
  */
 abstract class FileJournal {
-       protected $backend; // string
-       protected $ttlDays; // integer
+       /** @var  string */
+       protected $backend;
+
+       /** @var int */
+       protected $ttlDays;
 
        /**
         * Construct a new instance from configuration.
-        * $config includes:
-        *     'ttlDays' : days to keep log entries around (false means "forever")
         *
-        * @param $config Array
+        * @param array $config Includes:
+        *     'ttlDays' : days to keep log entries around (false means "forever")
         */
        protected function __construct( array $config ) {
                $this->ttlDays = isset( $config['ttlDays'] ) ? $config['ttlDays'] : false;
@@ -53,7 +55,7 @@ abstract class FileJournal {
        /**
         * Create an appropriate FileJournal object from config
         *
-        * @param $config Array
+        * @param array $config
         * @param string $backend A registered file backend name
         * @throws MWException
         * @return FileJournal
@@ -65,6 +67,7 @@ abstract class FileJournal {
                        throw new MWException( "Class given is not an instance of FileJournal." );
                }
                $jrn->backend = $backend;
+
                return $jrn;
        }
 
@@ -79,18 +82,18 @@ abstract class FileJournal {
                        $s .= mt_rand( 0, 2147483647 );
                }
                $s = wfBaseConvert( sha1( $s ), 16, 36, 31 );
+
                return substr( wfBaseConvert( wfTimestamp( TS_MW ), 10, 36, 9 ) . $s, 0, 31 );
        }
 
        /**
         * Log changes made by a batch file operation.
-        * $entries is an array of log entries, each of which contains:
+        *
+        * @param array $entries List of file operations (each an array of parameters) which contain:
         *     op      : Basic operation name (create, update, delete)
         *     path    : The storage path of the file
         *     newSha1 : The final base 36 SHA-1 of the file
-        * Note that 'false' should be used as the SHA-1 for non-existing files.
-        *
-        * @param array $entries List of file operations (each an array of parameters)
+        *   Note that 'false' should be used as the SHA-1 for non-existing files.
         * @param string $batchId UUID string that identifies the operation batch
         * @return Status
         */
@@ -98,6 +101,7 @@ abstract class FileJournal {
                if ( !count( $entries ) ) {
                        return Status::newGood();
                }
+
                return $this->doLogChangeBatch( $entries, $batchId );
        }
 
@@ -113,7 +117,7 @@ abstract class FileJournal {
        /**
         * Get the position ID of the latest journal entry
         *
-        * @return integer|false
+        * @return int|bool
         */
        final public function getCurrentPosition() {
                return $this->doGetCurrentPosition();
@@ -121,15 +125,15 @@ abstract class FileJournal {
 
        /**
         * @see FileJournal::getCurrentPosition()
-        * @return integer|false
+        * @return int|bool
         */
        abstract protected function doGetCurrentPosition();
 
        /**
         * Get the position ID of the latest journal entry at some point in time
         *
-        * @param $time integer|string timestamp
-        * @return integer|false
+        * @param int|string $time timestamp
+        * @return int|bool
         */
        final public function getPositionAtTime( $time ) {
                return $this->doGetPositionAtTime( $time );
@@ -137,8 +141,8 @@ abstract class FileJournal {
 
        /**
         * @see FileJournal::getPositionAtTime()
-        * @param $time integer|string timestamp
-        * @return integer|false
+        * @param int|string $time Timestamp
+        * @return int|bool
         */
        abstract protected function doGetPositionAtTime( $time );
 
@@ -146,7 +150,10 @@ abstract class FileJournal {
         * Get an array of file change log entries.
         * A starting change ID and/or limit can be specified.
         *
-        * The result as a list of associative arrays, each having:
+        * @param $start integer Starting change ID or null
+        * @param $limit integer Maximum number of items to return
+        * @param &$next string Updated to the ID of the next entry.
+        * @return array List of associative arrays, each having:
         *     id         : unique, monotonic, ID for this change
         *     batch_uuid : UUID for an operation batch
         *     backend    : the backend name
@@ -154,13 +161,7 @@ abstract class FileJournal {
         *     path       : affected storage path
         *     new_sha1   : base 36 sha1 of the new file had the operation succeeded
         *     timestamp  : TS_MW timestamp of the batch change
-
-        * Also, $next is updated to the ID of the next entry.
-        *
-        * @param $start integer Starting change ID or null
-        * @param $limit integer Maximum number of items to return
-        * @param &$next string
-        * @return Array
+        *   Also, $next is updated to the ID of the next entry.
         */
        final public function getChangeEntries( $start = null, $limit = 0, &$next = null ) {
                $entries = $this->doGetChangeEntries( $start, $limit ? $limit + 1 : 0 );
@@ -170,12 +171,15 @@ abstract class FileJournal {
                } else {
                        $next = null; // end of list
                }
+
                return $entries;
        }
 
        /**
         * @see FileJournal::getChangeEntries()
-        * @return Array
+        * @param int $start
+        * @param int $limit
+        * @return array
         */
        abstract protected function doGetChangeEntries( $start, $limit );
 
@@ -202,8 +206,8 @@ abstract class FileJournal {
 class NullFileJournal extends FileJournal {
        /**
         * @see FileJournal::doLogChangeBatch()
-        * @param $entries array
-        * @param $batchId string
+        * @param array $entries
+        * @param string $batchId
         * @return Status
         */
        protected function doLogChangeBatch( array $entries, $batchId ) {
@@ -212,7 +216,7 @@ class NullFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetCurrentPosition()
-        * @return integer|false
+        * @return int|bool
         */
        protected function doGetCurrentPosition() {
                return false;
@@ -220,8 +224,8 @@ class NullFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetPositionAtTime()
-        * @param $time integer|string timestamp
-        * @return integer|false
+        * @param int|string $time timestamp
+        * @return int|bool
         */
        protected function doGetPositionAtTime( $time ) {
                return false;
@@ -229,7 +233,9 @@ class NullFileJournal extends FileJournal {
 
        /**
         * @see FileJournal::doGetChangeEntries()
-        * @return Array
+        * @param int $start
+        * @param int $limit
+        * @return array
         */
        protected function doGetChangeEntries( $start, $limit ) {
                return array();
index 3e934ba..4418a83 100644 (file)
@@ -37,7 +37,7 @@
  * @since 1.19
  */
 abstract class DBLockManager extends QuorumLockManager {
-       /** @var Array Map of DB names to server config */
+       /** @var array Map of DB names to server config */
        protected $dbServers; // (DB name => server config array)
        /** @var BagOStuff */
        protected $statusCache;
@@ -46,13 +46,13 @@ abstract class DBLockManager extends QuorumLockManager {
        protected $safeDelay; // integer number of seconds
 
        protected $session = 0; // random integer
-       /** @var Array Map Database connections (DB name => Database) */
+       /** @var array Map Database connections (DB name => Database) */
        protected $conns = array();
 
        /**
         * Construct a new instance from configuration.
         *
-        * $config paramaters include:
+        * @param array $config Paramaters include:
         *   - dbServers   : Associative array of DB names to server configuration.
         *                   Configuration is an associative array that includes:
         *                     - host        : DB server name
@@ -70,8 +70,6 @@ abstract class DBLockManager extends QuorumLockManager {
         *   - lockExpiry  : Lock timeout (seconds) for dropped connections. [optional]
         *                   This tells the DB server how long to wait before assuming
         *                   connection failure and releasing all the locks for a session.
-        *
-        * @param array $config
         */
        public function __construct( array $config ) {
                parent::__construct( $config );
@@ -116,6 +114,7 @@ abstract class DBLockManager extends QuorumLockManager {
                foreach ( $pathsByType as $type => $paths ) {
                        $status->merge( $this->doGetLocksOnServer( $lockSrv, $paths, $type ) );
                }
+
                return $status;
        }
 
@@ -125,6 +124,7 @@ abstract class DBLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::isServerUp()
+        * @param string $lockSrv
         * @return bool
         */
        protected function isServerUp( $lockSrv ) {
@@ -135,15 +135,17 @@ abstract class DBLockManager extends QuorumLockManager {
                        $this->getConnection( $lockSrv );
                } catch ( DBError $e ) {
                        $this->cacheRecordFailure( $lockSrv );
+
                        return false; // failed to connect
                }
+
                return true;
        }
 
        /**
         * Get (or reuse) a connection to a lock DB
         *
-        * @param $lockDb string
+        * @param string $lockDb
         * @return DatabaseBase
         * @throws DBError
         */
@@ -175,18 +177,19 @@ abstract class DBLockManager extends QuorumLockManager {
                if ( !$this->conns[$lockDb]->trxLevel() ) {
                        $this->conns[$lockDb]->begin( __METHOD__ ); // start transaction
                }
+
                return $this->conns[$lockDb];
        }
 
        /**
         * Do additional initialization for new lock DB connection
         *
-        * @param $lockDb string
-        * @param $db DatabaseBase
-        * @return void
+        * @param string $lockDb
+        * @param DatabaseBase $db
         * @throws DBError
         */
-       protected function initConnection( $lockDb, DatabaseBase $db ) {}
+       protected function initConnection( $lockDb, DatabaseBase $db ) {
+       }
 
        /**
         * Checks if the DB has not recently had connection/query errors.
@@ -204,7 +207,7 @@ abstract class DBLockManager extends QuorumLockManager {
        /**
         * Log a lock request failure to the cache
         *
-        * @param $lockDb string
+        * @param string $lockDb
         * @return bool Success
         */
        protected function cacheRecordFailure( $lockDb ) {
@@ -216,7 +219,7 @@ abstract class DBLockManager extends QuorumLockManager {
        /**
         * Get a cache key for recent query misses for a DB
         *
-        * @param $lockDb string
+        * @param string $lockDb
         * @return string
         */
        protected function getMissKey( $lockDb ) {
@@ -242,7 +245,7 @@ abstract class DBLockManager extends QuorumLockManager {
  * @ingroup LockManager
  */
 class MySqlLockManager extends DBLockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
@@ -250,8 +253,8 @@ class MySqlLockManager extends DBLockManager {
        );
 
        /**
-        * @param $lockDb string
-        * @param $db DatabaseBase
+        * @param string $lockDb
+        * @param DatabaseBase $db
         */
        protected function initConnection( $lockDb, DatabaseBase $db ) {
                # Let this transaction see lock rows from other transactions
@@ -263,6 +266,9 @@ class MySqlLockManager extends DBLockManager {
         * This does not use GET_LOCK() per http://bugs.mysql.com/bug.php?id=1118.
         *
         * @see DBLockManager::getLocksOnServer()
+        * @param string $lockSrv
+        * @param array $paths
+        * @param string $type
         * @return Status
         */
        protected function doGetLocksOnServer( $lockSrv, array $paths, $type ) {
@@ -359,7 +365,7 @@ class MySqlLockManager extends DBLockManager {
  * @ingroup LockManager
  */
 class PostgreSqlLockManager extends DBLockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
@@ -374,7 +380,7 @@ class PostgreSqlLockManager extends DBLockManager {
 
                $db = $this->getConnection( $lockSrv ); // checked in isServerUp()
                $bigints = array_unique( array_map(
-                       function( $key ) {
+                       function ( $key ) {
                                return wfBaseConvert( substr( $key, 0, 15 ), 16, 10 );
                        },
                        array_map( array( $this, 'sha1Base16Absolute' ), $paths )
index eacba70..bce6b34 100644 (file)
@@ -34,7 +34,7 @@
  * @since 1.19
  */
 class FSLockManager extends LockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
@@ -43,16 +43,14 @@ class FSLockManager extends LockManager {
 
        protected $lockDir; // global dir for all servers
 
-       /** @var Array Map of (locked key => lock file handle) */
+       /** @var array Map of (locked key => lock file handle) */
        protected $handles = array();
 
        /**
         * Construct a new instance from configuration.
         *
-        * $config includes:
+        * @param array $config Includes:
         *   - lockDirectory : Directory containing the lock files
-        *
-        * @param array $config
         */
        function __construct( array $config ) {
                parent::__construct( $config );
@@ -62,8 +60,8 @@ class FSLockManager extends LockManager {
 
        /**
         * @see LockManager::doLock()
-        * @param $paths array
-        * @param $type int
+        * @param array $paths
+        * @param int $type
         * @return Status
         */
        protected function doLock( array $paths, $type ) {
@@ -77,6 +75,7 @@ class FSLockManager extends LockManager {
                        } else {
                                // Abort and unlock everything
                                $status->merge( $this->doUnlock( $lockedPaths, $type ) );
+
                                return $status;
                        }
                }
@@ -86,8 +85,8 @@ class FSLockManager extends LockManager {
 
        /**
         * @see LockManager::doUnlock()
-        * @param $paths array
-        * @param $type int
+        * @param array $paths
+        * @param int $type
         * @return Status
         */
        protected function doUnlock( array $paths, $type ) {
@@ -103,8 +102,8 @@ class FSLockManager extends LockManager {
        /**
         * Lock a single resource key
         *
-        * @param $path string
-        * @param $type integer
+        * @param string $path
+        * @param int $type
         * @return Status
         */
        protected function doSingleLock( $path, $type ) {
@@ -148,8 +147,8 @@ class FSLockManager extends LockManager {
        /**
         * Unlock a single resource key
         *
-        * @param $path string
-        * @param $type integer
+        * @param string $path
+        * @param int $type
         * @return Status
         */
        protected function doSingleUnlock( $path, $type ) {
@@ -191,8 +190,8 @@ class FSLockManager extends LockManager {
        }
 
        /**
-        * @param $path string
-        * @param $handlesToClose array
+        * @param string $path
+        * @param array $handlesToClose
         * @return Status
         */
        private function closeLockHandles( $path, array $handlesToClose ) {
@@ -205,11 +204,12 @@ class FSLockManager extends LockManager {
                                $status->warning( 'lockmanager-fail-closelock', $path );
                        }
                }
+
                return $status;
        }
 
        /**
-        * @param $path string
+        * @param string $path
         * @return Status
         */
        private function pruneKeyLockFiles( $path ) {
@@ -221,12 +221,13 @@ class FSLockManager extends LockManager {
                        }
                        unset( $this->handles[$path] );
                }
+
                return $status;
        }
 
        /**
         * Get the path to the lock file for a key
-        * @param $path string
+        * @param string $path
         * @return string
         */
        protected function getLockPath( $path ) {
index 97de8dc..539a780 100644 (file)
  * @since 1.19
  */
 class LSLockManager extends QuorumLockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
                self::LOCK_EX => self::LOCK_EX
        );
 
-       /** @var Array Map of server names to server config */
+       /** @var array Map of server names to server config */
        protected $lockServers; // (server name => server config array)
 
-       /** @var Array Map Server connections (server name => resource) */
+       /** @var array Map Server connections (server name => resource) */
        protected $conns = array();
 
        protected $connTimeout; // float number of seconds
@@ -56,7 +56,7 @@ class LSLockManager extends QuorumLockManager {
        /**
         * Construct a new instance from configuration.
         *
-        * $config paramaters include:
+        * @param array $config Paramaters include:
         *   - lockServers  : Associative array of server names to configuration.
         *                    Configuration is an associative array that includes:
         *                      - host    : IP address/hostname
@@ -65,8 +65,6 @@ class LSLockManager extends QuorumLockManager {
         *   - srvsByBucket : Array of 1-16 consecutive integer keys, starting from 0,
         *                    each having an odd-numbered list of server names (peers) as values.
         *   - connTimeout  : Lock server connection attempt timeout. [optional]
-        *
-        * @param array $config
         */
        public function __construct( array $config ) {
                parent::__construct( $config );
@@ -87,6 +85,9 @@ class LSLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::getLocksOnServer()
+        * @param string $lockSrv
+        * @param array $paths
+        * @param int $type
         * @return Status
         */
        protected function getLocksOnServer( $lockSrv, array $paths, $type ) {
@@ -108,6 +109,9 @@ class LSLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::freeLocksOnServer()
+        * @param string $lockSrv
+        * @param array $paths
+        * @param int $type
         * @return Status
         */
        protected function freeLocksOnServer( $lockSrv, array $paths, $type ) {
@@ -146,6 +150,7 @@ class LSLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::isServerUp()
+        * @param string $lockSrv
         * @return bool
         */
        protected function isServerUp( $lockSrv ) {
@@ -155,10 +160,10 @@ class LSLockManager extends QuorumLockManager {
        /**
         * Send a command and get back the response
         *
-        * @param $lockSrv string
-        * @param $action string
-        * @param $type string
-        * @param $values Array
+        * @param string $lockSrv
+        * @param string $action
+        * @param string $type
+        * @param array $values
         * @return string|bool
         */
        protected function sendCommand( $lockSrv, $action, $type, $values ) {
@@ -179,13 +184,14 @@ class LSLockManager extends QuorumLockManager {
                if ( $response === false ) {
                        return false;
                }
+
                return trim( $response );
        }
 
        /**
         * Get (or reuse) a connection to a lock server
         *
-        * @param $lockSrv string
+        * @param string $lockSrv
         * @return resource
         */
        protected function getConnection( $lockSrv ) {
@@ -203,6 +209,7 @@ class LSLockManager extends QuorumLockManager {
                        stream_set_timeout( $conn, $sec, $usec );
                        $this->conns[$lockSrv] = $conn;
                }
+
                return $this->conns[$lockSrv];
        }
 
index dad8a62..df8d2d4 100644 (file)
  * @since 1.19
  */
 abstract class LockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_EX, // subclasses may use self::LOCK_SH
                self::LOCK_EX => self::LOCK_EX
        );
 
-       /** @var Array Map of (resource path => lock type => count) */
+       /** @var array Map of (resource path => lock type => count) */
        protected $locksHeld = array();
 
        protected $domain; // string; domain (usually wiki ID)
@@ -64,12 +64,10 @@ abstract class LockManager {
        /**
         * Construct a new instance from configuration
         *
-        * $config paramaters include:
+        * @param array $config Paramaters include:
         *   - domain  : Domain (usually wiki ID) that all resources are relative to [optional]
         *   - lockTTL : Age (in seconds) at which resource locks should expire.
         *               This only applies if locks are not tied to a connection/process.
-        *
-        * @param $config Array
         */
        public function __construct( array $config ) {
                $this->domain = isset( $config['domain'] ) ? $config['domain'] : wfWikiID();
@@ -87,8 +85,8 @@ abstract class LockManager {
         * Lock the resources at the given abstract paths
         *
         * @param array $paths List of resource names
-        * @param $type integer LockManager::LOCK_* constant
-        * @param integer $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
+        * @param int $type LockManager::LOCK_* constant
+        * @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
         * @return Status
         */
        final public function lock( array $paths, $type = self::LOCK_EX, $timeout = 0 ) {
@@ -99,7 +97,7 @@ abstract class LockManager {
         * Lock the resources at the given abstract paths
         *
         * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
-        * @param integer $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
+        * @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
         * @return Status
         * @since 1.22
         */
@@ -119,6 +117,7 @@ abstract class LockManager {
                        $elapsed = microtime( true ) - $start;
                } while ( $elapsed < $timeout && $elapsed >= 0 );
                wfProfileOut( __METHOD__ );
+
                return $status;
        }
 
@@ -126,7 +125,7 @@ abstract class LockManager {
         * Unlock the resources at the given abstract paths
         *
         * @param array $paths List of paths
-        * @param $type integer LockManager::LOCK_* constant
+        * @param int $type LockManager::LOCK_* constant
         * @return Status
         */
        final public function unlock( array $paths, $type = self::LOCK_EX ) {
@@ -145,6 +144,7 @@ abstract class LockManager {
                $pathsByType = $this->normalizePathsByType( $pathsByType );
                $status = $this->doUnlockByType( $pathsByType );
                wfProfileOut( __METHOD__ );
+
                return $status;
        }
 
@@ -153,7 +153,7 @@ abstract class LockManager {
         * Before hashing, the path will be prefixed with the domain ID.
         * This should be used interally for lock key or file names.
         *
-        * @param $path string
+        * @param string $path
         * @return string
         */
        final protected function sha1Base36Absolute( $path ) {
@@ -165,7 +165,7 @@ abstract class LockManager {
         * Before hashing, the path will be prefixed with the domain ID.
         * This should be used interally for lock key or file names.
         *
-        * @param $path string
+        * @param string $path
         * @return string
         */
        final protected function sha1Base16Absolute( $path ) {
@@ -176,8 +176,8 @@ abstract class LockManager {
         * Normalize the $paths array by converting LOCK_UW locks into the
         * appropriate type and removing any duplicated paths for each lock type.
         *
-        * @param array $paths Map of LockManager::LOCK_* constants to lists of paths
-        * @return Array
+        * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
+        * @return array
         * @since 1.22
         */
        final protected function normalizePathsByType( array $pathsByType ) {
@@ -185,12 +185,13 @@ abstract class LockManager {
                foreach ( $pathsByType as $type => $paths ) {
                        $res[$this->lockTypeMap[$type]] = array_unique( $paths );
                }
+
                return $res;
        }
 
        /**
         * @see LockManager::lockByType()
-        * @param array $paths Map of LockManager::LOCK_* constants to lists of paths
+        * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         * @since 1.22
         */
@@ -203,12 +204,13 @@ abstract class LockManager {
                                $lockedByType[$type] = $paths;
                        } else {
                                // Release the subset of locks that were acquired
-                               foreach ( $lockedByType as $type => $paths ) {
-                                       $status->merge( $this->doUnlock( $paths, $type ) );
+                               foreach ( $lockedByType as $lType => $lPaths ) {
+                                       $status->merge( $this->doUnlock( $lPaths, $lType ) );
                                }
                                break;
                        }
                }
+
                return $status;
        }
 
@@ -216,14 +218,14 @@ abstract class LockManager {
         * Lock resources with the given keys and lock type
         *
         * @param array $paths List of paths
-        * @param $type integer LockManager::LOCK_* constant
+        * @param int $type LockManager::LOCK_* constant
         * @return Status
         */
        abstract protected function doLock( array $paths, $type );
 
        /**
         * @see LockManager::unlockByType()
-        * @param array $paths Map of LockManager::LOCK_* constants to lists of paths
+        * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         * @since 1.22
         */
@@ -232,6 +234,7 @@ abstract class LockManager {
                foreach ( $pathsByType as $type => $paths ) {
                        $status->merge( $this->doUnlock( $paths, $type ) );
                }
+
                return $status;
        }
 
@@ -239,7 +242,7 @@ abstract class LockManager {
         * Unlock resources with the given keys and lock type
         *
         * @param array $paths List of paths
-        * @param $type integer LockManager::LOCK_* constant
+        * @param int $type LockManager::LOCK_* constant
         * @return Status
         */
        abstract protected function doUnlock( array $paths, $type );
index 9aff241..ecf396a 100644 (file)
  * @since 1.19
  */
 class LockManagerGroup {
-       /** @var Array (domain => LockManager) */
+       /** @var array (domain => LockManager) */
        protected static $instances = array();
 
        protected $domain; // string; domain (usually wiki ID)
 
-       /** @var Array of (name => ('class' => ..., 'config' => ..., 'instance' => ...)) */
+       /** @var array of (name => ('class' => ..., 'config' => ..., 'instance' => ...)) */
        protected $managers = array();
 
        /**
@@ -45,7 +45,7 @@ class LockManagerGroup {
        }
 
        /**
-        * @param string $domain Domain (usually wiki ID)
+        * @param bool|string $domain Domain (usually wiki ID). Default: false.
         * @return LockManagerGroup
         */
        public static function singleton( $domain = false ) {
@@ -54,13 +54,12 @@ class LockManagerGroup {
                        self::$instances[$domain] = new self( $domain );
                        self::$instances[$domain]->initFromGlobals();
                }
+
                return self::$instances[$domain];
        }
 
        /**
         * Destroy the singleton instances
-        *
-        * @return void
         */
        public static function destroySingletons() {
                self::$instances = array();
@@ -68,8 +67,6 @@ class LockManagerGroup {
 
        /**
         * Register lock managers from the global variables
-        *
-        * @return void
         */
        protected function initFromGlobals() {
                global $wgLockManagers;
@@ -80,8 +77,7 @@ class LockManagerGroup {
        /**
         * Register an array of file lock manager configurations
         *
-        * @param $configs Array
-        * @return void
+        * @param array $configs
         * @throws MWException
         */
        protected function register( array $configs ) {
@@ -107,7 +103,7 @@ class LockManagerGroup {
        /**
         * Get the lock manager object with a given name
         *
-        * @param $name string
+        * @param string $name
         * @return LockManager
         * @throws MWException
         */
@@ -121,14 +117,15 @@ class LockManagerGroup {
                        $config = $this->managers[$name]['config'];
                        $this->managers[$name]['instance'] = new $class( $config );
                }
+
                return $this->managers[$name]['instance'];
        }
 
        /**
         * Get the config array for a lock manager object with a given name
         *
-        * @param $name string
-        * @return Array
+        * @param string $name
+        * @return array
         * @throws MWException
         */
        public function config( $name ) {
@@ -136,6 +133,7 @@ class LockManagerGroup {
                        throw new MWException( "No lock manager defined with the name `$name`." );
                }
                $class = $this->managers[$name]['class'];
+
                return array( 'class' => $class ) + $this->managers[$name]['config'];
        }
 
index 5eab03e..f7ffb2d 100644 (file)
  * @since 1.20
  */
 class MemcLockManager extends QuorumLockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
                self::LOCK_EX => self::LOCK_EX
        );
 
-       /** @var Array Map server names to MemcachedBagOStuff objects */
+       /** @var array Map server names to MemcachedBagOStuff objects */
        protected $bagOStuffs = array();
-       /** @var Array */
-       protected $serversUp = array(); // (server name => bool)
 
-       protected $session = ''; // string; random UUID
+       /** @var array (server name => bool) */
+       protected $serversUp = array();
+
+       /** @var string random UUID */
+       protected $session = '';
 
        /**
         * Construct a new instance from configuration.
         *
-        * $config paramaters include:
+        * @param array $config Paramaters include:
         *   - lockServers  : Associative array of server names to "<IP>:<port>" strings.
         *   - srvsByBucket : Array of 1-16 consecutive integer keys, starting from 0,
         *                    each having an odd-numbered list of server names (peers) as values.
         *   - memcConfig   : Configuration array for ObjectCache::newFromParams. [optional]
         *                    If set, this must use one of the memcached classes.
-        *
-        * @param array $config
         * @throws MWException
         */
        public function __construct( array $config ) {
@@ -88,7 +88,7 @@ class MemcLockManager extends QuorumLockManager {
                $this->session = wfRandomString( 32 );
        }
 
-       // @TODO: change this code to work in one batch
+       // @todo Change this code to work in one batch
        protected function getLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = Status::newGood();
 
@@ -100,8 +100,8 @@ class MemcLockManager extends QuorumLockManager {
                                        ? array_merge( $lockedPaths[$type], $paths )
                                        : $paths;
                        } else {
-                               foreach ( $lockedPaths as $type => $paths ) {
-                                       $status->merge( $this->doFreeLocksOnServer( $lockSrv, $paths, $type ) );
+                               foreach ( $lockedPaths as $lType => $lPaths ) {
+                                       $status->merge( $this->doFreeLocksOnServer( $lockSrv, $lPaths, $lType ) );
                                }
                                break;
                        }
@@ -110,7 +110,7 @@ class MemcLockManager extends QuorumLockManager {
                return $status;
        }
 
-       // @TODO: change this code to work in one batch
+       // @todo Change this code to work in one batch
        protected function freeLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = Status::newGood();
 
@@ -123,6 +123,9 @@ class MemcLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::getLocksOnServer()
+        * @param string $lockSrv
+        * @param array $paths
+        * @param string $type
         * @return Status
         */
        protected function doGetLocksOnServer( $lockSrv, array $paths, $type ) {
@@ -136,6 +139,7 @@ class MemcLockManager extends QuorumLockManager {
                        foreach ( $paths as $path ) {
                                $status->fatal( 'lockmanager-fail-acquirelock', $path );
                        }
+
                        return $status;
                }
 
@@ -195,6 +199,9 @@ class MemcLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::freeLocksOnServer()
+        * @param string $lockSrv
+        * @param array $paths
+        * @param string $type
         * @return Status
         */
        protected function doFreeLocksOnServer( $lockSrv, array $paths, $type ) {
@@ -208,7 +215,8 @@ class MemcLockManager extends QuorumLockManager {
                        foreach ( $paths as $path ) {
                                $status->fatal( 'lockmanager-fail-releaselock', $path );
                        }
-                       return;
+
+                       return $status;
                }
 
                // Fetch all the existing lock records...
@@ -254,6 +262,7 @@ class MemcLockManager extends QuorumLockManager {
 
        /**
         * @see QuorumLockManager::isServerUp()
+        * @param string $lockSrv
         * @return bool
         */
        protected function isServerUp( $lockSrv ) {
@@ -280,11 +289,12 @@ class MemcLockManager extends QuorumLockManager {
                                return null; // server appears to be down
                        }
                }
+
                return $memc;
        }
 
        /**
-        * @param $path string
+        * @param string $path
         * @return string
         */
        protected function recordKeyForPath( $path ) {
@@ -292,27 +302,28 @@ class MemcLockManager extends QuorumLockManager {
        }
 
        /**
-        * @return Array An empty lock structure for a key
+        * @return array An empty lock structure for a key
         */
        protected static function newLockArray() {
                return array( self::LOCK_SH => array(), self::LOCK_EX => array() );
        }
 
        /**
-        * @param $a array
-        * @return Array An empty lock structure for a key
+        * @param array $a
+        * @return array An empty lock structure for a key
         */
        protected static function sanitizeLockArray( $a ) {
                if ( is_array( $a ) && isset( $a[self::LOCK_EX] ) && isset( $a[self::LOCK_SH] ) ) {
                        return $a;
                } else {
                        trigger_error( __METHOD__ . ": reset invalid lock array.", E_USER_WARNING );
+
                        return self::newLockArray();
                }
        }
 
        /**
-        * @param $memc MemcachedBagOStuff
+        * @param MemcachedBagOStuff $memc
         * @param array $keys List of keys to acquire
         * @return bool
         */
@@ -350,9 +361,8 @@ class MemcLockManager extends QuorumLockManager {
        }
 
        /**
-        * @param $memc MemcachedBagOStuff
+        * @param MemcachedBagOStuff $memc
         * @param array $keys List of acquired keys
-        * @return void
         */
        protected function releaseMutexes( MemcachedBagOStuff $memc, array $keys ) {
                foreach ( $keys as $key ) {
index 8356d32..d17074e 100644 (file)
  * @since 1.20
  */
 abstract class QuorumLockManager extends LockManager {
-       /** @var Array Map of bucket indexes to peer server lists */
+       /** @var array Map of bucket indexes to peer server lists */
        protected $srvsByBucket = array(); // (bucket index => (lsrv1, lsrv2, ...))
-       /** @var Array Map of degraded buckets */
+
+       /** @var array Map of degraded buckets */
        protected $degradedBuckets = array(); // (buckey index => UNIX timestamp)
 
        final protected function doLock( array $paths, $type ) {
@@ -65,6 +66,7 @@ abstract class QuorumLockManager extends LockManager {
                        $status->merge( $this->doLockingRequestBucket( $bucket, $pathsToLockByType ) );
                        if ( !$status->isOK() ) {
                                $status->merge( $this->doUnlockByType( $lockedPaths ) );
+
                                return $status;
                        }
                        // Record these locks as active
@@ -120,7 +122,7 @@ abstract class QuorumLockManager extends LockManager {
         * Attempt to acquire locks with the peers for a bucket.
         * This is all or nothing; if any key is locked then this totally fails.
         *
-        * @param $bucket integer
+        * @param int $bucket
         * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         */
@@ -162,7 +164,7 @@ abstract class QuorumLockManager extends LockManager {
        /**
         * Attempt to release locks with the peers for a bucket
         *
-        * @param $bucket integer
+        * @param int $bucket
         * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         */
@@ -198,8 +200,8 @@ abstract class QuorumLockManager extends LockManager {
         * Get the bucket for resource path.
         * This should avoid throwing any exceptions.
         *
-        * @param $path string
-        * @return integer
+        * @param string $path
+        * @return int
         */
        protected function getBucketFromPath( $path ) {
                $prefix = substr( sha1( $path ), 0, 2 ); // first 2 hex chars (8 bits)
@@ -210,7 +212,7 @@ abstract class QuorumLockManager extends LockManager {
         * Check if a lock server is up.
         * This should process cache results to reduce RTT.
         *
-        * @param $lockSrv string
+        * @param string $lockSrv
         * @return bool
         */
        abstract protected function isServerUp( $lockSrv );
@@ -218,7 +220,7 @@ abstract class QuorumLockManager extends LockManager {
        /**
         * Get a connection to a lock server and acquire locks
         *
-        * @param $lockSrv string
+        * @param string $lockSrv
         * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         */
@@ -229,7 +231,7 @@ abstract class QuorumLockManager extends LockManager {
         *
         * Subclasses must effectively implement this or releaseAllLocks().
         *
-        * @param $lockSrv string
+        * @param string $lockSrv
         * @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
         * @return Status
         */
index 43b0198..9d5612a 100644 (file)
@@ -38,7 +38,7 @@
  * @since 1.22
  */
 class RedisLockManager extends QuorumLockManager {
-       /** @var Array Mapping of lock types to the type actually used */
+       /** @var array Mapping of lock types to the type actually used */
        protected $lockTypeMap = array(
                self::LOCK_SH => self::LOCK_SH,
                self::LOCK_UW => self::LOCK_SH,
@@ -47,21 +47,21 @@ class RedisLockManager extends QuorumLockManager {
 
        /** @var RedisConnectionPool */
        protected $redisPool;
-       /** @var Array Map server names to hostname/IP and port numbers */
+
+       /** @var array Map server names to hostname/IP and port numbers */
        protected $lockServers = array();
 
-       protected $session = ''; // string; random UUID
+       /** @var string random UUID */
+       protected $session = '';
 
        /**
         * Construct a new instance from configuration.
         *
-        * $config paramaters include:
+        * @param array $config Parameters include:
         *   - lockServers  : Associative array of server names to "<IP>:<port>" strings.
         *   - srvsByBucket : Array of 1-16 consecutive integer keys, starting from 0,
         *                    each having an odd-numbered list of server names (peers) as values.
         *   - redisConfig  : Configuration for RedisConnectionPool::__construct().
-        *
-        * @param Array $config
         * @throws MWException
         */
        public function __construct( array $config ) {
@@ -90,8 +90,8 @@ class RedisLockManager extends QuorumLockManager {
                                        ? array_merge( $lockedPaths[$type], $paths )
                                        : $paths;
                        } else {
-                               foreach ( $lockedPaths as $type => $paths ) {
-                                       $status->merge( $this->doFreeLocksOnServer( $lockSrv, $paths, $type ) );
+                               foreach ( $lockedPaths as $lType => $lPaths ) {
+                                       $status->merge( $this->doFreeLocksOnServer( $lockSrv, $lPaths, $lType ) );
                                }
                                break;
                        }
@@ -100,7 +100,7 @@ class RedisLockManager extends QuorumLockManager {
                return $status;
        }
 
-       // @TODO: change this code to work in one batch
+       // @todo Change this code to work in one batch
        protected function freeLocksOnServer( $lockSrv, array $pathsByType ) {
                $status = Status::newGood();
 
@@ -120,6 +120,7 @@ class RedisLockManager extends QuorumLockManager {
                        foreach ( $paths as $path ) {
                                $status->fatal( 'lockmanager-fail-acquirelock', $path );
                        }
+
                        return $status;
                }
 
@@ -204,6 +205,7 @@ LUA;
                        foreach ( $paths as $path ) {
                                $status->fatal( 'lockmanager-fail-releaselock', $path );
                        }
+
                        return $status;
                }
 
@@ -267,7 +269,7 @@ LUA;
        }
 
        /**
-        * @param $path string
+        * @param string $path
         * @return string
         */
        protected function recordKeyForPath( $path ) {
index 5faad4a..2056e10 100644 (file)
 class ScopedLock {
        /** @var LockManager */
        protected $manager;
+
        /** @var Status */
        protected $status;
-       /** @var Array Map of lock types to resource paths */
+
+       /** @var array Map of lock types to resource paths */
        protected $pathsByType;
 
        /**
@@ -55,14 +57,13 @@ class ScopedLock {
         * Any locks are released once this object goes out of scope.
         * The status object is updated with any errors or warnings.
         *
-        * $type can be "mixed" and $paths can be a map of types to paths (since 1.22).
-        * Otherwise $type should be an integer and $paths should be a list of paths.
-        *
         * @param LockManager $manager
         * @param array $paths List of storage paths or map of lock types to path lists
-        * @param integer|string $type LockManager::LOCK_* constant or "mixed"
+        * @param int|string $type LockManager::LOCK_* constant or "mixed" and $paths
+        *   can be a map of types to paths (since 1.22). Otherwise $type should be an
+        *   integer and $paths should be a list of paths.
         * @param Status $status
-        * @param integer $timeout Timeout in seconds (0 means non-blocking) (since 1.22)
+        * @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.22)
         * @return ScopedLock|null Returns null on failure
         */
        public static function factory(
@@ -74,6 +75,7 @@ class ScopedLock {
                if ( $lockStatus->isOK() ) {
                        return new self( $manager, $pathsByType, $status );
                }
+
                return null;
        }
 
@@ -83,7 +85,6 @@ class ScopedLock {
         * This is the same as setting the lock object to null.
         *
         * @param ScopedLock $lock
-        * @return void
         * @since 1.21
         */
        public static function release( ScopedLock &$lock = null ) {
index 42c9c94..046b97c 100644 (file)
@@ -31,7 +31,6 @@
  * @deprecated since 1.19
  */
 class FSRepo extends FileRepo {
-
        /**
         * @param $info array
         * @throws MWException
index 1195d5f..47efa70 100644 (file)
@@ -42,24 +42,81 @@ class FileRepo {
 
        /** @var FileBackend */
        protected $backend;
+
        /** @var Array Map of zones to config */
        protected $zones = array();
 
-       var $thumbScriptUrl, $transformVia404;
-       var $descBaseUrl, $scriptDirUrl, $scriptExtension, $articleUrl;
-       var $fetchDescription, $initialCapital;
-       var $pathDisclosureProtection = 'simple'; // 'paranoid'
-       var $descriptionCacheExpiry, $url, $thumbUrl;
-       var $hashLevels, $deletedHashLevels;
+       /** @var string URL of thumb.php  */
+       protected $thumbScriptUrl;
+
+       /** @var bool Whether to skip media file transformation on parse and rely
+        *    on a 404 handler instead. */
+       protected $transformVia404;
+
+       /** @var string URL of image description pages, e.g.
+        *    http://en.wikipedia.org/wiki/File:
+        */
+       protected $descBaseUrl;
+
+       /** @var string URL of the MediaWiki installation, equivalent to
+        *    $wgScriptPath, e.g. https://en.wikipedia.org/w
+        */
+       protected $scriptDirUrl;
+
+       /** @var string Script extension of the MediaWiki installation, equivalent
+        *    to $wgScriptExtension, e.g. .php5 defaults to .php */
+       protected $scriptExtension;
+
+       /** @var string Equivalent to $wgArticlePath, e.g. http://en.wikipedia.org/wiki/$1 */
+       protected $articleUrl;
+
+       /** @var bool Whether to fetch commons image description pages and display
+        *    them on the local wiki */
+       public $fetchDescription;
+
+       /** @var bool Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE],
+        *    determines whether filenames implicitly start with a capital letter.
+        *    The current implementation may give incorrect description page links
+        *    when the local $wgCapitalLinks and initialCapital are mismatched.
+        */
+       protected $initialCapital;
+
+       /** @var string May be 'paranoid' to remove all parameters from error
+        *    messages, 'none' to leave the paths in unchanged, or 'simple' to
+        *    replace paths with placeholders. Default for LocalRepo is
+        *    'simple'.
+        */
+       protected $pathDisclosureProtection = 'simple';
+
+       /** @var int */
+       public $descriptionCacheExpiry;
+
+       /** @var bool Public zone URL. */
+       protected $url;
+
+       /** @var string The base thumbnail URL. Defaults to "<url>/thumb". */
+       protected $thumbUrl;
+
+       /** @var int The number of directory levels for hash-based division of files */
+       protected $hashLevels;
+
+       /** @var int The number of directory levels for hash-based division of deleted files */
+       protected $deletedHashLevels;
+
+       /** @var int File names over this size will use the short form of thumbnail
+        *    names. Short thumbnail names only have the width, parameters, and the
+        *    extension.
+        */
        protected $abbrvThreshold;
 
        /**
         * Factory functions for creating new files
         * Override these in the base class
         */
-       var $fileFactory = array( 'UnregisteredLocalFile', 'newFromTitle' );
-       var $oldFileFactory = false;
-       var $fileFactoryKey = false, $oldFileFactoryKey = false;
+       protected $fileFactory = array( 'UnregisteredLocalFile', 'newFromTitle' );
+       protected $oldFileFactory = false;
+       protected $fileFactoryKey = false;
+       protected $oldFileFactoryKey = false;
 
        /**
         * @param $info array|null
@@ -72,7 +129,8 @@ class FileRepo {
                        || !array_key_exists( 'name', $info )
                        || !array_key_exists( 'backend', $info )
                ) {
-                       throw new MWException( __CLASS__ . " requires an array of options having both 'name' and 'backend' keys.\n" );
+                       throw new MWException( __CLASS__ .
+                               " requires an array of options having both 'name' and 'backend' keys.\n" );
                }
 
                // Required settings
@@ -167,6 +225,7 @@ class FileRepo {
                                throw new MWException( "No '$zone' zone defined in the {$this->name} repo." );
                        }
                }
+
                return $status;
        }
 
@@ -193,6 +252,7 @@ class FileRepo {
                if ( $suffix !== false ) {
                        $path .= '/' . rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -201,14 +261,17 @@ class FileRepo {
         *
         * @param string $zone One of: public, deleted, temp, thumb
         * @param string|null $ext Optional file extension
-        * @return String or false
+        * @return string|bool
         */
        public function getZoneUrl( $zone, $ext = null ) {
-               if ( in_array( $zone, array( 'public', 'temp', 'thumb', 'transcoded' ) ) ) { // standard public zones
+               if ( in_array( $zone, array( 'public', 'temp', 'thumb', 'transcoded' ) ) ) {
+                       // standard public zones
                        if ( $ext !== null && isset( $this->zones[$zone]['urlsByExt'][$ext] ) ) {
-                               return $this->zones[$zone]['urlsByExt'][$ext]; // custom URL for extension/zone
+                               // custom URL for extension/zone
+                               return $this->zones[$zone]['urlsByExt'][$ext];
                        } elseif ( isset( $this->zones[$zone]['url'] ) ) {
-                               return $this->zones[$zone]['url']; // custom URL for zone
+                               // custom URL for zone
+                               return $this->zones[$zone]['url'];
                        }
                }
                switch ( $zone ) {
@@ -242,10 +305,11 @@ class FileRepo {
         */
        public function getZoneHandlerUrl( $zone ) {
                if ( isset( $this->zones[$zone]['handlerUrl'] )
-                       && in_array( $zone, array( 'public', 'temp', 'thumb', 'transcoded' ) ) )
-               {
+                       && in_array( $zone, array( 'public', 'temp', 'thumb', 'transcoded' ) )
+               {
                        return $this->zones[$zone]['handlerUrl'];
                }
+
                return false;
        }
 
@@ -273,6 +337,7 @@ class FileRepo {
                if ( !$base ) {
                        throw new MWException( __METHOD__ . ": invalid zone: $zone" );
                }
+
                return $base . '/' . rawurldecode( $rel );
        }
 
@@ -286,6 +351,7 @@ class FileRepo {
                if ( !isset( $this->zones[$zone] ) ) {
                        return array( null, null ); // bogus
                }
+
                return array( $this->zones[$zone]['container'], $this->zones[$zone]['directory'] );
        }
 
@@ -304,6 +370,7 @@ class FileRepo {
                if ( $base != '' ) { // may not be set
                        $base = "/{$base}";
                }
+
                return "mwstore://$backendName/{$container}{$base}";
        }
 
@@ -390,9 +457,11 @@ class FileRepo {
                        }
                        if ( $img->exists() ) {
                                $img->redirectedFrom( $title->getDBkey() );
+
                                return $img;
                        }
                }
+
                return false;
        }
 
@@ -423,6 +492,7 @@ class FileRepo {
                                $result[$file->getTitle()->getDBkey()] = $file;
                        }
                }
+
                return $result;
        }
 
@@ -457,6 +527,7 @@ class FileRepo {
                                }
                        }
                }
+
                return false;
        }
 
@@ -487,6 +558,7 @@ class FileRepo {
                                $result[$hash] = $files;
                        }
                }
+
                return $result;
        }
 
@@ -531,7 +603,7 @@ class FileRepo {
        }
 
        /**
-        * Get the name of an image from its title object
+        * Get the name of a file from its title object
         *
         * @param $title Title
         * @return String
@@ -546,6 +618,7 @@ class FileRepo {
                } else {
                        $name = $title->getDBkey();
                }
+
                return $name;
        }
 
@@ -596,6 +669,7 @@ class FileRepo {
                        for ( $i = 1; $i <= $levels; $i++ ) {
                                $path .= substr( $hash, 0, $i ) . '/';
                        }
+
                        return $path;
                }
        }
@@ -628,8 +702,10 @@ class FileRepo {
        public function makeUrl( $query = '', $entry = 'index' ) {
                if ( isset( $this->scriptDirUrl ) ) {
                        $ext = isset( $this->scriptExtension ) ? $this->scriptExtension : '.php';
+
                        return wfAppendQuery( "{$this->scriptDirUrl}/{$entry}{$ext}", $query );
                }
+
                return false;
        }
 
@@ -648,7 +724,7 @@ class FileRepo {
        public function getDescriptionUrl( $name ) {
                $encName = wfUrlencode( $name );
                if ( !is_null( $this->descBaseUrl ) ) {
-                       # "http://example.com/wiki/Image:"
+                       # "http://example.com/wiki/File:"
                        return $this->descBaseUrl . $encName;
                }
                if ( !is_null( $this->articleUrl ) ) {
@@ -667,6 +743,7 @@ class FileRepo {
                        # and just sort of hope index.php is right. ;)
                        return $this->makeUrl( "title=Image:$encName" );
                }
+
                return false;
        }
 
@@ -710,6 +787,7 @@ class FileRepo {
                        return $this->makeUrl( 'title=MediaWiki:Filepage.css&' .
                                wfArrayToCgi( Skin::getDynamicStylesheetQuery() ) );
                }
+
                return false;
        }
 
@@ -988,6 +1066,7 @@ class FileRepo {
                $temp = $this->getVirtualUrl( 'temp' );
                if ( substr( $virtualUrl, 0, strlen( $temp ) ) != $temp ) {
                        wfDebug( __METHOD__ . ": Invalid temp virtual URL\n" );
+
                        return false;
                }
 
@@ -1238,6 +1317,7 @@ class FileRepo {
         */
        public function fileExists( $file ) {
                $result = $this->fileExistsBatch( array( $file ) );
+
                return $result[0];
        }
 
@@ -1253,6 +1333,7 @@ class FileRepo {
                        $file = $this->resolveToStoragePath( $file );
                        $result[$key] = $this->backend->fileExists( array( 'src' => $file ) );
                }
+
                return $result;
        }
 
@@ -1367,6 +1448,7 @@ class FileRepo {
                for ( $i = 0; $i < $this->deletedHashLevels; $i++ ) {
                        $path .= $key[$i] . '/';
                }
+
                return $path;
        }
 
@@ -1382,6 +1464,7 @@ class FileRepo {
                if ( $this->isVirtualUrl( $path ) ) {
                        return $this->resolveVirtualUrl( $path );
                }
+
                return $path;
        }
 
@@ -1394,6 +1477,7 @@ class FileRepo {
         */
        public function getLocalCopy( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getLocalCopy( array( 'src' => $path ) );
        }
 
@@ -1407,6 +1491,7 @@ class FileRepo {
         */
        public function getLocalReference( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getLocalReference( array( 'src' => $path ) );
        }
 
@@ -1419,6 +1504,7 @@ class FileRepo {
         */
        public function getFileProps( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getFileProps( array( 'src' => $path ) );
        }
 
@@ -1430,6 +1516,7 @@ class FileRepo {
         */
        public function getFileTimestamp( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getFileTimestamp( array( 'src' => $path ) );
        }
 
@@ -1441,6 +1528,7 @@ class FileRepo {
         */
        public function getFileSize( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getFileSize( array( 'src' => $path ) );
        }
 
@@ -1452,6 +1540,7 @@ class FileRepo {
         */
        public function getFileSha1( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
+
                return $this->backend->getFileSha1Base36( array( 'src' => $path ) );
        }
 
@@ -1465,6 +1554,7 @@ class FileRepo {
        public function streamFile( $virtualUrl, $headers = array() ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
                $params = array( 'src' => $path, 'headers' => $headers );
+
                return $this->backend->streamFile( $params )->isOK();
        }
 
@@ -1516,6 +1606,7 @@ class FileRepo {
                if ( strval( $filename ) == '' ) {
                        return false;
                }
+
                return FileBackend::isPathTraversalFree( $filename );
        }
 
@@ -1564,6 +1655,7 @@ class FileRepo {
        public function newFatal( $message /*, parameters...*/ ) {
                $params = func_get_args();
                array_unshift( $params, $this );
+
                return call_user_func_array( array( 'FileRepoStatus', 'newFatal' ), $params );
        }
 
@@ -1596,7 +1688,8 @@ class FileRepo {
         * STUB
         * @param $title Title of image
         */
-       public function invalidateImageRedirect( Title $title ) {}
+       public function invalidateImageRedirect( Title $title ) {
+       }
 
        /**
         * Get the human-readable name of the repo
@@ -1608,6 +1701,7 @@ class FileRepo {
                if ( $this->isLocal() ) {
                        return null;
                }
+
                // 'shared-repo-name-wikimediacommons' is used when $wgUseInstantCommons = true
                return wfMessageFallback( 'shared-repo-name-' . $this->name, 'shared-repo' )->text();
        }
@@ -1624,6 +1718,7 @@ class FileRepo {
                        $ext = FileBackend::extensionFromPath( $name );
                        $name = ( $ext == '' ) ? 'thumbnail' : "thumbnail.$ext";
                }
+
                return $name;
        }
 
@@ -1658,6 +1753,7 @@ class FileRepo {
        public function getLocalCacheKey( /*...*/ ) {
                $args = func_get_args();
                array_unshift( $args, 'filerepo', $this->getName() );
+
                return call_user_func_array( 'wfMemcKey', $args );
        }
 
@@ -1680,13 +1776,13 @@ class FileRepo {
                                ),
                                'thumb' => array(
                                        'container' => $this->zones['thumb']['container'],
-                                       'directory' => ( $this->zones['thumb']['directory'] == '' )
+                                       'directory' => $this->zones['thumb']['directory'] == ''
                                                ? 'temp'
                                                : $this->zones['thumb']['directory'] . '/temp'
                                ),
                                'transcoded' => array(
                                        'container' => $this->zones['transcoded']['container'],
-                                       'directory' => ( $this->zones['transcoded']['directory'] == '' )
+                                       'directory' => $this->zones['transcoded']['directory'] == ''
                                                ? 'temp'
                                                : $this->zones['transcoded']['directory'] . '/temp'
                                )
@@ -1715,8 +1811,8 @@ class FileRepo {
         * @return void
         * @throws MWException
         */
-       protected function assertWritableRepo() {}
-
+       protected function assertWritableRepo() {
+       }
 
        /**
         * Return information about the repository.
@@ -1725,12 +1821,24 @@ class FileRepo {
         * @since 1.22
         */
        public function getInfo() {
-               return array(
+               $ret = array(
                        'name' => $this->getName(),
                        'displayname' => $this->getDisplayName(),
-                       'rootUrl' => $this->getRootUrl(),
+                       'rootUrl' => $this->getZoneUrl( 'public' ),
                        'local' => $this->isLocal(),
                );
+
+               $optionalSettings = array(
+                       'url', 'thumbUrl', 'initialCapital', 'descBaseUrl', 'scriptDirUrl', 'articleUrl',
+                       'fetchDescription', 'descriptionCacheExpiry', 'scriptExtension'
+               );
+               foreach ( $optionalSettings as $k ) {
+                       if ( isset( $this->$k ) ) {
+                               $ret[$k] = $this->$k;
+                       }
+               }
+
+               return $ret;
        }
 }
 
index 6f28b10..56fddf4 100644 (file)
@@ -29,8 +29,7 @@ class FileRepoStatus extends Status {
        /**
         * Factory function for fatal errors
         *
-        * @param $repo FileRepo
-        *
+        * @param FileRepo $repo
         * @return FileRepoStatus
         */
        static function newFatal( $repo /*, parameters...*/ ) {
@@ -38,17 +37,19 @@ class FileRepoStatus extends Status {
                $result = new self( $repo );
                call_user_func_array( array( &$result, 'error' ), $params );
                $result->ok = false;
+
                return $result;
        }
 
        /**
-        * @param $repo FileRepo
+        * @param FileRepo|bool $repo Default: false
         * @param $value
         * @return FileRepoStatus
         */
        static function newGood( $repo = false, $value = null ) {
                $result = new self( $repo );
                $result->value = $value;
+
                return $result;
        }
 
index 5eec9a5..bb16c8b 100644 (file)
@@ -42,13 +42,27 @@ class ForeignAPIRepo extends FileRepo {
         * Update the version every time you make breaking or significant changes. */
        const VERSION = "2.1";
 
-       var $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
-       /* Check back with Commons after a day */
-       var $apiThumbCacheExpiry = 86400; /* 24*60*60 */
-       /* Redownload thumbnail files after a month */
-       var $fileCacheExpiry = 2592000; /* 86400*30 */
+       /**
+        * List of iiprop values for the thumbnail fetch queries.
+        * @since 1.23
+        */
+       protected static $imageInfoProps = array(
+               'url',
+               'thumbnail',
+               'timestamp',
+       );
+
+       protected $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
+       /** @var int Check back with Commons after a day (24*60*60) */
+       protected $apiThumbCacheExpiry = 86400;
+
+       /** @var int Redownload thumbnail files after a month (86400*30) */
+       protected $fileCacheExpiry = 2592000;
 
-       protected $mQueryCache = array();
+       /** @var array  */
+       private $mQueryCache = array();
+
+       /** @var array  */
        protected $mFileExists = array();
 
        /**
@@ -100,6 +114,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( $time ) {
                        return false;
                }
+
                return parent::newFile( $title, $time );
        }
 
@@ -126,8 +141,11 @@ class ForeignAPIRepo extends FileRepo {
                        }
                }
 
-               $data = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
-                                                                                       'prop' => 'imageinfo' ) );
+               $data = $this->fetchImageQuery( array(
+                       'titles' => implode( $files, '|' ),
+                       'prop' => 'imageinfo' )
+               );
+
                if ( isset( $data['query']['pages'] ) ) {
                        # First, get results from the query. Note we only care whether the image exists,
                        # not whether it has a description page.
@@ -151,6 +169,7 @@ class ForeignAPIRepo extends FileRepo {
                                $results[$key] = $this->mFileExists[$file];
                        }
                }
+
                return $results;
        }
 
@@ -167,7 +186,7 @@ class ForeignAPIRepo extends FileRepo {
         * @return string
         */
        function fetchImageQuery( $query ) {
-               global $wgMemc, $wgLanguageCode;
+               global $wgLanguageCode;
 
                $query = array_merge( $query,
                        array(
@@ -201,6 +220,7 @@ class ForeignAPIRepo extends FileRepo {
                                }
                        }
                }
+
                return false;
        }
 
@@ -224,6 +244,7 @@ class ForeignAPIRepo extends FileRepo {
                                $ret[] = new ForeignAPIFile( Title::makeTitle( NS_FILE, $img['name'] ), $this, $img );
                        }
                }
+
                return $ret;
        }
 
@@ -238,7 +259,7 @@ class ForeignAPIRepo extends FileRepo {
        function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
                $data = $this->fetchImageQuery( array(
                        'titles' => 'File:' . $name,
-                       'iiprop' => 'url|timestamp',
+                       'iiprop' => self::getIIProps(),
                        'iiurlwidth' => $width,
                        'iiurlheight' => $height,
                        'iiurlparam' => $otherParams,
@@ -248,6 +269,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( $data && $info && isset( $info['thumburl'] ) ) {
                        wfDebug( __METHOD__ . " got remote thumb " . $info['thumburl'] . "\n" );
                        $result = $info;
+
                        return $info['thumburl'];
                } else {
                        return false;
@@ -265,7 +287,7 @@ class ForeignAPIRepo extends FileRepo {
        function getThumbError( $name, $width = -1, $height = -1, $otherParams = '', $lang = null ) {
                $data = $this->fetchImageQuery( array(
                        'titles' => 'File:' . $name,
-                       'iiprop' => 'url|timestamp',
+                       'iiprop' => self::getIIProps(),
                        'iiurlwidth' => $width,
                        'iiurlheight' => $height,
                        'iiurlparam' => $otherParams,
@@ -276,6 +298,7 @@ class ForeignAPIRepo extends FileRepo {
 
                if ( $data && $info && isset( $info['thumberror'] ) ) {
                        wfDebug( __METHOD__ . " got remote thumb error " . $info['thumberror'] . "\n" );
+
                        return new MediaTransformError(
                                'thumbnail_error_remote',
                                $width,
@@ -297,7 +320,8 @@ class ForeignAPIRepo extends FileRepo {
         * @param string $name is a dbkey form of a title
         * @param $width
         * @param $height
-        * @param string $params Other rendering parameters (page number, etc) from handler's makeParamString.
+        * @param string $params Other rendering parameters (page number, etc)
+        *   from handler's makeParamString.
         * @return bool|string
         */
        function getThumbUrlFromCache( $name, $width, $height, $params = "" ) {
@@ -322,6 +346,7 @@ class ForeignAPIRepo extends FileRepo {
                        if ( isset( $knownThumbUrls[$sizekey] ) ) {
                                wfDebug( __METHOD__ . ': Got thumburl from local cache: ' .
                                        "{$knownThumbUrls[$sizekey]} \n" );
+
                                return $knownThumbUrls[$sizekey];
                        }
                        /* This size is not yet known */
@@ -332,6 +357,7 @@ class ForeignAPIRepo extends FileRepo {
 
                if ( !$foreignUrl ) {
                        wfDebug( __METHOD__ . " Could not find thumburl\n" );
+
                        return false;
                }
 
@@ -339,14 +365,17 @@ class ForeignAPIRepo extends FileRepo {
                $fileName = rawurldecode( pathinfo( $foreignUrl, PATHINFO_BASENAME ) );
                if ( !$this->validateFilename( $fileName ) ) {
                        wfDebug( __METHOD__ . " The deduced filename $fileName is not safe\n" );
+
                        return false;
                }
                $localPath = $this->getZonePath( 'thumb' ) . "/" . $this->getHashPath( $name ) . $name;
                $localFilename = $localPath . "/" . $fileName;
-               $localUrl = $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) . rawurlencode( $name ) . "/" . rawurlencode( $fileName );
+               $localUrl = $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) .
+                       rawurlencode( $name ) . "/" . rawurlencode( $fileName );
 
                if ( $backend->fileExists( array( 'src' => $localFilename ) )
-                       && isset( $metadata['timestamp'] ) ) {
+                       && isset( $metadata['timestamp'] )
+               ) {
                        wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
                        $modified = $backend->getFileTimestamp( array( 'src' => $localFilename ) );
                        $remoteModified = strtotime( $metadata['timestamp'] );
@@ -356,6 +385,7 @@ class ForeignAPIRepo extends FileRepo {
                                /* Use our current and already downloaded thumbnail */
                                $knownThumbUrls[$sizekey] = $localUrl;
                                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
+
                                return $localUrl;
                        }
                        /* There is a new Commons file, or existing thumbnail older than a month */
@@ -363,6 +393,7 @@ class ForeignAPIRepo extends FileRepo {
                $thumb = self::httpGet( $foreignUrl );
                if ( !$thumb ) {
                        wfDebug( __METHOD__ . " Could not download thumb\n" );
+
                        return false;
                }
 
@@ -371,11 +402,13 @@ class ForeignAPIRepo extends FileRepo {
                $params = array( 'dst' => $localFilename, 'content' => $thumb );
                if ( !$backend->quickCreate( $params )->isOK() ) {
                        wfDebug( __METHOD__ . " could not write to thumb path '$localFilename'\n" );
+
                        return $foreignUrl;
                }
                $knownThumbUrls[$sizekey] = $localUrl;
                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
                wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
+
                return $localUrl;
        }
 
@@ -406,6 +439,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( in_array( $zone, $supported ) ) {
                        return parent::getZonePath( $zone );
                }
+
                return false;
        }
 
@@ -485,6 +519,14 @@ class ForeignAPIRepo extends FileRepo {
                }
        }
 
+       /**
+        * @return string
+        * @since 1.23
+        */
+       protected static function getIIProps() {
+               return join( '|', self::$imageInfoProps );
+       }
+
        /**
         * HTTP GET request to a mediawiki API (with caching)
         * @param $target string Used in cache key creation, mostly
index 37c6572..b38416f 100644 (file)
  */
 class ForeignDBRepo extends LocalRepo {
        # Settings
-       var $dbType, $dbServer, $dbUser, $dbPassword, $dbName, $dbFlags,
-               $tablePrefix, $hasSharedCache;
+       protected $dbType;
+       protected $dbServer;
+       protected $dbUser;
+       protected $dbPassword;
+       protected $dbName;
+       protected $dbFlags;
+       protected $tablePrefix;
+       protected $hasSharedCache;
 
        # Other stuff
-       var $dbConn;
-       var $fileFactory = array( 'ForeignDBFile', 'newFromTitle' );
-       var $fileFromRowFactory = array( 'ForeignDBFile', 'newFromRow' );
+       protected $dbConn;
+       protected $fileFactory = array( 'ForeignDBFile', 'newFromTitle' );
+       protected $fileFromRowFactory = array( 'ForeignDBFile', 'newFromRow' );
 
        /**
         * @param $info array|null
@@ -68,6 +74,7 @@ class ForeignDBRepo extends LocalRepo {
                                )
                        );
                }
+
                return $this->dbConn;
        }
 
@@ -95,6 +102,7 @@ class ForeignDBRepo extends LocalRepo {
                if ( $this->hasSharedCache() ) {
                        $args = func_get_args();
                        array_unshift( $args, $this->dbName, $this->tablePrefix );
+
                        return call_user_func_array( 'wfForeignMemcKey', $args );
                } else {
                        return false;
index 7951fb1..ad63706 100644 (file)
  * @ingroup FileRepo
  */
 class ForeignDBViaLBRepo extends LocalRepo {
-       var $wiki, $dbName, $tablePrefix;
-       var $fileFactory = array( 'ForeignDBFile', 'newFromTitle' );
-       var $fileFromRowFactory = array( 'ForeignDBFile', 'newFromRow' );
+       protected $wiki;
+       protected $dbName;
+       protected $tablePrefix;
+       protected $fileFactory = array( 'ForeignDBFile', 'newFromTitle' );
+       protected $fileFromRowFactory = array( 'ForeignDBFile', 'newFromRow' );
 
        /**
         * @param $info array|null
@@ -69,6 +71,7 @@ class ForeignDBViaLBRepo extends LocalRepo {
                if ( $this->hasSharedCache() ) {
                        $args = func_get_args();
                        array_unshift( $args, $this->wiki );
+
                        return implode( ':', $args );
                } else {
                        return false;
index 9b62243..965f677 100644 (file)
  * @ingroup FileRepo
  */
 class LocalRepo extends FileRepo {
-       var $fileFactory           = array( 'LocalFile'   , 'newFromTitle' );
-       var $fileFactoryKey        = array( 'LocalFile'   , 'newFromKey'   );
-       var $fileFromRowFactory    = array( 'LocalFile'   , 'newFromRow'   );
-       var $oldFileFactory        = array( 'OldLocalFile', 'newFromTitle' );
-       var $oldFileFactoryKey     = array( 'OldLocalFile', 'newFromKey'   );
-       var $oldFileFromRowFactory = array( 'OldLocalFile', 'newFromRow'   );
+       protected $fileFactory = array( 'LocalFile', 'newFromTitle' );
+       protected $fileFactoryKey = array( 'LocalFile', 'newFromKey' );
+       protected $fileFromRowFactory = array( 'LocalFile', 'newFromRow' );
+       protected $oldFileFromRowFactory = array( 'OldLocalFile', 'newFromRow' );
+       protected $oldFileFactory = array( 'OldLocalFile', 'newFromTitle' );
+       protected $oldFileFactoryKey = array( 'OldLocalFile', 'newFromKey' );
 
        /**
         * @throws MWException
@@ -97,6 +97,7 @@ class LocalRepo extends FileRepo {
                        }
                        $dbw->commit( __METHOD__ );
                }
+
                return $status;
        }
 
@@ -111,6 +112,7 @@ class LocalRepo extends FileRepo {
                $options = ( $lock === 'lock' ) ? array( 'FOR UPDATE' ) : array();
 
                $dbw = $this->getMasterDB();
+
                return (bool)$dbw->selectField( 'filearchive', '1',
                        array( 'fa_storage_group' => 'deleted', 'fa_storage_key' => $key ),
                        __METHOD__, $options
@@ -131,6 +133,7 @@ class LocalRepo extends FileRepo {
                $ext = File::normalizeExtension( substr( $key, strcspn( $key, '.' ) + 1 ) );
 
                $dbw = $this->getMasterDB();
+
                return (bool)$dbw->selectField( 'oldimage', '1',
                        array( 'oi_sha1' => $sha1,
                                'oi_archive_name ' . $dbw->buildLike( $dbw->anyString(), ".$ext" ),
@@ -178,6 +181,7 @@ class LocalRepo extends FileRepo {
                $id = $this->getArticleID( $title );
                if ( !$id ) {
                        $wgMemc->add( $memcKey, " ", $expiry );
+
                        return false;
                }
                $dbr = $this->getSlaveDB();
@@ -191,9 +195,11 @@ class LocalRepo extends FileRepo {
                if ( $row && $row->rd_namespace == NS_FILE ) {
                        $targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title );
                        $wgMemc->add( $memcKey, $targetTitle->getDBkey(), $expiry );
+
                        return $targetTitle;
                } else {
                        $wgMemc->add( $memcKey, '', $expiry );
+
                        return false;
                }
        }
@@ -219,6 +225,7 @@ class LocalRepo extends FileRepo {
                        ),
                        __METHOD__ //Function name
                );
+
                return $id;
        }
 
@@ -299,13 +306,14 @@ class LocalRepo extends FileRepo {
                        'img_name ' . $dbr->buildLike( $prefix, $dbr->anyString() ),
                        __METHOD__,
                        $selectOptions
-                       );
+               );
 
                // Build file objects
                $files = array();
                foreach ( $res as $row ) {
                        $files[] = $this->newFileFromRow( $row );
                }
+
                return $files;
        }
 
@@ -334,6 +342,7 @@ class LocalRepo extends FileRepo {
         */
        function getSharedCacheKey( /*...*/ ) {
                $args = func_get_args();
+
                return call_user_func_array( 'wfMemcKey', $args );
        }
 
index dda51ce..29e4cad 100644 (file)
@@ -30,7 +30,8 @@ class NullRepo extends FileRepo {
        /**
         * @param $info array|null
         */
-       function __construct( $info ) {}
+       function __construct( $info ) {
+       }
 
        protected function assertWritableRepo() {
                throw new MWException( get_class( $this ) . ': write operations are not supported.' );
index b2b9477..1a7ae34 100644 (file)
  * @ingroup FileRepo
  */
 class RepoGroup {
-       /**
-        * @var LocalRepo
-        */
-       var $localRepo;
+       /** @var LocalRepo */
+       protected $localRepo;
 
-       var $foreignRepos, $reposInitialised = false;
-       var $localInfo, $foreignInfo;
-       var $cache;
+       protected $foreignRepos;
 
-       /**
-        * @var RepoGroup
-        */
+       /** @var bool */
+       protected $reposInitialised = false;
+
+       protected $localInfo;
+       protected $foreignInfo;
+
+       /** @var array  */
+       protected $cache;
+
+       /** @var RepoGroup */
        protected static $instance;
+
+       /** Maximum number of cache items */
        const MAX_CACHE_SIZE = 500;
 
        /**
@@ -53,6 +58,7 @@ class RepoGroup {
                }
                global $wgLocalFileRepo, $wgForeignFileRepos;
                self::$instance = new RepoGroup( $wgLocalFileRepo, $wgForeignFileRepos );
+
                return self::$instance;
        }
 
@@ -126,14 +132,15 @@ class RepoGroup {
                # Check the cache
                if ( empty( $options['ignoreRedirect'] )
                        && empty( $options['private'] )
-                       && empty( $options['bypassCache'] ) )
-               {
+                       && empty( $options['bypassCache'] )
+               {
                        $time = isset( $options['time'] ) ? $options['time'] : '';
                        $dbkey = $title->getDBkey();
                        if ( isset( $this->cache[$dbkey][$time] ) ) {
                                wfDebug( __METHOD__ . ": got File:$dbkey from process cache\n" );
                                # Move it to the end of the list so that we can delete the LRU entry later
                                $this->pingCache( $dbkey );
+
                                # Return the entry
                                return $this->cache[$dbkey][$time];
                        }
@@ -195,6 +202,7 @@ class RepoGroup {
 
                        $images = array_merge( $images, $repo->findFiles( $items ) );
                }
+
                return $images;
        }
 
@@ -218,6 +226,7 @@ class RepoGroup {
                                return $redir;
                        }
                }
+
                return false;
        }
 
@@ -243,6 +252,7 @@ class RepoGroup {
                                }
                        }
                }
+
                return $file;
        }
 
@@ -262,6 +272,7 @@ class RepoGroup {
                        $result = array_merge( $result, $repo->findBySha1( $hash ) );
                }
                usort( $result, 'File::compare' );
+
                return $result;
        }
 
@@ -284,6 +295,7 @@ class RepoGroup {
                foreach ( $result as $hash => $files ) {
                        usort( $result[$hash], 'File::compare' );
                }
+
                return $result;
        }
 
@@ -319,6 +331,7 @@ class RepoGroup {
                                return $repo;
                        }
                }
+
                return false;
        }
 
@@ -347,6 +360,7 @@ class RepoGroup {
                                return true;
                        }
                }
+
                return false;
        }
 
@@ -379,6 +393,7 @@ class RepoGroup {
         */
        protected function newRepo( $info ) {
                $class = $info['class'];
+
                return new $class( $info );
        }
 
@@ -397,6 +412,7 @@ class RepoGroup {
                if ( count( $bits ) != 3 ) {
                        throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" );
                }
+
                return $bits;
        }
 
@@ -411,6 +427,7 @@ class RepoGroup {
                                $repoName = 'local';
                        }
                        $repo = $this->getRepo( $repoName );
+
                        return $repo->getFileProps( $fileName );
                } else {
                        return FSFile::getPropsFromPath( $fileName );
index 749f11a..91c2fb4 100644 (file)
  * @ingroup FileAbstraction
  */
 class ArchivedFile {
-       /**#@+
-        * @private
-        */
-       var $id, # filearchive row ID
-               $name, # image name
-               $group, # FileStore storage group
-               $key, # FileStore sha1 key
-               $size, # file dimensions
-               $bits,  # size in bytes
-               $width, # width
-               $height, # height
-               $metadata, # metadata string
-               $mime, # mime type
-               $media_type, # media type
-               $description, # upload description
-               $user, # user ID of uploader
-               $user_text, # user name of uploader
-               $timestamp, # time of upload
-               $dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx)
-               $deleted, # Bitfield akin to rev_deleted
-               $sha1, # sha1 hash of file content
-               $pageCount,
-               $archive_name;
+       /** @var int filearchive row ID */
+       private $id;
 
-       /**
-        * @var MediaHandler
-        */
-       var $handler;
-       /**
-        * @var Title
+       /** @var string File name */
+       private $name;
+
+       /** @var string FileStore storage group */
+       private $group;
+
+       /** @var string FileStore SHA-1 key */
+       private $key;
+
+       /** @var int File size in bytes */
+       private $size;
+
+       /** @var int size in bytes */
+       private $bits;
+
+       /** @var int Width */
+       private $width;
+
+       /** @var int Height */
+       private $height;
+
+       /** @var string Metadata string */
+       private $metadata;
+
+       /** @var string MIME type */
+       private $mime;
+
+       /** @var string Media type */
+       private $media_type;
+
+       /** @var string Upload description */
+       private $description;
+
+       /** @var int User ID of uploader */
+       private $user;
+
+       /** @var string User name of uploader */
+       private $user_text;
+
+       /** @var string Time of upload */
+       private $timestamp;
+
+       /** @var bool Whether or not all this has been loaded from the database (loadFromXxx) */
+       private $dataLoaded;
+
+       /** @var int Bitfield akin to rev_deleted */
+       private $deleted;
+
+       /** @var string SHA-1 hash of file content */
+       private $sha1;
+
+       /** @var string Number of pages of a multipage document, or false for
+        * documents which aren't multipage documents
         */
-       var $title; # image title
+       private $pageCount;
+
+       /** @var string Original base filename */
+       private $archive_name;
 
-       /**#@-*/
+       /** @var MediaHandler */
+       protected $handler;
+
+       /** @var Title */
+       protected $title; # image title
 
        /**
         * @throws MWException
@@ -169,6 +202,7 @@ class ArchivedFile {
        public static function newFromRow( $row ) {
                $file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
                $file->loadFromRow( $row );
+
                return $file;
        }
 
@@ -256,6 +290,7 @@ class ArchivedFile {
         */
        public function getID() {
                $this->load();
+
                return $this->id;
        }
 
@@ -264,6 +299,7 @@ class ArchivedFile {
         */
        public function exists() {
                $this->load();
+
                return $this->exists;
        }
 
@@ -273,6 +309,7 @@ class ArchivedFile {
         */
        public function getKey() {
                $this->load();
+
                return $this->key;
        }
 
@@ -298,6 +335,7 @@ class ArchivedFile {
         */
        public function getWidth() {
                $this->load();
+
                return $this->width;
        }
 
@@ -307,6 +345,7 @@ class ArchivedFile {
         */
        public function getHeight() {
                $this->load();
+
                return $this->height;
        }
 
@@ -316,6 +355,7 @@ class ArchivedFile {
         */
        public function getMetadata() {
                $this->load();
+
                return $this->metadata;
        }
 
@@ -325,6 +365,7 @@ class ArchivedFile {
         */
        public function getSize() {
                $this->load();
+
                return $this->size;
        }
 
@@ -334,6 +375,7 @@ class ArchivedFile {
         */
        public function getBits() {
                $this->load();
+
                return $this->bits;
        }
 
@@ -343,6 +385,7 @@ class ArchivedFile {
         */
        public function getMimeType() {
                $this->load();
+
                return $this->mime;
        }
 
@@ -354,6 +397,7 @@ class ArchivedFile {
                if ( !isset( $this->handler ) ) {
                        $this->handler = MediaHandler::getHandler( $this->getMimeType() );
                }
+
                return $this->handler;
        }
 
@@ -369,6 +413,7 @@ class ArchivedFile {
                                $this->pageCount = false;
                        }
                }
+
                return $this->pageCount;
        }
 
@@ -379,6 +424,7 @@ class ArchivedFile {
         */
        public function getMediaType() {
                $this->load();
+
                return $this->media_type;
        }
 
@@ -389,6 +435,7 @@ class ArchivedFile {
         */
        public function getTimestamp() {
                $this->load();
+
                return wfTimestamp( TS_MW, $this->timestamp );
        }
 
@@ -400,6 +447,7 @@ class ArchivedFile {
         */
        function getSha1() {
                $this->load();
+
                return $this->sha1;
        }
 
@@ -452,6 +500,7 @@ class ArchivedFile {
         */
        public function getRawUser() {
                $this->load();
+
                return $this->user;
        }
 
@@ -462,6 +511,7 @@ class ArchivedFile {
         */
        public function getRawUserText() {
                $this->load();
+
                return $this->user_text;
        }
 
@@ -472,6 +522,7 @@ class ArchivedFile {
         */
        public function getRawDescription() {
                $this->load();
+
                return $this->description;
        }
 
@@ -481,6 +532,7 @@ class ArchivedFile {
         */
        public function getVisibility() {
                $this->load();
+
                return $this->deleted;
        }
 
@@ -492,6 +544,7 @@ class ArchivedFile {
         */
        public function isDeleted( $field ) {
                $this->load();
+
                return ( $this->deleted & $field ) == $field;
        }
 
@@ -504,6 +557,7 @@ class ArchivedFile {
         */
        public function userCan( $field, User $user = null ) {
                $this->load();
+
                return Revision::userCanBitfield( $this->deleted, $field, $user );
        }
 }
index ec5f927..cf4ddf5 100644 (file)
@@ -91,43 +91,62 @@ abstract class File {
         * The following member variables are not lazy-initialised
         */
 
-       /**
-        * @var FileRepo|bool
-        */
-       var $repo;
+       /** @var FileRepo|bool */
+       public $repo;
 
-       /**
-        * @var Title
-        */
-       var $title;
+       /** @var Title|string|bool */
+       protected $title;
 
-       var $lastError, $redirected, $redirectedTitle;
+       /** @var string Text of last error  */
+       protected $lastError;
 
-       /**
-        * @var FSFile|bool False if undefined
-        */
+       /** @var string Main part of the title, with underscores (Title::getDBkey)  */
+       protected $redirected;
+
+       /** @var Title */
+       protected $redirectedTitle;
+
+       /** @var FSFile|bool False if undefined */
        protected $fsFile;
 
-       /**
-        * @var MediaHandler
-        */
+       /** @var MediaHandler */
        protected $handler;
 
-       /**
-        * @var string
+       /** @var string The URL corresponding to one of the four basic zones */
+       protected $url;
+
+       /** @var string File extension */
+       protected $extension;
+
+       /** @var string The name of a file from its title object */
+       protected $name;
+
+       /** @var string The storage path corresponding to one of the zones */
+       protected $path;
+
+       /** @var string Relative path including trailing slash */
+       protected $hashPath;
+
+       /** @var string number of pages of a multipage document, or false for
+        *    documents which aren't multipage documents
         */
-       protected $url, $extension, $name, $path, $hashPath, $pageCount, $transformScript;
+       protected $pageCount;
 
+       /** @var string URL of transformscript (for example thumb.php) */
+       protected $transformScript;
+
+       /** @var Title */
        protected $redirectTitle;
 
-       /**
-        * @var bool
-        */
-       protected $canRender, $isSafeFile;
+       /** @var bool Wether the output of transform() for this file is likely to be valid. */
+       protected $canRender;
 
-       /**
-        * @var string Required Repository class type
+       /** @var bool Wether this media file is in a format that is unlikely to
+        *    contain viruses or malicious content
         */
+       protected $isSafeFile;
+
+       /** @var string Required Repository class type */
        protected $repoClass = 'FileRepo';
 
        /**
@@ -174,6 +193,7 @@ abstract class File {
                if ( !$ret && $exception !== false ) {
                        throw new MWException( "`$title` is not a valid file title." );
                }
+
                return $ret;
        }
 
@@ -183,6 +203,7 @@ abstract class File {
                        return null;
                } else {
                        $this->$name = call_user_func( $function );
+
                        return $this->$name;
                }
        }
@@ -224,6 +245,7 @@ abstract class File {
                $n = strrpos( $new, '.' );
                $newExt = self::normalizeExtension( $n ? substr( $new, $n + 1 ) : '' );
                $mimeMagic = MimeMagic::singleton();
+
                return $mimeMagic->isMatchingExtension( $newExt, $oldMime );
        }
 
@@ -232,7 +254,8 @@ abstract class File {
         * Called by ImagePage
         * STUB
         */
-       function upgradeRow() {}
+       function upgradeRow() {
+       }
 
        /**
         * Split an internet media type into its two components; if not
@@ -271,6 +294,7 @@ abstract class File {
                        $this->assertRepoDefined();
                        $this->name = $this->repo->getNameFromTitle( $this->title );
                }
+
                return $this->name;
        }
 
@@ -285,6 +309,7 @@ abstract class File {
                        $this->extension = self::normalizeExtension(
                                $n ? substr( $this->getName(), $n + 1 ) : '' );
                }
+
                return $this->extension;
        }
 
@@ -306,6 +331,7 @@ abstract class File {
                if ( $this->redirected ) {
                        return $this->getRedirectedTitle();
                }
+
                return $this->title;
        }
 
@@ -320,6 +346,7 @@ abstract class File {
                        $ext = $this->getExtension();
                        $this->url = $this->repo->getZoneUrl( 'public', $ext ) . '/' . $this->getUrlRel();
                }
+
                return $this->url;
        }
 
@@ -351,6 +378,7 @@ abstract class File {
                        } else {
                                wfDebug( __METHOD__ . ': supposed to render ' . $this->getName() .
                                        ' (' . $this->getMimeType() . "), but can't!\n" );
+
                                return $this->getURL(); #hm... return NULL?
                        }
                } else {
@@ -376,6 +404,7 @@ abstract class File {
                        $this->assertRepoDefined();
                        $this->path = $this->repo->getZonePath( 'public' ) . '/' . $this->getRel();
                }
+
                return $this->path;
        }
 
@@ -394,6 +423,7 @@ abstract class File {
                                $this->fsFile = false; // null => false; cache negative hits
                        }
                }
+
                return ( $this->fsFile )
                        ? $this->fsFile->getPath()
                        : false;
@@ -512,6 +542,18 @@ abstract class File {
                return false;
        }
 
+       /**
+        * Like getMetadata but returns a handler independent array of common values.
+        * @see MediaHandler::getCommonMetaArray()
+        * @return Array or false if not supported
+        * @since 1.23
+        */
+       public function getCommonMetaArray() {
+               $handler = $this->getHandler();
+
+               return $handler->getCommonMetaArray( $this );
+       }
+
        /**
         * get versioned metadata
         *
@@ -590,6 +632,7 @@ abstract class File {
                if ( !isset( $this->canRender ) ) {
                        $this->canRender = $this->getHandler() && $this->handler->canRender( $this );
                }
+
                return $this->canRender;
        }
 
@@ -639,8 +682,9 @@ abstract class File {
         */
        function isSafeFile() {
                if ( !isset( $this->isSafeFile ) ) {
-                       $this->isSafeFile = $this->_getIsSafeFile();
+                       $this->isSafeFile = $this->getIsSafeFileUncached();
                }
+
                return $this->isSafeFile;
        }
 
@@ -658,7 +702,7 @@ abstract class File {
         *
         * @return bool
         */
-       protected function _getIsSafeFile() {
+       protected function getIsSafeFileUncached() {
                global $wgTrustedMediaFormats;
 
                if ( $this->allowInlineDisplay() ) {
@@ -742,6 +786,7 @@ abstract class File {
                                }
                        }
                }
+
                return $this->transformScript;
        }
 
@@ -760,6 +805,7 @@ abstract class File {
                        return $this->iconThumb();
                }
                $hp['width'] = $width;
+
                return $this->transform( $hp );
        }
 
@@ -776,6 +822,7 @@ abstract class File {
                $name = ( $this->repo && !( $flags & self::THUMB_FULL_NAME ) )
                        ? $this->repo->nameForThumb( $this->getName() )
                        : $this->getName();
+
                return $this->generateThumbName( $name, $params );
        }
 
@@ -798,6 +845,7 @@ abstract class File {
                if ( $thumbExt != $extension ) {
                        $thumbName .= ".$thumbExt";
                }
+
                return $thumbName;
        }
 
@@ -827,6 +875,7 @@ abstract class File {
                if ( is_null( $thumb ) || $thumb->isError() ) {
                        return '';
                }
+
                return $thumb->getUrl();
        }
 
@@ -975,6 +1024,7 @@ abstract class File {
                } while ( false );
 
                wfProfileOut( __METHOD__ );
+
                return is_object( $thumb ) ? $thumb : false;
        }
 
@@ -988,6 +1038,7 @@ abstract class File {
                if ( $thumbExt != '' && $thumbExt !== $this->getExtension() ) {
                        $fileName .= ".$thumbExt";
                }
+
                return FileBackend::makeContentDisposition( 'inline', $fileName );
        }
 
@@ -996,7 +1047,8 @@ abstract class File {
         * STUB
         * Overridden by LocalFile
         */
-       function migrateThumbFile( $thumbName ) {}
+       function migrateThumbFile( $thumbName ) {
+       }
 
        /**
         * Get a MediaHandler instance for this file
@@ -1007,6 +1059,7 @@ abstract class File {
                if ( !isset( $this->handler ) ) {
                        $this->handler = MediaHandler::getHandler( $this->getMimeType() );
                }
+
                return $this->handler;
        }
 
@@ -1024,9 +1077,11 @@ abstract class File {
                        $filepath = $wgStyleDirectory . $path;
                        if ( file_exists( $filepath ) ) { // always FS
                                $params = array( 'width' => 120, 'height' => 120 );
+
                                return new ThumbnailImage( $this, $wgStylePath . $path, false, $params );
                        }
                }
+
                return null;
        }
 
@@ -1055,7 +1110,8 @@ abstract class File {
         * @param array $options Options, which include:
         *     'forThumbRefresh' : The purging is only to refresh thumbnails
         */
-       function purgeCache( $options = array() ) {}
+       function purgeCache( $options = array() ) {
+       }
 
        /**
         * Purge the file description page, but don't go after
@@ -1121,7 +1177,8 @@ abstract class File {
         * STUB
         * Overridden in LocalFile.
         */
-       public function resetHistory() {}
+       public function resetHistory() {
+       }
 
        /**
         * Get the filename hash component of the directory including trailing slash,
@@ -1135,6 +1192,7 @@ abstract class File {
                        $this->assertRepoDefined();
                        $this->hashPath = $this->repo->getHashPath( $this->getName() );
                }
+
                return $this->hashPath;
        }
 
@@ -1162,6 +1220,7 @@ abstract class File {
                } else {
                        $path .= $suffix;
                }
+
                return $path;
        }
 
@@ -1178,6 +1237,7 @@ abstract class File {
                if ( $suffix !== false ) {
                        $path .= '/' . $suffix;
                }
+
                return $path;
        }
 
@@ -1207,6 +1267,7 @@ abstract class File {
                } else {
                        $path .= $suffix;
                }
+
                return $path;
        }
 
@@ -1219,6 +1280,7 @@ abstract class File {
         */
        function getArchivePath( $suffix = false ) {
                $this->assertRepoDefined();
+
                return $this->repo->getZonePath( 'public' ) . '/' . $this->getArchiveRel( $suffix );
        }
 
@@ -1232,6 +1294,7 @@ abstract class File {
         */
        function getArchiveThumbPath( $archiveName, $suffix = false ) {
                $this->assertRepoDefined();
+
                return $this->repo->getZonePath( 'thumb' ) . '/' .
                        $this->getArchiveThumbRel( $archiveName, $suffix );
        }
@@ -1245,6 +1308,7 @@ abstract class File {
         */
        function getThumbPath( $suffix = false ) {
                $this->assertRepoDefined();
+
                return $this->repo->getZonePath( 'thumb' ) . '/' . $this->getThumbRel( $suffix );
        }
 
@@ -1257,6 +1321,7 @@ abstract class File {
         */
        function getTranscodedPath( $suffix = false ) {
                $this->assertRepoDefined();
+
                return $this->repo->getZonePath( 'transcoded' ) . '/' . $this->getThumbRel( $suffix );
        }
 
@@ -1276,6 +1341,7 @@ abstract class File {
                } else {
                        $path .= rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1297,6 +1363,7 @@ abstract class File {
                } else {
                        $path .= rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1315,6 +1382,7 @@ abstract class File {
                if ( $suffix !== false ) {
                        $path .= '/' . rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1353,6 +1421,7 @@ abstract class File {
                if ( $suffix !== false ) {
                        $path .= '/' . rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1371,6 +1440,7 @@ abstract class File {
                } else {
                        $path .= rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1387,6 +1457,7 @@ abstract class File {
                if ( $suffix !== false ) {
                        $path .= '/' . rawurlencode( $suffix );
                }
+
                return $path;
        }
 
@@ -1395,6 +1466,7 @@ abstract class File {
         */
        function isHashed() {
                $this->assertRepoDefined();
+
                return (bool)$this->repo->getHashLevels();
        }
 
@@ -1420,7 +1492,9 @@ abstract class File {
         * @return bool
         * @throws MWException
         */
-       function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false, $timestamp = false, User $user = null ) {
+       function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
+               $watch = false, $timestamp = false, User $user = null
+       ) {
                $this->readOnlyError();
        }
 
@@ -1457,6 +1531,7 @@ abstract class File {
                if ( !$this->getHandler() ) {
                        return false;
                }
+
                return $this->getHandler()->formatMetadata( $this, $this->getMetadata() );
        }
 
@@ -1525,6 +1600,7 @@ abstract class File {
         */
        function wasDeleted() {
                $title = $this->getTitle();
+
                return $title && $title->isDeletedQuick();
        }
 
@@ -1605,6 +1681,7 @@ abstract class File {
                                $this->pageCount = false;
                        }
                }
+
                return $this->pageCount;
        }
 
@@ -1637,6 +1714,7 @@ abstract class File {
                if ( !$this->getHandler() ) {
                        return false;
                }
+
                return $this->handler->getImageSize( $this, $fileName );
        }
 
@@ -1672,11 +1750,16 @@ abstract class File {
                if ( $renderUrl ) {
                        if ( $this->repo->descriptionCacheExpiry > 0 ) {
                                wfDebug( "Attempting to get the description from cache..." );
-                               $key = $this->repo->getLocalCacheKey( 'RemoteFileDescription', 'url', $lang->getCode(),
-                                                                       $this->getName() );
+                               $key = $this->repo->getLocalCacheKey(
+                                       'RemoteFileDescription',
+                                       'url',
+                                       $lang->getCode(),
+                                       $this->getName()
+                               );
                                $obj = $wgMemc->get( $key );
                                if ( $obj ) {
                                        wfDebug( "success!\n" );
+
                                        return $obj;
                                }
                                wfDebug( "miss\n" );
@@ -1686,6 +1769,7 @@ abstract class File {
                        if ( $res && $this->repo->descriptionCacheExpiry > 0 ) {
                                $wgMemc->set( $key, $res, $this->repo->descriptionCacheExpiry );
                        }
+
                        return $res;
                } else {
                        return false;
@@ -1715,6 +1799,7 @@ abstract class File {
         */
        function getTimestamp() {
                $this->assertRepoDefined();
+
                return $this->repo->getFileTimestamp( $this->getPath() );
        }
 
@@ -1725,6 +1810,7 @@ abstract class File {
         */
        function getSha1() {
                $this->assertRepoDefined();
+
                return $this->repo->getFileSha1( $this->getPath() );
        }
 
@@ -1740,6 +1826,7 @@ abstract class File {
                }
                $ext = $this->getExtension();
                $dotExt = $ext === '' ? '' : ".$ext";
+
                return $hash . $dotExt;
        }
 
@@ -1770,6 +1857,7 @@ abstract class File {
                wfDeprecated( __METHOD__, '1.19' );
 
                $fsFile = new FSFile( $path );
+
                return $fsFile->getProps();
        }
 
@@ -1789,6 +1877,7 @@ abstract class File {
                wfDeprecated( __METHOD__, '1.19' );
 
                $fsFile = new FSFile( $path );
+
                return $fsFile->getSha1Base36();
        }
 
@@ -1855,13 +1944,15 @@ abstract class File {
                        if ( !$this->redirectTitle ) {
                                $this->redirectTitle = Title::makeTitle( NS_FILE, $this->redirected );
                        }
+
                        return $this->redirectTitle;
                }
+
                return null;
        }
 
        /**
-        * @param  $from
+        * @param $from
         * @return void
         */
        function redirectedFrom( $from ) {
index ed96d44..2f713a9 100644 (file)
@@ -57,7 +57,10 @@ class ForeignAPIFile extends File {
                        'titles' => 'File:' . $title->getDBkey(),
                        'iiprop' => self::getProps(),
                        'prop' => 'imageinfo',
-                       'iimetadataversion' => MediaHandler::getMetadataVersion()
+                       'iimetadataversion' => MediaHandler::getMetadataVersion(),
+                       // extmetadata is language-dependant, accessing the current language here
+                       // would be problematic, so we just get them all
+                       'iiextmetadatamultilang' => 1,
                ) );
 
                $info = $repo->getImageInfo( $data );
@@ -75,6 +78,7 @@ class ForeignAPIFile extends File {
                        } else {
                                $img = new self( $title, $repo, $info, true );
                        }
+
                        return $img;
                } else {
                        return null;
@@ -86,7 +90,7 @@ class ForeignAPIFile extends File {
         * @return string
         */
        static function getProps() {
-               return 'timestamp|user|comment|url|size|sha1|metadata|mime|mediatype';
+               return 'timestamp|user|comment|url|size|sha1|metadata|mime|mediatype|extmetadata';
        }
 
        // Dummy functions...
@@ -130,6 +134,7 @@ class ForeignAPIFile extends File {
                );
                if ( $thumbUrl === false ) {
                        global $wgLang;
+
                        return $this->repo->getThumbError(
                                $this->getName(),
                                $width,
@@ -138,6 +143,7 @@ class ForeignAPIFile extends File {
                                $wgLang->getCode()
                        );
                }
+
                return $this->handler->getTransform( $this, 'bogus', $thumbUrl, $params );
        }
 
@@ -166,6 +172,18 @@ class ForeignAPIFile extends File {
                if ( isset( $this->mInfo['metadata'] ) ) {
                        return serialize( self::parseMetadata( $this->mInfo['metadata'] ) );
                }
+
+               return null;
+       }
+
+       /**
+        * @return array|null extended metadata (see imageinfo API for format) or null on error
+        */
+       public function getExtendedMetadata() {
+               if ( isset( $this->mInfo['extmetadata'] ) ) {
+                       return $this->mInfo['extmetadata'];
+               }
+
                return null;
        }
 
@@ -181,6 +199,7 @@ class ForeignAPIFile extends File {
                foreach ( $metadata as $meta ) {
                        $ret[$meta['name']] = self::parseMetadata( $meta['value'] );
                }
+
                return $ret;
        }
 
@@ -241,6 +260,7 @@ class ForeignAPIFile extends File {
                        $magic = MimeMagic::singleton();
                        $this->mInfo['mime'] = $magic->guessTypesForExtension( $this->getExtension() );
                }
+
                return $this->mInfo['mime'];
        }
 
@@ -252,6 +272,7 @@ class ForeignAPIFile extends File {
                        return $this->mInfo['mediatype'];
                }
                $magic = MimeMagic::singleton();
+
                return $magic->getMediaType( null, $this->getMimeType() );
        }
 
@@ -275,6 +296,7 @@ class ForeignAPIFile extends File {
                        if ( $suffix ) {
                                $path = $path . $suffix . '/';
                        }
+
                        return $path;
                } else {
                        return null;
index 01d6b0f..b7a5c35 100644 (file)
@@ -27,7 +27,6 @@
  * @ingroup FileAbstraction
  */
 class ForeignDBFile extends LocalFile {
-
        /**
         * @param $title
         * @param $repo
@@ -51,6 +50,7 @@ class ForeignDBFile extends LocalFile {
                $title = Title::makeTitle( NS_FILE, $row->img_name );
                $file = new self( $title, $repo );
                $file->loadFromRow( $row );
+
                return $file;
        }
 
index fe769be..c6ea79f 100644 (file)
@@ -210,6 +210,7 @@ class LocalFile extends File {
 
                if ( !$key ) {
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
 
@@ -236,6 +237,7 @@ class LocalFile extends File {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $this->dataLoaded;
        }
 
@@ -289,7 +291,8 @@ class LocalFile extends File {
         */
        function getCacheFields( $prefix = 'img_' ) {
                static $fields = array( 'size', 'width', 'height', 'bits', 'media_type',
-                       'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user', 'user_text', 'description' );
+                       'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user',
+                       'user_text', 'description' );
                static $results = array();
 
                if ( $prefix == '' ) {
@@ -407,6 +410,7 @@ class LocalFile extends File {
                foreach ( $array as $name => $value ) {
                        $decoded[substr( $name, $prefixLength )] = $value;
                }
+
                return $decoded;
        }
 
@@ -518,6 +522,7 @@ class LocalFile extends File {
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": file does not exist, aborting\n" );
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -526,6 +531,7 @@ class LocalFile extends File {
 
                if ( wfReadOnly() ) {
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
                wfDebug( __METHOD__ . ': upgrading ' . $this->getName() . " to the current schema\n" );
@@ -539,7 +545,7 @@ class LocalFile extends File {
                                'img_media_type' => $this->media_type,
                                'img_major_mime' => $major,
                                'img_minor_mime' => $minor,
-                               'img_metadata' => $dbw->encodeBlob($this->metadata),
+                               'img_metadata' => $dbw->encodeBlob( $this->metadata ),
                                'img_sha1' => $this->sha1,
                        ),
                        array( 'img_name' => $this->getName() ),
@@ -597,6 +603,7 @@ class LocalFile extends File {
                        list( $fileExists ) = $this->repo->fileExists( $this->getVirtualUrl() );
                        $this->missing = !$fileExists;
                }
+
                return $this->missing;
        }
 
@@ -684,6 +691,7 @@ class LocalFile extends File {
         */
        function getBitDepth() {
                $this->load();
+
                return $this->bits;
        }
 
@@ -693,6 +701,7 @@ class LocalFile extends File {
         */
        public function getSize() {
                $this->load();
+
                return $this->size;
        }
 
@@ -702,6 +711,7 @@ class LocalFile extends File {
         */
        function getMimeType() {
                $this->load();
+
                return $this->mime;
        }
 
@@ -712,6 +722,7 @@ class LocalFile extends File {
         */
        function getMediaType() {
                $this->load();
+
                return $this->media_type;
        }
 
@@ -727,6 +738,7 @@ class LocalFile extends File {
         */
        public function exists() {
                $this->load();
+
                return $this->fileExists;
        }
 
@@ -761,7 +773,6 @@ class LocalFile extends File {
                        clearstatcache();
                }
                */
-
                /*
                if ( $this->repo->fileExists( $thumbDir ) ) {
                        // Delete file where directory should be
@@ -793,7 +804,8 @@ class LocalFile extends File {
                        foreach ( $iterator as $file ) {
                                $files[] = $file;
                        }
-               } catch ( FileBackendError $e ) {} // suppress (bug 54674)
+               } catch ( FileBackendError $e ) {
+               } // suppress (bug 54674)
 
                return $files;
        }
@@ -982,11 +994,7 @@ class LocalFile extends File {
                $r = array();
 
                foreach ( $res as $row ) {
-                       if ( $this->repo->oldFileFromRowFactory ) {
-                               $r[] = call_user_func( $this->repo->oldFileFromRowFactory, $row, $this->repo );
-                       } else {
-                               $r[] = OldLocalFile::newFromRow( $row, $this->repo );
-                       }
+                       $r[] = $this->repo->newFileFromRow( $row );
                }
 
                if ( $order == 'ASC' ) {
@@ -1011,7 +1019,7 @@ class LocalFile extends File {
 
                $dbr = $this->repo->getSlaveDB();
 
-               if ( $this->historyLine == 0 ) {// called for the first time, return line from cur
+               if ( $this->historyLine == 0 ) { // called for the first time, return line from cur
                        $this->historyRes = $dbr->select( 'image',
                                array(
                                        '*',
@@ -1025,6 +1033,7 @@ class LocalFile extends File {
 
                        if ( 0 == $dbr->numRows( $this->historyRes ) ) {
                                $this->historyRes = null;
+
                                return false;
                        }
                } elseif ( $this->historyLine == 1 ) {
@@ -1034,7 +1043,7 @@ class LocalFile extends File {
                                array( 'ORDER BY' => 'oi_timestamp DESC' )
                        );
                }
-               $this->historyLine ++;
+               $this->historyLine++;
 
                return $dbr->fetchObject( $this->historyRes );
        }
@@ -1078,7 +1087,9 @@ class LocalFile extends File {
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) {
+       function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false,
+               $timestamp = false, $user = null
+       ) {
                global $wgContLang;
 
                if ( $this->getRepo()->getReadOnlyReason() !== false ) {
@@ -1088,8 +1099,8 @@ class LocalFile extends File {
                if ( !$props ) {
                        wfProfileIn( __METHOD__ . '-getProps' );
                        if ( $this->repo->isVirtualUrl( $srcPath )
-                               || FileBackend::isStoragePath( $srcPath ) )
-                       {
+                               || FileBackend::isStoragePath( $srcPath )
+                       {
                                $props = $this->repo->getFileProps( $srcPath );
                        } else {
                                $props = FSFile::getPropsFromPath( $srcPath );
@@ -1141,8 +1152,7 @@ class LocalFile extends File {
         * @return bool
         */
        function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
-               $watch = false, $timestamp = false, User $user = null )
-       {
+               $watch = false, $timestamp = false, User $user = null ) {
                if ( !$user ) {
                        global $wgUser;
                        $user = $wgUser;
@@ -1157,6 +1167,7 @@ class LocalFile extends File {
                if ( $watch ) {
                        $user->addWatch( $this->getTitle() );
                }
+
                return true;
        }
 
@@ -1203,6 +1214,7 @@ class LocalFile extends File {
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": File " . $this->getRel() . " went missing!\n" );
                        wfProfileOut( __METHOD__ );
+
                        return false;
                }
 
@@ -1225,7 +1237,7 @@ class LocalFile extends File {
                                'img_description' => $comment,
                                'img_user' => $user->getId(),
                                'img_user_text' => $user->getName(),
-                               'img_metadata' => $dbw->encodeBlob($this->metadata),
+                               'img_metadata' => $dbw->encodeBlob( $this->metadata ),
                                'img_sha1' => $this->sha1
                        ),
                        __METHOD__,
@@ -1242,21 +1254,21 @@ class LocalFile extends File {
                        # Insert previous contents into oldimage
                        $dbw->insertSelect( 'oldimage', 'image',
                                array(
-                                       'oi_name'         => 'img_name',
+                                       'oi_name' => 'img_name',
                                        'oi_archive_name' => $dbw->addQuotes( $oldver ),
-                                       'oi_size'         => 'img_size',
-                                       'oi_width'        => 'img_width',
-                                       'oi_height'       => 'img_height',
-                                       'oi_bits'         => 'img_bits',
-                                       'oi_timestamp'    => 'img_timestamp',
-                                       'oi_description'  => 'img_description',
-                                       'oi_user'         => 'img_user',
-                                       'oi_user_text'    => 'img_user_text',
-                                       'oi_metadata'     => 'img_metadata',
-                                       'oi_media_type'   => 'img_media_type',
-                                       'oi_major_mime'   => 'img_major_mime',
-                                       'oi_minor_mime'   => 'img_minor_mime',
-                                       'oi_sha1'         => 'img_sha1'
+                                       'oi_size' => 'img_size',
+                                       'oi_width' => 'img_width',
+                                       'oi_height' => 'img_height',
+                                       'oi_bits' => 'img_bits',
+                                       'oi_timestamp' => 'img_timestamp',
+                                       'oi_description' => 'img_description',
+                                       'oi_user' => 'img_user',
+                                       'oi_user_text' => 'img_user_text',
+                                       'oi_metadata' => 'img_metadata',
+                                       'oi_media_type' => 'img_media_type',
+                                       'oi_major_mime' => 'img_major_mime',
+                                       'oi_minor_mime' => 'img_minor_mime',
+                                       'oi_sha1' => 'img_sha1'
                                ),
                                array( 'img_name' => $this->getName() ),
                                __METHOD__
@@ -1265,19 +1277,19 @@ class LocalFile extends File {
                        # Update the current image row
                        $dbw->update( 'image',
                                array( /* SET */
-                                       'img_size'        => $this->size,
-                                       'img_width'       => intval( $this->width ),
-                                       'img_height'      => intval( $this->height ),
-                                       'img_bits'        => $this->bits,
-                                       'img_media_type'  => $this->media_type,
-                                       'img_major_mime'  => $this->major_mime,
-                                       'img_minor_mime'  => $this->minor_mime,
-                                       'img_timestamp'   => $timestamp,
+                                       'img_size' => $this->size,
+                                       'img_width' => intval( $this->width ),
+                                       'img_height' => intval( $this->height ),
+                                       'img_bits' => $this->bits,
+                                       'img_media_type' => $this->media_type,
+                                       'img_major_mime' => $this->major_mime,
+                                       'img_minor_mime' => $this->minor_mime,
+                                       'img_timestamp' => $timestamp,
                                        'img_description' => $comment,
-                                       'img_user'        => $user->getId(),
-                                       'img_user_text'   => $user->getName(),
-                                       'img_metadata'    => $dbw->encodeBlob($this->metadata),
-                                       'img_sha1'        => $this->sha1
+                                       'img_user' => $user->getId(),
+                                       'img_user_text' => $user->getName(),
+                                       'img_metadata' => $dbw->encodeBlob( $this->metadata ),
+                                       'img_sha1' => $this->sha1
                                ),
                                array( 'img_name' => $this->getName() ),
                                __METHOD__
@@ -1356,7 +1368,13 @@ class LocalFile extends File {
                        # There's already a log entry, so don't make a second RC entry
                        # Squid and file cache for the description page are purged by doEditContent.
                        $content = ContentHandler::makeContent( $pageText, $descTitle );
-                       $status = $wikiPage->doEditContent( $content, $comment, EDIT_NEW | EDIT_SUPPRESS_RC, false, $user );
+                       $status = $wikiPage->doEditContent(
+                               $content,
+                               $comment,
+                               EDIT_NEW | EDIT_SUPPRESS_RC,
+                               false,
+                               $user
+                       );
 
                        $dbw->begin( __METHOD__ ); // XXX; doEdit() uses a transaction
                        // Now that the page exists, make an RC entry.
@@ -1371,7 +1389,6 @@ class LocalFile extends File {
                        $dbw->commit( __METHOD__ ); // commit before anything bad can happen
                }
 
-
                wfProfileOut( __METHOD__ . '-edit' );
 
                # Save to cache and purge the squid
@@ -1414,6 +1431,7 @@ class LocalFile extends File {
                }
 
                wfProfileOut( __METHOD__ );
+
                return true;
        }
 
@@ -1427,7 +1445,7 @@ class LocalFile extends File {
         *
         * @param string $srcPath local filesystem path to the source image
         * @param $flags Integer: a bitwise combination of:
-        *     File::DELETE_SOURCE      Delete the source file, i.e. move rather than copy
+        *     File::DELETE_SOURCE    Delete the source file, i.e. move rather than copy
         * @param array $options Optional additional parameters
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
@@ -1446,7 +1464,7 @@ class LocalFile extends File {
         * @param string $srcPath local filesystem path to the source image
         * @param string $dstRel target relative path
         * @param $flags Integer: a bitwise combination of:
-        *     File::DELETE_SOURCE      Delete the source file, i.e. move rather than copy
+        *     File::DELETE_SOURCE    Delete the source file, i.e. move rather than copy
         * @param array $options Optional additional parameters
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
@@ -1513,7 +1531,7 @@ class LocalFile extends File {
                // Hack: the lock()/unlock() pair is nested in a transaction so the locking is not
                // tied to BEGIN/COMMIT. To avoid slow purges in the transaction, move them outside.
                $this->getRepo()->getMasterDB()->onTransactionIdle(
-                       function() use ( $oldTitleFile, $newTitleFile, $archiveNames ) {
+                       function () use ( $oldTitleFile, $newTitleFile, $archiveNames ) {
                                $oldTitleFile->purgeEverything();
                                foreach ( $archiveNames as $archiveName ) {
                                        $oldTitleFile->purgeOldThumbnails( $archiveName );
@@ -1567,7 +1585,7 @@ class LocalFile extends File {
                // tied to BEGIN/COMMIT. To avoid slow purges in the transaction, move them outside.
                $file = $this;
                $this->getRepo()->getMasterDB()->onTransactionIdle(
-                       function() use ( $file, $archiveNames ) {
+                       function () use ( $file, $archiveNames ) {
                                global $wgUseSquid;
 
                                $file->purgeEverything();
@@ -1697,6 +1715,7 @@ class LocalFile extends File {
                        return false;
                }
                $pout = $content->getParserOutput( $this->title, null, new ParserOptions( null, $lang ) );
+
                return $pout->getText();
        }
 
@@ -1708,8 +1727,8 @@ class LocalFile extends File {
                if ( $audience == self::FOR_PUBLIC && $this->isDeleted( self::DELETED_COMMENT ) ) {
                        return '';
                } elseif ( $audience == self::FOR_THIS_USER
-                       && !$this->userCan( self::DELETED_COMMENT, $user ) )
-               {
+                       && !$this->userCan( self::DELETED_COMMENT, $user )
+               {
                        return '';
                } else {
                        return $this->description;
@@ -1721,6 +1740,7 @@ class LocalFile extends File {
         */
        function getTimestamp() {
                $this->load();
+
                return $this->timestamp;
        }
 
@@ -1754,9 +1774,10 @@ class LocalFile extends File {
         */
        function isCacheable() {
                $this->load();
+
                // If extra data (metadata) was not loaded then it must have been large
                return $this->extraDataLoaded
-                       && strlen( serialize( $this->metadata ) ) <= self::CACHE_FIELD_MAX_LEN;
+               && strlen( serialize( $this->metadata ) ) <= self::CACHE_FIELD_MAX_LEN;
        }
 
        /**
@@ -1780,7 +1801,7 @@ class LocalFile extends File {
                        if ( !$cache->lock( $key, 60 ) ) {
                                throw new MWException( "Could not acquire lock for '{$this->getName()}.'" );
                        }
-                       $dbw->onTransactionIdle( function() use ( $cache, $key ) {
+                       $dbw->onTransactionIdle( function () use ( $cache, $key ) {
                                $cache->unlock( $key ); // release on commit
                        } );
                }
@@ -1990,27 +2011,27 @@ class LocalFileDeleteBatch {
                        $dbw->insertSelect( 'filearchive', 'image',
                                array(
                                        'fa_storage_group' => $encGroup,
-                                       'fa_storage_key'   => "CASE WHEN img_sha1='' THEN '' ELSE $concat END",
-                                       'fa_deleted_user'      => $encUserId,
+                                       'fa_storage_key' => "CASE WHEN img_sha1='' THEN '' ELSE $concat END",
+                                       'fa_deleted_user' => $encUserId,
                                        'fa_deleted_timestamp' => $encTimestamp,
-                                       'fa_deleted_reason'    => $encReason,
-                                       'fa_deleted'           => $this->suppress ? $bitfield : 0,
+                                       'fa_deleted_reason' => $encReason,
+                                       'fa_deleted' => $this->suppress ? $bitfield : 0,
 
-                                       'fa_name'         => 'img_name',
+                                       'fa_name' => 'img_name',
                                        'fa_archive_name' => 'NULL',
-                                       'fa_size'         => 'img_size',
-                                       'fa_width'        => 'img_width',
-                                       'fa_height'       => 'img_height',
-                                       'fa_metadata'     => 'img_metadata',
-                                       'fa_bits'         => 'img_bits',
-                                       'fa_media_type'   => 'img_media_type',
-                                       'fa_major_mime'   => 'img_major_mime',
-                                       'fa_minor_mime'   => 'img_minor_mime',
-                                       'fa_description'  => 'img_description',
-                                       'fa_user'         => 'img_user',
-                                       'fa_user_text'    => 'img_user_text',
-                                       'fa_timestamp'    => 'img_timestamp',
-                                       'fa_sha1'         => 'img_sha1',
+                                       'fa_size' => 'img_size',
+                                       'fa_width' => 'img_width',
+                                       'fa_height' => 'img_height',
+                                       'fa_metadata' => 'img_metadata',
+                                       'fa_bits' => 'img_bits',
+                                       'fa_media_type' => 'img_media_type',
+                                       'fa_major_mime' => 'img_major_mime',
+                                       'fa_minor_mime' => 'img_minor_mime',
+                                       'fa_description' => 'img_description',
+                                       'fa_user' => 'img_user',
+                                       'fa_user_text' => 'img_user_text',
+                                       'fa_timestamp' => 'img_timestamp',
+                                       'fa_sha1' => 'img_sha1',
                                ), $where, __METHOD__ );
                }
 
@@ -2022,27 +2043,27 @@ class LocalFileDeleteBatch {
                        $dbw->insertSelect( 'filearchive', 'oldimage',
                                array(
                                        'fa_storage_group' => $encGroup,
-                                       'fa_storage_key'   => "CASE WHEN oi_sha1='' THEN '' ELSE $concat END",
-                                       'fa_deleted_user'      => $encUserId,
+                                       'fa_storage_key' => "CASE WHEN oi_sha1='' THEN '' ELSE $concat END",
+                                       'fa_deleted_user' => $encUserId,
                                        'fa_deleted_timestamp' => $encTimestamp,
-                                       'fa_deleted_reason'    => $encReason,
-                                       'fa_deleted'           => $this->suppress ? $bitfield : 'oi_deleted',
+                                       'fa_deleted_reason' => $encReason,
+                                       'fa_deleted' => $this->suppress ? $bitfield : 'oi_deleted',
 
-                                       'fa_name'         => 'oi_name',
+                                       'fa_name' => 'oi_name',
                                        'fa_archive_name' => 'oi_archive_name',
-                                       'fa_size'         => 'oi_size',
-                                       'fa_width'        => 'oi_width',
-                                       'fa_height'       => 'oi_height',
-                                       'fa_metadata'     => 'oi_metadata',
-                                       'fa_bits'         => 'oi_bits',
-                                       'fa_media_type'   => 'oi_media_type',
-                                       'fa_major_mime'   => 'oi_major_mime',
-                                       'fa_minor_mime'   => 'oi_minor_mime',
-                                       'fa_description'  => 'oi_description',
-                                       'fa_user'         => 'oi_user',
-                                       'fa_user_text'    => 'oi_user_text',
-                                       'fa_timestamp'    => 'oi_timestamp',
-                                       'fa_sha1'         => 'oi_sha1',
+                                       'fa_size' => 'oi_size',
+                                       'fa_width' => 'oi_width',
+                                       'fa_height' => 'oi_height',
+                                       'fa_metadata' => 'oi_metadata',
+                                       'fa_bits' => 'oi_bits',
+                                       'fa_media_type' => 'oi_media_type',
+                                       'fa_major_mime' => 'oi_major_mime',
+                                       'fa_minor_mime' => 'oi_minor_mime',
+                                       'fa_description' => 'oi_description',
+                                       'fa_user' => 'oi_user',
+                                       'fa_user_text' => 'oi_user_text',
+                                       'fa_timestamp' => 'oi_timestamp',
+                                       'fa_sha1' => 'oi_sha1',
                                ), $where, __METHOD__ );
                }
        }
@@ -2130,6 +2151,7 @@ class LocalFileDeleteBatch {
                        // TODO: delete the defunct filearchive rows if we are using a non-transactional DB
                        $this->file->unlockAndRollback();
                        wfProfileOut( __METHOD__ );
+
                        return $this->status;
                }
 
@@ -2274,7 +2296,8 @@ class LocalFileRestoreBatch {
                                continue;
                        }
 
-                       $deletedRel = $this->file->repo->getDeletedHashPath( $row->fa_storage_key ) . $row->fa_storage_key;
+                       $deletedRel = $this->file->repo->getDeletedHashPath( $row->fa_storage_key ) .
+                               $row->fa_storage_key;
                        $deletedUrl = $this->file->repo->getVirtualUrl() . '/deleted/' . $deletedRel;
 
                        if ( isset( $row->fa_sha1 ) ) {
@@ -2292,7 +2315,8 @@ class LocalFileRestoreBatch {
                        if ( is_null( $row->fa_major_mime ) || $row->fa_major_mime == 'unknown'
                                || is_null( $row->fa_minor_mime ) || $row->fa_minor_mime == 'unknown'
                                || is_null( $row->fa_media_type ) || $row->fa_media_type == 'UNKNOWN'
-                               || is_null( $row->fa_metadata ) ) {
+                               || is_null( $row->fa_metadata )
+                       ) {
                                // Refresh our metadata
                                // Required for a new current revision; nice for older ones too. :)
                                $props = RepoGroup::singleton()->getFileProps( $deletedUrl );
@@ -2301,7 +2325,7 @@ class LocalFileRestoreBatch {
                                        'minor_mime' => $row->fa_minor_mime,
                                        'major_mime' => $row->fa_major_mime,
                                        'media_type' => $row->fa_media_type,
-                                       'metadata'   => $row->fa_metadata
+                                       'metadata' => $row->fa_metadata
                                );
                        }
 
@@ -2309,20 +2333,20 @@ class LocalFileRestoreBatch {
                                // This revision will be published as the new current version
                                $destRel = $this->file->getRel();
                                $insertCurrent = array(
-                                       'img_name'        => $row->fa_name,
-                                       'img_size'        => $row->fa_size,
-                                       'img_width'       => $row->fa_width,
-                                       'img_height'      => $row->fa_height,
-                                       'img_metadata'    => $props['metadata'],
-                                       'img_bits'        => $row->fa_bits,
-                                       'img_media_type'  => $props['media_type'],
-                                       'img_major_mime'  => $props['major_mime'],
-                                       'img_minor_mime'  => $props['minor_mime'],
+                                       'img_name' => $row->fa_name,
+                                       'img_size' => $row->fa_size,
+                                       'img_width' => $row->fa_width,
+                                       'img_height' => $row->fa_height,
+                                       'img_metadata' => $props['metadata'],
+                                       'img_bits' => $row->fa_bits,
+                                       'img_media_type' => $props['media_type'],
+                                       'img_major_mime' => $props['major_mime'],
+                                       'img_minor_mime' => $props['minor_mime'],
                                        'img_description' => $row->fa_description,
-                                       'img_user'        => $row->fa_user,
-                                       'img_user_text'   => $row->fa_user_text,
-                                       'img_timestamp'   => $row->fa_timestamp,
-                                       'img_sha1'        => $sha1
+                                       'img_user' => $row->fa_user,
+                                       'img_user_text' => $row->fa_user_text,
+                                       'img_timestamp' => $row->fa_timestamp,
+                                       'img_sha1' => $sha1
                                );
 
                                // The live (current) version cannot be hidden!
@@ -2348,22 +2372,22 @@ class LocalFileRestoreBatch {
                                $archiveNames[$archiveName] = true;
                                $destRel = $this->file->getArchiveRel( $archiveName );
                                $insertBatch[] = array(
-                                       'oi_name'         => $row->fa_name,
+                                       'oi_name' => $row->fa_name,
                                        'oi_archive_name' => $archiveName,
-                                       'oi_size'         => $row->fa_size,
-                                       'oi_width'        => $row->fa_width,
-                                       'oi_height'       => $row->fa_height,
-                                       'oi_bits'         => $row->fa_bits,
-                                       'oi_description'  => $row->fa_description,
-                                       'oi_user'         => $row->fa_user,
-                                       'oi_user_text'    => $row->fa_user_text,
-                                       'oi_timestamp'    => $row->fa_timestamp,
-                                       'oi_metadata'     => $props['metadata'],
-                                       'oi_media_type'   => $props['media_type'],
-                                       'oi_major_mime'   => $props['major_mime'],
-                                       'oi_minor_mime'   => $props['minor_mime'],
-                                       'oi_deleted'      => $this->unsuppress ? 0 : $row->fa_deleted,
-                                       'oi_sha1'         => $sha1 );
+                                       'oi_size' => $row->fa_size,
+                                       'oi_width' => $row->fa_width,
+                                       'oi_height' => $row->fa_height,
+                                       'oi_bits' => $row->fa_bits,
+                                       'oi_description' => $row->fa_description,
+                                       'oi_user' => $row->fa_user,
+                                       'oi_user_text' => $row->fa_user_text,
+                                       'oi_timestamp' => $row->fa_timestamp,
+                                       'oi_metadata' => $props['metadata'],
+                                       'oi_media_type' => $props['media_type'],
+                                       'oi_major_mime' => $props['major_mime'],
+                                       'oi_minor_mime' => $props['minor_mime'],
+                                       'oi_deleted' => $this->unsuppress ? 0 : $row->fa_deleted,
+                                       'oi_sha1' => $sha1 );
                        }
 
                        $deleteIds[] = $row->fa_id;
@@ -2650,21 +2674,25 @@ class LocalFileMoveBatch {
                if ( !$statusDb->isGood() ) {
                        $this->file->unlockAndRollback();
                        $statusDb->ok = false;
+
                        return $statusDb;
                }
-               wfDebugLog( 'imagemove', "Renamed {$this->file->getName()} in database: {$statusDb->successCount} successes, {$statusDb->failCount} failures" );
+               wfDebugLog( 'imagemove', "Renamed {$this->file->getName()} in database: " .
+                       "{$statusDb->successCount} successes, {$statusDb->failCount} failures" );
 
                // Copy the files into their new location.
                // If a prior process fataled copying or cleaning up files we tolerate any
                // of the existing files if they are identical to the ones being stored.
                $statusMove = $repo->storeBatch( $triplets, FileRepo::OVERWRITE_SAME );
-               wfDebugLog( 'imagemove', "Moved files for {$this->file->getName()}: {$statusMove->successCount} successes, {$statusMove->failCount} failures" );
+               wfDebugLog( 'imagemove', "Moved files for {$this->file->getName()}: " .
+                       "{$statusMove->successCount} successes, {$statusMove->failCount} failures" );
                if ( !$statusMove->isGood() ) {
                        // Delete any files copied over (while the destination is still locked)
                        $this->cleanupTarget( $triplets );
                        $this->file->unlockAndRollback(); // unlocks the destination
                        wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
                        $statusMove->ok = false;
+
                        return $statusMove;
                }
                $this->file->unlock(); // done
@@ -2702,6 +2730,7 @@ class LocalFileMoveBatch {
                } else {
                        $status->failCount++;
                        $status->fatal( 'imageinvalidfilename' );
+
                        return $status;
                }
 
@@ -2743,7 +2772,10 @@ class LocalFileMoveBatch {
                        // $move: (oldRelativePath, newRelativePath)
                        $srcUrl = $this->file->repo->getVirtualUrl() . '/public/' . rawurlencode( $move[0] );
                        $triplets[] = array( $srcUrl, 'public', $move[1] );
-                       wfDebugLog( 'imagemove', "Generated move triplet for {$this->file->getName()}: {$srcUrl} :: public :: {$move[1]}" );
+                       wfDebugLog(
+                               'imagemove',
+                               "Generated move triplet for {$this->file->getName()}: {$srcUrl} :: public :: {$move[1]}"
+                       );
                }
 
                return $triplets;
index 2c54596..ae4ad1c 100644 (file)
  * @ingroup FileAbstraction
  */
 class OldLocalFile extends LocalFile {
-       var $requestedTime, $archive_name;
+       /** @var string Timestamp */
+       protected $requestedTime;
+
+       /** @var string Archive name */
+       protected $archive_name;
 
        const CACHE_VERSION = 1;
        const MAX_CACHE_ROWS = 20;
@@ -44,6 +48,7 @@ class OldLocalFile extends LocalFile {
                if ( $time === null ) {
                        throw new MWException( __METHOD__ . ' got null for $time parameter' );
                }
+
                return new self( $title, $repo, $time, null );
        }
 
@@ -66,6 +71,7 @@ class OldLocalFile extends LocalFile {
                $title = Title::makeTitle( NS_FILE, $row->oi_name );
                $file = new self( $title, $repo, null, $row->oi_archive_name );
                $file->loadFromRow( $row, 'oi_' );
+
                return $file;
        }
 
@@ -150,6 +156,7 @@ class OldLocalFile extends LocalFile {
                if ( !isset( $this->archive_name ) ) {
                        $this->load();
                }
+
                return $this->archive_name;
        }
 
@@ -233,6 +240,7 @@ class OldLocalFile extends LocalFile {
                $fields = parent::getCacheFields( $prefix );
                $fields[] = $prefix . 'archive_name';
                $fields[] = $prefix . 'deleted';
+
                return $fields;
        }
 
@@ -258,6 +266,7 @@ class OldLocalFile extends LocalFile {
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": file does not exist, aborting\n" );
                        wfProfileOut( __METHOD__ );
+
                        return;
                }
 
@@ -267,15 +276,15 @@ class OldLocalFile extends LocalFile {
                wfDebug( __METHOD__ . ': upgrading ' . $this->archive_name . " to the current schema\n" );
                $dbw->update( 'oldimage',
                        array(
-                               'oi_size'       => $this->size, // sanity
-                               'oi_width'      => $this->width,
-                               'oi_height'     => $this->height,
-                               'oi_bits'       => $this->bits,
+                               'oi_size' => $this->size, // sanity
+                               'oi_width' => $this->width,
+                               'oi_height' => $this->height,
+                               'oi_bits' => $this->bits,
                                'oi_media_type' => $this->media_type,
                                'oi_major_mime' => $major,
                                'oi_minor_mime' => $minor,
-                               'oi_metadata'   => $this->metadata,
-                               'oi_sha1'       => $this->sha1,
+                               'oi_metadata' => $this->metadata,
+                               'oi_sha1' => $this->sha1,
                        ), array(
                                'oi_name' => $this->getName(),
                                'oi_archive_name' => $this->archive_name ),
@@ -291,6 +300,7 @@ class OldLocalFile extends LocalFile {
         */
        function isDeleted( $field ) {
                $this->load();
+
                return ( $this->deleted & $field ) == $field;
        }
 
@@ -300,6 +310,7 @@ class OldLocalFile extends LocalFile {
         */
        function getVisibility() {
                $this->load();
+
                return (int)$this->deleted;
        }
 
@@ -313,6 +324,7 @@ class OldLocalFile extends LocalFile {
         */
        function userCan( $field, User $user = null ) {
                $this->load();
+
                return Revision::userCanBitfield( $this->deleted, $field, $user );
        }
 
@@ -370,21 +382,21 @@ class OldLocalFile extends LocalFile {
 
                $dbw->insert( 'oldimage',
                        array(
-                               'oi_name'         => $this->getName(),
+                               'oi_name' => $this->getName(),
                                'oi_archive_name' => $archiveName,
-                               'oi_size'         => $props['size'],
-                               'oi_width'        => intval( $props['width'] ),
-                               'oi_height'       => intval( $props['height'] ),
-                               'oi_bits'         => $props['bits'],
-                               'oi_timestamp'    => $dbw->timestamp( $timestamp ),
-                               'oi_description'  => $comment,
-                               'oi_user'         => $user->getId(),
-                               'oi_user_text'    => $user->getName(),
-                               'oi_metadata'     => $props['metadata'],
-                               'oi_media_type'   => $props['media_type'],
-                               'oi_major_mime'   => $props['major_mime'],
-                               'oi_minor_mime'   => $props['minor_mime'],
-                               'oi_sha1'         => $props['sha1'],
+                               'oi_size' => $props['size'],
+                               'oi_width' => intval( $props['width'] ),
+                               'oi_height' => intval( $props['height'] ),
+                               'oi_bits' => $props['bits'],
+                               'oi_timestamp' => $dbw->timestamp( $timestamp ),
+                               'oi_description' => $comment,
+                               'oi_user' => $user->getId(),
+                               'oi_user_text' => $user->getName(),
+                               'oi_metadata' => $props['metadata'],
+                               'oi_media_type' => $props['media_type'],
+                               'oi_major_mime' => $props['major_mime'],
+                               'oi_minor_mime' => $props['minor_mime'],
+                               'oi_sha1' => $props['sha1'],
                        ), __METHOD__
                );
 
@@ -392,5 +404,4 @@ class OldLocalFile extends LocalFile {
 
                return true;
        }
-
 }
index 47ba6d6..e7fa46e 100644 (file)
@@ -71,7 +71,8 @@ class UnregisteredLocalFile extends File {
         */
        function __construct( $title = false, $repo = false, $path = false, $mime = false ) {
                if ( !( $title && $repo ) && !$path ) {
-                       throw new MWException( __METHOD__ . ': not enough parameters, must specify title and repo, or a full path' );
+                       throw new MWException( __METHOD__ .
+                               ': not enough parameters, must specify title and repo, or a full path' );
                }
                if ( $title instanceof Title ) {
                        $this->title = File::normalizeTitle( $title, 'exception' );
@@ -105,6 +106,7 @@ class UnregisteredLocalFile extends File {
                        }
                        $this->dims[$page] = $this->handler->getPageDimensions( $this, $page );
                }
+
                return $this->dims[$page];
        }
 
@@ -114,6 +116,7 @@ class UnregisteredLocalFile extends File {
         */
        function getWidth( $page = 1 ) {
                $dim = $this->cachePageDimensions( $page );
+
                return $dim['width'];
        }
 
@@ -123,6 +126,7 @@ class UnregisteredLocalFile extends File {
         */
        function getHeight( $page = 1 ) {
                $dim = $this->cachePageDimensions( $page );
+
                return $dim['height'];
        }
 
@@ -134,6 +138,7 @@ class UnregisteredLocalFile extends File {
                        $magic = MimeMagic::singleton();
                        $this->mime = $magic->guessMimeType( $this->getLocalRefPath() );
                }
+
                return $this->mime;
        }
 
@@ -145,6 +150,7 @@ class UnregisteredLocalFile extends File {
                if ( !$this->getHandler() ) {
                        return false;
                }
+
                return $this->handler->getImageSize( $this, $this->getLocalRefPath() );
        }
 
@@ -159,6 +165,7 @@ class UnregisteredLocalFile extends File {
                                $this->metadata = $this->handler->getMetadata( $this, $this->getLocalRefPath() );
                        }
                }
+
                return $this->metadata;
        }
 
@@ -179,6 +186,7 @@ class UnregisteredLocalFile extends File {
         */
        function getSize() {
                $this->assertRepoDefined();
+
                return $this->repo->getFileSize( $this->path );
        }
 
index f8b8c50..a341601 100644 (file)
  * @ingroup Media
  */
 abstract class ImageGalleryBase extends ContextSource {
-       var $mImages, $mShowBytes, $mShowFilename, $mMode;
-       var $mCaption = false;
+       /** @var array Gallery images  */
+       protected $mImages;
+
+       /** @var bool Whether to show the filesize in bytes in categories   */
+       protected $mShowBytes;
+
+       /** @var bool Whether to show the filename. Default: true */
+       protected $mShowFilename;
+
+       /** @var string Gallery mode. Default: traditional */
+       protected $mMode;
+
+       /** @var bool|string Gallery caption. Default: false */
+       protected $mCaption = false;
 
        /**
-        * Hide blacklisted images?
+        * @var bool Hide blacklisted images?
         */
-       var $mHideBadImages;
+       protected $mHideBadImages;
 
        /**
-        * Registered parser object for output callbacks
-        * @var Parser
+        * @var Parser Registered parser object for output callbacks
         */
-       var $mParser;
+       protected $mParser;
 
        /**
-        * Contextual title, used when images are being screened
-        * against the bad image list
+        * @var Title Contextual title, used when images are being screened against
+        *   the bad image list
         */
        protected $contextTitle = false;
 
+       /** @var array */
        protected $mAttribs = array();
 
+       /** @var bool */
        static private $modeMapping = false;
 
        /**
         * Get a new image gallery. This is the method other callers
         * should use to get a gallery.
         *
-        * @param String|bool $mode Mode to use. False to use the default.
+        * @param string|bool $mode Mode to use. False to use the default.
+        * @throws MWException
         */
        static function factory( $mode = false ) {
                global $wgGalleryOptions, $wgContLang;
@@ -74,7 +88,7 @@ abstract class ImageGalleryBase extends ContextSource {
                }
        }
 
-       static private function loadModes() {
+       private static function loadModes() {
                if ( self::$modeMapping === false ) {
                        self::$modeMapping = array(
                                'traditional' => 'TraditionalImageGallery',
@@ -150,8 +164,8 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Set how many images will be displayed per row.
         *
-        * @param $num Integer >= 0; If perrow=0 the gallery layout will adapt to screensize
-        * invalid numbers will be rejected
+        * @param int $num Integer >= 0; If perrow=0 the gallery layout will adapt
+        *   to screensize invalid numbers will be rejected
         */
        public function setPerRow( $num ) {
                if ( $num >= 0 ) {
@@ -162,7 +176,7 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Set how wide each image will be, in pixels.
         *
-        * @param $num Integer > 0; invalid numbers will be ignored
+        * @param int $num Integer > 0; invalid numbers will be ignored
         */
        public function setWidths( $num ) {
                if ( $num > 0 ) {
@@ -173,7 +187,7 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Set how high each image will be, in pixels.
         *
-        * @param $num Integer > 0; invalid numbers will be ignored
+        * @param int $num Integer > 0; invalid numbers will be ignored
         */
        public function setHeights( $num ) {
                if ( $num > 0 ) {
@@ -186,14 +200,15 @@ abstract class ImageGalleryBase extends ContextSource {
         * to allow extensions to add additional parameters to
         * <gallery> parser tag.
         *
-        * @param Array $options Attributes of gallery tag.
+        * @param array $options Attributes of gallery tag.
         */
-       public function setAdditionalOptions( $options ) { }
+       public function setAdditionalOptions( $options ) {
+       }
 
        /**
         * Instruct the class to use a specific skin for rendering
         *
-        * @param $skin Skin object
+        * @param Skin $skin
         * @deprecated since 1.18 Not used anymore
         */
        function useSkin( $skin ) {
@@ -204,11 +219,12 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Add an image to the gallery.
         *
-        * @param $title Title object of the image that is added to the gallery
-        * @param $html  String: Additional HTML text to be shown. The name and size of the image are always shown.
-        * @param $alt   String: Alt text for the image
-        * @param $link  String: Override image link (optional)
-        * @param $handlerOpts Array: Array of options for image handler (aka page number)
+        * @param Title $title Title object of the image that is added to the gallery
+        * @param string $html Additional HTML text to be shown. The name and size
+        *   of the image are always shown.
+        * @param string $alt Alt text for the image
+        * @param string $link Override image link (optional)
+        * @param array $handlerOpts Array of options for image handler (aka page number)
         */
        function add( $title, $html = '', $alt = '', $link = '', $handlerOpts = array() ) {
                if ( $title instanceof File ) {
@@ -222,11 +238,12 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Add an image at the beginning of the gallery.
         *
-        * @param $title Title object of the image that is added to the gallery
-        * @param $html  String: Additional HTML text to be shown. The name and size of the image are always shown.
-        * @param $alt   String: Alt text for the image
-        * @param $link  String: Override image link (optional)
-        * @param $handlerOpts Array: Array of options for image handler (aka page number)
+        * @param Title $title Title object of the image that is added to the gallery
+        * @param string $html Additional HTML text to be shown. The name and size
+        *   of the image are always shown.
+        * @param string $alt Alt text for the image
+        * @param string $link  Override image link (optional)
+        * @param array $handlerOpts Array of options for image handler (aka page number)
         */
        function insert( $title, $html = '', $alt = '', $link = '', $handlerOpts = array() ) {
                if ( $title instanceof File ) {
@@ -248,7 +265,7 @@ abstract class ImageGalleryBase extends ContextSource {
         * Enable/Disable showing of the file size of an image in the gallery.
         * Enabled by default.
         *
-        * @param $f Boolean: set to false to disable.
+        * @param bool $f Set to false to disable.
         */
        function setShowBytes( $f ) {
                $this->mShowBytes = (bool)$f;
@@ -258,7 +275,7 @@ abstract class ImageGalleryBase extends ContextSource {
         * Enable/Disable showing of the filename of an image in the gallery.
         * Enabled by default.
         *
-        * @param $f Boolean: set to false to disable.
+        * @param bool $f Set to false to disable.
         */
        function setShowFilename( $f ) {
                $this->mShowFilename = (bool)$f;
@@ -271,7 +288,7 @@ abstract class ImageGalleryBase extends ContextSource {
         * Note -- if taking from user input, you should probably run through
         * Sanitizer::validateAttributes() first.
         *
-        * @param array $attribs of HTML attribute pairs
+        * @param array $attribs Array of HTML attribute pairs
         */
        function setAttributes( $attribs ) {
                $this->mAttribs = $attribs;
@@ -280,12 +297,12 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Display an html representation of the gallery
         *
-        * @return String The html
+        * @return string The html
         */
        abstract public function toHTML();
 
        /**
-        * @return Integer: number of images in the gallery
+        * @return int Number of images in the gallery
         */
        public function count() {
                return count( $this->mImages );
@@ -294,7 +311,7 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Set the contextual title
         *
-        * @param $title Title: contextual title
+        * @param Title $title Contextual title
         */
        public function setContextTitle( $title ) {
                $this->contextTitle = $title;
@@ -303,7 +320,7 @@ abstract class ImageGalleryBase extends ContextSource {
        /**
         * Get the contextual title, if applicable
         *
-        * @return mixed Title or false
+        * @return Title|bool Title or false
         */
        public function getContextTitle() {
                return is_object( $this->contextTitle ) && $this->contextTitle instanceof Title
@@ -313,19 +330,11 @@ abstract class ImageGalleryBase extends ContextSource {
 
        /**
         * Determines the correct language to be used for this image gallery
-        * @return Language object
+        * @return Language
         */
        protected function getRenderLang() {
                return $this->mParser
                        ? $this->mParser->getTargetLanguage()
                        : $this->getLanguage();
        }
-
-       /* Old constants no longer used.
-       const THUMB_PADDING = 30;
-       const GB_PADDING = 5;
-       const GB_BORDERS = 8;
-       */
-
 }
-
index 6b0d0fa..70f5bd9 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 class NolinesImageGallery extends TraditionalImageGallery {
-
        protected function getThumbPadding() {
                return 0;
        }
index 963ee6b..bb55c89 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 class PackedImageGallery extends TraditionalImageGallery {
-
        function __construct( $mode = 'traditional' ) {
                parent::__construct( $mode );
                // Does not support per row option.
@@ -49,6 +48,7 @@ class PackedImageGallery extends TraditionalImageGallery {
 
        /**
         * @param File $img The file being transformed. May be false
+        * @return array
         */
        protected function getThumbParams( $img ) {
                if ( $img && $img->getMediaType() === MEDIATYPE_AUDIO ) {
@@ -58,6 +58,7 @@ class PackedImageGallery extends TraditionalImageGallery {
                        // factor, so use random big number.
                        $width = $this->mHeights * 10 + 100;
                }
+
                // self::SCALE_FACTOR so the js has some room to manipulate sizes.
                return array(
                        'width' => $width * self::SCALE_FACTOR,
@@ -70,14 +71,18 @@ class PackedImageGallery extends TraditionalImageGallery {
                if ( $thumbWidth < 60 * self::SCALE_FACTOR ) {
                        $thumbWidth = 60 * self::SCALE_FACTOR;
                }
+
                return $thumbWidth / self::SCALE_FACTOR + $this->getThumbPadding();
        }
 
        /**
-        * @param MediaTransformOutput|bool $thumb the thumbnail, or false if no thumb (which can happen)
+        * @param MediaTransformOutput|bool $thumb the thumbnail, or false if no
+        *   thumb (which can happen)
+        * @return float
         */
        protected function getGBWidth( $thumb ) {
                $thumbWidth = $thumb ? $thumb->getWidth() : $this->mWidths * self::SCALE_FACTOR;
+
                return $this->getThumbDivWidth( $thumbWidth ) + $this->getGBPadding();
        }
 
index bba06fc..f9c131f 100644 (file)
  */
 
 class PackedOverlayImageGallery extends PackedImageGallery {
-
        /**
         * Add the wrapper html around the thumb's caption
         *
-        * @param String $galleryText The caption
-        * @param MediaTransformOutput|boolean $thumb The thumb this caption is for or false for bad image.
+        * @param string $galleryText The caption
+        * @param MediaTransformOutput|bool $thumb The thumb this caption is for
+        *   or false for bad image.
+        * @return string
         */
        protected function wrapGalleryText( $galleryText, $thumb ) {
 
@@ -37,17 +38,19 @@ class PackedOverlayImageGallery extends PackedImageGallery {
                        return '';
                }
 
-               # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which
-               # in version 4.8.6 generated crackpot html in its absence, see:
-               # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar
+               # ATTENTION: The newline after <div class="gallerytext"> is needed to
+               # accommodate htmltidy which in version 4.8.6 generated crackpot HTML
+               # in its absence, see: http://bugzilla.wikimedia.org/show_bug.cgi?id=1765
+               # -Ævar
 
                $thumbWidth = $this->getGBWidth( $thumb ) - $this->getThumbPadding() - $this->getGBPadding();
                $captionWidth = ceil( $thumbWidth - 20 );
 
                $outerWrapper = '<div class="gallerytextwrapper" style="width: ' . $captionWidth . 'px">';
+
                return "\n\t\t\t" . $outerWrapper . '<div class="gallerytext">' . "\n"
-                                       . $galleryText
-                                       . "\n\t\t\t</div>";
+                       . $galleryText
+                       . "\n\t\t\t</div>";
        }
 }
 
@@ -57,4 +60,5 @@ class PackedOverlayImageGallery extends PackedImageGallery {
  * falls back to PackedHoverGallery. Degrades gracefully for
  * screen readers.
  */
-class PackedHoverImageGallery extends PackedOverlayImageGallery { }
+class PackedHoverImageGallery extends PackedOverlayImageGallery {
+}
index 1f60fa6..cfedac7 100644 (file)
@@ -21,8 +21,6 @@
  */
 
 class TraditionalImageGallery extends ImageGalleryBase {
-
-
        /**
         * Return a HTML representation of the image gallery
         *
@@ -38,8 +36,10 @@ class TraditionalImageGallery extends ImageGalleryBase {
                if ( $this->mPerRow > 0 ) {
                        $maxwidth = $this->mPerRow * ( $this->mWidths + $this->getAllPadding() );
                        $oldStyle = isset( $this->mAttribs['style'] ) ? $this->mAttribs['style'] : '';
-                       # _width is ignored by any sane browser. IE6 doesn't know max-width so it uses _width instead
-                       $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle;
+                       # _width is ignored by any sane browser. IE6 doesn't know max-width
+                       # so it uses _width instead
+                       $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" .
+                               $oldStyle;
                }
 
                $attribs = Sanitizer::mergeAttributes(
@@ -60,6 +60,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
                $lang = $this->getRenderLang();
                # Output each image...
                foreach ( $this->mImages as $pair ) {
+                       /** @var Title $nt */
                        $nt = $pair[0];
                        $text = $pair[1]; # "text" means "caption" here
                        $alt = $pair[2];
@@ -90,28 +91,31 @@ class TraditionalImageGallery extends ImageGalleryBase {
 
                        if ( !$img ) {
                                # We're dealing with a non-image, spit out the name and be done with it.
-                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
+                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: '
+                                       . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
                                        . htmlspecialchars( $nt->getText() ) . '</div>';
 
                                if ( $this->mParser instanceof Parser ) {
                                        $this->mParser->addTrackingCategory( 'broken-file-category' );
                                }
-                       } elseif ( $this->mHideBadImages && wfIsBadImage( $nt->getDBkey(), $this->getContextTitle() ) ) {
+                       } elseif ( $this->mHideBadImages
+                               && wfIsBadImage( $nt->getDBkey(), $this->getContextTitle() )
+                       ) {
                                # The image is blacklisted, just show it as a text link.
-                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">' .
-                                       Linker::link(
+                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' .
+                                       ( $this->getThumbPadding() + $this->mHeights ) . 'px;">' .
+                                       Linker::linkKnown(
                                                $nt,
-                                               htmlspecialchars( $nt->getText() ),
-                                               array(),
-                                               array(),
-                                               array( 'known', 'noclasses' )
+                                               htmlspecialchars( $nt->getText() )
                                        ) .
                                        '</div>';
                        } elseif ( !( $thumb = $img->transform( $transformOptions ) ) ) {
                                # Error generating thumbnail.
-                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
+                               $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: '
+                                       . ( $this->getThumbPadding() + $this->mHeights ) . 'px;">'
                                        . htmlspecialchars( $img->getLastError() ) . '</div>';
                        } else {
+                               /** @var MediaTransformOutput $thumb */
                                $vpad = $this->getVPad( $this->mHeights, $thumb->getHeight() );
 
                                $imageParameters = array(
@@ -120,7 +124,9 @@ class TraditionalImageGallery extends ImageGalleryBase {
                                        'alt' => $alt,
                                        'custom-url-link' => $link
                                );
-                               # In the absence of both alt text and caption, fall back on providing screen readers with the filename as alt text
+
+                               // In the absence of both alt text and caption, fall back on
+                               // providing screen readers with the filename as alt text
                                if ( $alt == '' && $text == '' ) {
                                        $imageParameters['alt'] = $nt->getText();
                                }
@@ -128,22 +134,27 @@ class TraditionalImageGallery extends ImageGalleryBase {
                                $this->adjustImageParameters( $thumb, $imageParameters );
 
                                # Set both fixed width and min-height.
-                               $thumbhtml = "\n\t\t\t" .
-                                       '<div class="thumb" style="width: ' . $this->getThumbDivWidth( $thumb->getWidth() ) . 'px;">'
-                                       # Auto-margin centering for block-level elements. Needed now that we have video
-                                       # handlers since they may emit block-level elements as opposed to simple <img> tags.
-                                       # ref http://css-discuss.incutio.com/?page=CenteringBlockElement
+                               $thumbhtml = "\n\t\t\t"
+                                       . '<div class="thumb" style="width: '
+                                       . $this->getThumbDivWidth( $thumb->getWidth() ) . 'px;">'
+                                       # Auto-margin centering for block-level elements. Needed
+                                       # now that we have video handlers since they may emit block-
+                                       # level elements as opposed to simple <img> tags. ref
+                                       # http://css-discuss.incutio.com/?page=CenteringBlockElement
                                        . '<div style="margin:' . $vpad . 'px auto;">'
                                        . $thumb->toHtml( $imageParameters ) . '</div></div>';
 
                                // Call parser transform hook
-                               if ( $this->mParser && $img->getHandler() ) {
-                                       $img->getHandler()->parserTransformHook( $this->mParser, $img );
+                               /** @var MediaHandler $handler */
+                               $handler = $img->getHandler();
+                               if ( $this->mParser && $handler ) {
+                                       $handler->parserTransformHook( $this->mParser, $img );
                                }
                        }
 
-                       //TODO
-                       // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) . ":{$ut}" );
+                       // @todo Code is incomplete.
+                       // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) .
+                       // ":{$ut}" );
                        // $ul = Linker::link( $linkTarget, $ut );
 
                        if ( $this->mShowBytes ) {
@@ -158,48 +169,46 @@ class TraditionalImageGallery extends ImageGalleryBase {
                        }
 
                        $textlink = $this->mShowFilename ?
-                               Linker::link(
+                               Linker::linkKnown(
                                        $nt,
-                                       htmlspecialchars( $lang->truncate( $nt->getText(), $this->mCaptionLength ) ),
-                                       array(),
-                                       array(),
-                                       array( 'known', 'noclasses' )
+                                       htmlspecialchars( $lang->truncate( $nt->getText(), $this->mCaptionLength ) )
                                ) . "<br />\n" :
                                '';
 
-
                        $galleryText = $textlink . $text . $fileSize;
                        $galleryText = $this->wrapGalleryText( $galleryText, $thumb );
 
                        # Weird double wrapping (the extra div inside the li) needed due to FF2 bug
                        # Can be safely removed if FF2 falls completely out of existence
-                       $output .=
-                               "\n\t\t" . '<li class="gallerybox" style="width: ' . $this->getGBWidth( $thumb ) . 'px">'
-                                       . '<div style="width: ' . $this->getGBWidth( $thumb ) . 'px">'
-                                       . $thumbhtml
-                                       . $galleryText
-                                       . "\n\t\t</div></li>";
+                       $output .= "\n\t\t" . '<li class="gallerybox" style="width: '
+                               . $this->getGBWidth( $thumb ) . 'px">'
+                               . '<div style="width: ' . $this->getGBWidth( $thumb ) . 'px">'
+                               . $thumbhtml
+                               . $galleryText
+                               . "\n\t\t</div></li>";
                }
                $output .= "\n</ul>";
 
                return $output;
        }
 
-
        /**
         * Add the wrapper html around the thumb's caption
         *
-        * @param String $galleryText The caption
-        * @param MediaTransformOutput|boolean $thumb The thumb this caption is for or false for bad image.
+        * @param string $galleryText The caption
+        * @param MediaTransformOutput|bool $thumb The thumb this caption is for
+        *   or false for bad image.
+        * @return string
         */
        protected function wrapGalleryText( $galleryText, $thumb ) {
-               # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which
-               # in version 4.8.6 generated crackpot html in its absence, see:
-               # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765 -Ævar
+               # ATTENTION: The newline after <div class="gallerytext"> is needed to
+               # accommodate htmltidy which in version 4.8.6 generated crackpot html in
+               # its absence, see: http://bugzilla.wikimedia.org/show_bug.cgi?id=1765
+               # -Ævar
 
                return "\n\t\t\t" . '<div class="gallerytext">' . "\n"
-                                       . $galleryText
-                                       . "\n\t\t\t</div>";
+                       . $galleryText
+                       . "\n\t\t\t</div>";
        }
 
        /**
@@ -213,7 +222,6 @@ class TraditionalImageGallery extends ImageGalleryBase {
        }
 
        /**
-        *
         * @note GB stands for gallerybox (as in the <li class="gallerybox"> element)
         *
         * @return int
@@ -236,7 +244,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
        /**
         * Get total padding.
         *
-        * @return int How many pixels of whitespace surround the thumbnail.
+        * @return int Number of pixels of whitespace surrounding the thumbnail.
         */
        protected function getAllPadding() {
                return $this->getThumbPadding() + $this->getGBPadding() + $this->getGBBorders();
@@ -249,7 +257,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
         *
         * @param int $boxHeight How high we want the box to be.
         * @param int $thumbHeight How high the thumbnail is.
-        * @return int How many vertical padding to add on each side.
+        * @return int Vertical padding to add on each side.
         */
        protected function getVPad( $boxHeight, $thumbHeight ) {
                return ( $this->getThumbPadding() + $boxHeight - $thumbHeight ) / 2;
@@ -259,6 +267,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
         * Get the transform parameters for a thumbnail.
         *
         * @param File $img The file in question. May be false for invalid image
+        * @return array
         */
        protected function getThumbParams( $img ) {
                return array(
@@ -285,8 +294,8 @@ class TraditionalImageGallery extends ImageGalleryBase {
         * plus padding on gallerybox.
         *
         * @note Important: parameter will be false if no thumb used.
-        * @param Mixed $thumb MediaTransformObject object or false.
-        * @return int width of gallerybox element
+        * @param MediaTransformOutput|bool $thumb MediaTransformObject object or false.
+        * @return int Width of gallerybox element
         */
        protected function getGBWidth( $thumb ) {
                return $this->mWidths + $this->getThumbPadding() + $this->getGBPadding();
@@ -297,7 +306,7 @@ class TraditionalImageGallery extends ImageGalleryBase {
         *
         * Primarily intended for subclasses.
         *
-        * @return Array modules to include
+        * @return array Modules to include
         */
        protected function getModules() {
                return array();
@@ -308,9 +317,10 @@ class TraditionalImageGallery extends ImageGalleryBase {
         *
         * Used by a subclass to insert extra high resolution images.
         * @param MediaTransformOutput $thumb The thumbnail
-        * @param Array $imageParameters Array of options
+        * @param array $imageParameters Array of options
         */
-       protected function adjustImageParameters( $thumb, &$imageParameters ) { }
+       protected function adjustImageParameters( $thumb, &$imageParameters ) {
+       }
 }
 
 /**
index 0110ac5..b4f2194 100644 (file)
@@ -243,7 +243,10 @@ abstract class DatabaseInstaller {
                if ( $status->isOK() ) {
                        $status->value->setSchemaVars( $this->getSchemaVars() );
                } else {
-                       throw new MWException( __METHOD__ . ': unexpected DB connection error' );
+                       $msg = __METHOD__ . ': unexpected error while establishing'
+                               . ' a database connection with message: '
+                               . $status->getMessage()->plain();
+                       throw new MWException( $msg );
                }
        }
 
@@ -438,6 +441,10 @@ abstract class DatabaseInstaller {
        /**
         * Get a labelled checkbox to configure a local boolean variable.
         *
+        * @param string $var
+        * @param string $label
+        * @param array $attribs Optional.
+        * @param string $helpData Optional.
         * @return string
         */
        public function getCheckBox( $var, $label, $attribs = array(), $helpData = "" ) {
@@ -544,8 +551,8 @@ abstract class DatabaseInstaller {
 
        /**
         * Get a standard web-user fieldset
-        * @param string $noCreateMsg Message to display instead of the creation checkbox.
-        *   Set this to false to show a creation checkbox.
+        * @param string|bool $noCreateMsg Message to display instead of the creation checkbox.
+        *   Set this to false to show a creation checkbox (default).
         *
         * @return String
         */
index 267b6c5..3f2e2cb 100644 (file)
@@ -77,7 +77,7 @@ abstract class DatabaseUpdater {
        /**
         * File handle for SQL output.
         *
-        * @var Filehandle
+        * @var resource
         */
        protected $fileHandle = null;
 
@@ -88,12 +88,17 @@ abstract class DatabaseUpdater {
         */
        protected $skipSchema = false;
 
+       /**
+        * Hold the value of $wgContentHandlerUseDB during the upgrade.
+        */
+       protected $holdContentHandlerUseDB = true;
+
        /**
         * Constructor
         *
-        * @param $db DatabaseBase object to perform updates on
+        * @param DatabaseBase $db To perform updates on
         * @param bool $shared Whether to perform updates on shared tables
-        * @param $maintenance Maintenance Maintenance object which created us
+        * @param Maintenance $maintenance Maintenance object which created us
         */
        protected function __construct( DatabaseBase &$db, $shared, Maintenance $maintenance = null ) {
                $this->db = $db;
@@ -199,7 +204,7 @@ abstract class DatabaseUpdater {
         *
         * @since 1.17
         *
-        * @param array $update the update to run. Format is the following:
+        * @param array $update The update to run. Format is the following:
         *                first item is the callback function, it also can be a
         *                simple string with the name of a function in this class,
         *                following elements are parameters to the function.
@@ -383,7 +388,7 @@ abstract class DatabaseUpdater {
        /**
         * Do all the updates
         *
-        * @param array $what what updates to perform
+        * @param array $what What updates to perform
         */
        public function doUpdates( $what = array( 'core', 'extensions', 'stats' ) ) {
                global $wgVersion;
@@ -418,7 +423,7 @@ abstract class DatabaseUpdater {
         * Helper function for doUpdates()
         *
         * @param array $updates of updates to run
-        * @param $passSelf Boolean: whether to pass this object we calling external
+        * @param bool $passSelf Whether to pass this object we calling external
         *                  functions
         */
        private function runUpdates( array $updates, $passSelf ) {
@@ -445,8 +450,8 @@ abstract class DatabaseUpdater {
        }
 
        /**
-        * @param $version
-        * @param $updates array
+        * @param string $version
+        * @param array $updates
         */
        protected function setAppliedUpdates( $version, $updates = array() ) {
                $this->db->clearFlag( DBO_DDLMODE );
@@ -465,7 +470,6 @@ abstract class DatabaseUpdater {
         * Obviously, only use this for updates that occur after the updatelog table was
         * created!
         * @param string $key Name of the key to check for
-        *
         * @return bool
         */
        public function updateRowExists( $key ) {
@@ -484,7 +488,7 @@ abstract class DatabaseUpdater {
         * Obviously, only use this for updates that occur after the updatelog table was
         * created!
         * @param string $key Name of key to insert
-        * @param string $val [optional] value to insert along with the key
+        * @param string $val [optional] Value to insert along with the key
         */
        public function insertUpdateRow( $key, $val = null ) {
                $this->db->clearFlag( DBO_DDLMODE );
@@ -514,7 +518,7 @@ abstract class DatabaseUpdater {
         * Updates will be prevented if the table is a shared table and it is not
         * specified to run updates on shared tables.
         *
-        * @param string $name table name
+        * @param string $name Table name
         * @return bool
         */
        protected function doTable( $name ) {
@@ -579,7 +583,7 @@ abstract class DatabaseUpdater {
         * 1.13...) with the values being arrays of updates, identical to how
         * updaters.inc did it (for now)
         *
-        * @return Array
+        * @return array
         */
        abstract protected function getCoreUpdateList();
 
@@ -600,8 +604,8 @@ abstract class DatabaseUpdater {
         *
         * This is used as a callback for for sourceLine().
         *
-        * @param string $line text to append to the file
-        * @return Boolean false to skip actually executing the file
+        * @param string $line Text to append to the file
+        * @return bool False to skip actually executing the file
         * @throws MWException
         */
        public function appendLine( $line ) {
@@ -619,7 +623,7 @@ abstract class DatabaseUpdater {
         * @param string $path Path to the patch file
         * @param $isFullPath Boolean Whether to treat $path as a relative or not
         * @param string $msg Description of the patch
-        * @return boolean false if patch is skipped.
+        * @return bool False if patch is skipped.
         */
        protected function applyPatch( $path, $isFullPath = false, $msg = null ) {
                if ( $msg === null ) {
@@ -651,8 +655,8 @@ abstract class DatabaseUpdater {
         *
         * @param string $name Name of the new table
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function addTable( $name, $patch, $fullpath = false ) {
                if ( !$this->doTable( $name ) ) {
@@ -674,8 +678,8 @@ abstract class DatabaseUpdater {
         * @param string $table Name of the table to modify
         * @param string $field Name of the new field
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function addField( $table, $field, $patch, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -699,8 +703,8 @@ abstract class DatabaseUpdater {
         * @param string $table Name of the table to modify
         * @param string $index Name of the new index
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function addIndex( $table, $index, $patch, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -724,8 +728,8 @@ abstract class DatabaseUpdater {
         * @param string $table Name of the table to modify
         * @param string $field Name of the old field
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function dropField( $table, $field, $patch, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -747,8 +751,8 @@ abstract class DatabaseUpdater {
         * @param string $table Name of the table to modify
         * @param string $index Name of the index
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean: Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function dropIndex( $table, $index, $patch, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -773,8 +777,8 @@ abstract class DatabaseUpdater {
         * @param $skipBothIndexExistWarning Boolean: Whether to warn if both the
         * old and the new indexes exist.
         * @param string $patch Path to the patch file
-        * @param $fullpath Boolean: Whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        protected function renameIndex( $table, $oldIndex, $newIndex,
                $skipBothIndexExistWarning, $patch, $fullpath = false
@@ -825,10 +829,10 @@ abstract class DatabaseUpdater {
         *
         * Public @since 1.20
         *
-        * @param $table string
-        * @param $patch string|false
-        * @param $fullpath bool
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param string $table Table to drop.
+        * @param string|bool $patch String of patch file that will drop the table. Default: false.
+        * @param bool $fullpath Whether $patch is a full path. Default: false.
+        * @return bool False if this was skipped because schema changes are skipped
         */
        public function dropTable( $table, $patch = false, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -855,11 +859,11 @@ abstract class DatabaseUpdater {
        /**
         * Modify an existing field
         *
-        * @param string $table name of the table to which the field belongs
-        * @param string $field name of the field to modify
-        * @param string $patch path to the patch file
-        * @param $fullpath Boolean: whether to treat $patch path as a relative or not
-        * @return Boolean false if this was skipped because schema changes are skipped
+        * @param string $table Name of the table to which the field belongs
+        * @param string $field Name of the field to modify
+        * @param string $patch Path to the patch file
+        * @param bool $fullpath Whether to treat $patch path as a relative or not
+        * @return bool False if this was skipped because schema changes are skipped
         */
        public function modifyField( $table, $field, $patch, $fullpath = false ) {
                if ( !$this->doTable( $table ) ) {
@@ -1033,4 +1037,30 @@ abstract class DatabaseUpdater {
                $cl->execute();
                $this->output( "done.\n" );
        }
+
+       /**
+        * Turns off content handler fields during parts of the upgrade
+        * where they aren't available.
+        */
+       protected function disableContentHandlerUseDB() {
+               global $wgContentHandlerUseDB;
+
+               if ( $wgContentHandlerUseDB ) {
+                       $this->output( "Turning off Content Handler DB fields for this part of upgrade.\n" );
+                       $this->holdContentHandlerUseDB = $wgContentHandlerUseDB;
+                       $wgContentHandlerUseDB = false;
+               }
+       }
+
+       /**
+        * Turns content handler fields back on.
+        */
+       protected function enableContentHandlerUseDB() {
+               global $wgContentHandlerUseDB;
+
+               if ( $this->holdContentHandlerUseDB ) {
+                       $this->output( "Content Handler DB fields should be usable now.\n" );
+                       $wgContentHandlerUseDB = $this->holdContentHandlerUseDB;
+               }
+       }
 }
index edf5ff2..68dd216 100644 (file)
@@ -74,7 +74,7 @@ This program is free software; you can redistribute it and/or modify it under th
 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 <doclink href=Copying>a copy of the GNU General Public License</doclink> along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. or [http://www.gnu.org/copyleft/gpl.html read it online].",
+You should have received <doclink href=Copying>a copy of the GNU General Public License</doclink> along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, or [http://www.gnu.org/copyleft/gpl.html read it online].",
        'config-sidebar'                  => "* [//www.mediawiki.org MediaWiki home]
 * [//www.mediawiki.org/wiki/Help:Contents User's Guide]
 * [//www.mediawiki.org/wiki/Manual:Contents Administrator's Guide]
@@ -224,7 +224,7 @@ In '''binary mode''', MediaWiki stores UTF-8 text to the database in binary fiel
 This is more efficient than MySQL's UTF-8 mode, and allows you to use the full range of Unicode characters.
 In '''UTF-8 mode''', MySQL will know what character set your data is in, and can present and convert it appropriately,
 but it will not let you store characters above the [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
-       'config-mysql-old'                => 'MySQL $1 or later is required, you have $2.',
+       'config-mysql-old'                => 'MySQL $1 or later is required. You have $2.',
        'config-db-port'                  => 'Database port:',
        'config-db-schema'                => 'Schema for MediaWiki:',
        'config-db-schema-help'           => 'This schema will usually be fine.
@@ -277,7 +277,7 @@ Check the host, username and password and try again.',
 Use only ASCII letters (a-z, A-Z), numbers (0-9) and underscores (_).',
        'config-db-sys-create-oracle' => 'Installer only supports using a SYSDBA account for creating a new account.',
        'config-db-sys-user-exists-oracle' => 'User account "$1" already exists. SYSDBA can only be used for creating of a new account!',
-       'config-postgres-old'             => 'PostgreSQL $1 or later is required, you have $2.',
+       'config-postgres-old'             => 'PostgreSQL $1 or later is required. You have $2.',
        'config-sqlite-name-help'         => 'Choose a name that identifies your wiki.
 Do not use spaces or hyphens.
 This will be used for the SQLite data file name.',
@@ -340,7 +340,7 @@ The account you specify here must already exist.',
 
 If your MySQL installation supports InnoDB, it is highly recommended that you choose that instead.
 If your MySQL installation does not support InnoDB, maybe it's time for an upgrade.",
-       'config-mysql-only-myisam-dep'    => "'''Warning:''' MyISAM is the only available storage engine for MySQL, which is not recommended for use with MediaWiki, because:
+       'config-mysql-only-myisam-dep'    => "'''Warning:''' MyISAM is the only available storage engine for MySQL on this machine, and this is not recommended for use with MediaWiki, because:
 * it barely supports concurrency due to table locking
 * it is more prone to corruption than other engines
 * the MediaWiki codebase does not always handle MyISAM as it should
@@ -374,7 +374,7 @@ Specify a different project namespace.',
        'config-ns-conflict'               => 'The specified namespace "<nowiki>$1</nowiki>" conflicts with a default MediaWiki namespace.
 Specify a different project namespace.',
        'config-admin-box'                => 'Administrator account',
-       'config-admin-name'               => 'Your name:',
+       'config-admin-name'               => 'Your username:',
        'config-admin-password'           => 'Password:',
        'config-admin-password-confirm'   => 'Password again:',
        'config-admin-help'               => 'Enter your preferred username here, for example "Joe Bloggs".
@@ -499,7 +499,7 @@ If you do not know the port, the default is 11211.',
        'config-extensions'               => 'Extensions',
        'config-extensions-help'          => 'The extensions listed above were detected in your <code>./extensions</code> directory.
 
-They may require additional configuration, but you can enable them now',
+They may require additional configuration, but you can enable them now.',
        'config-install-alreadydone'      => "'''Warning:''' You seem to have already installed MediaWiki and are trying to install it again.
 Please proceed to the next page.",
        'config-install-begin'            => 'By pressing "{{int:config-continue}}", you will begin the installation of MediaWiki.
index 276c572..765838b 100644 (file)
@@ -1152,11 +1152,11 @@ abstract class Installer {
                        return chr( 0xC0 | $c >> 6 ) . chr( 0x80 | $c & 0x3F );
                } elseif ( $c <= 0xFFFF ) {
                        return chr( 0xE0 | $c >> 12 ) . chr( 0x80 | $c >> 6 & 0x3F )
-                               . chr( 0x80 | $c & 0x3F );
+                       . chr( 0x80 | $c & 0x3F );
                } elseif ( $c <= 0x10FFFF ) {
                        return chr( 0xF0 | $c >> 18 ) . chr( 0x80 | $c >> 12 & 0x3F )
-                               . chr( 0x80 | $c >> 6 & 0x3F )
-                               . chr( 0x80 | $c & 0x3F );
+                       . chr( 0x80 | $c >> 6 & 0x3F )
+                       . chr( 0x80 | $c & 0x3F );
                } else {
                        return false;
                }
@@ -1301,8 +1301,13 @@ abstract class Installer {
        /**
         * Same as locateExecutable(), but checks in getPossibleBinPaths() by default
         * @see locateExecutable()
-        * @param $names
-        * @param $versionInfo bool
+        * @param array $names Array of possible names.
+        * @param array|bool $versionInfo Default: false or array with two members:
+        *         0 => Command to run for version check, with $1 for the full executable name
+        *         1 => String to compare the output with
+        *
+        * If $versionInfo is not false, only executables with a version
+        * matching $versionInfo[1] will be returned.
         * @return bool|string
         */
        public static function locateExecutableInDefaultPaths( $names, $versionInfo = false ) {
@@ -1737,6 +1742,11 @@ abstract class Installer {
 
                // Some of the environment checks make shell requests, remove limits
                $GLOBALS['wgMaxShellMemory'] = 0;
+
+               // Don't bother embedding images into generated CSS, which is not cached
+               $GLOBALS['wgResourceLoaderLESSFunctions']['embeddable'] = function ( $frame, $less ) {
+                       return $less->toBool( false );
+               };
        }
 
        /**
index 56d8353..2433fbd 100644 (file)
@@ -220,12 +220,23 @@ class LocalSettingsGenerator {
                                                wfBoolToStr( $perm ) . ";\n";
                                }
                        }
+                       $noFollow = '';
+                       if ( $this->groupPermissions['*']['edit'] === false
+                               && $this->groupPermissions['*']['createaccount'] === false
+                               && $this->groupPermissions['*']['read'] !== false ) {
+                               $noFollow = "# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
+                                       . "# the general public and wish to apply nofollow to external links as a\n"
+                                       . "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
+                                       . "# and open wikis will generally require other anti-spam measures; for more\n"
+                                       . "# information, see https://www.mediawiki.org/wiki/Manual:Combating_spam\n"
+                                       . "\$wgNoFollowLinks = false;";
+                       }
                }
 
-               $wgServerSetting = "";
+               $serverSetting = "";
                if ( array_key_exists( 'wgServer', $this->values ) && $this->values['wgServer'] !== null ) {
-                       $wgServerSetting = "\n## The protocol and server name to use in fully-qualified URLs\n";
-                       $wgServerSetting .= "\$wgServer = \"{$this->values['wgServer']}\";\n";
+                       $serverSetting = "\n## The protocol and server name to use in fully-qualified URLs\n";
+                       $serverSetting .= "\$wgServer = \"{$this->values['wgServer']}\";\n";
                }
 
                switch ( $this->values['wgMainCacheType'] ) {
@@ -271,7 +282,7 @@ if ( !defined( 'MEDIAWIKI' ) ) {
 ## http://www.mediawiki.org/wiki/Manual:Short_URL
 \$wgScriptPath = \"{$this->values['wgScriptPath']}\";
 \$wgScriptExtension = \"{$this->values['wgScriptExtension']}\";
-${wgServerSetting}
+${serverSetting}
 ## The relative URL path to the skins directory
 \$wgStylePath = \"\$wgScriptPath/skins\";
 
@@ -353,6 +364,7 @@ ${wgServerSetting}
 # Path to the GNU diff3 utility. Used for conflict resolution.
 \$wgDiff3 = \"{$this->values['wgDiff3']}\";
 
-{$groupRights}";
+{$groupRights}
+{$noFollow}";
        }
 }
index 5f76972..2d43324 100644 (file)
@@ -268,9 +268,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return false;
                }
-               /**
-                * @var $conn DatabaseBase
-                */
+               /** @var $conn DatabaseBase */
                $conn = $status->value;
 
                // Get current account name
@@ -436,13 +434,14 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$create ) {
                        // Test the web account
                        try {
-                               $db = DatabaseBase::factory( 'mysql', array(
+                               DatabaseBase::factory( 'mysql', array(
                                        'host' => $this->getVar( 'wgDBserver' ),
                                        'user' => $this->getVar( 'wgDBuser' ),
                                        'password' => $this->getVar( 'wgDBpassword' ),
                                        'dbname' => false,
                                        'flags' => 0,
-                                       'tablePrefix' => $this->getVar( 'wgDBprefix' ) ) );
+                                       'tablePrefix' => $this->getVar( 'wgDBprefix' )
+                               ) );
                        } catch ( DBConnectionError $e ) {
                                return Status::newFatal( 'config-connection-error', $e->getMessage() );
                        }
@@ -479,6 +478,7 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( !$status->isOK() ) {
                        return $status;
                }
+               /** @var DatabaseBase $conn */
                $conn = $status->value;
                $dbName = $this->getVar( 'wgDBname' );
                if ( !$conn->selectDB( $dbName ) ) {
@@ -516,13 +516,14 @@ class MysqlInstaller extends DatabaseInstaller {
                if ( $this->getVar( '_CreateDBAccount' ) ) {
                        // Before we blindly try to create a user that already has access,
                        try { // first attempt to connect to the database
-                               $db = DatabaseBase::factory( 'mysql', array(
+                               DatabaseBase::factory( 'mysql', array(
                                        'host' => $server,
                                        'user' => $dbUser,
                                        'password' => $password,
                                        'dbname' => false,
                                        'flags' => 0,
-                                       'tablePrefix' => $this->getVar( 'wgDBprefix' ) ) );
+                                       'tablePrefix' => $this->getVar( 'wgDBprefix' )
+                               ) );
                                $grantableNames[] = $this->buildFullUserName( $dbUser, $server );
                                $tryToCreate = false;
                        } catch ( DBConnectionError $e ) {
index 6ff7af0..cc5313a 100644 (file)
@@ -31,6 +31,8 @@ class MysqlUpdater extends DatabaseUpdater {
 
        protected function getCoreUpdateList() {
                return array(
+                       array( 'disableContentHandlerUseDB' ),
+
                        // 1.2
                        array( 'addField', 'ipblocks', 'ipb_id', 'patch-ipblocks.sql' ),
                        array( 'addField', 'ipblocks', 'ipb_expiry', 'patch-ipb_expiry.sql' ),
@@ -218,6 +220,7 @@ class MysqlUpdater extends DatabaseUpdater {
                        array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
                        array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
                        array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
+                       array( 'enableContentHandlerUseDB' ),
                        array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
                        array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
                        array( 'addTable', 'sites', 'patch-sites.sql' ),
@@ -239,6 +242,9 @@ class MysqlUpdater extends DatabaseUpdater {
                                'patch-iwlinks-from-title-index.sql' ),
                        array( 'addField', 'archive', 'ar_id', 'patch-archive-ar_id.sql' ),
                        array( 'addField', 'externallinks', 'el_id', 'patch-externallinks-el_id.sql' ),
+
+                       // 1.23
+                       array( 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ),
                );
        }
 
@@ -246,15 +252,17 @@ class MysqlUpdater extends DatabaseUpdater {
         * 1.4 betas were missing the 'binary' marker from logging.log_title,
         * which causes a collation mismatch error on joins in MySQL 4.1.
         *
-        * @param string $table table name
-        * @param string $field field name to check
-        * @param string $patchFile path to the patch to correct the field
+        * @param string $table Table name
+        * @param string $field Field name to check
+        * @param string $patchFile Path to the patch to correct the field
+        * @return bool
         */
        protected function checkBin( $table, $field, $patchFile ) {
                if ( !$this->doTable( $table ) ) {
                        return true;
                }
 
+               /** @var MySQLField $fieldInfo */
                $fieldInfo = $this->db->fieldInfo( $table, $field );
                if ( $fieldInfo->isBinary() ) {
                        $this->output( "...$table table has correct $field encoding.\n" );
@@ -266,10 +274,10 @@ class MysqlUpdater extends DatabaseUpdater {
        /**
         * Check whether an index contain a field
         *
-        * @param string $table table name
-        * @param string $index index name to check
-        * @param string $field field that should be in the index
-        * @return Boolean
+        * @param string $table Table name
+        * @param string $index Index name to check
+        * @param string $field Field that should be in the index
+        * @return bool
         */
        protected function indexHasField( $table, $index, $field ) {
                if ( !$this->doTable( $table ) ) {
@@ -694,7 +702,7 @@ class MysqlUpdater extends DatabaseUpdater {
 
                if ( !$this->db->tableExists( 'user_rights', __METHOD__ ) ) {
                        if ( $this->db->fieldExists( 'user', 'user_rights', __METHOD__ ) ) {
-                               $this->db->applyPatch(
+                               $this->applyPatch(
                                        'patch-user_rights.sql',
                                        false,
                                        'Upgrading from a 1.3 or older database? Breaking out user_rights for conversion'
index 7757510..113dce6 100644 (file)
@@ -247,6 +247,7 @@ class OracleInstaller extends DatabaseInstaller {
                                return $status;
                        }
                }
+
                $this->db = $status->value;
                $this->setupSchemaVars();
 
index ec91e57..7b6f49c 100644 (file)
@@ -38,6 +38,8 @@ class OracleUpdater extends DatabaseUpdater {
 
        protected function getCoreUpdateList() {
                return array(
+                       array( 'disableContentHandlerUseDB' ),
+
                        // 1.17
                        array( 'doNamespaceDefaults' ),
                        array( 'doFKRenameDeferr' ),
@@ -79,6 +81,7 @@ class OracleUpdater extends DatabaseUpdater {
                        array( 'addField', 'archive', 'ar_id', 'patch-archive-ar_id.sql' ),
                        array( 'addField', 'externallinks', 'el_id', 'patch-externallinks-el_id.sql' ),
                        array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
+                       array( 'enableContentHandlerUseDB' ),
                        array( 'dropField', 'site_stats', 'ss_admins', 'patch-ss_admins.sql' ),
                        array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
                        array( 'addTable', 'sites', 'patch-sites.sql' ),
index dfe7865..e8a1c80 100644 (file)
@@ -66,6 +66,8 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addSequence', 'logging', false, 'logging_log_id_seq' ),
                        array( 'addSequence', 'page_restrictions', false, 'page_restrictions_pr_id_seq' ),
                        array( 'addSequence', 'filearchive', 'fa_id', 'filearchive_fa_id_seq' ),
+                       array( 'addSequence', 'archive', false, 'archive_ar_id_seq' ),
+                       array( 'addSequence', 'externallinks', false, 'externallinks_el_id_seq' ),
 
                        # new tables
                        array( 'addTable', 'category', 'patch-category.sql' ),
@@ -395,6 +397,9 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addInterwikiType' ),
                        # end
                        array( 'tsearchFixes' ),
+
+                       // 1.23
+                       array( 'addPgField', 'recentchanges', 'rc_source',            "TEXT NOT NULL DEFAULT ''" ),
                );
        }
 
index 78ca511..e0ed1ec 100644 (file)
@@ -31,6 +31,8 @@ class SqliteUpdater extends DatabaseUpdater {
 
        protected function getCoreUpdateList() {
                return array(
+                       array( 'disableContentHandlerUseDB' ),
+
                        // 1.14
                        array( 'addField', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ),
                        array( 'doActiveUsersInit' ),
@@ -97,6 +99,8 @@ class SqliteUpdater extends DatabaseUpdater {
                        array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
                        array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
                        array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
+                       array( 'enableContentHandlerUseDB' ),
+
                        array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
                        array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
                        array( 'addTable', 'sites', 'patch-sites.sql' ),
@@ -111,9 +115,14 @@ class SqliteUpdater extends DatabaseUpdater {
                        array( 'addIndex', 'page_props', 'pp_propname_page',
                                'patch-page_props-propname-page-index.sql' ),
                        array( 'addIndex', 'image', 'img_media_mime', 'patch-img_media_mime-index.sql' ),
+
+                       // 1.22
                        array( 'addIndex', 'iwlinks', 'iwl_prefix_from_title', 'patch-iwlinks-from-title-index.sql' ),
                        array( 'addField', 'archive', 'ar_id', 'patch-archive-ar_id.sql' ),
                        array( 'addField', 'externallinks', 'el_id', 'patch-externallinks-el_id.sql' ),
+
+                       // 1.23
+                       array( 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ),
                );
        }
 
index e23edf5..79fdc99 100644 (file)
@@ -124,7 +124,7 @@ class WebInstaller extends Installer {
        /**
         * Constructor.
         *
-        * @param $request WebRequest
+        * @param WebRequest $request
         */
        public function __construct( WebRequest $request ) {
                parent::__construct();
@@ -142,7 +142,7 @@ class WebInstaller extends Installer {
         *
         * @param array $session initial session array
         *
-        * @return Array: new session array
+        * @return array New session array
         */
        public function execute( array $session ) {
                $this->session = $session;
@@ -326,6 +326,7 @@ class WebInstaller extends Installer {
        /**
         * Start the PHP session. This may be called before execute() to start the PHP session.
         *
+        * @throws Exception
         * @return bool
         */
        public function startSession() {
@@ -336,7 +337,12 @@ class WebInstaller extends Installer {
 
                $this->phpErrors = array();
                set_error_handler( array( $this, 'errorHandler' ) );
-               session_start();
+               try {
+                       session_start();
+               } catch ( Exception $e ) {
+                       restore_error_handler();
+                       throw $e;
+               }
                restore_error_handler();
 
                if ( $this->phpErrors ) {
@@ -391,7 +397,7 @@ class WebInstaller extends Installer {
        /**
         * Temporary error handler for session start debugging.
         * @param $errno
-        * @param $errstr string
+        * @param string $errstr
         */
        public function errorHandler( $errno, $errstr ) {
                $this->phpErrors[] = $errstr;
@@ -424,7 +430,7 @@ class WebInstaller extends Installer {
        /**
         * Get a URL for submission back to the same script.
         *
-        * @param $query array
+        * @param array $query
         * @return string
         */
        public function getUrl( $query = array() ) {
@@ -442,7 +448,7 @@ class WebInstaller extends Installer {
        /**
         * Get a WebInstallerPage by name.
         *
-        * @param $pageName String
+        * @param string $pageName
         * @return WebInstallerPage
         */
        public function getPageByName( $pageName ) {
@@ -454,7 +460,7 @@ class WebInstaller extends Installer {
        /**
         * Get a session variable.
         *
-        * @param $name String
+        * @param string $name
         * @param $default
         * @return null
         */
@@ -468,8 +474,8 @@ class WebInstaller extends Installer {
 
        /**
         * Set a session variable.
-        * @param string $name key for the variable
-        * @param $value Mixed
+        * @param string $name Key for the variable
+        * @param mixed $value
         */
        public function setSession( $name, $value ) {
                $this->session[$name] = $value;
@@ -523,7 +529,7 @@ class WebInstaller extends Installer {
        /**
         * Called by execute() before page output starts, to show a page list.
         *
-        * @param $currentPageName string
+        * @param string $currentPageName
         */
        private function startPageWrapper( $currentPageName ) {
                $s = "<div class=\"config-page-wrapper\">\n";
@@ -563,9 +569,9 @@ class WebInstaller extends Installer {
        /**
         * Get a list item for the page list.
         *
-        * @param $pageName string
-        * @param $enabled boolean
-        * @param $currentPageName string
+        * @param string $pageName
+        * @param bool $enabled
+        * @param string $currentPageName
         *
         * @return string
         */
@@ -630,7 +636,7 @@ class WebInstaller extends Installer {
        /**
         * Get HTML for an error box with an icon.
         *
-        * @param string $text wikitext, get this with wfMessage()->plain()
+        * @param string $text Wikitext, get this with wfMessage()->plain()
         *
         * @return string
         */
@@ -641,7 +647,7 @@ class WebInstaller extends Installer {
        /**
         * Get HTML for a warning box with an icon.
         *
-        * @param string $text wikitext, get this with wfMessage()->plain()
+        * @param string $text Wikitext, get this with wfMessage()->plain()
         *
         * @return string
         */
@@ -652,9 +658,9 @@ class WebInstaller extends Installer {
        /**
         * Get HTML for an info box with an icon.
         *
-        * @param string $text wikitext, get this with wfMessage()->plain()
-        * @param string $icon icon name, file in skins/common/images
-        * @param string $class additional class name to add to the wrapper div
+        * @param string $text Wikitext, get this with wfMessage()->plain()
+        * @param string|bool $icon Icon name, file in skins/common/images. Default: false
+        * @param string|bool $class Additional class name to add to the wrapper div. Default: false.
         *
         * @return string
         */
@@ -691,7 +697,7 @@ class WebInstaller extends Installer {
 
        /**
         * Output a help box.
-        * @param string $msg key for wfMessage()
+        * @param string $msg Key for wfMessage()
         */
        public function showHelpBox( $msg /*, ... */ ) {
                $args = func_get_args();
@@ -703,7 +709,7 @@ class WebInstaller extends Installer {
         * Show a short informational message.
         * Output looks like a list.
         *
-        * @param $msg string
+        * @param string $msg
         */
        public function showMessage( $msg /*, ... */ ) {
                $args = func_get_args();
@@ -715,7 +721,7 @@ class WebInstaller extends Installer {
        }
 
        /**
-        * @param $status Status
+        * @param Status $status
         */
        public function showStatusMessage( Status $status ) {
                $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
@@ -731,7 +737,7 @@ class WebInstaller extends Installer {
         * @param $msg
         * @param $forId
         * @param $contents
-        * @param $helpData string
+        * @param string $helpData
         * @return string
         */
        public function label( $msg, $forId, $contents, $helpData = "" ) {
@@ -764,7 +770,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled text box to configure a variable.
         *
-        * @param $params Array
+        * @param array $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -811,7 +817,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled textarea to configure a variable
         *
-        * @param $params Array
+        * @param array $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -860,7 +866,7 @@ class WebInstaller extends Installer {
         * Get a labelled password box to configure a variable.
         *
         * Implements password hiding
-        * @param $params Array
+        * @param array $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -889,7 +895,7 @@ class WebInstaller extends Installer {
        /**
         * Get a labelled checkbox to configure a boolean variable.
         *
-        * @param $params Array
+        * @param array $params
         *    Parameters are:
         *      var:         The variable to be configured (required)
         *      label:       The message name for the label (required)
@@ -940,7 +946,7 @@ class WebInstaller extends Installer {
        /**
         * Get a set of labelled radio buttons.
         *
-        * @param $params Array
+        * @param array $params
         *    Parameters are:
         *      var:             The variable to be configured (required)
         *      label:           The message name for the label (required)
@@ -1006,7 +1012,7 @@ class WebInstaller extends Installer {
        /**
         * Output an error or warning box using a Status object.
         *
-        * @param $status Status
+        * @param Status $status
         */
        public function showStatusBox( $status ) {
                if ( !$status->isGood() ) {
@@ -1027,8 +1033,8 @@ class WebInstaller extends Installer {
         * Assumes that variables containing "password" in the name are (potentially
         * fake) passwords.
         *
-        * @param $varNames Array
-        * @param string $prefix the prefix added to variables to obtain form names
+        * @param array $varNames
+        * @param string $prefix The prefix added to variables to obtain form names
         *
         * @return array
         */
@@ -1092,7 +1098,7 @@ class WebInstaller extends Installer {
         * @param $text
         * @param $attribs
         * @param $parser
-        * @return String Html for download link
+        * @return string Html for download link
         */
        public function downloadLinkHook( $text, $attribs, $parser ) {
                $img = Html::element( 'img', array(
index 1df8f05..00a4ff8 100644 (file)
@@ -104,47 +104,83 @@ class WebInstallerOutput {
 
        /**
         * Get the raw vector CSS, flipping if needed
+        *
+        * @todo Possibly get rid of this function and use ResourceLoader in the manner it was
+        *   designed to be used in, rather than just grabbing a list of filenames from it,
+        *   and not properly handling such details as media types in module definitions.
+        *
         * @param string $dir 'ltr' or 'rtl'
         * @return String
         */
        public function getCSS( $dir ) {
-               $skinDir = dirname( dirname( __DIR__ ) ) . '/skins';
-
-               // All these files will be concatenated in sequence and loaded
-               // as one file.
-               // The string 'images/' in the files' contents will be replaced
-               // by '../skins/$skinName/images/', where $skinName is what appears
-               // before the last '/' in each of the strings.
-               $cssFileNames = array(
-
-                       // Basically the "skins.vector" ResourceLoader module styles
-                       'common/shared.css',
-                       'common/commonElements.css',
-                       'common/commonContent.css',
-                       'common/commonInterface.css',
-                       'vector/screen.css',
-
-                       // mw-config specific
-                       'common/config.css',
+               // All CSS files these modules reference will be concatenated in sequence
+               // and loaded as one file.
+               $moduleNames = array(
+                       'mediawiki.legacy.shared',
+                       'skins.vector',
+                       'mediawiki.legacy.config',
                );
 
+               $prepend = '';
                $css = '';
 
-               wfSuppressWarnings();
-               foreach ( $cssFileNames as $cssFileName ) {
-                       $fullCssFileName = "$skinDir/$cssFileName";
-                       $cssFileContents = file_get_contents( $fullCssFileName );
-                       if ( $cssFileContents ) {
-                               preg_match( "/^(\w+)\//", $cssFileName, $match );
-                               $skinName = $match[1];
-                               $css .= str_replace( 'images/', "../skins/$skinName/images/", $cssFileContents );
-                       } else {
-                               $css .= "/** Your webserver cannot read $fullCssFileName. Please check file permissions. */";
+               $resourceLoader = new ResourceLoader();
+               foreach ( $moduleNames as $moduleName ) {
+                       /** @var ResourceLoaderFileModule $module */
+                       $module = $resourceLoader->getModule( $moduleName );
+                       $cssFileNames = $module->getAllStyleFiles();
+
+                       wfSuppressWarnings();
+                       foreach ( $cssFileNames as $cssFileName ) {
+                               if ( !file_exists( $cssFileName ) ) {
+                                       $prepend .= ResourceLoader::makeComment( "Unable to find $cssFileName." );
+                                       continue;
+                               }
+
+                               if ( !is_readable( $cssFileName ) ) {
+                                       $prepend .= ResourceLoader::makeComment( "Unable to read $cssFileName. " .
+                                               "Please check file permissions." );
+                                       continue;
+                               }
+
+                               try {
+
+                                       if ( preg_match( '/\.less$/', $cssFileName ) ) {
+                                               // Run the LESS compiler for *.less files (bug 55589)
+                                               $compiler = ResourceLoader::getLessCompiler();
+                                               $cssFileContents = $compiler->compileFile( $cssFileName );
+                                       } else {
+                                               // Regular CSS file
+                                               $cssFileContents = file_get_contents( $cssFileName );
+                                       }
+
+                                       if ( $cssFileContents ) {
+                                               // Rewrite URLs, though don't bother embedding images. While static image
+                                               // files may be cached, CSS returned by this function is definitely not.
+                                               $cssDirName = dirname( $cssFileName );
+                                               $css .= CSSMin::remap(
+                                                       /* source */ $cssFileContents,
+                                                       /* local */ $cssDirName,
+                                                       /* remote */ '..' . str_replace(
+                                                               array( $GLOBALS['IP'], DIRECTORY_SEPARATOR ),
+                                                               array( '', '/' ),
+                                                               $cssDirName
+                                                       ),
+                                                       /* embedData */ false
+                                               );
+                                       } else {
+                                               $prepend .= ResourceLoader::makeComment( "Unable to read $cssFileName." );
+                                       }
+                               } catch ( Exception $e ) {
+                                       $prepend .= ResourceLoader::formatException( $e );
+                               }
+
+                               $css .= "\n";
                        }
-
-                       $css .= "\n";
+                       wfRestoreWarnings();
                }
-               wfRestoreWarnings();
+
+               $css = $prepend . $css;
 
                if ( $dir == 'rtl' ) {
                        $css = CSSJanus::transform( $css, true );
@@ -258,16 +294,14 @@ class WebInstallerOutput {
 
        public function outputFooter() {
                if ( $this->useShortHeader ) {
-?>
-</body></html>
-<?php
+                       echo Html::closeElement( 'body' ) . Html::closeElement( 'html' );
+
                        return;
                }
 ?>
 
 </div></div>
 
-
 <div id="mw-panel">
        <div class="portal" id="p-logo">
          <a style="background-image: url(../skins/common/images/mediawiki.png);"
@@ -281,9 +315,8 @@ class WebInstallerOutput {
        </div></div>
 </div>
 
-</body>
-</html>
 <?php
+               echo Html::closeElement( 'body' ) . Html::closeElement( 'html' );
        }
 
        public function outputShortHeader() {
index e30373e..1c95d9a 100644 (file)
@@ -185,7 +185,6 @@ abstract class WebInstallerPage {
 }
 
 class WebInstaller_Language extends WebInstallerPage {
-
        public function execute() {
                global $wgLang;
                $r = $this->parent->request;
index 4003fa8..3c237bf 100644 (file)
@@ -123,28 +123,34 @@ class Interwiki {
                static $db, $site;
 
                wfDebug( __METHOD__ . "( $prefix )\n" );
-               if ( !$db ) {
-                       $db = CdbReader::open( $wgInterwikiCache );
-               }
-               /* Resolve site name */
-               if ( $wgInterwikiScopes >= 3 && !$site ) {
-                       $site = $db->get( '__sites:' . wfWikiID() );
-                       if ( $site == '' ) {
-                               $site = $wgInterwikiFallbackSite;
+               $value = false;
+               try {
+                       if ( !$db ) {
+                               $db = CdbReader::open( $wgInterwikiCache );
+                       }
+                       /* Resolve site name */
+                       if ( $wgInterwikiScopes >= 3 && !$site ) {
+                               $site = $db->get( '__sites:' . wfWikiID() );
+                               if ( $site == '' ) {
+                                       $site = $wgInterwikiFallbackSite;
+                               }
                        }
-               }
 
-               $value = $db->get( wfMemcKey( $prefix ) );
-               // Site level
-               if ( $value == '' && $wgInterwikiScopes >= 3 ) {
-                       $value = $db->get( "_{$site}:{$prefix}" );
-               }
-               // Global Level
-               if ( $value == '' && $wgInterwikiScopes >= 2 ) {
-                       $value = $db->get( "__global:{$prefix}" );
-               }
-               if ( $value == 'undef' ) {
-                       $value = '';
+                       $value = $db->get( wfMemcKey( $prefix ) );
+                       // Site level
+                       if ( $value == '' && $wgInterwikiScopes >= 3 ) {
+                               $value = $db->get( "_{$site}:{$prefix}" );
+                       }
+                       // Global Level
+                       if ( $value == '' && $wgInterwikiScopes >= 2 ) {
+                               $value = $db->get( "__global:{$prefix}" );
+                       }
+                       if ( $value == 'undef' ) {
+                               $value = '';
+                       }
+               } catch ( CdbException $e ) {
+                       wfDebug( __METHOD__ . ": CdbException caught, error message was "
+                               . $e->getMessage() );
                }
 
                return $value;
@@ -232,51 +238,55 @@ class Interwiki {
                static $db, $site;
 
                wfDebug( __METHOD__ . "()\n" );
-               if ( !$db ) {
-                       $db = CdbReader::open( $wgInterwikiCache );
-               }
-               /* Resolve site name */
-               if ( $wgInterwikiScopes >= 3 && !$site ) {
-                       $site = $db->get( '__sites:' . wfWikiID() );
-                       if ( $site == '' ) {
-                               $site = $wgInterwikiFallbackSite;
-                       }
-               }
-
-               // List of interwiki sources
-               $sources = array();
-               // Global Level
-               if ( $wgInterwikiScopes >= 2 ) {
-                       $sources[] = '__global';
-               }
-               // Site level
-               if ( $wgInterwikiScopes >= 3 ) {
-                       $sources[] = '_' . $site;
-               }
-               $sources[] = wfWikiID();
-
                $data = array();
-
-               foreach ( $sources as $source ) {
-                       $list = $db->get( "__list:{$source}" );
-                       foreach ( explode( ' ', $list ) as $iw_prefix ) {
-                               $row = $db->get( "{$source}:{$iw_prefix}" );
-                               if ( !$row ) {
-                                       continue;
+               try {
+                       if ( !$db ) {
+                               $db = CdbReader::open( $wgInterwikiCache );
+                       }
+                       /* Resolve site name */
+                       if ( $wgInterwikiScopes >= 3 && !$site ) {
+                               $site = $db->get( '__sites:' . wfWikiID() );
+                               if ( $site == '' ) {
+                                       $site = $wgInterwikiFallbackSite;
                                }
+                       }
 
-                               list( $iw_local, $iw_url ) = explode( ' ', $row );
-
-                               if ( $local !== null && $local != $iw_local ) {
-                                       continue;
+                       // List of interwiki sources
+                       $sources = array();
+                       // Global Level
+                       if ( $wgInterwikiScopes >= 2 ) {
+                               $sources[] = '__global';
+                       }
+                       // Site level
+                       if ( $wgInterwikiScopes >= 3 ) {
+                               $sources[] = '_' . $site;
+                       }
+                       $sources[] = wfWikiID();
+
+                       foreach ( $sources as $source ) {
+                               $list = $db->get( "__list:{$source}" );
+                               foreach ( explode( ' ', $list ) as $iw_prefix ) {
+                                       $row = $db->get( "{$source}:{$iw_prefix}" );
+                                       if ( !$row ) {
+                                               continue;
+                                       }
+
+                                       list( $iw_local, $iw_url ) = explode( ' ', $row );
+
+                                       if ( $local !== null && $local != $iw_local ) {
+                                               continue;
+                                       }
+
+                                       $data[$iw_prefix] = array(
+                                               'iw_prefix' => $iw_prefix,
+                                               'iw_url' => $iw_url,
+                                               'iw_local' => $iw_local,
+                                       );
                                }
-
-                               $data[$iw_prefix] = array(
-                                       'iw_prefix' => $iw_prefix,
-                                       'iw_url' => $iw_url,
-                                       'iw_local' => $iw_local,
-                               );
                        }
+               } catch ( CdbException $e ) {
+                       wfDebug( __METHOD__ . ": CdbException caught, error message was "
+                               . $e->getMessage() );
                }
 
                ksort( $data );
index ab7df5d..e33baf5 100644 (file)
  * @ingroup JobQueue
  */
 abstract class Job {
-       /**
-        * @var Title
-        */
-       var $title;
+       /** @var int Job identifier */
+       public $id;
+
+       /** @var string */
+       public $command;
 
-       var $command,
-               $params,
-               $id,
-               $removeDuplicates,
-               $error;
+       /** @var array|bool Array of job parameters or false if none */
+       public $params;
 
-       /** @var Array Additional queue metadata */
+       /** @var array Additional queue metadata */
        public $metadata = array();
 
+       /** @var Title */
+       protected $title;
+
+       /** @var bool Expensive jobs may set this to true */
+       protected $removeDuplicates;
+
+       /** @var string Text for error that occurred last */
+       protected $error;
+
        /*-------------------------------------------------------------------------
         * Abstract functions
         *------------------------------------------------------------------------*/
 
        /**
         * Run the job
-        * @return boolean success
+        * @return bool Success
         */
        abstract public function run();
 
@@ -60,7 +67,7 @@ abstract class Job {
         * Create the appropriate object to handle a specific job
         *
         * @param string $command Job command
-        * @param $title Title: Associated title
+        * @param Title $title Associated title
         * @param array|bool $params Job parameters
         * @param int $id Job identifier
         * @throws MWException
@@ -70,6 +77,7 @@ abstract class Job {
                global $wgJobClasses;
                if ( isset( $wgJobClasses[$command] ) ) {
                        $class = $wgJobClasses[$command];
+
                        return new $class( $title, $params, $id );
                }
                throw new MWException( "Invalid job command `{$command}`" );
@@ -122,7 +130,7 @@ abstract class Job {
         * Pop a job off the front of the queue.
         * This is subject to $wgJobTypesExcludedFromDefaultQueue.
         *
-        * @return Job or false if there's no jobs
+        * @return Job|bool False if there are no jobs
         * @deprecated since 1.21
         */
        public static function pop() {
@@ -145,11 +153,12 @@ abstract class Job {
                $this->params = $params;
                $this->id = $id;
 
-               $this->removeDuplicates = false; // expensive jobs may set this to true
+               // expensive jobs may set this to true
+               $this->removeDuplicates = false;
        }
 
        /**
-        * @return integer May be 0 for jobs stored outside the DB
+        * @return int May be 0 for jobs stored outside the DB
         * @deprecated since 1.22
         */
        public function getId() {
@@ -178,7 +187,7 @@ abstract class Job {
        }
 
        /**
-        * @return integer|null UNIX timestamp to delay running this job until, otherwise null
+        * @return int|null UNIX timestamp to delay running this job until, otherwise null
         * @since 1.22
         */
        public function getReleaseTimestamp() {
@@ -208,7 +217,7 @@ abstract class Job {
         * only checked if ignoreDuplicates() returns true, meaning that duplicate
         * jobs are supposed to be ignored.
         *
-        * @return Array Map of key/values
+        * @return array Map of key/values
         * @since 1.21
         */
        public function getDeduplicationInfo() {
@@ -225,13 +234,16 @@ abstract class Job {
                        // Likewise for jobs with different delay times
                        unset( $info['params']['jobReleaseTimestamp'] );
                }
+
                return $info;
        }
 
        /**
         * @see JobQueue::deduplicateRootJob()
         * @param string $key A key that identifies the task
-        * @return Array
+        * @return array Map of:
+        *   - rootJobSignature : hash (e.g. SHA1) that identifies the task
+        *   - rootJobTimestamp : TS_MW timestamp of this instance of the task
         * @since 1.21
         */
        public static function newRootJobParams( $key ) {
@@ -243,7 +255,7 @@ abstract class Job {
 
        /**
         * @see JobQueue::deduplicateRootJob()
-        * @return Array
+        * @return array
         * @since 1.21
         */
        public function getRootJobParams() {
@@ -305,6 +317,7 @@ abstract class Job {
                        if ( $paramString !== '' ) {
                                $s .= ' ' . $paramString;
                        }
+
                        return $s;
                } else {
                        return "{$this->command} $paramString";
index 6556ee8..8d93dc0 100644 (file)
  * @since 1.21
  */
 abstract class JobQueue {
-       protected $wiki; // string; wiki ID
-       protected $type; // string; job type
-       protected $order; // string; job priority for pop()
-       protected $claimTTL; // integer; seconds
-       protected $maxTries; // integer; maximum number of times to try a job
-       protected $checkDelay; // boolean; allow delayed jobs
+       /** @var string Wiki ID */
+       protected $wiki;
+
+       /** @var string Job type */
+       protected $type;
+
+       /** @var string Job priority for pop() */
+       protected $order;
+
+       /** @var int Time to live in seconds */
+       protected $claimTTL;
+
+       /** @var int Maximum number of times to try a job */
+       protected $maxTries;
+
+       /** @var bool Allow delayed jobs */
+       protected $checkDelay;
 
        /** @var BagOStuff */
        protected $dupCache;
@@ -44,7 +55,8 @@ abstract class JobQueue {
        const ROOTJOB_TTL = 2419200; // integer; seconds to remember root jobs (28 days)
 
        /**
-        * @param $params array
+        * @param array $params
+        * @throws MWException
         */
        protected function __construct( array $params ) {
                $this->wiki = $params['wiki'];
@@ -93,7 +105,7 @@ abstract class JobQueue {
         *
         * Queue classes should throw an exception if they do not support the options given.
         *
-        * @param $params array
+        * @param array $params
         * @return JobQueue
         * @throws MWException
         */
@@ -106,6 +118,7 @@ abstract class JobQueue {
                if ( !( $obj instanceof self ) ) {
                        throw new MWException( "Class '$class' is not a " . __CLASS__ . " class." );
                }
+
                return $obj;
        }
 
@@ -141,7 +154,7 @@ abstract class JobQueue {
        /**
         * Get the allowed queue orders for configuration validation
         *
-        * @return Array Subset of (random, timestamp, fifo, undefined)
+        * @return array Subset of (random, timestamp, fifo, undefined)
         */
        abstract protected function supportedOrders();
 
@@ -155,7 +168,7 @@ abstract class JobQueue {
        /**
         * Find out if delayed jobs are supported for configuration validation
         *
-        * @return boolean Whether delayed jobs are supported
+        * @return bool Whether delayed jobs are supported
         */
        protected function supportsDelayedJobs() {
                return false; // not implemented
@@ -177,6 +190,7 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $res = $this->doIsEmpty();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -192,19 +206,20 @@ abstract class JobQueue {
         *
         * If caching is used, this number might be out of date for a minute.
         *
-        * @return integer
+        * @return int
         * @throws JobQueueError
         */
        final public function getSize() {
                wfProfileIn( __METHOD__ );
                $res = $this->doGetSize();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
        /**
         * @see JobQueue::getSize()
-        * @return integer
+        * @return int
         */
        abstract protected function doGetSize();
 
@@ -214,19 +229,20 @@ abstract class JobQueue {
         *
         * If caching is used, this number might be out of date for a minute.
         *
-        * @return integer
+        * @return int
         * @throws JobQueueError
         */
        final public function getAcquiredCount() {
                wfProfileIn( __METHOD__ );
                $res = $this->doGetAcquiredCount();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
        /**
         * @see JobQueue::getAcquiredCount()
-        * @return integer
+        * @return int
         */
        abstract protected function doGetAcquiredCount();
 
@@ -236,7 +252,7 @@ abstract class JobQueue {
         *
         * If caching is used, this number might be out of date for a minute.
         *
-        * @return integer
+        * @return int
         * @throws JobQueueError
         * @since 1.22
         */
@@ -244,12 +260,13 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $res = $this->doGetDelayedCount();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
        /**
         * @see JobQueue::getDelayedCount()
-        * @return integer
+        * @return int
         */
        protected function doGetDelayedCount() {
                return 0; // not implemented
@@ -261,19 +278,20 @@ abstract class JobQueue {
         *
         * If caching is used, this number might be out of date for a minute.
         *
-        * @return integer
+        * @return int
         * @throws JobQueueError
         */
        final public function getAbandonedCount() {
                wfProfileIn( __METHOD__ );
                $res = $this->doGetAbandonedCount();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
        /**
         * @see JobQueue::getAbandonedCount()
-        * @return integer
+        * @return int
         */
        protected function doGetAbandonedCount() {
                return 0; // not implemented
@@ -284,8 +302,8 @@ abstract class JobQueue {
         * This does not require $wgJobClasses to be set for the given job type.
         * Outside callers should use JobQueueGroup::push() instead of this function.
         *
-        * @param $jobs Job|Array
-        * @param $flags integer Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @param Job|array $jobs A single job or an array of Jobs
+        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
         * @return bool Returns false on failure
         * @throws JobQueueError
         */
@@ -299,9 +317,9 @@ abstract class JobQueue {
         * Outside callers should use JobQueueGroup::push() instead of this function.
         *
         * @param array $jobs List of Jobs
-        * @param $flags integer Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @param int $flags Bitfield (supports JobQueue::QOS_ATOMIC)
+        * @throws MWException
         * @return bool Returns false on failure
-        * @throws JobQueueError
         */
        final public function batchPush( array $jobs, $flags = 0 ) {
                if ( !count( $jobs ) ) {
@@ -321,11 +339,14 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $ok = $this->doBatchPush( $jobs, $flags );
                wfProfileOut( __METHOD__ );
+
                return $ok;
        }
 
        /**
         * @see JobQueue::batchPush()
+        * @param array $jobs
+        * @param $flags
         * @return bool
         */
        abstract protected function doBatchPush( array $jobs, $flags );
@@ -335,8 +356,8 @@ abstract class JobQueue {
         * This requires $wgJobClasses to be set for the given job type.
         * Outside callers should use JobQueueGroup::pop() instead of this function.
         *
+        * @throws MWException
         * @return Job|bool Returns false if there are no jobs
-        * @throws JobQueueError
         */
        final public function pop() {
                global $wgJobClasses;
@@ -358,7 +379,9 @@ abstract class JobQueue {
                                JobQueue::incrStats( 'job-pop-duplicate', $this->type );
                                $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
                        }
-               } catch ( MWException $e ) {} // don't lose jobs over this
+               } catch ( MWException $e ) {
+                       // don't lose jobs over this
+               }
 
                return $job;
        }
@@ -375,9 +398,9 @@ abstract class JobQueue {
         * This does nothing for certain queue classes or if "claimTTL" is not set.
         * Outside callers should use JobQueueGroup::ack() instead of this function.
         *
-        * @param $job Job
+        * @param Job $job
+        * @throws MWException
         * @return bool
-        * @throws JobQueueError
         */
        final public function ack( Job $job ) {
                if ( $job->getType() !== $this->type ) {
@@ -386,11 +409,13 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $ok = $this->doAck( $job );
                wfProfileOut( __METHOD__ );
+
                return $ok;
        }
 
        /**
         * @see JobQueue::ack()
+        * @param Job $job
         * @return bool
         */
        abstract protected function doAck( Job $job );
@@ -422,9 +447,9 @@ abstract class JobQueue {
         *
         * This does nothing for certain queue classes.
         *
-        * @param $job Job
+        * @param Job $job
+        * @throws MWException
         * @return bool
-        * @throws JobQueueError
         */
        final public function deduplicateRootJob( Job $job ) {
                if ( $job->getType() !== $this->type ) {
@@ -433,12 +458,14 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $ok = $this->doDeduplicateRootJob( $job );
                wfProfileOut( __METHOD__ );
+
                return $ok;
        }
 
        /**
         * @see JobQueue::deduplicateRootJob()
-        * @param $job Job
+        * @param Job $job
+        * @throws MWException
         * @return bool
         */
        protected function doDeduplicateRootJob( Job $job ) {
@@ -465,9 +492,9 @@ abstract class JobQueue {
        /**
         * Check if the "root" job of a given job has been superseded by a newer one
         *
-        * @param $job Job
+        * @param Job $job
+        * @throws MWException
         * @return bool
-        * @throws JobQueueError
         */
        final protected function isRootJobOldDuplicate( Job $job ) {
                if ( $job->getType() !== $this->type ) {
@@ -476,6 +503,7 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $isDuplicate = $this->doIsRootJobOldDuplicate( $job );
                wfProfileOut( __METHOD__ );
+
                return $isDuplicate;
        }
 
@@ -504,6 +532,7 @@ abstract class JobQueue {
         */
        protected function getRootJobCacheKey( $signature ) {
                list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+
                return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, 'rootjob', $signature );
        }
 
@@ -518,11 +547,13 @@ abstract class JobQueue {
                wfProfileIn( __METHOD__ );
                $res = $this->doDelete();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
        /**
         * @see JobQueue::delete()
+        * @throws MWException
         * @return bool Success
         */
        protected function doDelete() {
@@ -547,7 +578,8 @@ abstract class JobQueue {
         * @see JobQueue::waitForBackups()
         * @return void
         */
-       protected function doWaitForBackups() {}
+       protected function doWaitForBackups() {
+       }
 
        /**
         * Return a map of task names to task definition maps.
@@ -559,19 +591,20 @@ abstract class JobQueue {
         *   - callback : a PHP callable that performs the task
         *   - period   : the period in seconds corresponding to the task frequency
         *
-        * @return Array
+        * @return array
         */
        final public function getPeriodicTasks() {
                $tasks = $this->doGetPeriodicTasks();
                foreach ( $tasks as $name => &$def ) {
                        $def['name'] = $name;
                }
+
                return $tasks;
        }
 
        /**
         * @see JobQueue::getPeriodicTasks()
-        * @return Array
+        * @return array
         */
        protected function doGetPeriodicTasks() {
                return array();
@@ -592,7 +625,8 @@ abstract class JobQueue {
         * @see JobQueue::flushCaches()
         * @return void
         */
-       protected function doFlushCaches() {}
+       protected function doFlushCaches() {
+       }
 
        /**
         * Get an iterator to traverse over all available jobs in this queue.
@@ -637,6 +671,7 @@ abstract class JobQueue {
         */
        final public function getSiblingQueuesWithJobs( array $types ) {
                $section = new ProfileSection( __METHOD__ );
+
                return $this->doGetSiblingQueuesWithJobs( $types );
        }
 
@@ -661,6 +696,7 @@ abstract class JobQueue {
         */
        final public function getSiblingQueueSizes( array $types ) {
                $section = new ProfileSection( __METHOD__ );
+
                return $this->doGetSiblingQueueSizes( $types );
        }
 
@@ -678,7 +714,7 @@ abstract class JobQueue {
         *
         * @param string $key Event type
         * @param string $type Job type
-        * @param integer $delta
+        * @param int $delta
         * @since 1.22
         */
        public static function incrStats( $key, $type, $delta = 1 ) {
@@ -689,7 +725,7 @@ abstract class JobQueue {
        /**
         * Namespace the queue with a key to isolate it for testing
         *
-        * @param $key string
+        * @param string $key
         * @return void
         * @throws MWException
         */
@@ -702,5 +738,8 @@ abstract class JobQueue {
  * @ingroup JobQueue
  * @since 1.22
  */
-class JobQueueError extends MWException {}
-class JobQueueConnectionError extends JobQueueError {}
+class JobQueueError extends MWException {
+}
+
+class JobQueueConnectionError extends JobQueueError {
+}
index c39083d..b795695 100644 (file)
@@ -37,7 +37,8 @@ class JobQueueDB extends JobQueue {
        /** @var BagOStuff */
        protected $cache;
 
-       protected $cluster = false; // string; name of an external DB cluster
+       /** @var bool|string Name of an external DB cluster. False if not set */
+       protected $cluster = false;
 
        /**
         * Additional parameters include:
@@ -45,7 +46,7 @@ class JobQueueDB extends JobQueue {
         *               If not specified, the primary DB cluster for the wiki will be used.
         *               This can be overridden with a custom cluster so that DB handles will
         *               be retrieved via LBFactory::getExternalLB() and getConnection().
-        * @param $params array
+        * @param array $params
         */
        protected function __construct( array $params ) {
                global $wgMemc;
@@ -94,7 +95,7 @@ class JobQueueDB extends JobQueue {
 
        /**
         * @see JobQueue::doGetSize()
-        * @return integer
+        * @return int
         */
        protected function doGetSize() {
                $key = $this->getCacheKey( 'size' );
@@ -120,7 +121,7 @@ class JobQueueDB extends JobQueue {
 
        /**
         * @see JobQueue::doGetAcquiredCount()
-        * @return integer
+        * @return int
         */
        protected function doGetAcquiredCount() {
                if ( $this->claimTTL <= 0 ) {
@@ -150,7 +151,7 @@ class JobQueueDB extends JobQueue {
 
        /**
         * @see JobQueue::doGetAbandonedCount()
-        * @return integer
+        * @return int
         * @throws MWException
         */
        protected function doGetAbandonedCount() {
@@ -198,7 +199,7 @@ class JobQueueDB extends JobQueue {
                $that = $this;
                $method = __METHOD__;
                $dbw->onTransactionIdle(
-                       function() use ( $dbw, $that, $jobs, $flags, $method ) {
+                       function () use ( $dbw, $that, $jobs, $flags, $method ) {
                                $that->doBatchPushInternal( $dbw, $jobs, $flags, $method );
                        }
                );
@@ -209,12 +210,12 @@ class JobQueueDB extends JobQueue {
        /**
         * This function should *not* be called outside of JobQueueDB
         *
-        * @param DatabaseBase $dbw
+        * @param IDatabase $dbw
         * @param array $jobs
         * @param int $flags
         * @param string $method
-        * @return boolean
-        * @throws type
+        * @throws DBError
+        * @return bool
         */
        public function doBatchPushInternal( IDatabase $dbw, array $jobs, $flags, $method ) {
                if ( !count( $jobs ) ) {
@@ -258,8 +259,11 @@ class JobQueueDB extends JobQueue {
                                $dbw->insert( 'job', $rowBatch, $method );
                        }
                        JobQueue::incrStats( 'job-insert', $this->type, count( $rows ) );
-                       JobQueue::incrStats( 'job-insert-duplicate', $this->type,
-                               count( $rowSet ) + count( $rowList ) - count( $rows ) );
+                       JobQueue::incrStats(
+                               'job-insert-duplicate',
+                               $this->type,
+                               count( $rowSet ) + count( $rowList ) - count( $rows )
+                       );
                } catch ( DBError $e ) {
                        if ( $flags & self::QOS_ATOMIC ) {
                                $dbw->rollback( $method );
@@ -289,7 +293,7 @@ class JobQueueDB extends JobQueue {
                        $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
                        $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
                        $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
-                       $scopedReset = new ScopedCallback( function() use ( $dbw, $autoTrx ) {
+                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
                                $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
                        } );
 
@@ -336,7 +340,7 @@ class JobQueueDB extends JobQueue {
         * @param string $uuid 32 char hex string
         * @param $rand integer Random unsigned integer (31 bits)
         * @param bool $gte Search for job_random >= $random (otherwise job_random <= $random)
-        * @return Row|false
+        * @return stdClass|bool Row|false
         */
        protected function claimRandom( $uuid, $rand, $gte ) {
                $dbw = $this->getMasterDB();
@@ -386,6 +390,7 @@ class JobQueueDB extends JobQueue {
                                        continue; // use job_random
                                }
                        }
+
                        if ( $row ) { // claim the job
                                $dbw->update( 'job', // update by PK
                                        array(
@@ -412,7 +417,7 @@ class JobQueueDB extends JobQueue {
         * Reserve a row with a single UPDATE without holding row locks over RTTs...
         *
         * @param string $uuid 32 char hex string
-        * @return Row|false
+        * @return stdClass|bool Row|false
         */
        protected function claimOldest( $uuid ) {
                $dbw = $this->getMasterDB();
@@ -485,7 +490,7 @@ class JobQueueDB extends JobQueue {
                        $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction
                        $autoTrx = $dbw->getFlag( DBO_TRX ); // get current setting
                        $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
-                       $scopedReset = new ScopedCallback( function() use ( $dbw, $autoTrx ) {
+                       $scopedReset = new ScopedCallback( function () use ( $dbw, $autoTrx ) {
                                $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore old setting
                        } );
 
@@ -520,7 +525,7 @@ class JobQueueDB extends JobQueue {
                // jobs to become no-ops without any actual jobs that made them redundant.
                $dbw = $this->getMasterDB();
                $cache = $this->dupCache;
-               $dbw->onTransactionIdle( function() use ( $cache, $params, $key, $dbw ) {
+               $dbw->onTransactionIdle( function () use ( $cache, $params, $key, $dbw ) {
                        $timestamp = $cache->get( $key ); // current last timestamp of this job
                        if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
                                return true; // a newer version of this root job was enqueued
@@ -544,6 +549,7 @@ class JobQueueDB extends JobQueue {
                } catch ( DBError $e ) {
                        $this->throwDBException( $e );
                }
+
                return true;
        }
 
@@ -556,7 +562,7 @@ class JobQueueDB extends JobQueue {
        }
 
        /**
-        * @return Array
+        * @return array
         */
        protected function doGetPeriodicTasks() {
                return array(
@@ -586,7 +592,7 @@ class JobQueueDB extends JobQueue {
                        return new MappedIterator(
                                $dbr->select( 'job', '*',
                                        array( 'job_cmd' => $this->getType(), 'job_token' => '' ) ),
-                               function( $row ) use ( $dbr ) {
+                               function ( $row ) use ( $dbr ) {
                                        $job = Job::factory(
                                                $row->job_cmd,
                                                Title::makeTitle( $row->job_namespace, $row->job_title ),
@@ -618,6 +624,7 @@ class JobQueueDB extends JobQueue {
                foreach ( $res as $row ) {
                        $types[] = $row->job_cmd;
                }
+
                return $types;
        }
 
@@ -630,13 +637,14 @@ class JobQueueDB extends JobQueue {
                foreach ( $res as $row ) {
                        $sizes[$row->job_cmd] = (int)$row->count;
                }
+
                return $sizes;
        }
 
        /**
         * Recycle or destroy any jobs that have been claimed for too long
         *
-        * @return integer Number of jobs recycled/deleted
+        * @return int Number of jobs recycled/deleted
         */
        public function recycleAndDeleteStaleJobs() {
                $now = time();
@@ -663,7 +671,7 @@ class JobQueueDB extends JobQueue {
                                        __METHOD__
                                );
                                $ids = array_map(
-                                       function( $o ) {
+                                       function ( $o ) {
                                                return $o->job_id;
                                        }, iterator_to_array( $res )
                                );
@@ -699,7 +707,7 @@ class JobQueueDB extends JobQueue {
                        // the IDs first means that the UPDATE can be done by primary key (less deadlocks).
                        $res = $dbw->select( 'job', 'job_id', $conds, __METHOD__ );
                        $ids = array_map(
-                               function( $o ) {
+                               function ( $o ) {
                                        return $o->job_id;
                                }, iterator_to_array( $res )
                        );
@@ -718,29 +726,31 @@ class JobQueueDB extends JobQueue {
        }
 
        /**
-        * @param $job Job
+        * @param Job $job
         * @return array
         */
        protected function insertFields( Job $job ) {
                $dbw = $this->getMasterDB();
+
                return array(
                        // Fields that describe the nature of the job
-                       'job_cmd'       => $job->getType(),
+                       'job_cmd' => $job->getType(),
                        'job_namespace' => $job->getTitle()->getNamespace(),
-                       'job_title'     => $job->getTitle()->getDBkey(),
-                       'job_params'    => self::makeBlob( $job->getParams() ),
+                       'job_title' => $job->getTitle()->getDBkey(),
+                       'job_params' => self::makeBlob( $job->getParams() ),
                        // Additional job metadata
-                       'job_id'        => $dbw->nextSequenceValue( 'job_job_id_seq' ),
+                       'job_id' => $dbw->nextSequenceValue( 'job_job_id_seq' ),
                        'job_timestamp' => $dbw->timestamp(),
-                       'job_sha1'      => wfBaseConvert(
+                       'job_sha1' => wfBaseConvert(
                                sha1( serialize( $job->getDeduplicationInfo() ) ),
                                16, 36, 31
                        ),
-                       'job_random'    => mt_rand( 0, self::MAX_JOB_RANDOM )
+                       'job_random' => mt_rand( 0, self::MAX_JOB_RANDOM )
                );
        }
 
        /**
+        * @throws JobQueueConnectionError
         * @return DBConnRef
         */
        protected function getSlaveDB() {
@@ -752,6 +762,7 @@ class JobQueueDB extends JobQueue {
        }
 
        /**
+        * @throws JobQueueConnectionError
         * @return DBConnRef
         */
        protected function getMasterDB() {
@@ -770,15 +781,18 @@ class JobQueueDB extends JobQueue {
                $lb = ( $this->cluster !== false )
                        ? wfGetLBFactory()->getExternalLB( $this->cluster, $this->wiki )
                        : wfGetLB( $this->wiki );
+
                return $lb->getConnectionRef( $index, array(), $this->wiki );
        }
 
        /**
+        * @param $property
         * @return string
         */
        private function getCacheKey( $property ) {
                list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
                $cluster = is_string( $this->cluster ) ? $this->cluster : 'main';
+
                return wfForeignMemcKey( $db, $prefix, 'jobqueue', $cluster, $this->type, $property );
        }
 
index d3ce164..589bed6 100644 (file)
  * @since 1.22
  */
 class JobQueueFederated extends JobQueue {
-       /** @var Array (partition name => weight) reverse sorted by weight */
+       /** @var array (partition name => weight) reverse sorted by weight */
        protected $partitionMap = array();
-       /** @var Array (partition name => JobQueue) reverse sorted by weight */
+
+       /** @var array (partition name => JobQueue) reverse sorted by weight */
        protected $partitionQueues = array();
+
        /** @var HashRing */
        protected $partitionPushRing;
+
        /** @var BagOStuff */
        protected $cache;
 
+       /** @var int Maximum number of partitions to try */
+       protected $maxPartitionsTry;
+
        const CACHE_TTL_SHORT = 30; // integer; seconds to cache info without re-validating
        const CACHE_TTL_LONG = 300; // integer; seconds to cache info that is kept up to date
 
@@ -72,7 +78,12 @@ class JobQueueFederated extends JobQueue {
         *                          the federated queue itself (e.g. 'order' and 'claimTTL').
         *  - partitionsNoPush    : List of partition names that can handle pop() but not push().
         *                          This can be used to migrate away from a certain partition.
+        *  - maxPartitionsTry    : Maximum number of times to attempt job insertion using
+        *                          different partition queues. This improves availability
+        *                          during failure, at the cost of added latency and somewhat
+        *                          less reliable job de-duplication mechanisms.
         * @param array $params
+        * @throws MWException
         */
        protected function __construct( array $params ) {
                parent::__construct( $params );
@@ -82,6 +93,9 @@ class JobQueueFederated extends JobQueue {
                if ( !isset( $params['partitionsBySection'][$section] ) ) {
                        throw new MWException( "No configuration for section '$section'." );
                }
+               $this->maxPartitionsTry = isset( $params['maxPartitionsTry'] )
+                       ? $params['maxPartitionsTry']
+                       : 2;
                // Get the full partition map
                $this->partitionMap = $params['partitionsBySection'][$section];
                arsort( $this->partitionMap, SORT_NUMERIC );
@@ -94,10 +108,10 @@ class JobQueueFederated extends JobQueue {
                }
                // Get the config to pass to merge into each partition queue config
                $baseConfig = $params;
-               foreach ( array( 'class', 'sectionsByWiki',
-                       'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o )
-               {
-                       unset( $baseConfig[$o] );
+               foreach ( array( 'class', 'sectionsByWiki', 'maxPartitionsTry',
+                       'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o
+               {
+                       unset( $baseConfig[$o] ); // partition queue doesn't care about this
                }
                // Get the partition queue objects
                foreach ( $this->partitionMap as $partition => $w ) {
@@ -140,6 +154,7 @@ class JobQueueFederated extends JobQueue {
                        try {
                                if ( !$queue->doIsEmpty() ) {
                                        $this->cache->add( $key, 'false', self::CACHE_TTL_LONG );
+
                                        return false;
                                }
                        } catch ( JobQueueError $e ) {
@@ -148,6 +163,7 @@ class JobQueueFederated extends JobQueue {
                }
 
                $this->cache->add( $key, 'true', self::CACHE_TTL_LONG );
+
                return true;
        }
 
@@ -170,7 +186,7 @@ class JobQueueFederated extends JobQueue {
        /**
         * @param string $type
         * @param string $method
-        * @return integer
+        * @return int
         */
        protected function getCrossPartitionSum( $type, $method ) {
                $key = $this->getCacheKey( $type );
@@ -190,28 +206,32 @@ class JobQueueFederated extends JobQueue {
                }
 
                $this->cache->set( $key, $count, self::CACHE_TTL_SHORT );
+
                return $count;
        }
 
        protected function doBatchPush( array $jobs, $flags ) {
-               if ( !count( $jobs ) ) {
-                       return true; // nothing to do
-               }
                // Local ring variable that may be changed to point to a new ring on failure
                $partitionRing = $this->partitionPushRing;
-               // Try to insert the jobs and update $partitionsTry on any failures
-               $jobsLeft = $this->tryJobInsertions( $jobs, $partitionRing, $flags );
-               if ( count( $jobsLeft ) ) { // some jobs failed to insert?
-                       // Try to insert the remaning jobs once more, ignoring the bad partitions
-                       return !count( $this->tryJobInsertions( $jobsLeft, $partitionRing, $flags ) );
+               // Try to insert the jobs and update $partitionsTry on any failures.
+               // Retry to insert any remaning jobs again, ignoring the bad partitions.
+               $jobsLeft = $jobs;
+               for ( $i = $this->maxPartitionsTry; $i > 0 && count( $jobsLeft ); --$i ) {
+                       $jobsLeft = $this->tryJobInsertions( $jobsLeft, $partitionRing, $flags );
+               }
+               if ( count( $jobsLeft ) ) {
+                       throw new JobQueueError(
+                               "Could not insert job(s), {$this->maxPartitionsTry} partitions tried." );
                }
+
                return true;
        }
 
        /**
         * @param array $jobs
         * @param HashRing $partitionRing
-        * @param integer $flags
+        * @param int $flags
+        * @throws JobQueueError
         * @return array List of Job object that could not be inserted
         */
        protected function tryJobInsertions( array $jobs, HashRing &$partitionRing, $flags ) {
@@ -221,6 +241,7 @@ class JobQueueFederated extends JobQueue {
                // to use a consistent hash to avoid allowing duplicate jobs per partition.
                // When inserting a batch of de-duplicated jobs, QOS_ATOMIC is disregarded.
                $uJobsByPartition = array(); // (partition name => job list)
+               /** @var Job $job */
                foreach ( $jobs as $key => $job ) {
                        if ( $job->ignoreDuplicates() ) {
                                $sha1 = sha1( serialize( $job->getDeduplicationInfo() ) );
@@ -240,6 +261,7 @@ class JobQueueFederated extends JobQueue {
 
                // Insert the de-duplicated jobs into the queues...
                foreach ( $uJobsByPartition as $partition => $jobBatch ) {
+                       /** @var JobQueue $queue */
                        $queue = $this->partitionQueues[$partition];
                        try {
                                $ok = $queue->doBatchPush( $jobBatch, $flags | self::QOS_ATOMIC );
@@ -299,6 +321,8 @@ class JobQueueFederated extends JobQueue {
                        if ( $partition === false ) {
                                break; // all partitions at 0 weight
                        }
+
+                       /** @var JobQueue $queue */
                        $queue = $this->partitionQueues[$partition];
                        try {
                                $job = $queue->pop();
@@ -308,6 +332,7 @@ class JobQueueFederated extends JobQueue {
                        }
                        if ( $job ) {
                                $job->metadata['QueuePartition'] = $partition;
+
                                return $job;
                        } else {
                                unset( $partitionsTry[$partition] ); // blacklist partition
@@ -315,6 +340,7 @@ class JobQueueFederated extends JobQueue {
                }
 
                $this->cache->set( $key, 'true', JobQueueDB::CACHE_TTL_LONG );
+
                return false;
        }
 
@@ -322,6 +348,7 @@ class JobQueueFederated extends JobQueue {
                if ( !isset( $job->metadata['QueuePartition'] ) ) {
                        throw new MWException( "The given job has no defined partition name." );
                }
+
                return $this->partitionQueues[$job->metadata['QueuePartition']]->ack( $job );
        }
 
@@ -335,6 +362,7 @@ class JobQueueFederated extends JobQueue {
                                return $this->partitionQueues[$partitions[1]]->doIsRootJobOldDuplicate( $job );
                        }
                }
+
                return false;
        }
 
@@ -348,10 +376,12 @@ class JobQueueFederated extends JobQueue {
                                return $this->partitionQueues[$partitions[1]]->doDeduplicateRootJob( $job );
                        }
                }
+
                return false;
        }
 
        protected function doDelete() {
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        try {
                                $queue->doDelete();
@@ -362,6 +392,7 @@ class JobQueueFederated extends JobQueue {
        }
 
        protected function doWaitForBackups() {
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        try {
                                $queue->waitForBackups();
@@ -373,11 +404,13 @@ class JobQueueFederated extends JobQueue {
 
        protected function doGetPeriodicTasks() {
                $tasks = array();
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $partition => $queue ) {
                        foreach ( $queue->getPeriodicTasks() as $task => $def ) {
                                $tasks["{$partition}:{$task}"] = $def;
                        }
                }
+
                return $tasks;
        }
 
@@ -389,9 +422,12 @@ class JobQueueFederated extends JobQueue {
                        'delayedcount',
                        'abandonedcount'
                );
+
                foreach ( $types as $type ) {
                        $this->cache->delete( $this->getCacheKey( $type ) );
                }
+
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        $queue->doFlushCaches();
                }
@@ -399,17 +435,23 @@ class JobQueueFederated extends JobQueue {
 
        public function getAllQueuedJobs() {
                $iterator = new AppendIterator();
+
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        $iterator->append( $queue->getAllQueuedJobs() );
                }
+
                return $iterator;
        }
 
        public function getAllDelayedJobs() {
                $iterator = new AppendIterator();
+
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        $iterator->append( $queue->getAllDelayedJobs() );
                }
+
                return $iterator;
        }
 
@@ -420,6 +462,8 @@ class JobQueueFederated extends JobQueue {
 
        protected function doGetSiblingQueuesWithJobs( array $types ) {
                $result = array();
+
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        try {
                                $nonEmpty = $queue->doGetSiblingQueuesWithJobs( $types );
@@ -435,11 +479,14 @@ class JobQueueFederated extends JobQueue {
                                MWExceptionHandler::logException( $e );
                        }
                }
+
                return array_values( $result );
        }
 
        protected function doGetSiblingQueueSizes( array $types ) {
                $result = array();
+
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        try {
                                $sizes = $queue->doGetSiblingQueueSizes( $types );
@@ -454,20 +501,24 @@ class JobQueueFederated extends JobQueue {
                                MWExceptionHandler::logException( $e );
                        }
                }
+
                return $result;
        }
 
        public function setTestingPrefix( $key ) {
+               /** @var JobQueue $queue */
                foreach ( $this->partitionQueues as $queue ) {
                        $queue->setTestingPrefix( $key );
                }
        }
 
        /**
+        * @param $property
         * @return string
         */
        private function getCacheKey( $property ) {
                list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
+
                return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $property );
        }
 }
index a20ea4a..a3ec8a7 100644 (file)
  * @since 1.21
  */
 class JobQueueGroup {
-       /** @var Array */
+       /** @var array */
        protected static $instances = array();
 
        /** @var ProcessCacheLRU */
        protected $cache;
 
-       protected $wiki; // string; wiki ID
+       /** @var string Wiki ID */
+       protected $wiki;
 
        /** @var array Map of (bucket => (queue => JobQueue, types => list of types) */
        protected $coalescedQueues;
@@ -58,7 +59,7 @@ class JobQueueGroup {
        }
 
        /**
-        * @param string $wiki Wiki ID
+        * @param bool|string $wiki Wiki ID
         * @return JobQueueGroup
         */
        public static function singleton( $wiki = false ) {
@@ -66,6 +67,7 @@ class JobQueueGroup {
                if ( !isset( self::$instances[$wiki] ) ) {
                        self::$instances[$wiki] = new self( $wiki );
                }
+
                return self::$instances[$wiki];
        }
 
@@ -81,7 +83,7 @@ class JobQueueGroup {
        /**
         * Get the job queue object for a given queue type
         *
-        * @param $type string
+        * @param string $type
         * @return JobQueue
         */
        public function get( $type ) {
@@ -103,12 +105,15 @@ class JobQueueGroup {
         * This inserts the jobs into the queue specified by $wgJobTypeConf
         * and updates the aggregate job queue information cache as needed.
         *
-        * @param $jobs Job|array A single Job or a list of Jobs
+        * @param Job|array $jobs A single Job or a list of Jobs
         * @throws MWException
         * @return bool
         */
        public function push( $jobs ) {
                $jobs = is_array( $jobs ) ? $jobs : array( $jobs );
+               if ( !count( $jobs ) ) {
+                       return true;
+               }
 
                $jobsByType = array(); // (job type => list of jobs)
                foreach ( $jobs as $job ) {
@@ -144,8 +149,8 @@ class JobQueueGroup {
         * This pops a job off a queue as specified by $wgJobTypeConf and
         * updates the aggregate job queue information cache as needed.
         *
-        * @param $qtype integer|string JobQueueGroup::TYPE_DEFAULT or type string
-        * @param $flags integer Bitfield of JobQueueGroup::USE_* constants
+        * @param int|string $qtype JobQueueGroup::TYPE_DEFAULT or type string
+        * @param int $flags Bitfield of JobQueueGroup::USE_* constants
         * @return Job|bool Returns false on failure
         */
        public function pop( $qtype = self::TYPE_DEFAULT, $flags = 0 ) {
@@ -157,6 +162,7 @@ class JobQueueGroup {
                        if ( !$job ) {
                                JobQueueAggregator::singleton()->notifyQueueEmpty( $this->wiki, $qtype );
                        }
+
                        return $job;
                } else { // any job in the "default" jobs types
                        if ( $flags & self::USE_CACHE ) {
@@ -193,7 +199,7 @@ class JobQueueGroup {
        /**
         * Acknowledge that a job was completed
         *
-        * @param $job Job
+        * @param Job $job
         * @return bool
         */
        public function ack( Job $job ) {
@@ -204,7 +210,7 @@ class JobQueueGroup {
         * Register the "root job" of a given job into the queue for de-duplication.
         * This should only be called right *after* all the new jobs have been inserted.
         *
-        * @param $job Job
+        * @param Job $job
         * @return bool
         */
        public function deduplicateRootJob( Job $job ) {
@@ -253,7 +259,7 @@ class JobQueueGroup {
        /**
         * Get the list of job types that have non-empty queues
         *
-        * @return Array List of job types that have non-empty queues
+        * @return array List of job types that have non-empty queues
         */
        public function getQueuesWithJobs() {
                $types = array();
@@ -269,13 +275,14 @@ class JobQueueGroup {
                                }
                        }
                }
+
                return $types;
        }
 
        /**
         * Get the size of the queus for a list of job types
         *
-        * @return Array Map of (job type => size)
+        * @return array Map of (job type => size)
         */
        public function getQueueSizes() {
                $sizeMap = array();
@@ -289,6 +296,7 @@ class JobQueueGroup {
                                }
                        }
                }
+
                return $sizeMap;
        }
 
@@ -327,7 +335,7 @@ class JobQueueGroup {
         * This is only used for performance, such as to avoid spamming
         * the queue with many sub-jobs before they actually get run.
         *
-        * @param $type string
+        * @param string $type
         * @return bool
         */
        public function isQueueDeprioritized( $type ) {
@@ -335,12 +343,16 @@ class JobQueueGroup {
                        return $this->cache->get( 'isDeprioritized', $type );
                }
                if ( $type === 'refreshLinks2' ) {
-                       // Don't keep converting refreshLinks2 => refreshLinks jobs if the
+                       // Don't keep converting refreshLinksPartition => refreshLinks jobs if the
                        // later jobs have not been done yet. This helps throttle queue spam.
-                       $deprioritized = !$this->get( 'refreshLinks' )->isEmpty();
+                       // @TODO: this is mostly a WMF-specific hack and should be removed when
+                       // refreshLinks2 jobs are drained.
+                       $deprioritized = !$this->get( 'refreshLinks' )->getSize() > 10000;
                        $this->cache->set( 'isDeprioritized', $type, $deprioritized );
+
                        return $deprioritized;
                }
+
                return false;
        }
 
@@ -351,7 +363,7 @@ class JobQueueGroup {
         * the defined run period. Concurrent calls to this function will cause tasks
         * to be attempted twice, so they may need their own methods of mutual exclusion.
         *
-        * @return integer Number of tasks run
+        * @return int Number of tasks run
         */
        public function executeReadyPeriodicTasks() {
                global $wgMemc;
@@ -368,27 +380,27 @@ class JobQueueGroup {
                                if ( $definition['period'] <= 0 ) {
                                        continue; // disabled
                                } elseif ( !isset( $lastRuns[$type][$task] )
-                                       || $lastRuns[$type][$task] < ( time() - $definition['period'] ) )
-                               {
+                                       || $lastRuns[$type][$task] < ( time() - $definition['period'] )
+                               {
                                        try {
                                                if ( call_user_func( $definition['callback'] ) !== null ) {
                                                        $tasksRun[$type][$task] = time();
                                                        ++$count;
                                                }
                                        } catch ( JobQueueError $e ) {
-                                               wfDebugLog( 'exception', $e->getLogMessage() );
+                                               MWExceptionHandler::logException( $e );
                                        }
                                }
                        }
                }
 
-               $wgMemc->merge( $key, function( $cache, $key, $lastRuns ) use ( $tasksRun ) {
+               $wgMemc->merge( $key, function ( $cache, $key, $lastRuns ) use ( $tasksRun ) {
                        if ( is_array( $lastRuns ) ) {
                                foreach ( $tasksRun as $type => $tasks ) {
                                        foreach ( $tasks as $task => $timestamp ) {
                                                if ( !isset( $lastRuns[$type][$task] )
-                                                       || $timestamp > $lastRuns[$type][$task] )
-                                               {
+                                                       || $timestamp > $lastRuns[$type][$task]
+                                               {
                                                        $lastRuns[$type][$task] = $timestamp;
                                                }
                                        }
@@ -396,6 +408,7 @@ class JobQueueGroup {
                        } else {
                                $lastRuns = $tasksRun;
                        }
+
                        return $lastRuns;
                } );
 
@@ -420,6 +433,7 @@ class JobQueueGroup {
                        } else {
                                $value = $wgConf->getConfig( $this->wiki, $name );
                                $wgMemc->set( $key, array( 'v' => $value ), 86400 + mt_rand( 0, 86400 ) );
+
                                return $value;
                        }
                }
index 378e175..9d2a673 100644 (file)
@@ -60,17 +60,21 @@ class JobQueueRedis extends JobQueue {
        /** @var RedisConnectionPool */
        protected $redisPool;
 
-       protected $server; // string; server address
-       protected $compression; // string; compression method to use
+       /** @var string Server address */
+       protected $server;
+
+       /** @var string Compression method to use */
+       protected $compression;
 
        const MAX_AGE_PRUNE = 604800; // integer; seconds a job can live once claimed (7 days)
 
-       protected $key; // string; key to prefix the queue keys with (used for testing)
+       /** @var string Key to prefix the queue keys with (used for testing) */
+       protected $key;
 
        /**
         * @params include:
         *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
-        *                   Note that the serializer option is ignored "none" is always used.
+        *                   Note that the serializer option is ignored as "none" is always used.
         *   - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
         *                   If a hostname is specified but no port, the standard port number
         *                   6379 will be used. Required.
@@ -108,7 +112,7 @@ class JobQueueRedis extends JobQueue {
 
        /**
         * @see JobQueue::doGetSize()
-        * @return integer
+        * @return int
         * @throws MWException
         */
        protected function doGetSize() {
@@ -122,8 +126,8 @@ class JobQueueRedis extends JobQueue {
 
        /**
         * @see JobQueue::doGetAcquiredCount()
-        * @return integer
-        * @throws MWException
+        * @return int
+        * @throws JobQueueError
         */
        protected function doGetAcquiredCount() {
                if ( $this->claimTTL <= 0 ) {
@@ -134,6 +138,7 @@ class JobQueueRedis extends JobQueue {
                        $conn->multi( Redis::PIPELINE );
                        $conn->zSize( $this->getQueueKey( 'z-claimed' ) );
                        $conn->zSize( $this->getQueueKey( 'z-abandoned' ) );
+
                        return array_sum( $conn->exec() );
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
@@ -142,8 +147,8 @@ class JobQueueRedis extends JobQueue {
 
        /**
         * @see JobQueue::doGetDelayedCount()
-        * @return integer
-        * @throws MWException
+        * @return int
+        * @throws JobQueueError
         */
        protected function doGetDelayedCount() {
                if ( !$this->checkDelay ) {
@@ -159,8 +164,8 @@ class JobQueueRedis extends JobQueue {
 
        /**
         * @see JobQueue::doGetAbandonedCount()
-        * @return integer
-        * @throws MWException
+        * @return int
+        * @throws JobQueueError
         */
        protected function doGetAbandonedCount() {
                if ( $this->claimTTL <= 0 ) {
@@ -179,7 +184,7 @@ class JobQueueRedis extends JobQueue {
         * @param array $jobs
         * @param $flags
         * @return bool
-        * @throws MWException
+        * @throws JobQueueError
         */
        protected function doBatchPush( array $jobs, $flags ) {
                // Convert the jobs into field maps (de-duplicated against each other)
@@ -217,6 +222,7 @@ class JobQueueRedis extends JobQueue {
                        }
                        if ( $failed > 0 ) {
                                wfDebugLog( 'JobQueueRedis', "Could not insert {$failed} {$this->type} job(s)." );
+
                                return false;
                        }
                        JobQueue::incrStats( 'job-insert', $this->type, count( $items ) );
@@ -232,7 +238,7 @@ class JobQueueRedis extends JobQueue {
        /**
         * @param RedisConnRef $conn
         * @param array $items List of results from JobQueueRedis::getNewJobFields()
-        * @return integer Number of jobs inserted (duplicates are ignored)
+        * @return int Number of jobs inserted (duplicates are ignored)
         * @throws RedisException
         */
        protected function pushBlobs( RedisConnRef $conn, array $items ) {
@@ -245,23 +251,24 @@ class JobQueueRedis extends JobQueue {
                }
                static $script =
 <<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kDelayed, kData = unpack(KEYS)
                if #ARGV % 4 ~= 0 then return redis.error_reply('Unmatched arguments') end
                local pushed = 0
                for i = 1,#ARGV,4 do
                        local id,sha1,rtimestamp,blob = ARGV[i],ARGV[i+1],ARGV[i+2],ARGV[i+3]
-                       if sha1 == '' or redis.call('hExists',KEYS[3],sha1) == 0 then
+                       if sha1 == '' or redis.call('hExists',kIdBySha1,sha1) == 0 then
                                if 1*rtimestamp > 0 then
                                        -- Insert into delayed queue (release time as score)
-                                       redis.call('zAdd',KEYS[4],rtimestamp,id)
+                                       redis.call('zAdd',kDelayed,rtimestamp,id)
                                else
                                        -- Insert into unclaimed queue
-                                       redis.call('lPush',KEYS[1],id)
+                                       redis.call('lPush',kUnclaimed,id)
                                end
                                if sha1 ~= '' then
-                                       redis.call('hSet',KEYS[2],id,sha1)
-                                       redis.call('hSet',KEYS[3],sha1,id)
+                                       redis.call('hSet',kSha1ById,id,sha1)
+                                       redis.call('hSet',kIdBySha1,sha1,id)
                                end
-                               redis.call('hSet',KEYS[5],id,blob)
+                               redis.call('hSet',kData,id,blob)
                                pushed = pushed + 1
                        end
                end
@@ -285,7 +292,7 @@ LUA;
        /**
         * @see JobQueue::doPop()
         * @return Job|bool
-        * @throws MWException
+        * @throws JobQueueError
         */
        protected function doPop() {
                $job = false;
@@ -337,16 +344,17 @@ LUA;
        protected function popAndDeleteBlob( RedisConnRef $conn ) {
                static $script =
 <<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kData = unpack(KEYS)
                -- Pop an item off the queue
-               local id = redis.call('rpop',KEYS[1])
+               local id = redis.call('rpop',kUnclaimed)
                if not id then return false end
                -- Get the job data and remove it
-               local item = redis.call('hGet',KEYS[4],id)
-               redis.call('hDel',KEYS[4],id)
+               local item = redis.call('hGet',kData,id)
+               redis.call('hDel',kData,id)
                -- Allow new duplicates of this job
-               local sha1 = redis.call('hGet',KEYS[2],id)
-               if sha1 then redis.call('hDel',KEYS[3],sha1) end
-               redis.call('hDel',KEYS[2],id)
+               local sha1 = redis.call('hGet',kSha1ById,id)
+               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
+               redis.call('hDel',kSha1ById,id)
                -- Return the job data
                return item
 LUA;
@@ -369,17 +377,18 @@ LUA;
        protected function popAndAcquireBlob( RedisConnRef $conn ) {
                static $script =
 <<<LUA
+               local kUnclaimed, kSha1ById, kIdBySha1, kClaimed, kAttempts, kData = unpack(KEYS)
                -- Pop an item off the queue
-               local id = redis.call('rPop',KEYS[1])
+               local id = redis.call('rPop',kUnclaimed)
                if not id then return false end
                -- Allow new duplicates of this job
-               local sha1 = redis.call('hGet',KEYS[2],id)
-               if sha1 then redis.call('hDel',KEYS[3],sha1) end
-               redis.call('hDel',KEYS[2],id)
+               local sha1 = redis.call('hGet',kSha1ById,id)
+               if sha1 then redis.call('hDel',kIdBySha1,sha1) end
+               redis.call('hDel',kSha1ById,id)
                -- Mark the jobs as claimed and return it
-               redis.call('zAdd',KEYS[4],ARGV[1],id)
-               redis.call('hIncrBy',KEYS[5],id,1)
-               return redis.call('hGet',KEYS[6],id)
+               redis.call('zAdd',kClaimed,ARGV[1],id)
+               redis.call('hIncrBy',kAttempts,id,1)
+               return redis.call('hGet',kData,id)
 LUA;
                return $conn->luaEval( $script,
                        array(
@@ -399,7 +408,7 @@ LUA;
         * @see JobQueue::doAck()
         * @param Job $job
         * @return Job|bool
-        * @throws MWException
+        * @throws MWException|JobQueueError
         */
        protected function doAck( Job $job ) {
                if ( !isset( $job->metadata['uuid'] ) ) {
@@ -410,11 +419,12 @@ LUA;
                        try {
                                static $script =
 <<<LUA
+                               local kClaimed, kAttempts, kData = unpack(KEYS)
                                -- Unmark the job as claimed
-                               redis.call('zRem',KEYS[1],ARGV[1])
-                               redis.call('hDel',KEYS[2],ARGV[1])
+                               redis.call('zRem',kClaimed,ARGV[1])
+                               redis.call('hDel',kAttempts,ARGV[1])
                                -- Delete the job data itself
-                               return redis.call('hDel',KEYS[3],ARGV[1])
+                               return redis.call('hDel',kData,ARGV[1])
 LUA;
                                $res = $conn->luaEval( $script,
                                        array(
@@ -428,12 +438,14 @@ LUA;
 
                                if ( !$res ) {
                                        wfDebugLog( 'JobQueueRedis', "Could not acknowledge {$this->type} job." );
+
                                        return false;
                                }
                        } catch ( RedisException $e ) {
                                $this->throwRedisException( $this->server, $conn, $e );
                        }
                }
+
                return true;
        }
 
@@ -441,7 +453,7 @@ LUA;
         * @see JobQueue::doDeduplicateRootJob()
         * @param Job $job
         * @return bool
-        * @throws MWException
+        * @throws MWException|JobQueueError
         */
        protected function doDeduplicateRootJob( Job $job ) {
                if ( !$job->hasRootJobParams() ) {
@@ -457,6 +469,7 @@ LUA;
                        if ( $timestamp && $timestamp >= $params['rootJobTimestamp'] ) {
                                return true; // a newer version of this root job was enqueued
                        }
+
                        // Update the timestamp of the last root job started at the location...
                        return $conn->set( $key, $params['rootJobTimestamp'], self::ROOTJOB_TTL ); // 2 weeks
                } catch ( RedisException $e ) {
@@ -468,6 +481,7 @@ LUA;
         * @see JobQueue::doIsRootJobOldDuplicate()
         * @param Job $job
         * @return bool
+        * @throws JobQueueError
         */
        protected function doIsRootJobOldDuplicate( Job $job ) {
                if ( !$job->hasRootJobParams() ) {
@@ -490,6 +504,7 @@ LUA;
        /**
         * @see JobQueue::doDelete()
         * @return bool
+        * @throws JobQueueError
         */
        protected function doDelete() {
                static $props = array( 'l-unclaimed', 'z-claimed', 'z-abandoned',
@@ -501,6 +516,7 @@ LUA;
                        foreach ( $props as $prop ) {
                                $keys[] = $this->getQueueKey( $prop );
                        }
+
                        return ( $conn->delete( $keys ) !== false );
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
@@ -515,12 +531,15 @@ LUA;
                $conn = $this->getConnection();
                try {
                        $that = $this;
+
                        return new MappedIterator(
                                $conn->lRange( $this->getQueueKey( 'l-unclaimed' ), 0, -1 ),
-                               function( $uid ) use ( $that, $conn ) {
+                               function ( $uid ) use ( $that, $conn ) {
                                        return $that->getJobFromUidInternal( $uid, $conn );
                                },
-                               array( 'accept' => function ( $job ) { return is_object( $job ); } )
+                               array( 'accept' => function ( $job ) {
+                                       return is_object( $job );
+                               } )
                        );
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
@@ -535,12 +554,15 @@ LUA;
                $conn = $this->getConnection();
                try {
                        $that = $this;
+
                        return new MappedIterator( // delayed jobs
                                $conn->zRange( $this->getQueueKey( 'z-delayed' ), 0, -1 ),
-                               function( $uid ) use ( $that, $conn ) {
+                               function ( $uid ) use ( $that, $conn ) {
                                        return $that->getJobFromUidInternal( $uid, $conn );
                                },
-                               array( 'accept' => function ( $job ) { return is_object( $job ); } )
+                               array( 'accept' => function ( $job ) {
+                                       return is_object( $job );
+                               } )
                        );
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
@@ -573,6 +595,7 @@ LUA;
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
                }
+
                return $sizes;
        }
 
@@ -582,7 +605,7 @@ LUA;
         * @param $uid string
         * @param $conn RedisConnRef
         * @return Job|bool Returns false if the job does not exist
-        * @throws MWException
+        * @throws MWException|JobQueueError
         */
        public function getJobFromUidInternal( $uid, RedisConnRef $conn ) {
                try {
@@ -597,6 +620,7 @@ LUA;
                        $title = Title::makeTitle( $item['namespace'], $item['title'] );
                        $job = Job::factory( $item['type'], $title, $item['params'] );
                        $job->metadata['uuid'] = $item['uuid'];
+
                        return $job;
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $this->server, $conn, $e );
@@ -606,8 +630,8 @@ LUA;
        /**
         * Release any ready delayed jobs into the queue
         *
-        * @return integer Number of jobs released
-        * @throws MWException
+        * @return int Number of jobs released
+        * @throws JobQueueError
         */
        public function releaseReadyDelayedJobs() {
                $count = 0;
@@ -616,12 +640,13 @@ LUA;
                try {
                        static $script =
 <<<LUA
+                       local kDelayed, kUnclaimed = unpack(KEYS)
                        -- Get the list of ready delayed jobs, sorted by readiness
-                       local ids = redis.call('zRangeByScore',KEYS[1],0,ARGV[1])
+                       local ids = redis.call('zRangeByScore',kDelayed,0,ARGV[1])
                        -- Migrate the jobs from the "delayed" set to the "unclaimed" list
                        for k,id in ipairs(ids) do
-                               redis.call('lPush',KEYS[2],id)
-                               redis.call('zRem',KEYS[1],id)
+                               redis.call('lPush',kUnclaimed,id)
+                               redis.call('zRem',kDelayed,id)
                        end
                        return #ids
 LUA;
@@ -643,8 +668,8 @@ LUA;
        /**
         * Recycle or destroy any jobs that have been claimed for too long
         *
-        * @return integer Number of jobs recycled/deleted
-        * @throws MWException
+        * @return int Number of jobs recycled/deleted
+        * @throws MWException|JobQueueError
         */
        public function recycleAndDeleteStaleJobs() {
                if ( $this->claimTTL <= 0 ) { // sanity
@@ -660,33 +685,34 @@ LUA;
                        $now = time();
                        static $script =
 <<<LUA
+                       local kClaimed, kAttempts, kUnclaimed, kData, kAbandoned = unpack(KEYS)
                        local released,abandoned,pruned = 0,0,0
                        -- Get all non-dead jobs that have an expired claim on them.
                        -- The score for each item is the last claim timestamp (UNIX).
-                       local staleClaims = redis.call('zRangeByScore',KEYS[1],0,ARGV[1])
+                       local staleClaims = redis.call('zRangeByScore',kClaimed,0,ARGV[1])
                        for k,id in ipairs(staleClaims) do
-                               local timestamp = redis.call('zScore',KEYS[1],id)
-                               local attempts = redis.call('hGet',KEYS[2],id)
+                               local timestamp = redis.call('zScore',kClaimed,id)
+                               local attempts = redis.call('hGet',kAttempts,id)
                                if attempts < ARGV[3] then
                                        -- Claim expired and retries left: re-enqueue the job
-                                       redis.call('lPush',KEYS[3],id)
-                                       redis.call('hIncrBy',KEYS[2],id,1)
+                                       redis.call('lPush',kUnclaimed,id)
+                                       redis.call('hIncrBy',kAttempts,id,1)
                                        released = released + 1
                                else
                                        -- Claim expired and no retries left: mark the job as dead
-                                       redis.call('zAdd',KEYS[5],timestamp,id)
+                                       redis.call('zAdd',kAbandoned,timestamp,id)
                                        abandoned = abandoned + 1
                                end
-                               redis.call('zRem',KEYS[1],id)
+                               redis.call('zRem',kClaimed,id)
                        end
                        -- Get all of the dead jobs that have been marked as dead for too long.
                        -- The score for each item is the last claim timestamp (UNIX).
-                       local deadClaims = redis.call('zRangeByScore',KEYS[5],0,ARGV[2])
+                       local deadClaims = redis.call('zRangeByScore',kAbandoned,0,ARGV[2])
                        for k,id in ipairs(deadClaims) do
                                -- Stale and out of retries: remove any traces of the job
-                               redis.call('zRem',KEYS[5],id)
-                               redis.call('hDel',KEYS[2],id)
-                               redis.call('hDel',KEYS[4],id)
+                               redis.call('zRem',kAbandoned,id)
+                               redis.call('hDel',kAttempts,id)
+                               redis.call('hDel',kData,id)
                                pruned = pruned + 1
                        end
                        return {released,abandoned,pruned}
@@ -718,7 +744,7 @@ LUA;
        }
 
        /**
-        * @return Array
+        * @return array
         */
        protected function doGetPeriodicTasks() {
                $tasks = array();
@@ -734,28 +760,29 @@ LUA;
                                'period' => 300 // 5 minutes
                        );
                }
+
                return $tasks;
        }
 
        /**
-        * @param $job Job
+        * @param Job $job
         * @return array
         */
        protected function getNewJobFields( Job $job ) {
                return array(
                        // Fields that describe the nature of the job
-                       'type'       => $job->getType(),
-                       'namespace'  => $job->getTitle()->getNamespace(),
-                       'title'      => $job->getTitle()->getDBkey(),
-                       'params'     => $job->getParams(),
+                       'type' => $job->getType(),
+                       'namespace' => $job->getTitle()->getNamespace(),
+                       'title' => $job->getTitle()->getDBkey(),
+                       'params' => $job->getParams(),
                        // Some jobs cannot run until a "release timestamp"
-                       'rtimestamp' => $job->getReleaseTimestamp() ?: 0,
+                       'rtimestamp' => $job->getReleaseTimestamp() ? : 0,
                        // Additional job metadata
-                       'uuid'       => UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND ),
-                       'sha1'       => $job->ignoreDuplicates()
-                               ? wfBaseConvert( sha1( serialize( $job->getDeduplicationInfo() ) ), 16, 36, 31 )
-                               : '',
-                       'timestamp'  => time() // UNIX timestamp
+                       'uuid' => UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND ),
+                       'sha1' => $job->ignoreDuplicates()
+                                       ? wfBaseConvert( sha1( serialize( $job->getDeduplicationInfo() ) ), 16, 36, 31 )
+                                       : '',
+                       'timestamp' => time() // UNIX timestamp
                );
        }
 
@@ -768,8 +795,10 @@ LUA;
                if ( $title ) {
                        $job = Job::factory( $fields['type'], $title, $fields['params'] );
                        $job->metadata['uuid'] = $fields['uuid'];
+
                        return $job;
                }
+
                return false;
        }
 
@@ -780,10 +809,12 @@ LUA;
        protected function serialize( array $fields ) {
                $blob = serialize( $fields );
                if ( $this->compression === 'gzip'
-                       && strlen( $blob ) >= 1024 && function_exists( 'gzdeflate' ) )
-               {
+                       && strlen( $blob ) >= 1024
+                       && function_exists( 'gzdeflate' )
+               ) {
                        $object = (object)array( 'blob' => gzdeflate( $blob ), 'enc' => 'gzip' );
                        $blobz = serialize( $object );
+
                        return ( strlen( $blobz ) < strlen( $blob ) ) ? $blobz : $blob;
                } else {
                        return $blob;
@@ -803,20 +834,22 @@ LUA;
                                $fields = false;
                        }
                }
+
                return is_array( $fields ) ? $fields : false;
        }
 
        /**
         * Get a connection to the server that handles all sub-queues for this queue
         *
-        * @return Array (server name, Redis instance)
-        * @throws MWException
+        * @return RedisConnRef
+        * @throws JobQueueConnectionError
         */
        protected function getConnection() {
                $conn = $this->redisPool->getConnection( $this->server );
                if ( !$conn ) {
                        throw new JobQueueConnectionError( "Unable to connect to redis server." );
                }
+
                return $conn;
        }
 
@@ -824,7 +857,7 @@ LUA;
         * @param $server string
         * @param $conn RedisConnRef
         * @param $e RedisException
-        * @throws MWException
+        * @throws JobQueueError
         */
        protected function throwRedisException( $server, RedisConnRef $conn, $e ) {
                $this->redisPool->handleException( $server, $conn, $e );
index a8186ab..8600eed 100644 (file)
@@ -34,9 +34,11 @@ abstract class JobQueueAggregator {
        /**
         * @param array $params
         */
-       protected function __construct( array $params ) {}
+       protected function __construct( array $params ) {
+       }
 
        /**
+        * @throws MWException
         * @return JobQueueAggregator
         */
        final public static function singleton() {
@@ -74,6 +76,7 @@ abstract class JobQueueAggregator {
                wfProfileIn( __METHOD__ );
                $ok = $this->doNotifyQueueEmpty( $wiki, $type );
                wfProfileOut( __METHOD__ );
+
                return $ok;
        }
 
@@ -93,6 +96,7 @@ abstract class JobQueueAggregator {
                wfProfileIn( __METHOD__ );
                $ok = $this->doNotifyQueueNonEmpty( $wiki, $type );
                wfProfileOut( __METHOD__ );
+
                return $ok;
        }
 
@@ -104,12 +108,13 @@ abstract class JobQueueAggregator {
        /**
         * Get the list of all of the queues with jobs
         *
-        * @return Array (job type => (list of wiki IDs))
+        * @return array (job type => (list of wiki IDs))
         */
        final public function getAllReadyWikiQueues() {
                wfProfileIn( __METHOD__ );
                $res = $this->doGetAllReadyWikiQueues();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -127,6 +132,7 @@ abstract class JobQueueAggregator {
                wfProfileIn( __METHOD__ );
                $res = $this->doPurge();
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -139,7 +145,7 @@ abstract class JobQueueAggregator {
         * Get all databases that have a pending job.
         * This poll all the queues and is this expensive.
         *
-        * @return Array (job type => (list of wiki IDs))
+        * @return array (job type => (list of wiki IDs))
         */
        protected function findPendingWikiQueues() {
                global $wgLocalDatabases;
index 9434da0..d733a42 100644 (file)
@@ -65,6 +65,7 @@ class JobQueueAggregatorMemc extends JobQueueAggregator {
                        }
                        $this->cache->delete( "$key:lock" ); // unlock
                }
+
                return true;
        }
 
@@ -103,6 +104,7 @@ class JobQueueAggregatorMemc extends JobQueueAggregator {
                                $this->cache->delete( "$key:rebuild" ); // unlock
                        }
                }
+
                return is_array( $pendingDbInfo )
                        ? $pendingDbInfo['pendingDBs']
                        : array(); // cache is both empty and locked
index c6a799d..057a587 100644 (file)
@@ -32,23 +32,27 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
        /** @var RedisConnectionPool */
        protected $redisPool;
 
+       /** @var array List of Redis server addresses */
+       protected $servers;
+
        /**
         * @params include:
-        *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
-        *   - redisServer : A hostname/port combination or the absolute path of a UNIX socket.
-        *                   If a hostname is specified but no port, the standard port number
-        *                   6379 will be used. Required.
+        *   - redisConfig  : An array of parameters to RedisConnectionPool::__construct().
+        *   - redisServers : Array of server entries, the first being the primary and the
+        *                    others being fallback servers. Each entry is either a hostname/port
+        *                    combination or the absolute path of a UNIX socket.
+        *                    If a hostname is specified but no port, the standard port number
+        *                    6379 will be used. Required.
         * @param array $params
         */
        protected function __construct( array $params ) {
                parent::__construct( $params );
-               $this->server = $params['redisServer'];
+               $this->servers = isset( $params['redisServers'] )
+                       ? $params['redisServers']
+                       : array( $params['redisServer'] ); // b/c
                $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
        }
 
-       /**
-        * @see JobQueueAggregator::doNotifyQueueEmpty()
-        */
        protected function doNotifyQueueEmpty( $wiki, $type ) {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -56,16 +60,15 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                }
                try {
                        $conn->hDel( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ) );
+
                        return true;
                } catch ( RedisException $e ) {
                        $this->handleException( $conn, $e );
+
                        return false;
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doNotifyQueueNonEmpty()
-        */
        protected function doNotifyQueueNonEmpty( $wiki, $type ) {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -73,16 +76,15 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                }
                try {
                        $conn->hSet( $this->getReadyQueueKey(), $this->encQueueName( $type, $wiki ), time() );
+
                        return true;
                } catch ( RedisException $e ) {
                        $this->handleException( $conn, $e );
+
                        return false;
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doAllGetReadyWikiQueues()
-        */
        protected function doGetAllReadyWikiQueues() {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -126,13 +128,11 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                        return $pendingDBs;
                } catch ( RedisException $e ) {
                        $this->handleException( $conn, $e );
+
                        return array();
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doPurge()
-        */
        protected function doPurge() {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -142,19 +142,29 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                        $conn->delete( $this->getReadyQueueKey() );
                } catch ( RedisException $e ) {
                        $this->handleException( $conn, $e );
+
                        return false;
                }
+
                return true;
        }
 
        /**
         * Get a connection to the server that handles all sub-queues for this queue
         *
-        * @return Array (server name, Redis instance)
+        * @return RedisConnRef|bool Returns false on failure
         * @throws MWException
         */
        protected function getConnection() {
-               return $this->redisPool->getConnection( $this->server );
+               $conn = false;
+               foreach ( $this->servers as $server ) {
+                       $conn = $this->redisPool->getConnection( $server );
+                       if ( $conn ) {
+                               break;
+                       }
+               }
+
+               return $conn;
        }
 
        /**
@@ -163,7 +173,7 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
         * @return void
         */
        protected function handleException( RedisConnRef $conn, $e ) {
-               $this->redisPool->handleException( $this->server, $conn, $e );
+               $this->redisPool->handleException( $conn->getServer(), $conn, $e );
        }
 
        /**
@@ -188,6 +198,7 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
         */
        private function dencQueueName( $name ) {
                list( $type, $wiki ) = explode( '/', $name, 2 );
+
                return array( rawurldecode( $type ), rawurldecode( $wiki ) );
        }
 }
index 6237e56..eff16b9 100644 (file)
@@ -39,6 +39,7 @@ class AssembleUploadChunksJob extends Job {
                        $user = $context->getUser();
                        if ( !$user->isLoggedIn() ) {
                                $this->setLastError( "Could not load the author user from session." );
+
                                return false;
                        }
 
@@ -47,7 +48,9 @@ class AssembleUploadChunksJob extends Job {
                                // with the session correctly. Note that being able to load
                                // the user does not necessarily mean the session was loaded.
                                // Most likely cause by suhosin.session.encrypt = On.
-                               $this->setLastError( "Error associating with user session. Try setting suhosin.session.encrypt = Off" );
+                               $this->setLastError( "Error associating with user session. " .
+                                       "Try setting suhosin.session.encrypt = Off" );
+
                                return false;
                        }
 
@@ -71,6 +74,7 @@ class AssembleUploadChunksJob extends Job {
                                        array( 'result' => 'Failure', 'stage' => 'assembling', 'status' => $status )
                                );
                                $this->setLastError( $status->getWikiText() );
+
                                return false;
                        }
 
@@ -108,8 +112,10 @@ class AssembleUploadChunksJob extends Job {
                                )
                        );
                        $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+
                        return false;
                }
+
                return true;
        }
 
@@ -118,6 +124,7 @@ class AssembleUploadChunksJob extends Job {
                if ( is_array( $info['params'] ) ) {
                        $info['params'] = array( 'filekey' => $info['params']['filekey'] );
                }
+
                return $info;
        }
 
index 33e749b..f5f0d63 100644 (file)
  * @ingroup JobQueue
  */
 class DoubleRedirectJob extends Job {
-       var $reason, $redirTitle;
+       /** @var string Reason for the change, 'maintenance' or 'move'. Suffix fo
+        *    message key 'double-redirect-fixed-'.
+        */
+       private $reason;
 
-       /**
-        * @var User
+       /** @var Title The title which has changed, redirects pointing to this
+        *    title are fixed
         */
-       static $user;
+       private $redirTitle;
+
+       /** @var User */
+       private static $user;
 
        /**
         * Insert jobs into the job queue to fix redirects to the given title
-        * @param string $reason the reason for the fix, see message "double-redirect-fixed-<reason>"
-        * @param $redirTitle Title: the title which has changed, redirects pointing to this title are fixed
+        * @param string $reason the reason for the fix, see message
+        *   "double-redirect-fixed-<reason>"
+        * @param $redirTitle Title: the title which has changed, redirects
+        *   pointing to this title are fixed
         * @param bool $destTitle Not used
         */
        public static function fixRedirects( $reason, $redirTitle, $destTitle = false ) {
@@ -73,6 +81,11 @@ class DoubleRedirectJob extends Job {
                JobQueueGroup::singleton()->push( $jobs );
        }
 
+       /**
+        * @param Title $title
+        * @param array|bool $params
+        * @param int $id
+        */
        function __construct( $title, $params = false, $id = 0 ) {
                parent::__construct( 'fixDoubleRedirect', $title, $params, $id );
                $this->reason = $params['reason'];
@@ -85,18 +98,21 @@ class DoubleRedirectJob extends Job {
        function run() {
                if ( !$this->redirTitle ) {
                        $this->setLastError( 'Invalid title' );
+
                        return false;
                }
 
                $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
                if ( !$targetRev ) {
                        wfDebug( __METHOD__ . ": target redirect already deleted, ignoring\n" );
+
                        return true;
                }
                $content = $targetRev->getContent();
                $currentDest = $content ? $content->getRedirectTarget() : null;
                if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) {
                        wfDebug( __METHOD__ . ": Redirect has changed since the job was queued\n" );
+
                        return true;
                }
 
@@ -104,13 +120,16 @@ class DoubleRedirectJob extends Job {
                $mw = MagicWord::get( 'staticredirect' );
                if ( $content->matchMagicWord( $mw ) ) {
                        wfDebug( __METHOD__ . ": skipping: suppressed with __STATICREDIRECT__\n" );
+
                        return true;
                }
 
                // Find the current final destination
                $newTitle = self::getFinalDestination( $this->redirTitle );
                if ( !$newTitle ) {
-                       wfDebug( __METHOD__ . ": skipping: single redirect, circular redirect or invalid redirect destination\n" );
+                       wfDebug( __METHOD__ .
+                               ": skipping: single redirect, circular redirect or invalid redirect destination\n" );
+
                        return true;
                }
                if ( $newTitle->equals( $this->redirTitle ) ) {
@@ -128,12 +147,14 @@ class DoubleRedirectJob extends Job {
 
                if ( $newContent->equals( $content ) ) {
                        $this->setLastError( 'Content unchanged???' );
+
                        return false;
                }
 
                $user = $this->getUser();
                if ( !$user ) {
                        $this->setLastError( 'Invalid user' );
+
                        return false;
                }
 
@@ -171,6 +192,7 @@ class DoubleRedirectJob extends Job {
                        $titleText = $title->getPrefixedDBkey();
                        if ( isset( $seenTitles[$titleText] ) ) {
                                wfDebug( __METHOD__, "Circular redirect detected, aborting\n" );
+
                                return false;
                        }
                        $seenTitles[$titleText] = true;
@@ -195,9 +217,15 @@ class DoubleRedirectJob extends Job {
                                # No redirect from here, chain terminates
                                break;
                        } else {
-                               $dest = $title = Title::makeTitle( $row->rd_namespace, $row->rd_title, '', $row->rd_interwiki );
+                               $dest = $title = Title::makeTitle(
+                                       $row->rd_namespace,
+                                       $row->rd_title,
+                                       '',
+                                       $row->rd_interwiki
+                               );
                        }
                }
+
                return $dest;
        }
 
@@ -210,12 +238,14 @@ class DoubleRedirectJob extends Job {
         */
        function getUser() {
                if ( !self::$user ) {
-                       self::$user = User::newFromName( wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text() );
+                       $username = wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text();
+                       self::$user = User::newFromName( $username );
                        # User::newFromName() can return false on a badly configured wiki.
                        if ( self::$user && !self::$user->isLoggedIn() ) {
                                self::$user->addToDatabase();
                        }
                }
+
                return self::$user;
        }
 }
index be1bfe5..7e5bd3c 100644 (file)
@@ -30,7 +30,7 @@ final class DuplicateJob extends Job {
        /**
         * Callers should use DuplicateJob::newFromJob() instead
         *
-        * @param $title Title
+        * @param Title $title
         * @param array $params job parameters
         * @param $id Integer: job id
         */
@@ -50,6 +50,7 @@ final class DuplicateJob extends Job {
                $djob->params = is_array( $djob->params ) ? $djob->params : array();
                $djob->params = array( 'isDuplicate' => true ) + $djob->params;
                $djob->metadata = $job->metadata;
+
                return $djob;
        }
 
index 9fbf312..f24cebb 100644 (file)
@@ -43,5 +43,4 @@ class EmaillingJob extends Job {
 
                return $status->isOK();
        }
-
 }
index bbe988d..97a7af6 100644 (file)
@@ -27,7 +27,6 @@
  * @ingroup JobQueue
  */
 class EnotifNotifyJob extends Job {
-
        function __construct( $title, $params, $id = 0 ) {
                parent::__construct( 'enotifNotify', $title, $params, $id );
        }
@@ -39,7 +38,7 @@ class EnotifNotifyJob extends Job {
                        $editor = User::newFromId( $this->params['editorID'] );
                // B/C, only the name might be given.
                } else {
-                       # FIXME: newFromName could return false on a badly configured wiki.
+                       # @todo FIXME: newFromName could return false on a badly configured wiki.
                        $editor = User::newFromName( $this->params['editor'], false );
                }
                $enotif->actuallyNotifyOnPageChange(
@@ -52,7 +51,7 @@ class EnotifNotifyJob extends Job {
                        $this->params['watchers'],
                        $this->params['pageStatus']
                );
+
                return true;
        }
-
 }
index 44c240b..8885e25 100644 (file)
@@ -47,13 +47,17 @@ class HTMLCacheUpdateJob extends Job {
        /** @var BacklinkCache */
        protected $blCache;
 
-       protected $rowsPerJob, $rowsPerQuery;
+       /** @var int Number of rows to update per job, see $wgUpdateRowsPerJob */
+       protected $rowsPerJob;
+
+       /** @var int Number of rows to update per query, see $wgUpdateRowsPerQuery */
+       protected $rowsPerQuery;
 
        /**
         * Construct a job
-        * @param $title Title: the title linked to
+        * @param Title $title The title linked to
         * @param array $params job parameters (table, start and end page_ids)
-        * @param $id Integer: job id
+        * @param int $id Job id
         */
        function __construct( $title, $params, $id = 0 ) {
                global $wgUpdateRowsPerJob, $wgUpdateRowsPerQuery;
@@ -86,6 +90,7 @@ class HTMLCacheUpdateJob extends Job {
                $numRows = $this->blCache->getNumLinks( $this->params['table'], $max );
                if ( $wgMaxBacklinksInvalidate !== false && $numRows > $wgMaxBacklinksInvalidate ) {
                        wfDebug( "Skipped HTML cache invalidation of {$this->title->getPrefixedText()}." );
+
                        return true;
                }
 
@@ -123,6 +128,7 @@ class HTMLCacheUpdateJob extends Job {
                        # period of time, say by updating a heavily-used template.
                        $this->insertJobsFromTitles( $titleArray );
                }
+
                return true;
        }
 
@@ -131,9 +137,8 @@ class HTMLCacheUpdateJob extends Job {
         * using a pre-calculated title array which gives the links in that range.
         * Queue the resulting jobs.
         *
-        * @param $titleArray array
-        * @param $rootJobParams array
-        * @return void
+        * @param array|TitleArrayFromResult $titleArray
+        * @param array $rootJobParams
         */
        protected function insertJobsFromTitles( $titleArray, $rootJobParams = array() ) {
                // Carry over any "root job" information
@@ -144,6 +149,7 @@ class HTMLCacheUpdateJob extends Job {
                $jobs = array();
                $start = $this->params['start']; # start of the current job
                $numTitles = 0;
+               /** @var Title $title */
                foreach ( $titleArray as $title ) {
                        $id = $title->getArticleID();
                        # $numTitles is now the number of titles in the current job not
@@ -184,8 +190,7 @@ class HTMLCacheUpdateJob extends Job {
        }
 
        /**
-        * @param $rootJobParams array
-        * @return void
+        * @param array $rootJobParams
         */
        protected function insertPartitionJobs( $rootJobParams = array() ) {
                // Carry over any "root job" information
@@ -213,7 +218,7 @@ class HTMLCacheUpdateJob extends Job {
 
        /**
         * Invalidate an array (or iterator) of Title objects, right now
-        * @param $titleArray array
+        * @param array|TitleArrayFromResult $titleArray
         */
        protected function invalidateTitles( $titleArray ) {
                global $wgUseFileCache, $wgUseSquid;
@@ -223,6 +228,7 @@ class HTMLCacheUpdateJob extends Job {
 
                # Get all IDs in this query into an array
                $ids = array();
+               /** @var Title $title */
                foreach ( $titleArray as $title ) {
                        $ids[] = $title->getArticleID();
                }
index b6164a5..f62419c 100644 (file)
@@ -46,9 +46,9 @@
  */
 class NullJob extends Job {
        /**
-        * @param $title Title (can be anything)
+        * @param Title $title
         * @param array $params job parameters (lives, usleep)
-        * @param $id Integer: job id
+        * @param int $id Job id
         */
        function __construct( $title, $params, $id = 0 ) {
                parent::__construct( 'null', $title, $params, $id );
@@ -71,6 +71,7 @@ class NullJob extends Job {
                        $job = new self( $this->title, $params );
                        JobQueueGroup::singleton()->push( $job );
                }
+
                return true;
        }
 }
index 5a24f93..88ac9cf 100644 (file)
@@ -39,6 +39,7 @@ class PublishStashedFileJob extends Job {
                        $user = $context->getUser();
                        if ( !$user->isLoggedIn() ) {
                                $this->setLastError( "Could not load the author user from session." );
+
                                return false;
                        }
 
@@ -47,11 +48,12 @@ class PublishStashedFileJob extends Job {
                                // with the session correctly. Note that being able to load
                                // the user does not necessarily mean the session was loaded.
                                // Most likely cause by suhosin.session.encrypt = On.
-                               $this->setLastError( "Error associating with user session. Try setting suhosin.session.encrypt = Off" );
+                               $this->setLastError( "Error associating with user session. " .
+                                       "Try setting suhosin.session.encrypt = Off" );
+
                                return false;
                        }
 
-
                        UploadBase::setSessionStatus(
                                $this->params['filekey'],
                                array( 'result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood() )
@@ -74,6 +76,7 @@ class PublishStashedFileJob extends Job {
                                        array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
                                );
                                $this->setLastError( "Could not verify upload." );
+
                                return false;
                        }
 
@@ -90,6 +93,7 @@ class PublishStashedFileJob extends Job {
                                        array( 'result' => 'Failure', 'stage' => 'publish', 'status' => $status )
                                );
                                $this->setLastError( $status->getWikiText() );
+
                                return false;
                        }
 
@@ -121,8 +125,10 @@ class PublishStashedFileJob extends Job {
                                )
                        );
                        $this->setLastError( get_class( $e ) . ": " . $e->getText() );
+
                        return false;
                }
+
                return true;
        }
 
@@ -131,6 +137,7 @@ class PublishStashedFileJob extends Job {
                if ( is_array( $info['params'] ) ) {
                        $info['params'] = array( 'filekey' => $info['params']['filekey'] );
                }
+
                return $info;
        }
 
index 4fc8bac..e81998d 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Job to update links for a given title.
+ * Job to update link tables for pages
  *
  * 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
  */
 
 /**
- * Background job to update links for a given title.
+ * Job to update link tables for pages
+ *
+ * This job comes in a few variants:
+ *   - a) Recursive jobs to update links for backlink pages for a given title
+ *   - b) Jobs to update links for a set of titles (the job title is ignored)
+ *   - c) Jobs to update links for a single title (the job title)
  *
  * @ingroup JobQueue
  */
 class RefreshLinksJob extends Job {
+       const VERSION = 1;
+
        function __construct( $title, $params = '', $id = 0 ) {
                parent::__construct( 'refreshLinks', $title, $params, $id );
-               $this->removeDuplicates = true; // job is expensive
+               $this->params['version'] = self::VERSION;
+               // Base backlink update jobs and per-title update jobs can be de-duplicated.
+               // If template A changes twice before any jobs run, a clean queue will have:
+               //              (A base, A base)
+               // The second job is ignored by the queue on insertion.
+               // Suppose, many pages use template A, and that template itself uses template B.
+               // An edit to both will first create two base jobs. A clean FIFO queue will have:
+               //              (A base, B base)
+               // When these jobs run, the queue will have per-title and remnant partition jobs:
+               //              (titleX,titleY,titleZ,...,A remnant,titleM,titleN,titleO,...,B remnant)
+               // Some these jobs will be the same, and will automatically be ignored by
+               // the queue upon insertion. Some title jobs will run before the duplicate is
+               // inserted, so the work will still be done twice in those cases. More titles
+               // can be de-duplicated as the remnant jobs continue to be broken down. This
+               // works best when $wgUpdateRowsPerJob, and either the pages have few backlinks
+               // and/or the backlink sets for pages A and B are almost identical.
+               $this->removeDuplicates = !isset( $params['range'] )
+                       && ( !isset( $params['pages'] ) || count( $params['pages'] ) == 1 );
        }
 
-       /**
-        * Run a refreshLinks job
-        * @return boolean success
-        */
        function run() {
-               $linkCache = LinkCache::singleton();
-               $linkCache->clear();
+               global $wgUpdateRowsPerJob;
 
                if ( is_null( $this->title ) ) {
-                       $this->error = "refreshLinks: Invalid title";
+                       $this->setLastError( "Invalid page title" );
                        return false;
                }
 
-               # Wait for the DB of the current/next slave DB handle to catch up to the master.
-               # This way, we get the correct page_latest for templates or files that just changed
-               # milliseconds ago, having triggered this job to begin with.
-               if ( isset( $this->params['masterPos'] ) && $this->params['masterPos'] !== false ) {
-                       wfGetLB()->waitFor( $this->params['masterPos'] );
-               }
-
-               $revision = Revision::newFromTitle( $this->title, false, Revision::READ_NORMAL );
-               if ( !$revision ) {
-                       $this->error = 'refreshLinks: Article not found "' .
-                               $this->title->getPrefixedDBkey() . '"';
-                       return false; // XXX: what if it was just deleted?
+               // Job to update all (or a range of) backlink pages for a page
+               if ( isset( $this->params['recursive'] ) ) {
+                       // Carry over information for de-duplication
+                       $extraParams = $this->getRootJobParams();
+                       // Avoid slave lag when fetching templates.
+                       // When the outermost job is run, we know that the caller that enqueued it must have
+                       // committed the relevant changes to the DB by now. At that point, record the master
+                       // position and pass it along as the job recursively breaks into smaller range jobs.
+                       // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
+                       if ( isset( $this->params['masterPos'] ) ) {
+                               $extraParams['masterPos'] = $this->params['masterPos'];
+                       } elseif ( wfGetLB()->getServerCount() > 1 ) {
+                               $extraParams['masterPos'] = wfGetLB()->getMasterPos();
+                       } else {
+                               $extraParams['masterPos'] = false;
+                       }
+                       // Convert this into no more than $wgUpdateRowsPerJob RefreshLinks per-title
+                       // jobs and possibly a recursive RefreshLinks job for the rest of the backlinks
+                       $jobs = BacklinkJobUtils::partitionBacklinkJob(
+                               $this,
+                               $wgUpdateRowsPerJob,
+                               1, // job-per-title
+                               array( 'params' => $extraParams )
+                       );
+                       JobQueueGroup::singleton()->push( $jobs );
+               // Job to update link tables for for a set of titles
+               } elseif ( isset( $this->params['pages'] ) ) {
+                       foreach ( $this->params['pages'] as $pageId => $nsAndKey ) {
+                               list( $ns, $dbKey ) = $nsAndKey;
+                               $this->runForTitle( Title::makeTitleSafe( $ns, $dbKey ) );
+                       }
+               // Job to update link tables for a given title
+               } else {
+                       $this->runForTitle( $this->title );
                }
 
-               self::runForTitleInternal( $this->title, $revision, __METHOD__ );
-
                return true;
        }
 
-       /**
-        * @return Array
-        */
-       public function getDeduplicationInfo() {
-               $info = parent::getDeduplicationInfo();
-               // Don't let highly unique "masterPos" values ruin duplicate detection
-               if ( is_array( $info['params'] ) ) {
-                       unset( $info['params']['masterPos'] );
-               }
-               return $info;
-       }
-
-       /**
-        * @param $title Title
-        * @param $revision Revision
-        * @param $fname string
-        * @return void
-        */
-       public static function runForTitleInternal( Title $title, Revision $revision, $fname ) {
-               wfProfileIn( $fname );
-               $content = $revision->getContent( Revision::RAW );
-
-               if ( !$content ) {
-                       // if there is no content, pretend the content is empty
-                       $content = $revision->getContentHandler()->makeEmptyContent();
-               }
-
-               // Revision ID must be passed to the parser output to get revision variables correct
-               $parserOutput = $content->getParserOutput( $title, $revision->getId(), null, false );
-
-               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput );
-               DataUpdate::runUpdates( $updates );
-
-               InfoAction::invalidateCache( $title );
-
-               wfProfileOut( $fname );
-       }
-}
-
-/**
- * Background job to update links for a given title.
- * Newer version for high use templates.
- *
- * @ingroup JobQueue
- */
-class RefreshLinksJob2 extends Job {
-       function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'refreshLinks2', $title, $params, $id );
-               // Base jobs for large templates can easily be de-duplicated
-               $this->removeDuplicates = !isset( $params['start'] ) && !isset( $params['end'] );
-       }
-
-       /**
-        * Run a refreshLinks2 job
-        * @return boolean success
-        */
-       function run() {
-               global $wgUpdateRowsPerJob;
-
+       protected function runForTitle( Title $title = null ) {
                $linkCache = LinkCache::singleton();
                $linkCache->clear();
 
-               if ( is_null( $this->title ) ) {
-                       $this->error = "refreshLinks2: Invalid title";
+               if ( is_null( $title ) ) {
+                       $this->setLastError( "refreshLinks: Invalid title" );
                        return false;
                }
 
-               // Back compat for pre-r94435 jobs
-               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
-
-               // Avoid slave lag when fetching templates.
-               // When the outermost job is run, we know that the caller that enqueued it must have
-               // committed the relevant changes to the DB by now. At that point, record the master
-               // position and pass it along as the job recursively breaks into smaller range jobs.
-               // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
-               if ( isset( $this->params['masterPos'] ) ) {
-                       $masterPos = $this->params['masterPos'];
-               } elseif ( wfGetLB()->getServerCount() > 1 ) {
-                       $masterPos = wfGetLB()->getMasterPos();
-               } else {
-                       $masterPos = false;
+               // Wait for the DB of the current/next slave DB handle to catch up to the master.
+               // This way, we get the correct page_latest for templates or files that just changed
+               // milliseconds ago, having triggered this job to begin with.
+               if ( isset( $this->params['masterPos'] ) && $this->params['masterPos'] !== false ) {
+                       wfGetLB()->waitFor( $this->params['masterPos'] );
                }
 
-               $tbc = $this->title->getBacklinkCache();
+               // Fetch the current revision...
+               $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
+               if ( !$revision ) {
+                       $this->setLastError( "refreshLinks: Article not found {$title->getPrefixedDBkey()}" );
+                       return false; // XXX: what if it was just deleted?
+               }
+               $content = $revision->getContent( Revision::RAW );
+               if ( !$content ) {
+                       // If there is no content, pretend the content is empty
+                       $content = $revision->getContentHandler()->makeEmptyContent();
+               }
 
-               $jobs = array(); // jobs to insert
-               if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
-                       # This is a partition job to trigger the insertion of leaf jobs...
-                       $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
-               } else {
-                       # This is a base job to trigger the insertion of partitioned jobs...
-                       if ( $tbc->getNumLinks( $table, $wgUpdateRowsPerJob + 1 ) <= $wgUpdateRowsPerJob ) {
-                               # Just directly insert the single per-title jobs
-                               $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
-                       } else {
-                               # Insert the partition jobs to make per-title jobs
-                               foreach ( $tbc->partition( $table, $wgUpdateRowsPerJob ) as $batch ) {
-                                       list( $start, $end ) = $batch;
-                                       $jobs[] = new RefreshLinksJob2( $this->title,
-                                               array(
-                                                       'table' => $table,
-                                                       'start' => $start,
-                                                       'end' => $end,
-                                                       'masterPos' => $masterPos,
-                                               ) + $this->getRootJobParams() // carry over information for de-duplication
-                                       );
+               $parserOutput = false;
+               // If page_touched changed after this root job (with a good slave lag skew factor),
+               // then it is likely that any views of the pages already resulted in re-parses which
+               // are now in cache. This can be reused to avoid expensive parsing in some cases.
+               if ( isset( $this->params['rootJobTimestamp'] ) ) {
+                       $page = WikiPage::factory( $title );
+                       $skewedTimestamp = wfTimestamp( TS_UNIX, $this->params['rootJobTimestamp'] ) + 5;
+                       if ( $page->getTouched() > wfTimestamp( TS_MW, $skewedTimestamp ) ) {
+                               $parserOptions = $page->makeParserOptions( 'canonical' );
+                               $parserOutput = ParserCache::singleton()->getDirty( $page, $parserOptions );
+                               if ( $parserOutput->getCacheTime() <= $skewedTimestamp ) {
+                                       $parserOutput = false; // too stale
                                }
                        }
                }
-
-               if ( count( $jobs ) ) {
-                       JobQueueGroup::singleton()->push( $jobs );
+               // Fetch the current revision and parse it if necessary...
+               if ( $parserOutput == false ) {
+                       // Revision ID must be passed to the parser output to get revision variables correct
+                       $parserOutput = $content->getParserOutput( $title, $revision->getId(), null, false );
                }
 
-               return true;
-       }
+               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput );
+               DataUpdate::runUpdates( $updates );
 
-       /**
-        * @param $table string
-        * @param $masterPos mixed
-        * @return Array
-        */
-       protected function getSingleTitleJobs( $table, $masterPos ) {
-               # The "start"/"end" fields are not set for the base jobs
-               $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
-               $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
-               $titles = $this->title->getBacklinkCache()->getLinks( $table, $start, $end );
-               # Convert into single page refresh links jobs.
-               # This handles well when in sapi mode and is useful in any case for job
-               # de-duplication. If many pages use template A, and that template itself
-               # uses template B, then an edit to both will create many duplicate jobs.
-               # Roughly speaking, for each page, one of the "RefreshLinksJob" jobs will
-               # get run first, and when it does, it will remove the duplicates. Of course,
-               # one page could have its job popped when the other page's job is still
-               # buried within the logic of a refreshLinks2 job.
-               $jobs = array();
-               foreach ( $titles as $title ) {
-                       $jobs[] = new RefreshLinksJob( $title,
-                               array( 'masterPos' => $masterPos ) + $this->getRootJobParams()
-                       ); // carry over information for de-duplication
-               }
-               return $jobs;
+               InfoAction::invalidateCache( $title );
+
+               return true;
        }
 
-       /**
-        * @return Array
-        */
        public function getDeduplicationInfo() {
                $info = parent::getDeduplicationInfo();
-               // Don't let highly unique "masterPos" values ruin duplicate detection
                if ( is_array( $info['params'] ) ) {
+                       // Don't let highly unique "masterPos" values ruin duplicate detection
                        unset( $info['params']['masterPos'] );
+                       // For per-pages jobs, the job title is that of the template that changed
+                       // (or similar), so remove that since it ruins duplicate detection
+                       if ( isset( $info['pages'] ) ) {
+                               unset( $info['namespace'] );
+                               unset( $info['title'] );
+                       }
                }
+
                return $info;
        }
 }
diff --git a/includes/job/jobs/RefreshLinksJob2.php b/includes/job/jobs/RefreshLinksJob2.php
new file mode 100644 (file)
index 0000000..332f625
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Job to update links for a given title.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Background job to update links for titles in certain backlink range by page ID.
+ * Newer version for high use templates. This is deprecated by RefreshLinksPartitionJob.
+ *
+ * @ingroup JobQueue
+ * @deprecated 1.23
+ */
+class RefreshLinksJob2 extends Job {
+       function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'refreshLinks2', $title, $params, $id );
+               // Base jobs for large templates can easily be de-duplicated
+               $this->removeDuplicates = !isset( $params['start'] ) && !isset( $params['end'] );
+       }
+
+       /**
+        * Run a refreshLinks2 job
+        * @return boolean success
+        */
+       function run() {
+               global $wgUpdateRowsPerJob;
+
+               $linkCache = LinkCache::singleton();
+               $linkCache->clear();
+
+               if ( is_null( $this->title ) ) {
+                       $this->error = "refreshLinks2: Invalid title";
+                       return false;
+               }
+
+               // Back compat for pre-r94435 jobs
+               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
+
+               // Avoid slave lag when fetching templates.
+               // When the outermost job is run, we know that the caller that enqueued it must have
+               // committed the relevant changes to the DB by now. At that point, record the master
+               // position and pass it along as the job recursively breaks into smaller range jobs.
+               // Hopefully, when leaf jobs are popped, the slaves will have reached that position.
+               if ( isset( $this->params['masterPos'] ) ) {
+                       $masterPos = $this->params['masterPos'];
+               } elseif ( wfGetLB()->getServerCount() > 1 ) {
+                       $masterPos = wfGetLB()->getMasterPos();
+               } else {
+                       $masterPos = false;
+               }
+
+               $tbc = $this->title->getBacklinkCache();
+
+               $jobs = array(); // jobs to insert
+               if ( isset( $this->params['start'] ) && isset( $this->params['end'] ) ) {
+                       # This is a partition job to trigger the insertion of leaf jobs...
+                       $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
+               } else {
+                       # This is a base job to trigger the insertion of partitioned jobs...
+                       if ( $tbc->getNumLinks( $table, $wgUpdateRowsPerJob + 1 ) <= $wgUpdateRowsPerJob ) {
+                               # Just directly insert the single per-title jobs
+                               $jobs = array_merge( $jobs, $this->getSingleTitleJobs( $table, $masterPos ) );
+                       } else {
+                               # Insert the partition jobs to make per-title jobs
+                               foreach ( $tbc->partition( $table, $wgUpdateRowsPerJob ) as $batch ) {
+                                       list( $start, $end ) = $batch;
+                                       $jobs[] = new RefreshLinksJob2( $this->title,
+                                               array(
+                                                       'table' => $table,
+                                                       'start' => $start,
+                                                       'end' => $end,
+                                                       'masterPos' => $masterPos,
+                                               ) + $this->getRootJobParams() // carry over information for de-duplication
+                                       );
+                               }
+                       }
+               }
+
+               if ( count( $jobs ) ) {
+                       JobQueueGroup::singleton()->push( $jobs );
+               }
+
+               return true;
+       }
+
+       /**
+        * @param $table string
+        * @param $masterPos mixed
+        * @return Array
+        */
+       protected function getSingleTitleJobs( $table, $masterPos ) {
+               # The "start"/"end" fields are not set for the base jobs
+               $start = isset( $this->params['start'] ) ? $this->params['start'] : false;
+               $end = isset( $this->params['end'] ) ? $this->params['end'] : false;
+               $titles = $this->title->getBacklinkCache()->getLinks( $table, $start, $end );
+               # Convert into single page refresh links jobs.
+               # This handles well when in sapi mode and is useful in any case for job
+               # de-duplication. If many pages use template A, and that template itself
+               # uses template B, then an edit to both will create many duplicate jobs.
+               # Roughly speaking, for each page, one of the "RefreshLinksJob" jobs will
+               # get run first, and when it does, it will remove the duplicates. Of course,
+               # one page could have its job popped when the other page's job is still
+               # buried within the logic of a refreshLinks2 job.
+               $jobs = array();
+               foreach ( $titles as $title ) {
+                       $jobs[] = new RefreshLinksJob( $title,
+                               array( 'masterPos' => $masterPos ) + $this->getRootJobParams()
+                       ); // carry over information for de-duplication
+               }
+               return $jobs;
+       }
+
+       /**
+        * @return Array
+        */
+       public function getDeduplicationInfo() {
+               $info = parent::getDeduplicationInfo();
+               // Don't let highly unique "masterPos" values ruin duplicate detection
+               if ( is_array( $info['params'] ) ) {
+                       unset( $info['params']['masterPos'] );
+               }
+               return $info;
+       }
+}
index c993cfb..15d523f 100644 (file)
 class UploadFromUrlJob extends Job {
        const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
 
-       /**
-        * @var UploadFromUrl
-        */
+       /** @var UploadFromUrl */
        public $upload;
 
-       /**
-        * @var User
-        */
+       /** @var User */
        protected $user;
 
        public function __construct( $title, $params, $id = 0 ) {
@@ -66,6 +62,7 @@ class UploadFromUrlJob extends Job {
                $status = $this->upload->fetchFile( $opts );
                if ( !$status->isOk() ) {
                        $this->leaveMessage( $status );
+
                        return true;
                }
 
@@ -74,6 +71,7 @@ class UploadFromUrlJob extends Job {
                if ( $result['status'] != UploadBase::OK ) {
                        $status = $this->upload->convertVerifyErrorToStatus( $result );
                        $this->leaveMessage( $status );
+
                        return true;
                }
 
@@ -85,6 +83,8 @@ class UploadFromUrlJob extends Job {
                                # Stash the upload
                                $key = $this->upload->stashFile();
 
+                               // @todo FIXME: This has been broken for a while.
+                               // User::leaveUserMessage() does not exist.
                                if ( $this->params['leaveMessage'] ) {
                                        $this->user->leaveUserMessage(
                                                wfMessage( 'upload-warning-subj' )->text(),
@@ -111,25 +111,27 @@ class UploadFromUrlJob extends Job {
                        $this->user
                );
                $this->leaveMessage( $status );
-               return true;
 
+               return true;
        }
 
        /**
         * Leave a message on the user talk page or in the session according to
         * $params['leaveMessage'].
         *
-        * @param $status Status
+        * @param Status $status
         */
        protected function leaveMessage( $status ) {
                if ( $this->params['leaveMessage'] ) {
                        if ( $status->isGood() ) {
+                               // @todo FIXME: user->leaveUserMessage does not exist.
                                $this->user->leaveUserMessage( wfMessage( 'upload-success-subj' )->text(),
                                        wfMessage( 'upload-success-msg',
                                                $this->upload->getTitle()->getText(),
                                                $this->params['url']
                                        )->text() );
                        } else {
+                               // @todo FIXME: user->leaveUserMessage does not exist.
                                $this->user->leaveUserMessage( wfMessage( 'upload-failure-subj' )->text(),
                                        wfMessage( 'upload-failure-msg',
                                                $status->getWikiText(),
@@ -155,7 +157,7 @@ class UploadFromUrlJob extends Job {
         *
         * @param string $result the result (Success|Warning|Failure)
         * @param string $dataKey the key of the extra data
-        * @param $dataValue Mixed: the extra data itself
+        * @param mixed $dataValue The extra data itself
         */
        protected function storeResultInSession( $result, $dataKey, $dataValue ) {
                $session =& self::getSessionData( $this->params['sessionKey'] );
@@ -179,6 +181,7 @@ class UploadFromUrlJob extends Job {
                if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
                        $_SESSION[self::SESSION_KEYNAME][$key] = array();
                }
+
                return $_SESSION[self::SESSION_KEYNAME][$key];
        }
 }
diff --git a/includes/job/utils/BacklinkJobUtils.php b/includes/job/utils/BacklinkJobUtils.php
new file mode 100644 (file)
index 0000000..b0b6ccd
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Job to update links for a given title.
+ *
+ * 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 JobQueue
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class with Backlink related Job helper methods
+ *
+ * @ingroup JobQueue
+ * @since 1.23
+ */
+class BacklinkJobUtils {
+       /**
+        * Break down $job into approximately ($bSize/$cSize) leaf jobs and a single partition
+        * job that covers the remaining backlink range (if needed). Jobs for the first $bSize
+        * titles are collated ($cSize per job) into leaf jobs to do actual work. All the
+        * resulting jobs are of the same class as $job. No partition job is returned if the
+        * range covered by $job was less than $bSize, as the leaf jobs have full coverage.
+        *
+        * The leaf jobs have the 'pages' param set to a (<page ID>:(<namespace>,<DB key>),...)
+        * map so that the run() function knows what pages to act on. The leaf jobs will keep
+        * the same job title as the parent job (e.g. $job).
+        *
+        * The partition jobs have the 'range' parameter set to a map of the format
+        * (start:<integer>, end:<integer>, batchSize:<integer>, subranges:((<start>,<end>),...)),
+        * the 'table' parameter set to that of $job, and the 'recursive' parameter set to true.
+        * This method can be called on the resulting job to repeat the process again.
+        *
+        * The job provided ($job) must have the 'recursive' parameter set to true and the 'table'
+        * parameter must be set to a backlink table. The job title will be used as the title to
+        * find backlinks for. Any 'range' parameter must follow the same format as mentioned above.
+        * This should be managed by recursive calls to this method.
+        *
+        * The first jobs return are always the leaf jobs. This lets the caller use push() to
+        * put them directly into the queue and works well if the queue is FIFO. In such a queue,
+        * the leaf jobs have to get finished first before anything can resolve the next partition
+        * job, which keeps the queue very small.
+        *
+        * $opts includes:
+        *   - params : extra job parameters to include in each job
+        *
+        * @param Job $job
+        * @param int $bSize BacklinkCache partition size; usually $wgUpdateRowsPerJob
+        * @param int $cSize Max titles per leaf job; Usually 1 or a modest value
+        * @param array $opts Optional parameter map
+        * @return array List of Job objects
+        */
+       public static function partitionBacklinkJob( Job $job, $bSize, $cSize, $opts = array() ) {
+               $class = get_class( $job );
+               $title = $job->getTitle();
+               $params = $job->getParams();
+
+               if ( isset( $params['pages'] ) || empty( $params['recursive'] ) ) {
+                       $ranges = array(); // sanity; this is a leaf node
+                       wfWarn( __METHOD__ . " called on {$job->getType()} leaf job (explosive recursion)." );
+               } elseif ( isset( $params['range'] ) ) {
+                       // This is a range job to trigger the insertion of partitioned/title jobs...
+                       $ranges = $params['range']['subranges'];
+                       $realBSize = $params['range']['batchSize'];
+               } else {
+                       // This is a base job to trigger the insertion of partitioned jobs...
+                       $ranges = $title->getBacklinkCache()->partition( $params['table'], $bSize );
+                       $realBSize = $bSize;
+               }
+
+               $extraParams = isset( $opts['params'] ) ? $opts['params'] : array();
+
+               $jobs = array();
+               // Combine the first range (of size $bSize) backlinks into leaf jobs
+               if ( isset( $ranges[0] ) ) {
+                       list( $start, $end ) = $ranges[0];
+                       $titles = $title->getBacklinkCache()->getLinks( $params['table'], $start, $end );
+                       foreach ( array_chunk( iterator_to_array( $titles ), $cSize ) as $titleBatch ) {
+                               $pages = array();
+                               foreach ( $titleBatch as $tl ) {
+                                       $pages[$tl->getArticleId()] = array( $tl->getNamespace(), $tl->getDBKey() );
+                               }
+                               $jobs[] = new $class(
+                                       $title, // maintain parent job title
+                                       array( 'pages' => $pages ) + $extraParams
+                               );
+                       }
+               }
+               // Take all of the remaining ranges and build a partition job from it
+               if ( isset( $ranges[1] ) ) {
+                       $jobs[] = new $class(
+                               $title, // maintain parent job title
+                               array(
+                                       'recursive'     => true,
+                                       'table'         => $params['table'],
+                                       'range'         => array(
+                                               'start'     => $ranges[1][0],
+                                               'end'       => $ranges[count( $ranges ) - 1][1],
+                                               'batchSize' => $realBSize,
+                                               'subranges' => array_slice( $ranges, 1 )
+                                       ),
+                               ) + $extraParams
+                       );
+               }
+
+               return $jobs;
+       }
+}
index bc2fff1..83718c3 100644 (file)
@@ -24,7 +24,6 @@
  * JSON formatter wrapper class
  */
 class FormatJson {
-
        /**
         * Skip escaping most characters above U+007F for readability and compactness.
         * This encoding option saves 3 to 8 bytes (uncompressed) for each such character;
@@ -55,6 +54,17 @@ class FormatJson {
         */
        const ALL_OK = 3;
 
+       /**
+        * Regex that matches whitespace inside empty arrays and objects.
+        *
+        * This doesn't affect regular strings inside the JSON because those can't
+        * have a real line break (\n) in them, at this point they are already escaped
+        * as the string "\n" which this doesn't match.
+        *
+        * @private
+        */
+       const WS_CLEANUP_REGEX = '/(?<=[\[{])\n\s*+(?=[\]}])/';
+
        /**
         * Characters problematic in JavaScript.
         *
@@ -93,6 +103,7 @@ class FormatJson {
                if ( defined( 'JSON_UNESCAPED_UNICODE' ) ) {
                        return self::encode54( $value, $pretty, $escaping );
                }
+
                return self::encode53( $value, $pretty, $escaping );
        }
 
@@ -102,7 +113,7 @@ class FormatJson {
         * @param string $value The JSON string being decoded
         * @param bool $assoc When true, returned objects will be converted into associative arrays.
         *
-        * @return mixed: the value encoded in JSON in appropriate PHP type.
+        * @return mixed The value encoded in JSON in appropriate PHP type.
         * `null` is returned if the JSON cannot be decoded or if the encoded data is deeper than
         * the recursion limit.
         */
@@ -130,9 +141,16 @@ class FormatJson {
                if ( $json === false ) {
                        return false;
                }
+
+               if ( $pretty ) {
+                       // Remove whitespace inside empty arrays/objects; different JSON encoders
+                       // vary on this, and we want our output to be consistent across implementations.
+                       $json = preg_replace( self::WS_CLEANUP_REGEX, '', $json );
+               }
                if ( $escaping & self::UTF8_OK ) {
                        $json = str_replace( self::$badChars, self::$badCharsEscaped, $json );
                }
+
                return $json;
        }
 
@@ -173,6 +191,7 @@ class FormatJson {
                if ( $pretty ) {
                        return self::prettyPrint( $json );
                }
+
                return $json;
        }
 
@@ -213,6 +232,8 @@ class FormatJson {
                                        $buf .= substr( $json, $i, $skip );
                        }
                }
-               return str_replace( "\x01", '\"', preg_replace( '/ +$/m', '', $buf ) );
+               $buf = preg_replace( self::WS_CLEANUP_REGEX, '', $buf );
+
+               return str_replace( "\x01", '\"', $buf );
        }
 }
index 4f142fc..68e30eb 100644 (file)
@@ -38,7 +38,8 @@ class CSSMin {
         * which when base64 encoded will result in a 1/3 increase in size.
         */
        const EMBED_SIZE_LIMIT = 24576;
-       const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\'"]*)(?P<query>\??[^\)\'"]*)[\'"]?\s*\)';
+       const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\'"]*?)(?P<query>\?[^\)\'"]*?|)[\'"]?\s*\)';
+       const EMBED_REGEX = '\/\*\s*\@embed\s*\*\/';
 
        /* Protected Static Members */
 
@@ -140,8 +141,8 @@ class CSSMin {
        }
 
        /**
-        * Remaps CSS URL paths and automatically embeds data URIs for URL rules
-        * preceded by an /* @embed * / comment
+        * Remaps CSS URL paths and automatically embeds data URIs for CSS rules or url() values
+        * preceded by an / * @embed * / comment.
         *
         * @param string $source CSS data to remap
         * @param string $local File path where the source was read from
@@ -150,89 +151,118 @@ class CSSMin {
         * @return string Remapped CSS data
         */
        public static function remap( $source, $local, $remote, $embedData = true ) {
-               $pattern = '/((?P<embed>\s*\/\*\s*\@embed\s*\*\/)(?P<pre>[^\;\}]*))?' .
-                       self::URL_REGEX . '(?P<post>[^;]*)[\;]?/';
-               $offset = 0;
-               while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) {
-                       // Skip fully-qualified URLs and data URIs
-                       $urlScheme = parse_url( $match['file'][0], PHP_URL_SCHEME );
-                       if ( $urlScheme ) {
-                               // Move the offset to the end of the match, leaving it alone
-                               $offset = $match[0][1] + strlen( $match[0][0] );
-                               continue;
+               // High-level overview:
+               // * For each CSS rule in $source that includes at least one url() value:
+               //   * Check for an @embed comment at the start indicating that all URIs should be embedded
+               //   * For each url() value:
+               //     * Check for an @embed comment directly preceding the value
+               //     * If either @embed comment exists:
+               //       * Embedding the URL as data: URI, if it's possible / allowed
+               //       * Otherwise remap the URL to work in generated stylesheets
+
+               // Guard against trailing slashes, because "some/remote/../foo.png"
+               // resolves to "some/remote/foo.png" on (some?) clients (bug 27052).
+               if ( substr( $remote, -1 ) == '/' ) {
+                       $remote = substr( $remote, 0, -1 );
+               }
+
+               // Note: This will not correctly handle cases where ';', '{' or '}' appears in the rule itself,
+               // e.g. in a quoted string. You are advised not to use such characters in file names.
+               $pattern = '/[;{]\K[^;}]*' . CSSMin::URL_REGEX . '[^;}]*(?=[;}])/';
+               return preg_replace_callback( $pattern, function ( $matchOuter ) use ( $local, $remote, $embedData ) {
+                       $rule = $matchOuter[0];
+
+                       // Check for global @embed comment and remove it
+                       $embedAll = false;
+                       $rule = preg_replace( '/^(\s*)' . CSSMin::EMBED_REGEX . '\s*/', '$1', $rule, 1, $embedAll );
+
+                       // Build two versions of current rule: with remapped URLs and with embedded data: URIs (where possible)
+                       $pattern = '/(?P<embed>' . CSSMin::EMBED_REGEX . '\s*|)' . CSSMin::URL_REGEX . '/';
+
+                       $ruleWithRemapped = preg_replace_callback( $pattern, function ( $match ) use ( $local, $remote ) {
+                               $remapped = CSSMin::remapOne( $match['file'], $match['query'], $local, $remote, false );
+                               return "url({$remapped})";
+                       }, $rule );
+
+                       if ( $embedData ) {
+                               $ruleWithEmbedded = preg_replace_callback( $pattern, function ( $match ) use ( $embedAll, $local, $remote ) {
+                                       $embed = $embedAll || $match['embed'];
+                                       $embedded = CSSMin::remapOne( $match['file'], $match['query'], $local, $remote, $embed );
+                                       return "url({$embedded})";
+                               }, $rule );
                        }
-                       // URLs with absolute paths like /w/index.php need to be expanded
-                       // to absolute URLs but otherwise left alone
-                       if ( $match['file'][0] !== '' && $match['file'][0][0] === '/' ) {
-                               // Replace the file path with an expanded (possibly protocol-relative) URL
-                               // ...but only if wfExpandUrl() is even available.
-                               // This will not be the case if we're running outside of MW
-                               $lengthIncrease = 0;
-                               if ( function_exists( 'wfExpandUrl' ) ) {
-                                       $expanded = wfExpandUrl( $match['file'][0], PROTO_RELATIVE );
-                                       $origLength = strlen( $match['file'][0] );
-                                       $lengthIncrease = strlen( $expanded ) - $origLength;
-                                       $source = substr_replace( $source, $expanded,
-                                               $match['file'][1], $origLength
-                                       );
-                               }
-                               // Move the offset to the end of the match, leaving it alone
-                               $offset = $match[0][1] + strlen( $match[0][0] ) + $lengthIncrease;
-                               continue;
+
+                       if ( $embedData && $ruleWithEmbedded !== $ruleWithRemapped ) {
+                               // Build 2 CSS properties; one which uses a base64 encoded data URI in place
+                               // of the @embed comment to try and retain line-number integrity, and the
+                               // other with a remapped an versioned URL and an Internet Explorer hack
+                               // making it ignored in all browsers that support data URIs
+                               return "$ruleWithEmbedded;$ruleWithRemapped!ie";
+                       } else {
+                               // No reason to repeat twice
+                               return $ruleWithRemapped;
                        }
+               }, $source );
+
+               return $source;
+       }
+
+       /**
+        * Remap or embed a CSS URL path.
+        *
+        * @param string $file URL to remap/embed
+        * @param string $query
+        * @param string $local File path where the source was read from
+        * @param string $remote URL path to the file
+        * @param bool $embed Whether to do any data URI embedding
+        * @return string Remapped/embedded URL data
+        */
+       public static function remapOne( $file, $query, $local, $remote, $embed ) {
+               // Skip fully-qualified URLs and data URIs
+               $urlScheme = parse_url( $file, PHP_URL_SCHEME );
+               if ( $urlScheme ) {
+                       return $file;
+               }
 
-                       // Guard against double slashes, because "some/remote/../foo.png"
-                       // resolves to "some/remote/foo.png" on (some?) clients (bug 27052).
-                       if ( substr( $remote, -1 ) == '/' ) {
-                               $remote = substr( $remote, 0, -1 );
+               // URLs with absolute paths like /w/index.php need to be expanded
+               // to absolute URLs but otherwise left alone
+               if ( $file !== '' && $file[0] === '/' ) {
+                       // Replace the file path with an expanded (possibly protocol-relative) URL
+                       // ...but only if wfExpandUrl() is even available.
+                       // This will not be the case if we're running outside of MW
+                       if ( function_exists( 'wfExpandUrl' ) ) {
+                               return wfExpandUrl( $file, PROTO_RELATIVE );
+                       } else {
+                               return $file;
                        }
+               }
 
-                       // Shortcuts
-                       $embed = $match['embed'][0];
-                       $pre = $match['pre'][0];
-                       $post = $match['post'][0];
-                       $query = $match['query'][0];
-                       $url = "{$remote}/{$match['file'][0]}";
-                       $file = "{$local}/{$match['file'][0]}";
-
-                       $replacement = false;
-
-                       if ( $local !== false && file_exists( $file ) ) {
-                               // Add version parameter as a time-stamp in ISO 8601 format,
-                               // using Z for the timezone, meaning GMT
-                               $url .= '?' . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
-                               // Embedding requires a bit of extra processing, so let's skip that if we can
-                               if ( $embedData && $embed && $match['embed'][1] > 0 ) {
-                                       $data = self::encodeImageAsDataURI( $file );
-                                       if ( $data !== false ) {
-                                               // Build 2 CSS properties; one which uses a base64 encoded data URI in place
-                                               // of the @embed comment to try and retain line-number integrity, and the
-                                               // other with a remapped an versioned URL and an Internet Explorer hack
-                                               // making it ignored in all browsers that support data URIs
-                                               $replacement = "{$pre}url({$data}){$post};{$pre}url({$url}){$post}!ie;";
-                                       }
-                               }
-                               if ( $replacement === false ) {
-                                       // Assume that all paths are relative to $remote, and make them absolute
-                                       $replacement = "{$embed}{$pre}url({$url}){$post};";
+               $url = "{$remote}/{$file}";
+               $file = "{$local}/{$file}";
+
+               $replacement = false;
+
+               if ( $local !== false && file_exists( $file ) ) {
+                       // Add version parameter as a time-stamp in ISO 8601 format,
+                       // using Z for the timezone, meaning GMT
+                       $url .= '?' . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
+                       if ( $embed ) {
+                               $data = self::encodeImageAsDataURI( $file );
+                               if ( $data !== false ) {
+                                       return $data;
+                               } else {
+                                       return $url;
                                }
-                       } elseif ( $local === false ) {
+                       } else {
                                // Assume that all paths are relative to $remote, and make them absolute
-                               $replacement = "{$embed}{$pre}url({$url}{$query}){$post};";
+                               return $url;
                        }
-                       if ( $replacement !== false ) {
-                               // Perform replacement on the source
-                               $source = substr_replace(
-                                       $source, $replacement, $match[0][1], strlen( $match[0][0] )
-                               );
-                               // Move the offset to the end of the replacement in the source
-                               $offset = $match[0][1] + strlen( $replacement );
-                               continue;
-                       }
-                       // Move the offset to the end of the match, leaving it alone
-                       $offset = $match[0][1] + strlen( $match[0][0] );
+               } elseif ( $local === false ) {
+                       // Assume that all paths are relative to $remote, and make them absolute
+                       return $url . $query;
+               } else {
+                       return $file;
                }
-               return $source;
        }
 
        /**
diff --git a/includes/libs/ScopedPHPTimeout.php b/includes/libs/ScopedPHPTimeout.php
new file mode 100644 (file)
index 0000000..d1493c3
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Expansion of the PHP execution time limit feature for a function call.
+ *
+ * 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
+ */
+
+/**
+ * Class to expand PHP execution time for a function call.
+ * Use this when performing changes that should not be interrupted.
+ *
+ * On construction, set_time_limit() is called and set to $seconds.
+ * If the client aborts the connection, PHP will continue to run.
+ * When the object goes out of scope, the timer is restarted, with
+ * the original time limit minus the time the object existed.
+ */
+class ScopedPHPTimeout {
+       protected $startTime; // float; seconds
+       protected $oldTimeout; // integer; seconds
+       protected $oldIgnoreAbort; // boolean
+
+       protected static $stackDepth = 0; // integer
+       protected static $totalCalls = 0; // integer
+       protected static $totalElapsed = 0; // float; seconds
+
+       /* Prevent callers in infinite loops from running forever */
+       const MAX_TOTAL_CALLS = 1000000;
+       const MAX_TOTAL_TIME = 300; // seconds
+
+       /**
+        * @param $seconds integer
+        */
+       public function __construct( $seconds ) {
+               if ( ini_get( 'max_execution_time' ) > 0 ) { // CLI uses 0
+                       if ( self::$totalCalls >= self::MAX_TOTAL_CALLS ) {
+                               trigger_error( "Maximum invocations of " . __CLASS__ . " exceeded." );
+                       } elseif ( self::$totalElapsed >= self::MAX_TOTAL_TIME ) {
+                               trigger_error( "Time limit within invocations of " . __CLASS__ . " exceeded." );
+                       } elseif ( self::$stackDepth > 0 ) { // recursion guard
+                               trigger_error( "Resursive invocation of " . __CLASS__ . " attempted." );
+                       } else {
+                               $this->oldIgnoreAbort = ignore_user_abort( true );
+                               $this->oldTimeout = ini_set( 'max_execution_time', $seconds );
+                               $this->startTime = microtime( true );
+                               ++self::$stackDepth;
+                               ++self::$totalCalls; // proof against < 1us scopes
+                       }
+               }
+       }
+
+       /**
+        * Restore the original timeout.
+        * This does not account for the timer value on __construct().
+        */
+       public function __destruct() {
+               if ( $this->oldTimeout ) {
+                       $elapsed = microtime( true ) - $this->startTime;
+                       // Note: a limit of 0 is treated as "forever"
+                       set_time_limit( max( 1, $this->oldTimeout - (int)$elapsed ) );
+                       // If each scoped timeout is for less than one second, we end up
+                       // restoring the original timeout without any decrease in value.
+                       // Thus web scripts in an infinite loop can run forever unless we
+                       // take some measures to prevent this. Track total time and calls.
+                       self::$totalElapsed += $elapsed;
+                       --self::$stackDepth;
+                       ignore_user_abort( $this->oldIgnoreAbort );
+               }
+       }
+}
diff --git a/includes/libs/XmlTypeCheck.php b/includes/libs/XmlTypeCheck.php
new file mode 100644 (file)
index 0000000..92ca7d8
--- /dev/null
@@ -0,0 +1,184 @@
+<?php
+/**
+ * XML syntax and type checker.
+ *
+ * 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
+ */
+
+class XmlTypeCheck {
+       /**
+        * Will be set to true or false to indicate whether the file is
+        * well-formed XML. Note that this doesn't check schema validity.
+        */
+       public $wellFormed = false;
+
+       /**
+        * Will be set to true if the optional element filter returned
+        * a match at some point.
+        */
+       public $filterMatch = false;
+
+       /**
+        * Name of the document's root element, including any namespace
+        * as an expanded URL.
+        */
+       public $rootElement = '';
+
+       /**
+        * @param string $input a filename or string containing the XML element
+        * @param callable $filterCallback (optional)
+        *        Function to call to do additional custom validity checks from the
+        *        SAX element handler event. This gives you access to the element
+        *        namespace, name, and attributes, but not to text contents.
+        *        Filter should return 'true' to toggle on $this->filterMatch
+        * @param boolean $isFile (optional) indicates if the first parameter is a
+        *        filename (default, true) or if it is a string (false)
+        */
+       function __construct( $input, $filterCallback = null, $isFile = true ) {
+               $this->filterCallback = $filterCallback;
+               if ( $isFile ) {
+                       $this->validateFromFile( $input );
+               } else {
+                       $this->validateFromString( $input );
+               }
+       }
+
+       /**
+        * Alternative constructor: from filename
+        *
+        * @param string $fname the filename of an XML document
+        * @param callable $filterCallback (optional)
+        *        Function to call to do additional custom validity checks from the
+        *        SAX element handler event. This gives you access to the element
+        *        namespace, name, and attributes, but not to text contents.
+        *        Filter should return 'true' to toggle on $this->filterMatch
+        * @return XmlTypeCheck
+        */
+       public static function newFromFilename( $fname, $filterCallback = null ) {
+               return new self( $fname, $filterCallback, true );
+       }
+
+       /**
+        * Alternative constructor: from string
+        *
+        * @param string $string a string containing an XML element
+        * @param callable $filterCallback (optional)
+        *        Function to call to do additional custom validity checks from the
+        *        SAX element handler event. This gives you access to the element
+        *        namespace, name, and attributes, but not to text contents.
+        *        Filter should return 'true' to toggle on $this->filterMatch
+        * @return XmlTypeCheck
+        */
+       public static function newFromString( $string, $filterCallback = null ) {
+               return new self( $string, $filterCallback, false );
+       }
+
+       /**
+        * Get the root element. Simple accessor to $rootElement
+        *
+        * @return string
+        */
+       public function getRootElement() {
+               return $this->rootElement;
+       }
+
+       /**
+        * Get an XML parser with the root element handler.
+        * @see XmlTypeCheck::rootElementOpen()
+        * @return resource a resource handle for the XML parser
+        */
+       private function getParser() {
+               $parser = xml_parser_create_ns( 'UTF-8' );
+               // case folding violates XML standard, turn it off
+               xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
+               xml_set_element_handler( $parser, array( $this, 'rootElementOpen' ), false );
+               return $parser;
+       }
+
+       /**
+        * @param string $fname the filename
+        */
+       private function validateFromFile( $fname ) {
+               $parser = $this->getParser();
+
+               if ( file_exists( $fname ) ) {
+                       $file = fopen( $fname, "rb" );
+                       if ( $file ) {
+                               do {
+                                       $chunk = fread( $file, 32768 );
+                                       $ret = xml_parse( $parser, $chunk, feof( $file ) );
+                                       if ( $ret == 0 ) {
+                                               $this->wellFormed = false;
+                                               fclose( $file );
+                                               xml_parser_free( $parser );
+                                               return;
+                                       }
+                               } while ( !feof( $file ) );
+
+                               fclose( $file );
+                       }
+               }
+               $this->wellFormed = true;
+
+               xml_parser_free( $parser );
+       }
+
+       /**
+        *
+        * @param string $string the XML-input-string to be checked.
+        */
+       private function validateFromString( $string ) {
+               $parser = $this->getParser();
+               $ret = xml_parse( $parser, $string, true );
+               xml_parser_free( $parser );
+               if ( $ret == 0 ) {
+                       $this->wellFormed = false;
+                       return;
+               }
+               $this->wellFormed = true;
+       }
+
+       /**
+        * @param $parser
+        * @param $name
+        * @param $attribs
+        */
+       private function rootElementOpen( $parser, $name, $attribs ) {
+               $this->rootElement = $name;
+
+               if ( is_callable( $this->filterCallback ) ) {
+                       xml_set_element_handler( $parser, array( $this, 'elementOpen' ), false );
+                       $this->elementOpen( $parser, $name, $attribs );
+               } else {
+                       // We only need the first open element
+                       xml_set_element_handler( $parser, false, false );
+               }
+       }
+
+       /**
+        * @param $parser
+        * @param $name
+        * @param $attribs
+        */
+       private function elementOpen( $parser, $name, $attribs ) {
+               if ( call_user_func( $this->filterCallback, $name, $attribs ) ) {
+                       // Filter hit!
+                       $this->filterMatch = true;
+               }
+       }
+}
index 2a1545b..82197b5 100644 (file)
@@ -6,7 +6,40 @@
 # and is available on most Linux systems. If Perl was distributed with
 # BSD::Resource included, we would happily use that instead, but it isn't.
 
+# Clean up cgroup
+cleanup() {
+       # First we have to move the current task into a "garbage" group, otherwise
+       # the cgroup will not be empty, and attempting to remove it will fail with
+       # "Device or resource busy"
+       if [ -w "$MW_CGROUP"/tasks ]; then
+               GARBAGE="$MW_CGROUP"
+       else
+               GARBAGE="$MW_CGROUP"/garbage-`id -un`
+               if [ ! -e "$GARBAGE" ]; then
+                       mkdir -m 0700 "$GARBAGE"
+               fi
+       fi
+       echo $BASHPID > "$GARBAGE"/tasks
+
+       # Suppress errors in case the cgroup has disappeared due to a release script
+       rmdir "$MW_CGROUP"/$$ 2>/dev/null
+}
+
+updateTaskCount() {
+       # There are lots of ways to count lines in a file in shell script, but this
+       # is one of the few that doesn't create another process, which would
+       # increase the returned number of tasks.
+       readarray < "$MW_CGROUP"/$$/tasks
+       NUM_TASKS=${#MAPFILE[*]}
+}
+
+log() {
+       echo limit.sh: "$*" >&3
+       echo limit.sh: "$*" >&2
+}
+
 MW_INCLUDE_STDERR=
+MW_USE_LOG_PIPE=
 MW_CPU_LIMIT=0
 MW_CGROUP=
 MW_MEM_LIMIT=0
@@ -19,6 +52,10 @@ eval "$2"
 if [ -n "$MW_INCLUDE_STDERR" ]; then
        exec 2>&1
 fi
+if [ -z "$MW_USE_LOG_PIPE" ]; then
+       # Open a dummy log FD
+       exec 3>/dev/null
+fi
 
 if [ "$MW_CPU_LIMIT" -gt 0 ]; then
        ulimit -t "$MW_CPU_LIMIT"
@@ -27,9 +64,11 @@ if [ "$MW_MEM_LIMIT" -gt 0 ]; then
        if [ -n "$MW_CGROUP" ]; then
                # Create cgroup
                if ! mkdir -m 0700 "$MW_CGROUP"/$$; then
-                       echo "limit.sh: failed to create the cgroup." 1>&2
-                       exit 1
+                       log "failed to create the cgroup."
+                       MW_CGROUP=""
                fi
+       fi
+       if [ -n "$MW_CGROUP" ]; then
                echo $$ > "$MW_CGROUP"/$$/tasks
                if [ -n "$MW_CGROUP_NOTIFY" ]; then
                        echo "1" > "$MW_CGROUP"/$$/notify_on_release
@@ -48,43 +87,16 @@ if [ "$MW_FILE_SIZE_LIMIT" -gt 0 ]; then
        ulimit -f "$MW_FILE_SIZE_LIMIT"
 fi
 if [ "$MW_WALL_CLOCK_LIMIT" -gt 0 -a -x "/usr/bin/timeout" ]; then
-       /usr/bin/timeout $MW_WALL_CLOCK_LIMIT /bin/bash -c "$1"
+       /usr/bin/timeout $MW_WALL_CLOCK_LIMIT /bin/bash -c "$1" 3>&-
        STATUS="$?"
        if [ "$STATUS" == 124 ]; then
-               echo "limit.sh: timed out." 1>&2
+               log "timed out executing command \"$1\""
        fi
 else
-       eval "$1"
+       eval "$1" 3>&-
        STATUS="$?"
 fi
 
-# Clean up cgroup
-cleanup() {
-       # First we have to move the current task into a "garbage" group, otherwise
-       # the cgroup will not be empty, and attempting to remove it will fail with
-       # "Device or resource busy"
-       if [ -w "$MW_CGROUP"/tasks ]; then
-               GARBAGE="$MW_CGROUP"
-       else
-               GARBAGE="$MW_CGROUP"/garbage-"$USER"
-               if [ ! -e "$GARBAGE" ]; then
-                       mkdir -m 0700 "$GARBAGE"
-               fi
-       fi
-       echo $BASHPID > "$GARBAGE"/tasks
-
-       # Suppress errors in case the cgroup has disappeared due to a release script
-       rmdir "$MW_CGROUP"/$$ 2>/dev/null
-}
-
-updateTaskCount() {
-       # There are lots of ways to count lines in a file in shell script, but this
-       # is one of the few that doesn't create another process, which would
-       # increase the returned number of tasks.
-       readarray < "$MW_CGROUP"/$$/tasks
-       NUM_TASKS=${#MAPFILE[*]}
-}
-
 if [ -n "$MW_CGROUP" ]; then
        updateTaskCount
 
@@ -97,7 +109,7 @@ if [ -n "$MW_CGROUP" ]; then
                                updateTaskCount
                        done
                        cleanup
-               ) >&/dev/null < /dev/null &
+               ) >&/dev/null < /dev/null 3>&- &
                disown -a
        else
                cleanup
index 01528b7..d761a87 100644 (file)
@@ -36,6 +36,7 @@ class DeleteLogFormatter extends LogFormatter {
                                return "$key-legacy";
                        }
                }
+
                return $key;
        }
 
@@ -47,11 +48,14 @@ class DeleteLogFormatter extends LogFormatter {
                $params = parent::getMessageParameters();
                $subtype = $this->entry->getSubtype();
                if ( in_array( $subtype, array( 'event', 'revision' ) ) ) {
-                       // $params[3] here is 'revision' for page revisions, 'oldimage' for file versions, or a comma-separated list of log_ids for log entries.
-                       // $subtype here is 'revision' for page revisions and file versions, or 'event' for log entries.
-                       if (
-                               ( $subtype === 'event' && count( $params ) === 6 ) ||
-                               ( $subtype === 'revision' && isset( $params[3] ) && ( $params[3] === 'revision' || $params[3] === 'oldimage' ) )
+                       // $params[3] here is 'revision' for page revisions, 'oldimage' for
+                       // file versions, or a comma-separated list of log_ids for log
+                       // entries. $subtype here is 'revision' for page revisions and file
+                       // versions, or 'event' for log entries.
+                       if ( ( $subtype === 'event' && count( $params ) === 6 )
+                               || ( $subtype === 'revision' && isset( $params[3] )
+                                       && ( $params[3] === 'revision' || $params[3] === 'oldimage' )
+                               )
                        ) {
                                $paramStart = $subtype === 'revision' ? 4 : 3;
 
@@ -74,6 +78,7 @@ class DeleteLogFormatter extends LogFormatter {
                                $newParams[3] = $changeText;
                                $count = count( explode( ',', $params[$paramStart] ) );
                                $newParams[4] = $this->context->getLanguage()->formatNum( $count );
+
                                return $this->parsedParametersDeleteLog = $newParams;
                        } else {
                                return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
@@ -87,6 +92,7 @@ class DeleteLogFormatter extends LogFormatter {
                // Input is like ofield=2134 or just the number
                if ( strpos( $string, 'field=' ) === 1 ) {
                        list( , $field ) = explode( '=', $string );
+
                        return (int)$field;
                } else {
                        return (int)$string;
@@ -95,102 +101,106 @@ class DeleteLogFormatter extends LogFormatter {
 
        public function getActionLinks() {
                $user = $this->context->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) || $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
+               if ( !$user->isAllowed( 'deletedhistory' )
+                       || $this->entry->isDeleted( LogPage::DELETED_ACTION )
+               ) {
                        return '';
                }
 
                switch ( $this->entry->getSubtype() ) {
-               case 'delete': // Show undelete link
-                       if ( $user->isAllowed( 'undelete' ) ) {
-                               $message = 'undeletelink';
-                       } else {
-                               $message = 'undeleteviewlink';
-                       }
-                       $revert = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Undelete' ),
-                               $this->msg( $message )->escaped(),
-                               array(),
-                               array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() )
-                       );
-                       return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
-
-               case 'revision': // If an edit was hidden from a page give a review link to the history
-                       $params = $this->extractParameters();
-                       if ( !isset( $params[3] ) || !isset( $params[4] ) ) {
-                               return '';
-                       }
-
-                       // Different revision types use different URL params...
-                       $key = $params[3];
-                       // This is a CSV of the IDs
-                       $ids = explode( ',', $params[4] );
-
-                       $links = array();
-
-                       // If there's only one item, we can show a diff link
-                       if ( count( $ids ) == 1 ) {
-                               // Live revision diffs...
-                               if ( $key == 'oldid' || $key == 'revision' ) {
-                                       $links[] = Linker::linkKnown(
-                                               $this->entry->getTarget(),
-                                               $this->msg( 'diff' )->escaped(),
-                                               array(),
-                                               array(
-                                                       'diff' => intval( $ids[0] ),
-                                                       'unhide' => 1
-                                               )
-                                       );
-                               // Deleted revision diffs...
-                               } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
-                                       $links[] = Linker::linkKnown(
-                                               SpecialPage::getTitleFor( 'Undelete' ),
-                                               $this->msg( 'diff' )->escaped(),
-                                               array(),
-                                               array(
-                                                       'target' => $this->entry->getTarget()->getPrefixedDBkey(),
-                                                       'diff' => 'prev',
-                                                       'timestamp' => $ids[0]
-                                               )
-                                       );
+                       case 'delete': // Show undelete link
+                               if ( $user->isAllowed( 'undelete' ) ) {
+                                       $message = 'undeletelink';
+                               } else {
+                                       $message = 'undeleteviewlink';
+                               }
+                               $revert = Linker::linkKnown(
+                                       SpecialPage::getTitleFor( 'Undelete' ),
+                                       $this->msg( $message )->escaped(),
+                                       array(),
+                                       array( 'target' => $this->entry->getTarget()->getPrefixedDBkey() )
+                               );
+
+                               return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+
+                       case 'revision': // If an edit was hidden from a page give a review link to the history
+                               $params = $this->extractParameters();
+                               if ( !isset( $params[3] ) || !isset( $params[4] ) ) {
+                                       return '';
                                }
-                       }
-
-                       // View/modify link...
-                       $links[] = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Revisiondelete' ),
-                               $this->msg( 'revdel-restore' )->escaped(),
-                               array(),
-                               array(
-                                       'target' => $this->entry->getTarget()->getPrefixedText(),
-                                       'type' => $key,
-                                       'ids' => implode( ',', $ids ),
-                               )
-                       );
 
-                       return $this->msg( 'parentheses' )->rawParams(
-                               $this->context->getLanguage()->pipeList( $links ) )->escaped();
+                               // Different revision types use different URL params...
+                               $key = $params[3];
+                               // This is a CSV of the IDs
+                               $ids = explode( ',', $params[4] );
+
+                               $links = array();
+
+                               // If there's only one item, we can show a diff link
+                               if ( count( $ids ) == 1 ) {
+                                       // Live revision diffs...
+                                       if ( $key == 'oldid' || $key == 'revision' ) {
+                                               $links[] = Linker::linkKnown(
+                                                       $this->entry->getTarget(),
+                                                       $this->msg( 'diff' )->escaped(),
+                                                       array(),
+                                                       array(
+                                                               'diff' => intval( $ids[0] ),
+                                                               'unhide' => 1
+                                                       )
+                                               );
+                                               // Deleted revision diffs...
+                                       } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
+                                               $links[] = Linker::linkKnown(
+                                                       SpecialPage::getTitleFor( 'Undelete' ),
+                                                       $this->msg( 'diff' )->escaped(),
+                                                       array(),
+                                                       array(
+                                                               'target' => $this->entry->getTarget()->getPrefixedDBkey(),
+                                                               'diff' => 'prev',
+                                                               'timestamp' => $ids[0]
+                                                       )
+                                               );
+                                       }
+                               }
 
-               case 'event': // Hidden log items, give review link
-                       $params = $this->extractParameters();
-                       if ( !isset( $params[3] ) ) {
+                               // View/modify link...
+                               $links[] = Linker::linkKnown(
+                                       SpecialPage::getTitleFor( 'Revisiondelete' ),
+                                       $this->msg( 'revdel-restore' )->escaped(),
+                                       array(),
+                                       array(
+                                               'target' => $this->entry->getTarget()->getPrefixedText(),
+                                               'type' => $key,
+                                               'ids' => implode( ',', $ids ),
+                                       )
+                               );
+
+                               return $this->msg( 'parentheses' )->rawParams(
+                                       $this->context->getLanguage()->pipeList( $links ) )->escaped();
+
+                       case 'event': // Hidden log items, give review link
+                               $params = $this->extractParameters();
+                               if ( !isset( $params[3] ) ) {
+                                       return '';
+                               }
+                               // This is a CSV of the IDs
+                               $query = $params[3];
+                               // Link to each hidden object ID, $params[1] is the url param
+                               $revert = Linker::linkKnown(
+                                       SpecialPage::getTitleFor( 'Revisiondelete' ),
+                                       $this->msg( 'revdel-restore' )->escaped(),
+                                       array(),
+                                       array(
+                                               'target' => $this->entry->getTarget()->getPrefixedText(),
+                                               'type' => 'logging',
+                                               'ids' => $query
+                                       )
+                               );
+
+                               return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
+                       default:
                                return '';
-                       }
-                       // This is a CSV of the IDs
-                       $query = $params[3];
-                       // Link to each hidden object ID, $params[1] is the url param
-                       $revert = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Revisiondelete' ),
-                               $this->msg( 'revdel-restore' )->escaped(),
-                               array(),
-                               array(
-                                       'target' => $this->entry->getTarget()->getPrefixedText(),
-                                       'type' => 'logging',
-                                       'ids' => $query
-                               )
-                       );
-                       return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
-               default:
-                       return '';
                }
        }
 }
index b2a8e50..e15943f 100644 (file)
@@ -33,7 +33,6 @@
  * @since 1.19
  */
 interface LogEntry {
-
        /**
         * The main log type.
         * @return string
@@ -117,7 +116,6 @@ abstract class LogEntryBase implements LogEntry {
        public function isLegacy() {
                return false;
        }
-
 }
 
 /**
@@ -202,6 +200,7 @@ class DatabaseLogEntry extends LogEntryBase {
        public function isLegacy() {
                // This does the check
                $this->getParameters();
+
                return $this->legacy;
        }
 
@@ -229,6 +228,7 @@ class DatabaseLogEntry extends LogEntryBase {
                                $this->legacy = true;
                        }
                }
+
                return $this->params;
        }
 
@@ -246,6 +246,7 @@ class DatabaseLogEntry extends LogEntryBase {
                                $this->performer = User::newFromName( $userText, false );
                        }
                }
+
                return $this->performer;
        }
 
@@ -253,6 +254,7 @@ class DatabaseLogEntry extends LogEntryBase {
                $namespace = $this->row->log_namespace;
                $page = $this->row->log_title;
                $title = Title::makeTitle( $namespace, $page );
+
                return $title;
        }
 
@@ -267,7 +269,6 @@ class DatabaseLogEntry extends LogEntryBase {
        public function getDeleted() {
                return $this->row->log_deleted;
        }
-
 }
 
 class RCDatabaseLogEntry extends DatabaseLogEntry {
@@ -301,6 +302,7 @@ class RCDatabaseLogEntry extends DatabaseLogEntry {
                                $this->performer = User::newFromName( $userText, false );
                        }
                }
+
                return $this->performer;
        }
 
@@ -308,6 +310,7 @@ class RCDatabaseLogEntry extends DatabaseLogEntry {
                $namespace = $this->row->rc_namespace;
                $page = $this->row->rc_title;
                $title = Title::makeTitle( $namespace, $page );
+
                return $title;
        }
 
@@ -322,7 +325,6 @@ class RCDatabaseLogEntry extends DatabaseLogEntry {
        public function getDeleted() {
                return $this->row->rc_deleted;
        }
-
 }
 
 /**
@@ -448,7 +450,7 @@ class ManualLogEntry extends LogEntryBase {
        public function insert( IDatabase $dbw = null ) {
                global $wgContLang;
 
-               $dbw = $dbw ?: wfGetDB( DB_MASTER );
+               $dbw = $dbw ? : wfGetDB( DB_MASTER );
                $id = $dbw->nextSequenceValue( 'logging_log_id_seq' );
 
                if ( $this->timestamp === null ) {
@@ -484,8 +486,8 @@ class ManualLogEntry extends LogEntryBase {
                        }
                        foreach ( $values as $value ) {
                                $rows[] = array(
-                                       'ls_field'  => $tag,
-                                       'ls_value'  => $value,
+                                       'ls_field' => $tag,
+                                       'ls_value' => $value,
                                        'ls_log_id' => $this->id
                                );
                        }
@@ -498,16 +500,12 @@ class ManualLogEntry extends LogEntryBase {
        }
 
        /**
-        * Publishes the log entry.
-        * @param int $newId id of the log entry.
-        * @param string $to rcandudp (default), rc, udp
+        * Get a RecentChanges object for the log entry
+        * @param int $newId
+        * @return RecentChange
+        * @since 1.23
         */
-       public function publish( $newId, $to = 'rcandudp' ) {
-               $log = new LogPage( $this->getType() );
-               if ( $log->isRestricted() ) {
-                       return;
-               }
-
+       public function getRecentChange( $newId = 0 ) {
                $formatter = LogFormatter::newFromEntry( $this );
                $context = RequestContext::newExtraneousContext( $this->getTarget() );
                $formatter->setContext( $context );
@@ -524,7 +522,8 @@ class ManualLogEntry extends LogEntryBase {
                                $ip = $user->getName();
                        }
                }
-               $rc = RecentChange::newLogEntry(
+
+               return RecentChange::newLogEntry(
                        $this->getTimestamp(),
                        $logpage,
                        $user,
@@ -538,6 +537,20 @@ class ManualLogEntry extends LogEntryBase {
                        $newId,
                        $formatter->getIRCActionComment() // Used for IRC feeds
                );
+       }
+
+       /**
+        * Publishes the log entry.
+        * @param int $newId id of the log entry.
+        * @param string $to rcandudp (default), rc, udp
+        */
+       public function publish( $newId, $to = 'rcandudp' ) {
+               $log = new LogPage( $this->getType() );
+               if ( $log->isRestricted() ) {
+                       return;
+               }
+
+               $rc = $this->getRecentChange( $newId );
 
                if ( $to === 'rc' || $to === 'rcandudp' ) {
                        $rc->save( 'pleasedontudp' );
@@ -578,6 +591,7 @@ class ManualLogEntry extends LogEntryBase {
 
        public function getTimestamp() {
                $ts = $this->timestamp !== null ? $this->timestamp : wfTimestampNow();
+
                return wfTimestamp( TS_MW, $ts );
        }
 
@@ -588,5 +602,4 @@ class ManualLogEntry extends LogEntryBase {
        public function getDeleted() {
                return (int)$this->deleted;
        }
-
 }
index c27b57a..fabe153 100644 (file)
@@ -176,6 +176,7 @@ class LogEventsList extends ContextSource {
                        $links[$type] = $this->msg( "log-show-hide-{$type}" )->rawParams( $link )->escaped();
                        $hiddens .= Html::hidden( "hide_{$type}_log", $val ) . "\n";
                }
+
                // Build links
                return '<small>' . $this->getLanguage()->pipeList( $links ) . '</small>' . $hiddens;
        }
@@ -191,6 +192,7 @@ class LogEventsList extends ContextSource {
                        unset( $this->mDefaultQuery['month'] );
                        unset( $this->mDefaultQuery['year'] );
                }
+
                return $this->mDefaultQuery;
        }
 
@@ -202,6 +204,7 @@ class LogEventsList extends ContextSource {
                $queryType = count( $queryTypes ) == 1 ? $queryTypes[0] : '';
                $selector = $this->getTypeSelector();
                $selector->setDefault( $queryType );
+
                return $selector->getHtml();
        }
 
@@ -242,9 +245,15 @@ class LogEventsList extends ContextSource {
         * @return String: Formatted HTML
         */
        private function getUserInput( $user ) {
-               return '<span style="white-space: nowrap">' .
-                       Xml::inputLabel( $this->msg( 'specialloguserlabel' )->text(), 'user', 'mw-log-user', 15, $user ) .
-                       '</span>';
+               $label = Xml::inputLabel(
+                       $this->msg( 'specialloguserlabel' )->text(),
+                       'user',
+                       'mw-log-user',
+                       15,
+                       $user
+               );
+
+               return '<span style="white-space: nowrap">' . $label . '</span>';
        }
 
        /**
@@ -252,9 +261,15 @@ class LogEventsList extends ContextSource {
         * @return String: Formatted HTML
         */
        private function getTitleInput( $title ) {
-               return '<span style="white-space: nowrap">' .
-                       Xml::inputLabel( $this->msg( 'speciallogtitlelabel' )->text(), 'page', 'mw-log-page', 20, $title ) .
-                       '</span>';
+               $label = Xml::inputLabel(
+                       $this->msg( 'speciallogtitlelabel' )->text(),
+                       'page',
+                       'mw-log-page',
+                       20,
+                       $title
+               );
+
+               return '<span style="white-space: nowrap">' . $label .  '</span>';
        }
 
        /**
@@ -281,6 +296,7 @@ class LogEventsList extends ContextSource {
                        return Xml::inputLabel( $this->msg( 'revdelete-offender' )->text(), 'offender',
                                'mw-log-offender', 20, $offender );
                }
+
                return '';
        }
 
@@ -343,8 +359,11 @@ class LogEventsList extends ContextSource {
         * @return string
         */
        private function getShowHideLinks( $row ) {
-               if ( ( $this->flags == self::NO_ACTION_LINK ) // we don't want to see the links
-                       || $row->log_type == 'suppress' ) { // no one can hide items from the suppress log
+               // We don't want to see the links and
+               // no one can hide items from the suppress log.
+               if ( ( $this->flags == self::NO_ACTION_LINK )
+                       || $row->log_type == 'suppress'
+               ) {
                        return '';
                }
                $del = '';
@@ -353,14 +372,21 @@ class LogEventsList extends ContextSource {
                if ( $user->isAllowed( 'deletedhistory' ) ) {
                        $canHide = $user->isAllowed( 'deletelogentry' );
                        if ( $row->log_deleted || $canHide ) {
-                               if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES ) { // Show checkboxes instead of links.
-                                       if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops
+                               // Show checkboxes instead of links.
+                               if ( $canHide && $this->flags & self::USE_REVDEL_CHECKBOXES ) {
+                                       // If event was hidden from sysops
+                                       if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) {
                                                $del = Xml::check( 'deleterevisions', false, array( 'disabled' => 'disabled' ) );
                                        } else {
-                                               $del = Xml::check( 'showhiderevisions', false, array( 'name' => 'ids[' . $row->log_id . ']' ) );
+                                               $del = Xml::check(
+                                                       'showhiderevisions',
+                                                       false,
+                                                       array( 'name' => 'ids[' . $row->log_id . ']' )
+                                               );
                                        }
                                } else {
-                                       if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) { // If event was hidden from sysops
+                                       // If event was hidden from sysops
+                                       if ( !self::userCan( $row, LogPage::DELETED_RESTRICTED, $user ) ) {
                                                $del = Linker::revDeleteLinkDisabled( $canHide );
                                        } else {
                                                $query = array(
@@ -368,11 +394,16 @@ class LogEventsList extends ContextSource {
                                                        'type' => 'logging',
                                                        'ids' => $row->log_id,
                                                );
-                                               $del = Linker::revDeleteLink( $query, self::isDeleted( $row, LogPage::DELETED_RESTRICTED ), $canHide );
+                                               $del = Linker::revDeleteLink(
+                                                       $query,
+                                                       self::isDeleted( $row, LogPage::DELETED_RESTRICTED ),
+                                                       $canHide
+                                               );
                                        }
                                }
                        }
                }
+
                return $del;
        }
 
@@ -394,6 +425,7 @@ class LogEventsList extends ContextSource {
                                $match = $wgUser->isAllowed( $right );
                        }
                }
+
                return $match;
        }
 
@@ -431,6 +463,7 @@ class LogEventsList extends ContextSource {
                                global $wgUser;
                                $user = $wgUser;
                        }
+
                        return $user->isAllowed( $permission );
                } else {
                        return true;
@@ -613,6 +646,7 @@ class LogEventsList extends ContextSource {
                } elseif ( $hiddenLogs ) {
                        return 'log_type NOT IN (' . $db->makeList( $hiddenLogs ) . ')';
                }
+
                return false;
        }
 }
index 8f60aee..ab6e35e 100644 (file)
@@ -154,6 +154,7 @@ class LogFormatter {
                $this->plaintext = true;
                $text = $this->getActionText();
                $this->plaintext = false;
+
                return $text;
        }
 
@@ -224,15 +225,19 @@ class LogFormatter {
                                                $text = wfMessage( 'undeletedarticle' )
                                                        ->rawParams( $target )->inContentLanguage()->escaped();
                                                break;
+                                       // @codingStandardsIgnoreStart Long line
                                        //case 'revision': // Revision deletion
                                        //case 'event': // Log deletion
-                                               // see https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/LogPage.php?&pathrev=97044&r1=97043&r2=97044
+                                       // see https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/LogPage.php?&pathrev=97044&r1=97043&r2=97044
                                        //default:
+                                       // @codingStandardsIgnoreEnd
                                }
                                break;
 
                        case 'patrol':
+                               // @codingStandardsIgnoreStart Long line
                                // https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/PatrolLog.php?&pathrev=97495&r1=97494&r2=97495
+                               // @codingStandardsIgnoreEnd
                                // Create a diff link to the patrolled revision
                                if ( $entry->getSubtype() === 'patrol' ) {
                                        $diffLink = htmlspecialchars(
@@ -247,18 +252,18 @@ class LogFormatter {
 
                        case 'protect':
                                switch ( $entry->getSubtype() ) {
-                               case 'protect':
-                                       $text = wfMessage( 'protectedarticle' )
-                                               ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
-                                       break;
-                               case 'unprotect':
-                                       $text = wfMessage( 'unprotectedarticle' )
-                                               ->rawParams( $target )->inContentLanguage()->escaped();
-                                       break;
-                               case 'modify':
-                                       $text = wfMessage( 'modifiedarticleprotection' )
-                                               ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
-                                       break;
+                                       case 'protect':
+                                               $text = wfMessage( 'protectedarticle' )
+                                                       ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
+                                               break;
+                                       case 'unprotect':
+                                               $text = wfMessage( 'unprotectedarticle' )
+                                                       ->rawParams( $target )->inContentLanguage()->escaped();
+                                               break;
+                                       case 'modify':
+                                               $text = wfMessage( 'modifiedarticleprotection' )
+                                                       ->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
+                                               break;
                                }
                                break;
 
@@ -316,8 +321,7 @@ class LogFormatter {
                                                break;
                                }
                                break;
-
-                       // case 'suppress' --private log -- aaron  (sign your messages so we know who to blame in a few years :-D)
+                       // case 'suppress' --private log -- aaron  (so we know who to blame in a few years :-D)
                        // default:
                }
                if ( is_null( $text ) ) {
@@ -326,6 +330,7 @@ class LogFormatter {
 
                $this->plaintext = false;
                $this->irctext = false;
+
                return $text;
        }
 
@@ -359,6 +364,7 @@ class LogFormatter {
        protected function getActionMessage() {
                $message = $this->msg( $this->getMessageKey() );
                $message->params( $this->getMessageParameters() );
+
                return $message;
        }
 
@@ -421,6 +427,7 @@ class LogFormatter {
                                }
                        }
                }
+
                return $params;
        }
 
@@ -446,6 +453,7 @@ class LogFormatter {
 
                // Bad things happens if the numbers are not in correct order
                ksort( $params );
+
                return $this->parsedParameters = $params;
        }
 
@@ -538,6 +546,7 @@ class LogFormatter {
                        }
                        $link = '[[' . $title->getPrefixedText() . ']]';
                }
+
                return $link;
        }
 
@@ -592,6 +601,7 @@ class LogFormatter {
 
                $content = $this->msg( $message )->escaped();
                $attribs = array( 'class' => 'history-deleted' );
+
                return Html::rawElement( 'span', $attribs, $content );
        }
 
@@ -605,6 +615,7 @@ class LogFormatter {
                        return $content;
                }
                $attribs = array( 'class' => 'history-deleted' );
+
                return Html::rawElement( 'span', $attribs, $content );
        }
 
@@ -635,6 +646,7 @@ class LogFormatter {
                                );
                        }
                }
+
                return $element;
        }
 
@@ -654,7 +666,6 @@ class LogFormatter {
                // problems with extensions
                return $this->getMessageParameters();
        }
-
 }
 
 /**
@@ -735,7 +746,9 @@ class LegacyLogFormatter extends LogFormatter {
                $subtype = $this->entry->getSubtype();
 
                // Show unblock/change block link
-               if ( ( $type == 'block' || $type == 'suppress' ) && ( $subtype == 'block' || $subtype == 'reblock' ) ) {
+               if ( ( $type == 'block' || $type == 'suppress' )
+                       && ( $subtype == 'block' || $subtype == 'reblock' )
+               ) {
                        if ( !$this->context->getUser()->isAllowed( 'block' ) ) {
                                return '';
                        }
@@ -750,10 +763,13 @@ class LegacyLogFormatter extends LogFormatter {
                                        $this->msg( 'change-blocklink' )->escaped()
                                )
                        );
+
                        return $this->msg( 'parentheses' )->rawParams(
                                $this->context->getLanguage()->pipeList( $links ) )->escaped();
                // Show change protection link
-               } elseif ( $type == 'protect' && ( $subtype == 'protect' || $subtype == 'modify' || $subtype == 'unprotect' ) ) {
+               } elseif ( $type == 'protect'
+                       && ( $subtype == 'protect' || $subtype == 'modify' || $subtype == 'unprotect' )
+               ) {
                        $links = array(
                                Linker::link( $title,
                                        $this->msg( 'hist' )->escaped(),
@@ -772,6 +788,7 @@ class LegacyLogFormatter extends LogFormatter {
                                        array( 'action' => 'protect' )
                                );
                        }
+
                        return $this->msg( 'parentheses' )->rawParams(
                                $this->context->getLanguage()->pipeList( $links ) )->escaped();
                // Show unmerge link
@@ -791,6 +808,7 @@ class LegacyLogFormatter extends LogFormatter {
                                        'mergepoint' => $params[4]
                                )
                        );
+
                        return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
                }
 
@@ -813,4 +831,3 @@ class LegacyLogFormatter extends LogFormatter {
                return $this->revert;
        }
 }
-
index cc473c1..51c41a8 100644 (file)
@@ -118,6 +118,7 @@ class LogPage {
                        );
                        $rc->notifyRC2UDP();
                }
+
                return $newId;
        }
 
@@ -175,6 +176,7 @@ class LogPage {
         */
        public static function validTypes() {
                global $wgLogTypes;
+
                return $wgLogTypes;
        }
 
@@ -216,6 +218,7 @@ class LogPage {
         */
        public static function logHeader( $type ) {
                global $wgLogHeaders;
+
                return wfMessage( $wgLogHeaders[$type] )->parse();
        }
 
@@ -233,8 +236,8 @@ class LogPage {
         * @return HTML string
         */
        public static function actionText( $type, $action, $title = null, $skin = null,
-               $params = array(), $filterWikilinks = false )
-       {
+               $params = array(), $filterWikilinks = false
+       {
                global $wgLang, $wgContLang, $wgLogActions;
 
                if ( is_null( $skin ) ) {
@@ -254,7 +257,8 @@ class LogPage {
                                $titleLink = self::getTitleLink( $type, $langObjOrNull, $title, $params );
 
                                if ( count( $params ) == 0 ) {
-                                       $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped();
+                                       $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )
+                                               ->inLanguage( $langObj )->escaped();
                                } else {
                                        $details = '';
                                        array_unshift( $params, $titleLink );
@@ -262,7 +266,12 @@ class LogPage {
                                        // User suppression
                                        if ( preg_match( '/^(block|suppress)\/(block|reblock)$/', $key ) ) {
                                                if ( $skin ) {
-                                                       $params[1] = '<span class="blockExpiry" title="&lrm;' . htmlspecialchars( $params[1] ) . '">' .
+                                                       // Localize the duration, and add a tooltip
+                                                       // in English to help visitors from other wikis.
+                                                       // The lrm is needed to make sure that the number
+                                                       // is shown on the correct side of the tooltip text.
+                                                       $durationTooltip = '&lrm;' . htmlspecialchars( $params[1] );
+                                                       $params[1] = "<span class='blockExpiry' title='$durationTooltip'>" .
                                                                $wgLang->translateBlockExpiry( $params[1] ) . '</span>';
                                                } else {
                                                        $params[1] = $wgContLang->translateBlockExpiry( $params[1] );
@@ -281,11 +290,16 @@ class LogPage {
 
                                                // Cascading flag...
                                                if ( $params[2] ) {
-                                                       $details .= ' [' . wfMessage( 'protect-summary-cascade' )->inLanguage( $langObj )->text() . ']';
+                                                       $text = wfMessage( 'protect-summary-cascade' )
+                                                               ->inLanguage( $langObj )->text();
+                                                       $details .= ' ';
+                                                       $details .= wfMessage( 'brackets', $text )->inLanguage( $langObj )->text();
+
                                                }
                                        }
 
-                                       $rv = wfMessage( $wgLogActions[$key] )->rawParams( $params )->inLanguage( $langObj )->escaped() . $details;
+                                       $rv = wfMessage( $wgLogActions[$key] )->rawParams( $params )
+                                                       ->inLanguage( $langObj )->escaped() . $details;
                                }
                        }
                } else {
@@ -402,7 +416,8 @@ class LogPage {
        /**
         * Add a log entry
         *
-        * @param string $action one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir'
+        * @param string $action one of '', 'block', 'protect', 'rights', 'delete',
+        *   'upload', 'move', 'move_redir'
         * @param $target Title object
         * @param string $comment description associated
         * @param array $params parameters passed later to wfMessage function
@@ -523,10 +538,12 @@ class LogPage {
                        return ''; //nothing to do
                }
                $flags = explode( ',', $flags );
+               $flagsCount = count( $flags );
 
-               for ( $i = 0; $i < count( $flags ); $i++ ) {
+               for ( $i = 0; $i < $flagsCount; $i++ ) {
                        $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
                }
+
                return wfMessage( 'parentheses' )->inLanguage( $lang )
                        ->rawParams( $lang->commaList( $flags ) )->escaped();
        }
@@ -593,6 +610,7 @@ class LogPage {
                } else {
                        $key = 'log-description-' . $this->type;
                }
+
                return wfMessage( $key );
        }
 
@@ -609,6 +627,7 @@ class LogPage {
                        // '' always returns true with $user->isAllowed()
                        $restriction = '';
                }
+
                return $restriction;
        }
 
@@ -619,7 +638,7 @@ class LogPage {
         */
        public function isRestricted() {
                $restriction = $this->getRestriction();
+
                return $restriction !== '' && $restriction !== '*';
        }
-
 }
index 09ae3b8..1c613e8 100644 (file)
  * @ingroup Pager
  */
 class LogPager extends ReverseChronologicalPager {
-       private $types = array(), $performer = '', $title = '', $pattern = '';
+       private $types = array();
+       private $performer = '';
+       private $title = '';
+       private $pattern = '';
        private $typeCGI = '';
        public $mLogEventsList;
 
@@ -35,13 +38,13 @@ class LogPager extends ReverseChronologicalPager {
         * Constructor
         *
         * @param LogEventsList $list
-        * @param string $types or Array: log types to show
+        * @param string|array $types Log types to show
         * @param string $performer the user who made the log entries
         * @param string|Title $title the page title the log entries are for
         * @param string $pattern do a prefix search rather than an exact title match
         * @param array $conds extra conditions for the query
-        * @param int $year The year to start from
-        * @param int $month The month to start from
+        * @param int|bool $year The year to start from. Default: false
+        * @param int|bool $month The month to start from. Default: false
         * @param string $tagFilter tag
         */
        public function __construct( $list, $types = array(), $performer = '', $title = '', $pattern = '',
@@ -64,6 +67,7 @@ class LogPager extends ReverseChronologicalPager {
                $query['user'] = $this->performer;
                $query['month'] = $this->mMonth;
                $query['year'] = $this->mYear;
+
                return $query;
        }
 
@@ -84,6 +88,7 @@ class LogPager extends ReverseChronologicalPager {
                                }
                        }
                }
+
                return $filters;
        }
 
@@ -242,8 +247,8 @@ class LogPager extends ReverseChronologicalPager {
                        $index['log_search'] = 'ls_field_val';
                        $index['logging'] = 'PRIMARY';
                        if ( !$this->hasEqualsClause( 'ls_field' )
-                               || !$this->hasEqualsClause( 'ls_value' ) )
-                       {
+                               || !$this->hasEqualsClause( 'ls_value' )
+                       {
                                # Since (ls_field,ls_value,ls_logid) is unique, if the condition is
                                # to match a specific (ls_field,ls_value) tuple, then there will be
                                # no duplicate log rows. Otherwise, we need to remove the duplicates.
@@ -266,6 +271,7 @@ class LogPager extends ReverseChronologicalPager {
                # Add ChangeTags filter query
                ChangeTags::modifyDisplayQuery( $info['tables'], $info['fields'], $info['conds'],
                        $info['join_conds'], $info['options'], $this->mTagFilter );
+
                return $info;
        }
 
@@ -303,6 +309,7 @@ class LogPager extends ReverseChronologicalPager {
                        $this->mResult->seek( 0 );
                }
                wfProfileOut( __METHOD__ );
+
                return '';
        }
 
index 0978f97..3913016 100644 (file)
@@ -31,6 +31,7 @@
 class MoveLogFormatter extends LogFormatter {
        public function getPreloadTitles() {
                $params = $this->extractParameters();
+
                return array( Title::newFromText( $params[3] ) );
        }
 
@@ -40,6 +41,7 @@ class MoveLogFormatter extends LogFormatter {
                if ( isset( $params[4] ) && $params[4] === '1' ) {
                        $key .= '-noredirect';
                }
+
                return $key;
        }
 
@@ -49,14 +51,15 @@ class MoveLogFormatter extends LogFormatter {
                $newname = $this->makePageLink( Title::newFromText( $params[3] ) );
                $params[2] = Message::rawParam( $oldname );
                $params[3] = Message::rawParam( $newname );
+
                return $params;
        }
 
        public function getActionLinks() {
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
                        || $this->entry->getSubtype() !== 'move'
-                       || !$this->context->getUser()->isAllowed( 'move' ) )
-               {
+                       || !$this->context->getUser()->isAllowed( 'move' )
+               {
                        return '';
                }
 
@@ -77,6 +80,7 @@ class MoveLogFormatter extends LogFormatter {
                                'wpMovetalk' => 0
                        )
                );
+
                return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
        }
 }
index 602728b..c870d51 100644 (file)
@@ -41,6 +41,7 @@ class NewUsersLogFormatter extends LogFormatter {
                        $params[2] = Message::rawParam( $this->makeUserLink( $target ) );
                        $params[3] = $target->getName();
                }
+
                return $params;
        }
 
@@ -51,6 +52,7 @@ class NewUsersLogFormatter extends LogFormatter {
                        # not needed and can contain incorrect links
                        return '';
                }
+
                return parent::getComment();
        }
 
@@ -60,6 +62,7 @@ class NewUsersLogFormatter extends LogFormatter {
                        //add the user talk to LinkBatch for the userLink
                        return array( Title::makeTitle( NS_USER_TALK, $this->entry->getTarget()->getText() ) );
                }
+
                return array();
        }
 }
index bb76d5a..40be52c 100644 (file)
@@ -27,7 +27,6 @@
  * logs of patrol events
  */
 class PatrolLog {
-
        /**
         * Record a log event for a change being patrolled
         *
@@ -65,6 +64,7 @@ class PatrolLog {
                if ( !$auto ) {
                        $entry->publish( $logid, 'udp' );
                }
+
                return true;
        }
 
@@ -82,5 +82,4 @@ class PatrolLog {
                        '6::auto' => (int)$auto
                );
        }
-
 }
index 507039b..2abaf17 100644 (file)
@@ -35,6 +35,7 @@ class PatrolLogFormatter extends LogFormatter {
                if ( isset( $params[5] ) && $params[5] ) {
                        $key .= '-auto';
                }
+
                return $key;
        }
 
@@ -58,6 +59,7 @@ class PatrolLogFormatter extends LogFormatter {
                }
 
                $params[3] = Message::rawParam( $revlink );
+
                return $params;
        }
 }
index d3daf6e..ac252ae 100644 (file)
@@ -55,6 +55,7 @@ class RightsLogFormatter extends LogFormatter {
                if ( !isset( $params[3] ) && !isset( $params[4] ) ) {
                        $key .= '-legacy';
                }
+
                return $key;
        }
 
index e2444a1..4959687 100644 (file)
@@ -168,6 +168,13 @@ class BitmapHandler extends ImageHandler {
 
                # Transform functions and binaries need a FS source file
                $scalerParams['srcPath'] = $image->getLocalRefPath();
+               if ( $scalerParams['srcPath'] === false ) { // Failed to get local copy
+                       wfDebugLog( 'thumbnail',
+                               sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
+                                       wfHostname(), $image->getName() ) );
+                       return new MediaTransformError( 'thumbnail_error',
+                               $scalerParams['clientWidth'], $scalerParams['clientHeight'] );
+               }
 
                # Try a hook
                $mto = null;
@@ -701,7 +708,6 @@ class BitmapHandler extends ImageHandler {
                imagejpeg( $dst_image, $thumbPath, 95 );
        }
 
-
        /**
         * Returns whether the current scaler supports rotation (im and gd do)
         *
index 7c39c81..00b4298 100644 (file)
@@ -116,7 +116,7 @@ class BitmapMetadataHandler {
        function getMetadataArray() {
                // this seems a bit ugly... This is all so its merged in right order
                // based on the MWG recomendation.
-               $temp = Array();
+               $temp = array();
                krsort( $this->metaPriority );
                foreach ( $this->metaPriority as $pri ) {
                        foreach ( $pri as $type ) {
@@ -153,7 +153,7 @@ class BitmapMetadataHandler {
 
                $seg = JpegMetadataExtractor::segmentSplitter( $filename );
                if ( isset( $seg['COM'] ) && isset( $seg['COM'][0] ) ) {
-                       $meta->addMetadata( Array( 'JPEGFileComment' => $seg['COM'] ), 'native' );
+                       $meta->addMetadata( array( 'JPEGFileComment' => $seg['COM'] ), 'native' );
                }
                if ( isset( $seg['PSIR'] ) && count( $seg['PSIR'] ) > 0 ) {
                        foreach ( $seg['PSIR'] as $curPSIRValue ) {
index 9a2794a..50dd266 100644 (file)
@@ -319,7 +319,7 @@ class Exif {
         * Make $this->mFilteredExifData
         */
        function makeFilteredData() {
-               $this->mFilteredExifData = Array();
+               $this->mFilteredExifData = array();
 
                foreach ( array_keys( $this->mRawExifData ) as $section ) {
                        if ( !in_array( $section, array_keys( $this->mExifTags ) ) ) {
index d8d0bed..aa9db3a 100644 (file)
@@ -61,16 +61,18 @@ class ExifBitmapHandler extends BitmapHandler {
                                . $metadata['Software'][0][1] . ')';
                }
 
+               $formatter = new FormatMetadata;
+
                // ContactInfo also has to be dealt with specially
                if ( isset( $metadata['Contact'] ) ) {
                        $metadata['Contact'] =
-                               FormatMetadata::collapseContactInfo(
+                               $formatter->collapseContactInfo(
                                        $metadata['Contact'] );
                }
 
                foreach ( $metadata as &$val ) {
                        if ( is_array( $val ) ) {
-                               $val = FormatMetadata::flattenArray( $val, 'ul', $avoidHtml );
+                               $val = $formatter->flattenArrayReal( $val, 'ul', $avoidHtml );
                        }
                }
                $metadata['MEDIAWIKI_EXIF_VERSION'] = 1;
@@ -95,12 +97,12 @@ class ExifBitmapHandler extends BitmapHandler {
                wfSuppressWarnings();
                $exif = unserialize( $metadata );
                wfRestoreWarnings();
-               if ( !isset( $exif['MEDIAWIKI_EXIF_VERSION'] ) ||
-                       $exif['MEDIAWIKI_EXIF_VERSION'] != Exif::version() )
-               {
-                       if ( isset( $exif['MEDIAWIKI_EXIF_VERSION'] ) &&
-                               $exif['MEDIAWIKI_EXIF_VERSION'] == 1 )
-                       {
+               if ( !isset( $exif['MEDIAWIKI_EXIF_VERSION'] )
+                       || $exif['MEDIAWIKI_EXIF_VERSION'] != Exif::version()
+               {
+                       if ( isset( $exif['MEDIAWIKI_EXIF_VERSION'] )
+                               && $exif['MEDIAWIKI_EXIF_VERSION'] == 1
+                       {
                                //back-compatible but old
                                wfDebug( __METHOD__ . ": back-compat version\n" );
                                return self::METADATA_COMPATIBLE;
@@ -117,25 +119,32 @@ class ExifBitmapHandler extends BitmapHandler {
         * @return array|bool
         */
        function formatMetadata( $image ) {
-               $metadata = $image->getMetadata();
-               if ( $metadata === self::OLD_BROKEN_FILE ||
-                       $metadata === self::BROKEN_FILE ||
-                       $this->isMetadataValid( $image, $metadata ) === self::METADATA_BAD )
-               {
+               $meta = $this->getCommonMetaArray( $image );
+               if ( count( $meta ) === 0 ) {
+                       return false;
+               }
+
+               return $this->formatMetadataHelper( $meta );
+       }
+
+       public function getCommonMetaArray( File $file ) {
+               $metadata = $file->getMetadata();
+               if ( $metadata === self::OLD_BROKEN_FILE
+                       || $metadata === self::BROKEN_FILE
+                       || $this->isMetadataValid( $file, $metadata ) === self::METADATA_BAD
+               ) {
                        // So we don't try and display metadata from PagedTiffHandler
                        // for example when using InstantCommons.
-                       return false;
+                       return array();
                }
 
                $exif = unserialize( $metadata );
                if ( !$exif ) {
-                       return false;
+                       return array();
                }
                unset( $exif['MEDIAWIKI_EXIF_VERSION'] );
-               if ( count( $exif ) == 0 ) {
-                       return false;
-               }
-               return $this->formatMetadataHelper( $exif );
+
+               return $exif;
        }
 
        function getMetadataType( $image ) {
index 1c5136f..74e51cf 100644 (file)
  * is already a large number of messages using the 'exif' prefix.
  *
  * @ingroup Media
+ * @since 1.23 the class extends ContextSource and various formerly-public internal methods are private
  */
-class FormatMetadata {
+class FormatMetadata extends ContextSource {
+
+       /**
+        * Only output a single language for multi-language fields
+        * @var boolean
+        * @since 1.23
+        */
+       protected $singleLang = false;
+
+       /**
+        * Trigger only outputting single language for multilanguage fields
+        *
+        * @param Boolean $val
+        * @since 1.23
+        */
+       public function setSingleLanguage( $val ) {
+               $this->singleLang = $val;
+       }
 
        /**
         * Numbers given by Exif user agents are often magical, that is they
@@ -52,13 +70,33 @@ class FormatMetadata {
         * value which most of the time are plain integers. This function
         * formats Exif (and other metadata) values into human readable form.
         *
+        * This is the usual entry point for this class.
+        *
         * @param array $tags the Exif data to format ( as returned by
         *                    Exif::getFilteredData() or BitmapMetadataHandler )
+        * @param IContextSource $context Context to use (optional)
         * @return array
         */
-       public static function getFormattedData( $tags ) {
-               global $wgLang;
+       public static function getFormattedData( $tags, $context = false ) {
+               $obj = new FormatMetadata;
+               if ( $context ) {
+                       $obj->setContext( $context );
+               }
+               return $obj->makeFormattedData( $tags );
+       }
 
+       /**
+        * Numbers given by Exif user agents are often magical, that is they
+        * should be replaced by a detailed explanation depending on their
+        * value which most of the time are plain integers. This function
+        * formats Exif (and other metadata) values into human readable form.
+        *
+        * @param array $tags the Exif data to format ( as returned by
+        *                    Exif::getFilteredData() or BitmapMetadataHandler )
+        * @return array
+        * @since 1.23
+        */
+       public function makeFormattedData( $tags ) {
                $resolutionunit = !isset( $tags['ResolutionUnit'] ) || $tags['ResolutionUnit'] == 2 ? 2 : 3;
                unset( $tags['ResolutionUnit'] );
 
@@ -67,7 +105,7 @@ class FormatMetadata {
                        // This seems ugly to wrap non-array's in an array just to unwrap again,
                        // especially when most of the time it is not an array
                        if ( !is_array( $tags[$tag] ) ) {
-                               $vals = Array( $vals );
+                               $vals = array( $vals );
                        }
 
                        // _type is a special value to say what array type
@@ -107,7 +145,7 @@ class FormatMetadata {
                                        $time = wfTimestamp( TS_MW, '1971:01:01 ' . $tags[$tag] );
                                        // the 1971:01:01 is just a placeholder, and not shown to user.
                                        if ( $time && intval( $time ) > 0 ) {
-                                               $tags[$tag] = $wgLang->time( $time );
+                                               $tags[$tag] = $this->getLanguage()->time( $time );
                                        }
                                } catch ( TimestampException $e ) {
                                        // This shouldn't happen, but we've seen bad formats
@@ -121,7 +159,7 @@ class FormatMetadata {
                        // instead of the other props which are single
                        // valued (mostly) so handle as a special case.
                        if ( $tag === 'Contact' ) {
-                               $vals = self::collapseContactInfo( $vals );
+                               $vals = $this->collapseContactInfo( $vals );
                                continue;
                        }
 
@@ -133,7 +171,7 @@ class FormatMetadata {
                                        case 1: case 2: case 3: case 4:
                                        case 5: case 6: case 7: case 8:
                                        case 32773: case 32946: case 34712:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -144,7 +182,7 @@ class FormatMetadata {
                                case 'PhotometricInterpretation':
                                        switch ( $val ) {
                                        case 2: case 6:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -155,7 +193,7 @@ class FormatMetadata {
                                case 'Orientation':
                                        switch ( $val ) {
                                        case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -166,7 +204,7 @@ class FormatMetadata {
                                case 'PlanarConfiguration':
                                        switch ( $val ) {
                                        case 1: case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -179,7 +217,7 @@ class FormatMetadata {
                                        switch ( $val ) {
                                        case 1:
                                        case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -191,10 +229,10 @@ class FormatMetadata {
                                case 'YResolution':
                                        switch ( $resolutionunit ) {
                                                case 2:
-                                                       $val = self::msg( 'XYResolution', 'i', self::formatNum( $val ) );
+                                                       $val = $this->exifMsg( 'XYResolution', 'i', $this->formatNum( $val ) );
                                                        break;
                                                case 3:
-                                                       $val = self::msg( 'XYResolution', 'c', self::formatNum( $val ) );
+                                                       $val = $this->exifMsg( 'XYResolution', 'c', $this->formatNum( $val ) );
                                                        break;
                                                default:
                                                        /* If not recognized, display as is. */
@@ -210,7 +248,7 @@ class FormatMetadata {
                                case 'ColorSpace':
                                        switch ( $val ) {
                                        case 1: case 65535:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -221,7 +259,7 @@ class FormatMetadata {
                                case 'ComponentsConfiguration':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3: case 4: case 5: case 6:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -238,12 +276,12 @@ class FormatMetadata {
                                case 'dc-date':
                                case 'DateTimeMetadata':
                                        if ( $val == '0000:00:00 00:00:00' || $val == '    :  :     :  :  ' ) {
-                                               $val = wfMessage( 'exif-unknowndate' )->text();
+                                               $val = $this->msg( 'exif-unknowndate' )->text();
                                        } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d):(?:\d\d)$/D', $val ) ) {
                                                // Full date.
                                                $time = wfTimestamp( TS_MW, $val );
                                                if ( $time && intval( $time ) > 0 ) {
-                                                       $val = $wgLang->timeanddate( $time );
+                                                       $val = $this->getLanguage()->timeanddate( $time );
                                                }
                                        } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d) (?:\d\d):(?:\d\d)$/D', $val ) ) {
                                                // No second field. Still format the same
@@ -251,7 +289,7 @@ class FormatMetadata {
                                                // but second still available in api
                                                $time = wfTimestamp( TS_MW, $val . ':00' );
                                                if ( $time && intval( $time ) > 0 ) {
-                                                       $val = $wgLang->timeanddate( $time );
+                                                       $val = $this->getLanguage()->timeanddate( $time );
                                                }
                                        } elseif ( preg_match( '/^(?:\d{4}):(?:\d\d):(?:\d\d)$/D', $val ) ) {
                                                // If only the date but not the time is filled in.
@@ -260,7 +298,7 @@ class FormatMetadata {
                                                        . substr( $val, 8, 2 )
                                                        . '000000' );
                                                if ( $time && intval( $time ) > 0 ) {
-                                                       $val = $wgLang->date( $time );
+                                                       $val = $this->getLanguage()->date( $time );
                                                }
                                        }
                                        // else it will just output $val without formatting it.
@@ -269,7 +307,7 @@ class FormatMetadata {
                                case 'ExposureProgram':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -278,13 +316,13 @@ class FormatMetadata {
                                        break;
 
                                case 'SubjectDistance':
-                                       $val = self::msg( $tag, '', self::formatNum( $val ) );
+                                       $val = $this->exifMsg( $tag, '', $this->formatNum( $val ) );
                                        break;
 
                                case 'MeteringMode':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 255:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -297,7 +335,7 @@ class FormatMetadata {
                                        case 0: case 1: case 2: case 3: case 4: case 9: case 10: case 11:
                                        case 12: case 13: case 14: case 15: case 17: case 18: case 19: case 20:
                                        case 21: case 22: case 23: case 24: case 255:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -322,15 +360,15 @@ class FormatMetadata {
                                                        continue;
                                                }
                                                $fullTag = $tag . '-' . $subTag;
-                                               $flashMsgs[] = self::msg( $fullTag, $subValue );
+                                               $flashMsgs[] = $this->exifMsg( $fullTag, $subValue );
                                        }
-                                       $val = $wgLang->commaList( $flashMsgs );
+                                       $val = $this->getLanguage()->commaList( $flashMsgs );
                                        break;
 
                                case 'FocalPlaneResolutionUnit':
                                        switch ( $val ) {
                                        case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -341,7 +379,7 @@ class FormatMetadata {
                                case 'SensingMethod':
                                        switch ( $val ) {
                                        case 1: case 2: case 3: case 4: case 5: case 7: case 8:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -352,7 +390,7 @@ class FormatMetadata {
                                case 'FileSource':
                                        switch ( $val ) {
                                        case 3:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -363,7 +401,7 @@ class FormatMetadata {
                                case 'SceneType':
                                        switch ( $val ) {
                                        case 1:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -374,7 +412,7 @@ class FormatMetadata {
                                case 'CustomRendered':
                                        switch ( $val ) {
                                        case 0: case 1:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -385,7 +423,7 @@ class FormatMetadata {
                                case 'ExposureMode':
                                        switch ( $val ) {
                                        case 0: case 1: case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -396,7 +434,7 @@ class FormatMetadata {
                                case 'WhiteBalance':
                                        switch ( $val ) {
                                        case 0: case 1:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -407,7 +445,7 @@ class FormatMetadata {
                                case 'SceneCaptureType':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -418,7 +456,7 @@ class FormatMetadata {
                                case 'GainControl':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3: case 4:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -429,7 +467,7 @@ class FormatMetadata {
                                case 'Contrast':
                                        switch ( $val ) {
                                        case 0: case 1: case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -440,7 +478,7 @@ class FormatMetadata {
                                case 'Saturation':
                                        switch ( $val ) {
                                        case 0: case 1: case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -451,7 +489,7 @@ class FormatMetadata {
                                case 'Sharpness':
                                        switch ( $val ) {
                                        case 0: case 1: case 2:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -462,7 +500,7 @@ class FormatMetadata {
                                case 'SubjectDistanceRange':
                                        switch ( $val ) {
                                        case 0: case 1: case 2: case 3:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -475,7 +513,7 @@ class FormatMetadata {
                                case 'GPSDestLatitudeRef':
                                        switch ( $val ) {
                                        case 'N': case 'S':
-                                               $val = self::msg( 'GPSLatitude', $val );
+                                               $val = $this->exifMsg( 'GPSLatitude', $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -487,7 +525,7 @@ class FormatMetadata {
                                case 'GPSDestLongitudeRef':
                                        switch ( $val ) {
                                        case 'E': case 'W':
-                                               $val = self::msg( 'GPSLongitude', $val );
+                                               $val = $this->exifMsg( 'GPSLongitude', $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -497,16 +535,16 @@ class FormatMetadata {
 
                                case 'GPSAltitude':
                                        if ( $val < 0 ) {
-                                               $val = self::msg( 'GPSAltitude', 'below-sealevel', self::formatNum( -$val, 3 ) );
+                                               $val = $this->exifMsg( 'GPSAltitude', 'below-sealevel', $this->formatNum( -$val, 3 ) );
                                        } else {
-                                               $val = self::msg( 'GPSAltitude', 'above-sealevel', self::formatNum( $val, 3 ) );
+                                               $val = $this->exifMsg( 'GPSAltitude', 'above-sealevel', $this->formatNum( $val, 3 ) );
                                        }
                                        break;
 
                                case 'GPSStatus':
                                        switch ( $val ) {
                                        case 'A': case 'V':
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -517,7 +555,7 @@ class FormatMetadata {
                                case 'GPSMeasureMode':
                                        switch ( $val ) {
                                        case 2: case 3:
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -530,7 +568,7 @@ class FormatMetadata {
                                case 'GPSDestBearingRef':
                                        switch ( $val ) {
                                        case 'T': case 'M':
-                                               $val = self::msg( 'GPSDirection', $val );
+                                               $val = $this->exifMsg( 'GPSDirection', $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -540,17 +578,17 @@ class FormatMetadata {
 
                                case 'GPSLatitude':
                                case 'GPSDestLatitude':
-                                       $val = self::formatCoords( $val, 'latitude' );
+                                       $val = $this->formatCoords( $val, 'latitude' );
                                        break;
                                case 'GPSLongitude':
                                case 'GPSDestLongitude':
-                                       $val = self::formatCoords( $val, 'longitude' );
+                                       $val = $this->formatCoords( $val, 'longitude' );
                                        break;
 
                                case 'GPSSpeedRef':
                                        switch ( $val ) {
                                        case 'K': case 'M': case 'N':
-                                               $val = self::msg( 'GPSSpeed', $val );
+                                               $val = $this->exifMsg( 'GPSSpeed', $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -561,7 +599,7 @@ class FormatMetadata {
                                case 'GPSDestDistanceRef':
                                        switch ( $val ) {
                                        case 'K': case 'M': case 'N':
-                                               $val = self::msg( 'GPSDestDistance', $val );
+                                               $val = $this->exifMsg( 'GPSDestDistance', $val );
                                                break;
                                        default:
                                                /* If not recognized, display as is. */
@@ -572,15 +610,15 @@ class FormatMetadata {
                                case 'GPSDOP':
                                        // See http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
                                        if ( $val <= 2 ) {
-                                               $val = self::msg( $tag, 'excellent', self::formatNum( $val ) );
+                                               $val = $this->exifMsg( $tag, 'excellent', $this->formatNum( $val ) );
                                        } elseif ( $val <= 5 ) {
-                                               $val = self::msg( $tag, 'good', self::formatNum( $val ) );
+                                               $val = $this->exifMsg( $tag, 'good', $this->formatNum( $val ) );
                                        } elseif ( $val <= 10 ) {
-                                               $val = self::msg( $tag, 'moderate', self::formatNum( $val ) );
+                                               $val = $this->exifMsg( $tag, 'moderate', $this->formatNum( $val ) );
                                        } elseif ( $val <= 20 ) {
-                                               $val = self::msg( $tag, 'fair', self::formatNum( $val ) );
+                                               $val = $this->exifMsg( $tag, 'fair', $this->formatNum( $val ) );
                                        } else {
-                                               $val = self::msg( $tag, 'poor', self::formatNum( $val ) );
+                                               $val = $this->exifMsg( $tag, 'poor', $this->formatNum( $val ) );
                                        }
                                        break;
 
@@ -589,41 +627,41 @@ class FormatMetadata {
                                // the make, model and software name to link to their articles.
                                case 'Make':
                                case 'Model':
-                                       $val = self::msg( $tag, '', $val );
+                                       $val = $this->exifMsg( $tag, '', $val );
                                        break;
 
                                case 'Software':
                                        if ( is_array( $val ) ) {
                                                //if its a software, version array.
-                                               $val = wfMessage( 'exif-software-version-value', $val[0], $val[1] )->text();
+                                               $val = $this->msg( 'exif-software-version-value', $val[0], $val[1] )->text();
                                        } else {
-                                               $val = self::msg( $tag, '', $val );
+                                               $val = $this->exifMsg( $tag, '', $val );
                                        }
                                        break;
 
                                case 'ExposureTime':
                                        // Show the pretty fraction as well as decimal version
-                                       $val = wfMessage( 'exif-exposuretime-format',
-                                               self::formatFraction( $val ), self::formatNum( $val ) )->text();
+                                       $val = $this->msg( 'exif-exposuretime-format',
+                                               $this->formatFraction( $val ), $this->formatNum( $val ) )->text();
                                        break;
                                case 'ISOSpeedRatings':
                                        // If its = 65535 that means its at the
                                        // limit of the size of Exif::short and
                                        // is really higher.
                                        if ( $val == '65535' ) {
-                                               $val = self::msg( $tag, 'overflow' );
+                                               $val = $this->exifMsg( $tag, 'overflow' );
                                        } else {
-                                               $val = self::formatNum( $val );
+                                               $val = $this->formatNum( $val );
                                        }
                                        break;
                                case 'FNumber':
-                                       $val = wfMessage( 'exif-fnumber-format',
-                                               self::formatNum( $val ) )->text();
+                                       $val = $this->msg( 'exif-fnumber-format',
+                                               $this->formatNum( $val ) )->text();
                                        break;
 
                                case 'FocalLength': case 'FocalLengthIn35mmFilm':
-                                       $val = wfMessage( 'exif-focallength-format',
-                                               self::formatNum( $val ) )->text();
+                                       $val = $this->msg( 'exif-focallength-format',
+                                               $this->formatNum( $val ) )->text();
                                        break;
 
                                case 'MaxApertureValue':
@@ -637,9 +675,9 @@ class FormatMetadata {
                                        if ( is_numeric( $val ) ) {
                                                $fNumber = pow( 2, $val / 2 );
                                                if ( $fNumber !== false ) {
-                                                       $val = wfMessage( 'exif-maxaperturevalue-value',
-                                                               self::formatNum( $val ),
-                                                               self::formatNum( $fNumber, 2 )
+                                                       $val = $this->msg( 'exif-maxaperturevalue-value',
+                                                               $this->formatNum( $val ),
+                                                               $this->formatNum( $fNumber, 2 )
                                                        )->text();
                                                }
                                        }
@@ -658,7 +696,7 @@ class FormatMetadata {
                                                case 'sci': case 'soi':
                                                case 'spo': case 'war':
                                                case 'wea':
-                                                       $val = self::msg(
+                                                       $val = $this->exifMsg(
                                                                'iimcategory',
                                                                $val
                                                        );
@@ -670,7 +708,7 @@ class FormatMetadata {
                                        // classification. We decode the
                                        // first 2 digits, which provide
                                        // a broad category.
-                                       $val = self::convertNewsCode( $val );
+                                       $val = $this->convertNewsCode( $val );
                                        break;
                                case 'Urgency':
                                        // 1-8 with 1 being highest, 5 normal
@@ -687,7 +725,7 @@ class FormatMetadata {
                                        }
 
                                        if ( $urgency !== '' ) {
-                                               $val = self::msg( 'urgency',
+                                               $val = $this->exifMsg( 'urgency',
                                                        $urgency, $val
                                                );
                                        }
@@ -700,7 +738,7 @@ class FormatMetadata {
                                case 'PixelYDimension':
                                case 'ImageWidth':
                                case 'ImageLength':
-                                       $val = self::formatNum( $val ) . ' ' . wfMessage( 'unit-pixel' )->text();
+                                       $val = $this->formatNum( $val ) . ' ' . $this->msg( 'unit-pixel' )->text();
                                        break;
 
                                // Do not transform fields with pure text.
@@ -783,7 +821,7 @@ class FormatMetadata {
                                case 'ObjectCycle':
                                        switch ( $val ) {
                                        case 'a': case 'p': case 'b':
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        default:
                                                $val = htmlspecialchars( $val );
@@ -793,20 +831,20 @@ class FormatMetadata {
                                case 'Copyrighted':
                                        switch ( $val ) {
                                        case 'True': case 'False':
-                                               $val = self::msg( $tag, $val );
+                                               $val = $this->exifMsg( $tag, $val );
                                                break;
                                        }
                                        break;
                                case 'Rating':
                                        if ( $val == '-1' ) {
-                                               $val = self::msg( $tag, 'rejected' );
+                                               $val = $this->exifMsg( $tag, 'rejected' );
                                        } else {
-                                               $val = self::formatNum( $val );
+                                               $val = $this->formatNum( $val );
                                        }
                                        break;
 
                                case 'LanguageCode':
-                                       $lang = Language::fetchLanguageName( strtolower( $val ), $wgLang->getCode() );
+                                       $lang = Language::fetchLanguageName( strtolower( $val ), $this->getLanguage()->getCode() );
                                        if ( $lang ) {
                                                $val = htmlspecialchars( $lang );
                                        } else {
@@ -815,17 +853,64 @@ class FormatMetadata {
                                        break;
 
                                default:
-                                       $val = self::formatNum( $val );
+                                       $val = $this->formatNum( $val );
                                        break;
                                }
                        }
                        // End formatting values, start flattening arrays.
-                       $vals = self::flattenArray( $vals, $type );
+                       $vals = $this->flattenArrayReal( $vals, $type );
 
                }
                return $tags;
        }
 
+       /**
+        * Flatten an array, using the content language for any messages.
+        *
+        * @param array $vals array of values
+        * @param string $type Type of array (either lang, ul, ol).
+        *     lang = language assoc array with keys being the lang code
+        *     ul = unordered list, ol = ordered list
+        *     type can also come from the '_type' member of $vals.
+        * @param $noHtml Boolean If to avoid returning anything resembling
+        *     html. (Ugly hack for backwards compatibility with old mediawiki).
+        * @param IContextSource $context
+        * @return String single value (in wiki-syntax).
+        * @since 1.23
+        */
+       public static function flattenArrayContentLang( $vals, $type = 'ul', $noHtml = false, $context = false ) {
+               global $wgContLang;
+               $obj = new FormatMetadata;
+               if ( $context ) {
+                       $obj->setContext( $context );
+               }
+               $context = new DerivativeContext( $obj->getContext() );
+               $context->setLanguage( $wgContLang );
+               $obj->setContext( $context );
+               return $obj->flattenArrayReal( $vals, $type, $noHtml );
+       }
+
+       /**
+        * Flatten an array, using the user language for any messages.
+        *
+        * @param array $vals array of values
+        * @param string $type Type of array (either lang, ul, ol).
+        *     lang = language assoc array with keys being the lang code
+        *     ul = unordered list, ol = ordered list
+        *     type can also come from the '_type' member of $vals.
+        * @param $noHtml Boolean If to avoid returning anything resembling
+        *     html. (Ugly hack for backwards compatibility with old mediawiki).
+        * @param IContextSource $context
+        * @return String single value (in wiki-syntax).
+        */
+       public static function flattenArray( $vals, $type = 'ul', $noHtml = false, $context = false ) {
+               $obj = new FormatMetadata;
+               if ( $context ) {
+                       $obj->setContext( $context );
+               }
+               return $obj->flattenArrayReal( $vals, $type, $noHtml );
+       }
+
        /**
         * A function to collapse multivalued tags into a single value.
         * This turns an array of (for example) authors into a bulleted list.
@@ -834,14 +919,19 @@ class FormatMetadata {
         *
         * @param array $vals array of values
         * @param string $type Type of array (either lang, ul, ol).
-        * lang = language assoc array with keys being the lang code
-        * ul = unordered list, ol = ordered list
-        * type can also come from the '_type' member of $vals.
+        *     lang = language assoc array with keys being the lang code
+        *     ul = unordered list, ol = ordered list
+        *     type can also come from the '_type' member of $vals.
         * @param $noHtml Boolean If to avoid returning anything resembling
-        * html. (Ugly hack for backwards compatibility with old mediawiki).
+        *     html. (Ugly hack for backwards compatibility with old mediawiki).
         * @return String single value (in wiki-syntax).
+        * @since 1.23
         */
-       public static function flattenArray( $vals, $type = 'ul', $noHtml = false ) {
+       public function flattenArrayReal( $vals, $type = 'ul', $noHtml = false ) {
+               if ( !is_array( $vals ) ) {
+                       return $vals; // do nothing if not an array;
+               }
+
                if ( isset( $vals['_type'] ) ) {
                        $type = $vals['_type'];
                        unset( $vals['_type'] );
@@ -862,7 +952,6 @@ class FormatMetadata {
                 * languages, we don't want to show them all by default
                 */
                else {
-                       global $wgContLang;
                        switch ( $type ) {
                        case 'lang':
                                // Display default, followed by ContLang,
@@ -873,7 +962,7 @@ class FormatMetadata {
 
                                $content = '';
 
-                               $cLang = $wgContLang->getCode();
+                               $priorityLanguages = $this->getPriorityLanguages();
                                $defaultItem = false;
                                $defaultLang = false;
 
@@ -888,18 +977,24 @@ class FormatMetadata {
                                        $defaultItem = $vals['x-default'];
                                        unset( $vals['x-default'] );
                                }
-                               // Do contentLanguage.
-                               if ( isset( $vals[$cLang] ) ) {
-                                       $isDefault = false;
-                                       if ( $vals[$cLang] === $defaultItem ) {
-                                               $defaultItem = false;
-                                               $isDefault = true;
-                                       }
-                                       $content .= self::langItem(
-                                               $vals[$cLang], $cLang,
-                                               $isDefault, $noHtml );
+                               foreach ( $priorityLanguages as $pLang ) {
+                                       if ( isset( $vals[$pLang] ) ) {
+                                               $isDefault = false;
+                                               if ( $vals[$pLang] === $defaultItem ) {
+                                                       $defaultItem = false;
+                                                       $isDefault = true;
+                                               }
+                                               $content .= $this->langItem(
+                                                       $vals[$pLang], $pLang,
+                                                       $isDefault, $noHtml );
+
+                                               unset( $vals[$pLang] );
 
-                                       unset( $vals[$cLang] );
+                                               if ( $this->singleLang ) {
+                                                       return Html::rawElement( 'span',
+                                                               array( 'lang' => $pLang ), $vals[$pLang] );
+                                               }
+                                       }
                                }
 
                                // Now do the rest.
@@ -908,13 +1003,20 @@ class FormatMetadata {
                                                $defaultLang = $lang;
                                                continue;
                                        }
-                                       $content .= self::langItem( $item,
+                                       $content .= $this->langItem( $item,
                                                $lang, false, $noHtml );
+                                       if ( $this->singleLang ) {
+                                               return Html::rawElement( 'span',
+                                                       array( 'lang' => $lang ), $item );
+                                       }
                                }
                                if ( $defaultItem !== false ) {
-                                       $content = self::langItem( $defaultItem,
+                                       $content = $this->langItem( $defaultItem,
                                                $defaultLang, true, $noHtml ) .
                                                $content;
+                                       if ( $this->singleLang ) {
+                                               return $defaultItem;
+                                       }
                                }
                                if ( $noHtml ) {
                                        return $content;
@@ -947,7 +1049,7 @@ class FormatMetadata {
         * @return string language item (Note: despite how this looks,
         * this is treated as wikitext not html).
         */
-       private static function langItem( $value, $lang, $default = false, $noHtml = false ) {
+       private function langItem( $value, $lang, $default = false, $noHtml = false ) {
                if ( $lang === false && $default === false ) {
                        throw new MWException( '$lang and $default cannot both '
                                . 'be false.' );
@@ -961,13 +1063,12 @@ class FormatMetadata {
                }
 
                if ( $lang === false ) {
+                       $msg = $this->msg( 'metadata-langitem-default', $wrappedValue );
                        if ( $noHtml ) {
-                               return wfMessage( 'metadata-langitem-default',
-                                       $wrappedValue )->text() . "\n\n";
+                               return $msg->text() . "\n\n";
                        } /* else */
                        return '<li class="mw-metadata-lang-default">'
-                               . wfMessage( 'metadata-langitem-default',
-                                       $wrappedValue )->text()
+                               . $msg->text()
                                . "</li>\n";
                }
 
@@ -984,9 +1085,9 @@ class FormatMetadata {
                }
                // else we have a language specified
 
+               $msg = $this->msg( 'metadata-langitem', $wrappedValue, $langName, $lang );
                if ( $noHtml ) {
-                       return '*' . wfMessage( 'metadata-langitem',
-                               $wrappedValue, $langName, $lang )->text();
+                       return '*' . $msg->text();
                } /* else: */
 
                $item = '<li class="mw-metadata-lang-code-'
@@ -995,8 +1096,7 @@ class FormatMetadata {
                        $item .= ' mw-metadata-lang-default';
                }
                $item .= '" lang="' . $lang . '">';
-               $item .= wfMessage( 'metadata-langitem',
-                       $wrappedValue, $langName, $lang )->text();
+               $item .= $msg->text();
                $item .= "</li>\n";
                return $item;
        }
@@ -1010,15 +1110,15 @@ class FormatMetadata {
         * @param string $val the value of the tag
         * @param string $arg an argument to pass ($1)
         * @param string $arg2 a 2nd argument to pass ($2)
-        * @return string A wfMessage of "exif-$tag-$val" in lower case
+        * @return string The text content of "exif-$tag-$val" message in lower case
         */
-       static function msg( $tag, $val, $arg = null, $arg2 = null ) {
+       private function exifMsg( $tag, $val, $arg = null, $arg2 = null ) {
                global $wgContLang;
 
                if ( $val === '' ) {
                        $val = 'value';
                }
-               return wfMessage( $wgContLang->lc( "exif-$tag-$val" ), $arg, $arg2 )->text();
+               return $this->msg( $wgContLang->lc( "exif-$tag-$val" ), $arg, $arg2 )->text();
        }
 
        /**
@@ -1029,15 +1129,14 @@ class FormatMetadata {
         * @param $round float|int|bool digits to round to or false.
         * @return mixed A floating point number or whatever we were fed
         */
-       static function formatNum( $num, $round = false ) {
-               global $wgLang;
+       private function formatNum( $num, $round = false ) {
                $m = array();
                if ( is_array( $num ) ) {
                        $out = array();
                        foreach ( $num as $number ) {
-                               $out[] = self::formatNum( $number );
+                               $out[] = $this->formatNum( $number );
                        }
-                       return $wgLang->commaList( $out );
+                       return $this->getLanguage()->commaList( $out );
                }
                if ( preg_match( '/^(-?\d+)\/(\d+)$/', $num, $m ) ) {
                        if ( $m[2] != 0 ) {
@@ -1049,12 +1148,12 @@ class FormatMetadata {
                                $newNum = $num;
                        }
 
-                       return $wgLang->formatNum( $newNum );
+                       return $this->getLanguage()->formatNum( $newNum );
                } else {
                        if ( is_numeric( $num ) && $round !== false ) {
                                $num = round( $num, $round );
                        }
-                       return $wgLang->formatNum( $num );
+                       return $this->getLanguage()->formatNum( $num );
                }
        }
 
@@ -1066,18 +1165,18 @@ class FormatMetadata {
         * @param $num Mixed: the value to format
         * @return mixed A floating point number or whatever we were fed
         */
-       static function formatFraction( $num ) {
+       private function formatFraction( $num ) {
                $m = array();
                if ( preg_match( '/^(-?\d+)\/(\d+)$/', $num, $m ) ) {
                        $numerator = intval( $m[1] );
                        $denominator = intval( $m[2] );
-                       $gcd = self::gcd( abs( $numerator ), $denominator );
+                       $gcd = $this->gcd( abs( $numerator ), $denominator );
                        if ( $gcd != 0 ) {
                                // 0 shouldn't happen! ;)
-                               return self::formatNum( $numerator / $gcd ) . '/' . self::formatNum( $denominator / $gcd );
+                               return $this->formatNum( $numerator / $gcd ) . '/' . $this->formatNum( $denominator / $gcd );
                        }
                }
-               return self::formatNum( $num );
+               return $this->formatNum( $num );
        }
 
        /**
@@ -1088,7 +1187,7 @@ class FormatMetadata {
         * @return int
         * @private
         */
-       static function gcd( $a, $b ) {
+       private function gcd( $a, $b ) {
                /*
                        // http://en.wikipedia.org/wiki/Euclidean_algorithm
                        // Recursive form would be:
@@ -1119,7 +1218,7 @@ class FormatMetadata {
         * @param string $val The 8 digit news code.
         * @return string The human readable form
         */
-       private static function convertNewsCode( $val ) {
+       private function convertNewsCode( $val ) {
                if ( !preg_match( '/^\d{8}$/D', $val ) ) {
                        // Not a valid news code.
                        return $val;
@@ -1179,8 +1278,8 @@ class FormatMetadata {
                                break;
                }
                if ( $cat !== '' ) {
-                       $catMsg = self::msg( 'iimcategory', $cat );
-                       $val = self::msg( 'subjectnewscode', '', $val, $catMsg );
+                       $catMsg = $this->exifMsg( 'iimcategory', $cat );
+                       $val = $this->exifMsg( 'subjectnewscode', '', $val, $catMsg );
                }
                return $val;
        }
@@ -1193,7 +1292,7 @@ class FormatMetadata {
         * @param string $type latitude or longitude (for if its a NWS or E)
         * @return mixed A floating point number or whatever we were fed
         */
-       static function formatCoords( $coord, $type ) {
+       private function formatCoords( $coord, $type ) {
                $ref = '';
                if ( $coord < 0 ) {
                        $nCoord = -$coord;
@@ -1215,11 +1314,11 @@ class FormatMetadata {
                $min = floor( ( $nCoord - $deg ) * 60.0 );
                $sec = round( ( ( $nCoord - $deg ) - $min / 60 ) * 3600, 2 );
 
-               $deg = self::formatNum( $deg );
-               $min = self::formatNum( $min );
-               $sec = self::formatNum( $sec );
+               $deg = $this->formatNum( $deg );
+               $min = $this->formatNum( $min );
+               $sec = $this->formatNum( $sec );
 
-               return wfMessage( 'exif-coordinate-format', $deg, $min, $sec, $ref, $coord )->text();
+               return $this->msg( 'exif-coordinate-format', $deg, $min, $sec, $ref, $coord )->text();
        }
 
        /**
@@ -1235,8 +1334,9 @@ class FormatMetadata {
         * public.
         *
         * @return String of html-ish looking wikitext
+        * @since 1.23 no longer static
         */
-       public static function collapseContactInfo( $vals ) {
+       public function collapseContactInfo( $vals ) {
                if ( !( isset( $vals['CiAdrExtadr'] )
                        || isset( $vals['CiAdrCity'] )
                        || isset( $vals['CiAdrCtry'] )
@@ -1258,7 +1358,7 @@ class FormatMetadata {
                        foreach ( $vals as &$val ) {
                                $val = htmlspecialchars( $val );
                        }
-                       return self::flattenArray( $vals );
+                       return $this->flattenArrayReal( $vals );
                } else {
                        // We have a real ContactInfo field.
                        // Its unclear if all these fields have to be
@@ -1340,11 +1440,302 @@ class FormatMetadata {
                                        . htmlspecialchars( $vals['CiUrlWork'] )
                                        . '</span>';
                        }
-                       return wfMessage( 'exif-contact-value', $email, $url,
+                       return $this->msg( 'exif-contact-value', $email, $url,
                                $street, $city, $region, $postal, $country,
                                $tel )->text();
                }
        }
+
+       /**
+        * Get a list of fields that are visible by default.
+        *
+        * @return array
+        * @since 1.23
+        */
+       public static function getVisibleFields() {
+               $fields = array();
+               $lines = explode( "\n", wfMessage( 'metadata-fields' )->inContentLanguage()->text() );
+               foreach ( $lines as $line ) {
+                       $matches = array();
+                       if ( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) {
+                               $fields[] = $matches[1];
+                       }
+               }
+               $fields = array_map( 'strtolower', $fields );
+               return $fields;
+       }
+
+       /**
+        * Get an array of extended metadata. (See the imageinfo API for format.)
+        *
+        * @param File $file File to use
+        * @return array [<property name> => ['value' => <value>]], or [] on error
+        * @since 1.23
+        */
+       public function fetchExtendedMetadata( File $file ) {
+               global $wgMemc;
+
+               wfProfileIn( __METHOD__ );
+
+               // If revision deleted, exit immediately
+               if ( $file->isDeleted( File::DELETED_FILE ) ) {
+                       wfProfileOut( __METHOD__ );
+                       return array();
+               }
+
+               $cacheKey = wfMemcKey(
+                       'getExtendedMetadata',
+                       $this->getLanguage()->getCode(),
+                       (int) $this->singleLang,
+                       $file->getSha1()
+               );
+
+               $cachedValue = $wgMemc->get( $cacheKey );
+               if (
+                       $cachedValue
+                       && wfRunHooks( 'ValidateExtendedMetadataCache', array( $cachedValue['timestamp'], $file ) )
+               ) {
+                       $extendedMetadata = $cachedValue['data'];
+               } else {
+                       $maxCacheTime = ( $file instanceof ForeignAPIFile ) ? 60 * 60 * 12 : 60 * 60 * 24 * 30;
+                       $fileMetadata = $this->getExtendedMetadataFromFile( $file );
+                       $extendedMetadata = $this->getExtendedMetadataFromHook( $file, $fileMetadata, $maxCacheTime );
+                       if ( $this->singleLang ) {
+                               $this->resolveMultilangMetadata( $extendedMetadata );
+                       }
+                       // Make sure the metadata won't break the API when an XML format is used.
+                       // This is an API-specific function so it would be cleaner to call it from
+                       // outside fetchExtendedMetadata, but this way we don't need to redo the
+                       // computation on a cache hit.
+                       $this->sanitizeArrayForXml( $extendedMetadata );
+                       $valueToCache = array( 'data' => $extendedMetadata, 'timestamp' => wfTimestampNow() );
+                       $wgMemc->set( $cacheKey, $valueToCache, $maxCacheTime );
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $extendedMetadata;
+       }
+
+       /**
+        * Get file-based metadata in standardized format.
+        *
+        * Note that for a remote file, this might return metadata supplied by extensions.
+        *
+        * @param File $file File to use
+        * @return array [<property name> => ['value' => <value>]], or [] on error
+        * @since 1.23
+        */
+       protected function getExtendedMetadataFromFile( File $file ) {
+               // If this is a remote file accessed via an API request, we already
+               // have remote metadata so we just ignore any local one
+               if ( $file instanceof ForeignAPIFile ) {
+                       // in case of error we pretend no metadata - this will get cached. Might or might not be a good idea.
+                       return $file->getExtendedMetadata() ?: array();
+               }
+
+               wfProfileIn( __METHOD__ );
+
+               $uploadDate = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
+
+               $fileMetadata = array(
+                       // This is modification time, which is close to "upload" time.
+                       'DateTime' => array(
+                               'value' => $uploadDate,
+                               'source' => 'mediawiki-metadata',
+                       ),
+               );
+
+               $title = $file->getTitle();
+               if ( $title ) {
+                       $text = $title->getText();
+                       $pos = strrpos( $text, '.' );
+
+                       if ( $pos ) {
+                               $name = substr( $text, 0, $pos );
+                       } else {
+                               $name = $text;
+                       }
+
+                       $fileMetadata[ 'ObjectName' ] = array(
+                               'value' => $name,
+                               'source' => 'mediawiki-metadata',
+                       );
+               }
+
+               $common = $file->getCommonMetaArray();
+
+               if ( $common !== false ) {
+                       foreach ( $common as $key => $value ) {
+                               $fileMetadata[$key] = array(
+                                       'value' => $value,
+                                       'source' => 'file-metadata',
+                               );
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $fileMetadata;
+       }
+
+       /**
+        * Get additional metadata from hooks in standardized format.
+        *
+        * @param File $file File to use
+        * @param array $extendedMetadata
+        * @param int $maxCacheTime hook handlers might use this parameter to override cache time
+        *
+        * @return array [<property name> => ['value' => <value>]], or [] on error
+        * @since 1.23
+        */
+       protected function getExtendedMetadataFromHook( File $file, array $extendedMetadata, &$maxCacheTime ) {
+               wfProfileIn( __METHOD__ );
+
+               wfRunHooks( 'GetExtendedMetadata', array(
+                       &$extendedMetadata,
+                       $file,
+                       $this->getContext(),
+                       $this->singleLang,
+                       &$maxCacheTime
+               ) );
+
+               $visible = array_flip( self::getVisibleFields() );
+               foreach ( $extendedMetadata as $key => $value ) {
+                       if ( !isset( $visible[ strtolower( $key ) ] ) ) {
+                               $extendedMetadata[$key]['hidden'] = '';
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $extendedMetadata;
+       }
+
+       /**
+        * Turns an XMP-style multilang array into a single value.
+        * If the value is not a multilang array, it is returned unchanged.
+        * See mediawiki.org/wiki/Manual:File_metadata_handling#Multi-language_array_format
+        * @param mixed $value
+        * @return mixed value in best language, null if there were no languages at all
+        * @since 1.23
+        */
+       protected function resolveMultilangValue( $value ) {
+               if (
+                       !is_array( $value )
+                       || !isset( $value['_type'] )
+                       || $value['_type'] != 'lang'
+               ) {
+                       return $value; // do nothing if not a multilang array
+               }
+
+               // choose the language best matching user or site settings
+               $priorityLanguages = $this->getPriorityLanguages();
+               foreach ( $priorityLanguages as $lang ) {
+                       if ( isset( $value[$lang] ) ) {
+                               return $value[$lang];
+                       }
+               }
+
+               // otherwise go with the default language, if set
+               if ( isset( $value['x-default'] ) ) {
+                       return $value['x-default'];
+               }
+
+               // otherwise just return any one language
+               unset( $value['_type'] );
+               if ( !empty( $value ) ) {
+                       return reset( $value );
+               }
+
+               // this should not happen; signal error
+               return null;
+       }
+
+       /**
+        * Takes an array returned by the getExtendedMetadata* functions,
+        * and resolves multi-language values in it.
+        * @param array $metadata
+        * @since 1.23
+        */
+       protected function resolveMultilangMetadata( &$metadata ) {
+               if ( !is_array( $metadata ) ) {
+                       return;
+               }
+               foreach ( $metadata as &$field ) {
+                       if ( isset( $field['value'] ) ) {
+                               $field['value'] = $this->resolveMultilangValue( $field['value'] );
+                       }
+               }
+       }
+
+       /**
+        * Makes sure the given array is a valid API response fragment
+        * (can be transformed into XML)
+        * @param array $arr
+        */
+       protected function sanitizeArrayForXml( &$arr ) {
+               if ( !is_array( $arr ) ) {
+                       return;
+               }
+
+               $counter = 1;
+               foreach ( $arr as $key => &$value ) {
+                       $sanitizedKey = $this->sanitizeKeyForXml( $key );
+                       if ( $sanitizedKey !== $key ) {
+                               if ( isset( $arr[$sanitizedKey] ) ) {
+                                       // Make the sanitized keys hopefully unique.
+                                       // To make it definitely unique would be too much effort, given that
+                                       // sanitizing is only needed for misformatted metadata anyway, but
+                                       // this at least covers the case when $arr is numeric.
+                                       $sanitizedKey .= $counter;
+                                       ++$counter;
+                               }
+                               $arr[$sanitizedKey] = $arr[$key];
+                               unset( $arr[$key] );
+                       }
+                       if ( is_array( $value ) ) {
+                               $this->sanitizeArrayForXml( $value );
+                       }
+               }
+       }
+
+       /**
+        * Turns a string into a valid XML identifier.
+        * Used to ensure that keys of an associative array in the
+        * API response do not break the XML formatter.
+        * @param string $key
+        * @return string
+        * @since 1.23
+        */
+       protected function sanitizeKeyForXml( $key ) {
+               // drop all characters which are not valid in an XML tag name
+               // a bunch of non-ASCII letters would be valid but probably won't
+               // be used so we take the easy way
+               $key = preg_replace( '/[^a-zA-z0-9_:.-]/', '', $key );
+               // drop characters which are invalid at the first position
+               $key = preg_replace( '/^[\d-.]+/', '', $key );
+
+               if ( $key == '' ) {
+                       $key = '_';
+               }
+
+               // special case for an internal keyword
+               if ( $key == '_element' ) {
+                       $key = 'element';
+               }
+
+               return $key;
+       }
+
+       /**
+        * Returns a list of languages (first is best) to use when formatting multilang fields,
+        * based on user and site preferences.
+        * @return array
+        * @since 1.23
+        */
+       protected function getPriorityLanguages() {
+               $priorityLanguages = Language::getFallbacksIncludingSiteLanguage( $this->getLanguage()->getCode() );
+               $priorityLanguages = array_merge( (array) $this->getLanguage()->getCode(), $priorityLanguages[0], $priorityLanguages[1] );
+               return $priorityLanguages;
+       }
 }
 
 /** For compatability with old FormatExif class
index 608fb25..19635da 100644 (file)
@@ -47,20 +47,31 @@ class GIFHandler extends BitmapHandler {
         * @return array|bool
         */
        function formatMetadata( $image ) {
+               $meta = $this->getCommonMetaArray( $image );
+               if ( count( $meta ) === 0 ) {
+                       return false;
+               }
+
+               return $this->formatMetadataHelper( $meta );
+       }
+
+       /**
+        * Return the standard metadata elements for #filemetadata parser func.
+        * @param File $image
+        * @return array|bool
+        */
+       public function getCommonMetaArray( File $image ) {
                $meta = $image->getMetadata();
 
                if ( !$meta ) {
-                       return false;
+                       return array();
                }
                $meta = unserialize( $meta );
-               if ( !isset( $meta['metadata'] ) || count( $meta['metadata'] ) <= 1 ) {
-                       return false;
-               }
-
-               if ( isset( $meta['metadata']['_MW_GIF_VERSION'] ) ) {
-                       unset( $meta['metadata']['_MW_GIF_VERSION'] );
+               if ( !isset( $meta['metadata'] ) ) {
+                       return array();
                }
-               return $this->formatMetadataHelper( $meta['metadata'] );
+               unset( $meta['metadata']['_MW_GIF_VERSION'] );
+               return $meta['metadata'];
        }
 
        /**
index 887afa3..77ec5a6 100644 (file)
@@ -163,8 +163,8 @@ class GIFMetadataExtractor {
 
                                        $commentCount = count( $comment );
                                        if ( $commentCount === 0
-                                               || $comment[$commentCount - 1] !== $data )
-                                       {
+                                               || $comment[$commentCount - 1] !== $data
+                                       {
                                                // Some applications repeat the same comment on each
                                                // frame of an animated GIF image, so if this comment
                                                // is identical to the last, only extract once.
@@ -217,8 +217,8 @@ class GIFMetadataExtractor {
                                                $xmp = self::readBlock( $fh, true );
 
                                                if ( substr( $xmp, -257, 3 ) !== "\x01\xFF\xFE"
-                                                       || substr( $xmp, -4 ) !== "\x03\x02\x01\x00" )
-                                               {
+                                                       || substr( $xmp, -4 ) !== "\x03\x02\x01\x00"
+                                               {
                                                        // this is just a sanity check.
                                                        throw new Exception( "XMP does not have magic trailer!" );
                                                }
index 544dd21..d3af31b 100644 (file)
@@ -40,7 +40,7 @@ class IPTC {
         */
        static function parse( $rawData ) {
                $parsed = iptcparse( $rawData );
-               $data = Array();
+               $data = array();
                if ( !is_array( $parsed ) ) {
                                return $data;
                }
@@ -225,7 +225,7 @@ class IPTC {
                                        if ( isset( $parsed['2#060'] ) ) {
                                                $time = $parsed['2#060'];
                                        } else {
-                                               $time = Array();
+                                               $time = array();
                                        }
                                        $timestamp = self::timeHelper( $val, $time, $c );
                                        if ( $timestamp ) {
@@ -239,7 +239,7 @@ class IPTC {
                                        if ( isset( $parsed['2#063'] ) ) {
                                                $time = $parsed['2#063'];
                                        } else {
-                                               $time = Array();
+                                               $time = array();
                                        }
                                        $timestamp = self::timeHelper( $val, $time, $c );
                                        if ( $timestamp ) {
@@ -252,7 +252,7 @@ class IPTC {
                                        if ( isset( $parsed['2#035'] ) ) {
                                                $time = $parsed['2#035'];
                                        } else {
-                                               $time = Array();
+                                               $time = array();
                                        }
                                        $timestamp = self::timeHelper( $val, $time, $c );
                                        if ( $timestamp ) {
@@ -265,7 +265,7 @@ class IPTC {
                                        if ( isset( $parsed['2#038'] ) ) {
                                                $time = $parsed['2#038'];
                                        } else {
-                                               $time = Array();
+                                               $time = array();
                                        }
                                        $timestamp = self::timeHelper( $val, $time, $c );
                                        if ( $timestamp ) {
@@ -315,9 +315,7 @@ class IPTC {
                                        foreach ( $codes as $ic ) {
                                                $fields = explode( ':', $ic, 3 );
 
-                                               if ( count( $fields ) < 2 ||
-                                                       $fields[0] !== 'IPTC' )
-                                               {
+                                               if ( count( $fields ) < 2 || $fields[0] !== 'IPTC' ) {
                                                        wfDebugLog( 'IPTC', 'IPTC: '
                                                                . 'Invalid 2:12 - ' . $ic );
                                                        break;
index e079003..b6586d0 100644 (file)
@@ -213,7 +213,6 @@ abstract class ImageHandler extends MediaHandler {
                return $image->getWidth() * $image->getHeight();
        }
 
-
        /**
         * @param $file File
         * @return string
index 779e23c..56dcae0 100644 (file)
@@ -39,7 +39,7 @@ abstract class MediaHandler {
        /**
         * Get a MediaHandler for a given MIME type from the instance cache
         *
-        * @param $type string
+        * @param string $type
         *
         * @return MediaHandler
         */
@@ -70,7 +70,7 @@ abstract class MediaHandler {
         * Return true to accept the parameter, and false to reject it.
         * If you return false, the parser will do something quiet and forgiving.
         *
-        * @param $name
+        * @param string $name
         * @param $value
         */
        abstract function validateParam( $name, $value );
@@ -78,16 +78,16 @@ abstract class MediaHandler {
        /**
         * Merge a parameter array into a string appropriate for inclusion in filenames
         *
-        * @param $params array Array of parameters that have been through normaliseParams.
-        * @return String
+        * @param array $params Array of parameters that have been through normaliseParams.
+        * @return string
         */
        abstract function makeParamString( $params );
 
        /**
         * Parse a param string made with makeParamString back into an array
         *
-        * @param $str string The parameter string without file name (e.g. 122px)
-        * @return Array|Boolean Array of parameters or false on failure.
+        * @param string $str The parameter string without file name (e.g. 122px)
+        * @return array|bool Array of parameters or false on failure.
         */
        abstract function parseParamString( $str );
 
@@ -104,19 +104,19 @@ abstract class MediaHandler {
         * Get an image size array like that returned by getimagesize(), or false if it
         * can't be determined.
         *
-        * @param $image File: the image object, or false if there isn't one
+        * @param File $image The image object, or false if there isn't one
         * @param string $path the filename
-        * @return Array Follow the format of PHP getimagesize() internal function. See http://www.php.net/getimagesize
+        * @return array Follow the format of PHP getimagesize() internal function. See http://www.php.net/getimagesize
         */
        abstract function getImageSize( $image, $path );
 
        /**
         * Get handler-specific metadata which will be saved in the img_metadata field.
         *
-        * @param $image File: the image object, or false if there isn't one.
+        * @param File $image The image object, or false if there isn't one.
         *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
-        * @param string $path the filename
-        * @return String
+        * @param string $path The filename
+        * @return string
         */
        function getMetadata( $image, $path ) {
                return '';
@@ -135,11 +135,11 @@ abstract class MediaHandler {
         * version 3 it might add to the end of the array the element 'foo=3'. if the core metadata
         * version is 2, the end version string would look like '2;foo=3'.
         *
-        * @return string version string
+        * @return string Version string
         */
        static function getMetadataVersion() {
-               $version = Array( '2' ); // core metadata version
-               wfRunHooks( 'GetMetadataVersion', Array( &$version ) );
+               $version = array( '2' ); // core metadata version
+               wfRunHooks( 'GetMetadataVersion', array( &$version ) );
                return implode( ';', $version );
        }
 
@@ -149,9 +149,9 @@ abstract class MediaHandler {
         * By default just returns $metadata, but can be used to allow
         * media handlers to convert between metadata versions.
         *
-        * @param $metadata Mixed String or Array metadata array (serialized if string)
-        * @param $version Integer target version
-        * @return Array serialized metadata in specified version, or $metadata on fail.
+        * @param mixed|string|array $metadata Metadata array (serialized if string)
+        * @param int $version Target version
+        * @return array Serialized metadata in specified version, or $metadata on fail.
         */
        function convertMetadataVersion( $metadata, $version = 1 ) {
                if ( !is_array( $metadata ) ) {
@@ -167,7 +167,7 @@ abstract class MediaHandler {
 
        /**
         * Get a string describing the type of metadata, for display purposes.
-        *
+        * @param $image
         * @return string
         */
        function getMetadataType( $image ) {
@@ -187,6 +187,43 @@ abstract class MediaHandler {
                return self::METADATA_GOOD;
        }
 
+       /**
+        * Get an array of standard (FormatMetadata type) metadata values.
+        *
+        * The returned data is largely the same as that from getMetadata(),
+        * but formatted in a standard, stable, handler-independent way.
+        * The idea being that some values like ImageDescription or Artist
+        * are universal and should be retrievable in a handler generic way.
+        *
+        * The specific properties are the type of properties that can be
+        * handled by the FormatMetadata class. These values are exposed to the
+        * user via the filemetadata parser function.
+        *
+        * Details of the response format of this function can be found at
+        * https://www.mediawiki.org/wiki/Manual:File_metadata_handling
+        * tl/dr: the response is an associative array of
+        * properties keyed by name, but the value can be complex. You probably
+        * want to call one of the FormatMetadata::flatten* functions on the
+        * property values before using them, or call
+        * FormatMetadata::getFormattedData() on the full response array, which
+        * transforms all values into prettified, human-readable text.
+        *
+        * Subclasses overriding this function must return a value which is a
+        * valid API response fragment (all associative array keys are valid
+        * XML tagnames).
+        *
+        * Note, if the file simply has no metadata, but the handler supports
+        * this interface, it should return an empty array, not false.
+        *
+        * @param File $file
+        *
+        * @return array|bool False if interface not supported
+        * @since 1.23
+        */
+       public function getCommonMetaArray( File $file ) {
+               return false;
+       }
+
        /**
         * Get a MediaTransformOutput object representing an alternate of the transformed
         * output which will call an intermediary thumbnail assist script.
@@ -204,7 +241,7 @@ abstract class MediaHandler {
         * Get a MediaTransformOutput object representing the transformed output. Does not
         * actually do the transform.
         *
-        * @param $image File: the image object
+        * @param File $image The image object
         * @param string $dstPath filesystem destination path
         * @param string $dstUrl Destination URL to use in output HTML
         * @param array $params Arbitrary set of parameters validated by $this->validateParam()
@@ -218,12 +255,12 @@ abstract class MediaHandler {
         * Get a MediaTransformOutput object representing the transformed output. Does the
         * transform unless $flags contains self::TRANSFORM_LATER.
         *
-        * @param $image File: the image object
+        * @param File $image The image object
         * @param string $dstPath filesystem destination path
         * @param string $dstUrl destination URL to use in output HTML
         * @param array $params arbitrary set of parameters validated by $this->validateParam()
         *   Note: These parameters have *not* gone through $this->normaliseParams()
-        * @param $flags Integer: a bitfield, may contain self::TRANSFORM_LATER
+        * @param int $flags A bitfield, may contain self::TRANSFORM_LATER
         *
         * @return MediaTransformOutput
         */
@@ -232,9 +269,9 @@ abstract class MediaHandler {
        /**
         * Get the thumbnail extension and MIME type for a given source MIME type
         *
-        * @param String $ext Extension of original file
-        * @param String $mime Mime type of original file
-        * @param Array $params Handler specific rendering parameters
+        * @param string $ext Extension of original file
+        * @param string $mime Mime type of original file
+        * @param array $params Handler specific rendering parameters
         * @return array thumbnail extension and MIME type
         */
        function getThumbType( $ext, $mime, $params = null ) {
@@ -255,8 +292,8 @@ abstract class MediaHandler {
 
        /**
         * Get useful response headers for GET/HEAD requests for a file with the given metadata
-        * @param $metadata mixed Result of the getMetadata() function of this handler for a file
-        * @return Array
+        * @param mixed $metadata Result of the getMetadata() function of this handler for a file
+        * @return array
         */
        public function getStreamHeaders( $metadata ) {
                return array();
@@ -436,16 +473,7 @@ abstract class MediaHandler {
         * @access protected
         */
        function visibleMetadataFields() {
-               $fields = array();
-               $lines = explode( "\n", wfMessage( 'metadata-fields' )->inContentLanguage()->text() );
-               foreach ( $lines as $line ) {
-                       $matches = array();
-                       if ( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) {
-                               $fields[] = $matches[1];
-                       }
-               }
-               $fields = array_map( 'strtolower', $fields );
-               return $fields;
+               return FormatMetadata::getVisibleFields();
        }
 
        /**
index 98f1386..d2c17ef 100644 (file)
@@ -52,20 +52,32 @@ class PNGHandler extends BitmapHandler {
         * @return array|bool
         */
        function formatMetadata( $image ) {
+               $meta = $this->getCommonMetaArray( $image );
+               if ( count( $meta ) === 0 ) {
+                       return false;
+               }
+
+               return $this->formatMetadataHelper( $meta );
+       }
+
+       /**
+        * Get a file type independent array of metadata.
+        *
+        * @param $image File
+        * @return array The metadata array
+        */
+       public function getCommonMetaArray( File $image ) {
                $meta = $image->getMetadata();
 
                if ( !$meta ) {
-                       return false;
+                       return array();
                }
                $meta = unserialize( $meta );
-               if ( !isset( $meta['metadata'] ) || count( $meta['metadata'] ) <= 1 ) {
-                       return false;
-               }
-
-               if ( isset( $meta['metadata']['_MW_PNG_VERSION'] ) ) {
-                       unset( $meta['metadata']['_MW_PNG_VERSION'] );
+               if ( !isset( $meta['metadata'] ) ) {
+                       return array();
                }
-               return $this->formatMetadataHelper( $meta['metadata'] );
+               unset( $meta['metadata']['_MW_PNG_VERSION'] );
+               return $meta['metadata'];
        }
 
        /**
index 72a9696..d6f8483 100644 (file)
 class SvgHandler extends ImageHandler {
        const SVG_METADATA_VERSION = 2;
 
+       /**
+        * A list of metadata tags that can be converted
+        * to the commonly used exif tags. This allows messages
+        * to be reused, and consistent tag names for {{#formatmetadata:..}}
+        */
+       private static $metaConversion = array(
+               'originalwidth' => 'ImageWidth',
+               'originalheight' => 'ImageLength',
+               'description' => 'ImageDescription',
+               'title' => 'ObjectName',
+       );
+
        function isEnabled() {
                global $wgSVGConverters, $wgSVGConverter;
                if ( !isset( $wgSVGConverters[$wgSVGConverter] ) ) {
@@ -340,19 +352,11 @@ class SvgHandler extends ImageHandler {
                // Sort fields into visible and collapsed
                $visibleFields = $this->visibleMetadataFields();
 
-               // Rename fields to be compatible with exif, so that
-               // the labels for these fields work and reuse existing messages.
-               $conversion = array(
-                       'originalwidth' => 'imagewidth',
-                       'originalheight' => 'imagelength',
-                       'description' => 'imagedescription',
-                       'title' => 'objectname',
-               );
                $showMeta = false;
                foreach ( $metadata as $name => $value ) {
                        $tag = strtolower( $name );
-                       if ( isset( $conversion[$tag] ) ) {
-                               $tag = $conversion[$tag];
+                       if ( isset( self::$metaConversion[$tag] ) ) {
+                               $tag = strtolower( self::$metaConversion[$tag] );
                        } else {
                                // Do not output other metadata not in list
                                continue;
@@ -368,7 +372,6 @@ class SvgHandler extends ImageHandler {
                return $showMeta ? $result : false;
        }
 
-
        /**
         * @param string $name Parameter name
         * @param $string $value Parameter value
@@ -431,4 +434,29 @@ class SvgHandler extends ImageHandler {
                        'lang' => $params['lang'],
                );
        }
+
+       public function getCommonMetaArray( File $file ) {
+               $metadata = $file->getMetadata();
+               if ( !$metadata ) {
+                       return array();
+               }
+               $metadata = $this->unpackMetadata( $metadata );
+               if ( !$metadata || isset( $metadata['error'] ) ) {
+                       return array();
+               }
+               $stdMetadata = array();
+               foreach ( $metadata as $name => $value ) {
+                       $tag = strtolower( $name );
+                       if ( $tag === 'originalwidth' || $tag === 'originalheight' ) {
+                               // Skip these. In the exif metadata stuff, it is assumed these
+                               // are measured in px, which is not the case here.
+                               continue;
+                       }
+                       if ( isset( self::$metaConversion[$tag] ) ) {
+                               $tag = self::$metaConversion[$tag];
+                               $stdMetadata[$tag] = $value;
+                       }
+               }
+               return $stdMetadata;
+       }
 }
index 2e33bb9..831e043 100644 (file)
@@ -45,7 +45,7 @@ class SVGReader {
 
        private $reader = null;
        private $mDebug = false;
-       private $metadata = Array();
+       private $metadata = array();
 
        /**
         * Constructor
index e77d384..a80a0c8 100644 (file)
@@ -103,12 +103,12 @@ class XCFHandler extends BitmapHandler {
                #        (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
                try {
                        $header = wfUnpack(
-                                 "A9magic"     # A: space padded
-                               . "/a5version"  # a: zero padded
-                               . "/Nwidth"     # \
-                               . "/Nheight"    # N: unsigned long 32bit big endian
-                               . "/Nbase_type" # /
-                       , $binaryHeader
+                               "A9magic" .        # A: space padded
+                                       "/a5version" . # a: zero padded
+                                       "/Nwidth" .    # \
+                                       "/Nheight" .   # N: unsigned long 32bit big endian
+                                       "/Nbase_type", # /
+                               $binaryHeader
                        );
                } catch ( MWException $mwe ) {
                        return false;
index 7eb3d19..3517986 100644 (file)
@@ -155,7 +155,7 @@ class XMPReader {
 
                $data = $this->results;
 
-               wfRunHooks( 'XMPGetResults', Array( &$data ) );
+               wfRunHooks( 'XMPGetResults', array( &$data ) );
 
                if ( isset( $data['xmp-special']['AuthorsPosition'] )
                        && is_string( $data['xmp-special']['AuthorsPosition'] )
@@ -608,8 +608,8 @@ class XMPReader {
        function endElement( $parser, $elm ) {
                if ( $elm === ( self::NS_RDF . ' RDF' )
                        || $elm === 'adobe:ns:meta/ xmpmeta'
-                       || $elm === 'adobe:ns:meta/ xapmeta' )
-               {
+                       || $elm === 'adobe:ns:meta/ xapmeta'
+               {
                        // ignore these.
                        return;
                }
@@ -897,8 +897,8 @@ class XMPReader {
 
                        if ( isset( $this->items[$ns][$tag] ) ) {
                                if ( isset( $this->items[$ns][$this->ancestorStruct]['children'] )
-                                       && !isset( $this->items[$ns][$this->ancestorStruct]['children'][$tag] ) )
-                               {
+                                       && !isset( $this->items[$ns][$this->ancestorStruct]['children'][$tag] )
+                               {
                                        // This assumes that we don't have inter-namespace nesting
                                        // which we don't in all the properties we're interested in.
                                        throw new MWException( " <$tag> appeared nested in <" . $this->ancestorStruct
@@ -996,8 +996,8 @@ class XMPReader {
                        throw new MWException( __METHOD__ . " <rdf:li> expected but got $elm." );
                }
                if ( !isset( $attribs[self::NS_XML . ' lang'] )
-                       || !preg_match( '/^[-A-Za-z0-9]{2,}$/D', $attribs[self::NS_XML . ' lang'] ) )
-               {
+                       || !preg_match( '/^[-A-Za-z0-9]{2,}$/D', $attribs[self::NS_XML . ' lang'] )
+               {
                        throw new MWException( __METHOD__
                                . " <rdf:li> did not contain, or has invalid xml:lang attribute in lang alternative" );
                }
@@ -1026,8 +1026,8 @@ class XMPReader {
 
                if ( $elm === self::NS_RDF . ' RDF'
                        || $elm === 'adobe:ns:meta/ xmpmeta'
-                       || $elm === 'adobe:ns:meta/ xapmeta' )
-               {
+                       || $elm === 'adobe:ns:meta/ xapmeta'
+               {
                        /* ignore. */
                        return;
                } elseif ( $elm === self::NS_RDF . ' Description' ) {
@@ -1119,8 +1119,8 @@ class XMPReader {
 
                if ( isset( $attribs[self::NS_RDF . ' parseType'] )
                        && $attribs[self::NS_RDF . ' parseType'] === 'Resource'
-                       && $this->mode[0] === self::MODE_SIMPLE )
-               {
+                       && $this->mode[0] === self::MODE_SIMPLE
+               {
                        // this is equivalent to having an inner rdf:Description
                        $this->mode[0] = self::MODE_QDESC;
                }
index f0b2cb5..afc9ece 100644 (file)
@@ -35,7 +35,7 @@ class XMPInfo {
                if ( !self::$ranHooks ) {
                        // This is for if someone makes a custom metadata extension.
                        // For example, a medical wiki might want to decode DICOM xmp properties.
-                       wfRunHooks( 'XMPGetInfo', Array( &self::$items ) );
+                       wfRunHooks( 'XMPGetInfo', array( &self::$items ) );
                        self::$ranHooks = true; // Only want to do this once.
                }
                return self::$items;
index 5118366..ad913b1 100644 (file)
@@ -39,6 +39,7 @@ if( defined( 'PRETTY_UTF8' ) ) {
 } else {
        /**
         * @ignore
+        * @param string $string
         * @return string
         */
        function pretty( $string ) {
index e5f60b5..f0a9128 100644 (file)
@@ -1026,9 +1026,9 @@ class MWMemcached {
 
                $len = strlen( $val );
 
-               if ( $this->_have_zlib && $this->_compress_enable &&
-                       $this->_compress_threshold && $len >= $this->_compress_threshold )
-               {
+               if ( $this->_have_zlib && $this->_compress_enable
+                       && $this->_compress_threshold && $len >= $this->_compress_threshold
+               {
                        $c_val = gzcompress( $val, 9 );
                        $c_len = strlen( $c_val );
 
index 135e0e8..adcf762 100644 (file)
@@ -55,7 +55,7 @@ class RedisBagOStuff extends BagOStuff {
         *     flap, for example if it is in swap death.
         */
        function __construct( $params ) {
-               $redisConf = array( 'serializer' => 'php' );
+               $redisConf = array( 'serializer' => 'none' ); // manage that in this class
                foreach ( array( 'connectTimeout', 'persistent', 'password' ) as $opt ) {
                        if ( isset( $params[$opt] ) ) {
                                $redisConf[$opt] = $params[$opt];
@@ -72,38 +72,38 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function get( $key, &$casToken = null ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                try {
-                       $result = $conn->get( $key );
+                       $result = $this->unserialize( $conn->get( $key ) );
                } catch ( RedisException $e ) {
                        $result = false;
                        $this->handleException( $server, $conn, $e );
                }
                $casToken = $result;
+
                $this->logRequest( 'get', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
        public function set( $key, $value, $expiry = 0 ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                $expiry = $this->convertToRelative( $expiry );
                try {
-                       if ( !$expiry ) {
-                               // No expiry, that is very different from zero expiry in Redis
-                               $result = $conn->set( $key, $value );
+                       if ( $expiry ) {
+                               $result = $conn->setex( $key, $expiry, $this->serialize( $value ) );
                        } else {
-                               $result = $conn->setex( $key, $expiry, $value );
+                               // No expiry, that is very different from zero expiry in Redis
+                               $result = $conn->set( $key, $this->serialize( $value ) );
                        }
                } catch ( RedisException $e ) {
                        $result = false;
@@ -111,15 +111,14 @@ class RedisBagOStuff extends BagOStuff {
                }
 
                $this->logRequest( 'set', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
        public function cas( $casToken, $key, $value, $expiry = 0 ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                $expiry = $this->convertToRelative( $expiry );
@@ -127,25 +126,18 @@ class RedisBagOStuff extends BagOStuff {
                        $conn->watch( $key );
 
                        if ( $this->get( $key ) !== $casToken ) {
-                               wfProfileOut( __METHOD__ );
+                               $conn->unwatch();
                                return false;
                        }
 
+                       // multi()/exec() will fail atomically if the key changed since watch()
                        $conn->multi();
-
-                       if ( !$expiry ) {
-                               // No expiry, that is very different from zero expiry in Redis
-                               $conn->set( $key, $value );
+                       if ( $expiry ) {
+                               $conn->setex( $key, $expiry, $this->serialize( $value ) );
                        } else {
-                               $conn->setex( $key, $expiry, $value );
+                               // No expiry, that is very different from zero expiry in Redis
+                               $conn->set( $key, $this->serialize( $value ) );
                        }
-
-                       /*
-                        * multi()/exec() (transactional mode) allows multiple values to
-                        * be set/get at once and will return an array of results, in
-                        * the order they were set/get. In this case, we only set 1
-                        * value, which should (in case of success) result in true.
-                        */
                        $result = ( $conn->exec() == array( true ) );
                } catch ( RedisException $e ) {
                        $result = false;
@@ -153,15 +145,14 @@ class RedisBagOStuff extends BagOStuff {
                }
 
                $this->logRequest( 'cas', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
        public function delete( $key, $time = 0 ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                try {
@@ -172,13 +163,14 @@ class RedisBagOStuff extends BagOStuff {
                        $result = false;
                        $this->handleException( $server, $conn, $e );
                }
+
                $this->logRequest( 'delete', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
        public function getMulti( array $keys ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                $batches = array();
                $conns = array();
                foreach ( $keys as $key ) {
@@ -204,7 +196,7 @@ class RedisBagOStuff extends BagOStuff {
                                }
                                foreach ( $batchResult as $i => $value ) {
                                        if ( $value !== false ) {
-                                               $result[$batchKeys[$i]] = $value;
+                                               $result[$batchKeys[$i]] = $this->unserialize( $value );
                                        }
                                }
                        } catch ( RedisException $e ) {
@@ -214,29 +206,32 @@ class RedisBagOStuff extends BagOStuff {
 
                $this->debug( "getMulti for " . count( $keys ) . " keys " .
                        "returned " . count( $result ) . " results" );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
        public function add( $key, $value, $expiry = 0 ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                $expiry = $this->convertToRelative( $expiry );
                try {
-                       $result = $conn->setnx( $key, $value );
-                       if ( $result && $expiry ) {
+                       if ( $expiry ) {
+                               $conn->multi();
+                               $conn->setnx( $key, $this->serialize( $value ) );
                                $conn->expire( $key, $expiry );
+                               $result = ( $conn->exec() == array( true, true ) );
+                       } else {
+                               $result = $conn->setnx( $key, $this->serialize( $value ) );
                        }
                } catch ( RedisException $e ) {
                        $result = false;
                        $this->handleException( $server, $conn, $e );
                }
+
                $this->logRequest( 'add', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
@@ -245,23 +240,22 @@ class RedisBagOStuff extends BagOStuff {
         * with WATCH or scripting, but this function is rarely used.
         */
        public function replace( $key, $value, $expiry = 0 ) {
-               wfProfileIn( __METHOD__ );
+               $section = new ProfileSection( __METHOD__ );
+
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
                if ( !$conn->exists( $key ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
                $expiry = $this->convertToRelative( $expiry );
                try {
                        if ( !$expiry ) {
-                               $result = $conn->set( $key, $value );
+                               $result = $conn->set( $key, $this->serialize( $value ) );
                        } else {
-                               $result = $conn->setex( $key, $expiry, $value );
+                               $result = $conn->setex( $key, $expiry, $this->serialize( $value ) );
                        }
                } catch ( RedisException $e ) {
                        $result = false;
@@ -269,10 +263,57 @@ class RedisBagOStuff extends BagOStuff {
                }
 
                $this->logRequest( 'replace', $key, $server, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
+       /**
+        * Non-atomic implementation of incr().
+        *
+        * Probably all callers actually want incr() to atomically initialise
+        * values to zero if they don't exist, as provided by the Redis INCR
+        * command. But we are constrained by the memcached-like interface to
+        * return null in that case. Once the key exists, further increments are
+        * atomic.
+        */
+       public function incr( $key, $value = 1 ) {
+               $section = new ProfileSection( __METHOD__ );
+
+               list( $server, $conn ) = $this->getConnection( $key );
+               if ( !$conn ) {
+                       return false;
+               }
+               if ( !$conn->exists( $key ) ) {
+                       return null;
+               }
+               try {
+                       $result = $this->unserialize( $conn->incrBy( $key, $value ) );
+               } catch ( RedisException $e ) {
+                       $result = false;
+                       $this->handleException( $server, $conn, $e );
+               }
+
+               $this->logRequest( 'incr', $key, $server, $result );
+               return $result;
+       }
+
+       /**
+        * @param mixed $data
+        * @return string
+        */
+       protected function serialize( $data ) {
+               // Ignore digit strings and ints so INCR/DECR work
+               return ( is_int( $data ) || ctype_digit( $data ) ) ? $data : serialize( $data );
+       }
+
+       /**
+        * @param string $data
+        * @return mixed
+        */
+       protected function unserialize( $data ) {
+               // Ignore digit strings and ints so INCR/DECR work
+               return ( is_int( $data ) || ctype_digit( $data ) ) ? $data : unserialize( $data );
+       }
+
        /**
         * Get a Redis object with a connection suitable for fetching the specified key
         * @return Array (server, RedisConnRef) or (false, false)
index acf2703..e845b55 100644 (file)
@@ -114,8 +114,8 @@ class SqlBagOStuff extends BagOStuff {
 
                        # Don't keep timing out trying to connect for each call if the DB is down
                        if ( isset( $this->connFailureErrors[$serverIndex] )
-                               && ( time() - $this->connFailureTimes[$serverIndex] ) < 60 )
-                       {
+                               && ( time() - $this->connFailureTimes[$serverIndex] ) < 60
+                       {
                                throw $this->connFailureErrors[$serverIndex];
                        }
 
@@ -248,13 +248,13 @@ class SqlBagOStuff extends BagOStuff {
                                        $db = $this->getDB( $row->serverIndex );
                                        if ( $this->isExpired( $db, $row->exptime ) ) { // MISS
                                                $this->debug( "get: key has expired, deleting" );
-                                               $db->begin( __METHOD__ );
+                                               $db->commit( __METHOD__, 'flush' );
                                                # Put the expiry time in the WHERE condition to avoid deleting a
                                                # newly-inserted value
                                                $db->delete( $row->tableName,
                                                        array( 'keyname' => $key, 'exptime' => $row->exptime ),
                                                        __METHOD__ );
-                                               $db->commit( __METHOD__ );
+                                               $db->commit( __METHOD__, 'flush' );
                                                $values[$key] = false;
                                        } else { // HIT
                                                $values[$key] = $this->unserialize( $db->decodeBlob( $row->value ) );
@@ -296,7 +296,7 @@ class SqlBagOStuff extends BagOStuff {
 
                                $encExpiry = $db->timestamp( $exptime );
                        }
-                       $db->begin( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                        // (bug 24425) use a replace if the db supports it instead of
                        // delete/insert to avoid clashes with conflicting keynames
                        $db->replace(
@@ -307,7 +307,7 @@ class SqlBagOStuff extends BagOStuff {
                                        'value' => $db->encodeBlob( $this->serialize( $value ) ),
                                        'exptime' => $encExpiry
                                ), __METHOD__ );
-                       $db->commit( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return false;
@@ -341,7 +341,7 @@ class SqlBagOStuff extends BagOStuff {
                                }
                                $encExpiry = $db->timestamp( $exptime );
                        }
-                       $db->begin( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                        // (bug 24425) use a replace if the db supports it instead of
                        // delete/insert to avoid clashes with conflicting keynames
                        $db->update(
@@ -357,7 +357,7 @@ class SqlBagOStuff extends BagOStuff {
                                ),
                                __METHOD__
                        );
-                       $db->commit( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBQueryError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
 
@@ -376,12 +376,12 @@ class SqlBagOStuff extends BagOStuff {
                list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
                try {
                        $db = $this->getDB( $serverIndex );
-                       $db->begin( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                        $db->delete(
                                $tableName,
                                array( 'keyname' => $key ),
                                __METHOD__ );
-                       $db->commit( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return false;
@@ -400,7 +400,7 @@ class SqlBagOStuff extends BagOStuff {
                try {
                        $db = $this->getDB( $serverIndex );
                        $step = intval( $step );
-                       $db->begin( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                        $row = $db->selectRow(
                                $tableName,
                                array( 'value', 'exptime' ),
@@ -409,14 +409,14 @@ class SqlBagOStuff extends BagOStuff {
                                array( 'FOR UPDATE' ) );
                        if ( $row === false ) {
                                // Missing
-                               $db->commit( __METHOD__ );
+                               $db->commit( __METHOD__, 'flush' );
 
                                return null;
                        }
                        $db->delete( $tableName, array( 'keyname' => $key ), __METHOD__ );
                        if ( $this->isExpired( $db, $row->exptime ) ) {
                                // Expired, do not reinsert
-                               $db->commit( __METHOD__ );
+                               $db->commit( __METHOD__, 'flush' );
 
                                return null;
                        }
@@ -434,7 +434,7 @@ class SqlBagOStuff extends BagOStuff {
                                // Race condition. See bug 28611
                                $newValue = null;
                        }
-                       $db->commit( __METHOD__ );
+                       $db->commit( __METHOD__, 'flush' );
                } catch ( DBError $e ) {
                        $this->handleWriteError( $e, $serverIndex );
                        return null;
@@ -524,7 +524,7 @@ class SqlBagOStuff extends BagOStuff {
                                                        $maxExpTime = $row->exptime;
                                                }
 
-                                               $db->begin( __METHOD__ );
+                                               $db->commit( __METHOD__, 'flush' );
                                                $db->delete(
                                                        $this->getTableNameByShard( $i ),
                                                        array(
@@ -533,7 +533,7 @@ class SqlBagOStuff extends BagOStuff {
                                                                'keyname' => $keys
                                                        ),
                                                        __METHOD__ );
-                                               $db->commit( __METHOD__ );
+                                               $db->commit( __METHOD__, 'flush' );
 
                                                if ( $progressCallback ) {
                                                        if ( intval( $totalSeconds ) === 0 ) {
@@ -566,9 +566,9 @@ class SqlBagOStuff extends BagOStuff {
                        try {
                                $db = $this->getDB( $serverIndex );
                                for ( $i = 0; $i < $this->shards; $i++ ) {
-                                       $db->begin( __METHOD__ );
+                                       $db->commit( __METHOD__, 'flush' );
                                        $db->delete( $this->getTableNameByShard( $i ), '*', __METHOD__ );
-                                       $db->commit( __METHOD__ );
+                                       $db->commit( __METHOD__, 'flush' );
                                }
                        } catch ( DBError $e ) {
                                $this->handleWriteError( $e, $serverIndex );
@@ -678,18 +678,18 @@ class SqlBagOStuff extends BagOStuff {
                for ( $serverIndex = 0; $serverIndex < $this->numServers; $serverIndex++ ) {
                        $db = $this->getDB( $serverIndex );
                        if ( $db->getType() !== 'mysql'
-                               || version_compare( $db->getServerVersion(), '4.1.0', '<' ) )
-                       {
+                               || version_compare( $db->getServerVersion(), '4.1.0', '<' )
+                       {
                                throw new MWException( __METHOD__ . ' is not supported on this DB server' );
                        }
 
                        for ( $i = 0; $i < $this->shards; $i++ ) {
-                               $db->begin( __METHOD__ );
+                               $db->commit( __METHOD__, 'flush' );
                                $db->query(
                                        'CREATE TABLE ' . $db->tableName( $this->getTableNameByShard( $i ) ) .
                                        ' LIKE ' . $db->tableName( 'objectcache' ),
                                        __METHOD__ );
-                               $db->commit( __METHOD__ );
+                               $db->commit( __METHOD__, 'flush' );
                        }
                }
        }
index 8190a8a..7b8935a 100644 (file)
  * @ingroup Parser
  */
 class CacheTime {
+       /** @var  array|bool ParserOptions which have been taken into account to
+        * produce output or false if not available.
+        */
+       public $mUsedOptions;
 
        var     $mVersion = Parser::VERSION,  # Compatibility check
                $mCacheTime = '',             # Time when this object was generated, or -1 for uncacheable. Used in ParserCache.
                $mCacheExpiry = null,         # Seconds after which the object should expire, use 0 for uncachable. Used in ParserCache.
                $mContainsOldMagic;           # Boolean variable indicating if the input contained variables like {{CURRENTDAY}}
 
-       function getCacheTime()              { return $this->mCacheTime; }
+       /**
+        * @return string TS_MW timestamp
+        */
+       function getCacheTime()              { return wfTimestamp( TS_MW, $this->mCacheTime ); }
 
        function containsOldMagic()          { return $this->mContainsOldMagic; }
        function setContainsOldMagic( $com ) { return wfSetVar( $this->mContainsOldMagic, $com ); }
 
        /**
         * setCacheTime() sets the timestamp expressing when the page has been rendered.
-        * This doesn not control expiry, see updateCacheExpiry() for that!
+        * This does not control expiry, see updateCacheExpiry() for that!
         * @param $t string
         * @return string
         */
index 4b6eeca..f57d412 100644 (file)
@@ -100,6 +100,15 @@ class CoreParserFunctions {
                $parser->setFunctionHook( 'subjectpagenamee', array( __CLASS__, 'subjectpagenamee' ), SFH_NO_HASH );
                $parser->setFunctionHook( 'tag',              array( __CLASS__, 'tagObj'           ), SFH_OBJECT_ARGS );
                $parser->setFunctionHook( 'formatdate',       array( __CLASS__, 'formatDate'       ) );
+               $parser->setFunctionHook( 'pageid',           array( __CLASS__, 'pageid'           ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionid',       array( __CLASS__, 'revisionid'       ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionday',      array( __CLASS__, 'revisionday'      ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionday2',     array( __CLASS__, 'revisionday2'     ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionmonth',    array( __CLASS__, 'revisionmonth'    ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionmonth1',   array( __CLASS__, 'revisionmonth1'   ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionyear',     array( __CLASS__, 'revisionyear'     ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisiontimestamp', array( __CLASS__, 'revisiontimestamp' ), SFH_NO_HASH );
+               $parser->setFunctionHook( 'revisionuser',     array( __CLASS__, 'revisionuser'     ), SFH_NO_HASH );
 
                if ( $wgAllowDisplayTitle ) {
                        $parser->setFunctionHook( 'displaytitle', array( __CLASS__, 'displaytitle' ), SFH_NO_HASH );
@@ -418,7 +427,7 @@ class CoreParserFunctions {
         * @param mixed $value value to match
         * @return boolean true on successful match
         */
-       static private function matchAgainstMagicword( $magicword, $value ) {
+       private static function matchAgainstMagicword( $magicword, $value ) {
                if ( strval( $value ) === '' ) {
                        return false;
                }
@@ -707,29 +716,15 @@ class CoreParserFunctions {
         * @return string
         */
        static function pagesize( $parser, $page = '', $raw = null ) {
-               static $cache = array();
                $title = Title::newFromText( $page );
 
                if ( !is_object( $title ) ) {
-                       $cache[$page] = 0;
                        return self::formatRaw( 0, $raw );
                }
 
-               # Normalize name for cache
-               $page = $title->getPrefixedText();
-
-               $length = 0;
-               if ( isset( $cache[$page] ) ) {
-                       $length = $cache[$page];
-               } elseif ( $parser->incrementExpensiveFunctionCount() ) {
-                       $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
-                       $pageID = $rev ? $rev->getPage() : 0;
-                       $revID = $rev ? $rev->getId() : 0;
-                       $length = $cache[$page] = $rev ? $rev->getSize() : 0;
-
-                       // Register dependency in templatelinks
-                       $parser->mOutput->addTemplate( $title, $pageID, $revID );
-               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $title );
+               $length = $rev ? $rev->getSize() : 0;
                return self::formatRaw( $length, $raw );
        }
 
@@ -949,4 +944,204 @@ class CoreParserFunctions {
                );
                return $parser->extensionSubstitution( $params, $frame );
        }
+
+       /**
+        * Fetched the current revision of the given title and return this.
+        * Will increment the expensive function count and
+        * add a template link to get the value refreshed on changes.
+        * For a given title, which is equal to the current parser title,
+        * the revision object from the parser is used, when that is the current one
+        *
+        * @param $parser Parser
+        * @param $title Title
+        * @return Revision
+        * @since 1.23
+        */
+       private static function getCachedRevisionObject( $parser, $title = null ) {
+               static $cache = array();
+
+               if ( is_null( $title ) ) {
+                       return null;
+               }
+
+               // Use the revision from the parser itself, when param is the current page
+               // and the revision is the current one
+               if ( $title->equals( $parser->getTitle() ) ) {
+                       $parserRev = $parser->getRevisionObject();
+                       if ( $parserRev && $parserRev->isCurrent() ) {
+                               // force reparse after edit with vary-revision flag
+                               $parser->getOutput()->setFlag( 'vary-revision' );
+                               wfDebug( __METHOD__ . ": use current revision from parser, setting vary-revision...\n" );
+                               return $parserRev;
+                       }
+               }
+
+               // Normalize name for cache
+               $page = $title->getPrefixedDBkey();
+
+               if ( array_key_exists( $page, $cache ) ) { // cache contains null values
+                       return $cache[$page];
+               }
+               if ( $parser->incrementExpensiveFunctionCount() ) {
+                       $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
+                       $pageID = $rev ? $rev->getPage() : 0;
+                       $revID = $rev ? $rev->getId() : 0;
+                       $cache[$page] = $rev; // maybe null
+
+                       // Register dependency in templatelinks
+                       $parser->getOutput()->addTemplate( $title, $pageID, $revID );
+
+                       return $rev;
+               }
+               $cache[$page] = null;
+               return null;
+       }
+
+       /**
+        * Get the pageid of a specified page
+        * @param $parser Parser
+        * @param $title string Title to get the pageid from
+        * @since 1.23
+        */
+       public static function pageid( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // Use title from parser to have correct pageid after edit
+               if ( $t->equals( $parser->getTitle() ) ) {
+                       $t = $parser->getTitle();
+               }
+               // fetch pageid from cache/database and return the value
+               $pageid = $t->getArticleID();
+               return $pageid ? $pageid : '';
+       }
+
+       /**
+        * Get the id from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the id from
+        * @since 1.23
+        */
+       public static function revisionid( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? $rev->getId() : '';
+       }
+
+       /**
+        * Get the day from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the day from
+        * @since 1.23
+        */
+       public static function revisionday( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'j' ) : '';
+       }
+
+       /**
+        * Get the day with leading zeros from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the day from
+        * @since 1.23
+        */
+       public static function revisionday2( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'd' ) : '';
+       }
+
+       /**
+        * Get the month with leading zeros from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the month from
+        * @since 1.23
+        */
+       public static function revisionmonth( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'm' ) : '';
+       }
+
+       /**
+        * Get the month from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the month from
+        * @since 1.23
+        */
+       public static function revisionmonth1( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'n' ) : '';
+       }
+
+       /**
+        * Get the year from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the year from
+        * @since 1.23
+        */
+       public static function revisionyear( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'Y' ) : '';
+       }
+
+       /**
+        * Get the timestamp from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the timestamp from
+        * @since 1.23
+        */
+       public static function revisiontimestamp( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'YmdHis' ) : '';
+       }
+
+       /**
+        * Get the user from the last revision of a specified page.
+        * @param $parser Parser
+        * @param $title string Title to get the user from
+        * @since 1.23
+        */
+       public static function revisionuser( $parser, $title = null ) {
+               $t = Title::newFromText( $title );
+               if ( is_null( $t ) ) {
+                       return '';
+               }
+               // fetch revision from cache/database and return the value
+               $rev = self::getCachedRevisionObject( $parser, $t );
+               return $rev ? $rev->getUserText() : '';
+       }
 }
index 4600402..40c0a89 100644 (file)
@@ -160,8 +160,8 @@ class LinkHolderArray {
                $pos = 0;
                while ( $pos < strlen( $text ) ) {
                        if ( !preg_match( '/<!--LINK (\d+):(\d+)-->/',
-                               $text, $m, PREG_OFFSET_CAPTURE, $pos ) )
-                       {
+                               $text, $m, PREG_OFFSET_CAPTURE, $pos )
+                       {
                                break;
                        }
                        $ns = $m[1][0];
@@ -251,9 +251,8 @@ class LinkHolderArray {
        }
 
        /**
-        * @todo FIXME: Update documentation. makeLinkObj() is deprecated.
         * Replace <!--LINK--> link placeholders with actual links, in the buffer
-        * Placeholders created in Skin::makeLinkObj()
+        *
         * @return array of link CSS classes, indexed by PDBK.
         */
        function replace( &$text ) {
index 5e86209..9be75ae 100644 (file)
@@ -115,6 +115,10 @@ class Parser {
        # Marker Suffix needs to be accessible staticly.
        const MARKER_SUFFIX = "-QINU\x7f";
 
+       # Markers used for wrapping the table of contents
+       const TOC_START = '<mw:toc>';
+       const TOC_END = '</mw:toc>';
+
        # Persistent:
        var $mTagHooks = array();
        var $mTransparentTagHooks = array();
@@ -416,8 +420,8 @@ class Parser {
                 * d) it is an interface message (which is in the user language)
                 */
                if ( !( $options->getDisableContentConversion()
-                               || isset( $this->mDoubleUnderscores['nocontentconvert'] ) ) )
-               {
+                       || isset( $this->mDoubleUnderscores['nocontentconvert'] ) )
+               {
                        if ( !$this->mOptions->getInterfaceMessage() ) {
                                # The position of the convert() call should not be changed. it
                                # assumes that the links are all replaced and the only thing left
@@ -434,10 +438,10 @@ class Parser {
                 * automatic link conversion.
                 */
                if ( !( $options->getDisableTitleConversion()
-                               || isset( $this->mDoubleUnderscores['nocontentconvert'] )
-                               || isset( $this->mDoubleUnderscores['notitleconvert'] )
-                               || $this->mOutput->getDisplayTitle() !== false ) )
-               {
+                       || isset( $this->mDoubleUnderscores['nocontentconvert'] )
+                       || isset( $this->mDoubleUnderscores['notitleconvert'] )
+                       || $this->mOutput->getDisplayTitle() !== false )
+               {
                        $convruletitle = $this->getConverterLanguage()->getConvRuleTitle();
                        if ( $convruletitle ) {
                                $this->mOutput->setTitleText( $convruletitle );
@@ -537,7 +541,7 @@ class Parser {
                        }
                        foreach ( $this->mOutput->getLimitReportData() as $key => $value ) {
                                if ( wfRunHooks( 'ParserLimitReportFormat',
-                                       array( $key, $value, &$limitReport, false, false )
+                                       array( $key, &$value, &$limitReport, false, false )
                                ) ) {
                                        $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false );
                                        $valueMsg = wfMessage( array( "$key-value-text", "$key-value" ) )
@@ -1692,9 +1696,9 @@ class Parser {
        public static function getExternalLinkRel( $url = false, $title = null ) {
                global $wgNoFollowLinks, $wgNoFollowNsExceptions, $wgNoFollowDomainExceptions;
                $ns = $title ? $title->getNamespace() : false;
-               if ( $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions ) &&
-                               !wfMatchesDomainList( $url, $wgNoFollowDomainExceptions ) )
-               {
+               if ( $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions )
+                       && !wfMatchesDomainList( $url, $wgNoFollowDomainExceptions )
+               {
                        return 'nofollow';
                }
                return null;
@@ -1784,14 +1788,14 @@ class Parser {
                        $imagematch = false;
                }
                if ( $this->mOptions->getAllowExternalImages()
-                        || ( $imagesexception && $imagematch ) ) {
+                       || ( $imagesexception && $imagematch ) ) {
                        if ( preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
                                # Image found
                                $text = Linker::makeExternalImage( $url );
                        }
                }
                if ( !$text && $this->mOptions->getEnableImageWhitelist()
-                        && preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
+                       && preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
                        $whitelist = explode( "\n", wfMessage( 'external_image_whitelist' )->inContentLanguage()->text() );
                        foreach ( $whitelist as $entry ) {
                                # Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments
@@ -1859,7 +1863,9 @@ class Parser {
                if ( $useLinkPrefixExtension ) {
                        # Match the end of a line for a word that's not followed by whitespace,
                        # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched
-                       $e2 = wfMessage( 'linkprefix' )->inContentLanguage()->text();
+                       global $wgContLang;
+                       $charset = $wgContLang->linkPrefixCharset();
+                       $e2 = "/^((?>.*[^$charset]|))(.+)$/sDu";
                }
 
                if ( is_null( $this->mTitle ) ) {
@@ -1922,11 +1928,10 @@ class Parser {
                                # Still some problems for cases where the ] is meant to be outside punctuation,
                                # and no image is in sight. See bug 2095.
                                #
-                               if ( $text !== '' &&
-                                       substr( $m[3], 0, 1 ) === ']' &&
-                                       strpos( $text, '[' ) !== false
-                               )
-                               {
+                               if ( $text !== ''
+                                       && substr( $m[3], 0, 1 ) === ']'
+                                       && strpos( $text, '[' ) !== false
+                               ) {
                                        $text .= ']'; # so that replaceExternalLinks($text) works later
                                        $m[3] = substr( $m[3], 1 );
                                }
@@ -2462,7 +2467,7 @@ class Parser {
                                $openmatch = preg_match( '/(?:<table|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<dl|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
                                $closematch = preg_match(
                                        '/(?:<\\/table|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|' .
-                                       '<td|<th|<\\/?blockquote|<\\/?div|<hr|<\\/pre|<\\/p|' . $this->mUniqPrefix . '-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS', $t );
+                                       '<td|<th|<\\/?blockquote|<\\/?div|<hr|<\\/pre|<\\/p|<\\/mw:|' . $this->mUniqPrefix . '-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS', $t );
                                if ( $openmatch or $closematch ) {
                                        $paragraphStack = false;
                                        # TODO bug 5718: paragraph closed
@@ -3381,8 +3386,8 @@ class Parser {
                        if ( !$title->isExternal() ) {
                                if ( $title->isSpecialPage()
                                        && $this->mOptions->getAllowSpecialInclusion()
-                                       && $this->ot['html'] )
-                               {
+                                       && $this->ot['html']
+                               {
                                        // Pass the template arguments as URL parameters.
                                        // "uselang" will have no effect since the Language object
                                        // is forced to the one defined in ParserOptions.
@@ -3500,8 +3505,8 @@ class Parser {
                        $text = wfEscapeWikiText( $text );
                } elseif ( is_string( $text )
                        && !$piece['lineStart']
-                       && preg_match( '/^(?:{\\||:|;|#|\*)/', $text ) )
-               {
+                       && preg_match( '/^(?:{\\||:|;|#|\*)/', $text )
+               {
                        # Bug 529: if the template begins with a table or block-level
                        # element, it should be treated as beginning a new line.
                        # This behavior is somewhat controversial.
@@ -3941,11 +3946,10 @@ class Parser {
                $object = false;
                $text = $frame->getArgument( $argName );
                if ( $text === false && $parts->getLength() > 0
-                 && (
-                       $this->ot['html']
-                       || $this->ot['pre']
-                       || ( $this->ot['wiki'] && $frame->isTemplate() )
-                 )
+                       && ( $this->ot['html']
+                               || $this->ot['pre']
+                               || ( $this->ot['wiki'] && $frame->isTemplate() )
+                       )
                ) {
                        # No match in frame, use the supplied default
                        $object = $parts->item( 0 )->getChildren();
@@ -4516,6 +4520,7 @@ class Parser {
                        }
                        $toc = Linker::tocList( $toc, $this->mOptions->getUserLangObj() );
                        $this->mOutput->setTOCHTML( $toc );
+                       $toc = self::TOC_START . $toc . self::TOC_END;
                }
 
                if ( $isMain ) {
@@ -5425,10 +5430,10 @@ class Parser {
                $params['frame']['caption'] = $caption;
 
                # Will the image be presented in a frame, with the caption below?
-               $imageIsFramed = isset( $params['frame']['frame'] ) ||
-                                                isset( $params['frame']['framed'] ) ||
-                                                isset( $params['frame']['thumbnail'] ) ||
-                                                isset( $params['frame']['manualthumb'] );
+               $imageIsFramed = isset( $params['frame']['frame'] )
+                       || isset( $params['frame']['framed'] )
+                       || isset( $params['frame']['thumbnail'] )
+                       || isset( $params['frame']['manualthumb'] );
 
                # In the old days, [[Image:Foo|text...]] would set alt text.  Later it
                # came to also set the caption, ordinary text after the image -- which
@@ -5755,8 +5760,9 @@ class Parser {
         * Get the revision object for $this->mRevisionId
         *
         * @return Revision|null either a Revision object or null
+        * @since 1.23 (public since 1.23)
         */
-       protected function getRevisionObject() {
+       public function getRevisionObject() {
                if ( !is_null( $this->mRevisionObject ) ) {
                        return $this->mRevisionObject;
                }
index 7053f13..7043b4a 100644 (file)
@@ -220,10 +220,10 @@ class ParserCache {
        }
 
        /**
-        * @param $parserOutput ParserOutput
-        * @param $article Article
-        * @param $popts ParserOptions
-        * @param $cacheTime Time when the cache was generated
+        * @param ParserOutput $parserOutput
+        * @param Article $article
+        * @param ParserOptions $popts
+        * @param string $cacheTime Time when the cache was generated
         */
        public function save( $parserOutput, $article, $popts, $cacheTime = null ) {
                $expire = $parserOutput->getCacheExpiry();
index bde508a..8393216 100644 (file)
@@ -240,6 +240,7 @@ class ParserOptions {
        function getExternalLinkTarget()            { return $this->mExternalLinkTarget; }
        function getDisableContentConversion()      { return $this->mDisableContentConversion; }
        function getDisableTitleConversion()        { return $this->mDisableTitleConversion; }
+       /** @deprecated since 1.22 use User::getOption('math') instead */
        function getMath()                          { $this->optionUsed( 'math' );
                                                                                                  return $this->mMath; }
        function getThumbSize()                     { $this->optionUsed( 'thumbsize' );
@@ -338,6 +339,7 @@ class ParserOptions {
        function setExternalLinkTarget( $x )        { return wfSetVar( $this->mExternalLinkTarget, $x ); }
        function disableContentConversion( $x = true ) { return wfSetVar( $this->mDisableContentConversion, $x ); }
        function disableTitleConversion( $x = true ) { return wfSetVar( $this->mDisableTitleConversion, $x ); }
+       /** @deprecated since 1.22 */
        function setMath( $x )                      { return wfSetVar( $this->mMath, $x ); }
        function setUserLang( $x )                  {
                if ( is_string( $x ) ) {
@@ -491,8 +493,6 @@ class ParserOptions {
         * so users sharign the options with vary for the same page share
         * the same cached data safely.
         *
-        * Replaces User::getPageRenderingHash()
-        *
         * Extensions which require it should install 'PageRenderingHash' hook,
         * which will give them a chance to modify this key based on their own
         * settings.
index 9519de9..76d14cf 100644 (file)
@@ -47,7 +47,8 @@ class ParserOutput extends CacheTime {
                $mEditSectionTokens = false,  # prefix/suffix markers if edit sections were output as tokens
                $mProperties = array(),       # Name/value pairs to be cached in the DB
                $mTOCHTML = '',               # HTML of the TOC
-               $mTimestamp;                  # Timestamp of the revision
+               $mTimestamp,                  # Timestamp of the revision
+               $mTOCEnabled = true;          # Whether TOC should be shown, can't override __NOTOC__
                private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
                private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
                private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
@@ -58,8 +59,8 @@ class ParserOutput extends CacheTime {
        const EDITSECTION_REGEX = '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
 
        function __construct( $text = '', $languageLinks = array(), $categoryLinks = array(),
-               $containsOldMagic = false, $titletext = '' )
-       {
+               $containsOldMagic = false, $titletext = ''
+       {
                $this->mText = $text;
                $this->mLanguageLinks = $languageLinks;
                $this->mCategories = $categoryLinks;
@@ -68,11 +69,27 @@ class ParserOutput extends CacheTime {
        }
 
        function getText() {
+               wfProfileIn( __METHOD__ );
+               $text = $this->mText;
                if ( $this->mEditSectionTokens ) {
-                       return preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
-                               array( &$this, 'replaceEditSectionLinksCallback' ), $this->mText );
+                       $text = preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
+                               array( &$this, 'replaceEditSectionLinksCallback' ), $text );
+               } else {
+                       $text = preg_replace( ParserOutput::EDITSECTION_REGEX, '', $text );
+               }
+
+               // If you have an old cached version of this class - sorry, you can't disable the TOC
+               if ( isset( $this->mTOCEnabled ) && $this->mTOCEnabled ) {
+                       $text = str_replace( array( Parser::TOC_START, Parser::TOC_END ), '', $text );
+               } else {
+                       $text = preg_replace(
+                               '#' . preg_quote( Parser::TOC_START ) . '.*?' . preg_quote( Parser::TOC_END ) . '#s',
+                               '',
+                               $text
+                       );
                }
-               return preg_replace( ParserOutput::EDITSECTION_REGEX, '', $this->mText );
+               wfProfileOut( __METHOD__ );
+               return $text;
        }
 
        /**
@@ -123,6 +140,7 @@ class ParserOutput extends CacheTime {
        function getTOCHTML()                { return $this->mTOCHTML; }
        function getTimestamp()              { return $this->mTimestamp; }
        function getLimitReportData()        { return $this->mLimitReportData; }
+       function getTOCEnabled()             { return $this->mTOCEnabled; }
 
        function setText( $text )            { return wfSetVar( $this->mText, $text ); }
        function setLanguageLinks( $ll )     { return wfSetVar( $this->mLanguageLinks, $ll ); }
@@ -134,6 +152,7 @@ class ParserOutput extends CacheTime {
        function setIndexPolicy( $policy )   { return wfSetVar( $this->mIndexPolicy, $policy ); }
        function setTOCHTML( $tochtml )      { return wfSetVar( $this->mTOCHTML, $tochtml ); }
        function setTimestamp( $timestamp )  { return wfSetVar( $this->mTimestamp, $timestamp ); }
+       function setTOCEnabled( $flag )      { return wfSetVar( $this->mTOCEnabled, $flag ); }
 
        function addCategory( $c, $sort )    { $this->mCategories[$c] = $sort; }
        function addLanguageLink( $t )       { $this->mLanguageLinks[] = $t; }
index 3138f48..6b2a874 100644 (file)
@@ -160,7 +160,6 @@ class Preprocessor_DOM implements Preprocessor {
                        $xml = $this->preprocessToXml( $text, $flags );
                }
 
-
                // Fail if the number of elements exceeds acceptable limits
                // Do not attempt to generate the DOM
                $this->parser->mGeneratedPPNodeCount += substr_count( $xml, '<' );
@@ -400,14 +399,14 @@ class Preprocessor_DOM implements Preprocessor {
                                                // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
                                                // it's a possible beneficial b/c break.
                                                if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
-                                                       && substr( $text, $wsEnd + 1, 1 ) == "\n" )
-                                               {
+                                                       && substr( $text, $wsEnd + 1, 1 ) == "\n"
+                                               {
                                                        // Remove leading whitespace from the end of the accumulator
                                                        // Sanity check first though
                                                        $wsLength = $i - $wsStart;
                                                        if ( $wsLength > 0
-                                                               && strspn( $accum, " \t", -$wsLength ) === $wsLength )
-                                                       {
+                                                               && strspn( $accum, " \t", -$wsLength ) === $wsLength
+                                                       {
                                                                $accum = substr( $accum, 0, -$wsLength );
                                                        }
 
@@ -476,8 +475,8 @@ class Preprocessor_DOM implements Preprocessor {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
                                        if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
-                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) )
-                                       {
+                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 )
+                                       {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>';
@@ -1142,8 +1141,8 @@ class PPFrame_DOM implements PPFrame {
                                        # Remove it in HTML, pre+remove and STRIP_COMMENTS modes
                                        if ( $this->parser->ot['html']
                                                || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
-                                               || ( $flags & PPFrame::STRIP_COMMENTS ) )
-                                       {
+                                               || ( $flags & PPFrame::STRIP_COMMENTS )
+                                       {
                                                $out .= '';
                                        }
                                        # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
index 2fc5e11..c2ab54e 100644 (file)
@@ -326,15 +326,15 @@ class Preprocessor_Hash implements Preprocessor {
                                                // the overall start. That's not how Sanitizer::removeHTMLcomments() did it, but
                                                // it's a possible beneficial b/c break.
                                                if ( $wsStart > 0 && substr( $text, $wsStart - 1, 1 ) == "\n"
-                                                       && substr( $text, $wsEnd + 1, 1 ) == "\n" )
-                                               {
+                                                       && substr( $text, $wsEnd + 1, 1 ) == "\n"
+                                               {
                                                        // Remove leading whitespace from the end of the accumulator
                                                        // Sanity check first though
                                                        $wsLength = $i - $wsStart;
                                                        if ( $wsLength > 0
                                                                && $accum->lastNode instanceof PPNode_Hash_Text
-                                                               && strspn( $accum->lastNode->value, " \t", -$wsLength ) === $wsLength )
-                                                       {
+                                                               && strspn( $accum->lastNode->value, " \t", -$wsLength ) === $wsLength
+                                                       {
                                                                $accum->lastNode->value = substr( $accum->lastNode->value, 0, -$wsLength );
                                                        }
 
@@ -404,8 +404,8 @@ class Preprocessor_Hash implements Preprocessor {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
                                        if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
-                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) )
-                                       {
+                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 )
+                                       {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = $matches[0][0];
@@ -1062,8 +1062,8 @@ class PPFrame_Hash implements PPFrame {
                                        # Remove it in HTML, pre+remove and STRIP_COMMENTS modes
                                        if ( $this->parser->ot['html']
                                                || ( $this->parser->ot['pre'] && $this->parser->mOptions->getRemoveComments() )
-                                               || ( $flags & PPFrame::STRIP_COMMENTS ) )
-                                       {
+                                               || ( $flags & PPFrame::STRIP_COMMENTS )
+                                       {
                                                $out .= '';
                                        }
                                        # Add a strip marker in PST mode so that pstPass2() can run some old-fashioned regexes on the result
@@ -1654,8 +1654,8 @@ class PPNode_Hash_Tree implements PPNode {
                        if ( $child->name === 'name' ) {
                                $bits['name'] = $child;
                                if ( $child->firstChild instanceof PPNode_Hash_Attr
-                                       && $child->firstChild->name === 'index' )
-                               {
+                                       && $child->firstChild->name === 'index'
+                               {
                                        $bits['index'] = $child->firstChild->value;
                                }
                        } elseif ( $child->name === 'value' ) {
index 0625140..32b16aa 100644 (file)
@@ -61,7 +61,10 @@ class MWTidyWrapper {
 
                // Replace <mw:editsection> elements with placeholders
                $wrappedtext = preg_replace_callback( ParserOutput::EDITSECTION_REGEX,
-                       array( &$this, 'replaceEditSectionLinksCallback' ), $text );
+                       array( &$this, 'replaceCallback' ), $text );
+               // ...and <mw:toc> markers
+               $wrappedtext = preg_replace_callback( '/\<\\/?mw:toc\>/',
+                       array( &$this, 'replaceCallback' ), $wrappedtext );
 
                // Modify inline Microdata <link> and <meta> elements so they say <html-link> and <html-meta> so
                // we can trick Tidy into not stripping them out by including them in tidy's new-empty-tags config
@@ -80,7 +83,7 @@ class MWTidyWrapper {
         *
         * @return string
         */
-       function replaceEditSectionLinksCallback( $m ) {
+       function replaceCallback( $m ) {
                $marker = "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}" . Parser::MARKER_SUFFIX;
                $this->mMarkerIndex++;
                $this->mTokens->setPair( $marker, $m[0] );
index 2282a3a..235a5ad 100644 (file)
@@ -283,8 +283,8 @@ class Profiler {
                        return; // short-circuit
                // @TODO: hardcoded check is a tad janky (what about FOR UPDATE?)
                } elseif ( !preg_match( '/^query-m: (?!SELECT)/', $method )
-                       && $realtime < $this->mDBLockThreshold )
-               {
+                       && $realtime < $this->mDBLockThreshold
+               {
                        return; // not a DB master query nor slow enough
                }
                $now = microtime( true );
index 0a1f3b1..982c6ae 100644 (file)
@@ -23,7 +23,8 @@
 
 /**
  * ProfilerSimpleUDP class, that sends out messages for 'udpprofile' daemon
- * (the one from mediawiki/trunk/udpprofile SVN )
+ * (the one from
+ *  http://git.wikimedia.org/tree/operations%2Fsoftware.git/master/udpprofile)
  * @ingroup Profiler
  */
 class ProfilerSimpleUDP extends ProfilerSimple {
index f4cb992..144ec95 100644 (file)
@@ -44,8 +44,8 @@ class JSONRCFeedFormatter implements RCFeedFormatter {
                                break;
 
                        case RC_NEW:
-                               $packet['length'] = array( 'old' => NULL, 'new' => $attrib['rc_new_len'] );
-                               $packet['revision'] = array( 'old' => NULL, 'new' => $attrib['rc_this_oldid'] );
+                               $packet['length'] = array( 'old' => null, 'new' => $attrib['rc_new_len'] );
+                               $packet['revision'] = array( 'old' => null, 'new' => $attrib['rc_this_oldid'] );
                                break;
 
                        case RC_LOG:
index ef999d9..3b072f9 100644 (file)
@@ -68,7 +68,8 @@ class ResourceLoader {
         */
        public function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) {
                if ( !count( $modules ) ) {
-                       return; // or else Database*::select() will explode, plus it's cheaper!
+                       // Or else Database*::select() will explode, plus it's cheaper!
+                       return;
                }
                $dbr = wfGetDB( DB_SLAVE );
                $skin = $context->getSkin();
@@ -140,9 +141,7 @@ class ResourceLoader {
 
                // For empty/whitespace-only data or for unknown filters, don't perform
                // any caching or processing
-               if ( trim( $data ) === ''
-                       || !in_array( $filter, array( 'minify-js', 'minify-css' ) ) )
-               {
+               if ( trim( $data ) === '' || !in_array( $filter, array( 'minify-js', 'minify-css' ) ) ) {
                        wfProfileOut( __METHOD__ );
                        return $data;
                }
@@ -451,7 +450,7 @@ class ResourceLoader {
                wfProfileIn( __METHOD__ );
                $errors = '';
 
-               // Split requested modules into two groups, modules and missing
+               // Find out which modules are missing and instantiate the others
                $modules = array();
                $missing = array();
                foreach ( $context->getModules() as $name ) {
@@ -527,7 +526,7 @@ class ResourceLoader {
                }
 
                // Save response to file cache unless there are errors
-               if ( isset( $fileCache ) && !$errors && !$missing ) {
+               if ( isset( $fileCache ) && !$errors && !count( $missing ) ) {
                        // Cache single modules...and other requests if there are enough hits
                        if ( ResourceFileCache::useFileCache( $context ) ) {
                                if ( $fileCache->isCacheWorthy() ) {
@@ -704,21 +703,24 @@ class ResourceLoader {
        /**
         * Generates code for a response
         *
-        * @param $context ResourceLoaderContext: Context in which to generate a response
+        * @param $context ResourceLoaderContext Context in which to generate a response
         * @param array $modules List of module objects keyed by module name
-        * @param array $missing List of unavailable modules (optional)
-        * @return String: Response data
+        * @param array $missing List of requested module names that are unregistered (optional)
+        * @return string Response data
         */
        public function makeModuleResponse( ResourceLoaderContext $context,
-               array $modules, $missing = array()
+               array $modules, array $missing = array()
        ) {
                $out = '';
                $exceptions = '';
-               if ( $modules === array() && $missing === array() ) {
+               $states = array();
+
+               if ( !count( $modules ) && !count( $missing ) ) {
                        return '/* No modules requested. Max made me put this here */';
                }
 
                wfProfileIn( __METHOD__ );
+
                // Pre-fetch blobs
                if ( $context->shouldIncludeMessages() ) {
                        try {
@@ -734,6 +736,10 @@ class ResourceLoader {
                        $blobs = array();
                }
 
+               foreach ( $missing as $name ) {
+                       $states[$name] = 'missing';
+               }
+
                // Generate output
                $isRaw = false;
                foreach ( $modules as $name => $module ) {
@@ -838,8 +844,8 @@ class ResourceLoader {
                                // Add exception to the output as a comment
                                $exceptions .= self::formatException( $e );
 
-                               // Register module as missing
-                               $missing[] = $name;
+                               // Respond to client with error-state instead of module implementation
+                               $states[$name] = 'error';
                                unset( $modules[$name] );
                        }
                        $isRaw |= $module->isRaw();
@@ -848,14 +854,17 @@ class ResourceLoader {
 
                // Update module states
                if ( $context->shouldIncludeScripts() && !$context->getRaw() && !$isRaw ) {
-                       // Set the state of modules loaded as only scripts to ready
                        if ( count( $modules ) && $context->getOnly() === 'scripts' ) {
-                               $out .= self::makeLoaderStateScript(
-                                       array_fill_keys( array_keys( $modules ), 'ready' ) );
+                               // Set the state of modules loaded as only scripts to ready as
+                               // they don't have an mw.loader.implement wrapper that sets the state
+                               foreach ( $modules as $name => $module ) {
+                                       $states[$name] = 'ready';
+                               }
                        }
-                       // Set the state of modules which were requested but unavailable as missing
-                       if ( is_array( $missing ) && count( $missing ) ) {
-                               $out .= self::makeLoaderStateScript( array_fill_keys( $missing, 'missing' ) );
+
+                       // Set the state of modules we didn't respond to with mw.loader.implement
+                       if ( count( $states ) ) {
+                               $out .= self::makeLoaderStateScript( $states );
                        }
                }
 
@@ -1223,6 +1232,13 @@ class ResourceLoader {
        public static function getLessCompiler() {
                global $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths;
 
+               // When called from the installer, it is possible that a required PHP extension
+               // is missing (at least for now; see bug 47564). If this is the case, throw an
+               // exception (caught by the installer) to prevent a fatal error later on.
+               if ( !function_exists( 'ctype_digit' ) ) {
+                       throw new MWException( 'lessc requires the Ctype extension' );
+               }
+
                $less = new lessc();
                $less->setPreserveComments( true );
                $less->setVariables( self::getLESSVars() );
index 9ed181e..43330da 100644 (file)
@@ -241,7 +241,11 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                case 'dependencies':
                                case 'messages':
                                case 'targets':
-                                       $this->{$member} = (array)$option;
+                                       // Normalise
+                                       $option = array_values( array_unique( (array)$option ) );
+                                       sort( $option );
+
+                                       $this->{$member} = $option;
                                        break;
                                // Single strings
                                case 'group':
@@ -457,14 +461,49 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                wfProfileIn( __METHOD__ . '-filemtime' );
                $filesMtime = max( array_map( array( __CLASS__, 'safeFilemtime' ), $files ) );
                wfProfileOut( __METHOD__ . '-filemtime' );
+
                $this->modifiedTime[$context->getHash()] = max(
                        $filesMtime,
-                       $this->getMsgBlobMtime( $context->getLanguage() ) );
+                       $this->getMsgBlobMtime( $context->getLanguage() ),
+                       $this->getDefinitionMtime( $context )
+               );
 
                wfProfileOut( __METHOD__ );
                return $this->modifiedTime[$context->getHash()];
        }
 
+       /**
+        * Get the definition summary for this module.
+        *
+        * @return Array
+        */
+       public function getDefinitionSummary( ResourceLoaderContext $context ) {
+               $summary = array(
+                       'class' => get_class( $this ),
+               );
+               foreach ( array(
+                       'scripts',
+                       'debugScripts',
+                       'loaderScripts',
+                       'styles',
+                       'languageScripts',
+                       'skinScripts',
+                       'skinStyles',
+                       'dependencies',
+                       'messages',
+                       'targets',
+                       'group',
+                       'position',
+                       'localBasePath',
+                       'remoteBasePath',
+                       'debugRaw',
+                       'raw',
+               ) as $member ) {
+                       $summary[$member] = $this->{$member};
+               };
+               return $summary;
+       }
+
        /* Protected Methods */
 
        /**
@@ -538,8 +577,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        return $list[$key];
                } elseif ( is_string( $fallback )
                        && isset( $list[$fallback] )
-                       && is_array( $list[$fallback] ) )
-               {
+                       && is_array( $list[$fallback] )
+               {
                        return $list[$fallback];
                }
                return array();
@@ -585,7 +624,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         */
        public function getAllStyleFiles() {
                $files = array();
-               foreach( (array)$this->styles as $key => $value ) {
+               foreach ( (array)$this->styles as $key => $value ) {
                        if ( is_array( $value ) ) {
                                $path = $key;
                        } else {
@@ -745,6 +784,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * recompiles as necessary.
         *
         * @since 1.22
+        * @throws Exception If Less encounters a parse error
+        * @throws MWException If Less compilation returns unexpection result
         * @param string $fileName File path of LESS source
         * @return string: CSS source
         */
index 11264fc..429bcec 100644 (file)
@@ -398,7 +398,8 @@ abstract class ResourceLoaderModule {
         * Helper method for calculating when the module's hash (if it has one) changed.
         *
         * @param ResourceLoaderContext $context
-        * @return integer: UNIX timestamp or 0 if there is no hash provided
+        * @return integer: UNIX timestamp or 0 if no hash was provided
+        *  by getModifiedHash()
         */
        public function getHashMtime( ResourceLoaderContext $context ) {
                $hash = $this->getModifiedHash( $context );
@@ -407,7 +408,7 @@ abstract class ResourceLoaderModule {
                }
 
                $cache = wfGetCache( CACHE_ANYTHING );
-               $key = wfMemcKey( 'resourceloader', 'modulemodifiedhash', $this->getName() );
+               $key = wfMemcKey( 'resourceloader', 'modulemodifiedhash', $this->getName(), $hash );
 
                $data = $cache->get( $key );
                if ( is_array( $data ) && $data['hash'] === $hash ) {
@@ -425,8 +426,10 @@ abstract class ResourceLoaderModule {
        }
 
        /**
-        * Get the last modification timestamp of the message blob for this
-        * module in a given language.
+        * Get the hash for whatever this module may contain.
+        *
+        * This is the method subclasses should implement if they want to make
+        * use of getHashMTime() inside getModifiedTime().
         *
         * @param ResourceLoaderContext $context
         * @return string|null: Hash
@@ -435,6 +438,81 @@ abstract class ResourceLoaderModule {
                return null;
        }
 
+       /**
+        * Helper method for calculating when this module's definition summary was last changed.
+        *
+        * @return integer: UNIX timestamp or 0 if no definition summary was provided
+        *  by getDefinitionSummary()
+        */
+       public function getDefinitionMtime( ResourceLoaderContext $context ) {
+               wfProfileIn( __METHOD__ );
+               $summary = $this->getDefinitionSummary( $context );
+               if ( $summary === null ) {
+                       wfProfileOut( __METHOD__ );
+                       return 0;
+               }
+
+               $hash = md5( json_encode( $summary ) );
+
+               $cache = wfGetCache( CACHE_ANYTHING );
+
+               // Embed the hash itself in the cache key. This allows for a few nifty things:
+               // - During deployment, servers with old and new versions of the code communicating
+               //   with the same memcached will not override the same key repeatedly increasing
+               //   the timestamp.
+               // - In case of the definition changing and then changing back in a short period of time
+               //   (e.g. in case of a revert or a corrupt server) the old timestamp and client-side cache
+               //   url will be re-used.
+               // - If different context-combinations (e.g. same skin, same language or some combination
+               //   thereof) result in the same definition, they will use the same hash and timestamp.
+               $key = wfMemcKey( 'resourceloader', 'moduledefinition', $this->getName(), $hash );
+
+               $data = $cache->get( $key );
+               if ( is_int( $data ) && $data > 0 ) {
+                       // We've seen this hash before, re-use the timestamp of when we first saw it.
+                       wfProfileOut( __METHOD__ );
+                       return $data;
+               }
+
+               wfDebugLog( 'resourceloader', __METHOD__ . ": New definition hash for module {$this->getName()} in context {$context->getHash()}: $hash." );
+
+               $timestamp = time();
+               $cache->set( $key, $timestamp );
+
+               wfProfileOut( __METHOD__ );
+               return $timestamp;
+       }
+
+       /**
+        * Get the definition summary for this module.
+        *
+        * This is the method subclasses should implement if they want to make
+        * use of getDefinitionMTime() inside getModifiedTime().
+        *
+        * Return an array containing values from all significant properties of this
+        * module's definition. Be sure to include things that are explicitly ordered,
+        * in their actaul order (bug 37812).
+        *
+        * Avoid including things that are insiginificant (e.g. order of message
+        * keys is insignificant and should be sorted to avoid unnecessary cache
+        * invalidation).
+        *
+        * Avoid including things already considered by other methods inside your
+        * getModifiedTime(), such as file mtime timestamps.
+        *
+        * Serialisation is done using json_encode, which means object state is not
+        * taken into account when building the hash. This data structure must only
+        * contain arrays and scalars as values (avoid object instances) which means
+        * it requires abstraction.
+        *
+        * @return Array|null
+        */
+       public function getDefinitionSummary( ResourceLoaderContext $context ) {
+               return array(
+                       'class' => get_class( $this ),
+               );
+       }
+
        /**
         * Check whether this module is known to be empty. If a child class
         * has an easy and cheap way to determine that this module is
index 20f6e0b..93c5d1b 100644 (file)
@@ -41,7 +41,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        $wgVariantArticlePath, $wgActionPaths, $wgVersion,
                        $wgEnableAPI, $wgEnableWriteAPI, $wgDBname,
                        $wgSitename, $wgFileExtensions, $wgExtensionAssetsPath,
-                       $wgCookiePrefix, $wgResourceLoaderMaxQueryLength;
+                       $wgCookiePrefix, $wgResourceLoaderMaxQueryLength,
+                       $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion;
 
                $mainPage = Title::newMainPage();
 
@@ -83,6 +84,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgMainPageTitle' => $mainPage->getPrefixedText(),
                        'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(),
                        'wgNamespaceIds' => $namespaceIds,
+                       'wgContentNamespaces' => MWNamespace::getContentNamespaces(),
                        'wgSiteName' => $wgSitename,
                        'wgFileExtensions' => array_values( array_unique( $wgFileExtensions ) ),
                        'wgDBname' => $wgDBname,
@@ -96,6 +98,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgResourceLoaderMaxQueryLength' => $wgResourceLoaderMaxQueryLength,
                        'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces,
                        'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass( Title::legalChars() ),
+                       'wgResourceLoaderStorageVersion' => $wgResourceLoaderStorageVersion,
+                       'wgResourceLoaderStorageEnabled' => $wgResourceLoaderStorageEnabled,
                );
 
                wfRunHooks( 'ResourceLoaderGetConfigVars', array( &$vars ) );
index 9064263..9004267 100644 (file)
  */
 class ResourceLoaderUserGroupsModule extends ResourceLoaderWikiModule {
 
-       /* Protected Methods */
+       /* Protected Members */
+
        protected $origin = self::ORIGIN_USER_SITEWIDE;
+       protected $targets = array( 'desktop', 'mobile' );
+
+       /* Protected Methods */
 
        /**
         * @param $context ResourceLoaderContext
index 7a04e47..7454b65 100644 (file)
  */
 class ResourceLoaderUserModule extends ResourceLoaderWikiModule {
 
-       /* Protected Methods */
+       /* Protected Members */
+
        protected $origin = self::ORIGIN_USER_INDIVIDUAL;
 
+       /* Protected Methods */
+
        /**
         * @param $context ResourceLoaderContext
         * @return array
index 0b7e196..1df8c56 100644 (file)
@@ -33,6 +33,8 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
 
        protected $origin = self::ORIGIN_CORE_INDIVIDUAL;
 
+       protected $targets = array( 'desktop', 'mobile' );
+
        /* Methods */
 
        /**
index 92ebbe9..cdc9611 100644 (file)
@@ -30,6 +30,8 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
 
        protected $origin = self::ORIGIN_CORE_INDIVIDUAL;
 
+       protected $targets = array( 'desktop', 'mobile' );
+
        /* Methods */
 
        /**
index 3f10ae5..2653f76 100644 (file)
@@ -180,10 +180,26 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
                if ( count( $mtimes ) ) {
                        $modifiedTime = max( $modifiedTime, max( $mtimes ) );
                }
-               $modifiedTime = max( $modifiedTime, $this->getMsgBlobMtime( $context->getLanguage() ) );
+               $modifiedTime = max(
+                       $modifiedTime,
+                       $this->getMsgBlobMtime( $context->getLanguage() ),
+                       $this->getDefinitionMtime( $context )
+               );
                return $modifiedTime;
        }
 
+       /**
+        * Get the definition summary for this module.
+        *
+        * @return Array
+        */
+       public function getDefinitionSummary( ResourceLoaderContext $context ) {
+               return array(
+                       'class' => get_class( $this ),
+                       'pages' => $this->getPages( $context ),
+               );
+       }
+
        /**
         * @param $context ResourceLoaderContext
         * @return bool
index dbcb3d7..02e1dda 100644 (file)
@@ -201,7 +201,6 @@ class RevisionDeleter {
                return call_user_func( array( self::$allowedTypes[$typeName], 'suggestTarget' ), $target, $ids );
        }
 
-
        /**
         * Checks if a revision still exists in the revision table.
         * If it doesn't, returns the corresponding ar_timestamp field
diff --git a/includes/search/SearchUpdate.php b/includes/search/SearchUpdate.php
deleted file mode 100644 (file)
index 82a413e..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-/**
- * Search index updater
- *
- * See deferred.txt
- *
- * 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 Search
- */
-
-/**
- * Database independant search index updater
- *
- * @ingroup Search
- */
-class SearchUpdate implements DeferrableUpdate {
-       /**
-        * Page id being updated
-        * @var int
-        */
-       private $id = 0;
-
-       /**
-        * Title we're updating
-        * @var Title
-        */
-       private $title;
-
-       /**
-        * Content of the page (not text)
-        * @var Content|false
-        */
-       private $content;
-
-       /**
-        * Constructor
-        *
-        * @param int $id Page id to update
-        * @param Title|string $title Title of page to update
-        * @param Content|string|false $c Content of the page to update.
-        *  If a Content object, text will be gotten from it. String is for back-compat.
-        *  Passing false tells the backend to just update the title, not the content
-        */
-       public function __construct( $id, $title, $c = false ) {
-               if ( is_string( $title ) ) {
-                       $nt = Title::newFromText( $title );
-               } else {
-                       $nt = $title;
-               }
-
-               if ( $nt ) {
-                       $this->id = $id;
-                       // is_string() check is back-compat for ApprovedRevs
-                       if ( is_string( $c ) ) {
-                               $this->content = new TextContent( $c );
-                       } else {
-                               $this->content = $c ?: false;
-                       }
-                       $this->title = $nt;
-               } else {
-                       wfDebug( "SearchUpdate object created with invalid title '$title'\n" );
-               }
-       }
-
-       /**
-        * Perform actual update for the entry
-        */
-       public function doUpdate() {
-               global $wgDisableSearchUpdate;
-
-               if ( $wgDisableSearchUpdate || !$this->id ) {
-                       return;
-               }
-
-               wfProfileIn( __METHOD__ );
-
-               $page = WikiPage::newFromId( $this->id, WikiPage::READ_LATEST );
-               $indexTitle = Title::indexTitle( $this->title->getNamespace(), $this->title->getText() );
-
-               foreach ( SearchEngine::getSearchTypes() as $type ) {
-                       $search = SearchEngine::create( $type );
-                       if ( !$search->supports( 'search-update' ) ) {
-                               continue;
-                       }
-
-                       $normalTitle = $search->normalizeText( $indexTitle );
-
-                       if ( $page === null ) {
-                               $search->delete( $this->id, $normalTitle );
-                               continue;
-                       } elseif ( $this->content === false ) {
-                               $search->updateTitle( $this->id, $normalTitle );
-                               continue;
-                       }
-
-                       $text = $search->getTextFromContent( $this->title, $this->content );
-                       if ( !$search->textAlreadyUpdatedForIndex() ) {
-                               $text = self::updateText( $text );
-                       }
-
-                       # Perform the actual update
-                       $search->update( $this->id, $normalTitle, $search->normalizeText( $text ) );
-               }
-
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Clean text for indexing. Only really suitable for indexing in databases.
-        * If you're using a real search engine, you'll probably want to override
-        * this behavior and do something nicer with the original wikitext.
-        */
-       public static function updateText( $text ) {
-               global $wgContLang;
-
-               # Language-specific strip/conversion
-               $text = $wgContLang->normalizeForSearch( $text );
-               $lc = SearchEngine::legalSearchChars() . '&#;';
-
-               wfProfileIn( __METHOD__ . '-regexps' );
-               $text = preg_replace( "/<\\/?\\s*[A-Za-z][^>]*?>/",
-                       ' ', $wgContLang->lc( " " . $text . " " ) ); # Strip HTML markup
-               $text = preg_replace( "/(^|\\n)==\\s*([^\\n]+)\\s*==(\\s)/sD",
-                       "\\1\\2 \\2 \\2\\3", $text ); # Emphasize headings
-
-               # Strip external URLs
-               $uc = "A-Za-z0-9_\\/:.,~%\\-+&;#?!=()@\\x80-\\xFF";
-               $protos = "http|https|ftp|mailto|news|gopher";
-               $pat = "/(^|[^\\[])({$protos}):[{$uc}]+([^{$uc}]|$)/";
-               $text = preg_replace( $pat, "\\1 \\3", $text );
-
-               $p1 = "/([^\\[])\\[({$protos}):[{$uc}]+]/";
-               $p2 = "/([^\\[])\\[({$protos}):[{$uc}]+\\s+([^\\]]+)]/";
-               $text = preg_replace( $p1, "\\1 ", $text );
-               $text = preg_replace( $p2, "\\1 \\3 ", $text );
-
-               # Internal image links
-               $pat2 = "/\\[\\[image:([{$uc}]+)\\.(gif|png|jpg|jpeg)([^{$uc}])/i";
-               $text = preg_replace( $pat2, " \\1 \\3", $text );
-
-               $text = preg_replace( "/([^{$lc}])([{$lc}]+)]]([a-z]+)/",
-                       "\\1\\2 \\2\\3", $text ); # Handle [[game]]s
-
-               # Strip all remaining non-search characters
-               $text = preg_replace( "/[^{$lc}]+/", " ", $text );
-
-               # Handle 's, s'
-               #
-               #   $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
-               #   $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
-               #
-               # These tail-anchored regexps are insanely slow. The worst case comes
-               # when Japanese or Chinese text (ie, no word spacing) is written on
-               # a wiki configured for Western UTF-8 mode. The Unicode characters are
-               # expanded to hex codes and the "words" are very long paragraph-length
-               # monstrosities. On a large page the above regexps may take over 20
-               # seconds *each* on a 1GHz-level processor.
-               #
-               # Following are reversed versions which are consistently fast
-               # (about 3 milliseconds on 1GHz-level processor).
-               #
-               $text = strrev( preg_replace( "/ s'([{$lc}]+)/", " s'\\1 \\1", strrev( $text ) ) );
-               $text = strrev( preg_replace( "/ 's([{$lc}]+)/", " s\\1", strrev( $text ) ) );
-
-               # Strip wiki '' and '''
-               $text = preg_replace( "/''[']*/", " ", $text );
-               wfProfileOut( __METHOD__ . '-regexps' );
-               return $text;
-       }
-}
index a082049..388705d 100644 (file)
@@ -49,6 +49,16 @@ class SpecialAllpages extends IncludableSpecialPage {
         */
        protected $maxPageLength = 70;
 
+       /**
+        * Maximum number of pages in a hierarchical ("top level") list.
+        *
+        * Traversal of the entire page list by spidering the top levels is thought
+        * to require O(N^3) DB CPU time where N is the number of pages on the wiki.
+        * See bug 56840. If this limit is exceeded, the behaviour becomes like a
+        * simple alphabetic pager.
+        */
+       protected $maxTopLevelPages = 50000;
+
        /**
         * Determines, which message describes the input field 'nsfrom'.
         *
@@ -201,6 +211,14 @@ class SpecialAllpages extends IncludableSpecialPage {
                $lines = $wgMemc->get( $key );
 
                $count = $dbr->estimateRowCount( 'page', '*', $where, __METHOD__ );
+
+               // Don't show a hierarchical list if the number of pages is very large,
+               // since generating it will cause a lot of scanning
+               if ( $count > $this->maxTopLevelPages ) {
+                       $this->showChunk( $namespace, $from, $to, $hideredirects );
+                       return;
+               }
+
                $maxPerSubpage = intval( $count / $this->maxLineCount );
                $maxPerSubpage = max( $maxPerSubpage, $this->maxPerPage );
 
index aab839f..e1531cc 100644 (file)
@@ -75,11 +75,7 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
                $user = $this->getUser();
                $request = $this->getRequest();
 
-               if ( !$request->wasPosted() && !$user->isLoggedIn() ) {
-                       $this->error( 'changeemail-no-info' );
-
-                       return;
-               }
+               $this->requireLogin( 'changeemail-no-info' );
 
                if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) {
                        $this->doReturnTo();
@@ -92,7 +88,7 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
 
                // This could also let someone check the current email address, so
                // require both permissions.
-               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
+               if ( !$user->isAllowed( 'viewmyprivateinfo' ) ) {
                        throw new PermissionsError( 'viewmyprivateinfo' );
                }
 
index 129e919..43a4d2c 100644 (file)
@@ -45,6 +45,11 @@ class SpecialChangePassword extends UnlistedSpecialPage {
                $this->getOutput()->disallowUserJs();
 
                $request = $this->getRequest();
+
+               if ( !$request->wasPosted() ) {
+                       $this->requireLogin( 'resetpass-no-info' );
+               }
+
                $this->mUserName = trim( $request->getVal( 'wpName' ) );
                $this->mOldpass = $request->getVal( 'wpPassword' );
                $this->mNewpass = $request->getVal( 'wpNewPassword' );
@@ -52,11 +57,6 @@ class SpecialChangePassword extends UnlistedSpecialPage {
                $this->mDomain = $request->getVal( 'wpDomain' );
 
                $user = $this->getUser();
-               if ( !$request->wasPosted() && !$user->isLoggedIn() ) {
-                       $this->error( $this->msg( 'resetpass-no-info' )->text() );
-
-                       return;
-               }
 
                if ( $request->wasPosted() && $request->getBool( 'wpCancel' ) ) {
                        $titleObj = Title::newFromText( $request->getVal( 'returnto' ) );
@@ -85,7 +85,7 @@ class SpecialChangePassword extends UnlistedSpecialPage {
 
                                if ( $user->isLoggedIn() ) {
                                        $this->getOutput()->wrapWikiMsg(
-                                                       "<div class=\"successbox\"><strong>\n$1\n</strong></div>",
+                                                       "<div class=\"successbox\">\n$1\n</div>",
                                                        'changepassword-success'
                                        );
                                        $this->getOutput()->returnToMain();
@@ -99,7 +99,7 @@ class SpecialChangePassword extends UnlistedSpecialPage {
                                                'wpLoginToken' => $token,
                                                'wpPassword' => $request->getVal( 'wpNewPassword' ),
                                        ) + $request->getValues( 'wpRemember', 'returnto', 'returntoquery' );
-                                       $login = new LoginForm( new FauxRequest( $data, true ) );
+                                       $login = new LoginForm( new DerivativeRequest( $request, $data, true ) );
                                        $login->setContext( $this->getContext() );
                                        $login->execute( null );
                                }
index 3828b1c..bef155c 100644 (file)
@@ -45,6 +45,8 @@ class EmailConfirmation extends UnlistedSpecialPage {
                $this->checkReadOnly();
                $this->checkPermissions();
 
+               $this->requireLogin( 'confirmemail_needlogin' );
+
                // This could also let someone check the current email address, so
                // require both permissions.
                if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
@@ -52,22 +54,10 @@ class EmailConfirmation extends UnlistedSpecialPage {
                }
 
                if ( $code === null || $code === '' ) {
-                       if ( $this->getUser()->isLoggedIn() ) {
-                               if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
-                                       $this->showRequestForm();
-                               } else {
-                                       $this->getOutput()->addWikiMsg( 'confirmemail_noemail' );
-                               }
+                       if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
+                               $this->showRequestForm();
                        } else {
-                               $llink = Linker::linkKnown(
-                                       SpecialPage::getTitleFor( 'Userlogin' ),
-                                       $this->msg( 'loginreqlink' )->escaped(),
-                                       array(),
-                                       array( 'returnto' => $this->getTitle()->getPrefixedText() )
-                               );
-                               $this->getOutput()->addHTML(
-                                       $this->msg( 'confirmemail_needlogin' )->rawParams( $llink )->parse()
-                               );
+                               $this->getOutput()->addWikiMsg( 'confirmemail_noemail' );
                        }
                } else {
                        $this->attemptConfirm( $code );
@@ -90,19 +80,17 @@ class EmailConfirmation extends UnlistedSpecialPage {
                        } else {
                                $out->addWikiText( $status->getWikiText( 'confirmemail_sendfailed' ) );
                        }
+               } elseif ( $user->isEmailConfirmed() ) {
+                       // 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 );
                } else {
-                       if ( $user->isEmailConfirmed() ) {
-                               // 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 );
-                       }
-
                        if ( $user->isEmailConfirmationPending() ) {
                                $out->wrapWikiMsg(
                                        "<div class=\"error mw-confirmemail-pending\">\n$1\n</div>",
index 0f910a5..af6a35b 100644 (file)
@@ -94,14 +94,14 @@ class SpecialContributions extends SpecialPage {
                        $out->setHTMLTitle( $this->msg(
                                'pagetitle',
                                $this->msg( 'contributions-title', $target )->plain()
-                       ) );
+                       )->inContentLanguage() );
                        $this->getSkin()->setRelevantUser( $userObj );
                } else {
                        $out->addSubtitle( $this->msg( 'sp-contributions-newbies-sub' ) );
-                       $out->setHTMLTitle( $this->msg(
-                               'pagetitle',
-                               $this->msg( 'sp-contributions-newbies-title' )->plain()
-                       ) );
+                       $out->setHTMLTitle(
+                               $this->msg( 'pagetitle', $this->msg( 'sp-contributions-newbies-title' ) )
+                                       ->inContentLanguage()->plain()
+                       );
                }
 
                if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) {
@@ -735,6 +735,11 @@ class ContribsPager extends ReverseChronologicalPager {
                # Get the current user name for accounts
                $join_cond['user'] = Revision::userJoinCond();
 
+               $options = array();
+               if ( $index ) {
+                       $options['USE INDEX'] = array( 'revision' => $index );
+               }
+
                $queryInfo = array(
                        'tables' => $tables,
                        'fields' => array_merge(
@@ -744,7 +749,7 @@ class ContribsPager extends ReverseChronologicalPager {
                                        'page_latest', 'page_is_redirect', 'page_len' )
                        ),
                        'conds' => $conds,
-                       'options' => array( 'USE INDEX' => array( 'revision' => $index ) ),
+                       'options' => $options,
                        'join_conds' => $join_cond
                );
 
@@ -766,10 +771,10 @@ class ContribsPager extends ReverseChronologicalPager {
                $condition = array();
                $join_conds = array();
                $tables = array( 'revision', 'page', 'user' );
+               $index = false;
                if ( $this->contribs == 'newbie' ) {
                        $max = $this->mDb->selectField( 'user', 'max(user_id)', false, __METHOD__ );
                        $condition[] = 'rev_user >' . (int)( $max - $max / 100 );
-                       $index = 'user_timestamp';
                        # ignore local groups with the bot right
                        # @todo FIXME: Global groups may have 'bot' rights
                        $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
@@ -954,7 +959,7 @@ class ContribsPager extends ReverseChronologicalPager {
                        } else {
                                $parentLen = 0;
                                if ( isset( $this->mParentLens[$row->rev_parent_id] ) ) {
-                                       $this->mParentLens[$row->rev_parent_id];
+                                       $parentLen = $this->mParentLens[$row->rev_parent_id];
                                }
 
                                $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
index 501552e..daa56b3 100644 (file)
@@ -36,7 +36,8 @@
  */
 class SpecialEditWatchlist extends UnlistedSpecialPage {
        /**
-        * Editing modes
+        * Editing modes. EDIT_CLEAR is no longer used; the "Clear" link scared people
+        * too much. Now it's passed on to the raw editor, from which it's very easy to clear.
         */
        const EDIT_CLEAR = 1;
        const EDIT_RAW = 2;
@@ -60,21 +61,10 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
        public function execute( $mode ) {
                $this->setHeaders();
 
-               $out = $this->getOutput();
-
                # Anons don't get a watchlist
-               if ( $this->getUser()->isAnon() ) {
-                       $out->setPageTitle( $this->msg( 'watchnologin' ) );
-                       $llink = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Userlogin' ),
-                               $this->msg( 'loginreqlink' )->escaped(),
-                               array(),
-                               array( 'returnto' => $this->getTitle()->getPrefixedText() )
-                       );
-                       $out->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() );
+               $this->requireLogin( 'watchlistanontext' );
 
-                       return;
-               }
+               $out = $this->getOutput();
 
                $this->checkPermissions();
                $this->checkReadOnly();
@@ -95,10 +85,6 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                $mode = self::getMode( $this->getRequest(), $mode );
 
                switch ( $mode ) {
-                       case self::EDIT_CLEAR:
-                               // The "Clear" link scared people too much.
-                               // Pass on to the raw editor, from which it's very easy to clear.
-
                        case self::EDIT_RAW:
                                $out->setPageTitle( $this->msg( 'watchlistedit-raw-title' ) );
                                $form = $this->getRawForm();
@@ -638,7 +624,6 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                switch ( $mode ) {
                        case 'clear':
                        case self::EDIT_CLEAR:
-                               return self::EDIT_CLEAR;
                        case 'raw':
                        case self::EDIT_RAW:
                                return self::EDIT_RAW;
diff --git a/includes/specials/SpecialExpandTemplates.php b/includes/specials/SpecialExpandTemplates.php
new file mode 100644 (file)
index 0000000..a78133c
--- /dev/null
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Implements Special:ExpandTemplates
+ *
+ * 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 expands submitted templates, parser functions,
+ * and variables, allowing easier debugging of these.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialExpandTemplates extends SpecialPage {
+
+       /** @var boolean whether or not to show the XML parse tree */
+       protected $generateXML;
+
+       /** @var boolean whether or not to remove comments in the expanded wikitext */
+       protected $removeComments;
+
+       /** @var boolean whether or not to remove <nowiki> tags in the expanded wikitext */
+       protected $removeNowiki;
+
+       /** @var maximum size in bytes to include. 50MB allows fixing those huge pages */
+       const MAX_INCLUDE_SIZE = 50000000;
+
+       function __construct() {
+               parent::__construct( 'ExpandTemplates' );
+       }
+
+       /**
+        * Show the special page
+        */
+       function execute( $subpage ) {
+               global $wgParser, $wgUseTidy, $wgAlwaysUseTidy;
+
+               $this->setHeaders();
+
+               $request = $this->getRequest();
+               $titleStr = $request->getText( 'wpContextTitle' );
+               $title = Title::newFromText( $titleStr );
+
+               if ( !$title ) {
+                       $title = $this->getTitle();
+               }
+               $input = $request->getText( 'wpInput' );
+               $this->generateXML = $request->getBool( 'wpGenerateXml' );
+
+               if ( strlen( $input ) ) {
+                       $this->removeComments = $request->getBool( 'wpRemoveComments', false );
+                       $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
+                       $options = ParserOptions::newFromContext( $this->getContext() );
+                       $options->setRemoveComments( $this->removeComments );
+                       $options->setTidy( true );
+                       $options->setMaxIncludeSize( self::MAX_INCLUDE_SIZE );
+
+                       if ( $this->generateXML ) {
+                               $wgParser->startExternalParse( $title, $options, OT_PREPROCESS );
+                               $dom = $wgParser->preprocessToDom( $input );
+
+                               if ( method_exists( $dom, 'saveXML' ) ) {
+                                       $xml = $dom->saveXML();
+                               } else {
+                                       $xml = $dom->__toString();
+                               }
+                       }
+
+                       $output = $wgParser->preprocess( $input, $title, $options );
+               } else {
+                       $this->removeComments = $request->getBool( 'wpRemoveComments', true );
+                       $this->removeNowiki = $request->getBool( 'wpRemoveNowiki', false );
+                       $output = false;
+               }
+
+               $out = $this->getOutput();
+               $out->addWikiMsg( 'expand_templates_intro' );
+               $out->addHTML( $this->makeForm( $titleStr, $input ) );
+
+               if ( $output !== false ) {
+                       if ( $this->generateXML && strlen( $output ) > 0 ) {
+                               $out->addHTML( $this->makeOutput( $xml, 'expand_templates_xml_output' ) );
+                       }
+
+                       $tmp = $this->makeOutput( $output );
+
+                       if ( $this->removeNowiki ) {
+                               $tmp = preg_replace(
+                                       array( '_&lt;nowiki&gt;_', '_&lt;/nowiki&gt;_', '_&lt;nowiki */&gt;_' ),
+                                       '',
+                                       $tmp
+                               );
+                       }
+
+                       if ( ( $wgUseTidy && $options->getTidy() ) || $wgAlwaysUseTidy ) {
+                               $tmp = MWTidy::tidy( $tmp );
+                       }
+
+                       $out->addHTML( $tmp );
+                       $this->showHtmlPreview( $title, $output, $out );
+               }
+
+       }
+
+       /**
+        * Generate a form allowing users to enter information
+        *
+        * @param string $title Value for context title field
+        * @param string $input Value for input textbox
+        * @return string
+        */
+       private function makeForm( $title, $input ) {
+               $self = $this->getTitle();
+               $form = Xml::openElement(
+                       'form',
+                       array( 'method' => 'post', 'action' => $self->getLocalUrl() )
+               );
+               $form .= "<fieldset><legend>" . $this->msg( 'expandtemplates' )->escaped() . "</legend>\n";
+
+               $form .= '<p>' . Xml::inputLabel(
+                       $this->msg( 'expand_templates_title' )->plain(),
+                       'wpContextTitle',
+                       'contexttitle',
+                       60,
+                       $title,
+                       array( 'autofocus' => true )
+               ) . '</p>';
+               $form .= '<p>' . Xml::label(
+                       $this->msg( 'expand_templates_input' )->text(),
+                       'input'
+               ) . '</p>';
+               $form .= Xml::textarea(
+                       'wpInput',
+                       $input,
+                       10,
+                       10,
+                       array( 'id' => 'input' )
+               );
+
+               $form .= '<p>' . Xml::checkLabel(
+                       $this->msg( 'expand_templates_remove_comments' )->text(),
+                       'wpRemoveComments',
+                       'removecomments',
+                       $this->removeComments
+               ) . '</p>';
+               $form .= '<p>' . Xml::checkLabel(
+                       $this->msg( 'expand_templates_remove_nowiki' )->text(),
+                       'wpRemoveNowiki',
+                       'removenowiki',
+                       $this->removeNowiki
+               ) . '</p>';
+               $form .= '<p>' . Xml::checkLabel(
+                       $this->msg( 'expand_templates_generate_xml' )->text(),
+                       'wpGenerateXml',
+                       'generate_xml',
+                       $this->generateXML
+               ) . '</p>';
+               $form .= '<p>' . Xml::submitButton(
+                       $this->msg( 'expand_templates_ok' )->text(),
+                       array( 'accesskey' => 's' )
+               ) . '</p>';
+               $form .= "</fieldset>\n";
+               $form .= Xml::closeElement( 'form' );
+
+               return $form;
+       }
+
+       /**
+        * Generate a nice little box with a heading for output
+        *
+        * @param string $output Wiki text output
+        * @param string $heading
+        * @return string
+        */
+       private function makeOutput( $output, $heading = 'expand_templates_output' ) {
+               $out = "<h2>" . $this->msg( $heading )->escaped() . "</h2>\n";
+               $out .= Xml::textarea(
+                       'output',
+                       $output,
+                       10,
+                       10,
+                       array( 'id' => 'output', 'readonly' => 'readonly' )
+               );
+
+               return $out;
+       }
+
+       /**
+        * Render the supplied wiki text and append to the page as a preview
+        *
+        * @param Title $title
+        * @param string $text
+        * @param OutputPage $out
+        */
+       private function showHtmlPreview( Title $title, $text, OutputPage $out ) {
+               global $wgParser;
+
+               $popts = ParserOptions::newFromContext( $this->getContext() );
+               $popts->setTargetLanguage( $title->getPageLanguage() );
+               $pout = $wgParser->parse( $text, $title, $popts );
+               $lang = $title->getPageViewLanguage();
+
+               $out->addHTML( "<h2>" . $this->msg( 'expand_templates_preview' )->escaped() . "</h2>\n" );
+               $out->addHTML( Html::openElement( 'div', array(
+                       'class' => 'mw-content-' . $lang->getDir(),
+                       'dir' => $lang->getDir(),
+                       'lang' => $lang->getHtmlCode(),
+               ) ) );
+
+               $out->addHTML( $pout->getText() );
+               $out->addHTML( Html::closeElement( 'div' ) );
+       }
+}
index d7d860d..1bc6c92 100644 (file)
@@ -411,7 +411,6 @@ class ImportReporter extends ContextSource {
        private $mOriginalPageOutCallback = null;
        private $mLogItemCount = 0;
 
-
        /**
         * @param WikiImporter $importer
         * @param $upload
index 5b0c56e..5c121ba 100644 (file)
@@ -62,25 +62,19 @@ class LinkSearchPage extends QueryPage {
                }
 
                $target2 = $target;
-               $protocol = '';
-               $pr_sl = strpos( $target2, '//' );
-               $pr_cl = strpos( $target2, ':' );
-               if ( $pr_sl ) {
-                       // For protocols with '//'
-                       $protocol = substr( $target2, 0, $pr_sl + 2 );
-                       $target2 = substr( $target2, $pr_sl + 2 );
-               } elseif ( !$pr_sl && $pr_cl ) {
-                       // For protocols without '//' like 'mailto:'
-                       $protocol = substr( $target2, 0, $pr_cl + 1 );
-                       $target2 = substr( $target2, $pr_cl + 1 );
-               } elseif ( $protocol == '' && $target2 != '' ) {
-                       // default
-                       $protocol = 'http://';
-               }
-               if ( $protocol != '' && !in_array( $protocol, $protocols_list ) ) {
-                       // unsupported protocol, show original search request
-                       $target2 = $target;
-                       $protocol = '';
+               // Get protocol, default is http://
+               $protocol = 'http://';
+               $bits = wfParseUrl( $target );
+               if ( isset( $bits['scheme'] ) && isset( $bits['delimiter'] ) ) {
+                       $protocol = $bits['scheme'] . $bits['delimiter'];
+                       // Make sure wfParseUrl() didn't make some well-intended correction in the
+                       // protocol
+                       if ( strcasecmp( $protocol, substr( $target, 0, strlen( $protocol ) ) ) === 0 ) {
+                               $target2 = substr( $target, strlen( $protocol ) );
+                       } else {
+                               // If it did, let LinkFilter::makeLikeArray() handle this
+                               $protocol = '';
+                       }
                }
 
                $out->addWikiMsg(
@@ -145,18 +139,26 @@ class LinkSearchPage extends QueryPage {
        /**
         * Return an appropriately formatted LIKE query and the clause
         *
-        * @param string $query
-        * @param string $prot
+        * @param String $query Search pattern to search for
+        * @param String $prot Protocol, e.g. 'http://'
+        *
         * @return array
         */
        static function mungeQuery( $query, $prot ) {
                $field = 'el_index';
-               $rv = LinkFilter::makeLikeArray( $query, $prot );
+               $dbr = wfGetDB( DB_SLAVE );
+
+               if ( $query === '*' && $prot !== '' ) {
+                       // Allow queries like 'ftp://*' to find all ftp links
+                       $rv = array( $prot, $dbr->anyString() );
+               } else {
+                       $rv = LinkFilter::makeLikeArray( $query, $prot );
+               }
+
                if ( $rv === false ) {
                        // LinkFilter doesn't handle wildcard in IP, so we'll have to munge here.
                        $pattern = '/^(:?[0-9]{1,3}\.)+\*\s*$|^(:?[0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]*\*\s*$/';
                        if ( preg_match( $pattern, $query ) ) {
-                               $dbr = wfGetDB( DB_SLAVE );
                                $rv = array( $prot . rtrim( $query, " \t*" ), $dbr->anyString() );
                                $field = 'el_to';
                        }
@@ -227,6 +229,9 @@ class LinkSearchPage extends QueryPage {
 
        /**
         * Override to check query validity.
+        *
+        * @param mixed $offset Numerical offset or false for no offset
+        * @param mixed $limit Numerical limit or false for no limit
         */
        function doQuery( $offset = false, $limit = false ) {
                list( $this->mMungedQuery, ) = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt );
index dff1cf7..7484995 100644 (file)
@@ -240,7 +240,7 @@ class ImageListPager extends TablePager {
                                }
                                $field = $prefix . substr( $field, 3 ) . ' AS ' . $field;
                        }
-                       $fields[array_search('top', $fields)] = "'no' AS top";
+                       $fields[array_search( 'top', $fields )] = "'no' AS top";
                } else {
                        if ( $this->mShowAll ) {
                                $fields[array_search( 'top', $fields )] = "'yes' AS top";
index 2c8792f..de05be4 100644 (file)
@@ -76,20 +76,19 @@ class ListredirectsPage extends QueryPage {
         * @param ResultWrapper $res
         */
        function preprocessResults( $db, $res ) {
-               $batch = new LinkBatch;
+               if ( !$res->numRows() ) {
+                       return;
+               }
 
+               $batch = new LinkBatch;
                foreach ( $res as $row ) {
                        $batch->add( $row->namespace, $row->title );
                        $batch->addObj( $this->getRedirectTarget( $row ) );
                }
-
                $batch->execute();
 
                // Back to start for display
-               if ( $res->numRows() > 0 ) {
-                       // If there are no rows we get an error seeking.
-                       $db->dataSeek( $res, 0 );
-               }
+               $res->seek( 0 );
        }
 
        protected function getRedirectTarget( $row ) {
index 2ffdd89..5265403 100644 (file)
@@ -98,6 +98,7 @@ class SpecialLog extends SpecialPage {
                # Some log types are only for a 'User:' title but we might have been given
                # only the username instead of the full title 'User:username'. This part try
                # to lookup for a user by that name and eventually fix user input. See bug 1697.
+               wfRunHooks( 'GetLogTypesOnUser', array( &$this->typeOnUser ) );
                if ( in_array( $opts->getValue( 'type' ), $this->typeOnUser ) ) {
                        # ok we have a type of log which expect a user title.
                        $target = Title::newFromText( $opts->getValue( 'page' ) );
index c486ba0..8e56574 100644 (file)
@@ -112,6 +112,8 @@ class SpecialPasswordReset extends FormSpecialPage {
                // from a FormSpecialPage class.
                $form->setWrapperLegend( false );
 
+               $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
+
                $i = 0;
                if ( isset( $wgPasswordResetRoutes['username'] ) && $wgPasswordResetRoutes['username'] ) {
                        $i++;
index ce7a45b..51454f6 100644 (file)
@@ -37,14 +37,7 @@ class SpecialPreferences extends SpecialPage {
                $out = $this->getOutput();
                $out->disallowUserJs(); # Prevent hijacked user scripts from sniffing passwords etc.
 
-               $user = $this->getUser();
-               if ( $user->isAnon() ) {
-                       throw new ErrorPageError(
-                               'prefsnologin',
-                               'prefsnologintext',
-                               array( $this->getTitle()->getPrefixedDBkey() )
-                       );
-               }
+               $this->requireLogin( 'prefsnologintext2' );
                $this->checkReadOnly();
 
                if ( $par == 'reset' ) {
@@ -57,12 +50,12 @@ class SpecialPreferences extends SpecialPage {
 
                if ( $this->getRequest()->getCheck( 'success' ) ) {
                        $out->wrapWikiMsg(
-                               "<div class=\"successbox mw-sp-pref-successbox\">\n$1\n</div>",
+                               "<div class=\"successbox\">\n$1\n</div>",
                                'savedprefs'
                        );
                }
 
-               $htmlForm = Preferences::getFormObject( $user, $this->getContext() );
+               $htmlForm = Preferences::getFormObject( $this->getUser(), $this->getContext() );
                $htmlForm->setSubmitCallback( array( 'Preferences', 'tryUISubmit' ) );
 
                $htmlForm->show();
index 0e022bf..14123a8 100644 (file)
@@ -87,7 +87,6 @@ class SpecialRandomInCategory extends SpecialPage {
                        $this->setCategory( $cat );
                }
 
-
                if ( !$this->category && $categoryStr ) {
                        $this->setHeaders();
                        $this->getOutput()->addWikiMsg( 'randomincategory-invalidcategory',
index a42a217..d306744 100644 (file)
@@ -517,8 +517,8 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                }
 
                if ( $rows->numRows() === 0 ) {
-                       $this->getOutput()->wrapWikiMsg(
-                               "<div class='mw-changeslist-empty'>\n$1\n</div>", 'recentchanges-noresult'
+                       $this->getOutput()->addHtml(
+                               '<div class="mw-changeslist-empty">' . $this->msg( 'recentchanges-noresult' )->parse() . '</div>'
                        );
                } else {
                        $this->getOutput()->addHTML( $rclistOutput );
@@ -562,6 +562,7 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                $nondefaults = $opts->getChangedValues();
 
                $panel = array();
+               $panel[] = self::makeLegend( $this->getContext() );
                $panel[] = $this->optionsPanel( $defaults, $nondefaults );
                $panel[] = '<hr />';
 
@@ -653,6 +654,55 @@ class SpecialRecentChanges extends IncludableSpecialPage {
                return $extraOpts;
        }
 
+       /**
+        * Return the legend displayed within the fieldset
+        *
+        * @param $context the object available as $this in non-static functions
+        * @return string
+        */
+       public static function makeLegend( IContextSource $context ) {
+               global $wgRecentChangesFlags;
+               $user = $context->getUser();
+               # The legend showing what the letters and stuff mean
+               $legend = Xml::openElement( 'dl', array( 'class' => 'mw-changeslist-legend' ) ) . "\n";
+               # Iterates through them and gets the messages for both letter and tooltip
+               $legendItems = $wgRecentChangesFlags;
+               if ( !$user->useRCPatrol() ) {
+                       unset( $legendItems['unpatrolled'] );
+               }
+               foreach ( $legendItems as $key => $legendInfo ) { # generate items of the legend
+                       $label = $legendInfo['title'];
+                       $letter = $legendInfo['letter'];
+                       $cssClass = isset( $legendInfo['class'] ) ? $legendInfo['class'] : $key;
+
+                       $legend .= Xml::element( 'dt',
+                               array( 'class' => $cssClass ), $context->msg( $letter )->text()
+                       ) . "\n";
+                       if ( $key === 'newpage' ) {
+                               $legend .= Xml::openElement( 'dd' );
+                               $legend .= $context->msg( $label )->escaped();
+                               $legend .= ' ' . $context->msg( 'recentchanges-legend-newpage' )->parse();
+                               $legend .= Xml::closeElement( 'dd' ) . "\n";
+                       } else {
+                               $legend .= Xml::element( 'dd', array(),
+                                       $context->msg( $label )->text()
+                               ) . "\n";
+                       }
+               }
+               # (+-123)
+               $legend .= Xml::tags( 'dt',
+                       array( 'class' => 'mw-plusminus-pos' ),
+                       $context->msg( 'recentchanges-legend-plusminus' )->parse()
+               ) . "\n";
+               $legend .= Xml::element(
+                       'dd',
+                       array( 'class' => 'mw-changeslist-legend-plusminus' ),
+                       $context->msg( 'recentchanges-label-plusminus' )->text()
+               ) . "\n";
+               $legend .= Xml::closeElement( 'dl' ) . "\n";
+               return $legend;
+       }
+
        /**
         * Send the text to be displayed above the options
         *
@@ -685,7 +735,6 @@ class SpecialRecentChanges extends IncludableSpecialPage {
        /**
         * Creates the choose namespace selection
         *
-        * @todo Uses radio buttons (HASHAR)
         * @param FormOptions $opts
         * @return string
         */
index a844704..f37ea20 100644 (file)
@@ -72,7 +72,7 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges {
                $outputPage = $this->getOutput();
                $title = Title::newFromURL( $target );
                if ( !$title || $title->getInterwiki() != '' ) {
-                       $outputPage->wrapWikiMsg( "<div class=\"errorbox\">\n$1\n</div>", 'allpagesbadtitle' );
+                       $outputPage->addHtml( '<div class="errorbox">' . $this->msg( 'allpagesbadtitle' )->parse() . '</div>' );
                        return false;
                }
 
index ef2a45d..db98bea 100644 (file)
@@ -61,6 +61,7 @@ class SpecialResetTokens extends FormSpecialPage {
        public function execute( $par ) {
                // This is a preferences page, so no user JS for y'all.
                $this->getOutput()->disallowUserJs();
+               $this->requireLogin();
 
                parent::execute( $par );
 
index 825be6c..87705a8 100644 (file)
@@ -194,6 +194,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
        protected function showConvenienceLinks() {
                # Give a link to the logs/hist for this page
                if ( $this->targetObj ) {
+                       // Also set header tabs to be for the target.
+                       $this->getSkin()->setRelevantTitle( $this->targetObj );
+
                        $links = array();
                        $links[] = Linker::linkKnown(
                                SpecialPage::getTitleFor( 'Log' ),
index 8609c74..bdcecf9 100644 (file)
@@ -88,7 +88,9 @@ class SpecialSearch extends SpecialPage {
                $this->outputHeader();
                $out = $this->getOutput();
                $out->allowClickjacking();
-               $out->addModuleStyles( 'mediawiki.special' );
+               $out->addModuleStyles( array(
+                       'mediawiki.special', 'mediawiki.special.search', 'mediawiki.ui'
+               ) );
 
                // Strip underscores from title parameter; most of the time we'll want
                // text form here. But don't strip underscores from actual text params!
@@ -105,8 +107,8 @@ class SpecialSearch extends SpecialPage {
 
                if ( $request->getVal( 'fulltext' )
                        || !is_null( $request->getVal( 'offset' ) )
-                       || !is_null( $request->getVal( 'searchx' ) ) )
-               {
+                       || !is_null( $request->getVal( 'searchx' ) )
+               {
                        $this->showResults( $search );
                } else {
                        $this->goResult( $search );
@@ -318,13 +320,12 @@ class SpecialSearch extends SpecialPage {
                        )
                );
                $out->addHtml(
-                       Xml::openElement( 'table', array( 'id' => 'mw-search-top-table', 'cellpadding' => 0, 'cellspacing' => 0 ) ) .
-                       Xml::openElement( 'tr' ) .
-                       Xml::openElement( 'td' ) . "\n" .
+                       # This is an awful awful ID name. It's not a table, but we
+                       # named it poorly from when this was a table so now we're
+                       # stuck with it
+                       Xml::openElement( 'div', array( 'id' => 'mw-search-top-table' ) ) .
                        $this->shortDialog( $term ) .
-                       Xml::closeElement( 'td' ) .
-                       Xml::closeElement( 'tr' ) .
-                       Xml::closeElement( 'table' )
+                       Xml::closeElement( 'div' )
                );
 
                // Sometimes the search engine knows there are too many hits
@@ -475,9 +476,10 @@ class SpecialSearch extends SpecialPage {
                $out = $this->getOutput();
                if ( strval( $term ) !== '' ) {
                        $out->setPageTitle( $this->msg( 'searchresults' ) );
-                       $out->setHTMLTitle( $this->msg( 'pagetitle' )->rawParams(
-                               $this->msg( 'searchresults-title' )->rawParams( $term )->text()
-                       ) );
+                       $out->setHTMLTitle( $this->msg( 'pagetitle' )
+                               ->rawParams( $this->msg( 'searchresults-title' )->rawParams( $term ) )
+                               ->inContentLanguage()->text()
+                       );
                }
                // add javascript specific to special:search
                $out->addModules( 'mediawiki.special.search' );
@@ -738,7 +740,7 @@ class SpecialSearch extends SpecialPage {
         *
         * @return string
         */
-       protected function showInterwiki( &$matches, $query ) {
+       protected function showInterwiki( $matches, $query ) {
                global $wgContLang;
                wfProfileIn( __METHOD__ );
                $terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
@@ -1094,10 +1096,14 @@ class SpecialSearch extends SpecialPage {
                $out .= Html::input( 'search', $term, 'search', array(
                        'id' => $this->profile === 'advanced' ? 'powerSearchText' : 'searchText',
                        'size' => '50',
-                       'autofocus'
+                       'autofocus',
+                       'class' => 'mw-ui-input',
                ) ) . "\n";
                $out .= Html::hidden( 'fulltext', 'Search' ) . "\n";
-               $out .= Xml::submitButton( $this->msg( 'searchbutton' )->text() ) . "\n";
+               $out .= Xml::submitButton(
+                       $this->msg( 'searchbutton' )->text(),
+                       array( 'class' => array( 'mw-ui-button', 'mw-ui-primary' ) )
+               ) . "\n";
                return $out . $this->didYouMeanHtml;
        }
 
index 47c89d0..0042b43 100644 (file)
@@ -144,6 +144,7 @@ class SpecialSpecialpages extends UnlistedSpecialPage {
                }
 
                if ( $includesRestrictedPages || $includesCachedPages ) {
+                       $out->wrapWikiMsg( "<h2 class=\"mw-specialpages-note-top\">$1</h2>", 'specialpages-note-top' );
                        $out->wrapWikiMsg( "<div class=\"mw-specialpages-notes\">\n$1\n</div>", 'specialpages-note' );
                }
        }
index ca93b6d..fbc8e91 100644 (file)
@@ -42,6 +42,11 @@ class SpecialUnblock extends SpecialPage {
 
                list( $this->target, $this->type ) = SpecialBlock::getTargetAndType( $par, $this->getRequest() );
                $this->block = Block::newFromTarget( $this->target );
+               if ( $this->target instanceof User ) {
+                       # Set the 'relevant user' in the skin, so it displays links like Contributions,
+                       # User logs, UserRights, etc.
+                       $this->getSkin()->setRelevantUser( $this->target );
+               }
 
                $this->setHeaders();
                $this->outputHeader();
index d4aed11..d33851d 100644 (file)
@@ -124,6 +124,8 @@ class PageArchive {
 
                $dbr = wfGetDB( DB_SLAVE );
 
+               $tables = array( 'archive' );
+
                $fields = array(
                        'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text',
                        'ar_comment', 'ar_len', 'ar_deleted', 'ar_rev_id', 'ar_sha1',
@@ -134,12 +136,28 @@ class PageArchive {
                        $fields[] = 'ar_content_model';
                }
 
-               $res = $dbr->select( 'archive',
+               $conds = array( 'ar_namespace' => $this->title->getNamespace(),
+                               'ar_title' => $this->title->getDBkey() );
+
+               $options = array( 'ORDER BY' => 'ar_timestamp DESC' );
+
+               $join_conds = array();
+
+               ChangeTags::modifyDisplayQuery(
+                       $tables,
                        $fields,
-                       array( 'ar_namespace' => $this->title->getNamespace(),
-                               'ar_title' => $this->title->getDBkey() ),
+                       $conds,
+                       $join_conds,
+                       $options
+               );
+
+               $res = $dbr->select( $tables,
+                       $fields,
+                       $conds,
                        __METHOD__,
-                       array( 'ORDER BY' => 'ar_timestamp DESC' ) );
+                       $options,
+                       $join_conds
+               );
 
                return $dbr->resultObject( $res );
        }
@@ -1083,6 +1101,16 @@ class SpecialUndelete extends SpecialPage {
                        $rdel = " $rdel";
                }
 
+               $minor = $rev->isMinor() ? ChangesList::flag( 'minor' ) : '';
+
+               $tags = wfGetDB( DB_SLAVE )->selectField(
+                       'tag_summary',
+                       'ts_tags',
+                       array( 'ts_rev_id' => $rev->getId() ),
+                       __METHOD__
+               );
+               $tagSummary = ChangeTags::formatSummaryRow( $tags, 'deleteddiff' );
+
                return '<div id="mw-diff-' . $prefix . 'title1"><strong>' .
                        Linker::link(
                                $targetPage,
@@ -1100,7 +1128,10 @@ class SpecialUndelete extends SpecialPage {
                        Linker::revUserTools( $rev ) . '<br />' .
                        '</div>' .
                        '<div id="mw-diff-' . $prefix . 'title3">' .
-                       Linker::revComment( $rev ) . $rdel . '<br />' .
+                       $minor . Linker::revComment( $rev ) . $rdel . '<br />' .
+                       '</div>' .
+                       '<div id="mw-diff-' . $prefix . 'title5">' .
+                       $tagSummary[0] . '<br />' .
                        '</div>';
        }
 
@@ -1367,6 +1398,9 @@ class SpecialUndelete extends SpecialPage {
                // User links
                $userLink = Linker::revUserTools( $rev );
 
+               // Minor edit
+               $minor = $rev->isMinor() ? ChangesList::flag( 'minor' ) : '';
+
                // Revision text size
                $size = $row->ar_len;
                if ( !is_null( $size ) ) {
@@ -1376,14 +1410,21 @@ class SpecialUndelete extends SpecialPage {
                // Edit summary
                $comment = Linker::revComment( $rev );
 
+               // Tags
+               $attribs = array();
+               list( $tagSummary, $classes ) = ChangeTags::formatSummaryRow( $row->ts_tags, 'deletedhistory' );
+               if ( $classes ) {
+                       $attribs['class'] = implode( ' ', $classes );
+               }
+
                // Revision delete links
                $revdlink = Linker::getRevDeleteLink( $user, $rev, $this->mTargetObj );
 
-               $revisionRow = $this->msg( 'undelete-revisionrow' )
-                       ->rawParams( $checkBox, $revdlink, $last, $pageLink, $userLink, $revTextSize, $comment )
+               $revisionRow = $this->msg( 'undelete-revision-row' )
+                       ->rawParams( $checkBox, $revdlink, $last, $pageLink, $userLink, $minor, $revTextSize, $comment, $tagSummary )
                        ->escaped();
 
-               return "<li>$revisionRow</li>";
+               return Xml::tags( 'li', $attribs, $revisionRow ) . "\n";
        }
 
        private function formatFileRow( $row ) {
index 09facf4..5e1591d 100644 (file)
@@ -60,7 +60,7 @@ class SpecialUpload extends SpecialPage {
 
        /** User input variables from the root section **/
        public $mIgnoreWarning;
-       public $mWatchThis;
+       public $mWatchthis;
        public $mCopyrightStatus;
        public $mCopyrightSource;
 
@@ -75,8 +75,6 @@ class SpecialUpload extends SpecialPage {
        public $uploadFormTextTop;
        public $uploadFormTextAfterSummary;
 
-       public $mWatchthis;
-
        /**
         * Initialize instance variables from request and create an Upload handler
         */
@@ -330,10 +328,10 @@ class SpecialUpload extends SpecialPage {
                # mDestWarningAck is set when some javascript has shown the warning
                # to the user. mForReUpload is set when the user clicks the "upload a
                # new version" link.
-               if ( !$warnings || ( count( $warnings ) == 1 &&
-                       isset( $warnings['exists'] ) &&
-                       ( $this->mDestWarningAck || $this->mForReUpload ) ) )
-               {
+               if ( !$warnings || ( count( $warnings ) == 1
+                       && isset( $warnings['exists'] )
+                       && ( $this->mDestWarningAck || $this->mForReUpload ) )
+               {
                        return false;
                }
 
@@ -517,11 +515,17 @@ class SpecialUpload extends SpecialPage {
                        return true;
                }
 
+               $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
+               if ( $desiredTitleObj instanceof Title && $this->getUser()->isWatched( $desiredTitleObj ) ) {
+                       // Already watched, don't change that
+                       return true;
+               }
+
                $local = wfLocalFile( $this->mDesiredDestName );
                if ( $local && $local->exists() ) {
                        // We're uploading a new version of an existing file.
                        // No creation, so don't watch it if we're not already.
-                       return $this->getUser()->isWatched( $local->getTitle() );
+                       return false;
                } else {
                        // New page should get watched if that's our option.
                        return $this->getUser()->getOption( 'watchcreations' );
@@ -812,7 +816,7 @@ class UploadForm extends HTMLForm {
                $this->mMaxUploadSize['file'] = UploadBase::getMaxUploadSize( 'file' );
                # Limit to upload_max_filesize unless we are running under HipHop and
                # that setting doesn't exist
-               if ( !wfIsHipHop() ) {
+               if ( !wfIsHHVM() ) {
                        $this->mMaxUploadSize['file'] = min( $this->mMaxUploadSize['file'],
                                wfShorthandToInteger( ini_get( 'upload_max_filesize' ) ),
                                wfShorthandToInteger( ini_get( 'post_max_size' ) )
@@ -1011,7 +1015,7 @@ class UploadForm extends HTMLForm {
                                        'id' => 'wpWatchthis',
                                        'label-message' => 'watchthisupload',
                                        'section' => 'options',
-                                       'default' => $user->getOption( 'watchcreations' ),
+                                       'default' => $this->mWatch,
                                )
                        );
                }
index 87b6442..1373df1 100644 (file)
@@ -308,6 +308,8 @@ class SpecialUploadStash extends UnlistedSpecialPage {
                header( "Content-Type: $contentType", true );
                header( 'Content-Transfer-Encoding: binary', true );
                header( 'Expires: Sun, 17-Jan-2038 19:14:07 GMT', true );
+               // Bug 53032 - It shouldn't be a problem here, but let's be safe and not cache
+               header( 'Cache-Control: private' );
                header( "Content-Length: $size", true );
        }
 
index 90c4c35..e701e0f 100644 (file)
@@ -106,7 +106,7 @@ class LoginForm extends SpecialPage {
                $this->mAction = $request->getVal( 'action' );
                $this->mRemember = $request->getCheck( 'wpRemember' );
                $this->mFromHTTP = $request->getBool( 'fromhttp', false );
-               $this->mStickHTTPS = ( !$this->mFromHTTP && $request->detectProtocol() === 'https' ) || $request->getBool( 'wpForceHttps', false );
+               $this->mStickHTTPS = ( !$this->mFromHTTP && $request->getProtocol() === 'https' ) || $request->getBool( 'wpForceHttps', false );
                $this->mLanguage = $request->getText( 'uselang' );
                $this->mSkipCookieCheck = $request->getCheck( 'wpSkipCookieCheck' );
                $this->mToken = ( $this->mType == 'signup' ) ? $request->getVal( 'wpCreateaccountToken' ) : $request->getVal( 'wpLoginToken' );
@@ -168,7 +168,7 @@ class LoginForm extends SpecialPage {
 
                // If logging in and not on HTTPS, either redirect to it or offer a link.
                global $wgSecureLogin;
-               if ( WebRequest::detectProtocol() !== 'https' ) {
+               if ( $this->mRequest->getProtocol() !== 'https' ) {
                        $title = $this->getFullTitle();
                        $query = array(
                                'returnto' => $this->mReturnTo,
@@ -219,10 +219,10 @@ class LoginForm extends SpecialPage {
                        return;
                }
 
-               $status = $this->addNewaccountInternal();
+               $status = $this->addNewAccountInternal();
                if ( !$status->isGood() ) {
-                       $error = $this->getOutput()->parse( $status->getWikiText() );
-                       $this->mainLoginForm( $error );
+                       $error = $status->getMessage();
+                       $this->mainLoginForm( $error->toString() );
                        return;
                }
 
@@ -257,8 +257,8 @@ class LoginForm extends SpecialPage {
                # Create the account and abort if there's a problem doing so
                $status = $this->addNewAccountInternal();
                if ( !$status->isGood() ) {
-                       $error = $this->getOutput()->parse( $status->getWikiText() );
-                       $this->mainLoginForm( $error );
+                       $error = $status->getMessage();
+                       $this->mainLoginForm( $error->toString() );
                        return false;
                }
 
@@ -447,7 +447,9 @@ class LoginForm extends SpecialPage {
                if ( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
                        // Hook point to add extra creation throttles and blocks
                        wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
-                       return Status::newFatal( new RawMessage( $abortError ) );
+                       $abortError = new RawMessage( $abortError );
+                       $abortError->text();
+                       return Status::newFatal( $abortError );
                }
 
                // Hook point to check for exempt from account creation throttle
@@ -863,7 +865,7 @@ class LoginForm extends SpecialPage {
         * @return Status object
         */
        function mailPasswordInternal( $u, $throttle = true, $emailTitle = 'passwordremindertitle', $emailText = 'passwordremindertext' ) {
-               global $wgCanonicalServer, $wgScript, $wgNewPasswordExpiry;
+               global $wgNewPasswordExpiry;
 
                if ( $u->getEmail() == '' ) {
                        return Status::newFatal( 'noemail', $u->getName() );
@@ -880,7 +882,11 @@ class LoginForm extends SpecialPage {
                $u->setNewpassword( $np, $throttle );
                $u->saveSettings();
                $userLanguage = $u->getOption( 'language' );
-               $m = $this->msg( $emailText, $ip, $u->getName(), $np, '<' . $wgCanonicalServer . $wgScript . '>',
+
+               $mainPage = Title::newMainPage();
+               $mainPageUrl = $mainPage->getCanonicalURL();
+
+               $m = $this->msg( $emailText, $ip, $u->getName(), $np, '<' . $mainPageUrl . '>',
                        round( $wgNewPasswordExpiry / 86400 ) )->inLanguage( $userLanguage )->text();
                $result = $u->sendMail( $this->msg( $emailTitle )->inLanguage( $userLanguage )->text(), $m );
 
@@ -1112,6 +1118,10 @@ class LoginForm extends SpecialPage {
                                'mediawiki.special.userlogin'
                        ) );
 
+                       $out->addModules( array(
+                               'mediawiki.special.createaccount.js'
+                       ) );
+
                        $q = 'action=submitlogin&type=login';
                        $linkq = 'type=signup';
                }
@@ -1194,7 +1204,7 @@ class LoginForm extends SpecialPage {
                $template->set( 'secureLoginUrl', $this->mSecureLoginUrl );
                // Use loginend-https for HTTPS requests if it's not blank, loginend otherwise
                // Ditto for signupend.  New forms use neither.
-               $usingHTTPS = WebRequest::detectProtocol() == 'https';
+               $usingHTTPS = $this->mRequest->getProtocol() == 'https';
                $loginendHTTPS = $this->msg( 'loginend-https' );
                $signupendHTTPS = $this->msg( 'signupend-https' );
                if ( $usingHTTPS && !$loginendHTTPS->isBlank() ) {
index 4afa279..9e93881 100644 (file)
@@ -39,20 +39,10 @@ class SpecialWatchlist extends SpecialPage {
 
                $user = $this->getUser();
                $output = $this->getOutput();
+               $output->addModuleStyles( 'mediawiki.special.changeslist' );
 
                # Anons don't get a watchlist
-               if ( $user->isAnon() ) {
-                       $output->setPageTitle( $this->msg( 'watchnologin' ) );
-                       $output->setRobotPolicy( 'noindex,nofollow' );
-                       $llink = Linker::linkKnown(
-                               SpecialPage::getTitleFor( 'Userlogin' ),
-                               $this->msg( 'loginreqlink' )->escaped(),
-                               array(),
-                               array( 'returnto' => $this->getTitle()->getPrefixedText() )
-                       );
-                       $output->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() );
-                       return;
-               }
+               $this->requireLogin( 'watchlistanontext' );
 
                // Check permissions
                $this->checkPermissions();
@@ -60,32 +50,32 @@ class SpecialWatchlist extends SpecialPage {
                // Add feed links
                $wlToken = $user->getTokenFromOption( 'watchlisttoken' );
                if ( $wlToken ) {
-                       $this->addFeedLinks( array( 'action' => 'feedwatchlist', 'allrev' => 'allrev',
-                                                               'wlowner' => $user->getName(), 'wltoken' => $wlToken ) );
+                       $this->addFeedLinks( array(
+                               'action' => 'feedwatchlist',
+                               'allrev' => 1,
+                               'wlowner' => $user->getName(),
+                               'wltoken' => $wlToken,
+                       ) );
                }
 
                $this->setHeaders();
                $this->outputHeader();
 
-               $output->addSubtitle( $this->msg( 'watchlistfor2', $user->getName()
-                       )->rawParams( SpecialEditWatchlist::buildTools( null ) ) );
+               $output->addSubtitle(
+                       $this->msg( 'watchlistfor2', $user->getName() )
+                               ->rawParams( SpecialEditWatchlist::buildTools( null ) )
+               );
 
                $request = $this->getRequest();
 
                $mode = SpecialEditWatchlist::getMode( $request, $par );
                if ( $mode !== false ) {
-                       # TODO: localise?
-                       switch ( $mode ) {
-                               case SpecialEditWatchlist::EDIT_CLEAR:
-                                       $mode = 'clear';
-                                       break;
-                               case SpecialEditWatchlist::EDIT_RAW:
-                                       $mode = 'raw';
-                                       break;
-                               default:
-                                       $mode = null;
+                       if ( $mode === SpecialEditWatchlist::EDIT_RAW ) {
+                               $title = SpecialPage::getTitleFor( 'EditWatchlist', 'raw' );
+                       } else {
+                               $title = SpecialPage::getTitleFor( 'EditWatchlist' );
                        }
-                       $title = SpecialPage::getTitleFor( 'EditWatchlist', $mode );
+
                        $output->redirect( $title->getLocalURL() );
                        return;
                }
@@ -164,9 +154,9 @@ class SpecialWatchlist extends SpecialPage {
                        wfAppendToArrayIfNotDefault( $name, $values[$name], $defaults, $nondefaults );
                }
 
-               if ( ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) && $request->getVal( 'reset' ) &&
-                       $request->wasPosted() )
-               {
+               if ( ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) && $request->getVal( 'reset' )
+                       && $request->wasPosted()
+               {
                        $user->clearAllNotifications();
                        $output->redirect( $this->getTitle()->getFullURL( $nondefaults ) );
                        return;
@@ -211,10 +201,6 @@ class SpecialWatchlist extends SpecialPage {
                        $nonRevisionTypes = array( RC_LOG );
                        wfRunHooks( 'SpecialWatchlistGetNonRevisionTypes', array( &$nonRevisionTypes ) );
                        if ( $nonRevisionTypes ) {
-                               if ( count( $nonRevisionTypes ) === 1 ) {
-                                       // if only one use an equality instead of IN condition
-                                       $nonRevisionTypes = reset( $nonRevisionTypes );
-                               }
                                $conds[] = $dbr->makeList(
                                        array(
                                                'rc_this_oldid=page_latest',
@@ -270,6 +256,8 @@ class SpecialWatchlist extends SpecialPage {
                        array( 'id' => 'mw-watchlist-options' )
                );
 
+               $form .= SpecialRecentChanges::makeLegend( $this->getContext() );
+
                $tables = array( 'recentchanges', 'watchlist' );
                $fields = RecentChange::selectFields();
                $join_conds = array(
index 0006df4..3f49ed3 100644 (file)
@@ -33,8 +33,8 @@ if ( !isset( $wgVersion ) ) {
 $matches = array();
 $ext = 'php';
 $path = '/';
-foreach( array_filter( explode( '/', $_SERVER['PHP_SELF'] ) ) as $part ) {
-       if( !preg_match( '/\.(php5?)$/', $part, $matches ) ) {
+foreach ( array_filter( explode( '/', $_SERVER['PHP_SELF'] ) ) as $part ) {
+       if ( !preg_match( '/\.(php5?)$/', $part, $matches ) ) {
                $path .= "$part/";
        } else {
                $ext = $matches[1] == 'php5' ? 'php5' : 'php';
index 4750af9..2f569d9 100644 (file)
@@ -113,17 +113,16 @@ class UsercreateTemplate extends BaseTemplate {
 
                        <?php
                        if ( $this->data['usedomain'] ) {
-                               $doms = "";
+                               $select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
+                               $select->setAttribute( 'tabindex', 4 );
                                foreach ( $this->data['domainnames'] as $dom ) {
-                                       $doms .= "<option>" . htmlspecialchars( $dom ) . "</option>";
+                                       $select->addOption( $dom );
                                }
                        ?>
                                <div id="mw-user-domain-section">
                                        <label for="wpDomain"><?php $this->msg( 'yourdomainname' ); ?></label>
                                        <div class="mw-input">
-                                               <select name="wpDomain" value="<?php $this->text( 'domain' ); ?>" tabindex="4">
-                                                       <?php echo $doms ?>
-                                               </select>
+                                               <?php echo $select->getHTML(); ?>
                                        </div>
                                </div>
                        <?php } ?>
index 5eb6094..38e071c 100644 (file)
@@ -113,16 +113,15 @@ class UserloginTemplate extends BaseTemplate {
 
                        <?php
                        if ( isset( $this->data['usedomain'] ) && $this->data['usedomain'] ) {
-                               $doms = "";
+                               $select = new XmlSelect( 'wpDomain', false, $this->data['domain'] );
+                               $select->setAttribute( 'tabindex', 3 );
                                foreach ( $this->data['domainnames'] as $dom ) {
-                                       $doms .= "<option>" . htmlspecialchars( $dom ) . "</option>";
+                                       $select->addOption( $dom );
                                }
                        ?>
                                <div id="mw-user-domain-section">
                                        <label for='wpDomain'><?php $this->msg( 'yourdomainname' ); ?></label>
-                                       <select name="wpDomain" value="<?php $this->text( 'domain' ); ?>" tabindex="3">
-                                               <?php echo $doms; ?>
-                                       </select>
+                                       <?php echo $select->getHTML(); ?>
                                </div>
                        <?php } ?>
 
index 2260241..a6c3421 100644 (file)
@@ -105,7 +105,7 @@ abstract class UploadBase {
                }
 
                # Check php's file_uploads setting
-               return wfIsHipHop() || wfIniGetBool( 'file_uploads' );
+               return wfIsHHVM() || wfIniGetBool( 'file_uploads' );
        }
 
        /**
@@ -250,7 +250,7 @@ abstract class UploadBase {
 
        /**
         * @param string $srcPath the source path
-        * @return string the real path if it was a virtual URL
+        * @return string|bool the real path if it was a virtual URL Returns false on failure
         */
        function getRealPath( $srcPath ) {
                wfProfileIn( __METHOD__ );
@@ -259,12 +259,15 @@ abstract class UploadBase {
                        // @todo just make uploads work with storage paths
                        // UploadFromStash loads files via virtual URLs
                        $tmpFile = $repo->getLocalCopy( $srcPath );
-                       $tmpFile->bind( $this ); // keep alive with $this
-                       wfProfileOut( __METHOD__ );
-                       return $tmpFile->getPath();
+                       if ( $tmpFile ) {
+                               $tmpFile->bind( $this ); // keep alive with $this
+                       }
+                       $path = $tmpFile ? $tmpFile->getPath() : false;
+               } else {
+                       $path = $srcPath;
                }
                wfProfileOut( __METHOD__ );
-               return $srcPath;
+               return $path;
        }
 
        /**
@@ -319,8 +322,8 @@ abstract class UploadBase {
 
                $error = '';
                if ( !wfRunHooks( 'UploadVerification',
-                       array( $this->mDestName, $this->mTempPath, &$error ) ) )
-               {
+                       array( $this->mDestName, $this->mTempPath, &$error ) )
+               {
                        wfProfileOut( __METHOD__ );
                        return array( 'status' => self::HOOK_ABORTED, 'error' => $error );
                }
@@ -394,7 +397,6 @@ abstract class UploadBase {
                return true;
        }
 
-
        /**
         * Verifies that it's ok to include the uploaded file
         *
@@ -421,7 +423,6 @@ abstract class UploadBase {
                        }
                }
 
-
                $handler = MediaHandler::getHandler( $mime );
                if ( $handler ) {
                        $handlerStatus = $handler->verifyUpload( $this->mTempPath );
@@ -1097,7 +1098,6 @@ abstract class UploadBase {
                return false;
        }
 
-
        /**
         * Check a whitelist of xml encodings that are known not to be interpreted differently
         * by the server's xml parser (expat) and some common browsers.
index 2e0b944..b572499 100644 (file)
  * @author Michael Dale
  */
 class UploadFromChunks extends UploadFromFile {
-       protected $mOffset, $mChunkIndex, $mFileKey, $mVirtualTempPath;
+       protected $mOffset;
+       protected $mChunkIndex;
+       protected $mFileKey;
+       protected $mVirtualTempPath;
 
        /**
         * Setup local pointers to stash, repo and user (similar to UploadFromStash)
         *
-        * @param $user User
-        * @param $stash UploadStash
-        * @param $repo FileRepo
+        * @param $user User|null Default: null
+        * @param $stash UploadStash|bool Default: false
+        * @param $repo FileRepo|bool Default: false
         */
        public function __construct( $user = null, $stash = false, $repo = false ) {
                // user object. sometimes this won't exist, as when running from cron.
@@ -108,13 +111,14 @@ class UploadFromChunks extends UploadFromFile {
         * @return FileRepoStatus
         */
        public function concatenateChunks() {
+               $chunkIndex = $this->getChunkIndex();
                wfDebug( __METHOD__ . " concatenate {$this->mChunkIndex} chunks:" .
-                       $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
+                       $this->getOffset() . ' inx:' . $chunkIndex . "\n" );
 
                // Concatenate all the chunks to mVirtualTempPath
-               $fileList = Array();
+               $fileList = array();
                // The first chunk is stored at the mVirtualTempPath path so we start on "chunk 1"
-               for ( $i = 0; $i <= $this->getChunkIndex(); $i++ ) {
+               for ( $i = 0; $i <= $chunkIndex; $i++ ) {
                        $fileList[] = $this->getVirtualChunkLocation( $i );
                }
 
@@ -122,9 +126,12 @@ class UploadFromChunks extends UploadFromFile {
                $ext = FileBackend::extensionFromPath( $this->mVirtualTempPath );
                // Get a 0-byte temp file to perform the concatenation at
                $tmpFile = TempFSFile::factory( 'chunkedupload_', $ext );
-               $tmpPath = $tmpFile
-                       ? $tmpFile->bind( $this )->getPath() // keep alive with $this
-                       : false; // fail in concatenate()
+               $tmpPath = false; // fail in concatenate()
+               if ( $tmpFile ) {
+                       // keep alive with $this
+                       $tmpPath = $tmpFile->bind( $this )->getPath();
+               }
+
                // Concatenate the chunks at the temp file
                $tStart = microtime( true );
                $status = $this->repo->concatenate( $fileList, $tmpPath, FileRepo::DELETE_SOURCE );
@@ -134,8 +141,10 @@ class UploadFromChunks extends UploadFromFile {
                }
                wfDebugLog( 'fileconcatenate', "Combined $i chunks in $tAmount seconds.\n" );
 
-               $this->mTempPath = $tmpPath; // file system path
-               $this->mFileSize = filesize( $this->mTempPath ); //Since this was set for the last chunk previously
+               // File system path
+               $this->mTempPath = $tmpPath;
+               // Since this was set for the last chunk previously
+               $this->mFileSize = filesize( $this->mTempPath );
                $ret = $this->verifyUpload();
                if ( $ret['status'] !== UploadBase::OK ) {
                        wfDebugLog( 'fileconcatenate', "Verification failed for chunked upload" );
@@ -321,7 +330,8 @@ class UploadFromChunks extends UploadFromFile {
                                        $error = array( 'unknown', 'no error recorded' );
                                }
                        }
-                       throw new UploadChunkFileException( "error storing file in '$chunkPath': " . implode( '; ', $error ) );
+                       throw new UploadChunkFileException( "Error storing file in '$chunkPath': " .
+                               implode( '; ', $error ) );
                }
                return $storeStatus;
        }
@@ -352,6 +362,11 @@ class UploadFromChunks extends UploadFromFile {
        }
 }
 
-class UploadChunkZeroLengthFileException extends MWException {};
-class UploadChunkFileException extends MWException {};
-class UploadChunkVerificationException extends MWException {};
+class UploadChunkZeroLengthFileException extends MWException {
+}
+
+class UploadChunkFileException extends MWException {
+}
+
+class UploadChunkVerificationException extends MWException {
+}
index cb85fc6..a67fc57 100644 (file)
  * @author Bryan Tong Minh
  */
 class UploadFromStash extends UploadBase {
-       protected $mFileKey, $mVirtualTempPath, $mFileProps, $mSourceType;
+       protected $mFileKey;
+       protected $mVirtualTempPath;
+       protected $mFileProps;
+       protected $mSourceType;
 
        // an instance of UploadStash
        private $stash;
@@ -37,9 +40,9 @@ class UploadFromStash extends UploadBase {
        private $repo;
 
        /**
-        * @param $user User
-        * @param $stash UploadStash
-        * @param $repo FileRepo
+        * @param User|bool $user Default: false
+        * @param UploadStash|bool $stash Default: false
+        * @param FileRepo|bool $repo Default: false
         */
        public function __construct( $user = false, $stash = false, $repo = false ) {
                // user object. sometimes this won't exist, as when running from cron.
@@ -65,7 +68,7 @@ class UploadFromStash extends UploadBase {
        }
 
        /**
-        * @param $key string
+        * @param string $key
         * @return bool
         */
        public static function isValidKey( $key ) {
@@ -74,9 +77,8 @@ class UploadFromStash extends UploadBase {
        }
 
        /**
-        * @param $request WebRequest
-        *
-        * @return Boolean
+        * @param WebRequest $request
+        * @return bool
         */
        public static function isValidRequest( $request ) {
                // this passes wpSessionKey to getText() as a default when wpFileKey isn't set.
@@ -86,8 +88,9 @@ class UploadFromStash extends UploadBase {
        }
 
        /**
-        * @param $key string
-        * @param $name string
+        * @param string $key
+        * @param string $name
+        * @param bool $initTempFile
         */
        public function initialize( $key, $name = 'upload_file', $initTempFile = true ) {
                /**
@@ -110,14 +113,17 @@ class UploadFromStash extends UploadBase {
        }
 
        /**
-        * @param $request WebRequest
+        * @param WebRequest $request
         */
        public function initializeFromRequest( &$request ) {
                // sends wpSessionKey as a default when wpFileKey is missing
                $fileKey = $request->getText( 'wpFileKey', $request->getText( 'wpSessionKey' ) );
 
                // chooses one of wpDestFile, wpUploadFile, filename in that order.
-               $desiredDestName = $request->getText( 'wpDestFile', $request->getText( 'wpUploadFile', $request->getText( 'filename' ) ) );
+               $desiredDestName = $request->getText(
+                       'wpDestFile',
+                       $request->getText( 'wpUploadFile', $request->getText( 'filename' ) )
+               );
 
                $this->initialize( $fileKey, $desiredDestName );
        }
@@ -144,7 +150,7 @@ class UploadFromStash extends UploadBase {
        /**
         * Stash the file.
         *
-        * @param $user User
+        * @param User $user
         * @return UploadStashFile
         */
        public function stashFile( User $user = null ) {
@@ -156,7 +162,7 @@ class UploadFromStash extends UploadBase {
 
        /**
         * This should return the key instead of the UploadStashFile instance, for backward compatibility.
-        * @return String
+        * @return string
         */
        public function stashSession() {
                return $this->stashFile()->getFileKey();
@@ -164,7 +170,7 @@ class UploadFromStash extends UploadBase {
 
        /**
         * Remove a temporarily kept file stashed by saveTempUploadedFile().
-        * @return bool success
+        * @return bool Success
         */
        public function unsaveUploadedFile() {
                return $this->stash->removeFile( $this->mFileKey );
@@ -172,10 +178,10 @@ class UploadFromStash extends UploadBase {
 
        /**
         * Perform the upload, then remove the database record afterward.
-        * @param $comment string
-        * @param $pageText string
-        * @param $watch bool
-        * @param $user User
+        * @param string $comment
+        * @param string $pageText
+        * @param bool $watch
+        * @param User $user
         * @return Status
         */
        public function performUpload( $comment, $pageText, $watch, $user ) {
index ebeb9c1..7db6c64 100644 (file)
@@ -358,7 +358,7 @@ class UploadStash {
                wfDebug( __METHOD__ . " clearing row $key\n" );
 
                // Ensure we have the UploadStashFile loaded for this key
-               $this->getFile( $key );
+               $this->getFile( $key, true );
 
                $dbw = $this->repo->getMasterDb();
 
diff --git a/includes/utils/ArrayUtils.php b/includes/utils/ArrayUtils.php
new file mode 100644 (file)
index 0000000..a222f81
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+
+class ArrayUtils {
+       /**
+        * Sort the given array in a pseudo-random order which depends only on the
+        * given key and each element value. This is typically used for load
+        * balancing between servers each with a local cache.
+        *
+        * Keys are preserved. The input array is modified in place.
+        *
+        * Note: Benchmarking on PHP 5.3 and 5.4 indicates that for small
+        * strings, md5() is only 10% slower than hash('joaat',...) etc.,
+        * since the function call overhead dominates. So there's not much
+        * justification for breaking compatibility with installations
+        * compiled with ./configure --disable-hash.
+        *
+        * @param array $array Array to sort
+        * @param string $key
+        * @param string $separator A separator used to delimit the array elements and the
+        *     key. This can be chosen to provide backwards compatibility with
+        *     various consistent hash implementations that existed before this
+        *     function was introduced.
+        */
+       public static function consistentHashSort( &$array, $key, $separator = "\000" ) {
+               $hashes = array();
+               foreach ( $array as $elt ) {
+                       $hashes[$elt] = md5( $elt . $separator . $key );
+               }
+               uasort( $array, function ( $a, $b ) use ( $hashes ) {
+                       return strcmp( $hashes[$a], $hashes[$b] );
+               } );
+       }
+
+       /**
+        * Given an array of non-normalised probabilities, this function will select
+        * an element and return the appropriate key
+        *
+        * @param array $weights
+        * @return bool|int|string
+        */
+       public static function pickRandom( $weights ) {
+               if ( !is_array( $weights ) || count( $weights ) == 0 ) {
+                       return false;
+               }
+
+               $sum = array_sum( $weights );
+               if ( $sum == 0 ) {
+                       # No loads on any of them
+                       # In previous versions, this triggered an unweighted random selection,
+                       # but this feature has been removed as of April 2006 to allow for strict
+                       # separation of query groups.
+                       return false;
+               }
+               $max = mt_getrandmax();
+               $rand = mt_rand( 0, $max ) / $max * $sum;
+
+               $sum = 0;
+               foreach ( $weights as $i => $w ) {
+                       $sum += $w;
+                       # Do not return keys if they have 0 weight.
+                       # Note that the "all 0 weight" case is handed above
+                       if ( $w > 0 && $sum >= $rand ) {
+                               break;
+                       }
+               }
+
+               return $i;
+       }
+}
diff --git a/includes/utils/Cdb.php b/includes/utils/Cdb.php
new file mode 100644 (file)
index 0000000..f556ee7
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+/**
+ * Native CDB file reader and writer.
+ *
+ * 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
+ */
+
+/**
+ * Read from a CDB file.
+ * Native and pure PHP implementations are provided.
+ * http://cr.yp.to/cdb.html
+ */
+abstract class CdbReader {
+       /**
+        * The file handle
+        */
+       protected $handle;
+
+       /**
+        * Open a file and return a subclass instance
+        *
+        * @param $fileName string
+        *
+        * @return CdbReader
+        */
+       public static function open( $fileName ) {
+               return self::haveExtension() ?
+                       new CdbReaderDBA( $fileName ) :
+                       new CdbReaderPHP( $fileName );
+       }
+
+       /**
+        * Returns true if the native extension is available
+        *
+        * @return bool
+        */
+       public static function haveExtension() {
+               if ( !function_exists( 'dba_handlers' ) ) {
+                       return false;
+               }
+               $handlers = dba_handlers();
+               if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * Create the object and open the file
+        *
+        * @param $fileName string
+        */
+       abstract public function __construct( $fileName );
+
+       /**
+        * Close the file. Optional, you can just let the variable go out of scope.
+        */
+       abstract public function close();
+
+       /**
+        * Get a value with a given key. Only string values are supported.
+        *
+        * @param $key string
+        */
+       abstract public function get( $key );
+}
+
+/**
+ * Write to a CDB file.
+ * Native and pure PHP implementations are provided.
+ */
+abstract class CdbWriter {
+       /**
+        * The file handle
+        */
+       protected $handle;
+
+       /**
+        * File we'll be writing to when we're done
+        * @var string
+        */
+       protected $realFileName;
+
+       /**
+        * File we write to temporarily until we're done
+        * @var string
+        */
+       protected $tmpFileName;
+
+       /**
+        * Open a writer and return a subclass instance.
+        * The user must have write access to the directory, for temporary file creation.
+        *
+        * @param $fileName string
+        *
+        * @return CdbWriterDBA|CdbWriterPHP
+        */
+       public static function open( $fileName ) {
+               return CdbReader::haveExtension() ?
+                       new CdbWriterDBA( $fileName ) :
+                       new CdbWriterPHP( $fileName );
+       }
+
+       /**
+        * Create the object and open the file
+        *
+        * @param $fileName string
+        */
+       abstract public function __construct( $fileName );
+
+       /**
+        * Set a key to a given value. The value will be converted to string.
+        * @param $key string
+        * @param $value string
+        */
+       abstract public function set( $key, $value );
+
+       /**
+        * Close the writer object. You should call this function before the object
+        * goes out of scope, to write out the final hashtables.
+        */
+       abstract public function close();
+
+       /**
+        * If the object goes out of scope, close it for sanity
+        */
+       public function __destruct() {
+               if ( isset( $this->handle ) ) {
+                       $this->close();
+               }
+       }
+
+       /**
+        * Are we running on Windows?
+        */
+       protected function isWindows() {
+               return substr( php_uname(), 0, 7 ) == 'Windows';
+       }
+}
+
+/**
+ * Exception for Cdb errors.
+ * This explicitly doesn't subclass MWException to encourage reuse.
+ */
+class CdbException extends Exception {}
diff --git a/includes/utils/CdbDBA.php b/includes/utils/CdbDBA.php
new file mode 100644 (file)
index 0000000..efcaf21
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * DBA-based CDB reader/writer
+ *
+ * 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
+ */
+
+/**
+ * Reader class which uses the DBA extension
+ */
+class CdbReaderDBA extends CdbReader {
+       public function __construct( $fileName ) {
+               $this->handle = dba_open( $fileName, 'r-', 'cdb' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file "' . $fileName . '"' );
+               }
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       dba_close( $this->handle );
+               }
+               unset( $this->handle );
+       }
+
+       public function get( $key ) {
+               return dba_fetch( $key, $this->handle );
+       }
+}
+
+/**
+ * Writer class which uses the DBA extension
+ */
+class CdbWriterDBA extends CdbWriter {
+       public function __construct( $fileName ) {
+               $this->realFileName = $fileName;
+               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
+               $this->handle = dba_open( $this->tmpFileName, 'n', 'cdb_make' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file for write "' . $fileName . '"' );
+               }
+       }
+
+       public function set( $key, $value ) {
+               return dba_insert( $key, $value, $this->handle );
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       dba_close( $this->handle );
+               }
+               if ( $this->isWindows() ) {
+                       unlink( $this->realFileName );
+               }
+               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
+                       throw new CdbException( 'Unable to move the new CDB file into place.' );
+               }
+               unset( $this->handle );
+       }
+}
diff --git a/includes/utils/CdbPHP.php b/includes/utils/CdbPHP.php
new file mode 100644 (file)
index 0000000..c178ffe
--- /dev/null
@@ -0,0 +1,491 @@
+<?php
+/**
+ * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
+ * appears in PHP 5.3. Changes are:
+ *    * Error returns replaced with exceptions
+ *    * Exception thrown if sizes or offsets are between 2GB and 4GB
+ *    * Some variables renamed
+ *
+ * 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
+ */
+
+/**
+ * Common functions for readers and writers
+ */
+class CdbFunctions {
+       /**
+        * Take a modulo of a signed integer as if it were an unsigned integer.
+        * $b must be less than 0x40000000 and greater than 0
+        *
+        * @param $a
+        * @param $b
+        *
+        * @return int
+        */
+       public static function unsignedMod( $a, $b ) {
+               if ( $a & 0x80000000 ) {
+                       $m = ( $a & 0x7fffffff ) % $b + 2 * ( 0x40000000 % $b );
+
+                       return $m % $b;
+               } else {
+                       return $a % $b;
+               }
+       }
+
+       /**
+        * Shift a signed integer right as if it were unsigned
+        * @param $a
+        * @param $b
+        * @return int
+        */
+       public static function unsignedShiftRight( $a, $b ) {
+               if ( $b == 0 ) {
+                       return $a;
+               }
+               if ( $a & 0x80000000 ) {
+                       return ( ( $a & 0x7fffffff ) >> $b ) | ( 0x40000000 >> ( $b - 1 ) );
+               } else {
+                       return $a >> $b;
+               }
+       }
+
+       /**
+        * The CDB hash function.
+        *
+        * @param $s string
+        *
+        * @return int
+        */
+       public static function hash( $s ) {
+               $h = 5381;
+               $len = strlen( $s );
+               for ( $i = 0; $i < $len; $i++ ) {
+                       $h5 = ( $h << 5 ) & 0xffffffff;
+                       // Do a 32-bit sum
+                       // Inlined here for speed
+                       $sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff );
+                       $h =
+                               (
+                                       ( $sum & 0x40000000 ? 1 : 0 )
+                                       + ( $h & 0x80000000 ? 2 : 0 )
+                                       + ( $h & 0x40000000 ? 1 : 0 )
+                                       + ( $h5 & 0x80000000 ? 2 : 0 )
+                                       + ( $h5 & 0x40000000 ? 1 : 0 )
+                               ) << 30
+                               | ( $sum & 0x3fffffff );
+                       $h ^= ord( $s[$i] );
+                       $h &= 0xffffffff;
+               }
+
+               return $h;
+       }
+}
+
+/**
+ * CDB reader class
+ */
+class CdbReaderPHP extends CdbReader {
+       /** The filename */
+       var $fileName;
+
+       /* number of hash slots searched under this key */
+       var $loop;
+
+       /* initialized if loop is nonzero */
+       var $khash;
+
+       /* initialized if loop is nonzero */
+       var $kpos;
+
+       /* initialized if loop is nonzero */
+       var $hpos;
+
+       /* initialized if loop is nonzero */
+       var $hslots;
+
+       /* initialized if findNext() returns true */
+       var $dpos;
+
+       /* initialized if cdb_findnext() returns 1 */
+       var $dlen;
+
+       /**
+        * @param $fileName string
+        * @throws CdbException
+        */
+       public function __construct( $fileName ) {
+               $this->fileName = $fileName;
+               $this->handle = fopen( $fileName, 'rb' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file "' . $this->fileName . '".' );
+               }
+               $this->findStart();
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       fclose( $this->handle );
+               }
+               unset( $this->handle );
+       }
+
+       /**
+        * @param $key
+        * @return bool|string
+        */
+       public function get( $key ) {
+               // strval is required
+               if ( $this->find( strval( $key ) ) ) {
+                       return $this->read( $this->dlen, $this->dpos );
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * @param $key
+        * @param $pos
+        * @return bool
+        */
+       protected function match( $key, $pos ) {
+               $buf = $this->read( strlen( $key ), $pos );
+
+               return $buf === $key;
+       }
+
+       protected function findStart() {
+               $this->loop = 0;
+       }
+
+       /**
+        * @throws CdbException
+        * @param $length
+        * @param $pos
+        * @return string
+        */
+       protected function read( $length, $pos ) {
+               if ( fseek( $this->handle, $pos ) == -1 ) {
+                       // This can easily happen if the internal pointers are incorrect
+                       throw new CdbException(
+                               'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
+               }
+
+               if ( $length == 0 ) {
+                       return '';
+               }
+
+               $buf = fread( $this->handle, $length );
+               if ( $buf === false || strlen( $buf ) !== $length ) {
+                       throw new CdbException(
+                               'Read from CDB file failed, file "' . $this->fileName . '" may be corrupted.' );
+               }
+
+               return $buf;
+       }
+
+       /**
+        * Unpack an unsigned integer and throw an exception if it needs more than 31 bits
+        * @param $s
+        * @throws CdbException
+        * @return mixed
+        */
+       protected function unpack31( $s ) {
+               $data = unpack( 'V', $s );
+               if ( $data[1] > 0x7fffffff ) {
+                       throw new CdbException(
+                               'Error in CDB file "' . $this->fileName . '", integer too big.' );
+               }
+
+               return $data[1];
+       }
+
+       /**
+        * Unpack a 32-bit signed integer
+        * @param $s
+        * @return int
+        */
+       protected function unpackSigned( $s ) {
+               $data = unpack( 'va/vb', $s );
+
+               return $data['a'] | ( $data['b'] << 16 );
+       }
+
+       /**
+        * @param $key
+        * @return bool
+        */
+       protected function findNext( $key ) {
+               if ( !$this->loop ) {
+                       $u = CdbFunctions::hash( $key );
+                       $buf = $this->read( 8, ( $u << 3 ) & 2047 );
+                       $this->hslots = $this->unpack31( substr( $buf, 4 ) );
+                       if ( !$this->hslots ) {
+                               return false;
+                       }
+                       $this->hpos = $this->unpack31( substr( $buf, 0, 4 ) );
+                       $this->khash = $u;
+                       $u = CdbFunctions::unsignedShiftRight( $u, 8 );
+                       $u = CdbFunctions::unsignedMod( $u, $this->hslots );
+                       $u <<= 3;
+                       $this->kpos = $this->hpos + $u;
+               }
+
+               while ( $this->loop < $this->hslots ) {
+                       $buf = $this->read( 8, $this->kpos );
+                       $pos = $this->unpack31( substr( $buf, 4 ) );
+                       if ( !$pos ) {
+                               return false;
+                       }
+                       $this->loop += 1;
+                       $this->kpos += 8;
+                       if ( $this->kpos == $this->hpos + ( $this->hslots << 3 ) ) {
+                               $this->kpos = $this->hpos;
+                       }
+                       $u = $this->unpackSigned( substr( $buf, 0, 4 ) );
+                       if ( $u === $this->khash ) {
+                               $buf = $this->read( 8, $pos );
+                               $keyLen = $this->unpack31( substr( $buf, 0, 4 ) );
+                               if ( $keyLen == strlen( $key ) && $this->match( $key, $pos + 8 ) ) {
+                                       // Found
+                                       $this->dlen = $this->unpack31( substr( $buf, 4 ) );
+                                       $this->dpos = $pos + 8 + $keyLen;
+
+                                       return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * @param $key
+        * @return bool
+        */
+       protected function find( $key ) {
+               $this->findStart();
+
+               return $this->findNext( $key );
+       }
+}
+
+/**
+ * CDB writer class
+ */
+class CdbWriterPHP extends CdbWriter {
+       var $hplist;
+       var $numentries, $pos;
+
+       /**
+        * @param $fileName string
+        */
+       public function __construct( $fileName ) {
+               $this->realFileName = $fileName;
+               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
+               $this->handle = fopen( $this->tmpFileName, 'wb' );
+               if ( !$this->handle ) {
+                       $this->throwException(
+                               'Unable to open CDB file "' . $this->tmpFileName . '" for write.' );
+               }
+               $this->hplist = array();
+               $this->numentries = 0;
+               $this->pos = 2048; // leaving space for the pointer array, 256 * 8
+               if ( fseek( $this->handle, $this->pos ) == -1 ) {
+                       $this->throwException( 'fseek failed in file "' . $this->tmpFileName . '".' );
+               }
+       }
+
+       /**
+        * @param string $key
+        * @param string $value
+        */
+       public function set( $key, $value ) {
+               if ( strval( $key ) === '' ) {
+                       // DBA cross-check hack
+                       return;
+               }
+               $this->addbegin( strlen( $key ), strlen( $value ) );
+               $this->write( $key );
+               $this->write( $value );
+               $this->addend( strlen( $key ), strlen( $value ), CdbFunctions::hash( $key ) );
+       }
+
+       /**
+        * @throws CdbException
+        */
+       public function close() {
+               $this->finish();
+               if ( isset( $this->handle ) ) {
+                       fclose( $this->handle );
+               }
+               if ( $this->isWindows() && file_exists( $this->realFileName ) ) {
+                       unlink( $this->realFileName );
+               }
+               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
+                       $this->throwException( 'Unable to move the new CDB file into place.' );
+               }
+               unset( $this->handle );
+       }
+
+       /**
+        * @throws CdbException
+        * @param $buf
+        */
+       protected function write( $buf ) {
+               $len = fwrite( $this->handle, $buf );
+               if ( $len !== strlen( $buf ) ) {
+                       $this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
+               }
+       }
+
+       /**
+        * @throws CdbException
+        * @param $len
+        */
+       protected function posplus( $len ) {
+               $newpos = $this->pos + $len;
+               if ( $newpos > 0x7fffffff ) {
+                       $this->throwException(
+                               'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
+               }
+               $this->pos = $newpos;
+       }
+
+       /**
+        * @param $keylen
+        * @param $datalen
+        * @param $h
+        */
+       protected function addend( $keylen, $datalen, $h ) {
+               $this->hplist[] = array(
+                       'h' => $h,
+                       'p' => $this->pos
+               );
+
+               $this->numentries++;
+               $this->posplus( 8 );
+               $this->posplus( $keylen );
+               $this->posplus( $datalen );
+       }
+
+       /**
+        * @throws CdbException
+        * @param $keylen
+        * @param $datalen
+        */
+       protected function addbegin( $keylen, $datalen ) {
+               if ( $keylen > 0x7fffffff ) {
+                       $this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
+               }
+               if ( $datalen > 0x7fffffff ) {
+                       $this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
+               }
+               $buf = pack( 'VV', $keylen, $datalen );
+               $this->write( $buf );
+       }
+
+       /**
+        * @throws CdbException
+        */
+       protected function finish() {
+               // Hack for DBA cross-check
+               $this->hplist = array_reverse( $this->hplist );
+
+               // Calculate the number of items that will be in each hashtable
+               $counts = array_fill( 0, 256, 0 );
+               foreach ( $this->hplist as $item ) {
+                       ++$counts[255 & $item['h']];
+               }
+
+               // Fill in $starts with the *end* indexes
+               $starts = array();
+               $pos = 0;
+               for ( $i = 0; $i < 256; ++$i ) {
+                       $pos += $counts[$i];
+                       $starts[$i] = $pos;
+               }
+
+               // Excessively clever and indulgent code to simultaneously fill $packedTables
+               // with the packed hashtables, and adjust the elements of $starts
+               // to actually point to the starts instead of the ends.
+               $packedTables = array_fill( 0, $this->numentries, false );
+               foreach ( $this->hplist as $item ) {
+                       $packedTables[--$starts[255 & $item['h']]] = $item;
+               }
+
+               $final = '';
+               for ( $i = 0; $i < 256; ++$i ) {
+                       $count = $counts[$i];
+
+                       // The size of the hashtable will be double the item count.
+                       // The rest of the slots will be empty.
+                       $len = $count + $count;
+                       $final .= pack( 'VV', $this->pos, $len );
+
+                       $hashtable = array();
+                       for ( $u = 0; $u < $len; ++$u ) {
+                               $hashtable[$u] = array( 'h' => 0, 'p' => 0 );
+                       }
+
+                       // Fill the hashtable, using the next empty slot if the hashed slot
+                       // is taken.
+                       for ( $u = 0; $u < $count; ++$u ) {
+                               $hp = $packedTables[$starts[$i] + $u];
+                               $where = CdbFunctions::unsignedMod(
+                                       CdbFunctions::unsignedShiftRight( $hp['h'], 8 ), $len );
+                               while ( $hashtable[$where]['p'] ) {
+                                       if ( ++$where == $len ) {
+                                               $where = 0;
+                                       }
+                               }
+                               $hashtable[$where] = $hp;
+                       }
+
+                       // Write the hashtable
+                       for ( $u = 0; $u < $len; ++$u ) {
+                               $buf = pack( 'vvV',
+                                       $hashtable[$u]['h'] & 0xffff,
+                                       CdbFunctions::unsignedShiftRight( $hashtable[$u]['h'], 16 ),
+                                       $hashtable[$u]['p'] );
+                               $this->write( $buf );
+                               $this->posplus( 8 );
+                       }
+               }
+
+               // Write the pointer array at the start of the file
+               rewind( $this->handle );
+               if ( ftell( $this->handle ) != 0 ) {
+                       $this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
+               }
+               $this->write( $final );
+       }
+
+       /**
+        * Clean up the temp file and throw an exception
+        *
+        * @param $msg string
+        * @throws CdbException
+        */
+       protected function throwException( $msg ) {
+               if ( $this->handle ) {
+                       fclose( $this->handle );
+                       unlink( $this->tmpFileName );
+               }
+               throw new CdbException( $msg );
+       }
+}
diff --git a/includes/utils/ConfEditor.php b/includes/utils/ConfEditor.php
new file mode 100644 (file)
index 0000000..a2fe507
--- /dev/null
@@ -0,0 +1,1125 @@
+<?php
+/**
+ * Configuration file editor.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * This is a state machine style parser with two internal stacks:
+ *   * A next state stack, which determines the state the machine will progress to next
+ *   * A path stack, which keeps track of the logical location in the file.
+ *
+ * Reference grammar:
+ *
+ * file = T_OPEN_TAG *statement
+ * statement = T_VARIABLE "=" expression ";"
+ * expression = array / scalar / T_VARIABLE
+ * array = T_ARRAY "(" [ element *( "," element ) [ "," ] ] ")"
+ * element = assoc-element / expression
+ * assoc-element = scalar T_DOUBLE_ARROW expression
+ * scalar = T_LNUMBER / T_DNUMBER / T_STRING / T_CONSTANT_ENCAPSED_STRING
+ */
+class ConfEditor {
+       /** The text to parse */
+       var $text;
+
+       /** The token array from token_get_all() */
+       var $tokens;
+
+       /** The current position in the token array */
+       var $pos;
+
+       /** The current 1-based line number */
+       var $lineNum;
+
+       /** The current 1-based column number */
+       var $colNum;
+
+       /** The current 0-based byte number */
+       var $byteNum;
+
+       /** The current ConfEditorToken object */
+       var $currentToken;
+
+       /** The previous ConfEditorToken object */
+       var $prevToken;
+
+       /**
+        * The state machine stack. This is an array of strings where the topmost
+        * element will be popped off and become the next parser state.
+        */
+       var $stateStack;
+
+       /**
+        * The path stack is a stack of associative arrays with the following elements:
+        *    name              The name of top level of the path
+        *    level             The level (number of elements) of the path
+        *    startByte         The byte offset of the start of the path
+        *    startToken        The token offset of the start
+        *    endByte           The byte offset of thee
+        *    endToken          The token offset of the end, plus one
+        *    valueStartToken   The start token offset of the value part
+        *    valueStartByte    The start byte offset of the value part
+        *    valueEndToken     The end token offset of the value part, plus one
+        *    valueEndByte      The end byte offset of the value part, plus one
+        *    nextArrayIndex    The next numeric array index at this level
+        *    hasComma          True if the array element ends with a comma
+        *    arrowByte         The byte offset of the "=>", or false if there isn't one
+        */
+       var $pathStack;
+
+       /**
+        * The elements of the top of the pathStack for every path encountered, indexed
+        * by slash-separated path.
+        */
+       var $pathInfo;
+
+       /**
+        * Next serial number for whitespace placeholder paths (\@extra-N)
+        */
+       var $serial;
+
+       /**
+        * Editor state. This consists of the internal copy/insert operations which
+        * are applied to the source string to obtain the destination string.
+        */
+       var $edits;
+
+       /**
+        * Simple entry point for command-line testing
+        *
+        * @param $text string
+        *
+        * @return string
+        */
+       static function test( $text ) {
+               try {
+                       $ce = new self( $text );
+                       $ce->parse();
+               } catch ( ConfEditorParseError $e ) {
+                       return $e->getMessage() . "\n" . $e->highlight( $text );
+               }
+
+               return "OK";
+       }
+
+       /**
+        * Construct a new parser
+        */
+       public function __construct( $text ) {
+               $this->text = $text;
+       }
+
+       /**
+        * Edit the text. Returns the edited text.
+        * @param array $ops of operations.
+        *
+        * Operations are given as an associative array, with members:
+        *    type:     One of delete, set, append or insert (required)
+        *    path:     The path to operate on (required)
+        *    key:      The array key to insert/append, with PHP quotes
+        *    value:    The value, with PHP quotes
+        *
+        * delete
+        *    Deletes an array element or statement with the specified path.
+        *    e.g.
+        *        array('type' => 'delete', 'path' => '$foo/bar/baz' )
+        *    is equivalent to the runtime PHP code:
+        *        unset( $foo['bar']['baz'] );
+        *
+        * set
+        *    Sets the value of an array element. If the element doesn't exist, it
+        *    is appended to the array. If it does exist, the value is set, with
+        *    comments and indenting preserved.
+        *
+        * append
+        *    Appends a new element to the end of the array. Adds a trailing comma.
+        *    e.g.
+        *        array( 'type' => 'append', 'path', '$foo/bar',
+        *            'key' => 'baz', 'value' => "'x'" )
+        *    is like the PHP code:
+        *        $foo['bar']['baz'] = 'x';
+        *
+        * insert
+        *    Insert a new element at the start of the array.
+        *
+        * @throws MWException
+        * @return string
+        */
+       public function edit( $ops ) {
+               $this->parse();
+
+               $this->edits = array(
+                       array( 'copy', 0, strlen( $this->text ) )
+               );
+               foreach ( $ops as $op ) {
+                       $type = $op['type'];
+                       $path = $op['path'];
+                       $value = isset( $op['value'] ) ? $op['value'] : null;
+                       $key = isset( $op['key'] ) ? $op['key'] : null;
+
+                       switch ( $type ) {
+                               case 'delete':
+                                       list( $start, $end ) = $this->findDeletionRegion( $path );
+                                       $this->replaceSourceRegion( $start, $end, false );
+                                       break;
+                               case 'set':
+                                       if ( isset( $this->pathInfo[$path] ) ) {
+                                               list( $start, $end ) = $this->findValueRegion( $path );
+                                               $encValue = $value; // var_export( $value, true );
+                                               $this->replaceSourceRegion( $start, $end, $encValue );
+                                               break;
+                                       }
+                                       // No existing path, fall through to append
+                                       $slashPos = strrpos( $path, '/' );
+                                       $key = var_export( substr( $path, $slashPos + 1 ), true );
+                                       $path = substr( $path, 0, $slashPos );
+                                       // Fall through
+                               case 'append':
+                                       // Find the last array element
+                                       $lastEltPath = $this->findLastArrayElement( $path );
+                                       if ( $lastEltPath === false ) {
+                                               throw new MWException( "Can't find any element of array \"$path\"" );
+                                       }
+                                       $lastEltInfo = $this->pathInfo[$lastEltPath];
+
+                                       // Has it got a comma already?
+                                       if ( strpos( $lastEltPath, '@extra' ) === false && !$lastEltInfo['hasComma'] ) {
+                                               // No comma, insert one after the value region
+                                               list( , $end ) = $this->findValueRegion( $lastEltPath );
+                                               $this->replaceSourceRegion( $end - 1, $end - 1, ',' );
+                                       }
+
+                                       // Make the text to insert
+                                       list( $start, $end ) = $this->findDeletionRegion( $lastEltPath );
+
+                                       if ( $key === null ) {
+                                               list( $indent, ) = $this->getIndent( $start );
+                                               $textToInsert = "$indent$value,";
+                                       } else {
+                                               list( $indent, $arrowIndent ) =
+                                                       $this->getIndent( $start, $key, $lastEltInfo['arrowByte'] );
+                                               $textToInsert = "$indent$key$arrowIndent=> $value,";
+                                       }
+                                       $textToInsert .= ( $indent === false ? ' ' : "\n" );
+
+                                       // Insert the item
+                                       $this->replaceSourceRegion( $end, $end, $textToInsert );
+                                       break;
+                               case 'insert':
+                                       // Find first array element
+                                       $firstEltPath = $this->findFirstArrayElement( $path );
+                                       if ( $firstEltPath === false ) {
+                                               throw new MWException( "Can't find array element of \"$path\"" );
+                                       }
+                                       list( $start, ) = $this->findDeletionRegion( $firstEltPath );
+                                       $info = $this->pathInfo[$firstEltPath];
+
+                                       // Make the text to insert
+                                       if ( $key === null ) {
+                                               list( $indent, ) = $this->getIndent( $start );
+                                               $textToInsert = "$indent$value,";
+                                       } else {
+                                               list( $indent, $arrowIndent ) =
+                                                       $this->getIndent( $start, $key, $info['arrowByte'] );
+                                               $textToInsert = "$indent$key$arrowIndent=> $value,";
+                                       }
+                                       $textToInsert .= ( $indent === false ? ' ' : "\n" );
+
+                                       // Insert the item
+                                       $this->replaceSourceRegion( $start, $start, $textToInsert );
+                                       break;
+                               default:
+                                       throw new MWException( "Unrecognised operation: \"$type\"" );
+                       }
+               }
+
+               // Do the edits
+               $out = '';
+               foreach ( $this->edits as $edit ) {
+                       if ( $edit[0] == 'copy' ) {
+                               $out .= substr( $this->text, $edit[1], $edit[2] - $edit[1] );
+                       } else { // if ( $edit[0] == 'insert' )
+                               $out .= $edit[1];
+                       }
+               }
+
+               // Do a second parse as a sanity check
+               $this->text = $out;
+               try {
+                       $this->parse();
+               } catch ( ConfEditorParseError $e ) {
+                       throw new MWException(
+                               "Sorry, ConfEditor broke the file during editing and it won't parse anymore: " .
+                               $e->getMessage() );
+               }
+
+               return $out;
+       }
+
+       /**
+        * Get the variables defined in the text
+        * @return array( varname => value )
+        */
+       function getVars() {
+               $vars = array();
+               $this->parse();
+               foreach ( $this->pathInfo as $path => $data ) {
+                       if ( $path[0] != '$' ) {
+                               continue;
+                       }
+                       $trimmedPath = substr( $path, 1 );
+                       $name = $data['name'];
+                       if ( $name[0] == '@' ) {
+                               continue;
+                       }
+                       if ( $name[0] == '$' ) {
+                               $name = substr( $name, 1 );
+                       }
+                       $parentPath = substr( $trimmedPath, 0,
+                               strlen( $trimmedPath ) - strlen( $name ) );
+                       if ( substr( $parentPath, -1 ) == '/' ) {
+                               $parentPath = substr( $parentPath, 0, -1 );
+                       }
+
+                       $value = substr( $this->text, $data['valueStartByte'],
+                               $data['valueEndByte'] - $data['valueStartByte']
+                       );
+                       $this->setVar( $vars, $parentPath, $name,
+                               $this->parseScalar( $value ) );
+               }
+
+               return $vars;
+       }
+
+       /**
+        * Set a value in an array, unless it's set already. For instance,
+        * setVar( $arr, 'foo/bar', 'baz', 3 ); will set
+        * $arr['foo']['bar']['baz'] = 3;
+        * @param $array array
+        * @param string $path slash-delimited path
+        * @param $key mixed Key
+        * @param $value mixed Value
+        */
+       function setVar( &$array, $path, $key, $value ) {
+               $pathArr = explode( '/', $path );
+               $target =& $array;
+               if ( $path !== '' ) {
+                       foreach ( $pathArr as $p ) {
+                               if ( !isset( $target[$p] ) ) {
+                                       $target[$p] = array();
+                               }
+                               $target =& $target[$p];
+                       }
+               }
+               if ( !isset( $target[$key] ) ) {
+                       $target[$key] = $value;
+               }
+       }
+
+       /**
+        * Parse a scalar value in PHP
+        * @return mixed Parsed value
+        */
+       function parseScalar( $str ) {
+               if ( $str !== '' && $str[0] == '\'' ) {
+                       // Single-quoted string
+                       // @todo FIXME: trim() call is due to mystery bug where whitespace gets
+                       // appended to the token; without it we ended up reading in the
+                       // extra quote on the end!
+                       return strtr( substr( trim( $str ), 1, -1 ),
+                               array( '\\\'' => '\'', '\\\\' => '\\' ) );
+               }
+               if ( $str !== '' && $str[0] == '"' ) {
+                       // Double-quoted string
+                       // @todo FIXME: trim() call is due to mystery bug where whitespace gets
+                       // appended to the token; without it we ended up reading in the
+                       // extra quote on the end!
+                       return stripcslashes( substr( trim( $str ), 1, -1 ) );
+               }
+               if ( substr( $str, 0, 4 ) == 'true' ) {
+                       return true;
+               }
+               if ( substr( $str, 0, 5 ) == 'false' ) {
+                       return false;
+               }
+               if ( substr( $str, 0, 4 ) == 'null' ) {
+                       return null;
+               }
+
+               // Must be some kind of numeric value, so let PHP's weak typing
+               // be useful for a change
+               return $str;
+       }
+
+       /**
+        * Replace the byte offset region of the source with $newText.
+        * Works by adding elements to the $this->edits array.
+        */
+       function replaceSourceRegion( $start, $end, $newText = false ) {
+               // Split all copy operations with a source corresponding to the region
+               // in question.
+               $newEdits = array();
+               foreach ( $this->edits as $edit ) {
+                       if ( $edit[0] !== 'copy' ) {
+                               $newEdits[] = $edit;
+                               continue;
+                       }
+                       $copyStart = $edit[1];
+                       $copyEnd = $edit[2];
+                       if ( $start >= $copyEnd || $end <= $copyStart ) {
+                               // Outside this region
+                               $newEdits[] = $edit;
+                               continue;
+                       }
+                       if ( ( $start < $copyStart && $end > $copyStart )
+                               || ( $start < $copyEnd && $end > $copyEnd )
+                       ) {
+                               throw new MWException( "Overlapping regions found, can't do the edit" );
+                       }
+                       // Split the copy
+                       $newEdits[] = array( 'copy', $copyStart, $start );
+                       if ( $newText !== false ) {
+                               $newEdits[] = array( 'insert', $newText );
+                       }
+                       $newEdits[] = array( 'copy', $end, $copyEnd );
+               }
+               $this->edits = $newEdits;
+       }
+
+       /**
+        * Finds the source byte region which you would want to delete, if $pathName
+        * was to be deleted. Includes the leading spaces and tabs, the trailing line
+        * break, and any comments in between.
+        * @param $pathName
+        * @throws MWException
+        * @return array
+        */
+       function findDeletionRegion( $pathName ) {
+               if ( !isset( $this->pathInfo[$pathName] ) ) {
+                       throw new MWException( "Can't find path \"$pathName\"" );
+               }
+               $path = $this->pathInfo[$pathName];
+               // Find the start
+               $this->firstToken();
+               while ( $this->pos != $path['startToken'] ) {
+                       $this->nextToken();
+               }
+               $regionStart = $path['startByte'];
+               for ( $offset = -1; $offset >= -$this->pos; $offset-- ) {
+                       $token = $this->getTokenAhead( $offset );
+                       if ( !$token->isSkip() ) {
+                               // If there is other content on the same line, don't move the start point
+                               // back, because that will cause the regions to overlap.
+                               $regionStart = $path['startByte'];
+                               break;
+                       }
+                       $lfPos = strrpos( $token->text, "\n" );
+                       if ( $lfPos === false ) {
+                               $regionStart -= strlen( $token->text );
+                       } else {
+                               // The line start does not include the LF
+                               $regionStart -= strlen( $token->text ) - $lfPos - 1;
+                               break;
+                       }
+               }
+               // Find the end
+               while ( $this->pos != $path['endToken'] ) {
+                       $this->nextToken();
+               }
+               $regionEnd = $path['endByte']; // past the end
+               $count = count( $this->tokens );
+               for ( $offset = 0; $offset < $count - $this->pos; $offset++ ) {
+                       $token = $this->getTokenAhead( $offset );
+                       if ( !$token->isSkip() ) {
+                               break;
+                       }
+                       $lfPos = strpos( $token->text, "\n" );
+                       if ( $lfPos === false ) {
+                               $regionEnd += strlen( $token->text );
+                       } else {
+                               // This should point past the LF
+                               $regionEnd += $lfPos + 1;
+                               break;
+                       }
+               }
+
+               return array( $regionStart, $regionEnd );
+       }
+
+       /**
+        * Find the byte region in the source corresponding to the value part.
+        * This includes the quotes, but does not include the trailing comma
+        * or semicolon.
+        *
+        * The end position is the past-the-end (end + 1) value as per convention.
+        * @param $pathName
+        * @throws MWException
+        * @return array
+        */
+       function findValueRegion( $pathName ) {
+               if ( !isset( $this->pathInfo[$pathName] ) ) {
+                       throw new MWException( "Can't find path \"$pathName\"" );
+               }
+               $path = $this->pathInfo[$pathName];
+               if ( $path['valueStartByte'] === false || $path['valueEndByte'] === false ) {
+                       throw new MWException( "Can't find value region for path \"$pathName\"" );
+               }
+
+               return array( $path['valueStartByte'], $path['valueEndByte'] );
+       }
+
+       /**
+        * Find the path name of the last element in the array.
+        * If the array is empty, this will return the \@extra interstitial element.
+        * If the specified path is not found or is not an array, it will return false.
+        * @return bool|int|string
+        */
+       function findLastArrayElement( $path ) {
+               // Try for a real element
+               $lastEltPath = false;
+               foreach ( $this->pathInfo as $candidatePath => $info ) {
+                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
+                       $part2 = substr( $candidatePath, strlen( $path ) + 1, 1 );
+                       if ( $part2 == '@' ) {
+                               // Do nothing
+                       } elseif ( $part1 == "$path/" ) {
+                               $lastEltPath = $candidatePath;
+                       } elseif ( $lastEltPath !== false ) {
+                               break;
+                       }
+               }
+               if ( $lastEltPath !== false ) {
+                       return $lastEltPath;
+               }
+
+               // Try for an interstitial element
+               $extraPath = false;
+               foreach ( $this->pathInfo as $candidatePath => $info ) {
+                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
+                       if ( $part1 == "$path/" ) {
+                               $extraPath = $candidatePath;
+                       } elseif ( $extraPath !== false ) {
+                               break;
+                       }
+               }
+
+               return $extraPath;
+       }
+
+       /**
+        * Find the path name of first element in the array.
+        * If the array is empty, this will return the \@extra interstitial element.
+        * If the specified path is not found or is not an array, it will return false.
+        * @return bool|int|string
+        */
+       function findFirstArrayElement( $path ) {
+               // Try for an ordinary element
+               foreach ( $this->pathInfo as $candidatePath => $info ) {
+                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
+                       $part2 = substr( $candidatePath, strlen( $path ) + 1, 1 );
+                       if ( $part1 == "$path/" && $part2 != '@' ) {
+                               return $candidatePath;
+                       }
+               }
+
+               // Try for an interstitial element
+               foreach ( $this->pathInfo as $candidatePath => $info ) {
+                       $part1 = substr( $candidatePath, 0, strlen( $path ) + 1 );
+                       if ( $part1 == "$path/" ) {
+                               return $candidatePath;
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Get the indent string which sits after a given start position.
+        * Returns false if the position is not at the start of the line.
+        * @return array
+        */
+       function getIndent( $pos, $key = false, $arrowPos = false ) {
+               $arrowIndent = ' ';
+               if ( $pos == 0 || $this->text[$pos - 1] == "\n" ) {
+                       $indentLength = strspn( $this->text, " \t", $pos );
+                       $indent = substr( $this->text, $pos, $indentLength );
+               } else {
+                       $indent = false;
+               }
+               if ( $indent !== false && $arrowPos !== false ) {
+                       $arrowIndentLength = $arrowPos - $pos - $indentLength - strlen( $key );
+                       if ( $arrowIndentLength > 0 ) {
+                               $arrowIndent = str_repeat( ' ', $arrowIndentLength );
+                       }
+               }
+
+               return array( $indent, $arrowIndent );
+       }
+
+       /**
+        * Run the parser on the text. Throws an exception if the string does not
+        * match our defined subset of PHP syntax.
+        */
+       public function parse() {
+               $this->initParse();
+               $this->pushState( 'file' );
+               $this->pushPath( '@extra-' . ( $this->serial++ ) );
+               $token = $this->firstToken();
+
+               while ( !$token->isEnd() ) {
+                       $state = $this->popState();
+                       if ( !$state ) {
+                               $this->error( 'internal error: empty state stack' );
+                       }
+
+                       switch ( $state ) {
+                               case 'file':
+                                       $this->expect( T_OPEN_TAG );
+                                       $token = $this->skipSpace();
+                                       if ( $token->isEnd() ) {
+                                               break 2;
+                                       }
+                                       $this->pushState( 'statement', 'file 2' );
+                                       break;
+                               case 'file 2':
+                                       $token = $this->skipSpace();
+                                       if ( $token->isEnd() ) {
+                                               break 2;
+                                       }
+                                       $this->pushState( 'statement', 'file 2' );
+                                       break;
+                               case 'statement':
+                                       $token = $this->skipSpace();
+                                       if ( !$this->validatePath( $token->text ) ) {
+                                               $this->error( "Invalid variable name \"{$token->text}\"" );
+                                       }
+                                       $this->nextPath( $token->text );
+                                       $this->expect( T_VARIABLE );
+                                       $this->skipSpace();
+                                       $arrayAssign = false;
+                                       if ( $this->currentToken()->type == '[' ) {
+                                               $this->nextToken();
+                                               $token = $this->skipSpace();
+                                               if ( !$token->isScalar() ) {
+                                                       $this->error( "expected a string or number for the array key" );
+                                               }
+                                               if ( $token->type == T_CONSTANT_ENCAPSED_STRING ) {
+                                                       $text = $this->parseScalar( $token->text );
+                                               } else {
+                                                       $text = $token->text;
+                                               }
+                                               if ( !$this->validatePath( $text ) ) {
+                                                       $this->error( "Invalid associative array name \"$text\"" );
+                                               }
+                                               $this->pushPath( $text );
+                                               $this->nextToken();
+                                               $this->skipSpace();
+                                               $this->expect( ']' );
+                                               $this->skipSpace();
+                                               $arrayAssign = true;
+                                       }
+                                       $this->expect( '=' );
+                                       $this->skipSpace();
+                                       $this->startPathValue();
+                                       if ( $arrayAssign ) {
+                                               $this->pushState( 'expression', 'array assign end' );
+                                       } else {
+                                               $this->pushState( 'expression', 'statement end' );
+                                       }
+                                       break;
+                               case 'array assign end':
+                               case 'statement end':
+                                       $this->endPathValue();
+                                       if ( $state == 'array assign end' ) {
+                                               $this->popPath();
+                                       }
+                                       $this->skipSpace();
+                                       $this->expect( ';' );
+                                       $this->nextPath( '@extra-' . ( $this->serial++ ) );
+                                       break;
+                               case 'expression':
+                                       $token = $this->skipSpace();
+                                       if ( $token->type == T_ARRAY ) {
+                                               $this->pushState( 'array' );
+                                       } elseif ( $token->isScalar() ) {
+                                               $this->nextToken();
+                                       } elseif ( $token->type == T_VARIABLE ) {
+                                               $this->nextToken();
+                                       } else {
+                                               $this->error( "expected simple expression" );
+                                       }
+                                       break;
+                               case 'array':
+                                       $this->skipSpace();
+                                       $this->expect( T_ARRAY );
+                                       $this->skipSpace();
+                                       $this->expect( '(' );
+                                       $this->skipSpace();
+                                       $this->pushPath( '@extra-' . ( $this->serial++ ) );
+                                       if ( $this->isAhead( ')' ) ) {
+                                               // Empty array
+                                               $this->pushState( 'array end' );
+                                       } else {
+                                               $this->pushState( 'element', 'array end' );
+                                       }
+                                       break;
+                               case 'array end':
+                                       $this->skipSpace();
+                                       $this->popPath();
+                                       $this->expect( ')' );
+                                       break;
+                               case 'element':
+                                       $token = $this->skipSpace();
+                                       // Look ahead to find the double arrow
+                                       if ( $token->isScalar() && $this->isAhead( T_DOUBLE_ARROW, 1 ) ) {
+                                               // Found associative element
+                                               $this->pushState( 'assoc-element', 'element end' );
+                                       } else {
+                                               // Not associative
+                                               $this->nextPath( '@next' );
+                                               $this->startPathValue();
+                                               $this->pushState( 'expression', 'element end' );
+                                       }
+                                       break;
+                               case 'element end':
+                                       $token = $this->skipSpace();
+                                       if ( $token->type == ',' ) {
+                                               $this->endPathValue();
+                                               $this->markComma();
+                                               $this->nextToken();
+                                               $this->nextPath( '@extra-' . ( $this->serial++ ) );
+                                               // Look ahead to find ending bracket
+                                               if ( $this->isAhead( ")" ) ) {
+                                                       // Found ending bracket, no continuation
+                                                       $this->skipSpace();
+                                               } else {
+                                                       // No ending bracket, continue to next element
+                                                       $this->pushState( 'element' );
+                                               }
+                                       } elseif ( $token->type == ')' ) {
+                                               // End array
+                                               $this->endPathValue();
+                                       } else {
+                                               $this->error( "expected the next array element or the end of the array" );
+                                       }
+                                       break;
+                               case 'assoc-element':
+                                       $token = $this->skipSpace();
+                                       if ( !$token->isScalar() ) {
+                                               $this->error( "expected a string or number for the array key" );
+                                       }
+                                       if ( $token->type == T_CONSTANT_ENCAPSED_STRING ) {
+                                               $text = $this->parseScalar( $token->text );
+                                       } else {
+                                               $text = $token->text;
+                                       }
+                                       if ( !$this->validatePath( $text ) ) {
+                                               $this->error( "Invalid associative array name \"$text\"" );
+                                       }
+                                       $this->nextPath( $text );
+                                       $this->nextToken();
+                                       $this->skipSpace();
+                                       $this->markArrow();
+                                       $this->expect( T_DOUBLE_ARROW );
+                                       $this->skipSpace();
+                                       $this->startPathValue();
+                                       $this->pushState( 'expression' );
+                                       break;
+                       }
+               }
+               if ( count( $this->stateStack ) ) {
+                       $this->error( 'unexpected end of file' );
+               }
+               $this->popPath();
+       }
+
+       /**
+        * Initialise a parse.
+        */
+       protected function initParse() {
+               $this->tokens = token_get_all( $this->text );
+               $this->stateStack = array();
+               $this->pathStack = array();
+               $this->firstToken();
+               $this->pathInfo = array();
+               $this->serial = 1;
+       }
+
+       /**
+        * Set the parse position. Do not call this except from firstToken() and
+        * nextToken(), there is more to update than just the position.
+        */
+       protected function setPos( $pos ) {
+               $this->pos = $pos;
+               if ( $this->pos >= count( $this->tokens ) ) {
+                       $this->currentToken = ConfEditorToken::newEnd();
+               } else {
+                       $this->currentToken = $this->newTokenObj( $this->tokens[$this->pos] );
+               }
+
+               return $this->currentToken;
+       }
+
+       /**
+        * Create a ConfEditorToken from an element of token_get_all()
+        * @return ConfEditorToken
+        */
+       function newTokenObj( $internalToken ) {
+               if ( is_array( $internalToken ) ) {
+                       return new ConfEditorToken( $internalToken[0], $internalToken[1] );
+               } else {
+                       return new ConfEditorToken( $internalToken, $internalToken );
+               }
+       }
+
+       /**
+        * Reset the parse position
+        */
+       function firstToken() {
+               $this->setPos( 0 );
+               $this->prevToken = ConfEditorToken::newEnd();
+               $this->lineNum = 1;
+               $this->colNum = 1;
+               $this->byteNum = 0;
+
+               return $this->currentToken;
+       }
+
+       /**
+        * Get the current token
+        */
+       function currentToken() {
+               return $this->currentToken;
+       }
+
+       /**
+        * Advance the current position and return the resulting next token
+        */
+       function nextToken() {
+               if ( $this->currentToken ) {
+                       $text = $this->currentToken->text;
+                       $lfCount = substr_count( $text, "\n" );
+                       if ( $lfCount ) {
+                               $this->lineNum += $lfCount;
+                               $this->colNum = strlen( $text ) - strrpos( $text, "\n" );
+                       } else {
+                               $this->colNum += strlen( $text );
+                       }
+                       $this->byteNum += strlen( $text );
+               }
+               $this->prevToken = $this->currentToken;
+               $this->setPos( $this->pos + 1 );
+
+               return $this->currentToken;
+       }
+
+       /**
+        * Get the token $offset steps ahead of the current position.
+        * $offset may be negative, to get tokens behind the current position.
+        * @return ConfEditorToken
+        */
+       function getTokenAhead( $offset ) {
+               $pos = $this->pos + $offset;
+               if ( $pos >= count( $this->tokens ) || $pos < 0 ) {
+                       return ConfEditorToken::newEnd();
+               } else {
+                       return $this->newTokenObj( $this->tokens[$pos] );
+               }
+       }
+
+       /**
+        * Advances the current position past any whitespace or comments
+        */
+       function skipSpace() {
+               while ( $this->currentToken && $this->currentToken->isSkip() ) {
+                       $this->nextToken();
+               }
+
+               return $this->currentToken;
+       }
+
+       /**
+        * Throws an error if the current token is not of the given type, and
+        * then advances to the next position.
+        */
+       function expect( $type ) {
+               if ( $this->currentToken && $this->currentToken->type == $type ) {
+                       return $this->nextToken();
+               } else {
+                       $this->error( "expected " . $this->getTypeName( $type ) .
+                               ", got " . $this->getTypeName( $this->currentToken->type ) );
+               }
+       }
+
+       /**
+        * Push a state or two on to the state stack.
+        */
+       function pushState( $nextState, $stateAfterThat = null ) {
+               if ( $stateAfterThat !== null ) {
+                       $this->stateStack[] = $stateAfterThat;
+               }
+               $this->stateStack[] = $nextState;
+       }
+
+       /**
+        * Pop a state from the state stack.
+        * @return mixed
+        */
+       function popState() {
+               return array_pop( $this->stateStack );
+       }
+
+       /**
+        * Returns true if the user input path is valid.
+        * This exists to allow "/" and "@" to be reserved for string path keys
+        * @return bool
+        */
+       function validatePath( $path ) {
+               return strpos( $path, '/' ) === false && substr( $path, 0, 1 ) != '@';
+       }
+
+       /**
+        * Internal function to update some things at the end of a path region. Do
+        * not call except from popPath() or nextPath().
+        */
+       function endPath() {
+               $key = '';
+               foreach ( $this->pathStack as $pathInfo ) {
+                       if ( $key !== '' ) {
+                               $key .= '/';
+                       }
+                       $key .= $pathInfo['name'];
+               }
+               $pathInfo['endByte'] = $this->byteNum;
+               $pathInfo['endToken'] = $this->pos;
+               $this->pathInfo[$key] = $pathInfo;
+       }
+
+       /**
+        * Go up to a new path level, for example at the start of an array.
+        */
+       function pushPath( $path ) {
+               $this->pathStack[] = array(
+                       'name' => $path,
+                       'level' => count( $this->pathStack ) + 1,
+                       'startByte' => $this->byteNum,
+                       'startToken' => $this->pos,
+                       'valueStartToken' => false,
+                       'valueStartByte' => false,
+                       'valueEndToken' => false,
+                       'valueEndByte' => false,
+                       'nextArrayIndex' => 0,
+                       'hasComma' => false,
+                       'arrowByte' => false
+               );
+       }
+
+       /**
+        * Go down a path level, for example at the end of an array.
+        */
+       function popPath() {
+               $this->endPath();
+               array_pop( $this->pathStack );
+       }
+
+       /**
+        * Go to the next path on the same level. This ends the current path and
+        * starts a new one. If $path is \@next, the new path is set to the next
+        * numeric array element.
+        */
+       function nextPath( $path ) {
+               $this->endPath();
+               $i = count( $this->pathStack ) - 1;
+               if ( $path == '@next' ) {
+                       $nextArrayIndex =& $this->pathStack[$i]['nextArrayIndex'];
+                       $this->pathStack[$i]['name'] = $nextArrayIndex;
+                       $nextArrayIndex++;
+               } else {
+                       $this->pathStack[$i]['name'] = $path;
+               }
+               $this->pathStack[$i] =
+                       array(
+                               'startByte' => $this->byteNum,
+                               'startToken' => $this->pos,
+                               'valueStartToken' => false,
+                               'valueStartByte' => false,
+                               'valueEndToken' => false,
+                               'valueEndByte' => false,
+                               'hasComma' => false,
+                               'arrowByte' => false,
+                       ) + $this->pathStack[$i];
+       }
+
+       /**
+        * Mark the start of the value part of a path.
+        */
+       function startPathValue() {
+               $path =& $this->pathStack[count( $this->pathStack ) - 1];
+               $path['valueStartToken'] = $this->pos;
+               $path['valueStartByte'] = $this->byteNum;
+       }
+
+       /**
+        * Mark the end of the value part of a path.
+        */
+       function endPathValue() {
+               $path =& $this->pathStack[count( $this->pathStack ) - 1];
+               $path['valueEndToken'] = $this->pos;
+               $path['valueEndByte'] = $this->byteNum;
+       }
+
+       /**
+        * Mark the comma separator in an array element
+        */
+       function markComma() {
+               $path =& $this->pathStack[count( $this->pathStack ) - 1];
+               $path['hasComma'] = true;
+       }
+
+       /**
+        * Mark the arrow separator in an associative array element
+        */
+       function markArrow() {
+               $path =& $this->pathStack[count( $this->pathStack ) - 1];
+               $path['arrowByte'] = $this->byteNum;
+       }
+
+       /**
+        * Generate a parse error
+        */
+       function error( $msg ) {
+               throw new ConfEditorParseError( $this, $msg );
+       }
+
+       /**
+        * Get a readable name for the given token type.
+        * @return string
+        */
+       function getTypeName( $type ) {
+               if ( is_int( $type ) ) {
+                       return token_name( $type );
+               } else {
+                       return "\"$type\"";
+               }
+       }
+
+       /**
+        * Looks ahead to see if the given type is the next token type, starting
+        * from the current position plus the given offset. Skips any intervening
+        * whitespace.
+        * @return bool
+        */
+       function isAhead( $type, $offset = 0 ) {
+               $ahead = $offset;
+               $token = $this->getTokenAhead( $offset );
+               while ( !$token->isEnd() ) {
+                       if ( $token->isSkip() ) {
+                               $ahead++;
+                               $token = $this->getTokenAhead( $ahead );
+                               continue;
+                       } elseif ( $token->type == $type ) {
+                               // Found the type
+                               return true;
+                       } else {
+                               // Not found
+                               return false;
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Get the previous token object
+        */
+       function prevToken() {
+               return $this->prevToken;
+       }
+
+       /**
+        * Echo a reasonably readable representation of the tokenizer array.
+        */
+       function dumpTokens() {
+               $out = '';
+               foreach ( $this->tokens as $token ) {
+                       $obj = $this->newTokenObj( $token );
+                       $out .= sprintf( "%-28s %s\n",
+                               $this->getTypeName( $obj->type ),
+                               addcslashes( $obj->text, "\0..\37" ) );
+               }
+               echo "<pre>" . htmlspecialchars( $out ) . "</pre>";
+       }
+}
+
+/**
+ * Exception class for parse errors
+ */
+class ConfEditorParseError extends MWException {
+       var $lineNum, $colNum;
+
+       function __construct( $editor, $msg ) {
+               $this->lineNum = $editor->lineNum;
+               $this->colNum = $editor->colNum;
+               parent::__construct( "Parse error on line {$editor->lineNum} " .
+                       "col {$editor->colNum}: $msg" );
+       }
+
+       function highlight( $text ) {
+               $lines = StringUtils::explode( "\n", $text );
+               foreach ( $lines as $lineNum => $line ) {
+                       if ( $lineNum == $this->lineNum - 1 ) {
+                               return "$line\n" . str_repeat( ' ', $this->colNum - 1 ) . "^\n";
+                       }
+               }
+
+               return '';
+       }
+}
+
+/**
+ * Class to wrap a token from the tokenizer.
+ */
+class ConfEditorToken {
+       var $type, $text;
+
+       static $scalarTypes = array( T_LNUMBER, T_DNUMBER, T_STRING, T_CONSTANT_ENCAPSED_STRING );
+       static $skipTypes = array( T_WHITESPACE, T_COMMENT, T_DOC_COMMENT );
+
+       static function newEnd() {
+               return new self( 'END', '' );
+       }
+
+       function __construct( $type, $text ) {
+               $this->type = $type;
+               $this->text = $text;
+       }
+
+       function isSkip() {
+               return in_array( $this->type, self::$skipTypes );
+       }
+
+       function isScalar() {
+               return in_array( $this->type, self::$scalarTypes );
+       }
+
+       function isEnd() {
+               return $this->type == 'END';
+       }
+}
diff --git a/includes/utils/HashRing.php b/includes/utils/HashRing.php
new file mode 100644 (file)
index 0000000..c152d41
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Convenience class for weighted consistent hash rings.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Convenience class for weighted consistent hash rings
+ *
+ * @since 1.22
+ */
+class HashRing {
+       /** @var Array (location => weight) */
+       protected $sourceMap = array();
+       /** @var Array (location => (start, end)) */
+       protected $ring = array();
+
+       const RING_SIZE = 268435456; // 2^28
+
+       /**
+        * @param array $map (location => weight)
+        */
+       public function __construct( array $map ) {
+               $map = array_filter( $map, function ( $w ) {
+                       return $w > 0;
+               } );
+               if ( !count( $map ) ) {
+                       throw new MWException( "Ring is empty or all weights are zero." );
+               }
+               $this->sourceMap = $map;
+               // Sort the locations based on the hash of their names
+               $hashes = array();
+               foreach ( $map as $location => $weight ) {
+                       $hashes[$location] = sha1( $location );
+               }
+               uksort( $map, function ( $a, $b ) use ( $hashes ) {
+                       return strcmp( $hashes[$a], $hashes[$b] );
+               } );
+               // Fit the map to weight-proportionate one with a space of size RING_SIZE
+               $sum = array_sum( $map );
+               $standardMap = array();
+               foreach ( $map as $location => $weight ) {
+                       $standardMap[$location] = (int)floor( $weight / $sum * self::RING_SIZE );
+               }
+               // Build a ring of RING_SIZE spots, with each location at a spot in location hash order
+               $index = 0;
+               foreach ( $standardMap as $location => $weight ) {
+                       // Location covers half-closed interval [$index,$index + $weight)
+                       $this->ring[$location] = array( $index, $index + $weight );
+                       $index += $weight;
+               }
+               // Make sure the last location covers what is left
+               end( $this->ring );
+               $this->ring[key( $this->ring )][1] = self::RING_SIZE;
+       }
+
+       /**
+        * Get the location of an item on the ring
+        *
+        * @param string $item
+        * @return string Location
+        */
+       public function getLocation( $item ) {
+               $locations = $this->getLocations( $item, 1 );
+
+               return $locations[0];
+       }
+
+       /**
+        * Get the location of an item on the ring, as well as the next clockwise locations
+        *
+        * @param string $item
+        * @param integer $limit Maximum number of locations to return
+        * @return array List of locations
+        */
+       public function getLocations( $item, $limit ) {
+               $locations = array();
+               $primaryLocation = null;
+               $spot = hexdec( substr( sha1( $item ), 0, 7 ) ); // first 28 bits
+               foreach ( $this->ring as $location => $range ) {
+                       if ( count( $locations ) >= $limit ) {
+                               break;
+                       }
+                       // The $primaryLocation is the location the item spot is in.
+                       // After that is reached, keep appending the next locations.
+                       if ( ( $range[0] <= $spot && $spot < $range[1] ) || $primaryLocation !== null ) {
+                               if ( $primaryLocation === null ) {
+                                       $primaryLocation = $location;
+                               }
+                               $locations[] = $location;
+                       }
+               }
+               // If more locations are requested, wrap-around and keep adding them
+               reset( $this->ring );
+               while ( count( $locations ) < $limit ) {
+                       list( $location, ) = each( $this->ring );
+                       if ( $location === $primaryLocation ) {
+                               break; // don't go in circles
+                       }
+                       $locations[] = $location;
+               }
+
+               return $locations;
+       }
+
+       /**
+        * Get the map of locations to weight (ignores 0-weight items)
+        *
+        * @return array
+        */
+       public function getLocationWeights() {
+               return $this->sourceMap;
+       }
+
+       /**
+        * Get a new hash ring with a location removed from the ring
+        *
+        * @param string $location
+        * @return HashRing|bool Returns false if no non-zero weighted spots are left
+        */
+       public function newWithoutLocation( $location ) {
+               $map = $this->sourceMap;
+               unset( $map[$location] );
+               if ( count( $map ) ) {
+                       return new self( $map );
+               }
+
+               return false;
+       }
+}
diff --git a/includes/utils/IP.php b/includes/utils/IP.php
new file mode 100644 (file)
index 0000000..002dcd9
--- /dev/null
@@ -0,0 +1,775 @@
+<?php
+/**
+ * Functions and constants to play with IP addresses and ranges
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Antoine Musso "<hashar at free dot fr>", Aaron Schulz
+ */
+
+// Some regex definition to "play" with IP address and IP address blocks
+
+// An IPv4 address is made of 4 bytes from x00 to xFF which is d0 to d255
+define( 'RE_IP_BYTE', '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])' );
+define( 'RE_IP_ADD', RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE . '\.' . RE_IP_BYTE );
+// An IPv4 block is an IP address and a prefix (d1 to d32)
+define( 'RE_IP_PREFIX', '(3[0-2]|[12]?\d)' );
+define( 'RE_IP_BLOCK', RE_IP_ADD . '\/' . RE_IP_PREFIX );
+
+// An IPv6 address is made up of 8 words (each x0000 to xFFFF).
+// However, the "::" abbreviation can be used on consecutive x0000 words.
+define( 'RE_IPV6_WORD', '([0-9A-Fa-f]{1,4})' );
+define( 'RE_IPV6_PREFIX', '(12[0-8]|1[01][0-9]|[1-9]?\d)' );
+define( 'RE_IPV6_ADD',
+       '(?:' . // starts with "::" (including "::")
+               ':(?::|(?::' . RE_IPV6_WORD . '){1,7})' .
+       '|' . // ends with "::" (except "::")
+               RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){0,6}::' .
+       '|' . // contains one "::" in the middle (the ^ makes the test fail if none found)
+               RE_IPV6_WORD . '(?::((?(-1)|:))?' . RE_IPV6_WORD . '){1,6}(?(-2)|^)' .
+       '|' . // contains no "::"
+               RE_IPV6_WORD . '(?::' . RE_IPV6_WORD . '){7}' .
+       ')'
+);
+// An IPv6 block is an IP address and a prefix (d1 to d128)
+define( 'RE_IPV6_BLOCK', RE_IPV6_ADD . '\/' . RE_IPV6_PREFIX );
+// For IPv6 canonicalization (NOT for strict validation; these are quite lax!)
+define( 'RE_IPV6_GAP', ':(?:0+:)*(?::(?:0+:)*)?' );
+define( 'RE_IPV6_V4_PREFIX', '0*' . RE_IPV6_GAP . '(?:ffff:)?' );
+
+// This might be useful for regexps used elsewhere, matches any IPv6 or IPv6 address or network
+define( 'IP_ADDRESS_STRING',
+       '(?:' .
+               RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?' . // IPv4
+       '|' .
+               RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?' . // IPv6
+       ')'
+);
+
+/**
+ * A collection of public static functions to play with IP address
+ * and IP blocks.
+ */
+class IP {
+       /**
+        * Determine if a string is as valid IP address or network (CIDR prefix).
+        * SIIT IPv4-translated addresses are rejected.
+        * Note: canonicalize() tries to convert translated addresses to IPv4.
+        *
+        * @param string $ip possible IP address
+        * @return Boolean
+        */
+       public static function isIPAddress( $ip ) {
+               return (bool)preg_match( '/^' . IP_ADDRESS_STRING . '$/', $ip );
+       }
+
+       /**
+        * Given a string, determine if it as valid IP in IPv6 only.
+        * Note: Unlike isValid(), this looks for networks too.
+        *
+        * @param string $ip possible IP address
+        * @return Boolean
+        */
+       public static function isIPv6( $ip ) {
+               return (bool)preg_match( '/^' . RE_IPV6_ADD . '(?:\/' . RE_IPV6_PREFIX . ')?$/', $ip );
+       }
+
+       /**
+        * Given a string, determine if it as valid IP in IPv4 only.
+        * Note: Unlike isValid(), this looks for networks too.
+        *
+        * @param string $ip possible IP address
+        * @return Boolean
+        */
+       public static function isIPv4( $ip ) {
+               return (bool)preg_match( '/^' . RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?$/', $ip );
+       }
+
+       /**
+        * Validate an IP address. Ranges are NOT considered valid.
+        * SIIT IPv4-translated addresses are rejected.
+        * Note: canonicalize() tries to convert translated addresses to IPv4.
+        *
+        * @param $ip String
+        * @return Boolean: True if it is valid.
+        */
+       public static function isValid( $ip ) {
+               return ( preg_match( '/^' . RE_IP_ADD . '$/', $ip )
+                       || preg_match( '/^' . RE_IPV6_ADD . '$/', $ip ) );
+       }
+
+       /**
+        * Validate an IP Block (valid address WITH a valid prefix).
+        * SIIT IPv4-translated addresses are rejected.
+        * Note: canonicalize() tries to convert translated addresses to IPv4.
+        *
+        * @param $ipblock String
+        * @return Boolean: True if it is valid.
+        */
+       public static function isValidBlock( $ipblock ) {
+               return ( preg_match( '/^' . RE_IPV6_BLOCK . '$/', $ipblock )
+                       || preg_match( '/^' . RE_IP_BLOCK . '$/', $ipblock ) );
+       }
+
+       /**
+        * Convert an IP into a verbose, uppercase, normalized form.
+        * IPv6 addresses in octet notation are expanded to 8 words.
+        * IPv4 addresses are just trimmed.
+        *
+        * @param string $ip IP address in quad or octet form (CIDR or not).
+        * @return String
+        */
+       public static function sanitizeIP( $ip ) {
+               $ip = trim( $ip );
+               if ( $ip === '' ) {
+                       return null;
+               }
+               if ( self::isIPv4( $ip ) || !self::isIPv6( $ip ) ) {
+                       return $ip; // nothing else to do for IPv4 addresses or invalid ones
+               }
+               // Remove any whitespaces, convert to upper case
+               $ip = strtoupper( $ip );
+               // Expand zero abbreviations
+               $abbrevPos = strpos( $ip, '::' );
+               if ( $abbrevPos !== false ) {
+                       // We know this is valid IPv6. Find the last index of the
+                       // address before any CIDR number (e.g. "a:b:c::/24").
+                       $CIDRStart = strpos( $ip, "/" );
+                       $addressEnd = ( $CIDRStart !== false )
+                               ? $CIDRStart - 1
+                               : strlen( $ip ) - 1;
+                       // If the '::' is at the beginning...
+                       if ( $abbrevPos == 0 ) {
+                               $repeat = '0:';
+                               $extra = ( $ip == '::' ) ? '0' : ''; // for the address '::'
+                               $pad = 9; // 7+2 (due to '::')
+                       // If the '::' is at the end...
+                       } elseif ( $abbrevPos == ( $addressEnd - 1 ) ) {
+                               $repeat = ':0';
+                               $extra = '';
+                               $pad = 9; // 7+2 (due to '::')
+                       // If the '::' is in the middle...
+                       } else {
+                               $repeat = ':0';
+                               $extra = ':';
+                               $pad = 8; // 6+2 (due to '::')
+                       }
+                       $ip = str_replace( '::',
+                               str_repeat( $repeat, $pad - substr_count( $ip, ':' ) ) . $extra,
+                               $ip
+                       );
+               }
+               // Remove leading zeros from each bloc as needed
+               $ip = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip );
+
+               return $ip;
+       }
+
+       /**
+        * Prettify an IP for display to end users.
+        * This will make it more compact and lower-case.
+        *
+        * @param $ip string
+        * @return string
+        */
+       public static function prettifyIP( $ip ) {
+               $ip = self::sanitizeIP( $ip ); // normalize (removes '::')
+               if ( self::isIPv6( $ip ) ) {
+                       // Split IP into an address and a CIDR
+                       if ( strpos( $ip, '/' ) !== false ) {
+                               list( $ip, $cidr ) = explode( '/', $ip, 2 );
+                       } else {
+                               list( $ip, $cidr ) = array( $ip, '' );
+                       }
+                       // Get the largest slice of words with multiple zeros
+                       $offset = 0;
+                       $longest = $longestPos = false;
+                       while ( preg_match(
+                               '!(?:^|:)0(?::0)+(?:$|:)!', $ip, $m, PREG_OFFSET_CAPTURE, $offset
+                       ) ) {
+                               list( $match, $pos ) = $m[0]; // full match
+                               if ( strlen( $match ) > strlen( $longest ) ) {
+                                       $longest = $match;
+                                       $longestPos = $pos;
+                               }
+                               $offset = ( $pos + strlen( $match ) ); // advance
+                       }
+                       if ( $longest !== false ) {
+                               // Replace this portion of the string with the '::' abbreviation
+                               $ip = substr_replace( $ip, '::', $longestPos, strlen( $longest ) );
+                       }
+                       // Add any CIDR back on
+                       if ( $cidr !== '' ) {
+                               $ip = "{$ip}/{$cidr}";
+                       }
+                       // Convert to lower case to make it more readable
+                       $ip = strtolower( $ip );
+               }
+
+               return $ip;
+       }
+
+       /**
+        * Given a host/port string, like one might find in the host part of a URL
+        * per RFC 2732, split the hostname part and the port part and return an
+        * array with an element for each. If there is no port part, the array will
+        * have false in place of the port. If the string was invalid in some way,
+        * false is returned.
+        *
+        * This was easy with IPv4 and was generally done in an ad-hoc way, but
+        * with IPv6 it's somewhat more complicated due to the need to parse the
+        * square brackets and colons.
+        *
+        * A bare IPv6 address is accepted despite the lack of square brackets.
+        *
+        * @param string $both The string with the host and port
+        * @return array
+        */
+       public static function splitHostAndPort( $both ) {
+               if ( substr( $both, 0, 1 ) === '[' ) {
+                       if ( preg_match( '/^\[(' . RE_IPV6_ADD . ')\](?::(?P<port>\d+))?$/', $both, $m ) ) {
+                               if ( isset( $m['port'] ) ) {
+                                       return array( $m[1], intval( $m['port'] ) );
+                               } else {
+                                       return array( $m[1], false );
+                               }
+                       } else {
+                               // Square bracket found but no IPv6
+                               return false;
+                       }
+               }
+               $numColons = substr_count( $both, ':' );
+               if ( $numColons >= 2 ) {
+                       // Is it a bare IPv6 address?
+                       if ( preg_match( '/^' . RE_IPV6_ADD . '$/', $both ) ) {
+                               return array( $both, false );
+                       } else {
+                               // Not valid IPv6, but too many colons for anything else
+                               return false;
+                       }
+               }
+               if ( $numColons >= 1 ) {
+                       // Host:port?
+                       $bits = explode( ':', $both );
+                       if ( preg_match( '/^\d+/', $bits[1] ) ) {
+                               return array( $bits[0], intval( $bits[1] ) );
+                       } else {
+                               // Not a valid port
+                               return false;
+                       }
+               }
+
+               // Plain hostname
+               return array( $both, false );
+       }
+
+       /**
+        * Given a host name and a port, combine them into host/port string like
+        * you might find in a URL. If the host contains a colon, wrap it in square
+        * brackets like in RFC 2732. If the port matches the default port, omit
+        * the port specification
+        *
+        * @param $host string
+        * @param $port int
+        * @param $defaultPort bool|int
+        * @return string
+        */
+       public static function combineHostAndPort( $host, $port, $defaultPort = false ) {
+               if ( strpos( $host, ':' ) !== false ) {
+                       $host = "[$host]";
+               }
+               if ( $defaultPort !== false && $port == $defaultPort ) {
+                       return $host;
+               } else {
+                       return "$host:$port";
+               }
+       }
+
+       /**
+        * Given an unsigned integer, returns an IPv6 address in octet notation
+        *
+        * @param $ip_int String: IP address.
+        * @return String
+        */
+       public static function toOctet( $ip_int ) {
+               return self::hexToOctet( wfBaseConvert( $ip_int, 10, 16, 32, false ) );
+       }
+
+       /**
+        * Convert an IPv4 or IPv6 hexadecimal representation back to readable format
+        *
+        * @param string $hex number, with "v6-" prefix if it is IPv6
+        * @return String: quad-dotted (IPv4) or octet notation (IPv6)
+        */
+       public static function formatHex( $hex ) {
+               if ( substr( $hex, 0, 3 ) == 'v6-' ) { // IPv6
+                       return self::hexToOctet( substr( $hex, 3 ) );
+               } else { // IPv4
+                       return self::hexToQuad( $hex );
+               }
+       }
+
+       /**
+        * Converts a hexadecimal number to an IPv6 address in octet notation
+        *
+        * @param $ip_hex String: pure hex (no v6- prefix)
+        * @return String (of format a:b:c:d:e:f:g:h)
+        */
+       public static function hexToOctet( $ip_hex ) {
+               // Pad hex to 32 chars (128 bits)
+               $ip_hex = str_pad( strtoupper( $ip_hex ), 32, '0', STR_PAD_LEFT );
+               // Separate into 8 words
+               $ip_oct = substr( $ip_hex, 0, 4 );
+               for ( $n = 1; $n < 8; $n++ ) {
+                       $ip_oct .= ':' . substr( $ip_hex, 4 * $n, 4 );
+               }
+               // NO leading zeroes
+               $ip_oct = preg_replace( '/(^|:)0+(' . RE_IPV6_WORD . ')/', '$1$2', $ip_oct );
+
+               return $ip_oct;
+       }
+
+       /**
+        * Converts a hexadecimal number to an IPv4 address in quad-dotted notation
+        *
+        * @param $ip_hex String: pure hex
+        * @return String (of format a.b.c.d)
+        */
+       public static function hexToQuad( $ip_hex ) {
+               // Pad hex to 8 chars (32 bits)
+               $ip_hex = str_pad( strtoupper( $ip_hex ), 8, '0', STR_PAD_LEFT );
+               // Separate into four quads
+               $s = '';
+               for ( $i = 0; $i < 4; $i++ ) {
+                       if ( $s !== '' ) {
+                               $s .= '.';
+                       }
+                       $s .= base_convert( substr( $ip_hex, $i * 2, 2 ), 16, 10 );
+               }
+
+               return $s;
+       }
+
+       /**
+        * Determine if an IP address really is an IP address, and if it is public,
+        * i.e. not RFC 1918 or similar
+        * Comes from ProxyTools.php
+        *
+        * @param $ip String
+        * @return Boolean
+        */
+       public static function isPublic( $ip ) {
+               if ( self::isIPv6( $ip ) ) {
+                       return self::isPublic6( $ip );
+               }
+               $n = self::toUnsigned( $ip );
+               if ( !$n ) {
+                       return false;
+               }
+
+               // ip2long accepts incomplete addresses, as well as some addresses
+               // followed by garbage characters. Check that it's really valid.
+               if ( $ip != long2ip( $n ) ) {
+                       return false;
+               }
+
+               static $privateRanges = false;
+               if ( !$privateRanges ) {
+                       $privateRanges = array(
+                               array( '10.0.0.0', '10.255.255.255' ), # RFC 1918 (private)
+                               array( '172.16.0.0', '172.31.255.255' ), # RFC 1918 (private)
+                               array( '192.168.0.0', '192.168.255.255' ), # RFC 1918 (private)
+                               array( '0.0.0.0', '0.255.255.255' ), # this network
+                               array( '127.0.0.0', '127.255.255.255' ), # loopback
+                       );
+               }
+
+               foreach ( $privateRanges as $r ) {
+                       $start = self::toUnsigned( $r[0] );
+                       $end = self::toUnsigned( $r[1] );
+                       if ( $n >= $start && $n <= $end ) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Determine if an IPv6 address really is an IP address, and if it is public,
+        * i.e. not RFC 4193 or similar
+        *
+        * @param $ip String
+        * @return Boolean
+        */
+       private static function isPublic6( $ip ) {
+               static $privateRanges = false;
+               if ( !$privateRanges ) {
+                       $privateRanges = array(
+                               array( 'fc00::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ), # RFC 4193 (local)
+                               array( '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1' ), # loopback
+                       );
+               }
+               $n = self::toHex( $ip );
+               foreach ( $privateRanges as $r ) {
+                       $start = self::toHex( $r[0] );
+                       $end = self::toHex( $r[1] );
+                       if ( $n >= $start && $n <= $end ) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Return a zero-padded upper case hexadecimal representation of an IP address.
+        *
+        * Hexadecimal addresses are used because they can easily be extended to
+        * IPv6 support. To separate the ranges, the return value from this
+        * function for an IPv6 address will be prefixed with "v6-", a non-
+        * hexadecimal string which sorts after the IPv4 addresses.
+        *
+        * @param string $ip quad dotted/octet IP address.
+        * @return String
+        */
+       public static function toHex( $ip ) {
+               if ( self::isIPv6( $ip ) ) {
+                       $n = 'v6-' . self::IPv6ToRawHex( $ip );
+               } else {
+                       $n = self::toUnsigned( $ip );
+                       if ( $n !== false ) {
+                               $n = wfBaseConvert( $n, 10, 16, 8, false );
+                       }
+               }
+
+               return $n;
+       }
+
+       /**
+        * Given an IPv6 address in octet notation, returns a pure hex string.
+        *
+        * @param string $ip octet ipv6 IP address.
+        * @return String: pure hex (uppercase)
+        */
+       private static function IPv6ToRawHex( $ip ) {
+               $ip = self::sanitizeIP( $ip );
+               if ( !$ip ) {
+                       return null;
+               }
+               $r_ip = '';
+               foreach ( explode( ':', $ip ) as $v ) {
+                       $r_ip .= str_pad( $v, 4, 0, STR_PAD_LEFT );
+               }
+
+               return $r_ip;
+       }
+
+       /**
+        * Given an IP address in dotted-quad/octet notation, returns an unsigned integer.
+        * Like ip2long() except that it actually works and has a consistent error return value.
+        * Comes from ProxyTools.php
+        *
+        * @param string $ip quad dotted IP address.
+        * @return Mixed: string/int/false
+        */
+       public static function toUnsigned( $ip ) {
+               if ( self::isIPv6( $ip ) ) {
+                       $n = self::toUnsigned6( $ip );
+               } else {
+                       $n = ip2long( $ip );
+                       if ( $n < 0 ) {
+                               $n += pow( 2, 32 );
+                               # On 32-bit platforms (and on Windows), 2^32 does not fit into an int,
+                               # so $n becomes a float. We convert it to string instead.
+                               if ( is_float( $n ) ) {
+                                       $n = (string)$n;
+                               }
+                       }
+               }
+
+               return $n;
+       }
+
+       /**
+        * @param $ip
+        * @return String
+        */
+       private static function toUnsigned6( $ip ) {
+               return wfBaseConvert( self::IPv6ToRawHex( $ip ), 16, 10 );
+       }
+
+       /**
+        * Convert a network specification in CIDR notation
+        * to an integer network and a number of bits
+        *
+        * @param string $range IP with CIDR prefix
+        * @return array(int or string, int)
+        */
+       public static function parseCIDR( $range ) {
+               if ( self::isIPv6( $range ) ) {
+                       return self::parseCIDR6( $range );
+               }
+               $parts = explode( '/', $range, 2 );
+               if ( count( $parts ) != 2 ) {
+                       return array( false, false );
+               }
+               list( $network, $bits ) = $parts;
+               $network = ip2long( $network );
+               if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 32 ) {
+                       if ( $bits == 0 ) {
+                               $network = 0;
+                       } else {
+                               $network &= ~( ( 1 << ( 32 - $bits ) ) - 1 );
+                       }
+                       # Convert to unsigned
+                       if ( $network < 0 ) {
+                               $network += pow( 2, 32 );
+                       }
+               } else {
+                       $network = false;
+                       $bits = false;
+               }
+
+               return array( $network, $bits );
+       }
+
+       /**
+        * Given a string range in a number of formats,
+        * return the start and end of the range in hexadecimal.
+        *
+        * Formats are:
+        *     1.2.3.4/24          CIDR
+        *     1.2.3.4 - 1.2.3.5   Explicit range
+        *     1.2.3.4             Single IP
+        *
+        *     2001:0db8:85a3::7344/96                       CIDR
+        *     2001:0db8:85a3::7344 - 2001:0db8:85a3::7344   Explicit range
+        *     2001:0db8:85a3::7344                          Single IP
+        * @param string $range IP range
+        * @return array(string, string)
+        */
+       public static function parseRange( $range ) {
+               // CIDR notation
+               if ( strpos( $range, '/' ) !== false ) {
+                       if ( self::isIPv6( $range ) ) {
+                               return self::parseRange6( $range );
+                       }
+                       list( $network, $bits ) = self::parseCIDR( $range );
+                       if ( $network === false ) {
+                               $start = $end = false;
+                       } else {
+                               $start = sprintf( '%08X', $network );
+                               $end = sprintf( '%08X', $network + pow( 2, ( 32 - $bits ) ) - 1 );
+                       }
+               // Explicit range
+               } elseif ( strpos( $range, '-' ) !== false ) {
+                       list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
+                       if ( self::isIPv6( $start ) && self::isIPv6( $end ) ) {
+                               return self::parseRange6( $range );
+                       }
+                       if ( self::isIPv4( $start ) && self::isIPv4( $end ) ) {
+                               $start = self::toUnsigned( $start );
+                               $end = self::toUnsigned( $end );
+                               if ( $start > $end ) {
+                                       $start = $end = false;
+                               } else {
+                                       $start = sprintf( '%08X', $start );
+                                       $end = sprintf( '%08X', $end );
+                               }
+                       } else {
+                               $start = $end = false;
+                       }
+               } else {
+                       # Single IP
+                       $start = $end = self::toHex( $range );
+               }
+               if ( $start === false || $end === false ) {
+                       return array( false, false );
+               } else {
+                       return array( $start, $end );
+               }
+       }
+
+       /**
+        * Convert a network specification in IPv6 CIDR notation to an
+        * integer network and a number of bits
+        *
+        * @param $range
+        *
+        * @return array(string, int)
+        */
+       private static function parseCIDR6( $range ) {
+               # Explode into <expanded IP,range>
+               $parts = explode( '/', IP::sanitizeIP( $range ), 2 );
+               if ( count( $parts ) != 2 ) {
+                       return array( false, false );
+               }
+               list( $network, $bits ) = $parts;
+               $network = self::IPv6ToRawHex( $network );
+               if ( $network !== false && is_numeric( $bits ) && $bits >= 0 && $bits <= 128 ) {
+                       if ( $bits == 0 ) {
+                               $network = "0";
+                       } else {
+                               # Native 32 bit functions WONT work here!!!
+                               # Convert to a padded binary number
+                               $network = wfBaseConvert( $network, 16, 2, 128 );
+                               # Truncate the last (128-$bits) bits and replace them with zeros
+                               $network = str_pad( substr( $network, 0, $bits ), 128, 0, STR_PAD_RIGHT );
+                               # Convert back to an integer
+                               $network = wfBaseConvert( $network, 2, 10 );
+                       }
+               } else {
+                       $network = false;
+                       $bits = false;
+               }
+
+               return array( $network, (int)$bits );
+       }
+
+       /**
+        * Given a string range in a number of formats, return the
+        * start and end of the range in hexadecimal. For IPv6.
+        *
+        * Formats are:
+        *     2001:0db8:85a3::7344/96                       CIDR
+        *     2001:0db8:85a3::7344 - 2001:0db8:85a3::7344   Explicit range
+        *     2001:0db8:85a3::7344/96                       Single IP
+        *
+        * @param $range
+        *
+        * @return array(string, string)
+        */
+       private static function parseRange6( $range ) {
+               # Expand any IPv6 IP
+               $range = IP::sanitizeIP( $range );
+               // CIDR notation...
+               if ( strpos( $range, '/' ) !== false ) {
+                       list( $network, $bits ) = self::parseCIDR6( $range );
+                       if ( $network === false ) {
+                               $start = $end = false;
+                       } else {
+                               $start = wfBaseConvert( $network, 10, 16, 32, false );
+                               # Turn network to binary (again)
+                               $end = wfBaseConvert( $network, 10, 2, 128 );
+                               # Truncate the last (128-$bits) bits and replace them with ones
+                               $end = str_pad( substr( $end, 0, $bits ), 128, 1, STR_PAD_RIGHT );
+                               # Convert to hex
+                               $end = wfBaseConvert( $end, 2, 16, 32, false );
+                               # see toHex() comment
+                               $start = "v6-$start";
+                               $end = "v6-$end";
+                       }
+       // Explicit range notation...
+               } elseif ( strpos( $range, '-' ) !== false ) {
+                       list( $start, $end ) = array_map( 'trim', explode( '-', $range, 2 ) );
+                       $start = self::toUnsigned6( $start );
+                       $end = self::toUnsigned6( $end );
+                       if ( $start > $end ) {
+                               $start = $end = false;
+                       } else {
+                               $start = wfBaseConvert( $start, 10, 16, 32, false );
+                               $end = wfBaseConvert( $end, 10, 16, 32, false );
+                       }
+                       # see toHex() comment
+                       $start = "v6-$start";
+                       $end = "v6-$end";
+               } else {
+                       # Single IP
+                       $start = $end = self::toHex( $range );
+               }
+               if ( $start === false || $end === false ) {
+                       return array( false, false );
+               } else {
+                       return array( $start, $end );
+               }
+       }
+
+       /**
+        * Determine if a given IPv4/IPv6 address is in a given CIDR network
+        *
+        * @param string $addr the address to check against the given range.
+        * @param string $range the range to check the given address against.
+        * @return Boolean: whether or not the given address is in the given range.
+        */
+       public static function isInRange( $addr, $range ) {
+               $hexIP = self::toHex( $addr );
+               list( $start, $end ) = self::parseRange( $range );
+
+               return ( strcmp( $hexIP, $start ) >= 0 &&
+                       strcmp( $hexIP, $end ) <= 0 );
+       }
+
+       /**
+        * Convert some unusual representations of IPv4 addresses to their
+        * canonical dotted quad representation.
+        *
+        * This currently only checks a few IPV4-to-IPv6 related cases.  More
+        * unusual representations may be added later.
+        *
+        * @param string $addr something that might be an IP address
+        * @return String: valid dotted quad IPv4 address or null
+        */
+       public static function canonicalize( $addr ) {
+               // remove zone info (bug 35738)
+               $addr = preg_replace( '/\%.*/', '', $addr );
+
+               if ( self::isValid( $addr ) ) {
+                       return $addr;
+               }
+               // Turn mapped addresses from ::ce:ffff:1.2.3.4 to 1.2.3.4
+               if ( strpos( $addr, ':' ) !== false && strpos( $addr, '.' ) !== false ) {
+                       $addr = substr( $addr, strrpos( $addr, ':' ) + 1 );
+                       if ( self::isIPv4( $addr ) ) {
+                               return $addr;
+                       }
+               }
+               // IPv6 loopback address
+               $m = array();
+               if ( preg_match( '/^0*' . RE_IPV6_GAP . '1$/', $addr, $m ) ) {
+                       return '127.0.0.1';
+               }
+               // IPv4-mapped and IPv4-compatible IPv6 addresses
+               if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . '(' . RE_IP_ADD . ')$/i', $addr, $m ) ) {
+                       return $m[1];
+               }
+               if ( preg_match( '/^' . RE_IPV6_V4_PREFIX . RE_IPV6_WORD .
+                       ':' . RE_IPV6_WORD . '$/i', $addr, $m )
+               ) {
+                       return long2ip( ( hexdec( $m[1] ) << 16 ) + hexdec( $m[2] ) );
+               }
+
+               return null; // give up
+       }
+
+       /**
+        * Gets rid of unneeded numbers in quad-dotted/octet IP strings
+        * For example, 127.111.113.151/24 -> 127.111.113.0/24
+        * @param string $range IP address to normalize
+        * @return string
+        */
+       public static function sanitizeRange( $range ) {
+               list( /*...*/, $bits ) = self::parseCIDR( $range );
+               list( $start, /*...*/ ) = self::parseRange( $range );
+               $start = self::formatHex( $start );
+               if ( $bits === false ) {
+                       return $start; // wasn't actually a range
+               }
+
+               return "$start/$bits";
+       }
+}
diff --git a/includes/utils/MWCryptRand.php b/includes/utils/MWCryptRand.php
new file mode 100644 (file)
index 0000000..0172974
--- /dev/null
@@ -0,0 +1,517 @@
+<?php
+/**
+ * A cryptographic random generator class used for generating secret keys
+ *
+ * This is based in part on Drupal code as well as what we used in our own code
+ * prior to introduction of this class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @author Daniel Friesen
+ * @file
+ */
+
+class MWCryptRand {
+       /**
+        * Minimum number of iterations we want to make in our drift calculations.
+        */
+       const MIN_ITERATIONS = 1000;
+
+       /**
+        * Number of milliseconds we want to spend generating each separate byte
+        * of the final generated bytes.
+        * This is used in combination with the hash length to determine the duration
+        * we should spend doing drift calculations.
+        */
+       const MSEC_PER_BYTE = 0.5;
+
+       /**
+        * Singleton instance for public use
+        */
+       protected static $singleton = null;
+
+       /**
+        * The hash algorithm being used
+        */
+       protected $algo = null;
+
+       /**
+        * The number of bytes outputted by the hash algorithm
+        */
+       protected $hashLength = null;
+
+       /**
+        * A boolean indicating whether the previous random generation was done using
+        * cryptographically strong random number generator or not.
+        */
+       protected $strong = null;
+
+       /**
+        * Initialize an initial random state based off of whatever we can find
+        */
+       protected function initialRandomState() {
+               // $_SERVER contains a variety of unstable user and system specific information
+               // It'll vary a little with each page, and vary even more with separate users
+               // It'll also vary slightly across different machines
+               $state = serialize( $_SERVER );
+
+               // To try vary the system information of the state a bit more
+               // by including the system's hostname into the state
+               $state .= wfHostname();
+
+               // Try to gather a little entropy from the different php rand sources
+               $state .= rand() . uniqid( mt_rand(), true );
+
+               // Include some information about the filesystem's current state in the random state
+               $files = array();
+
+               // We know this file is here so grab some info about ourselves
+               $files[] = __FILE__;
+
+               // We must also have a parent folder, and with the usual file structure, a grandparent
+               $files[] = __DIR__;
+               $files[] = dirname( __DIR__ );
+
+               // The config file is likely the most often edited file we know should
+               // be around so include its stat info into the state.
+               // The constant with its location will almost always be defined, as
+               // WebStart.php defines MW_CONFIG_FILE to $IP/LocalSettings.php unless
+               // being configured with MW_CONFIG_CALLBACK (e.g. the installer).
+               if ( defined( 'MW_CONFIG_FILE' ) ) {
+                       $files[] = MW_CONFIG_FILE;
+               }
+
+               foreach ( $files as $file ) {
+                       wfSuppressWarnings();
+                       $stat = stat( $file );
+                       wfRestoreWarnings();
+                       if ( $stat ) {
+                               // stat() duplicates data into numeric and string keys so kill off all the numeric ones
+                               foreach ( $stat as $k => $v ) {
+                                       if ( is_numeric( $k ) ) {
+                                               unset( $k );
+                                       }
+                               }
+                               // The absolute filename itself will differ from install to install so don't leave it out
+                               if ( ( $path = realpath( $file ) ) !== false ) {
+                                       $state .= $path;
+                               } else {
+                                       $state .= $file;
+                               }
+                               $state .= implode( '', $stat );
+                       } else {
+                               // The fact that the file isn't there is worth at least a
+                               // minuscule amount of entropy.
+                               $state .= '0';
+                       }
+               }
+
+               // Try and make this a little more unstable by including the varying process
+               // id of the php process we are running inside of if we are able to access it
+               if ( function_exists( 'getmypid' ) ) {
+                       $state .= getmypid();
+               }
+
+               // If available try to increase the instability of the data by throwing in
+               // the precise amount of memory that we happen to be using at the moment.
+               if ( function_exists( 'memory_get_usage' ) ) {
+                       $state .= memory_get_usage( true );
+               }
+
+               // It's mostly worthless but throw the wiki's id into the data for a little more variance
+               $state .= wfWikiID();
+
+               // If we have a secret key or proxy key set then throw it into the state as well
+               global $wgSecretKey, $wgProxyKey;
+               if ( $wgSecretKey ) {
+                       $state .= $wgSecretKey;
+               } elseif ( $wgProxyKey ) {
+                       $state .= $wgProxyKey;
+               }
+
+               return $state;
+       }
+
+       /**
+        * Randomly hash data while mixing in clock drift data for randomness
+        *
+        * @param string $data The data to randomly hash.
+        * @return String The hashed bytes
+        * @author Tim Starling
+        */
+       protected function driftHash( $data ) {
+               // Minimum number of iterations (to avoid slow operations causing the
+               // loop to gather little entropy)
+               $minIterations = self::MIN_ITERATIONS;
+               // Duration of time to spend doing calculations (in seconds)
+               $duration = ( self::MSEC_PER_BYTE / 1000 ) * $this->hashLength();
+               // Create a buffer to use to trigger memory operations
+               $bufLength = 10000000;
+               $buffer = str_repeat( ' ', $bufLength );
+               $bufPos = 0;
+
+               // Iterate for $duration seconds or at least $minIterations number of iterations
+               $iterations = 0;
+               $startTime = microtime( true );
+               $currentTime = $startTime;
+               while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
+                       // Trigger some memory writing to trigger some bus activity
+                       // This may create variance in the time between iterations
+                       $bufPos = ( $bufPos + 13 ) % $bufLength;
+                       $buffer[$bufPos] = ' ';
+                       // Add the drift between this iteration and the last in as entropy
+                       $nextTime = microtime( true );
+                       $delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
+                       $data .= $delta;
+                       // Every 100 iterations hash the data and entropy
+                       if ( $iterations % 100 === 0 ) {
+                               $data = sha1( $data );
+                       }
+                       $currentTime = $nextTime;
+                       $iterations++;
+               }
+               $timeTaken = $currentTime - $startTime;
+               $data = $this->hash( $data );
+
+               wfDebug( __METHOD__ . ": Clock drift calculation " .
+                       "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
+                       "iterations=$iterations, " .
+                       "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" );
+
+               return $data;
+       }
+
+       /**
+        * Return a rolling random state initially build using data from unstable sources
+        * @return string A new weak random state
+        */
+       protected function randomState() {
+               static $state = null;
+               if ( is_null( $state ) ) {
+                       // Initialize the state with whatever unstable data we can find
+                       // It's important that this data is hashed right afterwards to prevent
+                       // it from being leaked into the output stream
+                       $state = $this->hash( $this->initialRandomState() );
+               }
+               // Generate a new random state based on the initial random state or previous
+               // random state by combining it with clock drift
+               $state = $this->driftHash( $state );
+
+               return $state;
+       }
+
+       /**
+        * Decide on the best acceptable hash algorithm we have available for hash()
+        * @throws MWException
+        * @return String A hash algorithm
+        */
+       protected function hashAlgo() {
+               if ( !is_null( $this->algo ) ) {
+                       return $this->algo;
+               }
+
+               $algos = hash_algos();
+               $preference = array( 'whirlpool', 'sha256', 'sha1', 'md5' );
+
+               foreach ( $preference as $algorithm ) {
+                       if ( in_array( $algorithm, $algos ) ) {
+                               $this->algo = $algorithm;
+                               wfDebug( __METHOD__ . ": Using the {$this->algo} hash algorithm.\n" );
+
+                               return $this->algo;
+                       }
+               }
+
+               // We only reach here if no acceptable hash is found in the list, this should
+               // be a technical impossibility since most of php's hash list is fixed and
+               // some of the ones we list are available as their own native functions
+               // But since we already require at least 5.2 and hash() was default in
+               // 5.1.2 we don't bother falling back to methods like sha1 and md5.
+               throw new MWException( "Could not find an acceptable hashing function in hash_algos()" );
+       }
+
+       /**
+        * Return the byte-length output of the hash algorithm we are
+        * using in self::hash and self::hmac.
+        *
+        * @return int Number of bytes the hash outputs
+        */
+       protected function hashLength() {
+               if ( is_null( $this->hashLength ) ) {
+                       $this->hashLength = strlen( $this->hash( '' ) );
+               }
+
+               return $this->hashLength;
+       }
+
+       /**
+        * Generate an acceptably unstable one-way-hash of some text
+        * making use of the best hash algorithm that we have available.
+        *
+        * @param $data string
+        * @return String A raw hash of the data
+        */
+       protected function hash( $data ) {
+               return hash( $this->hashAlgo(), $data, true );
+       }
+
+       /**
+        * Generate an acceptably unstable one-way-hmac of some text
+        * making use of the best hash algorithm that we have available.
+        *
+        * @param $data string
+        * @param $key string
+        * @return String A raw hash of the data
+        */
+       protected function hmac( $data, $key ) {
+               return hash_hmac( $this->hashAlgo(), $data, $key, true );
+       }
+
+       /**
+        * @see self::wasStrong()
+        */
+       public function realWasStrong() {
+               if ( is_null( $this->strong ) ) {
+                       throw new MWException( __METHOD__ . ' called before generation of random data' );
+               }
+
+               return $this->strong;
+       }
+
+       /**
+        * @see self::generate()
+        */
+       public function realGenerate( $bytes, $forceStrong = false ) {
+               wfProfileIn( __METHOD__ );
+
+               wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " .
+                       wfGetAllCallers( 5 ) . "\n" );
+
+               $bytes = floor( $bytes );
+               static $buffer = '';
+               if ( is_null( $this->strong ) ) {
+                       // Set strength to false initially until we know what source data is coming from
+                       $this->strong = true;
+               }
+
+               if ( strlen( $buffer ) < $bytes ) {
+                       // If available make use of mcrypt_create_iv URANDOM source to generate randomness
+                       // On unix-like systems this reads from /dev/urandom but does it without any buffering
+                       // and bypasses openbasedir restrictions, so it's preferable to reading directly
+                       // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
+                       // entropy so this is also preferable to just trying to read urandom because it may work
+                       // on Windows systems as well.
+                       if ( function_exists( 'mcrypt_create_iv' ) ) {
+                               wfProfileIn( __METHOD__ . '-mcrypt' );
+                               $rem = $bytes - strlen( $buffer );
+                               $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
+                               if ( $iv === false ) {
+                                       wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
+                               } else {
+                                       $buffer .= $iv;
+                                       wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) .
+                                               " bytes of randomness.\n" );
+                               }
+                               wfProfileOut( __METHOD__ . '-mcrypt' );
+                       }
+               }
+
+               if ( strlen( $buffer ) < $bytes ) {
+                       // If available make use of openssl's random_pseudo_bytes method to
+                       // attempt to generate randomness. However don't do this on Windows
+                       // with PHP < 5.3.4 due to a bug:
+                       // http://stackoverflow.com/questions/1940168/openssl-random-pseudo-bytes-is-slow-php
+                       // http://git.php.net/?p=php-src.git;a=commitdiff;h=cd62a70863c261b07f6dadedad9464f7e213cad5
+                       if ( function_exists( 'openssl_random_pseudo_bytes' )
+                               && ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
+                       ) {
+                               wfProfileIn( __METHOD__ . '-openssl' );
+                               $rem = $bytes - strlen( $buffer );
+                               $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
+                               if ( $openssl_bytes === false ) {
+                                       wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes returned false.\n" );
+                               } else {
+                                       $buffer .= $openssl_bytes;
+                                       wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes generated " .
+                                               strlen( $openssl_bytes ) . " bytes of " .
+                                               ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" );
+                               }
+                               if ( strlen( $buffer ) >= $bytes ) {
+                                       // openssl tells us if the random source was strong, if some of our data was generated
+                                       // using it use it's say on whether the randomness is strong
+                                       $this->strong = !!$openssl_strong;
+                               }
+                               wfProfileOut( __METHOD__ . '-openssl' );
+                       }
+               }
+
+               // Only read from urandom if we can control the buffer size or were passed forceStrong
+               if ( strlen( $buffer ) < $bytes &&
+                       ( function_exists( 'stream_set_read_buffer' ) || $forceStrong )
+               ) {
+                       wfProfileIn( __METHOD__ . '-fopen-urandom' );
+                       $rem = $bytes - strlen( $buffer );
+                       if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
+                               wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom " .
+                                       "without control over the buffer size.\n" );
+                       }
+                       // /dev/urandom is generally considered the best possible commonly
+                       // available random source, and is available on most *nix systems.
+                       wfSuppressWarnings();
+                       $urandom = fopen( "/dev/urandom", "rb" );
+                       wfRestoreWarnings();
+
+                       // Attempt to read all our random data from urandom
+                       // php's fread always does buffered reads based on the stream's chunk_size
+                       // so in reality it will usually read more than the amount of data we're
+                       // asked for and not storing that risks depleting the system's random pool.
+                       // If stream_set_read_buffer is available set the chunk_size to the amount
+                       // of data we need. Otherwise read 8k, php's default chunk_size.
+                       if ( $urandom ) {
+                               // php's default chunk_size is 8k
+                               $chunk_size = 1024 * 8;
+                               if ( function_exists( 'stream_set_read_buffer' ) ) {
+                                       // If possible set the chunk_size to the amount of data we need
+                                       stream_set_read_buffer( $urandom, $rem );
+                                       $chunk_size = $rem;
+                               }
+                               $random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
+                               $buffer .= $random_bytes;
+                               fclose( $urandom );
+                               wfDebug( __METHOD__ . ": /dev/urandom generated " . strlen( $random_bytes ) .
+                                       " bytes of randomness.\n" );
+
+                               if ( strlen( $buffer ) >= $bytes ) {
+                                       // urandom is always strong, set to true if all our data was generated using it
+                                       $this->strong = true;
+                               }
+                       } else {
+                               wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
+                       }
+                       wfProfileOut( __METHOD__ . '-fopen-urandom' );
+               }
+
+               // If we cannot use or generate enough data from a secure source
+               // use this loop to generate a good set of pseudo random data.
+               // This works by initializing a random state using a pile of unstable data
+               // and continually shoving it through a hash along with a variable salt.
+               // We hash the random state with more salt to avoid the state from leaking
+               // out and being used to predict the /randomness/ that follows.
+               if ( strlen( $buffer ) < $bytes ) {
+                       wfDebug( __METHOD__ .
+                               ": Falling back to using a pseudo random state to generate randomness.\n" );
+               }
+               while ( strlen( $buffer ) < $bytes ) {
+                       wfProfileIn( __METHOD__ . '-fallback' );
+                       $buffer .= $this->hmac( $this->randomState(), mt_rand() );
+                       // This code is never really cryptographically strong, if we use it
+                       // at all, then set strong to false.
+                       $this->strong = false;
+                       wfProfileOut( __METHOD__ . '-fallback' );
+               }
+
+               // Once the buffer has been filled up with enough random data to fulfill
+               // the request shift off enough data to handle the request and leave the
+               // unused portion left inside the buffer for the next request for random data
+               $generated = substr( $buffer, 0, $bytes );
+               $buffer = substr( $buffer, $bytes );
+
+               wfDebug( __METHOD__ . ": " . strlen( $buffer ) .
+                       " bytes of randomness leftover in the buffer.\n" );
+
+               wfProfileOut( __METHOD__ );
+
+               return $generated;
+       }
+
+       /**
+        * @see self::generateHex()
+        */
+       public function realGenerateHex( $chars, $forceStrong = false ) {
+               // hex strings are 2x the length of raw binary so we divide the length in half
+               // odd numbers will result in a .5 that leads the generate() being 1 character
+               // short, so we use ceil() to ensure that we always have enough bytes
+               $bytes = ceil( $chars / 2 );
+               // Generate the data and then convert it to a hex string
+               $hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
+
+               // A bit of paranoia here, the caller asked for a specific length of string
+               // here, and it's possible (eg when given an odd number) that we may actually
+               // have at least 1 char more than they asked for. Just in case they made this
+               // call intending to insert it into a database that does truncation we don't
+               // want to give them too much and end up with their database and their live
+               // code having two different values because part of what we gave them is truncated
+               // hence, we strip out any run of characters longer than what we were asked for.
+               return substr( $hex, 0, $chars );
+       }
+
+       /** Publicly exposed static methods **/
+
+       /**
+        * Return a singleton instance of MWCryptRand
+        * @return MWCryptRand
+        */
+       protected static function singleton() {
+               if ( is_null( self::$singleton ) ) {
+                       self::$singleton = new self;
+               }
+
+               return self::$singleton;
+       }
+
+       /**
+        * Return a boolean indicating whether or not the source used for cryptographic
+        * random bytes generation in the previously run generate* call
+        * was cryptographically strong.
+        *
+        * @return bool Returns true if the source was strong, false if not.
+        */
+       public static function wasStrong() {
+               return self::singleton()->realWasStrong();
+       }
+
+       /**
+        * Generate a run of (ideally) cryptographically random data and return
+        * it in raw binary form.
+        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
+        * was cryptographically strong.
+        *
+        * @param int $bytes the number of bytes of random data to generate
+        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
+        *                          strong sources of entropy even if reading from them may steal
+        *                          more entropy from the system than optimal.
+        * @return String Raw binary random data
+        */
+       public static function generate( $bytes, $forceStrong = false ) {
+               return self::singleton()->realGenerate( $bytes, $forceStrong );
+       }
+
+       /**
+        * Generate a run of (ideally) cryptographically random data and return
+        * it in hexadecimal string format.
+        * You can use MWCryptRand::wasStrong() if you wish to know if the source used
+        * was cryptographically strong.
+        *
+        * @param int $chars the number of hex chars of random data to generate
+        * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
+        *                          strong sources of entropy even if reading from them may steal
+        *                          more entropy from the system than optimal.
+        * @return String Hexadecimal random data
+        */
+       public static function generateHex( $chars, $forceStrong = false ) {
+               return self::singleton()->realGenerateHex( $chars, $forceStrong );
+       }
+}
diff --git a/includes/utils/MWFunction.php b/includes/utils/MWFunction.php
new file mode 100644 (file)
index 0000000..7105f6c
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Helper methods to call functions and instance objects.
+ *
+ * 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
+ */
+
+class MWFunction {
+
+       /**
+        * @deprecated since 1.22; use call_user_func()
+        * @param $callback
+        * @return mixed
+        */
+       public static function call( $callback ) {
+               wfDeprecated( __METHOD__, '1.22' );
+               $args = func_get_args();
+
+               return call_user_func_array( 'call_user_func', $args );
+       }
+
+       /**
+        * @deprecated since 1.22; use call_user_func_array()
+        * @param $callback
+        * @param $argsarams
+        * @return mixed
+        */
+       public static function callArray( $callback, $argsarams ) {
+               wfDeprecated( __METHOD__, '1.22' );
+
+               return call_user_func_array( $callback, $argsarams );
+       }
+
+       /**
+        * @param $class
+        * @param $args array
+        * @return object
+        */
+       public static function newObj( $class, $args = array() ) {
+               if ( !count( $args ) ) {
+                       return new $class;
+               }
+
+               $ref = new ReflectionClass( $class );
+
+               return $ref->newInstanceArgs( $args );
+       }
+}
diff --git a/includes/utils/MappedIterator.php b/includes/utils/MappedIterator.php
new file mode 100644 (file)
index 0000000..f2e6df6
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Convenience class for generating iterators from iterators.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Convenience class for generating iterators from iterators.
+ *
+ * @since 1.21
+ */
+class MappedIterator extends FilterIterator {
+       /** @var callable */
+       protected $vCallback;
+       /** @var callable */
+       protected $aCallback;
+       /** @var array */
+       protected $cache = array();
+
+       protected $rewound = false; // boolean; whether rewind() has been called
+
+       /**
+        * Build an new iterator from a base iterator by having the former wrap the
+        * later, returning the result of "value" callback for each current() invocation.
+        * The callback takes the result of current() on the base iterator as an argument.
+        * The keys of the base iterator are reused verbatim.
+        *
+        * An "accept" callback can also be provided which will be called for each value in
+        * the base iterator (post-callback) and will return true if that value should be
+        * included in iteration of the MappedIterator (otherwise it will be filtered out).
+        *
+        * @param Iterator|Array $iter
+        * @param callable $vCallback Value transformation callback
+        * @param array $options Options map (includes "accept") (since 1.22)
+        * @throws MWException
+        */
+       public function __construct( $iter, $vCallback, array $options = array() ) {
+               if ( is_array( $iter ) ) {
+                       $baseIterator = new ArrayIterator( $iter );
+               } elseif ( $iter instanceof Iterator ) {
+                       $baseIterator = $iter;
+               } else {
+                       throw new MWException( "Invalid base iterator provided." );
+               }
+               parent::__construct( $baseIterator );
+               $this->vCallback = $vCallback;
+               $this->aCallback = isset( $options['accept'] ) ? $options['accept'] : null;
+       }
+
+       public function next() {
+               $this->cache = array();
+               parent::next();
+       }
+
+       public function rewind() {
+               $this->rewound = true;
+               $this->cache = array();
+               parent::rewind();
+       }
+
+       public function accept() {
+               $value = call_user_func( $this->vCallback, $this->getInnerIterator()->current() );
+               $ok = ( $this->aCallback ) ? call_user_func( $this->aCallback, $value ) : true;
+               if ( $ok ) {
+                       $this->cache['current'] = $value;
+               }
+
+               return $ok;
+       }
+
+       public function key() {
+               $this->init();
+
+               return parent::key();
+       }
+
+       public function valid() {
+               $this->init();
+
+               return parent::valid();
+       }
+
+       public function current() {
+               $this->init();
+               if ( parent::valid() ) {
+                       return $this->cache['current'];
+               } else {
+                       return null; // out of range
+               }
+       }
+
+       /**
+        * Obviate the usual need for rewind() before using a FilterIterator in a manual loop
+        */
+       protected function init() {
+               if ( !$this->rewound ) {
+                       $this->rewind();
+               }
+       }
+}
diff --git a/includes/utils/README b/includes/utils/README
new file mode 100644 (file)
index 0000000..b5b8ec8
--- /dev/null
@@ -0,0 +1,9 @@
+The classes in this directory are general utilities for use by any part of
+MediaWiki. They do not favour any particular user interface and are not
+constrained to serve any particular feature. This is similar to includes/libs,
+except that some dependency on the MediaWiki framework (such as the use of
+MWException, Status or wfDebug()) disqualifies them from use outside of
+MediaWiki without modification.
+
+Utilities should not use global configuration variables, rather they should rely
+on the caller to configure their behaviour.
diff --git a/includes/utils/ScopedCallback.php b/includes/utils/ScopedCallback.php
new file mode 100644 (file)
index 0000000..ef22e0a
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ * This file deals with RAII style scoped callbacks.
+ *
+ * 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
+ */
+
+/**
+ * Class for asserting that a callback happens when an dummy object leaves scope
+ *
+ * @since 1.21
+ */
+class ScopedCallback {
+       /** @var callable */
+       protected $callback;
+
+       /**
+        * @param callable $callback
+        * @throws MWException
+        */
+       public function __construct( $callback ) {
+               if ( !is_callable( $callback ) ) {
+                       throw new MWException( "Provided callback is not valid." );
+               }
+               $this->callback = $callback;
+       }
+
+       /**
+        * Trigger a scoped callback and destroy it.
+        * This is the same is just setting it to null.
+        *
+        * @param ScopedCallback $sc
+        */
+       public static function consume( ScopedCallback &$sc = null ) {
+               $sc = null;
+       }
+
+       /**
+        * Destroy a scoped callback without triggering it
+        *
+        * @param ScopedCallback $sc
+        */
+       public static function cancel( ScopedCallback &$sc = null ) {
+               if ( $sc ) {
+                       $sc->callback = null;
+               }
+               $sc = null;
+       }
+
+       /**
+        * Trigger the callback when this leaves scope
+        */
+       function __destruct() {
+               if ( $this->callback !== null ) {
+                       call_user_func( $this->callback );
+               }
+       }
+}
diff --git a/includes/utils/StringUtils.php b/includes/utils/StringUtils.php
new file mode 100644 (file)
index 0000000..9cd3d3f
--- /dev/null
@@ -0,0 +1,612 @@
+<?php
+/**
+ * Methods to play with strings.
+ *
+ * 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
+ */
+
+/**
+ * A collection of static methods to play with strings.
+ */
+class StringUtils {
+       /**
+        * Test whether a string is valid UTF-8.
+        *
+        * The function check for invalid byte sequences, overlong encoding but
+        * not for different normalisations.
+        *
+        * This relies internally on the mbstring function mb_check_encoding()
+        * hardcoded to check against UTF-8. Whenever the function is not available
+        * we fallback to a pure PHP implementation. Setting $disableMbstring to
+        * true will skip the use of mb_check_encoding, this is mostly intended for
+        * unit testing our internal implementation.
+        *
+        * @since 1.21
+        * @note In MediaWiki 1.21, this function did not provide proper UTF-8 validation.
+        * In particular, the pure PHP code path did not in fact check for overlong forms.
+        * Beware of this when backporting code to that version of MediaWiki.
+        *
+        * @param string $value String to check
+        * @param boolean $disableMbstring Whether to use the pure PHP
+        * implementation instead of trying mb_check_encoding. Intended for unit
+        * testing. Default: false
+        *
+        * @return boolean Whether the given $value is a valid UTF-8 encoded string
+        */
+       static function isUtf8( $value, $disableMbstring = false ) {
+               $value = (string)$value;
+
+               // If the mbstring extension is loaded, use it. However, before PHP 5.4, values above
+               // U+10FFFF are incorrectly allowed, so we have to check for them separately.
+               if ( !$disableMbstring && function_exists( 'mb_check_encoding' ) ) {
+                       static $newPHP;
+                       if ( $newPHP === null ) {
+                               $newPHP = !mb_check_encoding( "\xf4\x90\x80\x80", 'UTF-8' );
+                       }
+
+                       return mb_check_encoding( $value, 'UTF-8' ) &&
+                               ( $newPHP || preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $value ) === 0 );
+               }
+
+               if ( preg_match( "/[\x80-\xff]/S", $value ) === 0 ) {
+                       // String contains only ASCII characters, has to be valid
+                       return true;
+               }
+
+               // PCRE implements repetition using recursion; to avoid a stack overflow (and segfault)
+               // for large input, we check for invalid sequences (<= 5 bytes) rather than valid
+               // sequences, which can be as long as the input string is. Multiple short regexes are
+               // used rather than a single long regex for performance.
+               static $regexes;
+               if ( $regexes === null ) {
+                       $cont = "[\x80-\xbf]";
+                       $after = "(?!$cont)"; // "(?:[^\x80-\xbf]|$)" would work here
+                       $regexes = array(
+                               // Continuation byte at the start
+                               "/^$cont/",
+
+                               // ASCII byte followed by a continuation byte
+                               "/[\\x00-\x7f]$cont/S",
+
+                               // Illegal byte
+                               "/[\xc0\xc1\xf5-\xff]/S",
+
+                               // Invalid 2-byte sequence, or valid one then an extra continuation byte
+                               "/[\xc2-\xdf](?!$cont$after)/S",
+
+                               // Invalid 3-byte sequence, or valid one then an extra continuation byte
+                               "/\xe0(?![\xa0-\xbf]$cont$after)/",
+                               "/[\xe1-\xec\xee\xef](?!$cont{2}$after)/S",
+                               "/\xed(?![\x80-\x9f]$cont$after)/",
+
+                               // Invalid 4-byte sequence, or valid one then an extra continuation byte
+                               "/\xf0(?![\x90-\xbf]$cont{2}$after)/",
+                               "/[\xf1-\xf3](?!$cont{3}$after)/S",
+                               "/\xf4(?![\x80-\x8f]$cont{2}$after)/",
+                       );
+               }
+
+               foreach ( $regexes as $regex ) {
+                       if ( preg_match( $regex, $value ) !== 0 ) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * Perform an operation equivalent to
+        *
+        *     preg_replace( "!$startDelim(.*?)$endDelim!", $replace, $subject );
+        *
+        * except that it's worst-case O(N) instead of O(N^2)
+        *
+        * Compared to delimiterReplace(), this implementation is fast but memory-
+        * hungry and inflexible. The memory requirements are such that I don't
+        * recommend using it on anything but guaranteed small chunks of text.
+        *
+        * @param $startDelim
+        * @param $endDelim
+        * @param $replace
+        * @param $subject
+        *
+        * @return string
+        */
+       static function hungryDelimiterReplace( $startDelim, $endDelim, $replace, $subject ) {
+               $segments = explode( $startDelim, $subject );
+               $output = array_shift( $segments );
+               foreach ( $segments as $s ) {
+                       $endDelimPos = strpos( $s, $endDelim );
+                       if ( $endDelimPos === false ) {
+                               $output .= $startDelim . $s;
+                       } else {
+                               $output .= $replace . substr( $s, $endDelimPos + strlen( $endDelim ) );
+                       }
+               }
+
+               return $output;
+       }
+
+       /**
+        * Perform an operation equivalent to
+        *
+        *   preg_replace_callback( "!$startDelim(.*)$endDelim!s$flags", $callback, $subject )
+        *
+        * This implementation is slower than hungryDelimiterReplace but uses far less
+        * memory. The delimiters are literal strings, not regular expressions.
+        *
+        * If the start delimiter ends with an initial substring of the end delimiter,
+        * e.g. in the case of C-style comments, the behavior differs from the model
+        * regex. In this implementation, the end must share no characters with the
+        * start, so e.g. /*\/ is not considered to be both the start and end of a
+        * comment. /*\/xy/*\/ is considered to be a single comment with contents /xy/.
+        *
+        * @param string $startDelim start delimiter
+        * @param string $endDelim end delimiter
+        * @param $callback Callback: function to call on each match
+        * @param $subject String
+        * @param string $flags regular expression flags
+        * @throws MWException
+        * @return string
+        */
+       static function delimiterReplaceCallback( $startDelim, $endDelim, $callback,
+               $subject, $flags = ''
+       ) {
+               $inputPos = 0;
+               $outputPos = 0;
+               $output = '';
+               $foundStart = false;
+               $encStart = preg_quote( $startDelim, '!' );
+               $encEnd = preg_quote( $endDelim, '!' );
+               $strcmp = strpos( $flags, 'i' ) === false ? 'strcmp' : 'strcasecmp';
+               $endLength = strlen( $endDelim );
+               $m = array();
+
+               while ( $inputPos < strlen( $subject ) &&
+                       preg_match( "!($encStart)|($encEnd)!S$flags", $subject, $m, PREG_OFFSET_CAPTURE, $inputPos )
+               ) {
+                       $tokenOffset = $m[0][1];
+                       if ( $m[1][0] != '' ) {
+                               if ( $foundStart &&
+                                       $strcmp( $endDelim, substr( $subject, $tokenOffset, $endLength ) ) == 0
+                               ) {
+                                       # An end match is present at the same location
+                                       $tokenType = 'end';
+                                       $tokenLength = $endLength;
+                               } else {
+                                       $tokenType = 'start';
+                                       $tokenLength = strlen( $m[0][0] );
+                               }
+                       } elseif ( $m[2][0] != '' ) {
+                               $tokenType = 'end';
+                               $tokenLength = strlen( $m[0][0] );
+                       } else {
+                               throw new MWException( 'Invalid delimiter given to ' . __METHOD__ );
+                       }
+
+                       if ( $tokenType == 'start' ) {
+                               # Only move the start position if we haven't already found a start
+                               # This means that START START END matches outer pair
+                               if ( !$foundStart ) {
+                                       # Found start
+                                       $inputPos = $tokenOffset + $tokenLength;
+                                       # Write out the non-matching section
+                                       $output .= substr( $subject, $outputPos, $tokenOffset - $outputPos );
+                                       $outputPos = $tokenOffset;
+                                       $contentPos = $inputPos;
+                                       $foundStart = true;
+                               } else {
+                                       # Move the input position past the *first character* of START,
+                                       # to protect against missing END when it overlaps with START
+                                       $inputPos = $tokenOffset + 1;
+                               }
+                       } elseif ( $tokenType == 'end' ) {
+                               if ( $foundStart ) {
+                                       # Found match
+                                       $output .= call_user_func( $callback, array(
+                                               substr( $subject, $outputPos, $tokenOffset + $tokenLength - $outputPos ),
+                                               substr( $subject, $contentPos, $tokenOffset - $contentPos )
+                                       ) );
+                                       $foundStart = false;
+                               } else {
+                                       # Non-matching end, write it out
+                                       $output .= substr( $subject, $inputPos, $tokenOffset + $tokenLength - $outputPos );
+                               }
+                               $inputPos = $outputPos = $tokenOffset + $tokenLength;
+                       } else {
+                               throw new MWException( 'Invalid delimiter given to ' . __METHOD__ );
+                       }
+               }
+               if ( $outputPos < strlen( $subject ) ) {
+                       $output .= substr( $subject, $outputPos );
+               }
+
+               return $output;
+       }
+
+       /**
+        * Perform an operation equivalent to
+        *
+        *   preg_replace( "!$startDelim(.*)$endDelim!$flags", $replace, $subject )
+        *
+        * @param string $startDelim start delimiter regular expression
+        * @param string $endDelim end delimiter regular expression
+        * @param string $replace replacement string. May contain $1, which will be
+        *                 replaced by the text between the delimiters
+        * @param string $subject to search
+        * @param string $flags regular expression flags
+        * @return String: The string with the matches replaced
+        */
+       static function delimiterReplace( $startDelim, $endDelim, $replace, $subject, $flags = '' ) {
+               $replacer = new RegexlikeReplacer( $replace );
+
+               return self::delimiterReplaceCallback( $startDelim, $endDelim,
+                       $replacer->cb(), $subject, $flags );
+       }
+
+       /**
+        * More or less "markup-safe" explode()
+        * Ignores any instances of the separator inside <...>
+        * @param string $separator
+        * @param string $text
+        * @return array
+        */
+       static function explodeMarkup( $separator, $text ) {
+               $placeholder = "\x00";
+
+               // Remove placeholder instances
+               $text = str_replace( $placeholder, '', $text );
+
+               // Replace instances of the separator inside HTML-like tags with the placeholder
+               $replacer = new DoubleReplacer( $separator, $placeholder );
+               $cleaned = StringUtils::delimiterReplaceCallback( '<', '>', $replacer->cb(), $text );
+
+               // Explode, then put the replaced separators back in
+               $items = explode( $separator, $cleaned );
+               foreach ( $items as $i => $str ) {
+                       $items[$i] = str_replace( $placeholder, $separator, $str );
+               }
+
+               return $items;
+       }
+
+       /**
+        * Escape a string to make it suitable for inclusion in a preg_replace()
+        * replacement parameter.
+        *
+        * @param string $string
+        * @return string
+        */
+       static function escapeRegexReplacement( $string ) {
+               $string = str_replace( '\\', '\\\\', $string );
+               $string = str_replace( '$', '\\$', $string );
+
+               return $string;
+       }
+
+       /**
+        * Workalike for explode() with limited memory usage.
+        * Returns an Iterator
+        * @param string $separator
+        * @param string $subject
+        * @return ArrayIterator|ExplodeIterator
+        */
+       static function explode( $separator, $subject ) {
+               if ( substr_count( $subject, $separator ) > 1000 ) {
+                       return new ExplodeIterator( $separator, $subject );
+               } else {
+                       return new ArrayIterator( explode( $separator, $subject ) );
+               }
+       }
+}
+
+/**
+ * Base class for "replacers", objects used in preg_replace_callback() and
+ * StringUtils::delimiterReplaceCallback()
+ */
+class Replacer {
+       /**
+        * @return array
+        */
+       function cb() {
+               return array( &$this, 'replace' );
+       }
+}
+
+/**
+ * Class to replace regex matches with a string similar to that used in preg_replace()
+ */
+class RegexlikeReplacer extends Replacer {
+       private $r;
+
+       /**
+        * @param string $r
+        */
+       function __construct( $r ) {
+               $this->r = $r;
+       }
+
+       /**
+        * @param array $matches
+        * @return string
+        */
+       function replace( $matches ) {
+               $pairs = array();
+               foreach ( $matches as $i => $match ) {
+                       $pairs["\$$i"] = $match;
+               }
+
+               return strtr( $this->r, $pairs );
+       }
+}
+
+/**
+ * Class to perform secondary replacement within each replacement string
+ */
+class DoubleReplacer extends Replacer {
+       /**
+        * @param $from
+        * @param $to
+        * @param int $index
+        */
+       function __construct( $from, $to, $index = 0 ) {
+               $this->from = $from;
+               $this->to = $to;
+               $this->index = $index;
+       }
+
+       /**
+        * @param array $matches
+        * @return mixed
+        */
+       function replace( $matches ) {
+               return str_replace( $this->from, $this->to, $matches[$this->index] );
+       }
+}
+
+/**
+ * Class to perform replacement based on a simple hashtable lookup
+ */
+class HashtableReplacer extends Replacer {
+       private $table, $index;
+
+       /**
+        * @param $table
+        * @param int $index
+        */
+       function __construct( $table, $index = 0 ) {
+               $this->table = $table;
+               $this->index = $index;
+       }
+
+       /**
+        * @param array $matches
+        * @return mixed
+        */
+       function replace( $matches ) {
+               return $this->table[$matches[$this->index]];
+       }
+}
+
+/**
+ * Replacement array for FSS with fallback to strtr()
+ * Supports lazy initialisation of FSS resource
+ */
+class ReplacementArray {
+       private $data = false;
+       private $fss = false;
+
+       /**
+        * Create an object with the specified replacement array
+        * The array should have the same form as the replacement array for strtr()
+        * @param array $data
+        */
+       function __construct( $data = array() ) {
+               $this->data = $data;
+       }
+
+       /**
+        * @return array
+        */
+       function __sleep() {
+               return array( 'data' );
+       }
+
+       function __wakeup() {
+               $this->fss = false;
+       }
+
+       /**
+        * Set the whole replacement array at once
+        * @param array $data
+        */
+       function setArray( $data ) {
+               $this->data = $data;
+               $this->fss = false;
+       }
+
+       /**
+        * @return array|bool
+        */
+       function getArray() {
+               return $this->data;
+       }
+
+       /**
+        * Set an element of the replacement array
+        * @param string $from
+        * @param string $to
+        */
+       function setPair( $from, $to ) {
+               $this->data[$from] = $to;
+               $this->fss = false;
+       }
+
+       /**
+        * @param array $data
+        */
+       function mergeArray( $data ) {
+               $this->data = array_merge( $this->data, $data );
+               $this->fss = false;
+       }
+
+       /**
+        * @param ReplacementArray $other
+        */
+       function merge( $other ) {
+               $this->data = array_merge( $this->data, $other->data );
+               $this->fss = false;
+       }
+
+       /**
+        * @param string $from
+        */
+       function removePair( $from ) {
+               unset( $this->data[$from] );
+               $this->fss = false;
+       }
+
+       /**
+        * @param array $data
+        */
+       function removeArray( $data ) {
+               foreach ( $data as $from => $to ) {
+                       $this->removePair( $from );
+               }
+               $this->fss = false;
+       }
+
+       /**
+        * @param string $subject
+        * @return string
+        */
+       function replace( $subject ) {
+               if ( function_exists( 'fss_prep_replace' ) ) {
+                       wfProfileIn( __METHOD__ . '-fss' );
+                       if ( $this->fss === false ) {
+                               $this->fss = fss_prep_replace( $this->data );
+                       }
+                       $result = fss_exec_replace( $this->fss, $subject );
+                       wfProfileOut( __METHOD__ . '-fss' );
+               } else {
+                       wfProfileIn( __METHOD__ . '-strtr' );
+                       $result = strtr( $subject, $this->data );
+                       wfProfileOut( __METHOD__ . '-strtr' );
+               }
+
+               return $result;
+       }
+}
+
+/**
+ * An iterator which works exactly like:
+ *
+ * foreach ( explode( $delim, $s ) as $element ) {
+ *    ...
+ * }
+ *
+ * Except it doesn't use 193 byte per element
+ */
+class ExplodeIterator implements Iterator {
+       // The subject string
+       private $subject, $subjectLength;
+
+       // The delimiter
+       private $delim, $delimLength;
+
+       // The position of the start of the line
+       private $curPos;
+
+       // The position after the end of the next delimiter
+       private $endPos;
+
+       // The current token
+       private $current;
+
+       /**
+        * Construct a DelimIterator
+        * @param string $delim
+        * @param string $subject
+        */
+       function __construct( $delim, $subject ) {
+               $this->subject = $subject;
+               $this->delim = $delim;
+
+               // Micro-optimisation (theoretical)
+               $this->subjectLength = strlen( $subject );
+               $this->delimLength = strlen( $delim );
+
+               $this->rewind();
+       }
+
+       function rewind() {
+               $this->curPos = 0;
+               $this->endPos = strpos( $this->subject, $this->delim );
+               $this->refreshCurrent();
+       }
+
+       function refreshCurrent() {
+               if ( $this->curPos === false ) {
+                       $this->current = false;
+               } elseif ( $this->curPos >= $this->subjectLength ) {
+                       $this->current = '';
+               } elseif ( $this->endPos === false ) {
+                       $this->current = substr( $this->subject, $this->curPos );
+               } else {
+                       $this->current = substr( $this->subject, $this->curPos, $this->endPos - $this->curPos );
+               }
+       }
+
+       function current() {
+               return $this->current;
+       }
+
+       /**
+        * @return int|bool Current position or boolean false if invalid
+        */
+       function key() {
+               return $this->curPos;
+       }
+
+       /**
+        * @return string
+        */
+       function next() {
+               if ( $this->endPos === false ) {
+                       $this->curPos = false;
+               } else {
+                       $this->curPos = $this->endPos + $this->delimLength;
+                       if ( $this->curPos >= $this->subjectLength ) {
+                               $this->endPos = false;
+                       } else {
+                               $this->endPos = strpos( $this->subject, $this->delim, $this->curPos );
+                       }
+               }
+               $this->refreshCurrent();
+
+               return $this->current;
+       }
+
+       /**
+        * @return bool
+        */
+       function valid() {
+               return $this->curPos !== false;
+       }
+}
diff --git a/includes/utils/UIDGenerator.php b/includes/utils/UIDGenerator.php
new file mode 100644 (file)
index 0000000..10ff957
--- /dev/null
@@ -0,0 +1,344 @@
+<?php
+/**
+ * This file deals with UID generation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+/**
+ * Class for getting statistically unique IDs
+ *
+ * @since 1.21
+ */
+class UIDGenerator {
+       /** @var UIDGenerator */
+       protected static $instance = null;
+
+       protected $nodeId32; // string; node ID in binary (32 bits)
+       protected $nodeId48; // string; node ID in binary (48 bits)
+
+       protected $lockFile88; // string; local file path
+       protected $lockFile128; // string; local file path
+
+       /** @var Array */
+       protected $fileHandles = array(); // cache file handles
+
+       const QUICK_RAND = 1; // get randomness from fast and insecure sources
+
+       protected function __construct() {
+               $idFile = wfTempDir() . '/mw-' . __CLASS__ . '-UID-nodeid';
+               $nodeId = is_file( $idFile ) ? file_get_contents( $idFile ) : '';
+               // Try to get some ID that uniquely identifies this machine (RFC 4122)...
+               if ( !preg_match( '/^[0-9a-f]{12}$/i', $nodeId ) ) {
+                       wfSuppressWarnings();
+                       if ( wfIsWindows() ) {
+                               // http://technet.microsoft.com/en-us/library/bb490913.aspx
+                               $csv = trim( wfShellExec( 'getmac /NH /FO CSV' ) );
+                               $line = substr( $csv, 0, strcspn( $csv, "\n" ) );
+                               $info = str_getcsv( $line );
+                               $nodeId = isset( $info[0] ) ? str_replace( '-', '', $info[0] ) : '';
+                       } elseif ( is_executable( '/sbin/ifconfig' ) ) { // Linux/BSD/Solaris/OS X
+                               // See http://linux.die.net/man/8/ifconfig
+                               $m = array();
+                               preg_match( '/\s([0-9a-f]{2}(:[0-9a-f]{2}){5})\s/',
+                                       wfShellExec( '/sbin/ifconfig -a' ), $m );
+                               $nodeId = isset( $m[1] ) ? str_replace( ':', '', $m[1] ) : '';
+                       }
+                       wfRestoreWarnings();
+                       if ( !preg_match( '/^[0-9a-f]{12}$/i', $nodeId ) ) {
+                               $nodeId = MWCryptRand::generateHex( 12, true );
+                               $nodeId[1] = dechex( hexdec( $nodeId[1] ) | 0x1 ); // set multicast bit
+                       }
+                       file_put_contents( $idFile, $nodeId ); // cache
+               }
+               $this->nodeId32 = wfBaseConvert( substr( sha1( $nodeId ), 0, 8 ), 16, 2, 32 );
+               $this->nodeId48 = wfBaseConvert( $nodeId, 16, 2, 48 );
+               // If different processes run as different users, they may have different temp dirs.
+               // This is dealt with by initializing the clock sequence number and counters randomly.
+               $this->lockFile88 = wfTempDir() . '/mw-' . __CLASS__ . '-UID-88';
+               $this->lockFile128 = wfTempDir() . '/mw-' . __CLASS__ . '-UID-128';
+       }
+
+       /**
+        * @return UIDGenerator
+        */
+       protected static function singleton() {
+               if ( self::$instance === null ) {
+                       self::$instance = new self();
+               }
+
+               return self::$instance;
+       }
+
+       /**
+        * Get a statistically unique 88-bit unsigned integer ID string.
+        * The bits of the UID are prefixed with the time (down to the millisecond).
+        *
+        * These IDs are suitable as values for the shard key of distributed data.
+        * If a column uses these as values, it should be declared UNIQUE to handle collisions.
+        * New rows almost always have higher UIDs, which makes B-TREE updates on INSERT fast.
+        * They can also be stored "DECIMAL(27) UNSIGNED" or BINARY(11) in MySQL.
+        *
+        * UID generation is serialized on each server (as the node ID is for the whole machine).
+        *
+        * @param $base integer Specifies a base other than 10
+        * @return string Number
+        * @throws MWException
+        */
+       public static function newTimestampedUID88( $base = 10 ) {
+               if ( !is_integer( $base ) || $base > 36 || $base < 2 ) {
+                       throw new MWException( "Base must an integer be between 2 and 36" );
+               }
+               $gen = self::singleton();
+               $time = $gen->getTimestampAndDelay( 'lockFile88', 1, 1024 );
+
+               return wfBaseConvert( $gen->getTimestampedID88( $time ), 2, $base );
+       }
+
+       /**
+        * @param array $time (UIDGenerator::millitime(), clock sequence)
+        * @return string 88 bits
+        */
+       protected function getTimestampedID88( array $info ) {
+               list( $time, $counter ) = $info;
+               // Take the 46 MSBs of "milliseconds since epoch"
+               $id_bin = $this->millisecondsSinceEpochBinary( $time );
+               // Add a 10 bit counter resulting in 56 bits total
+               $id_bin .= str_pad( decbin( $counter ), 10, '0', STR_PAD_LEFT );
+               // Add the 32 bit node ID resulting in 88 bits total
+               $id_bin .= $this->nodeId32;
+               // Convert to a 1-27 digit integer string
+               if ( strlen( $id_bin ) !== 88 ) {
+                       throw new MWException( "Detected overflow for millisecond timestamp." );
+               }
+
+               return $id_bin;
+       }
+
+       /**
+        * Get a statistically unique 128-bit unsigned integer ID string.
+        * The bits of the UID are prefixed with the time (down to the millisecond).
+        *
+        * These IDs are suitable as globally unique IDs, without any enforced uniqueness.
+        * New rows almost always have higher UIDs, which makes B-TREE updates on INSERT fast.
+        * They can also be stored as "DECIMAL(39) UNSIGNED" or BINARY(16) in MySQL.
+        *
+        * UID generation is serialized on each server (as the node ID is for the whole machine).
+        *
+        * @param $base integer Specifies a base other than 10
+        * @return string Number
+        * @throws MWException
+        */
+       public static function newTimestampedUID128( $base = 10 ) {
+               if ( !is_integer( $base ) || $base > 36 || $base < 2 ) {
+                       throw new MWException( "Base must be an integer between 2 and 36" );
+               }
+               $gen = self::singleton();
+               $time = $gen->getTimestampAndDelay( 'lockFile128', 16384, 1048576 );
+
+               return wfBaseConvert( $gen->getTimestampedID128( $time ), 2, $base );
+       }
+
+       /**
+        * @param array $info (UIDGenerator::millitime(), counter, clock sequence)
+        * @return string 128 bits
+        */
+       protected function getTimestampedID128( array $info ) {
+               list( $time, $counter, $clkSeq ) = $info;
+               // Take the 46 MSBs of "milliseconds since epoch"
+               $id_bin = $this->millisecondsSinceEpochBinary( $time );
+               // Add a 20 bit counter resulting in 66 bits total
+               $id_bin .= str_pad( decbin( $counter ), 20, '0', STR_PAD_LEFT );
+               // Add a 14 bit clock sequence number resulting in 80 bits total
+               $id_bin .= str_pad( decbin( $clkSeq ), 14, '0', STR_PAD_LEFT );
+               // Add the 48 bit node ID resulting in 128 bits total
+               $id_bin .= $this->nodeId48;
+               // Convert to a 1-39 digit integer string
+               if ( strlen( $id_bin ) !== 128 ) {
+                       throw new MWException( "Detected overflow for millisecond timestamp." );
+               }
+
+               return $id_bin;
+       }
+
+       /**
+        * Return an RFC4122 compliant v4 UUID
+        *
+        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
+        * @return string
+        * @throws MWException
+        */
+       public static function newUUIDv4( $flags = 0 ) {
+               $hex = ( $flags & self::QUICK_RAND )
+                       ? wfRandomString( 31 )
+                       : MWCryptRand::generateHex( 31 );
+
+               return sprintf( '%s-%s-%s-%s-%s',
+                       // "time_low" (32 bits)
+                       substr( $hex, 0, 8 ),
+                       // "time_mid" (16 bits)
+                       substr( $hex, 8, 4 ),
+                       // "time_hi_and_version" (16 bits)
+                       '4' . substr( $hex, 12, 3 ),
+                       // "clk_seq_hi_res (8 bits, variant is binary 10x) and "clk_seq_low" (8 bits)
+                       dechex( 0x8 | ( hexdec( $hex[15] ) & 0x3 ) ) . $hex[16] . substr( $hex, 17, 2 ),
+                       // "node" (48 bits)
+                       substr( $hex, 19, 12 )
+               );
+       }
+
+       /**
+        * Return an RFC4122 compliant v4 UUID
+        *
+        * @param $flags integer Bitfield (supports UIDGenerator::QUICK_RAND)
+        * @return string 32 hex characters with no hyphens
+        * @throws MWException
+        */
+       public static function newRawUUIDv4( $flags = 0 ) {
+               return str_replace( '-', '', self::newUUIDv4( $flags ) );
+       }
+
+       /**
+        * Get a (time,counter,clock sequence) where (time,counter) is higher
+        * than any previous (time,counter) value for the given clock sequence.
+        * This is useful for making UIDs sequential on a per-node bases.
+        *
+        * @param string $lockFile Name of a local lock file
+        * @param $clockSeqSize integer The number of possible clock sequence values
+        * @param $counterSize integer The number of possible counter values
+        * @return Array (result of UIDGenerator::millitime(), counter, clock sequence)
+        * @throws MWException
+        */
+       protected function getTimestampAndDelay( $lockFile, $clockSeqSize, $counterSize ) {
+               // Get the UID lock file handle
+               if ( isset( $this->fileHandles[$lockFile] ) ) {
+                       $handle = $this->fileHandles[$lockFile];
+               } else {
+                       $handle = fopen( $this->$lockFile, 'cb+' );
+                       $this->fileHandles[$lockFile] = $handle ?: null; // cache
+               }
+               // Acquire the UID lock file
+               if ( $handle === false ) {
+                       throw new MWException( "Could not open '{$this->$lockFile}'." );
+               } elseif ( !flock( $handle, LOCK_EX ) ) {
+                       throw new MWException( "Could not acquire '{$this->$lockFile}'." );
+               }
+               // Get the current timestamp, clock sequence number, last time, and counter
+               rewind( $handle );
+               $data = explode( ' ', fgets( $handle ) ); // "<clk seq> <sec> <msec> <counter> <offset>"
+               $clockChanged = false; // clock set back significantly?
+               if ( count( $data ) == 5 ) { // last UID info already initialized
+                       $clkSeq = (int)$data[0] % $clockSeqSize;
+                       $prevTime = array( (int)$data[1], (int)$data[2] );
+                       $offset = (int)$data[4] % $counterSize; // random counter offset
+                       $counter = 0; // counter for UIDs with the same timestamp
+                       // Delay until the clock reaches the time of the last ID.
+                       // This detects any microtime() drift among processes.
+                       $time = $this->timeWaitUntil( $prevTime );
+                       if ( !$time ) { // too long to delay?
+                               $clockChanged = true; // bump clock sequence number
+                               $time = self::millitime();
+                       } elseif ( $time == $prevTime ) {
+                               // Bump the counter if there are timestamp collisions
+                               $counter = (int)$data[3] % $counterSize;
+                               if ( ++$counter >= $counterSize ) { // sanity (starts at 0)
+                                       flock( $handle, LOCK_UN ); // abort
+                                       throw new MWException( "Counter overflow for timestamp value." );
+                               }
+                       }
+               } else { // last UID info not initialized
+                       $clkSeq = mt_rand( 0, $clockSeqSize - 1 );
+                       $counter = 0;
+                       $offset = mt_rand( 0, $counterSize - 1 );
+                       $time = self::millitime();
+               }
+               // microtime() and gettimeofday() can drift from time() at least on Windows.
+               // The drift is immediate for processes running while the system clock changes.
+               // time() does not have this problem. See https://bugs.php.net/bug.php?id=42659.
+               if ( abs( time() - $time[0] ) >= 2 ) {
+                       // We don't want processes using too high or low timestamps to avoid duplicate
+                       // UIDs and clock sequence number churn. This process should just be restarted.
+                       flock( $handle, LOCK_UN ); // abort
+                       throw new MWException( "Process clock is outdated or drifted." );
+               }
+               // If microtime() is synced and a clock change was detected, then the clock went back
+               if ( $clockChanged ) {
+                       // Bump the clock sequence number and also randomize the counter offset,
+                       // which is useful for UIDs that do not include the clock sequence number.
+                       $clkSeq = ( $clkSeq + 1 ) % $clockSeqSize;
+                       $offset = mt_rand( 0, $counterSize - 1 );
+                       trigger_error( "Clock was set back; sequence number incremented." );
+               }
+               // Update the (clock sequence number, timestamp, counter)
+               ftruncate( $handle, 0 );
+               rewind( $handle );
+               fwrite( $handle, "{$clkSeq} {$time[0]} {$time[1]} {$counter} {$offset}" );
+               fflush( $handle );
+               // Release the UID lock file
+               flock( $handle, LOCK_UN );
+
+               return array( $time, ( $counter + $offset ) % $counterSize, $clkSeq );
+       }
+
+       /**
+        * Wait till the current timestamp reaches $time and return the current
+        * timestamp. This returns false if it would have to wait more than 10ms.
+        *
+        * @param array $time Result of UIDGenerator::millitime()
+        * @return Array|bool UIDGenerator::millitime() result or false
+        */
+       protected function timeWaitUntil( array $time ) {
+               do {
+                       $ct = self::millitime();
+                       if ( $ct >= $time ) { // http://php.net/manual/en/language.operators.comparison.php
+                               return $ct; // current timestamp is higher than $time
+                       }
+               } while ( ( ( $time[0] - $ct[0] ) * 1000 + ( $time[1] - $ct[1] ) ) <= 10 );
+
+               return false;
+       }
+
+       /**
+        * @param array $time Result of UIDGenerator::millitime()
+        * @return string 46 MSBs of "milliseconds since epoch" in binary (rolls over in 4201)
+        */
+       protected function millisecondsSinceEpochBinary( array $time ) {
+               list( $sec, $msec ) = $time;
+               $ts = 1000 * $sec + $msec;
+               if ( $ts > pow( 2, 52 ) ) {
+                       throw new MWException( __METHOD__ .
+                               ': sorry, this function doesn\'t work after the year 144680' );
+               }
+
+               return substr( wfBaseConvert( $ts, 10, 2, 46 ), -46 );
+       }
+
+       /**
+        * @return Array (current time in seconds, milliseconds since then)
+        */
+       protected static function millitime() {
+               list( $msec, $sec ) = explode( ' ', microtime() );
+
+               return array( (int)$sec, (int)( $msec * 1000 ) );
+       }
+
+       function __destruct() {
+               array_map( 'fclose', $this->fileHandles );
+       }
+}
diff --git a/includes/utils/ZipDirectoryReader.php b/includes/utils/ZipDirectoryReader.php
new file mode 100644 (file)
index 0000000..1419bbb
--- /dev/null
@@ -0,0 +1,720 @@
+<?php
+/**
+ * ZIP file directories reader, for the purposes of upload verification.
+ *
+ * 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
+ */
+
+/**
+ * A class for reading ZIP file directories, for the purposes of upload
+ * verification.
+ *
+ * Only a functional interface is provided: ZipFileReader::read(). No access is
+ * given to object instances.
+ *
+ */
+class ZipDirectoryReader {
+       /**
+        * Read a ZIP file and call a function for each file discovered in it.
+        *
+        * Because this class is aimed at verification, an error is raised on
+        * suspicious or ambiguous input, instead of emulating some standard
+        * behavior.
+        *
+        * @param string $fileName The archive file name
+        * @param array $callback The callback function. It will be called for each file
+        *   with a single associative array each time, with members:
+        *
+        *      - name: The file name. Directories conventionally have a trailing
+        *        slash.
+        *
+        *      - mtime: The file modification time, in MediaWiki 14-char format
+        *
+        *      - size: The uncompressed file size
+        *
+        * @param array $options An associative array of read options, with the option
+        *    name in the key. This may currently contain:
+        *
+        *      - zip64: If this is set to true, then we will emulate a
+        *        library with ZIP64 support, like OpenJDK 7. If it is set to
+        *        false, then we will emulate a library with no knowledge of
+        *        ZIP64.
+        *
+        *        NOTE: The ZIP64 code is untested and probably doesn't work. It
+        *        turned out to be easier to just reject ZIP64 archive uploads,
+        *        since they are likely to be very rare. Confirming safety of a
+        *        ZIP64 file is fairly complex. What do you do with a file that is
+        *        ambiguous and broken when read with a non-ZIP64 reader, but valid
+        *        when read with a ZIP64 reader? This situation is normal for a
+        *        valid ZIP64 file, and working out what non-ZIP64 readers will make
+        *        of such a file is not trivial.
+        *
+        * @return Status object. The following fatal errors are defined:
+        *
+        *      - zip-file-open-error: The file could not be opened.
+        *
+        *      - zip-wrong-format: The file does not appear to be a ZIP file.
+        *
+        *      - zip-bad: There was something wrong or ambiguous about the file
+        *        data.
+        *
+        *      - zip-unsupported: The ZIP file uses features which
+        *        ZipDirectoryReader does not support.
+        *
+        * The default messages for those fatal errors are written in a way that
+        * makes sense for upload verification.
+        *
+        * If a fatal error is returned, more information about the error will be
+        * available in the debug log.
+        *
+        * Note that the callback function may be called any number of times before
+        * a fatal error is returned. If this occurs, the data sent to the callback
+        * function should be discarded.
+        */
+       public static function read( $fileName, $callback, $options = array() ) {
+               $zdr = new self( $fileName, $callback, $options );
+
+               return $zdr->execute();
+       }
+
+       /** The file name */
+       protected $fileName;
+
+       /** The opened file resource */
+       protected $file;
+
+       /** The cached length of the file, or null if it has not been loaded yet. */
+       protected $fileLength;
+
+       /** A segmented cache of the file contents */
+       protected $buffer;
+
+       /** The file data callback */
+       protected $callback;
+
+       /** The ZIP64 mode */
+       protected $zip64 = false;
+
+       /** Stored headers */
+       protected $eocdr, $eocdr64, $eocdr64Locator;
+
+       protected $data;
+
+       /** The "extra field" ID for ZIP64 central directory entries */
+       const ZIP64_EXTRA_HEADER = 0x0001;
+
+       /** The segment size for the file contents cache */
+       const SEGSIZE = 16384;
+
+       /** The index of the "general field" bit for UTF-8 file names */
+       const GENERAL_UTF8 = 11;
+
+       /** The index of the "general field" bit for central directory encryption */
+       const GENERAL_CD_ENCRYPTED = 13;
+
+       /**
+        * Private constructor
+        */
+       protected function __construct( $fileName, $callback, $options ) {
+               $this->fileName = $fileName;
+               $this->callback = $callback;
+
+               if ( isset( $options['zip64'] ) ) {
+                       $this->zip64 = $options['zip64'];
+               }
+       }
+
+       /**
+        * Read the directory according to settings in $this.
+        *
+        * @return Status
+        */
+       function execute() {
+               $this->file = fopen( $this->fileName, 'r' );
+               $this->data = array();
+               if ( !$this->file ) {
+                       return Status::newFatal( 'zip-file-open-error' );
+               }
+
+               $status = Status::newGood();
+               try {
+                       $this->readEndOfCentralDirectoryRecord();
+                       if ( $this->zip64 ) {
+                               list( $offset, $size ) = $this->findZip64CentralDirectory();
+                               $this->readCentralDirectory( $offset, $size );
+                       } else {
+                               if ( $this->eocdr['CD size'] == 0xffffffff
+                                       || $this->eocdr['CD offset'] == 0xffffffff
+                                       || $this->eocdr['CD entries total'] == 0xffff
+                               ) {
+                                       $this->error( 'zip-unsupported', 'Central directory header indicates ZIP64, ' .
+                                               'but we are in legacy mode. Rejecting this upload is necessary to avoid ' .
+                                               'opening vulnerabilities on clients using OpenJDK 7 or later.' );
+                               }
+
+                               list( $offset, $size ) = $this->findOldCentralDirectory();
+                               $this->readCentralDirectory( $offset, $size );
+                       }
+               } catch ( ZipDirectoryReaderError $e ) {
+                       $status->fatal( $e->getErrorCode() );
+               }
+
+               fclose( $this->file );
+
+               return $status;
+       }
+
+       /**
+        * Throw an error, and log a debug message
+        */
+       function error( $code, $debugMessage ) {
+               wfDebug( __CLASS__ . ": Fatal error: $debugMessage\n" );
+               throw new ZipDirectoryReaderError( $code );
+       }
+
+       /**
+        * Read the header which is at the end of the central directory,
+        * unimaginatively called the "end of central directory record" by the ZIP
+        * spec.
+        */
+       function readEndOfCentralDirectoryRecord() {
+               $info = array(
+                       'signature' => 4,
+                       'disk' => 2,
+                       'CD start disk' => 2,
+                       'CD entries this disk' => 2,
+                       'CD entries total' => 2,
+                       'CD size' => 4,
+                       'CD offset' => 4,
+                       'file comment length' => 2,
+               );
+               $structSize = $this->getStructSize( $info );
+               $startPos = $this->getFileLength() - 65536 - $structSize;
+               if ( $startPos < 0 ) {
+                       $startPos = 0;
+               }
+
+               $block = $this->getBlock( $startPos );
+               $sigPos = strrpos( $block, "PK\x05\x06" );
+               if ( $sigPos === false ) {
+                       $this->error( 'zip-wrong-format',
+                               "zip file lacks EOCDR signature. It probably isn't a zip file." );
+               }
+
+               $this->eocdr = $this->unpack( substr( $block, $sigPos ), $info );
+               $this->eocdr['EOCDR size'] = $structSize + $this->eocdr['file comment length'];
+
+               if ( $structSize + $this->eocdr['file comment length'] != strlen( $block ) - $sigPos ) {
+                       $this->error( 'zip-bad', 'trailing bytes after the end of the file comment' );
+               }
+               if ( $this->eocdr['disk'] !== 0
+                       || $this->eocdr['CD start disk'] !== 0
+               ) {
+                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR)' );
+               }
+               $this->eocdr += $this->unpack(
+                       $block,
+                       array( 'file comment' => array( 'string', $this->eocdr['file comment length'] ) ),
+                       $sigPos + $structSize );
+               $this->eocdr['position'] = $startPos + $sigPos;
+       }
+
+       /**
+        * Read the header called the "ZIP64 end of central directory locator". An
+        * error will be raised if it does not exist.
+        */
+       function readZip64EndOfCentralDirectoryLocator() {
+               $info = array(
+                       'signature' => array( 'string', 4 ),
+                       'eocdr64 start disk' => 4,
+                       'eocdr64 offset' => 8,
+                       'number of disks' => 4,
+               );
+               $structSize = $this->getStructSize( $info );
+
+               $start = $this->getFileLength() - $this->eocdr['EOCDR size'] - $structSize;
+               $block = $this->getBlock( $start, $structSize );
+               $this->eocdr64Locator = $data = $this->unpack( $block, $info );
+
+               if ( $data['signature'] !== "PK\x06\x07" ) {
+                       // Note: Java will allow this and continue to read the
+                       // EOCDR64, so we have to reject the upload, we can't
+                       // just use the EOCDR header instead.
+                       $this->error( 'zip-bad', 'wrong signature on Zip64 end of central directory locator' );
+               }
+       }
+
+       /**
+        * Read the header called the "ZIP64 end of central directory record". It
+        * may replace the regular "end of central directory record" in ZIP64 files.
+        */
+       function readZip64EndOfCentralDirectoryRecord() {
+               if ( $this->eocdr64Locator['eocdr64 start disk'] != 0
+                       || $this->eocdr64Locator['number of disks'] != 0
+               ) {
+                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR64 locator)' );
+               }
+
+               $info = array(
+                       'signature' => array( 'string', 4 ),
+                       'EOCDR64 size' => 8,
+                       'version made by' => 2,
+                       'version needed' => 2,
+                       'disk' => 4,
+                       'CD start disk' => 4,
+                       'CD entries this disk' => 8,
+                       'CD entries total' => 8,
+                       'CD size' => 8,
+                       'CD offset' => 8
+               );
+               $structSize = $this->getStructSize( $info );
+               $block = $this->getBlock( $this->eocdr64Locator['eocdr64 offset'], $structSize );
+               $this->eocdr64 = $data = $this->unpack( $block, $info );
+               if ( $data['signature'] !== "PK\x06\x06" ) {
+                       $this->error( 'zip-bad', 'wrong signature on Zip64 end of central directory record' );
+               }
+               if ( $data['disk'] !== 0
+                       || $data['CD start disk'] !== 0
+               ) {
+                       $this->error( 'zip-unsupported', 'more than one disk (in EOCDR64)' );
+               }
+       }
+
+       /**
+        * Find the location of the central directory, as would be seen by a
+        * non-ZIP64 reader.
+        *
+        * @return List containing offset, size and end position.
+        */
+       function findOldCentralDirectory() {
+               $size = $this->eocdr['CD size'];
+               $offset = $this->eocdr['CD offset'];
+               $endPos = $this->eocdr['position'];
+
+               // Some readers use the EOCDR position instead of the offset field
+               // to find the directory, so to be safe, we check if they both agree.
+               if ( $offset + $size != $endPos ) {
+                       $this->error( 'zip-bad', 'the central directory does not immediately precede the end ' .
+                               'of central directory record' );
+               }
+
+               return array( $offset, $size );
+       }
+
+       /**
+        * Find the location of the central directory, as would be seen by a
+        * ZIP64-compliant reader.
+        *
+        * @return array List containing offset, size and end position.
+        */
+       function findZip64CentralDirectory() {
+               // The spec is ambiguous about the exact rules of precedence between the
+               // ZIP64 headers and the original headers. Here we follow zip_util.c
+               // from OpenJDK 7.
+               $size = $this->eocdr['CD size'];
+               $offset = $this->eocdr['CD offset'];
+               $numEntries = $this->eocdr['CD entries total'];
+               $endPos = $this->eocdr['position'];
+               if ( $size == 0xffffffff
+                       || $offset == 0xffffffff
+                       || $numEntries == 0xffff
+               ) {
+                       $this->readZip64EndOfCentralDirectoryLocator();
+
+                       if ( isset( $this->eocdr64Locator['eocdr64 offset'] ) ) {
+                               $this->readZip64EndOfCentralDirectoryRecord();
+                               if ( isset( $this->eocdr64['CD offset'] ) ) {
+                                       $size = $this->eocdr64['CD size'];
+                                       $offset = $this->eocdr64['CD offset'];
+                                       $endPos = $this->eocdr64Locator['eocdr64 offset'];
+                               }
+                       }
+               }
+               // Some readers use the EOCDR position instead of the offset field
+               // to find the directory, so to be safe, we check if they both agree.
+               if ( $offset + $size != $endPos ) {
+                       $this->error( 'zip-bad', 'the central directory does not immediately precede the end ' .
+                               'of central directory record' );
+               }
+
+               return array( $offset, $size );
+       }
+
+       /**
+        * Read the central directory at the given location
+        */
+       function readCentralDirectory( $offset, $size ) {
+               $block = $this->getBlock( $offset, $size );
+
+               $fixedInfo = array(
+                       'signature' => array( 'string', 4 ),
+                       'version made by' => 2,
+                       'version needed' => 2,
+                       'general bits' => 2,
+                       'compression method' => 2,
+                       'mod time' => 2,
+                       'mod date' => 2,
+                       'crc-32' => 4,
+                       'compressed size' => 4,
+                       'uncompressed size' => 4,
+                       'name length' => 2,
+                       'extra field length' => 2,
+                       'comment length' => 2,
+                       'disk number start' => 2,
+                       'internal attrs' => 2,
+                       'external attrs' => 4,
+                       'local header offset' => 4,
+               );
+               $fixedSize = $this->getStructSize( $fixedInfo );
+
+               $pos = 0;
+               while ( $pos < $size ) {
+                       $data = $this->unpack( $block, $fixedInfo, $pos );
+                       $pos += $fixedSize;
+
+                       if ( $data['signature'] !== "PK\x01\x02" ) {
+                               $this->error( 'zip-bad', 'Invalid signature found in directory entry' );
+                       }
+
+                       $variableInfo = array(
+                               'name' => array( 'string', $data['name length'] ),
+                               'extra field' => array( 'string', $data['extra field length'] ),
+                               'comment' => array( 'string', $data['comment length'] ),
+                       );
+                       $data += $this->unpack( $block, $variableInfo, $pos );
+                       $pos += $this->getStructSize( $variableInfo );
+
+                       if ( $this->zip64 && (
+                                       $data['compressed size'] == 0xffffffff
+                                       || $data['uncompressed size'] == 0xffffffff
+                                       || $data['local header offset'] == 0xffffffff )
+                       ) {
+                               $zip64Data = $this->unpackZip64Extra( $data['extra field'] );
+                               if ( $zip64Data ) {
+                                       $data = $zip64Data + $data;
+                               }
+                       }
+
+                       if ( $this->testBit( $data['general bits'], self::GENERAL_CD_ENCRYPTED ) ) {
+                               $this->error( 'zip-unsupported', 'central directory encryption is not supported' );
+                       }
+
+                       // Convert the timestamp into MediaWiki format
+                       // For the format, please see the MS-DOS 2.0 Programmer's Reference,
+                       // pages 3-5 and 3-6.
+                       $time = $data['mod time'];
+                       $date = $data['mod date'];
+
+                       $year = 1980 + ( $date >> 9 );
+                       $month = ( $date >> 5 ) & 15;
+                       $day = $date & 31;
+                       $hour = ( $time >> 11 ) & 31;
+                       $minute = ( $time >> 5 ) & 63;
+                       $second = ( $time & 31 ) * 2;
+                       $timestamp = sprintf( "%04d%02d%02d%02d%02d%02d",
+                               $year, $month, $day, $hour, $minute, $second );
+
+                       // Convert the character set in the file name
+                       if ( !function_exists( 'iconv' )
+                               || $this->testBit( $data['general bits'], self::GENERAL_UTF8 )
+                       ) {
+                               $name = $data['name'];
+                       } else {
+                               $name = iconv( 'CP437', 'UTF-8', $data['name'] );
+                       }
+
+                       // Compile a data array for the user, with a sensible format
+                       $userData = array(
+                               'name' => $name,
+                               'mtime' => $timestamp,
+                               'size' => $data['uncompressed size'],
+                       );
+                       call_user_func( $this->callback, $userData );
+               }
+       }
+
+       /**
+        * Interpret ZIP64 "extra field" data and return an associative array.
+        * @return array|bool
+        */
+       function unpackZip64Extra( $extraField ) {
+               $extraHeaderInfo = array(
+                       'id' => 2,
+                       'size' => 2,
+               );
+               $extraHeaderSize = $this->getStructSize( $extraHeaderInfo );
+
+               $zip64ExtraInfo = array(
+                       'uncompressed size' => 8,
+                       'compressed size' => 8,
+                       'local header offset' => 8,
+                       'disk number start' => 4,
+               );
+
+               $extraPos = 0;
+               while ( $extraPos < strlen( $extraField ) ) {
+                       $extra = $this->unpack( $extraField, $extraHeaderInfo, $extraPos );
+                       $extraPos += $extraHeaderSize;
+                       $extra += $this->unpack( $extraField,
+                               array( 'data' => array( 'string', $extra['size'] ) ),
+                               $extraPos );
+                       $extraPos += $extra['size'];
+
+                       if ( $extra['id'] == self::ZIP64_EXTRA_HEADER ) {
+                               return $this->unpack( $extra['data'], $zip64ExtraInfo );
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Get the length of the file.
+        */
+       function getFileLength() {
+               if ( $this->fileLength === null ) {
+                       $stat = fstat( $this->file );
+                       $this->fileLength = $stat['size'];
+               }
+
+               return $this->fileLength;
+       }
+
+       /**
+        * Get the file contents from a given offset. If there are not enough bytes
+        * in the file to satisfy the request, an exception will be thrown.
+        *
+        * @param int $start The byte offset of the start of the block.
+        * @param int $length The number of bytes to return. If omitted, the remainder
+        *    of the file will be returned.
+        *
+        * @return string
+        */
+       function getBlock( $start, $length = null ) {
+               $fileLength = $this->getFileLength();
+               if ( $start >= $fileLength ) {
+                       $this->error( 'zip-bad', "getBlock() requested position $start, " .
+                               "file length is $fileLength" );
+               }
+               if ( $length === null ) {
+                       $length = $fileLength - $start;
+               }
+               $end = $start + $length;
+               if ( $end > $fileLength ) {
+                       $this->error( 'zip-bad', "getBlock() requested end position $end, " .
+                               "file length is $fileLength" );
+               }
+               $startSeg = floor( $start / self::SEGSIZE );
+               $endSeg = ceil( $end / self::SEGSIZE );
+
+               $block = '';
+               for ( $segIndex = $startSeg; $segIndex <= $endSeg; $segIndex++ ) {
+                       $block .= $this->getSegment( $segIndex );
+               }
+
+               $block = substr( $block,
+                       $start - $startSeg * self::SEGSIZE,
+                       $length );
+
+               if ( strlen( $block ) < $length ) {
+                       $this->error( 'zip-bad', 'getBlock() returned an unexpectedly small amount of data' );
+               }
+
+               return $block;
+       }
+
+       /**
+        * Get a section of the file starting at position $segIndex * self::SEGSIZE,
+        * of length self::SEGSIZE. The result is cached. This is a helper function
+        * for getBlock().
+        *
+        * If there are not enough bytes in the file to satisfy the request, the
+        * return value will be truncated. If a request is made for a segment beyond
+        * the end of the file, an empty string will be returned.
+        * @return string
+        */
+       function getSegment( $segIndex ) {
+               if ( !isset( $this->buffer[$segIndex] ) ) {
+                       $bytePos = $segIndex * self::SEGSIZE;
+                       if ( $bytePos >= $this->getFileLength() ) {
+                               $this->buffer[$segIndex] = '';
+
+                               return '';
+                       }
+                       if ( fseek( $this->file, $bytePos ) ) {
+                               $this->error( 'zip-bad', "seek to $bytePos failed" );
+                       }
+                       $seg = fread( $this->file, self::SEGSIZE );
+                       if ( $seg === false ) {
+                               $this->error( 'zip-bad', "read from $bytePos failed" );
+                       }
+                       $this->buffer[$segIndex] = $seg;
+               }
+
+               return $this->buffer[$segIndex];
+       }
+
+       /**
+        * Get the size of a structure in bytes. See unpack() for the format of $struct.
+        * @return int
+        */
+       function getStructSize( $struct ) {
+               $size = 0;
+               foreach ( $struct as $type ) {
+                       if ( is_array( $type ) ) {
+                               list( , $fieldSize ) = $type;
+                               $size += $fieldSize;
+                       } else {
+                               $size += $type;
+                       }
+               }
+
+               return $size;
+       }
+
+       /**
+        * Unpack a binary structure. This is like the built-in unpack() function
+        * except nicer.
+        *
+        * @param string $string The binary data input
+        *
+        * @param array $struct An associative array giving structure members and their
+        *    types. In the key is the field name. The value may be either an
+        *    integer, in which case the field is a little-endian unsigned integer
+        *    encoded in the given number of bytes, or an array, in which case the
+        *    first element of the array is the type name, and the subsequent
+        *    elements are type-dependent parameters. Only one such type is defined:
+        *       - "string": The second array element gives the length of string.
+        *          Not null terminated.
+        *
+        * @param int $offset The offset into the string at which to start unpacking.
+        *
+        * @throws MWException
+        * @return array Unpacked associative array. Note that large integers in the input
+        *    may be represented as floating point numbers in the return value, so
+        *    the use of weak comparison is advised.
+        */
+       function unpack( $string, $struct, $offset = 0 ) {
+               $size = $this->getStructSize( $struct );
+               if ( $offset + $size > strlen( $string ) ) {
+                       $this->error( 'zip-bad', 'unpack() would run past the end of the supplied string' );
+               }
+
+               $data = array();
+               $pos = $offset;
+               foreach ( $struct as $key => $type ) {
+                       if ( is_array( $type ) ) {
+                               list( $typeName, $fieldSize ) = $type;
+                               switch ( $typeName ) {
+                                       case 'string':
+                                               $data[$key] = substr( $string, $pos, $fieldSize );
+                                               $pos += $fieldSize;
+                                               break;
+                                       default:
+                                               throw new MWException( __METHOD__ . ": invalid type \"$typeName\"" );
+                               }
+                       } else {
+                               // Unsigned little-endian integer
+                               $length = intval( $type );
+
+                               // Calculate the value. Use an algorithm which automatically
+                               // upgrades the value to floating point if necessary.
+                               $value = 0;
+                               for ( $i = $length - 1; $i >= 0; $i-- ) {
+                                       $value *= 256;
+                                       $value += ord( $string[$pos + $i] );
+                               }
+
+                               // Throw an exception if there was loss of precision
+                               if ( $value > pow( 2, 52 ) ) {
+                                       $this->error( 'zip-unsupported', 'number too large to be stored in a double. ' .
+                                               'This could happen if we tried to unpack a 64-bit structure ' .
+                                               'at an invalid location.' );
+                               }
+                               $data[$key] = $value;
+                               $pos += $length;
+                       }
+               }
+
+               return $data;
+       }
+
+       /**
+        * Returns a bit from a given position in an integer value, converted to
+        * boolean.
+        *
+        * @param $value integer
+        * @param int $bitIndex The index of the bit, where 0 is the LSB.
+        * @return bool
+        */
+       function testBit( $value, $bitIndex ) {
+               return (bool)( ( $value >> $bitIndex ) & 1 );
+       }
+
+       /**
+        * Debugging helper function which dumps a string in hexdump -C format.
+        */
+       function hexDump( $s ) {
+               $n = strlen( $s );
+               for ( $i = 0; $i < $n; $i += 16 ) {
+                       printf( "%08X ", $i );
+                       for ( $j = 0; $j < 16; $j++ ) {
+                               print " ";
+                               if ( $j == 8 ) {
+                                       print " ";
+                               }
+                               if ( $i + $j >= $n ) {
+                                       print "  ";
+                               } else {
+                                       printf( "%02X", ord( $s[$i + $j] ) );
+                               }
+                       }
+
+                       print "  |";
+                       for ( $j = 0; $j < 16; $j++ ) {
+                               if ( $i + $j >= $n ) {
+                                       print " ";
+                               } elseif ( ctype_print( $s[$i + $j] ) ) {
+                                       print $s[$i + $j];
+                               } else {
+                                       print '.';
+                               }
+                       }
+                       print "|\n";
+               }
+       }
+}
+
+/**
+ * Internal exception class. Will be caught by private code.
+ */
+class ZipDirectoryReaderError extends Exception {
+       protected $errorCode;
+
+       function __construct( $code ) {
+               $this->errorCode = $code;
+               parent::__construct( "ZipDirectoryReader error: $code" );
+       }
+
+       /**
+        * @return mixed
+        */
+       function getErrorCode() {
+               return $this->errorCode;
+       }
+}
index b18fb80..8885d0e 100644 (file)
--- a/index.php
+++ b/index.php
@@ -42,7 +42,7 @@ if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.
 
 # Initialise common code.  This gives us access to GlobalFunctions, the
 # AutoLoader, and the globals $wgRequest, $wgOut, $wgUser, $wgLang and
-# $wgContLang, amongst others; it does *not* load $wgTitle
+# $wgContLang, amongst others
 require __DIR__ . '/includes/WebStart.php';
 
 $mediaWiki = new MediaWiki();
index 527f382..0026fdf 100644 (file)
@@ -63,6 +63,7 @@ class FakeConverter {
        function markNoConversion( $text, $noParse = false ) { return $text; }
        function convertCategoryKey( $key ) { return $key; }
        function convertLinkToAllVariants( $text ) { return $this->autoConvertToAllVariants( $text ); }
+       /** @deprecated since 1.22 is no longer used */
        function armourMath( $text ) { return $text; }
        function validateVariant( $variant = null ) { return $variant === $this->mLang->getCode() ? $variant : null; }
        function translate( $text, $variant ) { return $text; }
@@ -212,8 +213,8 @@ class Language {
        protected static function newFromCode( $code ) {
                // Protect against path traversal below
                if ( !Language::isValidCode( $code )
-                       || strcspn( $code, ":/\\\000" ) !== strlen( $code ) )
-               {
+                       || strcspn( $code, ":/\\\000" ) !== strlen( $code )
+               {
                        throw new MWException( "Invalid language code \"$code\"" );
                }
 
@@ -1501,8 +1502,7 @@ class Language {
                if (
                        ( $zy > 1582 ) || ( ( $zy == 1582 ) && ( $zm > 10 ) ) ||
                        ( ( $zy == 1582 ) && ( $zm == 10 ) && ( $zd > 14 ) )
-               )
-               {
+               ) {
                        $zjd = (int)( ( 1461 * ( $zy + 4800 + (int)( ( $zm - 14 ) / 12 ) ) ) / 4 ) +
                                        (int)( ( 367 * ( $zm - 2 - 12 * ( (int)( ( $zm - 14 ) / 12 ) ) ) ) / 12 ) -
                                        (int)( ( 3 * (int)( ( ( $zy + 4900 + (int)( ( $zm - 14 ) / 12 ) ) / 100 ) ) ) / 4 ) +
@@ -1752,8 +1752,7 @@ class Language {
                                ( ( $gy > 1912 ) && ( $gy < 1926 ) ) ||
                                ( ( $gy == 1926 ) && ( $gm < 12 ) ) ||
                                ( ( $gy == 1926 ) && ( $gm == 12 ) && ( $gd < 26 ) )
-                       )
-                       {
+                       ) {
                                # Taishō period
                                $gy_gannen = $gy - 1912 + 1;
                                $gy_offset = $gy_gannen;
@@ -1765,8 +1764,7 @@ class Language {
                                ( ( $gy == 1926 ) && ( $gm == 12 ) && ( $gd >= 26 ) ) ||
                                ( ( $gy > 1926 ) && ( $gy < 1989 ) ) ||
                                ( ( $gy == 1989 ) && ( $gm == 1 ) && ( $gd < 8 ) )
-                       )
-                       {
+                       ) {
                                # Shōwa period
                                $gy_gannen = $gy - 1926 + 1;
                                $gy_offset = $gy_gannen;
@@ -3324,11 +3322,13 @@ class Language {
                                $length -= $eLength;
                                $string = substr( $string, 0, $length ); // xyz...
                                $string = $this->removeBadCharLast( $string );
+                               $string = rtrim( $string );
                                $string = $string . $ellipsis;
                        } else {
                                $length += $eLength;
                                $string = substr( $string, $length ); // ...xyz
                                $string = $this->removeBadCharFirst( $string );
+                               $string = ltrim( $string );
                                $string = $ellipsis . $string;
                        }
                }
@@ -3632,17 +3632,10 @@ class Language {
         */
        function convertPlural( $count, $forms ) {
                // Handle explicit n=pluralform cases
-               foreach ( $forms as $index => $form ) {
-                       if ( preg_match( '/^\d+=/i', $form ) ) {
-                               $pos = strpos( $form, '=' );
-                               if ( substr( $form, 0, $pos ) === (string)$count ) {
-                                       return substr( $form, $pos + 1 );
-                               }
-                               unset( $forms[$index] );
-                       }
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
                }
-
-               $forms = array_values( $forms );
                if ( !count( $forms ) ) {
                        return '';
                }
@@ -3652,6 +3645,34 @@ class Language {
                return $forms[$pluralForm];
        }
 
+       /**
+        * Handles explicit plural forms for Language::convertPlural()
+        *
+        * In {{PLURAL:$1|0=nothing|one|many}}, 0=nothing will be returned if $1 equals zero.
+        * If an explicitly defined plural form matches the $count, then
+        * string value returned, otherwise array returned for further consideration
+        * by CLDR rules or overridden convertPlural().
+        *
+        * @since 1.23
+        *
+        * @param int $count non-localized number
+        * @param array $forms different plural forms
+        *
+        * @return array|string
+        */
+       protected function handleExplicitPluralForms( $count, array $forms ) {
+               foreach ( $forms as $index => $form ) {
+                       if ( preg_match( '/\d+=/i', $form ) ) {
+                               $pos = strpos( $form, '=' );
+                               if ( substr( $form, 0, $pos ) === (string) $count ) {
+                                       return substr( $form, $pos + 1 );
+                               }
+                               unset( $forms[$index] );
+                       }
+               }
+               return array_values( $forms );
+       }
+
        /**
         * Checks that convertPlural was given an array and pads it to requested
         * amount of forms by copying the last one.
@@ -3811,6 +3832,7 @@ class Language {
         *
         * @param $text string
         * @return string
+        * @deprecated since 1.22 is no longer used
         */
        public function armourMath( $text ) {
                return $this->mConverter->armourMath( $text );
@@ -3949,6 +3971,16 @@ class Language {
                return self::$dataCache->getItem( $this->mCode, 'linkTrail' );
        }
 
+       /**
+        * A regular expression character set to match legal word-prefixing
+        * characters which should be merged onto a link of the form foo[[bar]].
+        *
+        * @return string
+        */
+       public function linkPrefixCharset() {
+               return self::$dataCache->getItem( $this->mCode, 'linkPrefixCharset' );
+       }
+
        /**
         * @return Language
         */
@@ -4034,8 +4066,8 @@ class Language {
        public static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
                // Protect against path traversal
                if ( !Language::isValidCode( $code )
-                       || strcspn( $code, ":/\\\000" ) !== strlen( $code ) )
-               {
+                       || strcspn( $code, ":/\\\000" ) !== strlen( $code )
+               {
                        throw new MWException( "Invalid language code \"$code\"" );
                }
 
@@ -4468,7 +4500,7 @@ class Language {
                        $nlink = htmlspecialchars( $next );
                } else {
                        $nlink = $this->numLink( $title, $offset + $limit, $limit,
-                               $query, $next, 'prevn-title', 'mw-nextlink' );
+                               $query, $next, 'nextn-title', 'mw-nextlink' );
                }
 
                # Make links to set number of items per page
index ccf9b1e..cdaab2c 100644 (file)
@@ -70,7 +70,7 @@ class LanguageConverter {
        public $mMaxDepth = 10;
        public $mVarSeparatorPattern;
 
-       const CACHE_VERSION_KEY = 'VERSION 6';
+       const CACHE_VERSION_KEY = 'VERSION 7';
 
        /**
         * Constructor
@@ -102,8 +102,7 @@ class LanguageConverter {
                        'R' => 'R',       // raw content
                        'D' => 'D',       // convert description (subclass implement)
                        '-' => '-',       // remove convert (not implement)
-                       'H' => 'H',       // add rule for convert code
-                                                 // (but no display in placed code)
+                       'H' => 'H',       // add rule for convert code (but no display in placed code)
                        'N' => 'N'        // current variant name
                );
                $this->mFlags = array_merge( $defaultflags, $flags );
@@ -402,9 +401,9 @@ class LanguageConverter {
                        $startPos = $elementPos + strlen( $element );
 
                        // Translate any alt or title attributes inside the matched element
-                       if ( $element !== '' && preg_match( '/^(<[^>\s]*)\s([^>]*)(.*)$/', $element,
-                               $elementMatches ) )
-                       {
+                       if ( $element !== ''
+                               && preg_match( '/^(<[^>\s]*)\s([^>]*)(.*)$/', $element, $elementMatches )
+                       {
                                $attrs = Sanitizer::decodeTagAttributes( $elementMatches[2] );
                                $changed = false;
                                foreach ( array( 'title', 'alt' ) as $attrName ) {
@@ -778,12 +777,12 @@ class LanguageConverter {
                $ns = NS_MAIN;
 
                if ( $disableLinkConversion ||
-                        ( !$ignoreOtherCond &&
-                          ( $isredir == 'no'
-                                || $action == 'edit'
-                                || $action == 'submit'
-                                || $linkconvert == 'no'
-                                || $wgUser->getOption( 'noconvertlink' ) == 1 ) ) ) {
+                       ( !$ignoreOtherCond &&
+                               ( $isredir == 'no'
+                                       || $action == 'edit'
+                                       || $action == 'submit'
+                                       || $linkconvert == 'no'
+                                       || $wgUser->getOption( 'noconvertlink' ) == 1 ) ) ) {
                        return;
                }
 
@@ -876,8 +875,7 @@ class LanguageConverter {
                        $this->mTables = $wgLangConvMemc->get( $this->mCacheKey );
                        wfProfileOut( __METHOD__ . '-cache' );
                }
-               if ( !$this->mTables
-                        || !array_key_exists( self::CACHE_VERSION_KEY, $this->mTables ) ) {
+               if ( !$this->mTables || !array_key_exists( self::CACHE_VERSION_KEY, $this->mTables ) ) {
                        wfProfileIn( __METHOD__ . '-recache' );
                        // not in cache, or we need a fresh reload.
                        // We will first load the default tables
@@ -1004,8 +1002,7 @@ class LanguageConverter {
                                continue;
                        }
                        $mappings = explode( '}-', $block, 2 );
-                       $stripped = str_replace( array( "'", '"', '*', '#' ), '',
-                                                                        $mappings[0] );
+                       $stripped = str_replace( array( "'", '"', '*', '#' ), '', $mappings[0] );
                        $table = StringUtils::explode( ';', $stripped );
                        foreach ( $table as $t ) {
                                $m = explode( '=>', $t, 3 );
@@ -1103,6 +1100,7 @@ class LanguageConverter {
         * @param $text String: text to armour against conversion
         * @return String: armoured text where { and } have been converted to
         *                 &#123; and &#125;
+        * @deprecated since 1.22 is no longer used
         */
        public function armourMath( $text ) {
                // convert '-{' and '}-' to '-&#123;' and '&#125;-' to prevent
@@ -1284,9 +1282,9 @@ class ConverterRule {
                                $from = trim( $u[0] );
                                $v = trim( $u[1] );
                                if ( array_key_exists( $v, $unidtable )
-                                        && !is_array( $unidtable[$v] )
-                                        && $to
-                                        && in_array( $v, $variants ) ) {
+                                       && !is_array( $unidtable[$v] )
+                                       && $to
+                                       && in_array( $v, $variants ) ) {
                                        $unidtable[$v] = array( $from => $to );
                                } elseif ( $to && in_array( $v, $variants ) ) {
                                        $unidtable[$v][$from] = $to;
@@ -1352,8 +1350,7 @@ class ConverterRule {
                                $disp = $disp[0];
                        }
                        // or display frist text under disable manual convert
-                       if ( !$disp
-                                && $this->mConverter->mManualLevel[$variant] == 'disable' ) {
+                       if ( !$disp && $this->mConverter->mManualLevel[$variant] == 'disable' ) {
                                if ( count( $bidtable ) > 0 ) {
                                        $disp = array_values( $bidtable );
                                        $disp = $disp[0];
@@ -1445,8 +1442,8 @@ class ConverterRule {
                        }
                        /* for unidirectional array fill to convert tables */
                        if ( ( $manLevel[$v] == 'bidirectional' || $manLevel[$v] == 'unidirectional' )
-                               && isset( $unidtable[$v] ) )
-                       {
+                               && isset( $unidtable[$v] )
+                       {
                                if ( isset( $this->mConvTable[$v] ) ) {
                                        $this->mConvTable[$v] = array_merge( $this->mConvTable[$v], $unidtable[$v] );
                                } else {
@@ -1476,8 +1473,9 @@ class ConverterRule {
                                // then convert <text to convert> to current language
                                $this->mRules = $this->mConverter->autoConvert( $this->mRules,
                                        $variant );
-                       } else { // if current variant no in flags,
-                                  // then we check its fallback variants.
+                       } else {
+                               // if current variant no in flags,
+                               // then we check its fallback variants.
                                $variantFallbacks =
                                        $this->mConverter->getVariantFallbacks( $variant );
                                if ( is_array( $variantFallbacks ) ) {
index 929c513..c5c7d23 100644 (file)
@@ -47,7 +47,7 @@
        'als' => 'Alemannisch', # Alemannic -- not a valid code, for compatibility. See gsw.
        'am' => 'አማርኛ', # Amharic
        'an' => 'aragonés',    # Aragonese
-       'ang' => 'Ænglisc',    # Old English (Bug 23283)
+       'ang' => 'Ænglisc',    # Old English, bug 23283
        'anp' => 'अङ्गिका',       # Angika
        'ar' => 'العربية',       # Arabic
        'arc' => 'ܐܪܡܝܐ',  # Aramaic
@@ -70,9 +70,9 @@
        'bcl' => 'Bikol Central', # Bikol: Central Bicolano language
        'be' => 'беларуская', #  Belarusian normative
        'be-tarask' => "беларуская (тарашкевіца)\xE2\x80\x8E",     # Belarusian in Taraskievica orthography
-       'be-x-old' => "беларуская (тарашкевіца)\xE2\x80\x8E",      # Belarusian in Taraskievica orthography; compat link
+       'be-x-old' => "беларуская (тарашкевіца)\xE2\x80\x8E",      # (be-tarask compat)
        'bg' => 'български',   # Bulgarian
-       'bh' => 'भोजपुरी',        # Bihari macro language. Falls back to Bhojpuri (bho). The name actually says "Bhojpuri".
+       'bh' => 'भोजपुरी',        # Bihari macro language. Falls back to Bhojpuri (bho)
        'bho' => 'भोजपुरी',       # Bhojpuri
        'bi' => 'Bislama',              # Bislama
        'bjn' => 'Bahasa Banjar',       # Banjarese
        'crh' => 'qırımtatarca',   # Crimean Tatar (multiple scripts - defaults to Latin)
        'crh-latn' => "qırımtatarca (Latin)\xE2\x80\x8E",       # Crimean Tatar (Latin)
        'crh-cyrl' => "къырымтатарджа (Кирилл)\xE2\x80\x8E",       # Crimean Tatar (Cyrillic)
-       'cs' => 'česky',       # Czech
+       'cs' => 'čeština',    # Czech
        'csb' => 'kaszëbsczi', # Cassubian
        'cu' => 'словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ',      # Old Church Slavonic (ancient language)
        'cv' => 'Чӑвашла',       # Chuvash
        'gl' => 'galego',               # Galician
        'glk' => 'گیلکی',  # Gilaki
        'gn' => 'Avañe\'ẽ',  # Guaraní, Paraguayan
+       'gom-latn' => 'Konknni',        # Goan Konkani (Latin script)
        'got' => '𐌲𐌿𐍄𐌹𐍃𐌺',    # Gothic
        'grc' => 'Ἀρχαία ἑλληνικὴ', # Ancient Greek
        'gsw' => 'Alemannisch', # Alemannic
        'ig' => 'Igbo',                 # Igbo
        'ii' => 'ꆇꉙ',       # Sichuan Yi
        'ik' => 'Iñupiak',     # Inupiak (Inupiatun, Northwest Alaska / Inupiatun, North Alaskan)
-       'ike-cans' => 'ᐃᓄᒃᑎᑐᑦ',     # Inuktitut, Eastern Canadian/Eastern Canadian "Eskimo"/"Eastern Arctic Eskimo"/Inuit (Unified Canadian Aboriginal Syllabics)
+       'ike-cans' => 'ᐃᓄᒃᑎᑐᑦ',     # Inuktitut, Eastern Canadian (Unified Canadian Aboriginal Syllabics)
        'ike-latn' => 'inuktitut',      # Inuktitut, Eastern Canadian (Latin script)
        'ilo' => 'Ilokano',     # Ilokano
        'inh' => 'ГӀалгӀай',    # Ingush
        'io' => 'Ido',                  # Ido
        'is' => 'íslenska',    # Icelandic
        'it' => 'italiano',             # Italian
-       'iu' => 'ᐃᓄᒃᑎᑐᑦ/inuktitut', # Inuktitut (macro language - do no localise, see ike/ikt - falls back to ike-cans)
+       'iu' => 'ᐃᓄᒃᑎᑐᑦ/inuktitut', # Inuktitut (macro language, see ike/ikt, falls back to ike-cans)
        'ja' => '日本語',    # Japanese
        'jam' => 'Patois',      # Jamaican Creole English
        'jbo' => 'Lojban',              # Lojban
        'lmo' => 'lumbaart',    # Lombard
        'ln' => 'lingála',             # Lingala
        'lo' => 'ລາວ',    # Laotian
+       'lrc' => 'لوری',    # Northern Luri
        'loz' => 'Silozi', # Lozi
        'lt' => 'lietuvių',    # Lithuanian
        'ltg' => 'latgaļu',    # Latgalian
        'lus' => 'Mizo ţawng', # Mizo/Lushai
        'lv' => 'latviešu',    # Latvian
-       'lzh' => '文言',      # Literary Chinese -- (bug 8217) lzh instead of zh-classical, http://www.sil.org/iso639-3/codes.asp?order=639_3&letter=l
+       'lzh' => '文言',      # Literary Chinese, bug 8217
        'lzz' => 'Lazuri',      # Laz
        'mai' => 'मैथिली', # Maithili
        'map-bms' => 'Basa Banyumasan', # Banyumasan
        'myv' => 'эрзянь',        # Erzya
        'mzn' => 'مازِرونی',            # Mazanderani
        'na' => 'Dorerin Naoero',               # Nauruan
-       'nah' => 'Nāhuatl',            # Nahuatl, en:Wikipedia writes Nahuatlahtolli, while another form is Náhuatl
-       'nan' => 'Bân-lâm-gú', # Min-nan -- (bug 8217) nan instead of zh-min-nan, http://www.sil.org/iso639-3/codes.asp?order=639_3&letter=n
+       'nah' => 'Nāhuatl',            # Nahuatl (not in ISO 639-3)
+       'nan' => 'Bân-lâm-gú', # Min-nan, bug 8217
        'nap' => 'Napulitano',  # Neapolitan, bug 43793
        'nb' => "norsk bokmål",                # Norwegian (Bokmal)
        'nds' => 'Plattdüütsch',      # Low German ''or'' Low Saxon
        'oc' => 'occitan',              # Occitan
        'om' => 'Oromoo',               # Oromo
        'or' => 'ଓଡ଼ିଆ',              # Oriya
-       'os' => 'Ирон', # Ossetic -- fixed per bug 29091
+       'os' => 'Ирон', # Ossetic, bug 29091
        'pa' => 'ਪੰਜਾਬੀ', # Eastern Punjabi (Gurmukhi script) (pan)
        'pag' => 'Pangasinan',  # Pangasinan
        'pam' => 'Kapampangan',   # Pampanga
        'pt' => 'português',   # Portuguese
        'pt-br' => 'português do Brasil',      # Brazilian Portuguese
        'qu' => 'Runa Simi',    # Southern Quechua
-       'qug' => 'Runa shimi',  # Kichwa/Northern Quechua (one of the codes it covers; temporarily used until Kichwa has its own)
+       'qug' => 'Runa shimi',  # Kichwa/Northern Quechua (temporarily used until Kichwa has its own)
        'rgn' => 'Rumagnôl',   # Romagnol
        'rif' => 'Tarifit',     # Tarifit
        'rm' => 'rumantsch',    # Raeto-Romance
        'war' => 'Winaray', # Waray-Waray
        'wo' => 'Wolof',                # Wolof
        'wuu' => '吴语',              # Wu Chinese
-       'xal' => 'хальмг',                # Kalmyk-Oirat (Kalmuk, Kalmuck, Kalmack, Qalmaq, Kalmytskii Jazyk, Khal:mag, Oirat, Volga Oirat, European Oirat, Western Mongolian)
+       'xal' => 'хальмг',                # Kalmyk-Oirat
        'xh' => 'isiXhosa',             # Xhosan
        'xmf' => 'მარგალური', # Mingrelian
        'yi' => 'ייִדיש', # Yiddish
        'yo' => 'Yorùbá',     # Yoruba
-       'yue' => '粵語',      # Cantonese -- (bug 8217) yue instead of zh-yue, http://www.sil.org/iso639-3/codes.asp?order=639_3&letter=y
+       'yue' => '粵語',      # Cantonese
        'za' => 'Vahcuengh',    # Zhuang
        'zea' => 'Zeêuws',     # Zeeuws/Zeaws
        'zh' => '中文',                                               # (Zhōng Wén) - Chinese
index 6497b50..d3e78fe 100644 (file)
@@ -46,6 +46,10 @@ class LanguageBe_tarask extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 3da7711..072e857 100644 (file)
@@ -28,7 +28,6 @@
  */
 class LanguageBs extends Language {
 
-
        /**
         * Convert from the nominative form of a noun to some other case
         * Invoked with {{GRAMMAR:case|word}}
index 975157f..0ae0524 100644 (file)
@@ -49,7 +49,7 @@ class LanguageDsb extends Language {
                        case 'lokatiw': # lokatiw
                                $word = 'wo ' . $word;
                                break;
-                       }
+               }
 
                return $word; # this will return the original value for 'nominatiw' (nominativ) and all undefined case values
        }
index ba8a53c..23a2916 100644 (file)
@@ -35,6 +35,10 @@ class LanguageGv extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 910bc10..0c65ec7 100644 (file)
@@ -34,6 +34,10 @@ class LanguageHr extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 5623f3c..1fc1404 100644 (file)
@@ -49,7 +49,7 @@ class LanguageHsb extends Language {
                        case 'lokatiw': # lokatiw
                                $word = 'wo ' . $word;
                                break;
-                       }
+               }
 
                return $word; # this will return the original value for 'nominatiw' (nominativ) and all undefined case values
        }
index 5a7bbf3..4e08613 100644 (file)
@@ -727,7 +727,7 @@ class LanguageKk_cyrl extends Language {
                $lastLetter[0] = $ar[count( $ar ) - 1];
 
                // Find the last vowel in the word
-               $lastLetter[1] = NULL;
+               $lastLetter[1] = null;
                foreach ( $wordReversed as $xvalue ) {
                        foreach ( $allVowels as $yvalue ) {
                                if ( strcmp( $xvalue, $yvalue ) == 0 ) {
@@ -737,7 +737,7 @@ class LanguageKk_cyrl extends Language {
                                        continue;
                                }
                        }
-                       if ( $lastLetter[1] !== NULL ) {
+                       if ( $lastLetter[1] !== null ) {
                                break;
                        } else {
                                continue;
index 09c5727..d25ce71 100644 (file)
@@ -189,6 +189,10 @@ class LanguageKsh extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index f37e2d5..7ea67f2 100644 (file)
@@ -67,7 +67,6 @@ class LanguageOs extends Language {
                # Variable for ending
                $ending = '';
 
-
                # CHecking if the $word is in plural form
                if ( preg_match( '/тæ$/u', $word ) ) {
                        $word = mb_substr( $word, 0, -1 );
index 11b42cf..243a876 100644 (file)
@@ -122,6 +122,10 @@ class LanguageRu extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 6f0ff4b..7310e8e 100644 (file)
@@ -246,6 +246,10 @@ class LanguageSr extends LanguageSr_ec {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index cb9e819..4787856 100644 (file)
@@ -34,6 +34,10 @@ class LanguageSr_ec extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 99d1293..3f086df 100644 (file)
@@ -34,6 +34,10 @@ class LanguageSr_el extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index 887f05c..8d2fe16 100644 (file)
@@ -21,7 +21,6 @@
  * @ingroup Language
  */
 
-
 /**
  * Turkish (Türkçe)
  *
index fc1e8a8..f362329 100644 (file)
@@ -66,7 +66,7 @@ class LanguageTyv extends Language {
                $wordReversed = array_reverse( $ar[0] ); // Here's an array with the order of the letters in the word reversed so we can find a match quicker *shrug*
 
                // Find the last vowel in the word
-               $wordLastVowel = NULL;
+               $wordLastVowel = null;
                foreach ( $wordReversed as $xvalue ) {
                        foreach ( $allVowels as $yvalue ) {
                                if ( strcmp( $xvalue, $yvalue ) == 0 ) {
@@ -76,7 +76,7 @@ class LanguageTyv extends Language {
                                        continue;
                                }
                        }
-                       if ( $wordLastVowel !== NULL ) {
+                       if ( $wordLastVowel !== null ) {
                                break;
                        } else {
                                continue;
index 4ad272b..aabe390 100644 (file)
@@ -92,6 +92,10 @@ class LanguageUk extends Language {
         * @return string
         */
        function convertPlural( $count, $forms ) {
+               $forms = $this->handleExplicitPluralForms( $count, $forms );
+               if ( is_string( $forms ) ) {
+                       return $forms;
+               }
                if ( !count( $forms ) ) {
                        return '';
                }
index c087891..395febc 100644 (file)
@@ -13,6 +13,8 @@
  * @author Ezagren
  * @author Fadli Idris
  * @author Meno25
+ * @author Rachmat.Wahidi
+ * @author Sayed Muddasir
  * @author Si Gam Acèh
  */
 
@@ -22,15 +24,15 @@ $namespaceNames = array(
        NS_MEDIA            => 'Alat',
        NS_SPECIAL          => 'Kusuih',
        NS_TALK             => 'Marit',
-       NS_USER             => 'Ureuëng_Nguy',
-       NS_USER_TALK        => 'Marit_Ureuëng_Nguy',
+       NS_USER             => 'Ureuëng_Ngui',
+       NS_USER_TALK        => 'Marit_Ureuëng_Ngui',
        NS_PROJECT_TALK     => 'Marit_$1',
        NS_FILE             => 'Beureukaih',
        NS_FILE_TALK        => 'Marit_Beureukaih',
        NS_MEDIAWIKI        => 'MediaWiki',
        NS_MEDIAWIKI_TALK   => 'Marit_MediaWiki',
-       NS_TEMPLATE         => 'Pola',
-       NS_TEMPLATE_TALK    => 'Marit_Pola',
+       NS_TEMPLATE         => 'Seunaleuëk',
+       NS_TEMPLATE_TALK    => 'Marit_Seunaleuëk',
        NS_HELP             => 'Beunantu',
        NS_HELP_TALK        => 'Marit_Beunantu',
        NS_CATEGORY         => 'Kawan',
@@ -43,6 +45,8 @@ $namespaceAliases = array(
        'Pembicaraan'           => NS_TALK,
        'Pengguna'              => NS_USER,
        'Bicara_Pengguna'       => NS_USER_TALK,
+       'Ureuëng_Nguy'          => NS_USER,
+       'Marit_Ureuëng_Nguy'    => NS_USER_TALK,
        'Pembicaraan_Pengguna'  => NS_USER_TALK,
        'Pembicaraan_$1'        => NS_PROJECT_TALK,
        'Berkas'                => NS_FILE,
@@ -56,6 +60,8 @@ $namespaceAliases = array(
        'Templat'               => NS_TEMPLATE,
        'Pembicaraan_Templat'   => NS_TEMPLATE_TALK,
        'Templat_Pembicaraan'   => NS_TEMPLATE_TALK,
+       'Pola'                  => NS_TEMPLATE,
+       'Marit_Pola'            => NS_TEMPLATE_TALK,
        'Bantuan'               => NS_HELP,
        'Bantuan_Pembicaraan'   => NS_HELP_TALK,
        'Pembicaraan_Bantuan'   => NS_HELP_TALK,
@@ -66,13 +72,14 @@ $namespaceAliases = array(
 );
 
 $specialPageAliases = array(
-       'Activeusers'               => array( 'Ureueng_nguy_udep' ),
-       'Allmessages'               => array( 'MandumPeusan' ),
-       'Allpages'                  => array( 'Dapeuta_on' ),
-       'Ancientpages'              => array( 'Teunuleh_trep' ),
-       'Blankpage'                 => array( 'On_soh' ),
-       'Block'                     => array( 'Theun_ureueng_nguy' ),
-       'Blockme'                   => array( 'Theun_lon' ),
+       'Activeusers'               => array( 'UreuëngNguiUdép' ),
+       'Allmessages'               => array( 'BanDumPeusan' ),
+       'AllMyUploads'              => array( 'BanDumPeunasoëLôn', 'BanDumBeureukaihLôn' ),
+       'Allpages'                  => array( 'DapeutaLaman' ),
+       'Ancientpages'              => array( 'TeunuléhAwai' ),
+       'Badtitle'                  => array( 'NanBrôk' ),
+       'Blankpage'                 => array( 'LamaSoh' ),
+       'Block'                     => array( 'TheunUreuëngNgui' ),
        'Booksources'               => array( 'Ne_kitab' ),
        'BrokenRedirects'           => array( 'Peuninah_reuloh' ),
        'Categories'                => array( 'Dapeuta_kawan' ),
@@ -82,7 +89,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Peugot_nan' ),
        'Deadendpages'              => array( 'On_mate' ),
        'DeletedContributions'      => array( 'Peuneugot_nyang_geusampoh' ),
-       'Disambiguations'           => array( 'Hana_jeulaih' ),
        'DoubleRedirects'           => array( 'Peuninah_ganda' ),
        'Emailuser'                 => array( 'Surat-e_ureueng_nguy' ),
        'Export'                    => array( 'Peuteubiet' ),
@@ -158,67 +164,67 @@ $specialPageAliases = array(
 
 $messages = array(
 # User preference toggles
-'tog-underline' => 'Bôh garéh yup bak hubông:',
+'tog-underline' => 'Bôh garéh yup peunawôt:',
 'tog-justify' => 'Peurata paragraf',
-'tog-hideminor' => 'Peusom neuandam bacut bak neuubah paléng barô',
-'tog-hidepatrolled' => 'Peusom neuandam teupatroli bak neuubah paléng barô',
-'tog-newpageshidepatrolled' => 'Peusom ôn teupatroli nibak dapeuta ôn barô',
-'tog-extendwatchlist' => 'Peuhah dapeuta keunalön keu peuleumah ban dum neuubah, kon nyang paléng barô mantöng',
-'tog-usenewrc' => 'Peusaho neuandam bak neuleumah neuubah barô ngon dapeuta keunalon meunurot ôn',
-'tog-numberheadings' => 'Bôh numbô nan keudroë',
+'tog-hideminor' => 'Peusom neuandam bacut bak neuubah barô',
+'tog-hidepatrolled' => 'Peusom neuandam teurunda bak neuubah barô',
+'tog-newpageshidepatrolled' => 'Peusom laman teurunda nibak dapeuta ôn barô',
+'tog-extendwatchlist' => 'Peuhah dapeuta keunalön keu peuleumah ban dum neuubah, kön nyang barô mantöng',
+'tog-usenewrc' => 'Peusaho neuandam bak neuleumah neuubah barô ngön dapeuta keunalön meunurôt ôn',
+'tog-numberheadings' => 'Bôh numbôi nan keudroë',
 'tog-showtoolbar' => 'Peuleumah bateuëng alat andam',
-'tog-editondblclick' => 'Andam ôn ngon duwa go teugon',
-'tog-editsection' => 'Peujeuet andam bideueng rot hubong [andam]',
-'tog-editsectiononrightclick' => 'Peujeuet andam bideueng ngon teugon blah uneun bak nan bideueng',
-'tog-showtoc' => 'Peuleumah dapeuta asoe (keu on-on nyang na leubeh nibak 3 boh aneuk ulee)',
-'tog-rememberpassword' => 'Ingat lôn tamong bak peuramban nyoë (keu paleng trep $1 {{PLURAL:$1|uroë|uroë}})',
-'tog-watchcreations' => 'Tamah halaman nyang lonpeugot u dapeuta keunalon',
-'tog-watchdefault' => 'Tamah halaman nyang lon-andam u dapeuta keunalon',
-'tog-watchmoves' => 'Tamah halaman nyang lonpupinah u dapeuta keunalon',
-'tog-watchdeletion' => 'Tamah halaman nyang lonsampoh u dapeuta keunalon',
-'tog-minordefault' => 'Boh tanda mandum neuandam sibagoe neuandam bacut ngon baku',
-'tog-previewontop' => 'Peuleumah hase yoh goh kutak andam',
-'tog-previewonfirst' => 'Peuleumah hase bak neuandam phon',
-'tog-nocache' => 'Pumate pumeugot beun on peuramban nyoe',
-'tog-enotifwatchlistpages' => "Peu'ek surat-e keu lon meunyo saboh halaman nyang lonkalon meuubah",
-'tog-enotifusertalkpages' => "Peu'ek keu lon surat-e meunyo on marit lon meuubah",
-'tog-enotifminoredits' => "Peu'ek cit surat-e keu lon bak neuubah ubit",
-'tog-enotifrevealaddr' => 'Peuleumah alamat surat-e lon bak neubrithee surat-e',
+'tog-editondblclick' => 'Andam laman ngön duwa gö teugön',
+'tog-editsection' => 'Peujeuet andam bideuëng röt hubông [andam]',
+'tog-editsectiononrightclick' => 'Peujeuët andam bideueng ngön teugön blah uneun bak nan bideueng',
+'tog-showtoc' => 'Peuleumah dapeuta asoe (keu laman-laman nyang na leubèh nibak 3 boh aneuk ulèë)',
+'tog-rememberpassword' => 'Ingat lôn tamöng bak peuramban nyoë (keu paléng trép $1 {{PLURAL:$1|uroë}})',
+'tog-watchcreations' => 'Tamah laman nyang lôn peugöt u dapeuta keunalön',
+'tog-watchdefault' => 'Tamah laman nyang lôn-andam u dapeuta keunalon',
+'tog-watchmoves' => 'Tamah laman nyang lôn peupinah u dapeuta keunalon',
+'tog-watchdeletion' => 'Tamah laman nyang lôn sampôh u dapeuta keunalon',
+'tog-minordefault' => 'Bôh tanda mandum neuandam sibagoe neuandam bacut ngön baku',
+'tog-previewontop' => 'Peuleumah hasé yôh goh plôk andam',
+'tog-previewonfirst' => 'Peuleumah hasé bak neuandam phôn',
+'tog-nocache' => 'Pumaté pumeugöt beun laman peuramban nyoe',
+'tog-enotifwatchlistpages' => "Peu'ék surat-e keu lôn meunyo saboh halaman nyang lôn kalon meuubah",
+'tog-enotifusertalkpages' => "Peu'ek keu lôn surat-e meunyo ôn marit lôn meuubah",
+'tog-enotifminoredits' => "Peu'ék cit surat-e keu lôn bak neuubah ubit",
+'tog-enotifrevealaddr' => 'Peuleumah alamat surat-e lôn bak neubrithèë surat-e',
 'tog-shownumberswatching' => 'Peuleumah jumeulah ureueng kalon',
 'tog-oldsig' => 'Tanda jaroe jinoe:',
-'tog-fancysig' => 'Peujeuet tanda jaroe sibagoe naseukah wiki (hana hubong keudroe)',
-'tog-uselivepreview' => 'Nguy peuleumah hase langsong (baci)',
-'tog-forceeditsummary' => 'Peuingat lon meunyo plok neuringkaih neuandam mantong soh',
+'tog-fancysig' => 'Peujeuet tanda jaroe sibagoe naseukah wiki (hana hubông keudroe)',
+'tog-uselivepreview' => 'Ngui peuleumah hasé langsông (baci)',
+'tog-forceeditsummary' => 'Peuingat lôn meunyo plôk neuringkaih neuandam mantöng soh',
 'tog-watchlisthideown' => 'Peusöm nyang lôn andam nibak dapeuta keunalön',
-'tog-watchlisthidebots' => 'Peusöm nyang teu andam nibak sagoö nyang bak dapeuta keunalön',
-'tog-watchlisthideminor' => 'Peusöm Andam Bacut bak dapeuta keunalön',
-'tog-watchlisthideliu' => 'Peusöm andam ureuëng nguy nyang tamöng nibak dapeuta keunalön',
-'tog-watchlisthideanons' => 'Peusöm andam ureuëng nguy hana taturi nibak dapeuta keunalön',
-'tog-watchlisthidepatrolled' => 'Peusom neuandam teukaway bak dapeuta keunalon',
-'tog-ccmeonemails' => "Peu'ek keu lon seunalen surat-e nyang lonpeu'ek keu ureueng la'en",
-'tog-diffonly' => 'Bek peuleumah asoe halaman di yup beunida neuandam',
+'tog-watchlisthidebots' => 'Peusöm nyang teuandam nibak dapeuta keunalön',
+'tog-watchlisthideminor' => 'Peusom Andam Bacut bak dapeuta keunalön',
+'tog-watchlisthideliu' => 'Peusom andam ureuëng ngui nyang tamöng nibak dapeuta keunalön',
+'tog-watchlisthideanons' => 'Peusöm andam ureuëng ngui hana taturi nibak dapeuta keunalön',
+'tog-watchlisthidepatrolled' => 'Peusom neuandam teukawai bak dapeuta keunalön',
+'tog-ccmeonemails' => "Peu'ék keu lôn seunalén surat-e nyang lôn peu'ék keu ureueng la'én",
+'tog-diffonly' => 'Bek peuleumah asoë laman di yup beunida neuandam',
 'tog-showhiddencats' => 'Peuleumah kawan teusom',
 'tog-norollbackdiff' => "Bek peudeuh beunida 'oh lheueh geupeuriwang",
-'tog-useeditwarning' => 'Neupeuingat lôn meunyoë meukubah ôn andam ngon hana teukeubah',
-'tog-prefershttps' => 'Sabè neunguy seunambông teulindông meunyoë neutamöng log',
+'tog-useeditwarning' => 'Neupeuingat lôn meunyö meukubah ôn andam ngön hana teukeubah',
+'tog-prefershttps' => 'Sabé neungui seunambông teulindông meunyö neutamöng log',
 
-'underline-always' => 'Sabe',
+'underline-always' => 'Sabé',
 'underline-never' => "H'an tom",
-'underline-default' => 'Kulet atawa ngon peuhah web teupasang',
+'underline-default' => 'Kulét atawa ngön peuhah wèb teupasang',
 
 # Font style option in Special:Preferences
-'editfont-style' => 'Gaya seunurat komputer bak plok andam',
+'editfont-style' => 'Gaya seunurat komputer bak plôk andam',
 'editfont-default' => 'Bawaan penjelajah web',
 'editfont-monospace' => 'Seunurat Monospace',
 'editfont-sansserif' => 'Seunurat Sans-serif',
 'editfont-serif' => 'Seunurat Serif',
 
 # Dates
-'sunday' => 'Aleuhat',
+'sunday' => 'Aleuhad',
 'monday' => 'Seulanyan',
 'tuesday' => 'Seulasa',
 'wednesday' => 'Rabu',
-'thursday' => 'Hameh',
+'thursday' => 'Hamèh',
 'friday' => "Jeumeu'at",
 'saturday' => 'Sabtu',
 'sun' => 'Aleu',
@@ -232,7 +238,7 @@ $messages = array(
 'february' => 'Buleuën Duwa',
 'march' => 'Buleuën Lhèë',
 'april' => 'Buleuën Peuët',
-'may_long' => 'Buleuën Limong',
+'may_long' => 'Buleuën Limöng',
 'june' => 'Buleuën Nam',
 'july' => 'Buleuën Tujôh',
 'august' => 'Buleuën Lapan',
@@ -244,7 +250,7 @@ $messages = array(
 'february-gen' => 'Buleuën Duwa',
 'march-gen' => 'Buleuën Lhèë',
 'april-gen' => 'Buleuën Peuët',
-'may-gen' => 'Buleuën Limong',
+'may-gen' => 'Buleuën Limöng',
 'june-gen' => 'Buleuën Nam',
 'july-gen' => 'Buleuën Tujôh',
 'august-gen' => 'Buleuën Lapan',
@@ -256,7 +262,7 @@ $messages = array(
 'feb' => 'Duwa',
 'mar' => 'Lhèë',
 'apr' => 'Peuët',
-'may' => 'Limong',
+'may' => 'Limöng',
 'jun' => 'Nam',
 'jul' => 'Tujôh',
 'aug' => 'Lapan',
@@ -278,23 +284,23 @@ $messages = array(
 'december-date' => '$1 Buleuën Duwa Blaih',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|Kawan|Kawan}}',
+'pagecategories' => '{{PLURAL:$1|Kawan}}',
 'category_header' => 'Teunuléh lam kawan "$1"',
 'subcategories' => 'Aneuk kawan',
 'category-media-header' => 'Peukakaih lam kawan "$1"',
-'category-empty' => "''Kawan nyoë jinoë hat hana teunuléh atawa media.''",
+'category-empty' => "''Kawan nyoë jinoë hat hana halaman atawa media.''",
 'hidden-categories' => '{{PLURAL:$1|Kawan teusom|Kawan teusom}}',
 'hidden-category-category' => 'Kawan teusom',
 'category-subcat-count' => '{{PLURAL:$2|Kawan nyoë  cit na saboh yupkawan nyoë.|Kawan nyoë na {{PLURAL:$1|yupkawan|$1 yupkawan}} nyoë, dari ban dum $2.}}',
-'category-subcat-count-limited' => 'Kawan nyoe na {{PLURAL:$1|aneuk kawan|$1 aneuk kawan}} lagee di yup.',
+'category-subcat-count-limited' => 'Kawan nyoë na {{PLURAL:$1|aneuk kawan|$1 aneuk kawan}} lagèë di yup.',
 'category-article-count' => '{{PLURAL:$2|Kawan nyoë cit na saboh ôn nyoë.|Kawan nyoë na  {{PLURAL:$1|ôn|$1 ôn }}, dari ban dum $2.}}',
-'category-article-count-limited' => 'Kawan nyoe na {{PLURAL:$1|saboh halaman|$1 halaman}} lagee di yup.',
-'category-file-count' => '{{PLURAL:$2|Kawan nyoe cit na beureukaih nyoe sagay.|{{PLURAL:$1|beureukaih|$1 beureukaih}} nyoe na lam kawan nyoe, nibak ban dum $2.}}',
-'category-file-count-limited' => 'Kawan nyoe na {{PLURAL:$1|beureukaih|$1 beureukaih}} lagee di yup.',
+'category-article-count-limited' => 'Kawan nyoë na {{PLURAL:$1|saboh halaman|$1 halaman}} lagèë di yup.',
+'category-file-count' => '{{PLURAL:$2|Kawan nyoë cit na beureukaih nyoë sagay.|{{PLURAL:$1|beureukaih|$1 beureukaih}} nyoë na lam kawan nyoë, nibak ban dum $2.}}',
+'category-file-count-limited' => 'Kawan nyoe na {{PLURAL:$1|beureukaih|$1 beureukaih}} lagèë di yup.',
 'listingcontinuesabbrev' => 'samb.',
-'index-category' => 'On nyang geuindex',
-'noindex-category' => 'On nyang hana geuindex',
-'broken-file-category' => 'On ngon gamba reuloh',
+'index-category' => 'Laman nyang geuindex',
+'noindex-category' => 'Laman nyang hana geuindex',
+'broken-file-category' => 'Laman ngön gamba reulöh',
 
 'about' => 'Bhaih',
 'article' => 'Teunuléh',
@@ -302,30 +308,30 @@ $messages = array(
 'cancel' => 'Peubateuë',
 'moredotdotdot' => 'Lom...',
 'morenotlisted' => 'Dapeuta nyoe hana leungkap',
-'mypage' => 'Ôn',
+'mypage' => 'Laman',
 'mytalk' => 'Marit',
 'anontalk' => 'Peugah haba IP nyoë.',
-'navigation' => 'Navigasi',
-'and' => '&#32;ngon',
+'navigation' => 'Keumudoë',
+'and' => '&#32;ngön',
 
 # Cologne Blue skin
 'qbfind' => 'Mita',
 'qbbrowse' => 'Lop',
 'qbedit' => 'Andam',
-'qbpageoptions' => 'Ôn nyoe',
-'qbmyoptions' => 'Ôn lôn',
-'qbspecialpages' => 'Ôn kusuih',
-'faq' => 'FAQ',
+'qbpageoptions' => 'Laman nyoe',
+'qbmyoptions' => 'Laman lôn',
+'qbspecialpages' => 'Laman kusuih',
+'faq' => 'Teunanyöng Umom',
 'faqpage' => 'Project:FAQ',
 
 # Vector skin
 'vector-action-addsection' => 'Tamah bhaih',
 'vector-action-delete' => 'Sampôh',
-'vector-action-move' => 'Peupinah',
+'vector-action-move' => 'Pupinah',
 'vector-action-protect' => 'Peulindông',
 'vector-action-undelete' => 'Bateuë sampôh',
 'vector-action-unprotect' => 'Gantoe neulindông',
-'vector-simplesearch-preference' => 'Peuudep beunteueng mita biasa (kulet Vector khong)',
+'vector-simplesearch-preference' => 'Peuudép beunteueng mita biasa (kulét Vèctor khöng)',
 'vector-view-create' => 'Peugöt',
 'vector-view-edit' => 'Andam',
 'vector-view-history' => 'Eu riwayat',
@@ -344,67 +350,67 @@ $messages = array(
 'searchbutton' => 'Mita',
 'go' => 'Jak u',
 'searcharticle' => 'Jak u',
-'history' => 'Riwayat ôn',
+'history' => 'Riwayat laman',
 'history_short' => 'Riwayat',
-'updatedmarker' => 'geuubah yoh seunaweue keuneulheueh lon phon kon',
+'updatedmarker' => 'geuubah yôh seunaweue keuneulheueh lôn phôn kön',
 'printableversion' => 'Seunalén rakam',
-'permalink' => 'Hubông teutap',
+'permalink' => 'Peunawôt teutap',
 'print' => 'Rakam',
-'view' => 'Beuet',
+'view' => 'Beuët',
 'edit' => 'Andam',
 'create' => 'Peugöt',
-'editthispage' => 'Andam ôn nyoë',
-'create-this-page' => 'Peugèt Ã´n nyoe',
+'editthispage' => 'Andam laman nyoë',
+'create-this-page' => 'Peugöt laman nyoë',
 'delete' => 'Sampôh',
-'deletethispage' => 'Sampôh ôn nyoe',
-'undeletethispage' => 'Bèk neusampôh ôn nyoë',
+'deletethispage' => 'Sampôh laman nyoë',
+'undeletethispage' => 'Bèk neusampôh laman nyoë',
 'undelete_short' => 'Bateuë sampôh {{PLURAL:$1|one edit|$1 edits}}',
-'viewdeleted_short' => 'Eu {{PLURAL:$1|saboh neuandam|$1 neuandam}} nyang geusampoh',
+'viewdeleted_short' => 'Eu {{PLURAL:$1|saboh neuandam|$1 neuandam}} nyang geusampôh',
 'protect' => 'Peulindông',
 'protect_change' => 'ubah',
-'protectthispage' => 'Peulindong on nyoe',
-'unprotect' => 'Gantoe neulindong',
-'unprotectthispage' => 'Gantoe neulindông ôn nyoë',
-'newpage' => 'Ôn barô',
-'talkpage' => 'Peugah haba bhah ôn nyoë',
+'protectthispage' => 'Peulindông laman nyoë',
+'unprotect' => 'Gantoë neulindông',
+'unprotectthispage' => 'Gantoë neulindông laman nyoë',
+'newpage' => 'Laman barô',
+'talkpage' => 'Peugah haba bhah laman nyoë',
 'talkpagelinktext' => 'Marit',
-'specialpage' => 'Ôn kusuih',
+'specialpage' => 'Laman kusuih',
 'personaltools' => 'Peukakaih droë',
-'postcomment' => 'Beunagi baro',
-'articlepage' => 'Eu ôn asoë',
+'postcomment' => 'Beunagi barô',
+'articlepage' => 'Eu asoë laman',
 'talk' => 'Marit',
-'views' => 'Ôn',
-'toolbox' => 'Plôk alat',
-'userpage' => 'Eu on ureueng nguy',
-'projectpage' => 'Eu ôn buët',
-'imagepage' => 'Eu on beureukaih',
-'mediawikipage' => 'Eu on peusan sistem',
-'templatepage' => 'Eu on seunaleuek',
-'viewhelppage' => 'Eu on beunantu',
-'categorypage' => 'Eu ôn kawan',
-'viewtalkpage' => 'Eu on marit',
+'views' => 'Seuneudeuih',
+'toolbox' => 'Alat',
+'userpage' => 'Eu laman ureuëng ngui',
+'projectpage' => 'Eu laman buët',
+'imagepage' => 'Eu laman beureukaih',
+'mediawikipage' => 'Eu laman peusan sistem',
+'templatepage' => 'Eu laman seunaleuëk',
+'viewhelppage' => 'Eu laman beunantu',
+'categorypage' => 'Eu laman kawan',
+'viewtalkpage' => 'Eu laman marit',
 'otherlanguages' => 'Bahsa la’én',
 'redirectedfrom' => '(Geupeupinah nibak $1)',
-'redirectpagesub' => 'Ôn peuninah',
-'lastmodifiedat' => 'Ôn nyoë seuneulheuëh geuubah bak $2, $1.',
-'viewcount' => 'On nyoe ka geusaweue {{PLURAL:$1|sigo|$sigo}}.<br />',
-'protectedpage' => 'Ôn teupeulindông',
-'jumpto' => 'Lansông u:',
-'jumptonavigation' => 'navigasi',
+'redirectpagesub' => 'Laman peuninah',
+'lastmodifiedat' => 'Laman nyoë seuneulheuëh geuubah bak $1 poh $2.',
+'viewcount' => 'Laman nyoë ka geusaweuë {{PLURAL:$1|sigo|$sigo}}.<br />',
+'protectedpage' => 'Laman teupeulindông',
+'jumpto' => 'Grôp u:',
+'jumptonavigation' => 'keumudoë',
 'jumptosearch' => 'mita',
-'view-pool-error' => "Meu'ah, server teungoh sibuk jinoe
-Le that ureueng nyang meuh'eut jak eu on nyoe
-Neupreh si'at yoh goh neubaci lom
+'view-pool-error' => "Meu'ah, server teungöh sibôk jinoe
+Le that ureueng nyang meuh'eut jak eu laman nyoe
+Neuprèh si'at yôh goh neubaci lom
 
 $1",
-'pool-timeout' => 'Liwat watee preh gunci',
-'pool-queuefull' => 'Seunapat neupreh peunoh',
-'pool-errorunknown' => 'Salah hana meukon',
+'pool-timeout' => 'Liwat watèë prèh gunci',
+'pool-queuefull' => 'Seunapat neuprèh peunoh',
+'pool-errorunknown' => 'Salah hana meukön',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Bhaih {{SITENAME}}',
 'aboutpage' => 'Project:Bhaih',
-'copyright' => "Asoë na meunurot $1 keucuali meunyo na hay la'en nyang geupeugah",
+'copyright' => "Asoë na meunurôt $1 keucuali meunyö na hay la'én nyang geupeugah",
 'copyrightpage' => '{{ns:project}}:Hak karang',
 'currentevents' => 'Haba barô',
 'currentevents-url' => 'Project:Haba barô',
@@ -421,21 +427,19 @@ $1",
 'privacypage' => 'Project:Jaga rahsia',
 
 'badaccess' => 'Salah khut/hak tamöng',
-'badaccess-group0' => 'Droeneuh hana geupeuidin keu neupeulaku buet nyang neulakee',
-'badaccess-groups' => 'Buet nyang neulakee geupeubatah keu ureueng nguy lam {{PLURAL:$2|kawan|salah saboh nibak kawan}}: $1.',
+'badaccess-group0' => 'Droeneuh hana geupeuidin keu neupeulaku buët nyang neulakèë',
+'badaccess-groups' => 'Buët nyang neulakèë geupeubatah keu ureuëng ngui lam {{PLURAL:$2|kawan|salah saboh nibak kawan}}: $1.',
 
-'versionrequired' => 'Peureulee MediaWiki versi $1',
-'versionrequiredtext' => "MediaWiki versi $1 geupeureulee keu neunguy on nyoe. Neu'eu [[Special:Version|on versi]]",
+'versionrequired' => 'Peureulèë MediaWiki vèrsi $1',
+'versionrequiredtext' => "MediaWiki versi $1 geupeureulèë keu neungui laman nyoë. Neu'eu [[Special:Version|on versi]]",
 
 'ok' => 'Ka göt',
 'retrievedfrom' => 'Geurumpok nibak "$1"',
 'youhavenewmessages' => 'Droëneuh na $1 ($2).',
-'newmessageslink' => 'peusan barô',
-'newmessagesdifflink' => 'neuubah seuneulheuëh',
 'youhavenewmessagesfromusers' => "Droeneuh na $1 nibak {{PLURAL:$3|ureueng nguy la'en|$3 ureueng nguy}} ($2).",
 'youhavenewmessagesmanyusers' => "Droeneuh na $1 nibak ureueng nguy la'en ($2)",
 'newmessageslinkplural' => '{{PLURAL:$1|saboh peusan baro|peusan baro}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|neuubah}} keuneulheueh',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|neuubah}} keuneulheuëh',
 'youhavenewmessagesmulti' => 'Droëneuh na padum boh peusan barô bak $1',
 'editsection' => 'andam',
 'editold' => 'andam',
@@ -451,23 +455,23 @@ $1",
 'thisisdeleted' => 'Eu atawa peuriwang $1?',
 'viewdeleted' => 'Eu $1?',
 'restorelink' => '$1 {{PLURAL:$1|neuandam|neuandam}} nyang ka geusampoh',
-'feedlinks' => 'Umpeuen:',
-'feed-invalid' => 'Jeuneh neulakee umpeuen hana paih',
-'feed-unavailable' => 'Umpeuen sindikasi hana',
+'feedlinks' => 'Umpeuën:',
+'feed-invalid' => 'Jeunèh neulakèë umpeuën hana paih',
+'feed-unavailable' => 'Umpeuën sindikasi hana',
 'site-rss-feed' => 'Umpeuën RSS $1',
 'site-atom-feed' => 'Umpeuën Atôm $1',
 'page-rss-feed' => 'Umpeuën RSS "$1"',
 'page-atom-feed' => 'Umpeuën Atom "$1"',
-'red-link-title' => '$1 (ôn goh na)',
-'sort-descending' => 'Peuurot tren',
-'sort-ascending' => 'Peuurot ek',
+'red-link-title' => '$1 (laman hana)',
+'sort-descending' => 'Peuurôt tren',
+'sort-ascending' => 'Peuurôt ék',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Ôn',
-'nstab-user' => 'Ureuëng nguy',
-'nstab-media' => 'Ôn media',
-'nstab-special' => 'Kusuih',
-'nstab-project' => 'Buët ôn',
+'nstab-main' => 'Laman',
+'nstab-user' => 'Ureuëng ngui',
+'nstab-media' => 'Laman media',
+'nstab-special' => 'Laman kusuih',
+'nstab-project' => 'Laman buët',
 'nstab-image' => 'Beureukaih',
 'nstab-mediawiki' => 'Peusan',
 'nstab-template' => 'Seunaleuëk',
@@ -475,58 +479,59 @@ $1",
 'nstab-category' => 'Kawan',
 
 # Main script and global functions
-'nosuchaction' => 'Hana buet nyan',
-'nosuchactiontext' => 'Buet nyang geulakee le URL nyan hana sah. Droeneuh kadang salah neukeutik URL, atawa neuseutot saboh neuhubong nyang hana beutoy. Hay nyoe kadang jeuet keu lageuem saboh bug bak alat leumiek nyang geunguy le {{SITENAME}}.',
-'nosuchspecialpage' => 'Hana on kusuih lagee nyan',
-'nospecialpagetext' => "<strong>Droeneuh ka neulakee on kusuih nyang hana sah.</strong>
-Dapeuta on kusuih nyang sah jeuet neu'eu bak [[Special:SpecialPages|{{int:specialpages}}]].",
+'nosuchaction' => 'Hana buët nyan',
+'nosuchactiontext' => 'Buët nyang geulakèë lé URL nyan hana sah. Droeneuh kadang salah neukeutik URL, atawa neuseutöt saboh neuhubông nyang hana beutôi. Hai nyoë kadang jeuët keu lageuëm saboh bug bak alat leumiëk nyang geungui lé {{SITENAME}}.',
+'nosuchspecialpage' => 'Hana laman kusuih lagèë nyan',
+'nospecialpagetext' => "<strong>Droeneuh ka neulakèë laman kusuih nyang hana sah.</strong>
+Dapeuta laman kusuih nyang sah jeuet neu'eu bak [[Special:SpecialPages|{{int:specialpages}}]].",
 
 # General errors
 'error' => 'Seunalah',
 'databaseerror' => 'Kesalahan basis data',
 'databaseerror-text' => 'Saboh salah bak nè data ka teujadi. Nyoë meuhat na nyang han paih bak peukakaih droëneuh',
-'databaseerror-textcl' => 'Teunanyong basis data teungoh kacho',
-'databaseerror-query' => 'Teunanyong: $1',
+'databaseerror-textcl' => 'Teunanyöng basis data teungöh kacho',
+'databaseerror-query' => 'Teunanyöng: $1',
 'databaseerror-function' => 'Guna: $1',
 'databaseerror-error' => 'Salah: $1',
-'laggedslavemode' => 'Peuneugah: On nyoe kadang hana neuubah baro',
-'readonly' => 'Basis data geurok',
-'enterlockreason' => 'Pasoe daleh neurok ngon pajan jeuet geupeuhah',
-'readonlytext' => "Basis data hat nyoe geurok keu teunamong baro ngon geunantoe la'en, kadang keu peulara basis data rutin, lheueh nyan baro lagee biasa teuma.
+'laggedslavemode' => 'Peuneugah: Laman nyoë kadang hana neuubah barô',
+'readonly' => 'Basis data geurôk',
+'enterlockreason' => 'Pasoë dalèh neurôk ngön pajan jeuët geupeuhah',
+'readonlytext' => "Basis data hat nyoë geurôk keu teunamöng barô ngön geunantoë la'én, kadang keu peulara basis data rutin, lheuëh nyan barô lagèë biasa teuma.
 
-Ureueng uroh nyang rok nyoe geupeutaba jeuneulaih nyoe: $1",
-'missing-article' => 'Basis data h’an jeuët jiteumèë naseukah nibak ôn nyang sipatôtjih na, nakeuh "$1" $2.
+Ureueng urôh nyang rôk nyoe geupeutaba jeuneulaih nyoe: $1",
+'missing-article' => 'Basis data hana jiteumèë naseukah nibak laman nyang sipatôtjih na, nyakni "$1" $2.
 
-Nyoë biasajih sabab hubông useuëng u geunantoë away nyang ka teusampôh.
+Hai nyoë kayém jipeusabab lé peunawôt useuëng u laman nyang ka geusampôh.
 
-Meunyo kön nyoë sababjih, Droëneuh kadang ka neuteumèë saboh bug lam software. Neutulông peugah bhah nyoë bak salah sidroë [[Special:ListUsers/sysop|Nyang urôh]], ngön neupeugah alamat URL nyang neusaweuë.',
+Meunyö kön nyoë sababjih, droëneuh kadang ka neuteumeung saboh \'\'bug\'\' lam peukakaih leumiëk.
+Neutulông bri thèë hai nyoë keu salah sidroë [[Special:ListUsers/sysop|ureuëng urôih]], ngön neupeugah alamat URL-jih.',
 'missingarticle-rev' => '(revisi#: $1)',
 'missingarticle-diff' => '(Bida: $1, $2)',
-'readonly_lag' => 'Basis data ka geurok otomatis silawet basis data sekunder teungoh geupeusinkron ngon basis data utama',
+'readonly_lag' => 'Basis data ka geurôk otomatis silawét basis data sekunder teungöh geupeusinkron ngön basis data utama',
 'internalerror' => 'Salah bak dalam',
 'internalerror_info' => 'Salah bak dalam: $1',
-'fileappenderrorread' => 'H\'an jitem beuet "$1" \'oh geutamah',
-'fileappenderror' => 'H\'an jeuet jipasoe "$1" u "$2"',
-'filecopyerror' => 'H\'an jeuet salen beureukaih "$1" u "$2".',
-'filerenameerror' => 'H\'an jeuet boh nan beureukaih "$1" u "$2".',
-'filedeleteerror' => 'H\'an jeuet sampoh beureukaih "$1".',
-'directorycreateerror' => 'H\'an jeuet peugot direktori "$1".',
-'filenotfound' => 'Beureukaih "$1" hana meurumpok.',
-'fileexistserror' => 'H\'an jeuet geusalen u beureukaih "$1": Beureukaih ka na.',
+'fileappenderrorread' => 'H\'an jitém beuet "$1" \'oh geutamah',
+'fileappenderror' => 'H\'an jeuet jipasoë "$1" u "$2"',
+'filecopyerror' => 'H\'an jeuet salén beureukaih "$1" u "$2".',
+'filerenameerror' => 'H\'an jeuët bôh nan beureukaih "$1" u "$2".',
+'filedeleteerror' => 'H\'an jeuët sampôh beureukaih "$1".',
+'directorycreateerror' => 'H\'an jeuet peugöt direktori "$1".',
+'filenotfound' => 'Beureukaih "$1" hana meurumpök.',
+'fileexistserror' => 'H\'an jeuet geusalén u beureukaih "$1": Beureukaih ka na.',
 'unexpected' => 'Yum hana geuharap: "$1"="$2".',
-'formerror' => "Reuloh: H'an jeuet peu'et formulir.",
-'badarticleerror' => "Buet nyoe h'an jeuet geupeulaku bak on nyoe.",
-'cannotdelete' => 'On atawa beureukaih "$1" h\'an jeuet geusampoh.
-Kadang ka na soe sampoh.',
-'cannotdelete-title' => 'H\'an jeuet sampoh on "$1"',
-'delete-hook-aborted' => "Seunampoh geupeubateue le kaw'et parser.
+'formerror' => "Reulöh: H'an jeuet peu'ék formulir.",
+'badarticleerror' => "Buet nyoe h'an jeuët geupeulaku bak laman nyoe.",
+'cannotdelete' => 'Laman atawa beureukaih "$1" h\'an jeuët geusampôh.
+Kadang ka na soe sampôh.',
+'cannotdelete-title' => 'H\'an jeuet sampôh laman "$1"',
+'delete-hook-aborted' => "Seunampôh geupeubateuë lé kaw'ét parser.
 Hana jeuneulaih.",
-'no-null-revision' => 'H\'an jeuet peugot revisi null baro keu halaman "$1"',
-'badtitle' => 'Nan hana sah',
-'badtitletext' => 'Nan ôn nyang neulakèë hana sah, soh, atawa nan antarabahsa atawa antarawiki nyang salah sambông.',
-'perfcached' => 'Data di yup nyoe geupeusom ngon kadang kon data baro. {{PLURAL:$1|saboh hase|$1 hase}} maksimum na lam beujana.',
-'perfcachedts' => 'Data di yup nyoe geupeusom, ngon geupeubaro seuneulheueh bak $1. {{PLURAL:$4|saboh hase|$4 hase}} paleng le na lam beujana.',
-'querypage-no-updates' => "Beunaro keu on nyoe hat nyoe teungoh h'an jeuet.
+'no-null-revision' => 'H\'an jeuet peugöt revisi null barô keu halaman "$1"',
+'badtitle' => 'Nan hana beutôi',
+'badtitletext' => 'Nan laman nyang neulakèë hana sah, soh, atawa nan antarabahsa atawa antarawiki nyang salah sambông.',
+'perfcached' => 'Data di yup nyoe geupeusom ngön kadang kön data barô. {{PLURAL:$1|saboh hase|$1 hase}} maksimum na lam beujana.',
+'perfcachedts' => 'Data di yup nyoe geupeusom, ngön geupeubarô seuneulheueh bak $1. {{PLURAL:$4|saboh hase|$4 hase}} paléng le na lam beujana.',
+'querypage-no-updates' => "Beunarô keu laman nyoe hat nyoe teungöh h'an jeuët.
 Data sinoe h'an geupasoe ulang.",
 'wrong_wfQuery_params' => 'Parameter salah u wfQuery()<br />
 Meunafaat: $1<br />
@@ -534,22 +539,50 @@ Neulakee: $2',
 'viewsource' => 'Eu nè',
 'viewsource-title' => 'Eu ne keu $1',
 'actionthrottled' => 'Buet geupeubataih',
-'actionthrottledtext' => 'Sibagoe saboh seunipat lawan-spam, droeneuh geupeubataih nibak neupeulaku buet nyoe le that go lam watee paneuk, ngon droeneuh ka leubeh nibak bataih.
-Neuci lom lam padum minet.',
-'protectedpagetext' => 'Laman nyoe ka geupeulindong mangat bek jeuet geuandam',
+'actionthrottledtext' => 'Sibagoe saboh seunipat lawan-spam, droeneuh geupeubataih nibak neupeulaku buet nyoe le that gö lam watèë paneuk, ngön droeneuh ka leubèh nibak bataih.
+Neuci lom lam padum minèt.',
+'protectedpagetext' => 'Laman nyoe ka geupeulindông mangat bèk jeuet geuandam',
 'viewsourcetext' => 'Droëneuh  jeuët neu’eu',
-'viewyourtext' => 'Droëneuh meuidzin kalon ngon neucok nè andam droëneuh u ôn nyoë',
-'protectedinterface' => 'Halaman nyoe na teks muka keu muka keu peukakaih leumiek ngon geupeulindong mangat bek jeuet jipeureuloh.
+'viewyourtext' => 'Droëneuh meuidzin kalön ngön neucok nè andam droëneuh u laman nyoë',
+'protectedinterface' => 'Halaman nyoe na tèks muka keu muka keu peukakaih leumiëk ngön geupeulindông mangat bek jeuet jipeureuloh.
 Keu neuk tamah atawa ubah teujeumah keu ban dum wiki, neungui [//translatewiki.net/ translatewiki.net], proyek lokalisasi MediaWiki.',
-'ns-specialprotected' => 'Ôn khusuih bèk neuandam',
-'exception-nologin' => 'Hana tamong lom',
+'mycustomcssprotected' => 'Droëneuh hana hak neuandam halaman CSS nyoe.',
+'mycustomjsprotected' => 'Droëneuh hana idin neuandam halaman JavaScript nyoe.',
+'mypreferencesprotected' => 'Droeneuh hana izin keu neuandam geunalak droeneuh.',
+'ns-specialprotected' => 'Laman khusuih bèk neuandam',
+'titleprotected' => 'Nan nyoe ka geupeulindông nibak neuandam lé [[User:$1|$1]].
+Dalèhjih nakeuh "\'\'$2\'\'".',
+'invalidtitle-knownnamespace' => 'Nan nyang hana sah ngön ruweueng nan "$2" ngön "$3"',
+'exception-nologin' => 'Hana tamöng lom',
+'exception-nologin-text' => 'halaman atawa buët nyoe beu neutamöng dilèë bak wiki nyoe.',
+
+# Virus scanner
+'virus-unknownscanner' => 'Antivirus hana meuturi:',
 
 # Login and logout pages
-'yourname' => 'Ureuëng nguy:',
-'userlogin-yourname-ph' => 'Peutamöng nan ureuëng nguy droëneuh',
+'logouttext' => "'''Droeneuh ka neutubiet log.'''
+
+Beuneuteupue meunyoe na padum-padum laman nyang deuh lagèe na neutamöng log, sampoe ka lheuh neupeugléh ''cache''.",
+'welcomeuser' => 'Seulamat trôk teuka, $1 !',
+'welcomecreation-msg' => 'Nan droëneuh ka geupeugöt. 
+Bèk tuwo neuatô [[Special:Preferences|geunalak {{SITENAME}}]] droëneuh.',
+'yourname' => 'Ureuëng ngui:',
+'userlogin-yourname' => 'Ureuëng ngui',
+'userlogin-yourname-ph' => 'Peutamöng nan ureuëng ngui droëneuh',
+'createacct-another-username-ph' => 'Pasoë nan ureuëng ngui droëneuh',
 'yourpassword' => 'Lageuëm:',
-'yourpasswordagain' => 'Pasoë lom lageuëm:',
-'remembermypassword' => 'Ingat lôn tamong bak peuramban nyoë (keu paleng trep $1 {{PLURAL:$1|uroë|uroë}})',
+'userlogin-yourpassword' => 'Lageuëm rahsia',
+'userlogin-yourpassword-ph' => 'Pasoë lageuëm rahsia droëneuh',
+'createacct-yourpassword-ph' => 'Pasoë lageuëm rahsia',
+'yourpasswordagain' => 'Pasoë lom lageuëm rahsia:',
+'createacct-yourpasswordagain' => 'Peunyo lageuëm rahsia',
+'createacct-yourpasswordagain-ph' => 'Pasoë lom lageuëm rahsia',
+'remembermypassword' => 'Ingat lôn tamöng bak peuramban nyoë (keu paléng trép $1 {{PLURAL:$1|uroë|days}})',
+'userlogin-remembermypassword' => 'Peubiyeuë lôn tamöng',
+'userlogin-signwithsecure' => 'Ngui server aman',
+'yourdomainname' => 'Domain droeneuh:',
+'password-change-forbidden' => 'Droëneuh h‘an jeuët neuubah lageuëm rahsia bak wiki nyoë.',
+'externaldberror' => 'Na seunalah bak peusahèh basis data luwa atawa droëneuh hana geubri idin keu neupeubarô akun luwa droëneuh',
 'login' => 'Tamöng',
 'nav-login-createaccount' => 'Tamöng / dapeuta',
 'loginprompt' => "Droëneuh suwah/payah neupeu’udép ''cookies'' mangat jeuët neutamong u {{SITENAME}}",
@@ -557,66 +590,149 @@ Keu neuk tamah atawa ubah teujeumah keu ban dum wiki, neungui [//translatewiki.n
 'userloginnocreate' => 'Tamöng',
 'logout' => 'Teubiët',
 'userlogout' => 'Teubiët',
-'notloggedin' => 'Hana tamong lom',
-'nologin' => "Goh na nan ureuëng nguy? '''$1'''.",
+'notloggedin' => 'Hana tamöng lom',
+'userlogin-noaccount' => 'Goh lom neudapeuta?',
+'userlogin-joinproject' => 'Neugabông ngön {{SITENAME}}',
+'nologin' => 'Goh lom neudapeuta? $1.',
 'nologinlink' => 'Peudapeuta nan barô',
 'createaccount' => 'Peudapeuta nan barô',
-'gotaccount' => "Ka lheuëh neudapeuta? '''$1'''.",
-'gotaccountlink' => 'Tamong',
-'userlogin-resetlink' => 'Tuwo ngon rincian tamong Droeneuh?',
-'loginsuccesstitle' => 'Meuhasé tamong',
-'loginsuccess' => "'''Droëneuh  jinoë ka neutamong di {{SITENAME}} sibagoë \"\$1\".'''",
-'nosuchuser' => 'Hana ureuëng nguy ngön nan "$1".
-Nan ureuëng nguy jipeubida harah rayek.
+'gotaccount' => 'Ka lheuëh neudapeuta? $1.',
+'gotaccountlink' => 'Tamöng',
+'userlogin-resetlink' => 'Tuwo rincian tamöng droëneuh?',
+'userlogin-resetpassword-link' => 'Tuwö lageuëm rahsia?',
+'helplogin-url' => 'Help:Tamöng',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Bantu tamöng]]',
+'userlogin-loggedin' => 'Droëneuh ka neutamöng seubagoë $1. Neungui blangko di yup keu neutamöng seubagoë ureuëng ngui la’én',
+'userlogin-createanother' => 'Peudapeuta nan barô',
+'createacct-join' => 'Neupasoë keutrangan bhaih droëneuh di yup nyoë',
+'createacct-another-join' => 'Neupasoë keutrangan nan ureuëng ngui barô di yup nyoë',
+'createacct-emailrequired' => 'Alamat surat-e',
+'createacct-emailoptional' => 'Alamat surat-e (hana wajéb)',
+'createacct-email-ph' => 'Neupasoë alamat surat-e droëneuh',
+'createacct-another-email-ph' => 'Pasoë alamat surat-e',
+'createaccountmail' => 'Neungui lageuëm rahsia beurangkapeuë keu si’at nyoë. Lheuëh nyan neupeu’et u surat-e nyang droëneuh meuh’eut',
+'createacct-realname' => 'Nan aseuli (hana wajéb)',
+'createaccountreason' => 'Choë:',
+'createacct-reason' => 'Choë:',
+'createacct-reason-ph' => 'Pakön droëneuh neupeugöt nan ureuëng ngui la’én',
+'createacct-captcha' => 'Paréksa aman',
+'createacct-imgcaptcha-ph' => "Pasoë seunurat nyang neu'eu di ateuëh",
+'createacct-submit' => 'Peudapeuta nan barô',
+'createacct-another-submit' => 'Peugöt nan ureuëng ngui la’én',
+'createacct-benefit-heading' => '{{SITENAME}} geupeugöt lé ureuëng lagèë droëneuh.',
+'createacct-benefit-body1' => '{{PLURAL:$1|andam}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|$1 halaman}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|ureuëng tuléh}} seuneulheuëh',
+'badretype' => 'Lageuëm rahsia nyang neupasoë salah.',
+'userexists' => "Nan ureuëng ngui nyang neupasoë ka na soë ngui.
+Neupiléh nan nyang la'én.",
+'loginerror' => 'Salah bak tamöng',
+'createacct-error' => 'Peudapeuta nan barô hana meuhasé',
+'createaccounterror' => 'H‘an jeuët peudapeuta nan: $1',
+'nocookiesnew' => "Nan ureueng ngui nyoe ka meupeugöt, tapi goh meutamöng.
+{{SITENAME}} jingui ''cookies'' keu peutamöng ureueng ngui.
+''Cookies'' droeneuh hana meupeuudép.
+Neupeuudép ''cookies'' dilèe, lheuh nyan neutamöng ngön nan ureueng ngui ngön lageuem rahsia droeneuh.",
+'noname' => 'Nan ureuëng ngui nyang Droënueh peutamöng hana sah.',
+'loginsuccesstitle' => 'Meuhasé tamöng',
+'loginsuccess' => "'''Droëneuh  jinoë ka neutamöng di {{SITENAME}} sibagoë \"\$1\".'''",
+'nosuchuser' => 'Hana ureuëng ngui ngön nan "$1".
+Nan ureuëng ngui jipeubida haraih rayek.
 Tulông neuparéksa keulayi neuija Droëneuh, atawa [[Special:UserLogin/signup|neudapeuta barô]].',
-'nosuchusershort' => 'Hana ureuëng nguy ngön nan "$1".
+'nosuchusershort' => 'Hana ureuëng ngui ngön nan "$1".
 Préksa keulayi neu’ija Droëneuh.',
 'nouserspecified' => 'Neupasoë nan Droëneuh.',
+'login-userblocked' => 'Ureuëng ngui nyoë ka teublokir, hana idin/hanjeut tamöng.',
 'wrongpassword' => 'Lageuëm nyang neupasoë salah. Neuci lom.',
 'wrongpasswordempty' => 'Droëneuh hana neupasoë lageuëm. Neuci lom.',
-'passwordtooshort' => "Lageuëm paléng h'an haroh na {{PLURAL:$1|1 karakter|$1 karakter}}.",
-'mailmypassword' => "Peu'ét lageuëm barô",
+'passwordtooshort' => "Lageuëm paléng h'an harôh na {{PLURAL:$1|1 karakter|$1 karakter}}.",
+'password-name-match' => 'Lageuëm Droeuneuh beubida nibak nan Ureuëng ngui.',
+'password-login-forbidden' => 'Ngui nan ureuëng ngui ngön lageuëm nyoë ka jitham.',
+'mailmypassword' => "Peu'ét lageuëm rahsia barô u surat-e",
 'passwordremindertitle' => 'Lageuëm seumeuntara barô keu {{SITENAME}}',
-'passwordremindertext' => 'Salah sidroë (kadang Droëneuh, ngön alamat IP $1) geulakèë lageuëm barô keu {{SITENAME}} ($4). Lageuëm si\'at keu ureuëng nguy "$2" ka geupeuna ngon ka geuato jeuet keu "$3". Meunyo nyoe nakeuh meukeusud droeneuh, droeneuh peureulee neutamong ngon neupileh lageuem baro jinoe. Lageuem siat droeneuh meung abeh lam {{PLURAL:$5|siuroe|$5 uroe}}.
-
-Meunyo ureueng la\'en nyang peugot neulakee nyoe, atawa meunyo droeneuh ka neuingat lageuem droeneuh, ngon droeneuh h\'an ek neugantoe le, droeneuh jeuet hana neupeureumeuen peusan nyoe ngon neulanjut neunguy lageuem awayneuh.',
-'noemail' => 'Hana alamat surat-e nyang teucatat keu ureuëng nguy "$1".',
-'passwordsent' => 'Lageuëm barô ka geupeu\'ét u surat-e nyang geupeudapeuta keu "$1". Neutamong teuma lheuëh neuteurimong surat-e nyan.',
-'eauthentsent' => 'Saboh surat èlèktronik keu peunyoë ka geukirém u alamat surat èlèktronik Droëneuh. Droëneuh beuneuseutöt préntah lam surat nyan keu neupeunyoë meunyo alamat nyan nakeuh beutôy atra Droëneuh. {{SITENAME}} h‘an geupeuudép surat Droëneuh meunyo langkah nyoë hana neupeulaku lom.',
+'passwordremindertext' => 'Salah sidroë (kadang Droëneuh, ngön alamat IP $1) geulakèë lageuëm barô keu {{SITENAME}} ($4). Lageuëm si\'at keu ureuëng ngui "$2" ka geupeuna ngön ka geuatô jeuet keu "$3". Meunyö nyoe nakeuh meukeusud droeneuh, droeneuh peureulèë neutamöng ngön neupiléh lageuëm barô jinoe. Lageuem siat droeneuh meung abéh lam {{PLURAL:$5|siuroe|$5 uroe}}.
+
+Meunyö ureuëng la\'én nyang peugöt neulakèë nyoe, atawa meunyö droeneuh ka neuingat lageuëm droeneuh, ngön droeneuh h\'an ék neugantoë lé, droeneuh jeuet hana neupeureumeuën peusan nyoe ngön neulanjut neungui lageuem awaineuh.',
+'noemail' => 'Hana alamat surat-e nyang teucatat keu ureuëng ngui "$1".',
+'noemailcreate' => 'Droeneuh suwah neuseudia alamt surat-e nyang jeut ngui.',
+'passwordsent' => 'Lageuëm barô ka geupeu\'et u surat-e nyang geupeudapeuta keu "$1". Neutamöng teuma lheuëh neuteurimöng surat-e nyan.',
+'eauthentsent' => 'Saboh surat-e keu peunyö ka geukirém u alamat surat-e Droëneuh. Droëneuh beuneuseutöt préntah lam surat nyan keu neupeunyö meunyö alamat nyan nakeuh beutôi atra Droëneuh. {{SITENAME}} h‘an geupeuudép surat Droëneuh meunyö langkah nyoë hana neupeubuet lom.',
+'cannotchangeemail' => 'Alamat surat-e han jeut geugantoe bak wiki nyoe.',
+'emaildisabled' => 'Situs nyoe han jeut geukirém surat-e.',
+'accountcreated' => 'Ureuëng ngui ka teupeugöt',
+'accountcreatedtext' => 'Ureuëng ngui keu [[{{ns:User}}:$1|$1]]([[{{ns:User talk}}:$1|talk]]) ka teupeugöt.',
+'createaccount-title' => 'Peugöt ureuëng ngui keu {{SITENAME}}',
+'usernamehasherror' => 'Nan ureueng ngui han jeut na tanda pageue',
+'login-throttled' => 'Droeneuh ka lé that neuujoe tamöng.
+Neuprèh $1 sigohlom neuujoe lom.',
 'loginlanguagelabel' => 'Bahsa: $1',
+'createacct-another-realname-tip' => 'Nan aseuli hana meucéh neupasoe.
+Meunyö neupasoe, euntreuk nan droëneuh nyan geupeuleumah mangat jitupeue soe nyang tuléh.',
+
+# Email sending
+'user-mail-no-addy' => 'Ujoe kirém surat-e ngön hana alamat surat-e.',
 
 # Change password dialog
-'retypenew' => 'Pasoë teuma lageuëm barô:',
+'resetpass' => 'Gantoë lageuëm rahsia',
+'resetpass_header' => 'Gantoë lageuëm rahsia nan ureuëng ngui',
+'oldpassword' => 'Lageuëm rahsia awai:',
+'newpassword' => 'Lageuëm rahsia barô:',
+'retypenew' => 'Pasoë lom lageuëm barô:',
+'resetpass_submit' => 'Atô lageuëm rahsia lheuëh nyan tamöng',
+'changepassword-success' => 'Lageuëm rahsia droëneuh meuhasé geugantoë!',
+'resetpass_forbidden' => "Lageuëm rahsia h'an jeuët geugantoë",
+'resetpass-no-info' => "Droëneuh suwah neutamöng mangat jeuët neu'eu laman nyoë",
+'resetpass-submit-loggedin' => 'Gantoë lageuëm rahsia',
+'resetpass-submit-cancel' => 'Pubateuë',
+'resetpass-temp-password' => 'Lageuem rahsia keu siat:',
+
+# Special:PasswordReset
+'passwordreset-username' => 'Ureueng ngui:',
+'passwordreset-capture' => 'Eu hasé surat-e?',
+'passwordreset-email' => 'Alamat surat-e:',
+'passwordreset-emailtitle' => 'Teuneurang nan ureueng ngui bak {{SITENAME}}',
+
+# Special:ChangeEmail
+'changeemail' => 'Gantoe alamat surat-e',
+'changeemail-header' => 'Gantoe alamat surat-e',
+'changeemail-no-info' => "Droeneuh suwah neutamöng mangat jeuet neu'eu laman nyoe",
+'changeemail-oldemail' => 'Alamat surat-e jinoe:',
+'changeemail-newemail' => 'Alamat surat-e barô:',
+'changeemail-none' => '(hana)',
+'changeemail-password' => 'Lageuem rahsia {{SITENAME}} droeneuh:',
+'changeemail-submit' => 'Gantoe surat-e',
+'changeemail-cancel' => 'Peubateue',
 
 # Edit page toolbar
-'bold_sample' => 'Rakam teubay',
-'bold_tip' => 'Haraih teubay',
+'bold_sample' => 'Rakam teubai',
+'bold_tip' => 'Haraih teubai',
 'italic_sample' => 'Rakam singèt naseukah nyoë',
 'italic_tip' => 'Rakam singèt',
-'link_sample' => 'Nan hubông',
-'link_tip' => 'Hubông dalam',
-'extlink_sample' => 'http://www.example.com nan hubông',
-'extlink_tip' => 'Hubông luwa (bèk tuwoë bôh http:// bak away)',
+'link_sample' => 'Nan peunawôt',
+'link_tip' => 'Peunawôt dalam',
+'extlink_sample' => 'http://www.example.com nan peunawôt',
+'extlink_tip' => 'Peunawôt luwa (neubôh http:// bak awai)',
 'headline_sample' => 'Naseukah nan',
 'headline_tip' => 'Aneuk beunagi tingkat 1',
 'nowiki_sample' => 'Bèk format naseukah nyoë',
 'nowiki_tip' => 'Bèk seutot beuntuk wiki',
 'image_tip' => 'Pasoë beureukaih',
-'media_tip' => 'Hubông beureukaih',
+'media_tip' => 'Peunawôt beureukaih',
 'sig_tip' => 'Tanda jaroë Droëneuh ngön tanda watèë',
 'hr_tip' => 'Garéh data',
 
 # Edit pages
-'summary' => 'Ehtisa:',
+'summary' => 'Éhtisa:',
 'subject' => 'Bhah/nan:',
 'minoredit' => 'Nyoë lôn andam bacut',
-'watchthis' => 'Kalön ôn nyoë',
-'savearticle' => 'Keubah ôn',
+'watchthis' => 'Kalön laman nyoë',
+'savearticle' => 'Keubah laman',
 'preview' => 'Eu dilèë',
 'showpreview' => 'Peuleumah hasé',
 'showdiff' => 'Peuleumah neuubah',
 'anoneditwarning' => 'Droëneuh   hana teudapeuta tamong. Alamat IP Droëneuh   teucatat lam tarèh (riwayat away) ôn nyoë.',
 'summary-preview' => 'Eu dilèë neuringkaih:',
+'blockedtitle' => 'Ureueng ngui geutheun',
 'blockedtext' => "'''Nan ureuëng nguy atawa alamat IP Droëneuh  ka geutheun.'''
 
 Geutheun lé $1. Dalèh jih nakeuh ''$2''.
@@ -630,78 +746,152 @@ Droëneuh   jeuët neutanyong bak $1 atawa [[{{MediaWiki:Grouppage-sysop}}|nyang
 Droëneuh   h’an jeuët neunguy alat 'Kirém surat-e ureuëng nguy nyoë' keucuali ka neupasoë alamat surat-e nyang sah di [[Special:Preferences|Geunalak]] Droëneuh ngön Droëneuh ka geutheun keu nguy nyan.
 
 Alamat IP Droëneuh nakeuh $3, ngön ID neutheun nakeuh $5. Tulông peuseureuta salah saboh atawa ban duwa beurita nyoë bak tiëp teunanyöng nyang neupeugöt.",
+'autoblockedtext' => "'''Nan ureuëng nguy atawa alamat IP Droëneuh  ka geutheun.'''
+
+Geutheun lé $1. Dalèh jih nakeuh ''$2''.
+
+* Geutheun yôh: $8
+* Neutheun maté tanggay bak: $6
+* Nyang geutheun: $7
+
+Droëneuh   jeuët neutanyong bak $1 atawa [[{{MediaWiki:Grouppage-sysop}}|nyang urôh nyang la’én]] keu peugah haba bhah nyoë.
+
+Droëneuh   h’an jeuët neunguy alat 'Kirém surat-e ureuëng nguy nyoë' keucuali ka neupasoë alamat surat-e nyang sah di [[Special:Preferences|Geunalak]] Droëneuh ngön Droëneuh ka geutheun keu nguy nyan.
+
+Alamat IP Droëneuh nakeuh $3, ngön ID neutheun nakeuh $5. Tulông peuseureuta salah saboh atawa ban duwa beurita nyoë bak tiëp teunanyöng nyang neupeugöt.",
+'blockednoreason' => 'hana dalèh nyang geubri',
+'whitelistedittext' => 'Droeneuh suwah $1 keu neuandam ôn.',
+'nosuchsectiontitle' => 'Bideueng hana geutumèe',
+'loginreqtitle' => 'Droeneuh payah neutamöng log.',
+'loginreqlink' => 'tamöng',
+'loginreqpagetext' => "Droeneuh payah $1 keu neu'eu ôn-ôn la'én.",
+'accmailtitle' => 'Lageuem rahsia ka meukirém',
 'newarticle' => '(Barô)',
-'newarticletext' => "Droëneuh   ka neuseutot u ôn nyang goh na. Keu peugöt ôn nyan, neukeutik asoë ôn di  kutak di yup nyoë (ngiëng [[{{MediaWiki:Helppage}}|ôn bantu]] keu beurita leubèh lanjut). Meunyo Droëneuh  hana neusaja ka trôk keunoë, teugon '''back''' nyang na bak layeuë.",
-'noarticletext' => 'Hana naseukah jinoë lam ôn nyoë.
+'newarticletext' => "Droëneuh ka neuseutöt peunawôt u laman nyang goh na.
+Keu neupeugöt laman nyan, neukeutik lam plôk di yup (eu [[{{MediaWiki:Helppage}}|laman beunantu]] keu haba leubèh le).
+Meunyö droëneuh trôk keunoë hana neusaja, neuteugön tèk '''back''' bak ''browser'''droëneuh.",
+'anontalkpagetext' => "----''Nyoe nakeuh ôn marit ureueng ngui nyang hana tamöng atawa hana geungui.''
+Saweub nyan, kamoe payah meukubah alamat IP-geuh keu meuparéksa. 
+Alamat IP mungkén jingui lé padum-padum droe ureueng.
+Meunyoe droeneuh ureueng nyang hana tamöng nyan, tulông [[Special:UserLogin/signup|peugöt nan ureueng ngui]] atawa [[Special:UserLogin|tamöng log]] mangat meuteugah nibak bhah nyang hana meuphôm bak uroe la'én.",
+'noarticletext' => 'Hana naseukah jinoë lam laman nyoë.
 Ji Droëneuh jeuët [[Special:Search/{{PAGENAME}}|neumita keu nan ôn nyoë]] bak ôn-ôn la’én, <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} log nyang na hubôngan], atawa [{{fullurl:{{FULLPAGENAME}}|action=edit}} neu\'andam ôn nyoë]</span>.',
-'noarticletext-nopermission' => 'Hana asoë bak ôn nyoë jinoë.
-Droëneuh jeuët [[Special:Search/{{PAGENAME}}|neumita keu nan ôn nyoë]] bak ôn-ôn la\'én,
-atawa <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} neumita log nyang na meuhubông]</span>, tapi Droëneuh hana idin keu neupeugöt ôn nyoë',
+'noarticletext-nopermission' => 'Hana asoë bak laman nyoë jinoë.
+Droëneuh jeuët [[Special:Search/{{PAGENAME}}|neumita keu nan ôn nyoë]] bak laman-laman la\'én,
+atawa <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} neumita log nyang na meuhubông]</span>, tapi Droëneuh hana idin keu neupeugöt laman nyoë',
+'userpage-userdoesnotexist-view' => 'Ureueng ngui "$1" hana teudapeuta.',
 'updated' => '(Seubarô)',
-'note' => "'''Ceunatat:'''",
-'previewnote' => "'''Beu neuingat meunyo ôn nyoë goh lom neukeubah!'''",
+'note' => "'''Hareutoë:'''",
+'previewnote' => "'''Beu neuingat meunyo laman nyoë goh lom neukeubah!'''",
 'editing' => 'Andam $1',
+'creating' => 'Teungöh meupeugöt $1',
 'editingsection' => 'Andam $1 (bideuëng)',
+'editingcomment' => 'Andam $1 (bideuëng)',
+'storedversion' => 'Riwayat meukubah',
+'yourdiff' => 'Bida',
 'copyrightwarning' => "Beu neuingat bahwa ban mandum nyang Droëneuh   tuléh keu {{SITENAME}} geukira geupeuteubiët di yup $2 (ngiëng $1 keu leubèh jeulah). Meunyoë Droëneuh h‘an neutém teunuléh Droëneuh  ji’andam ngön jiba ho ho la’én, bèk neupasoë teunuléh Droëneuh  keunoë.<br />Droëneuh  neumeujanji chit meunyoë teunuléh nyoë nakeuh atra neutuléh keudroë, atawa neucok nibak nè nè atra umôm atawa nè bibeuëh la’én.
 '''BÈK NEUPASOË TEUNULÉH NYANG GEUPEULINDÔNG HAK KARANG NYANG HANA IDIN'''",
-'templatesused' => '{{PLURAL:$1|Templat|Templat}} nyang geunguy bak ôn nyoë:',
-'templatesusedpreview' => '{{PLURAL:$1|Templat|Templat}} nyang geunguy bak eu dilèë nyoë:',
+'templatesused' => '{{PLURAL:$1|Templat|Templates}} nyang geungui bak laman nyoë:',
+'templatesusedpreview' => '{{PLURAL:$1|Templat|Templates}} nyang geungui bak eu dilèë nyoë:',
 'template-protected' => '(geulindông)',
 'template-semiprotected' => '(siteungoh-lindông)',
-'hiddencategories' => 'Ôn nyoë nakeuh anggèëta nibak {{PLURAL:$1|1 kawan teusom |$1 kawan teusom}}:',
-'nocreatetext' => '{{SITENAME}} ka jikot bak peugöt ôn barô. Ji Droëneuh   jeuët neuriwang teuma ngön neu’andam ôn nyang ka na, atawa [[Special:UserLogin|neutamong atawa neudapeuta]].',
+'hiddencategories' => 'Laman nyoë nakeuh anggèëta nibak {{PLURAL:$1|1 kawan teusom |$1 kawan teusom}}:',
+'nocreatetext' => '{{SITENAME}} ka jiköt bak peugöt laman barô. Ji Droëneuh   jeuët neuriwang teuma ngön neu’andam laman nyang ka na, atawa [[Special:UserLogin|neutamong atawa neudapeuta]].',
+'nocreate-loggedin' => 'Droeneuh hana khut keu neupeugöt laman-laman barô.',
+'sectioneditnotsupported-title' => 'Andam bideung hana meudukông',
+'sectioneditnotsupported-text' => 'Andam bideung hana meudukông bak ôn nyoe.',
+'permissionserrors' => 'Salah khut/hak tamöng',
+'permissionserrorstext' => 'Droëneuh hana hak tamöng keu $2, muroë {{PLURAL:$1|choë|choë}} nyoë:',
 'permissionserrorstext-withaction' => 'Droëneuh hana hak tamöng keu $2, muroë {{PLURAL:$1|choë|choë}} nyoë:',
-'recreate-moveddeleted-warn' => "'''Ingat: Droëneuh neupeugöt ulang saboh ôn nyang ka tom geusampôh. ''',
-
-Neutimang-timang dilèë peuë ék patôt neupeulanjut atra nyang teungoh neu’andam.
-Nyoë pat nakeuh log seunampôh nibak ôn nyoë:",
-'moveddeleted-notice' => 'Ôn nyoë ka geusampôh.
-Log seunampôh ngon log peuninah ôn nyoë geupeuseudiya di yup nyoe keu keuneubah.',
+'recreate-moveddeleted-warn' => "'''Ingat: Droëneuh neupeugöt ulang saboh laman nyang ka tom geusampôh. ''',
+
+Neutimang-timang dilèë peuë ék patôt neupeulanjut atra nyang teungöh neu’andam.
+Nyoë pat nakeuh log seunampôh nibak laman nyoë:",
+'moveddeleted-notice' => 'Laman nyoë ka geusampôh.
+Log seunampôh ngön log pinah laman nyoë geupeuseudia di yup nyoë keu keuneubah.',
+'log-fulllog' => 'Eu ban dum ceunatat',
+'edit-hook-aborted' => "Seunampôh geupeubateuë lé kaw'ét parser.
+Hana jeuneulaih.",
+'edit-gone-missing' => 'Han jeut peubarô ôn.
+Ôn nyoe mungkén ka geusampôh.',
+'postedit-confirmation' => 'Neuandam droeneuh ka meukubah.',
+'edit-already-exists' => 'Han jeut peugöt ôn barô.
+Ôn nyoe ka lheuh na.',
 
 # Parser/template warnings
 'post-expand-template-inclusion-warning' => "'''Ingat:''' Seunipat seunaleuëk nyang neunguy rayek that.
 Ladôm seunaleuëk hana geupeurôh",
-'post-expand-template-inclusion-category' => 'Ôn ngön seunipat seunaleuëk nyang leubèh bataih',
-'post-expand-template-argument-warning' => "'''Ingat:''' On nyoe na paleng h'an saboh alasan seunaleuek nyang na sunipat ekspansi nyang raya that.
-Alasan-alasan nyan hana geupeureumeuen.",
-'post-expand-template-argument-category' => 'On ngon alasan seunaleuek nyang hana geupeureumeuen',
+'post-expand-template-inclusion-category' => 'Laman ngön seunipat seunaleuëk nyang leubèh bataih',
+'post-expand-template-argument-warning' => "'''Ingat:''' Laman nyoe na paléng h'an saboh alasan seunaleuëk nyang na sunipat èkspansi nyang raya that.
+Alasan-alasan nyan hana geupeureumeuën.",
+'post-expand-template-argument-category' => 'Laman ngön dalèh seunaleuëk nyang hana geupeureumeuën',
+
+# Account creation failure
+'cantcreateaccounttitle' => 'Han jeut peugöt nan ureueng ngui',
+'cantcreateaccount-text' => "Peuneugöt nan ureueng ngui nibak alamat IP ('''$1''') ka geutheun lé [[User:$3|$3]].
+
+Dalèh $3 nyoe nakeuh ''$2''",
 
 # History pages
-'viewpagelogs' => 'Eu log ôn nyoë',
+'viewpagelogs' => 'Eu log laman nyoë',
+'nohistory' => 'Hana riwayat neuandam awai keu ôn nyoe.',
 'currentrev' => 'Geunantoë jinoë',
 'currentrev-asof' => 'Geunantoë barô bak $1',
 'revisionasof' => 'Geunantoë tiëp $1',
 'revision-info' => 'Geunantoë tiëp $1; $2',
-'previousrevision' => '←Geunantoë sigohlomjih',
+'previousrevision' => '← Geunantoë awai',
 'nextrevision' => 'Geunantoë lheuëh nyan→',
 'currentrevisionlink' => 'Geunantoë jinoë',
 'cur' => 'jin',
-'last' => 'akhé',
+'next' => 'u keu',
+'last' => 'sigohlom',
 'page_first' => 'phôn',
 'page_last' => 'keuneulheuëh',
 'histlegend' => "Piléh duwa teuneugön radiô, lheuëh nyan teugön teuneugön ''peubandéng'' keu peubandéng seunalén. Teugön saboh tanggay keu eu seunalén ôn bak tanggay nyan.<br />(skr) = bida ngön seunalén jinoë, (akhé) = bida ngön seunalén sigohlomjih. '''u''' = andam ubeut, '''b''' = andam bot, → = andam bideuëng, ← = ehtisa keudroë",
-'history-fieldset-title' => 'Eu riwayat away',
-'history-show-deleted' => 'Nyang geusampoh mantong',
+'history-fieldset-title' => 'Eu riwayat awai',
+'history-show-deleted' => 'Nyang geusampôh mantöng',
 'histfirst' => 'paléng trép',
 'histlast' => 'paléng barô',
+'historyempty' => '(soh)',
 
 # Revision feed
+'history-feed-title' => 'Riwayat neupeupah',
+'history-feed-description' => 'Riwayat neupeupah keu ôn nyoe bak wiki',
 'history-feed-item-nocomment' => '$1 bak $2',
 
 # Revision deletion
+'rev-deleted-comment' => '(mohtasa neuandam geusampôh)',
+'rev-deleted-user' => '(nan ureueng ngui geusampôh)',
+'rev-deleted-user-contribs' => '[nan ureueng ngui atawa alamat IP geusampôh - neuandam geupeusom bak dapeuta beuneuri]',
 'rev-delundel' => 'peuleumah/peusom',
-'revdel-restore' => 'Ubah neuleumah',
+'rev-showdeleted' => 'peudeuh',
+'revdelete-show-file-submit' => 'Nyoe',
+'revdelete-hide-comment' => 'Mohtasa neuandam',
+'revdelete-radio-same' => '(bèk neugantoe)',
+'revdelete-radio-set' => 'Deuh',
+'revdelete-radio-unset' => 'Teusom',
+'revdelete-log' => 'Dalèh:',
+'revdel-restore' => 'Gantoë seuneudeuih',
 'revdel-restore-deleted' => 'geunantoe nyang ka geusampôh',
-'revdel-restore-visible' => 'geunantoe nyang leumah',
+'revdel-restore-visible' => 'geunantoë nyang deuih',
+'pagehist' => 'Taréh laman',
+'deletedhist' => 'Taréh nyang meusampôh',
+
+# History merging
+'mergehistory-from' => 'Asai ôn:',
+'mergehistory-invalid-source' => 'Asai ôn payah nan nyang beutôi.',
+'mergehistory-reason' => 'Dalèh:',
 
 # Merge log
+'mergelog' => 'Peugabông log',
 'revertmerge' => 'Hana jadèh peugabông',
 
 # Diffs
 'history-title' => 'Riwayat geunantoë nibak "$1"',
 'lineno' => 'Baréh $1:',
 'compareselectedversions' => 'Peubandéng curak teupiléh',
-'editundo' => 'peubateuë',
+'editundo' => 'pubateuë',
+'diff-empty' => '(Hana bida)',
 'diff-multi' => '({{PLURAL:$1|Saboh|$1}} geunantoë antara nyang geupeugot le {{PLURAL:$2|sidroe|$2}} ureueng nguy hana geupeuleumah)',
 
 # Search results
@@ -710,30 +900,30 @@ Alasan-alasan nyan hana geupeureumeuen.",
 'searchresulttext' => 'Keu beurita leubèh le bhah meunita bak {{SITENAME}}, eu [[{{MediaWiki:Helppage}}|ôn beunantu]].',
 'searchsubtitle' => 'Droëneuh neumita \'\'\'[[:$1]]\'\'\' ([[Special:Prefixindex/$1|ban dum ôn nyang geupuphôn ngön "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|bandum ôn nyang teuhubông u "$1"]])',
 'searchsubtitleinvalid' => "Droëneuh neumita '''$1'''",
-'notitlematches' => 'Hana nan ôn nyang pah',
-'notextmatches' => 'Hana naseukah ôn nyang pah',
+'notitlematches' => 'Hana nan laman nyang pah',
+'notextmatches' => 'Hana naseukah laman nyang pah',
 'prevn' => '{{PLURAL:$1|$1}} sigohlomjih',
 'nextn' => '{{PLURAL:$1|$1}} lheuëh nyan',
 'prevn-title' => '$1 {{PLURAL:$1|hasé|hasé}} sigohlomjih',
 'nextn-title' => '$1 {{PLURAL:$1|hasé}} lheuëh nyan',
-'shown-title' => 'Peuleumah $1 {{PLURAL:$1|hasé}} tiëp ôn',
+'shown-title' => 'Peuleumah $1 {{PLURAL:$1|hasé}} tiëp laman',
 'viewprevnext' => 'Eu ($1 {{int:pipe-separator}} $2)($3)',
-'searchmenu-exists' => "'''Na on ngon nan \"[[:\$1]]\" bak wiki nyoe.'''",
-'searchmenu-new' => "'''Peugöt ôn \"[[:\$1]]\" bak wiki nyoë!'''",
-'searchprofile-articles' => 'Ôn asoë',
-'searchprofile-project' => 'Ôn Beunantu ngön Buët',
+'searchmenu-exists' => "'''Na laman ngön nan \"[[:\$1]]\" bak wiki nyoe.'''",
+'searchmenu-new' => "'''Peugöt laman \"[[:\$1]]\" bak wiki nyoë!'''",
+'searchprofile-articles' => 'Laman asoë',
+'searchprofile-project' => 'Laman Beunantu ngön Buët',
 'searchprofile-images' => 'Multimedia',
 'searchprofile-everything' => 'Ban dum',
 'searchprofile-advanced' => 'Tingkat lanjut',
 'searchprofile-articles-tooltip' => 'Mita bak $1',
 'searchprofile-project-tooltip' => 'Mita bak $1',
 'searchprofile-images-tooltip' => 'Mita beureukaih',
-'searchprofile-everything-tooltip' => 'Mita ban dum ôn asoë (rôh ôn marit)',
+'searchprofile-everything-tooltip' => 'Mita ban dum laman asoë (rôh ôn marit)',
 'searchprofile-advanced-tooltip' => 'Mita bak ruweuëng nan meupat-pat',
 'search-result-size' => '$1 ({{PLURAL:$2|1 narit|$2 narit}})',
 'search-result-category-size' => '{{PLURAL:$1|1 anggeeta|$1 anggeeta}} ({{PLURAL:$2|1 aneuk kawan|$2 aneuk kawan}}, {{PLURAL:$3|1 beureukaih|$3 beureukaih}})',
 'search-redirect' => '(peuninah $1)',
-'search-section' => '(beunagi $1)',
+'search-section' => '(bideuëng $1)',
 'search-suggest' => 'Kadang meukeusud Droëneuh nakeuh: $1',
 'search-interwiki-caption' => 'Buët la’én',
 'search-interwiki-default' => 'Hasé $1:',
@@ -741,64 +931,180 @@ Alasan-alasan nyan hana geupeureumeuen.",
 'searchrelated' => 'meusambat',
 'searchall' => 'ban dum',
 'showingresultsheader' => "{{PLURAL:$5|Hase '''$1''' nibak '''$3'''|Hase '''$1 - $2''' nibak '''$3'''}} keu '''$4'''",
-'nonefound' => "'''Ceunatat''': Cit ladôm ruweuëng nyang seucara baku geupeutamöng lam meunita. Ci neupuphôn leunakèë Droëneuh ngön ''all:'' keu mita ban dum asoë (rôh cit ôn peugah haba, tèmplat, ngön nyang la’én (nnl)), atawa neunguy ruweuëng nan nyang neumeuh’eut sibagoë neu’away.",
-'search-nonefound' => 'Hana hase nyang paih lagee atra neulakee',
+'nonefound' => "'''Teuneurang''': Ladôm ruweuëng nan mantöng nyang geumita. 
+Neubaci puphôn neulakèë droëneuh ngön ''all:'' keu jak mita ban dum asoë (rôh lam nyan laman marit, seunaleuëk, ngön nyang la’én nibak nyan), atawa neungui ruweuëng nan nyang neumeuh’eut sibagoë neuawai.",
+'search-nonefound' => 'Hana hasé nyang paih lagèë neulakèë',
 'powersearch' => 'Mita lanjut',
 'powersearch-legend' => 'Mita lanjut',
 'powersearch-ns' => 'Mita bak ruweuëng nan:',
 'powersearch-redir' => 'Dapeuta peuninah',
 'powersearch-field' => 'Mita',
+'powersearch-toggleall' => 'Ban dum',
+'powersearch-togglenone' => 'Hana',
 
 # Preferences page
 'preferences' => 'Galak',
 'mypreferences' => 'Atô',
+'prefs-edits' => 'Jumeulah neuandam:',
+'changepassword' => 'Gantoe lageuem rahsia',
+'prefs-skin' => 'Kulét',
+'skin-preview' => 'Eu dilèe',
+'datedefault' => 'Hana geunalak',
+'prefs-beta' => 'Fitur bèta',
+'prefs-datetime' => 'Uroe ngön jeum',
+'prefs-user-pages' => 'Laman ureueng ngui',
+'prefs-personal' => 'Profil ureueng ngui',
 'prefs-rc' => 'Ban meuubah',
-'prefs-email' => 'Peunileh surat-e',
+'prefs-watchlist' => 'Dapeuta keunalön',
+'prefs-watchlist-days' => 'Jumeulah uroe nyang meupeudeuh bak dapeuta keunalön:',
+'prefs-watchlist-days-max' => '{{PLURAL:$1|uroë}}',
+'prefs-misc' => "La'én-la'én",
+'prefs-resetpass' => 'Gantoe lageuem rahsia',
+'prefs-changeemail' => 'Gantoe alamat surat-e',
+'prefs-setemail' => 'Pasoe alamat surat-e',
+'prefs-email' => 'Peuniléh surat-e',
+'prefs-rendering' => 'Seuneudeuh',
+'saveprefs' => 'Kubah',
+'resetprefs' => 'Peugléh neuubah nyang goh meukubah',
+'prefs-editing' => 'Neuandam',
+'rows' => 'Baréh:',
 'searchresultshead' => 'Mita',
+'resultsperpage' => 'Hasé lam saboh laman:',
+'stub-threshold-disabled' => 'Geupeumaté',
+'timezoneuseoffset' => "La'én (peuteuntèe bidajih)",
+'timezoneoffset' => 'Bida:',
+'timezoneregion-america' => 'Amirika',
+'timezoneregion-antarctica' => 'Antartika',
+'timezoneregion-atlantic' => 'Laôt Atlantik',
+'timezoneregion-europe' => 'Ierupa',
+'timezoneregion-indian' => 'Laôt India',
+'timezoneregion-pacific' => 'Laôt Pasifik',
+'allowemail' => "Peuudép surat-e nibak ureueng ngui la'én",
+'prefs-searchoptions' => 'Mita',
+'prefs-namespaces' => 'Ruweuëng nan',
+'defaultns' => 'Atawa neumita lam ruweueng nan nyoe:',
+'default' => 'meuneumat',
+'prefs-files' => 'Beureukaih',
 'youremail' => 'Surat-e:',
+'prefs-registration' => 'Watèe neudapeuta:',
 'yourrealname' => 'Nan aseuli:',
+'yourlanguage' => 'Bahsa:',
+'yournick' => 'Tanda jaroe barô:',
+'prefs-help-signature' => 'Komèntar bak ôn marit suwah neubôh "<nowiki>~~~~</nowiki>", nyang eunteuk meugantoe keu tanda jaroe droeneuh ngön watèe jinoe.',
+'badsiglength' => 'Tanda jaroe droeneuh panyang that.
+Panyangjih bèk leubèh nibak $1 {{PLURAL:$1|haraih|haraih}}.',
+'gender-unknown' => 'Hana geupeunyata',
+'gender-male' => 'Ureueng agam',
+'gender-female' => 'Ureueng inöng',
+'email' => 'Surat-e',
 'prefs-help-realname' => '* Nan aseuli hana meucéh neupasoë.
-Meunyo neupasoë, euntreuk nan Droëneuh nyan geupeuleumah mangat jitupeuë soë nyang tuléh.',
-'prefs-help-email' => 'Alamat surat-e hana meuceh na, tapi geupeureulee keu seumeugot ulang lageuem, meunyo droeneuh tuwoe lageuem.',
-'prefs-help-email-others' => "Droeneuh jeuet cit neupileh neupubiyeue ureueng la'en geupeu'et surat keu droeneuh rot surat-e rot seunambat bak on ureueng nguy atawa on marit.
-Surat-e droeneuh h'an geupeugah keu ureueng nyan.",
+Meunyö neupasoë, euntreuk nan Droëneuh nyan geupeuleumah mangat jitupeuë soë nyang tuléh.',
+'prefs-help-email' => 'Alamat surat-e hana meucéh na, tapi geupeureulèë keu seumeugöt ulang lageuem, meunyö droeneuh tuwö lageuëm.',
+'prefs-help-email-others' => "Droeneuh jeuet cit neupiléh neupubiyeuë ureuëng la'én geupeu'et surat keu droeneuh röt surat-e röt seunambat bak laman ureueng ngui atawa on mariët.
+Surat-e droeneuh h'an geupeugah keu ureuëng nyan.",
+'prefs-help-email-required' => 'Peureulèe alamat surat-e.',
+'prefs-signature' => 'Tanda jaroe',
+'prefs-dateformat' => 'Format uroe/watèe',
+'prefs-timeoffset' => 'Bida watèe',
+'prefs-advancedediting' => 'Peuniléh umom',
+'prefs-editor' => 'Ureueng andam',
+'prefs-preview' => 'Eu dilèe',
+'prefs-diffs' => 'Bida',
+'prefs-help-prefershttps' => 'Geunalak nyoe geupeudeuh watèe neutamöng lom.',
+
+# User preference: email validation using jQuery
+'email-address-validity-valid' => 'Alamat surat-e sah',
+'email-address-validity-invalid' => 'Pasoe alamat surat-e nyang sah',
+
+# User rights
+'userrights-user-editname' => 'Pasoe nan ureueng ngui:',
+'editusergroup' => 'Ubah kawan ureueng ngui',
+'editinguser' => "Gantoe khut ureueng ngui '''[[User:$1|$1]]''' $2",
+'userrights-editusergroup' => 'Ubah kawan ureueng ngui',
+'saveusergroups' => 'Ubah kawan ureueng ngui',
+'userrights-groupsmember' => 'Anggèeta nibak:',
+'userrights-reason' => 'Dalèh:',
+'userrights-no-interwiki' => "Droeneuh hana izin keu neuubah khut ureueng ngui bak wiki la'én.",
+'userrights-notallowed' => 'Droeneuh hana izin keu neutamah atawa neupeugadöh khut ureueng ngui.',
+'userrights-changeable-col' => 'Kawan nyang jeut neugantoe',
+'userrights-unchangeable-col' => 'Kawan nyang han jeut neugantoe',
 
 # Groups
+'group' => 'Kawan:',
+'group-user' => 'Ureueng-ureueng ngui',
+'group-autoconfirmed' => 'Ureueng ngui nyang meu-konfirmasi otomatis',
 'group-sysop' => 'Ureuëng urôh',
-
+'group-bureaucrat' => 'Birôkrat',
+'group-suppress' => 'Ureueng kalön',
+'group-all' => '(ban dum)',
+
+'group-user-member' => '{{GENDER:$1|ureueng ngui}}',
+'group-autoconfirmed-member' => '{{GENDER:$1|ureueng ngui meu-konfirmasi otomatis}}',
+'group-bot-member' => '{{GENDER:$1|bot}}',
+'group-sysop-member' => '{{GENDER:$1|ureueng urôh}}',
+'group-bureaucrat-member' => '{{GENDER:$1|birôkrat}}',
+'group-suppress-member' => '{{GENDER:$1|ureueng kalön}}',
+
+'grouppage-user' => '{{ns:project}}:Ureueng ngui',
+'grouppage-autoconfirmed' => '{{ns:project}}:Ureueng ngui meu-konfirmasi otomatis',
+'grouppage-bot' => '{{ns:project}}:Bots',
 'grouppage-sysop' => '{{ns:project}}:Ureuëng urôh',
+'grouppage-bureaucrat' => '{{ns:project}}:Birôkrat',
+'grouppage-suppress' => '{{ns:project}}:Ureueng kalön',
+
+# Rights
+'right-read' => 'Beuet laman',
+'right-edit' => 'Andam laman',
+'right-createpage' => 'Peugöt laman barô (nyang kön laman marit)',
+'right-createtalk' => 'Peugöt ôn marit',
+'right-createaccount' => 'Peugöt nan ureueng ngui barô',
+'right-minoredit' => 'Bôh tanda seubagoe andam ubeut',
+'right-move' => 'Pinah laman',
+'right-move-subpages' => 'Pinah laman ngön ban dum aneuk laman',
+'right-move-rootuserpages' => 'Pinah laman ureueng ngui',
+'right-movefile' => 'Pinah beureukaih',
+'right-upload' => 'Peutamöng beureukaih',
+'right-upload_by_url' => 'Peutamöng beureukaih nibak URL',
+'right-delete' => 'Sampôh laman',
+'right-bigdelete' => 'Sampôh laman ngön ban dum riwayatjih',
+'right-browsearchive' => 'Mita laman nyang geusampôh',
 
 # Special:Log/newusers
-'newuserlogpage' => 'ureuëng nguy barô',
+'newuserlogpage' => 'Ureuëng ngui barô',
 
 # User rights log
 'rightslog' => 'Log neuubah hak peuhah',
 
 # Associated actions - in the sentence "You do not have permission to X"
-'action-edit' => 'andam ôn nyoë',
+'action-read' => 'beuët laman nyoe',
+'action-edit' => 'andam laman nyoë',
+'action-createpage' => 'peugöt laman',
+'action-move' => 'Peupinah laman nyoë',
 
 # Recent changes
-'nchanges' => '$1 {{PLURAL:$1|neu’ubah|neu’ubah}}',
+'nchanges' => '$1 {{PLURAL:$1|neuubah}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|yôh seunaweuë seuneulheuëh kön}}',
 'recentchanges' => 'Neuubah barô',
 'recentchanges-legend' => 'Peuniléh neuubah barô',
 'recentchanges-summary' => "Di yup nyoë nakeuh neuubah barô nyang na bak Wikipèdia nyoë.
-Ceunatat: (bida) = neuubah, (riwayat) = riwayat teumuléh, '''B''' = ôn barô, '''u''' = neuandam ubeut, '''b''' = neuandam bot, (± ''bit'') = jumeulah asoë meutamah/meukureuëng, → = neuandam beunagi, ← = mohtasa otomatis.
+Hareutoë: (bida) = neuubah, (riwayat) = riwayat teumuléh, '''B''' = laman barô, '''u''' = neuandam ubeut, '''b''' = neuandam bot, (± ''bit'') = jeumeulah asoë meutamah/meukureuëng, → = neuandam bideuëng, ← = mohtasa otomatis.
 ----",
-'recentchanges-feed-description' => 'Peuteumèë neu’ubah barô lam wiki bak umpeuën nyoë.',
-'recentchanges-label-newpage' => 'Neuandam nyoe jipeugot on baro',
+'recentchanges-noresult' => 'Hana neuubah lam lheuëng watèë nyoë nyang paih ngön syarat',
+'recentchanges-feed-description' => 'Seutöt neuubah barô lam wiki bak umpeuën nyoë.',
+'recentchanges-label-newpage' => 'Neuandam nyoë jipeugöt laman barô',
 'recentchanges-label-minor' => 'Nyoe neuandam ubeut',
 'recentchanges-label-bot' => 'Neuandam nyoe geupubuet le bot',
 'recentchanges-label-unpatrolled' => 'Neuandam nyoe goh lom geukalon',
 'rcnote' => "Di yup nyoë nakeuh {{PLURAL:$1|nakeuh '''1''' neu’ubah barô |nakeuh '''$1''' neu’ubah barô}} lam {{PLURAL:$2|'''1''' uroë|'''$2''' uroë}} nyoë, trôk ‘an $5, $4.",
-'rcnotefrom' => 'Di yup nyoë nakeuh neu’ubah yôh <strong>$2</strong> (geupeuleumah trôh ‘an <strong>$1</strong> neu’ubah).',
-'rclistfrom' => 'Peuleumah neuubah paléng barô yôh $1 kön',
+'rcnotefrom' => 'Di yup nyoë nakeuh neuubah yôh <strong>$2</strong> (geupeudeuh trôh ‘an <strong>$1</strong> neuubah).',
+'rclistfrom' => 'Peudeuih neuubah barô yôh $1 kön',
 'rcshowhideminor' => '$1 andam bacut',
 'rcshowhidebots' => '$1 bot',
-'rcshowhideliu' => '$1 ureuëng nguy tamong',
-'rcshowhideanons' => '$1 ureuëng nguy hana nan',
+'rcshowhideliu' => '$1 ureuëng ngui tamöng',
+'rcshowhideanons' => '$1 ureuëng ngui hana nan',
 'rcshowhidepatr' => '$1 andam teurunda',
 'rcshowhidemine' => '$1 atra lôn andam',
-'rclinks' => 'Peuleumah $1 neuubah paléng barô lam $2 uroë nyoë<br />$3',
+'rclinks' => 'Peudeuih $1 neuubah barô lam $2 uroë nyoë<br />$3',
 'diff' => 'bida',
 'hist' => 'riwayat',
 'hide' => 'Peusom',
@@ -806,48 +1112,100 @@ Ceunatat: (bida) = neuubah, (riwayat) = riwayat teumuléh, '''B''' = ôn barô,
 'minoreditletter' => 'b',
 'newpageletter' => 'B',
 'boteditletter' => 'b',
+'number_of_watching_users_pageview' => '[$1 {{PLURAL:$1|ureueng kalön|ureueng kalön}}]',
+'rc_categories_any' => 'Pue-pue mantöng',
+'rc-change-size-new' => '$1 {{PLURAL:$1|bita|bita}} lheuh meuandam',
+'newsectionsummary' => '/* $1 */ bideung barô',
 'rc-enhanced-expand' => 'Peuleumah rincian',
 'rc-enhanced-hide' => 'Peusom rincian',
+'rc-old-title' => 'sigohlom nyan geupeugöt "$1"',
 
 # Recent changes linked
-'recentchangeslinked' => 'Neuubah meuhubông',
+'recentchangeslinked' => "Neuubah meukaw'èt",
 'recentchangeslinked-feed' => 'Neuubah meuhubông',
-'recentchangeslinked-toolbox' => 'Neuubah meuhubông',
-'recentchangeslinked-title' => 'Neuubah nyang meuhubông ngön $1',
+'recentchangeslinked-toolbox' => "Neuubah teukaw'èt",
+'recentchangeslinked-title' => "Neuubah nyang meukaw'èt ngön $1",
 'recentchangeslinked-summary' => "Nyoë nakeuh dapeuta neuubah nyang geupeugèt ban-ban nyoë keu on-on nyang meuhubông nibak ôn ka kusuih (atawa keu anggèëta kawan kusuih).
 Ôn-ôn bak [[Special:Watchlist|keunalon droeneuh]] geucitak '''teubay'''.",
-'recentchangeslinked-page' => 'Nan ôn:',
-'recentchangeslinked-to' => 'Peuleumah neu’ubah nibak ôn-ôn nyang meusambông ngön ôn nyang geubri',
+'recentchangeslinked-page' => 'Nan laman:',
+'recentchangeslinked-to' => 'Peuleumah neuubah nibak laman-laman nyang mupawôt ngön laman nyang geubri',
 
 # Upload
-'upload' => 'Peutamong beureukaih',
-'uploadbtn' => 'Peutamong beureukah',
+'upload' => 'Peutamöng beureukaih',
+'uploadbtn' => 'Peutamong beureukaih',
+'reuploaddesc' => 'Riwang u laman peutamöng',
+'uploadnologin' => 'Hana lom meutamöng',
+'uploadnologintext' => 'Droeneuh suwah $1 keu neupeutamöng beureukaih.',
+'uploadlog' => 'ceunatat peutamöng',
 'uploadlogpage' => 'Log peutamöng',
+'uploadlogpagetext' => 'Nyoe nakeuh dapeuta peutamöng barô.
+Eu [[Special:NewFiles|galeri beureukaih barô]] keu seuneudeuh barô.',
+'filename' => 'Nan beureukaih',
 'filedesc' => 'Ehtisa',
+'fileuploadsummary' => 'Éhtisa:',
+'filesource' => 'Nè',
+'uploadedfiles' => 'Beureukaih nyang meupeutamöng',
+'minlength1' => 'Nan beureukaih beuna saboh haraih.',
+'illegalfilename' => 'Nan beureukaih "$1" meuasoe seunurat nyang han jeut na bak nan. Tulông gantoe nan nyan sigohlom neupeutamöng lom.',
+'filename-toolong' => 'Nan beureukaih han jeut leubèh nibak 240 bita.',
+'badfilename' => 'Nan beureukaih ka meugantoe keu "$1".',
+'empty-file' => 'Beureukaih nyang neupeutamöng soh.',
+'file-too-large' => 'Beureukaih nyang neupeutamöng rayek that.',
+'filename-tooshort' => 'Nan beureukaih paneuk that.',
+'filetype-banned' => 'Jeunèh beureukaih nyoe geutheun.',
+'illegal-filename' => 'Nan beureukaih han jeut lagèe nyoe.',
+'savefile' => 'Kubah beureukaih',
 'uploadedimage' => 'peutamöng "[[$1]]"',
+'overwroteimage' => 'peutamöng vèrsi barô "[[$1]]"',
+'upload-source' => 'Asai beureukaih',
+'sourcefilename' => 'Asai nan beureukaih:',
+'sourceurl' => 'Asai URL:',
+'upload-maxfilesize' => 'Paléng rayek beureukaih: $1',
+'upload-description' => 'Teuneurang beureukaih',
+'watchthisupload' => 'Kalön beureukaih nyoe',
+'upload-success-subj' => 'Ka meupeutamöng',
+
+# img_auth script messages
+'img-auth-nofile' => 'Hana beureukaih "$1".',
 
-'license' => 'Jeuneh lisensi:',
-'license-header' => 'Jeuneh lisensi',
+'license' => 'Jeunèh lisensi:',
+'license-header' => 'Jeunèh lisensi',
 
 # Special:ListFiles
+'imgfile' => 'beureukaih',
 'listfiles' => 'Dapeuta beureukah',
+'listfiles_thumb' => 'Beuntuk ubeut',
+'listfiles_date' => 'Uroe',
+'listfiles_name' => 'Nan',
+'listfiles_user' => 'Ureueng ngui',
+'listfiles_size' => 'Rayek',
+'listfiles_description' => 'Teuneurang',
+'listfiles_count' => 'Vèrsi',
+'listfiles-show-all' => 'Peurôh vèrsi awai gamba',
+'listfiles-latestversion' => 'Vèrsi jinoe',
+'listfiles-latestversion-yes' => 'Nyoe',
+'listfiles-latestversion-no' => 'Kön',
 
 # File description page
 'file-anchor-link' => 'Beureukaih',
 'filehist' => 'Riwayat beureukaih',
 'filehist-help' => "Neuteugon bak uroë buleuën/watèë keu neu'eu beureukaih nyoë ‘oh watèë nyan.",
+'filehist-deleteall' => 'sampôh ban dum',
+'filehist-deleteone' => 'sampôh',
 'filehist-revert' => 'peuriwang',
 'filehist-current' => 'jinoë hat',
 'filehist-datetime' => 'Uroë buleuën/Watèë',
 'filehist-thumb' => 'Beuntuk ubeut',
 'filehist-thumbtext' => 'Beuntuk ubeut keu seunalén tiëp $1',
-'filehist-user' => 'Ureuëng nguy',
+'filehist-nothumb' => 'Hana beuntuk ubeut',
+'filehist-user' => 'Ureuëng ngui',
 'filehist-dimensions' => 'Dimènsi',
 'filehist-filesize' => 'Rayek beureukah',
 'filehist-comment' => "Seuneu'ôt",
-'imagelinks' => 'Neunguy beureukaih',
-'linkstoimage' => 'Ôn di yup nyoë na {{PLURAL:$1|hubông|$1 hubông}} u beureukah nyoë:',
-'nolinkstoimage' => 'Hana ôn nyang na hubông u beureukah nyoë.',
+'filehist-missing' => 'Beureukaih hana meutumèe',
+'imagelinks' => 'Seuneungui beureukaih',
+'linkstoimage' => '{{PLURAL:$1|laman}} di yup nyoë mupawôt u beureukaih nyoë:',
+'nolinkstoimage' => 'Hana laman nyang na meupawôt u beureukaih nyoë.',
 'sharedupload' => 'Beureukah nyoë dari $1 ngön kadang geunguy lé buët-buët la’én.',
 'sharedupload-desc-here' => "Beureukaih nyoe nejih nibak $1 ngon kadang geunguy le proyek-proyek la'en.
 Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
@@ -860,10 +1218,10 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'listredirects' => 'Dapeuta peuninah',
 
 # Unused templates
-'unusedtemplates' => 'Templat nyang hana geunguy',
+'unusedtemplates' => 'Templat nyang hana geungui',
 
 # Random page
-'randompage' => 'Ôn beurangkari',
+'randompage' => 'Laman baranggari',
 
 # Random redirect
 'randomredirect' => 'Peuninah saban sakri',
@@ -875,7 +1233,7 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 
 'brokenredirects' => 'Peuninah reulöh',
 
-'withoutinterwiki' => 'Ôn tan na hubông bahsa',
+'withoutinterwiki' => 'Laman tan na hubông bahsa',
 
 'fewestrevisions' => 'Teunuléh ngön neu’ubah paléng dit',
 
@@ -883,34 +1241,38 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'nbytes' => '$1 {{PLURAL:$1|bit|bit}}',
 'nlinks' => '$1 {{PLURAL:$1|hubông|hubông}}',
 'nmembers' => '$1 {{PLURAL:$1|asoë|asoë}}',
-'lonelypages' => 'Ôn tan hubông balék',
-'uncategorizedpages' => 'Ôn nyang hana rôh lam kawan',
-'uncategorizedcategories' => 'Kawan nyang hana rôh lam kawan',
-'uncategorizedimages' => 'Beureukah nyang hana rôh lam kawan',
-'uncategorizedtemplates' => 'Templat nyang hana rôh lam kawan',
-'unusedcategories' => 'Kawan nyang hana geunguy',
-'unusedimages' => 'Beureukah nyang hana geunguy',
-'wantedcategories' => 'Kawan nyang geuhawa',
-'wantedpages' => 'Ôn nyang geuh‘eut',
-'mostlinked' => 'Ôn nyang paléng kayém geusaweuë',
-'mostlinkedcategories' => 'Kawan nyang paléng kayém geunguy',
-'mostlinkedtemplates' => 'Templat nyang paléng kayém geunguy',
+'lonelypages' => 'Laman tan hubông balék',
+'uncategorizedpages' => 'Laman hana kawan',
+'uncategorizedcategories' => 'Kawan hana kawan',
+'uncategorizedimages' => 'Beureukaih hana kawan',
+'uncategorizedtemplates' => 'Seunaleuëk hana kawan',
+'unusedcategories' => 'Kawan hana geungui',
+'unusedimages' => 'Beureukaih hana geungui',
+'popularpages' => 'Laman jithèë',
+'wantedcategories' => "Kawan geuh'eut",
+'wantedpages' => 'Laman geuh‘eut',
+'wantedpages-badtitle' => 'Nan hana sah lam kawan hasé: $1',
+'wantedfiles' => "Beureukaih nyang geumeuh'eut",
+'mostlinked' => 'Laman nyang paléng kayém geutuju',
+'mostlinkedcategories' => 'Kawan nyang paléng kayém geutuju',
+'mostlinkedtemplates' => 'Templat nyang paléng kayém geutuju',
 'mostcategories' => 'Teunuléh ngön kawan paléng le',
 'mostimages' => 'Beureukah nyang paléng kayém geunguy',
 'mostrevisions' => 'Teunuléh ngön neu’ubah paléng le',
-'prefixindex' => 'Ban dum ôn ngön haraih away',
-'shortpages' => 'Ôn paneuk',
-'longpages' => 'Ôn panyang',
-'deadendpages' => 'Ôn buntu',
-'protectedpages' => 'Ôn nyang geulindông',
-'listusers' => 'Dapeuta ureuëng nguy',
+'prefixindex' => 'Ban dum laman ngön haraih awai',
+'shortpages' => 'Laman paneuk',
+'longpages' => 'Laman panyang',
+'deadendpages' => 'Laman buntu',
+'protectedpages' => 'Laman nyang geulindông',
+'listusers' => 'Dapeuta ureuëng ngui',
 'usercreated' => '{{GENDER:$3|Geupeugot}} bak $1 poh $2',
-'newpages' => 'Ôn barô',
-'ancientpages' => 'Teunuléh away',
-'move' => 'Peupinah',
-'movethispage' => 'Peupinah ôn nyoë',
+'newpages' => 'Laman barô',
+'newpages-username' => 'Ureuëng ngui:',
+'ancientpages' => 'Laman paléng awai',
+'move' => 'Pupinah',
+'movethispage' => 'Pupinah laman nyoë',
 'pager-newer-n' => '{{PLURAL:$1|1 leubèh barô |$1 leubèh barô}}',
-'pager-older-n' => '{{PLURAL:$1|1 leubèh trép|$1 leubèh trép}}',
+'pager-older-n' => '{{PLURAL:$1|1 leubèh awai|$1 leubèh awai}}',
 
 # Book sources
 'booksources' => 'Nè kitab',
@@ -918,35 +1280,88 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'booksources-go' => 'Mita',
 
 # Special:Log
-'specialloguserlabel' => 'Ureuëng nguy:',
-'speciallogtitlelabel' => 'Nan:',
+'specialloguserlabel' => 'Ureuëng ngui:',
+'speciallogtitlelabel' => 'Sasaran (nan atawa ureuëng ngui):',
 'log' => 'Log',
-'all-logs-page' => 'Ban dum log',
+'all-logs-page' => 'Ban dum log umom',
 
 # Special:AllPages
-'allpages' => 'Dapeuta ôn',
+'allpages' => 'Ban dum laman',
 'alphaindexline' => '$1 u $2',
-'nextpage' => 'Ôn lheuëh nyan ($1)',
-'prevpage' => 'Ôn sigohlomjih ($1)',
-'allpagesfrom' => 'Peuleumah ôn peuphôn nibak:',
-'allpagesto' => 'Peuleumah ôn geupeuakhé bak:',
+'nextpage' => 'Laman lheuëh nyan ($1)',
+'prevpage' => 'Laman sigohlomjih ($1)',
+'allpagesfrom' => 'Peuleumah laman peuphôn nibak:',
+'allpagesto' => 'Peuleumah laman geupeuakhé bak:',
 'allarticles' => 'Dapeuta teunuléh',
+'allpagesprev' => 'U likôt',
+'allpagesnext' => 'U keue',
 'allpagessubmit' => 'Mita',
-'allpagesprefix' => 'Peuleumah ôn ngön harah phôn:',
+'allpagesprefix' => 'Peuleumah laman ngön harah phôn:',
+'allpages-hide-redirects' => 'Peusom peuninah',
 
 # Special:Categories
 'categories' => 'Dapeuta kawan',
+'special-categories-sort-count' => 'atôe meunurôt jumeulah',
+'special-categories-sort-abc' => 'atôe meunurôt seunurat',
+
+# Special:DeletedContributions
+'deletedcontributions' => 'Beuneuri nyang geusampôh',
+'deletedcontributions-title' => 'Beuneuri nyang geusampôh',
+'sp-deletedcontributions-contribs' => 'beuneuri',
 
 # Special:LinkSearch
-'linksearch' => 'Hubông luwa',
+'linksearch' => 'Mita seuneumat luwa',
+'linksearch-pat' => 'Pola mita:',
+'linksearch-ns' => 'Ruweueng nan:',
 'linksearch-ok' => 'Mita',
-'linksearch-line' => '$1 meusambat nibak $2',
+'linksearch-line' => '$1 meupawôt nibak $2',
+
+# Special:ListUsers
+'listusersfrom' => 'Peuleumah ureueng ngui nyang neuawai ngön:',
+'listusers-submit' => 'Peuleumah',
+'listusers-noresult' => 'Hana ureueng ngui nyang meutumèe.',
+'listusers-blocked' => '(geutheun)',
+
+# Special:ActiveUsers
+'activeusers' => 'Dapeuta ureueng ngui udép',
+'activeusers-intro' => 'Nyoe nakeuh dapeuta ureueng ngui nyang na geuandam $1 {{PLURAL:$1|uroe|uroe}} u likôt.',
+'activeusers-count' => '$1 {{PLURAL:$1|buet|buet}} lam {{PLURAL:$3|uroe|$3 uroe}} u likôt',
+'activeusers-from' => 'Peuleumah ureueng ngui nyang neuawai ngön:',
+'activeusers-hidebots' => 'Peusom bot',
+'activeusers-hidesysops' => 'Peusom ureueng urôh',
+'activeusers-noresult' => 'Hana ureueng ngui nyang meutumèe.',
 
 # Special:ListGroupRights
+'listgrouprights' => 'Dapeuta khut ureueng ngui',
+'listgrouprights-key' => 'Teuneurang:
+* <span class="listgrouprights-granted">Khut nyang geubri</span>
+* <span class="listgrouprights-revoked">Khut nyang hana geubri</span>',
+'listgrouprights-group' => 'Kawan',
+'listgrouprights-rights' => 'Khut',
+'listgrouprights-helppage' => 'Beunantu:Khut kawan',
 'listgrouprights-members' => '(dapeuta anggèëta)',
+'listgrouprights-addgroup' => 'Tamah {{PLURAL:$2|kawan|kawan}}: $1',
+'listgrouprights-removegroup' => 'Sampôh {{PLURAL:$2|kawan|kawan}}: $1',
+'listgrouprights-addgroup-all' => 'Tamah ban dum kawan',
+'listgrouprights-removegroup-all' => 'Sampôh ban dum kawan',
 
 # Email user
-'emailuser' => 'Surat-e ureuëng nguy',
+'emailuser' => 'Surat-e ureuëng ngui',
+'emailuser-title-target' => "Peu'ét surat-e keu {{GENDER:$1|ureuëng ngui}} nyoë",
+'emailuser-title-notarget' => "Peu'ét surat-e",
+'emailpage' => "Peu'ét surat-e keu ureuëng ngui",
+'emailusername' => 'Ureueng ngui:',
+'emailusernamesubmit' => 'Kirém',
+'email-legend' => "Kirém surat-e keu ureueng ngui {{SITENAME}} la'én",
+'emailfrom' => 'Ureueng kirém:',
+'emailto' => 'Ureueng teurimöng:',
+'emailsubject' => 'Bhah:',
+'emailmessage' => 'Peusan:',
+'emailsend' => 'Kirém',
+'emailccme' => 'Kubah saboh seunalén surat-e lôn.',
+'emailccsubject' => 'Salén peusan droeneuh keu $1: $2',
+'emailsent' => 'Surat-e meukirém',
+'emailsenttext' => 'Surat-e droeneuh ka meukirém.',
 
 # Watchlist
 'watchlist' => 'Dapeuta keunalön',
@@ -958,7 +1373,7 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'watchthispage' => 'Kalön ôn nyoë',
 'unwatch' => 'Bateuë kalön',
 'watchlist-details' => '{{PLURAL:$1|$1 ôn|$1 ôn}} geukalön, hana kira ôn peugah haba.',
-'wlshowlast' => 'Peuleumah $1 jeum $2 uroë $3 keuneulheuëh',
+'wlshowlast' => 'Peudeuh $1 jeum $2 uroë $3 seuneulheuëh',
 'watchlist-options' => 'Peuniléh dapeuta kalön',
 
 # Displayed when you click the "watch" button and it is in the process of watching
@@ -966,13 +1381,13 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'unwatching' => 'Hana kalön...',
 
 # Delete
-'deletepage' => 'Sampôh ôn',
-'historywarning' => 'Ingat: Ôn nyang hawa neusampôh na riwayat:',
-'confirmdeletetext' => 'Droëneuh neuk neusampôh ôn atawa beureukah nyoë keu sabé. Meunan cit ban mandum riwayatjih nibak basis data. Neupeupaseuti meunyo Droëneuh cit keubiët meung neusampôh, neutupeuë ban mandum akébatjih, ngön peuë nyang neupeulaku nyoë nakeuh meunurôt [[{{MediaWiki:Policy-url}}|kebijakan{{SITENAME}}]].',
+'deletepage' => 'Sampôh laman',
+'historywarning' => "'''Peuneugah:''' Laman nyang keumeung neusampôh na riwayat ngön kureuëng leubèh $1 {{PLURAL:$1|geunantoë}}:",
+'confirmdeletetext' => 'Droëneuh neuk neusampôh laman atawa beureukaih nyoë keu sabé. Meunan cit ban mandum riwayatjih nibak basis data. Neupeupaseuti meunyo Droëneuh cit keubiët meung neusampôh, neutupeuë ban mandum akébatjih, ngön peuë nyang neupeulaku nyoë nakeuh meunurôt [[{{MediaWiki:Policy-url}}|kebijakan{{SITENAME}}]].',
 'actioncomplete' => 'Seuleusoë',
-'actionfailed' => 'Hana meuhase',
-'deletedtext' => '"$1" ka geusampôh. Eu $2 keu log paléng barô bak ôn nyang ka geusampôh.',
-'dellogpage' => 'Log seunampoh',
+'actionfailed' => 'Hana meuhasé',
+'deletedtext' => '"$1" ka geusampôh. Eu $2 keu log paléng barô bak laman nyang ka geusampôh.',
+'dellogpage' => 'Log seunampôh',
 'deletecomment' => 'Choë:',
 'deleteotherreason' => 'Nyang la’én/choë la’én:',
 'deletereasonotherlist' => 'Choë la’én',
@@ -993,12 +1408,14 @@ Teuneurang bak [$2 on teuneurangjih] geupeuleumah di yup nyoe.",
 'protect-locked-access' => "Nan dapeuta Droëneuh hana hak keu jak gantoë tingkat lindông ôn. Nyoë pat nakeuh konfigurasi atra jinoë keu ôn '''$1''':",
 'protect-cascadeon' => 'Ôn nyoë teungöh geulindông kareuna geupeuseureuta lam {{PLURAL:$1|ôn|ôn-ôn}} nyoë nyang ka geulindông ngön peuniléh lindông meuturôt geupeuudép.
 Droëneuh jeuët neugantoë tingkat lindông keu ôn nyoë, tapi nyan hana peungarôh keu lindông meuturôt.',
-'protect-default' => 'Peuidin ban dum ureuëng nguy',
-'protect-fallback' => 'Peureulèë hak peuhah "$1"',
-'protect-level-autoconfirmed' => 'Theun ureuëng nguy barô ngön hana teudapeuta',
-'protect-level-sysop' => 'Ureuëng urôh mantöng',
+'protect-default' => 'Peuidin ban dum ureuëng ngui',
+'protect-fallback' => 'Peuidin ureuëng ngui ngön idin "$1" mantöng',
+'protect-level-autoconfirmed' => 'Peuidin ureuëng ngui nyang teudapeuta keudroë mantöng',
+'protect-level-sysop' => 'Peuidin ureuëng urôh mantöng',
 'protect-summary-cascade' => 'riti',
 'protect-expiring' => 'maté tanggay $1 (UTC)',
+'protect-expiring-local' => 'maté tanggai $1',
+'protect-expiry-indefinite' => 'sabé',
 'protect-cascade' => 'Peulindông ban mandum ôn nyang rôh lam ôn nyoë (lindông meuturôt).',
 'protect-cantedit' => 'Droëneuh h‘an jeuët neu’ubah tingkat lindông ôn nyoë kareuna Droëneuh hana hak keu neupeulaku nyan.',
 'protect-expiry-options' => '1 jeum:1 hour,1 uroë:1 day,1 minggu:1 week,2 minggu:2 weeks,1 buleuën:1 month,3 buleuën:3 months,6 buleuën:6 months,1 thôn:1 year,sabé:infinite',
@@ -1018,51 +1435,51 @@ Droëneuh jeuët neugantoë tingkat lindông keu ôn nyoë, tapi nyan hana peung
 'blanknamespace' => '(Keuë)',
 
 # Contributions
-'contributions' => 'Beuneuri {{GENDER:$1|ureuëng nguy}}',
-'contributions-title' => 'Beuneuri ureuëng nguy keu $1',
+'contributions' => 'Beuneuri {{GENDER:$1|ureuëng ngui}}',
+'contributions-title' => 'Beuneuri ureuëng ngui keu $1',
 'mycontris' => 'Beuneuri',
 'contribsub2' => 'Keu {{GENDER:$3|$1}} ($2)',
 'uctop' => '(jinoë)',
-'month' => 'Yôh buleuën (ngön yôh goh lom nyan)',
-'year' => 'Yôh thôn (ngön yôh goh lom nyan)',
+'month' => 'Mula phôn buleuën (ngön sigohlomjih)',
+'year' => 'Mula phôn thôn (ngön sigohlomjih)',
 
-'sp-contributions-newbies' => 'Keu ureuëng ban dapeuta mantöng',
+'sp-contributions-newbies' => 'Peudeuh beuneuri atra ureuëng ban dapeuta mantöng',
 'sp-contributions-newbies-sub' => 'Keu ureuëng nguy barô',
 'sp-contributions-blocklog' => 'Log peutheun',
 'sp-contributions-uploads' => 'peunasoe',
 'sp-contributions-logs' => 'log',
 'sp-contributions-talk' => 'marit',
 'sp-contributions-search' => 'Mita soë nyang tuléh',
-'sp-contributions-username' => 'Alamat IP atawa nan ureuëng nguy:',
+'sp-contributions-username' => 'Alamat IP atawa nan ureuëng ngui:',
 'sp-contributions-toponly' => 'Peuleumah geunantoe nyang baro mantong',
 'sp-contributions-submit' => 'Mita',
 
 # What links here
-'whatlinkshere' => 'Hubông balék',
-'whatlinkshere-title' => 'Ôn nyang na neuhubông u $1',
-'whatlinkshere-page' => 'Ôn:',
-'linkshere' => "Ôn-ôn nyoë meuhubông u '''[[:$1]]''':",
-'nolinkshere' => "Hana ôn nyang teuhubông u '''[[:$1]]'''.",
-'isredirect' => 'ôn peupinah',
+'whatlinkshere' => 'Peunawôt balék',
+'whatlinkshere-title' => 'Laman nyang mupawôt u $1',
+'whatlinkshere-page' => 'Laman:',
+'linkshere' => "Laman-laman nyoë meupawôt u '''[[:$1]]''':",
+'nolinkshere' => "Hana halaman nyang teukaw'et u '''[[:$1]]'''.",
+'isredirect' => 'laman peuninah',
 'istemplate' => 'ngön seunaleuëk',
-'isimage' => 'hubông beureukaih',
+'isimage' => 'peunawôt beureukaih',
 'whatlinkshere-prev' => '$1 {{PLURAL:$1|sigohlomjih|sigohlomjih}}',
 'whatlinkshere-next' => '$1 {{PLURAL:$1|lheuëh nyan|lheuëh nyan}}',
-'whatlinkshere-links' => '← hubông',
+'whatlinkshere-links' => '← peunawôt',
 'whatlinkshere-hideredirs' => '$1 peuninah',
 'whatlinkshere-hidetrans' => '$1 transklusi',
-'whatlinkshere-hidelinks' => '$1 hubông',
-'whatlinkshere-hideimages' => '$1 hubông beureukaih',
+'whatlinkshere-hidelinks' => '$1 peunawôt',
+'whatlinkshere-hideimages' => '$1 peunawôt beureukaih',
 'whatlinkshere-filters' => 'Saréng',
 
 # Block/unblock
-'blockip' => 'Theun ureuëng nguy',
+'blockip' => 'Theun ureuëng ngui',
 'ipboptions' => '2 jeum:2 hours,1 uroë:1 day,3 uroë:3 days,1 minggu:1 week,2 minggu:2 weeks,1 buleuën:1 month,3 buleuën:3 months,6 buleuën:6 months,1 thôn:1 year,sabé:infinite',
-'ipblocklist' => 'Ureuëng nguy teutheun',
+'ipblocklist' => 'Ureuëng ngui teutheun',
 'ipblocklist-submit' => 'Mita',
 'blocklink' => 'theun',
 'unblocklink' => 'peugadöh theun',
-'change-blocklink' => 'ubah theun',
+'change-blocklink' => 'gantoë theun',
 'contribslink' => 'beuneuri',
 'blocklogpage' => 'Log peutheun',
 'blocklogentry' => 'theun [[$1]] ngön watèë maté tanggay $2 $3',
@@ -1081,10 +1498,10 @@ Nyoë jeuët geupeuakébat neu’ubah nyang h’an neuduga ngön kreuëh ngön b
 *Droëneuh hana neubôh tanda cunténg bak kutak di yup nyoë
 
 Lam masalah nyoë, meunyo neuhawa, Droëneuh jeuët neupeupinah atawa neupeugabông ôn keudroë.",
-'movearticle' => 'Peupinah ôn:',
+'movearticle' => 'Peupinah laman:',
 'newtitle' => 'U nan barô:',
-'move-watch' => 'Kalön ôn nyoë',
-'movepagebtn' => 'Peupinah ôn',
+'move-watch' => 'Kalön laman nyoë',
+'movepagebtn' => 'Peupinah laman',
 'pagemovedsub' => 'Peupinah meuhasé',
 'movepage-moved' => '\'\'\'"$1" ka geupeupinah u "$2".\'\'\'',
 'articleexists' => 'Ôn ngön nan nyan ka na atawa nan nyang neupiléh hana sah. Neupiléh nan la’én.',
@@ -1096,7 +1513,7 @@ Lam masalah nyoë, meunyo neuhawa, Droëneuh jeuët neupeupinah atawa neupeugab
 'revertmove' => 'peuriwang',
 
 # Export
-'export' => 'Èkspor ôn',
+'export' => 'Peuteubiët laman',
 
 # Namespace 8 related
 'allmessages' => 'Peusan sistem',
@@ -1111,65 +1528,69 @@ Lam masalah nyoë, meunyo neuhawa, Droëneuh jeuët neupeupinah atawa neupeugab
 'importlogpage' => 'Log impor',
 
 # Tooltip help for the actions
-'tooltip-pt-userpage' => 'Ôn ureuëng nguy Droëneuh',
-'tooltip-pt-mytalk' => 'Ôn marit Droëneuh',
-'tooltip-pt-preferences' => 'Atô',
-'tooltip-pt-watchlist' => 'Dapeuta ôn nyang lônkalön',
+'tooltip-pt-userpage' => 'Laman ureuëng ngui droëneuh',
+'tooltip-pt-mytalk' => 'Laman marit droëneuh',
+'tooltip-pt-preferences' => 'Geunalak',
+'tooltip-pt-watchlist' => 'Dapeuta laman nyang lônkalön',
 'tooltip-pt-mycontris' => 'Dapeuta beuneuri Droëneuh',
 'tooltip-pt-login' => 'Droëneuh geupadan keu tamong log, bah pih nyan hana geupeuwajéb.',
 'tooltip-pt-logout' => 'Teubiët',
-'tooltip-ca-talk' => 'Marit ôn asoë',
-'tooltip-ca-edit' => 'Droëneuh jeuët neuandam ôn nyoë. Neunguy tumbôy eu dilèë yôh goh neukeubah.',
+'tooltip-ca-talk' => 'Marit laman asoë',
+'tooltip-ca-edit' => 'Droëneuh jeuët neuandam laman nyoë. Neungui tumbôi eu dilèë sigoh neukeubah.',
 'tooltip-ca-addsection' => 'Puphôn beunagi barô',
-'tooltip-ca-viewsource' => 'Ôn nyoë geupeulindông.
-Droëneuh jeuët neu’eu nèjih.',
-'tooltip-ca-history' => 'Seunalén away nibak ôn nyoë',
-'tooltip-ca-protect' => 'Peulindông ôn nyoë',
-'tooltip-ca-delete' => 'Sampôh ôn nyoë',
-'tooltip-ca-move' => 'Peupinah ôn nyoë',
-'tooltip-ca-watch' => 'Peutamah ôn nyoë u dapeuta kalön Droëneuh',
-'tooltip-ca-unwatch' => 'Sampôh ôn nyoë nibak dapeuta keunalön Droëneuh',
+'tooltip-ca-viewsource' => 'Laman nyoë geulindông.
+Droëneuh jeuët neu’eu nèjih mantöng.',
+'tooltip-ca-history' => 'Geunantoë awai nibak laman nyoë',
+'tooltip-ca-protect' => 'Peulindông laman nyoë',
+'tooltip-ca-delete' => 'Sampôh laman nyoë',
+'tooltip-ca-move' => 'Pupinah laman nyoë',
+'tooltip-ca-watch' => 'Tamah laman nyoë u dapeuta kalön droëneuh',
+'tooltip-ca-unwatch' => 'Sampôh laman nyoë nibak dapeuta kalön droëneuh',
 'tooltip-search' => 'Mita {{SITENAME}}',
-'tooltip-search-go' => 'Mita saboh ôn ngon nan nyang peureuséh lagèë nyoë meunyo na',
-'tooltip-search-fulltext' => 'Mita ôn nyang na asoë lagèë nyoë',
+'tooltip-search-go' => 'Mita saboh laman ngon nan nyang peureuséh lagèë nyoë meunyo na',
+'tooltip-search-fulltext' => 'Mita laman nyang na asoë lagèë nyoë',
 'tooltip-p-logo' => 'Saweuë ôn keuë',
-'tooltip-n-mainpage' => 'Jak u ôn keuë',
+'tooltip-n-mainpage' => 'Saweuë ôn keuë',
 'tooltip-n-mainpage-description' => 'Saweuë ôn keuë',
-'tooltip-n-portal' => 'Bhaih buët, peuë nyang jeuët neupeulaku, pat tamita sipeuë hay',
+'tooltip-n-portal' => 'Bhaih buët, peuë nyang jeuët neupubuët, pat keu mita sipeuë hai',
 'tooltip-n-currentevents' => 'Mita haba barô',
-'tooltip-n-recentchanges' => 'Dapeuta neuubah baro lam wiki.',
-'tooltip-n-randompage' => 'Peuleumah ôn beurangkari',
+'tooltip-n-recentchanges' => 'Dapeuta neuubah barô lam wiki.',
+'tooltip-n-randompage' => 'Peudeuih laman baranggari',
 'tooltip-n-help' => 'Bak mita bantu.',
-'tooltip-t-whatlinkshere' => 'Dapeuta ban dum ôn wiki nyang na neuhubông u ôn nyoë',
-'tooltip-t-recentchangeslinked' => 'Neuubah barô ôn nyang na seuneumat u ôn nyoë',
-'tooltip-feed-rss' => 'Umpeuën RSS keu ôn nyoë',
-'tooltip-feed-atom' => 'Umpeuën Atom keu ôn nyoë',
-'tooltip-t-contributions' => 'Eu dapeuta nyang ka geutuléh lé ureuëng nguy nyoë',
-'tooltip-t-emailuser' => "Peu'ét surat-e u ureuëng nguy nyoë",
+'tooltip-t-whatlinkshere' => 'Dapeuta ban dum laman wiki nyang mupawôt keunoë',
+'tooltip-t-recentchangeslinked' => 'Neuubah barô lam laman nyang meupawôt nibak laman nyoë',
+'tooltip-feed-rss' => 'Umpeuën RSS keu laman nyoë',
+'tooltip-feed-atom' => 'Umpeuën Atom keu laman nyoë',
+'tooltip-t-contributions' => 'Dapeuta beuneuri ureuëng ngui nyoë',
+'tooltip-t-emailuser' => "Peu'ét surat-e keu ureuëng ngui nyoë",
 'tooltip-t-upload' => 'Peutamong beureukaih',
-'tooltip-t-specialpages' => 'Dapeuta ban dum ôn kusuih',
-'tooltip-t-print' => 'Seunalén rakam ôn nyoë',
-'tooltip-t-permalink' => 'Hubông teutap keu geunantoë ôn nyoë',
-'tooltip-ca-nstab-main' => 'Eu ôn asoë',
-'tooltip-ca-nstab-user' => 'Eu ôn ureuëng nguy',
-'tooltip-ca-nstab-special' => 'Nyoë nakeuh ôn kusuih nyang h’an jeuët geu’andam.',
-'tooltip-ca-nstab-project' => 'Eu ôn buët',
-'tooltip-ca-nstab-image' => 'Eu ôn beureukaih',
+'tooltip-t-specialpages' => 'Dapeuta ban dum laman kusuih',
+'tooltip-t-print' => 'Seunalén rakam laman nyoë',
+'tooltip-t-permalink' => 'Peunawôt teutap keu geunantoë laman nyoë',
+'tooltip-ca-nstab-main' => 'Eu laman asoë',
+'tooltip-ca-nstab-user' => 'Eu laman ureuëng ngui',
+'tooltip-ca-nstab-special' => 'Nyoë nakeuh laman kusuih nyang h’an jeuët geuandam.',
+'tooltip-ca-nstab-project' => 'Eu laman buët',
+'tooltip-ca-nstab-image' => 'Eu laman beureukaih',
 'tooltip-ca-nstab-template' => 'Eu seunaleuëk',
-'tooltip-ca-nstab-help' => 'Eu ôn beunantu',
-'tooltip-ca-nstab-category' => 'Eu ôn kawan',
+'tooltip-ca-nstab-help' => 'Eu laman beunantu',
+'tooltip-ca-nstab-category' => 'Eu laman kawan',
 'tooltip-minoredit' => 'Bôh tanda keu nyoë sibagoë andam bacut',
 'tooltip-save' => 'Keubah neuubah Droëneuh',
-'tooltip-preview' => 'Peuleumah neuubah Droëneuh, neunguy nyoë sigohlom neukeubah!',
+'tooltip-preview' => 'Peuleumah neuubah Droëneuh, neungui nyoë sigohlom neukeubah!',
 'tooltip-diff' => 'Peuleumah neuubah nyang ka Droëneuh peugöt',
-'tooltip-compareselectedversions' => 'Ngiëng bida antara duwa curak ôn nyang jipilèh.',
-'tooltip-watch' => 'Peutamah ôn nyoë u dapeuta keunalön Droëneuh',
-'tooltip-rollback' => 'Peuriwang neu’andam-neu’andam bak ôn nyoë u nyang tuléh keuneulheuëh lam sigo teugön',
+'tooltip-compareselectedversions' => 'Ngiëng bida nibak duwa geunantoë laman nyang teupiléh',
+'tooltip-watch' => 'Tamah laman nyoë u dapeuta kalön droëneuh',
+'tooltip-rollback' => 'Peuriwang neu’andam-neu’andam bak laman nyoë u nyang tuléh keuneulheuëh lam sigo teugön',
 'tooltip-undo' => 'Peuriwang geunantoë nyoë ngön peuhah plôk neu’andam ngön cara eu dilèë. Choë jeuët geupeutamah bak plôk ehtisa.',
 'tooltip-summary' => 'Pasoë éhtisa paneuk',
+'interlanguage-link-title' => '$1 – $2',
+
+# Info page
+'pageinfo-toolboxlink' => 'Teuneurang laman',
 
 # Browsing diffs
-'previousdiff' => '← Bida away',
+'previousdiff' => '← Bida awai',
 'nextdiff' => 'Geunantoë lheuëh nyan →',
 
 # Media information
@@ -1211,16 +1632,43 @@ Data nyang la'én eunteuk teupeusom keudroë.
 
 # External editor support
 'edit-externally' => 'Andam beureukah nyoë ngön aplikasi luwa',
-'edit-externally-help' => '(Ngiëng [//meta.wikimedia.org/wiki/Help:External_editors arah atô] keu beurita leubèh lanjôt)',
+'edit-externally-help' => '(Ngiëng [//meta.wikimedia.org/wiki/Help:External_editors peurintah atô] keu haba leubèh lanjôt)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ban dum',
 'namespacesall' => 'ban dum',
 'monthsall' => 'ban dum',
 
+# Delete conflict
+'recreate' => 'Peugöt ulang',
+
+# action=purge
+'confirm_purge_button' => 'Ka göt',
+'confirm-purge-top' => 'Sampôh peuniyôh laman nyoë?',
+
+# action=watch/unwatch
+'confirm-watch-button' => 'Ka göt',
+'confirm-watch-top' => 'Tamah laman nyoë u dapeuta keunalön droëneuh?',
+'confirm-unwatch-button' => 'Ka göt',
+'confirm-unwatch-top' => 'Sampôh laman nyoë nibak dapeuta keunalön droëneuh?',
+
+# Multipage image navigation
+'imgmultipageprev' => '← laman sigohlomjih',
+
+# Auto-summaries
+'autosumm-new' => "Geupeugöt laman ngön asoë '$1'",
+
+# Live preview
+'livepreview-loading' => 'Pumasoë...',
+'livepreview-ready' => 'Pumasoë... Ka lheuëh!',
+'livepreview-failed' => 'Peudeuih hasé langsông hana meuhasé!
+Neuci peudeuih hasé biasa.',
+'livepreview-error' => 'H\'an jitém teusambat: $1 "$2"
+Neuci peudeuih hasé biasa.',
+
 # Watchlist editing tools
-'watchlisttools-view' => 'Peuleumah neuubah meuhubông',
-'watchlisttools-edit' => 'Peuleumah ngön andam dapeuta kaeunalön',
+'watchlisttools-view' => "Peudeuh neuubah meukaw'èt",
+'watchlisttools-edit' => 'Peudeuh ngön andam dapeuta keunalön',
 'watchlisttools-raw' => 'Andam dapeuta keunalön meuntah',
 
 # Core parser functions
@@ -1233,21 +1681,52 @@ Data nyang la'én eunteuk teupeusom keudroë.
 'fileduplicatesearch-submit' => 'Mita',
 
 # Special:SpecialPages
-'specialpages' => 'Ôn kusuih',
+'specialpages' => 'Laman kusuih',
+'specialpages-note' => '* Laman kusuih lagèë biasa.
+* <span class="mw-specialpagerestricted">Laman kusuih meuhat.</span>',
+'specialpages-group-maintenance' => 'Beuneuri thèë plara',
+'specialpages-group-other' => "La'én-la'én",
+'specialpages-group-login' => 'Tamöng / dapeuta',
+'specialpages-group-changes' => 'Neuubah barô ngön log',
+'specialpages-group-media' => 'Beuneuri thèë ngön pumasoë beureukaih',
+'specialpages-group-users' => 'Ureuëng ngui ngön khut ureuëng ngui',
+'specialpages-group-highuse' => 'Laman kayém geusaweuë',
+'specialpages-group-pages' => 'Dapeuta laman',
+'specialpages-group-pagetools' => 'Alat laman',
+'specialpages-group-wiki' => 'Data ngön alat',
+'specialpages-group-redirects' => 'Mita ngön pupinah',
+'specialpages-group-spam' => 'Alat spam',
+
+# Special:BlankPage
+'blankpage' => 'Laman soh',
+'intentionallyblankpage' => 'Laman nyoë geusaja peusoh',
 
 # External image whitelist
 'external_image_whitelist' => '#Neupubiyeue bareh nyoe lagee na<pre>
-#Neunguy fragmen-fragmen ekspresi regular (bak bagian antara // mantong) di yup nyoe
-#fragmen-fragmen nyoe eunteuk geupeupaih ngon URL nibak gamba-gamba luwa (nyang geupeuhubong lansong)
+#Neunguy bagian-bagian ekspresi regular (bak bagian antara // mantong) di yup nyoe
+#Bagian-bagian nyoe eunteuk geupupaih ngon URL nibak gamba-gamba luwa (nyang geupeuhubong lansong)
 #Fragmen nyang paih eunteuk geupeuleumah sibagoe gamba, seuhjih keu link mantong
 #Bareh nyang geupuphon ngon # eunteuk geupeujeuet keu bareh beunalah
 #Nyoe hana geupubida haraih rayek ngon ubeut
 #Neupeuduek ban dum beunagi ekspresi biasa di yup bareh nyoe. Neupubiyeue bareh nyoe lagee na</pre>',
 
 # Special:Tags
-'tag-filter' => 'Filter [[Special:Tags|tag]]:',
+'tags' => 'Tag neuubah nyang sah',
+'tag-filter' => 'Saréng [[Special:Tags|tag]]:',
+'tag-filter-submit' => 'Saréng',
 
 # Search suggestions
 'searchsuggest-search' => 'Mita',
 
+# Durations
+'duration-seconds' => '{{PLURAL:$1|deutik}}',
+'duration-minutes' => '{{PLURAL:$1|minèt}}',
+'duration-hours' => '{{PLURAL:$1|jeum}}',
+'duration-days' => '{{PLURAL:$1|uroë}}',
+'duration-weeks' => "{{PLURAL:$1|jeumeu'at}}",
+'duration-years' => '{{PLURAL:$1|thôn}}',
+'duration-decades' => '{{PLURAL:$1|dekade}}',
+'duration-centuries' => '{{PLURAL:$1|abad}}',
+'duration-millennia' => '{{PLURAL:$1|milenium}}',
+
 );
index b777cdb..b91ec0b 100644 (file)
@@ -272,8 +272,6 @@ $1',
 'ok' => 'ok',
 'retrievedfrom' => 'تم الاسترجاع من "$1"',
 'youhavenewmessages' => 'توجد لديك $1 ($2).',
-'newmessageslink' => 'رسائل جديدة',
-'newmessagesdifflink' => 'آخر تغيير',
 'youhavenewmessagesmulti' => 'لديك رسائل جديدة على $1',
 'editsection' => 'modifi el page (baddelha)',
 'editold' => 'modifi el page (baddelha)',
@@ -1324,7 +1322,7 @@ $1",
 
 # External editor support
 'edit-externally' => 'عدل هذا الملف باستخدام تطبيق خارجي',
-'edit-externally-help' => '(انظر [//www.mediawiki.org/wiki/Manual:External_editors تعليمات الإعداد] لمزيد من المعلومات)',
+'edit-externally-help' => '(انظر [https://www.mediawiki.org/wiki/Manual:External_editors تعليمات الإعداد] لمزيد من المعلومات)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'الكل',
index 1443309..b4b8fa4 100644 (file)
@@ -118,7 +118,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'OuBladsye' ),
        'Blankpage'                 => array( 'SkoonBladsy' ),
        'Block'                     => array( 'BlokIP' ),
-       'Blockme'                   => array( 'BlokMy' ),
        'Booksources'               => array( 'Boekbronne' ),
        'BrokenRedirects'           => array( 'Stukkende_aansture', 'Stukkendeaansture' ),
        'Categories'                => array( 'Kategorieë' ),
@@ -128,7 +127,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'SkepRekening', 'MaakGebruiker' ),
        'Deadendpages'              => array( 'DoodloopBladsye' ),
        'DeletedContributions'      => array( 'GeskrapteBydraes' ),
-       'Disambiguations'           => array( 'Dubbelsinnig' ),
        'DoubleRedirects'           => array( 'Dubbele_aansture', 'Dubbeleaansture' ),
        'Emailuser'                 => array( 'Stuur_e-pos', 'Stuure-pos', 'Stuur_epos', 'Stuurepos' ),
        'Export'                    => array( 'Eksporteer' ),
@@ -483,8 +481,6 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Ontsluit van "$1"',
 'youhavenewmessages' => 'U het $1 (sien $2).',
-'newmessageslink' => 'nuwe boodskappe',
-'newmessagesdifflink' => 'die laaste wysiging',
 'youhavenewmessagesfromusers' => "U het $1 van {{PLURAL:$3|'n ander gebruiker|$3 gebruikers}} ($2).",
 'youhavenewmessagesmanyusers' => 'U het $1 van baie gebruikers ($2).',
 'newmessageslinkplural' => "{{PLURAL:$1|'n nuwe boodskap|nuwe boodskappe}}",
@@ -1329,8 +1325,6 @@ U kan ook 'n naamruimte as voorvoegsel gebruik.",
 'preferences' => 'Voorkeure',
 'mypreferences' => 'Voorkeure',
 'prefs-edits' => 'Aantal wysigings:',
-'prefsnologin' => 'Nie ingeteken nie',
-'prefsnologintext' => 'U moet <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aanmeld]</span> om voorkeure te kan verander.',
 'changepassword' => 'Verander wagwoord',
 'prefs-skin' => 'Omslag',
 'skin-preview' => 'Voorskou',
@@ -1625,6 +1619,7 @@ As u dit verskaf, sal dit gebruik word om erkenning vir u werk te gee.',
 'recentchanges-label-minor' => "Hierdie is 'n klein wysiging",
 'recentchanges-label-bot' => "Hierdie wysiging was deur 'n bot uitgevoer",
 'recentchanges-label-unpatrolled' => 'Die wysiging is nog nie gekontroleer nie',
+'recentchanges-legend-newpage' => '$1 - nuwe bladsy',
 'rcnote' => "Hier volg die laaste {{PLURAL:$1|'''$1''' wysiging|'''$1''' wysigings}} gedurende die afgelope {{PLURAL:$2|dag|'''$2''' dae}}, soos vanaf $4 om $5.",
 'rcnotefrom' => "Hier volg wysigings sedert '''$2''' (maksimum van '''$1''' word gewys).",
 'rclistfrom' => 'Vertoon wysigings vanaf $1',
@@ -2876,7 +2871,7 @@ In die laaste geval kan u ook \'n verwysing gebruik, byvoorbeeld [[{{#Special:Ex
 'allmessagesdefault' => 'Verstekteks',
 'allmessagescurrent' => 'Huidige teks',
 'allmessagestext' => "Hier is 'n lys boodskappe wat in die ''MediaWiki''-naamruimte teenwoordig is.
-Gaan na [//www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] as u wil help om MediaWiki te vertaal.",
+Gaan na [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] as u wil help om MediaWiki te vertaal.",
 'allmessagesnotsupportedDB' => "Daar is geen ondersteuning vir '''{{ns:special}}:Allmessages''' omdat '''\$wgUseDatabaseMessages''' uitgeskakel is.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filtreer op staat van verandering:',
@@ -3042,6 +3037,7 @@ Die lêer is slegs gedeeltelik opgelaai.',
 U kan daar \'n wysigingsopsomming byvoeg.',
 'tooltip-preferences-save' => 'Stoor voorkeure',
 'tooltip-summary' => "Verskaf 'n kort opsomming",
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/** Gemeenskaplike CSS vir alle omslae */',
@@ -3070,6 +3066,8 @@ Hierdie situasie was waarskynlik deur 'n skakel na 'n eksterne webtuiste op ons
 'spam_reverting' => 'Besig met terugrol na die laaste weergawe wat nie skakels na $1 bevat nie',
 'spam_blanking' => "Alle weergawes met 'n skakel na $1 word verwyder",
 'spam_deleting' => 'Alle weergawes bevat verwysings na $1. Bladsy verwyder',
+'simpleantispam-label' => "Anti-spam kontrole.
+'''Moenie''' die veld invul nie!",
 
 # Info page
 'pageinfo-title' => 'Inligting oor "$1"',
@@ -3633,7 +3631,7 @@ Ander velde sal versteek wees.
 
 # External editor support
 'edit-externally' => "Wysig hierdie lêer met 'n eksterne program",
-'edit-externally-help' => '(Sien [//www.mediawiki.org/wiki/Manual:External_editors instruksies] vir meer inligting)',
+'edit-externally-help' => '(Sien [https://www.mediawiki.org/wiki/Manual:External_editors instruksies] vir meer inligting)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alles',
@@ -3820,7 +3818,7 @@ U kan ook die [[Special:EditWatchlist|standaard opdaterigskerm gebruik]].',
 'version-hook-subscribedby' => 'Gebruik deur',
 'version-version' => '(Weergawe $1)',
 'version-license' => 'Lisensie',
-'version-poweredby-credits' => "Hierdie wiki word aangedryf deur '''[//www.mediawiki.org/ MediaWiki]''', kopiereg © 2001-$1 $2.",
+'version-poweredby-credits' => "Hierdie wiki word aangedryf deur '''[https://www.mediawiki.org/ MediaWiki]''', kopiereg © 2001-$1 $2.",
 'version-poweredby-others' => 'andere',
 'version-poweredby-translators' => 'translatewiki.net-vertalers',
 'version-credits-summary' => 'Ons erken graag die volgende persone vir hul bydrae aan [[Special:Version|MediaWiki]].',
@@ -3861,8 +3859,7 @@ Saam met die program moes u \'n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van van
 
 # Special:SpecialPages
 'specialpages' => 'Spesiale bladsye',
-'specialpages-note' => '----
-* Normale spesiale bladsye.
+'specialpages-note' => '* Normale spesiale bladsye.
 * <span class="mw-specialpagerestricted">Spesiale bladsye met beperkte toegang.</span>
 * <span class="mw-specialpagecached">Spesiale bladsye met gegewens uit die kas (kan verouderd wees).</span>',
 'specialpages-group-maintenance' => 'Onderhoud verslae',
@@ -4075,4 +4072,21 @@ Anders kan u die eenvoudige vorm hieronder gebruik. U kommentaar sal by die blad
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|greep|grepe}}',
 'limitreport-expansiondepth' => 'Hoogste uitbreidingsdiepte',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Brei sjablone uit',
+'expand_templates_intro' => 'Hierdie spesiale bladsy lees die invoerteks en vervang al die sjablone rekursief.
+Dit vervang ook ontlederfunksies soos
+<nowiki>{{</nowiki>#language:…}}, en veranderlikes soos
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash; omtrent alles tussen dubbele krulhakkies word vervang.
+Dit word gedoen deur die relevante funksies in die MediaWiki-ontleder te roep.',
+'expand_templates_title' => 'Kontekstitel, vir {{FULLPAGENAME}}, ensovoorts:',
+'expand_templates_input' => 'Invoerteks:',
+'expand_templates_output' => 'Resultaat',
+'expand_templates_xml_output' => 'XML-afvoer',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Verwyder kommentaar',
+'expand_templates_remove_nowiki' => 'Onderdruk <nowiki> etikette in die resultaat',
+'expand_templates_generate_xml' => 'Wys XML-ontledingsboom',
+'expand_templates_preview' => 'Voorskou',
+
 );
index bb3265b..dcf2c47 100644 (file)
  */
 
 $namespaceNames = array(
-       NS_MEDIA            => 'Medya',
-       NS_SPECIAL          => 'Spesial',
-       NS_TALK             => 'Nkɔmbɔ',
-       NS_USER             => 'User',
-       NS_USER_TALK        => 'User_nkɔmbɔ',
-       NS_PROJECT_TALK     => '$1_nkɔmbɔ',
-       NS_FILE             => 'Fayl',
-       NS_FILE_TALK        => 'Fayl_nkɔmbɔ',
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Soronko',
+       NS_TALK             => 'Nkɔmmɔ',
+       NS_USER             => 'Odwumanyɛni',
+       NS_USER_TALK        => 'Odwumanyɛni_nkɔmmɔbea',
+       NS_PROJECT_TALK     => '$1_nkɔmmɔ',
+       NS_FILE             => 'File',
+       NS_FILE_TALK        => 'File_nkɔmmɔ',
        NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'MediaWiki_nkɔmbɔ',
-       NS_TEMPLATE         => 'Şablon',
-       NS_TEMPLATE_TALK    => 'Şablon_nkɔmbɔ',
-       NS_HELP             => 'Help',
-       NS_HELP_TALK        => 'Help_nkɔmbɔ',
-       NS_CATEGORY         => 'Kategori',
-       NS_CATEGORY_TALK    => 'Kategori_nkɔmbɔ',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_nkɔmmɔ',
+       NS_TEMPLATE         => 'Nhwɛsode',
+       NS_TEMPLATE_TALK    => 'Nhwɛsode_nkɔmmɔbea',
+       NS_HELP             => 'Boa',
+       NS_HELP_TALK        => 'Mmoa_nkɔmmɔbea',
+       NS_CATEGORY         => 'Nkyekyem',
+       NS_CATEGORY_TALK    => 'Nkyekyem_nkɔmmɔbea',
 );
 
 $messages = array(
index c5c19e2..51cf9d5 100644 (file)
@@ -320,8 +320,6 @@ Shih [[Special:Version|faqen e verzionit]].',
 'ok' => 'OK',
 'retrievedfrom' => 'Marrë nga "$1"',
 'youhavenewmessages' => 'Keni $1 ($2).',
-'newmessageslink' => 'mesazhe të reja',
-'newmessagesdifflink' => 'ndryshimi i fundit',
 'youhavenewmessagesmulti' => 'Keni mesazhe të reja në $1',
 'editsection' => 'redakto',
 'editold' => 'redakto',
@@ -936,8 +934,6 @@ Vini re se indeksat e tyne të përmbajtjes së {{SITENAME}} munden me qenë të
 'preferences' => 'Parapëlqimet',
 'mypreferences' => 'Parapëlqimet e mija',
 'prefs-edits' => 'Numri i redaktimeve:',
-'prefsnologin' => 'Nuk jeni kyçë',
-'prefsnologintext' => 'Duheni me qenë <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} i kyçun]</span> për me i caktue parapëlqimet.',
 'changepassword' => 'Ndërrimi i fjalëkalimit',
 'prefs-skin' => 'Doka',
 'skin-preview' => 'Parapâmja',
@@ -1504,6 +1500,9 @@ Lejon dhânien e arsyes në përmbledhje.',
 'siteusers' => '{{SITENAME}} {{PLURAL:$2|përdorues|përdorues}} $1',
 'creditspage' => 'Kreditat e faqes',
 
+# Spam protection
+'simpleantispam-label' => "Anti-spam kontrolloni. A'''''NUK' plotësoni këtë!",
+
 # Browsing diffs
 'previousdiff' => '← Redaktim mâ i vjetër',
 'nextdiff' => 'Redaktim ma i ri →',
@@ -1555,7 +1554,7 @@ Tjerat kanë me mbetë të mshefuna.
 
 # External editor support
 'edit-externally' => 'Ndryshoni kët figurë/skedë me një mjet të jashtëm',
-'edit-externally-help' => '(Shih [//www.mediawiki.org/wiki/Manual:External_editors udhëzimet e instalimit] për mâ shumë informata)',
+'edit-externally-help' => '(Shih [https://www.mediawiki.org/wiki/Manual:External_editors udhëzimet e instalimit] për mâ shumë informata)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'krejt',
index da80c4f..de58608 100644 (file)
@@ -294,8 +294,6 @@ $1',
 'ok' => 'እሺ',
 'retrievedfrom' => 'ከ «$1» የተወሰደ',
 'youhavenewmessages' => '$1 አሉዎት ($2)።',
-'newmessageslink' => 'አዲስ መልእክቶች',
-'newmessagesdifflink' => 'የመጨረሻ ለውጥ',
 'youhavenewmessagesfromusers' => 'ከ{{PLURAL:$3|ሌላ አባል|$3 አባላት}} $1 {{PLURAL:$1|አለዎት|አሉልዎ}}። ($2).',
 'youhavenewmessagesmanyusers' => 'ከአሥር አባላት በላይ $1 አሉልዎ! ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|፩ አዲስ መልዕክት|አዲስ መልእክቶች}}',
@@ -864,8 +862,6 @@ $1ን ወይም ማንም ሌላ [[{{MediaWiki:Grouppage-sysop}}|መጋቢ]] ስ
 'preferences' => 'ምርጫዎች፤',
 'mypreferences' => 'ምርጫዎች፤',
 'prefs-edits' => 'የለውጦች ቁጥር:',
-'prefsnologin' => 'ገና አልገቡም',
-'prefsnologintext' => 'ምርጫዎችዎን ለማስተካከል አስቀድሞ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} መግባት]</span>  ያስፈልግዎታል።',
 'changepassword' => 'መግቢያ ቃልዎን ለመቀየር',
 'prefs-skin' => 'የድህረ-ገጽ መልክ',
 'skin-preview' => 'ቅድመ-ዕይታ',
@@ -1072,6 +1068,7 @@ $1ን ወይም ማንም ሌላ [[{{MediaWiki:Grouppage-sysop}}|መጋቢ]] ስ
 'recentchanges-label-minor' => 'ይህ ለውጥ ጥቃቅን ነው።',
 'recentchanges-label-bot' => 'ይኸው ለውጥ በሎሌ ተደረገ።',
 'recentchanges-label-unpatrolled' => 'ይህ እርማት ገና አልተገመገመም',
+'recentchanges-legend-newpage' => '$1 - አዲስ ገጽ',
 'rcnote' => "ከ$5 $4 እ.ኤ.አ. {{PLURAL:$2|ባለፈው 1 ቀን|ባለፉት '''$2''' ቀኖች}} {{PLURAL:$1|የተደረገው '''1''' ለውጥ እታች ይገኛል|የተደረጉት '''$1''' መጨረሻ ለውጦች እታች ይገኛሉ}}።",
 'rcnotefrom' => "ከ'''$2''' ጀምሮ የተቀየሩት ገጾች (እስከ '''$1''' ድረስ) ክዚህ በታች ይታያሉ።",
 'rclistfrom' => '(ከ $1 ጀምሮ አዲስ ለውጦቹን ለማየት)',
@@ -1945,7 +1942,7 @@ $1',
 'allmessagesdefault' => 'የቆየው ጽሕፈት',
 'allmessagescurrent' => 'ያሁኑ ጽሕፈት',
 'allmessagestext' => 'በ«MediaWiki» ክፍለ-ዊኪ ያሉት የድረገጽ መልክ መልእክቶች ሙሉ ዝርዝር ይህ ነው።
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' ስለ ተዘጋ '''{{ns:special}}:Allmessages''' ሊጠቀም አይችልም።",
 'allmessages-filter-legend' => 'ማጣሪያ',
 'allmessages-filter-all' => 'ሁሉ',
@@ -2397,7 +2394,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ይህንን ፋይል በአፍአዊ ሶፍትዌር ለማዘጋጀት',
-'edit-externally-help' => '(ለተጨማሪ መረጃ ይህን ገፅ ተመልከቱ [//www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
+'edit-externally-help' => '(ለተጨማሪ መረጃ ይህን ገፅ ተመልከቱ [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ሁሉ',
@@ -2601,4 +2598,7 @@ $3
 'api-error-uploaddisabled' => 'ፋይል መላክ በዚህ ውኪ ላይ አልተፈቀደም።',
 'api-error-verification-error' => 'ይህ ፋይል የተበላሸ ወይም ትክክል ያልሆነ ቅጥያ ያለው ሊሆን ይችላል።',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'እሺ',
+
 );
index c180c9f..9883a46 100644 (file)
@@ -64,7 +64,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Todas_as_pachinas' ),
        'Ancientpages'              => array( 'Pachinas_mas_viellas', 'Pachinas_mas_antigas', 'Pachinas_más_biellas', 'Pachinas_biellas', 'Pachinas_antigas' ),
        'Block'                     => array( 'Bloqueyar' ),
-       'Blockme'                   => array( 'Bloqueya-me' ),
        'Booksources'               => array( 'Fuents_de_libros' ),
        'BrokenRedirects'           => array( 'Endreceras_trencatas', 'Endreceras_trencadas', 'Reendrezeras_trencatas', 'Endrezeras_trencatas', 'Reendrezeras_crebatas', 'Endrezeras_crebatas', 'Endrezeras_trencadas', 'Endrezeras_crebadas' ),
        'Categories'                => array( 'Categorías' ),
@@ -73,7 +72,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Contrebucions', 'Contrebuzions' ),
        'CreateAccount'             => array( 'Creyar_cuenta' ),
        'Deadendpages'              => array( 'Pachinas_sin_salida', 'Pachinas_sin_de_salida' ),
-       'Disambiguations'           => array( 'Desambigacions', 'Desambigazions', 'Pachinas_de_desambigazión' ),
        'DoubleRedirects'           => array( 'Endreceras_doples', 'Reendrezeras_dobles', 'Dobles_reendrezeras', 'Endrezeras_dobles', 'Dobles_endrezeras' ),
        'Emailuser'                 => array( 'Ninvía_mensache', 'Nimbía_mensache' ),
        'Export'                    => array( 'Exportar' ),
@@ -390,8 +388,6 @@ $1",
 'pagetitle' => '$1 - {{SITENAME}}',
 'retrievedfrom' => 'Obtenito de "$1"',
 'youhavenewmessages' => 'Tiene $1 ($2).',
-'newmessageslink' => 'mensaches nuevos',
-'newmessagesdifflink' => 'Esferencias con a versión anterior',
 'youhavenewmessagesmulti' => 'Tiene nuevos mensaches en $1',
 'editsection' => 'editar',
 'editold' => 'editar',
@@ -1087,8 +1083,6 @@ Asegure-se que iste cambio no trencará a continidat de l'historial d'a pachina.
 'preferences' => 'Preferencias',
 'mypreferences' => 'Preferencias',
 'prefs-edits' => "Numero d'edicions:",
-'prefsnologin' => 'No ye identificato',
-'prefsnologintext' => 'Ha d\'haber <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} encetato una sesión] </span> ta cambiar as preferencias d\'usuario.',
 'changepassword' => 'Cambiar a clau',
 'prefs-skin' => 'Aparencia',
 'skin-preview' => 'Fer una prebatina',
@@ -1361,6 +1355,7 @@ Habría de tener menos de $1 {{PLURAL:$1|carácter|carácters}}.',
 'recentchanges-label-minor' => 'Ista ye una edición menor',
 'recentchanges-label-bot' => 'Ista edición fue feita por un bot',
 'recentchanges-label-unpatrolled' => "Esta edición encara no s'ha controlato",
+'recentchanges-legend-newpage' => '$1 - pachina nueva',
 'rcnote' => "Contino {{PLURAL:$1|s'amuestra o unico cambeo feito|s'amuestran os zaguers '''$1''' cambeos feitos}} en {{PLURAL:$2|o zaguer día|os zaguers '''$2''' días}}, dica o $5, $4.",
 'rcnotefrom' => "Contino s'amuestran os cambeos dende '''$2''' (dica '''$1''').",
 'rclistfrom' => 'Amostrar cambeos recients dende $1',
@@ -2515,7 +2510,7 @@ En iste zaguer caso tamién puede usar un vinclo, por eixemplo [[{{#Special:Expo
 'allmessagesdefault' => 'texto por defecto',
 'allmessagescurrent' => 'texto actual',
 'allmessagestext' => "Ista ye una lista de totz os mensaches disponibles en o espacio de nombres MediaWiki.
-Vesite por favor [//www.mediawiki.org/wiki/Localisation a pachina sobre localización de MediaWiki] y  [//translatewiki.net translatewiki.net] si deseya contrebuyir t'a localización cheneral de MediaWiki.",
+Vesite por favor [https://www.mediawiki.org/wiki/Localisation a pachina sobre localización de MediaWiki] y  [//translatewiki.net translatewiki.net] si deseya contrebuyir t'a localización cheneral de MediaWiki.",
 'allmessagesnotsupportedDB' => 'Ista pachina no ye disponible porque wgUseDatabaseMessages ye desactivato.',
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar por estau de personalización:',
@@ -2718,6 +2713,8 @@ Puede veyer-ne, manimenos, o codigo fuent.',
 'spambot_username' => 'Esporga de spam de MediaWiki',
 'spam_reverting' => "Tornando t'a zaguera versión sin de vinclos ta $1",
 'spam_blanking' => 'Todas as versions teneban vinclos ta $1, se deixa en blanco',
+'simpleantispam-label' => "Preba anti-spam.
+'''NO''' replene esto!",
 
 # Info page
 'pageinfo-title' => 'Información ta «$1»',
@@ -3221,7 +3218,7 @@ Os campos de metadatos d'a imachen que amaneixen en iste mensache s'amostrarán
 
 # External editor support
 'edit-externally' => 'Editar iste fichero fendo servir una aplicación externa',
-'edit-externally-help' => '(Ta más información, leiga as [//www.mediawiki.org/wiki/Manual:External_editors instruccions de configuración])',
+'edit-externally-help' => '(Ta más información, leiga as [https://www.mediawiki.org/wiki/Manual:External_editors instruccions de configuración])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'totz',
@@ -3398,7 +3395,7 @@ Tamién puede fer servir o [[Special:EditWatchlist|editor estándar]].",
 'version-hook-subscribedby' => 'Suscrito por',
 'version-version' => '(Versión $1)',
 'version-license' => 'Licencia',
-'version-poweredby-credits' => "Iste wiki funciona gracias a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Iste wiki funciona gracias a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'atros',
 'version-license-info' => "MediaWiki ye software libre, puet redistribuyir-lo y/u modificar-lo baixo os terminos d'a Licencia Publica Cheneral GNU publicada por a Free Software Foundation, ya siga d'a suya versión 2 u (a la suya esleción) qualsiquier versión posterior. 
 
@@ -3422,8 +3419,7 @@ Con iste programa ha d'haber recibiu [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia
 
 # Special:SpecialPages
 'specialpages' => 'Pachinas especials',
-'specialpages-note' => '----
-* Pachinas especials normals.
+'specialpages-note' => '* Pachinas especials normals.
 * <strong class="mw-specialpagerestricted">Pachinas especials restrinchitas.</strong>',
 'specialpages-group-maintenance' => 'Informes de mantenimiento',
 'specialpages-group-other' => 'Atras pachinas especials',
@@ -3594,4 +3590,17 @@ Si no, puet usar o siguient formulario. O suyo comentario será adhibiu a la pac
 'api-error-uploaddisabled' => 'As cargas de fichers son desactivadas en iste wiki.',
 'api-error-verification-error' => 'Iste fichero puede estar danyau, u tiene una extensión incorrecta.',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espandir plantillas',
+'expand_templates_intro' => 'Ista pachina especial prene bel testo y espande recursivament todas as plantillas que bi ha en el. Tamién espande as funcions parser como <nowiki>{{</nowiki>#language:...}}, y as variables como <nowiki>{{</nowiki>CURRENTDAY}}&mdash; en cheneral tot o que sía entre dobles claus.
+Isto lo fa clamando ta o parser correspondient dende o propio MediaWiki.',
+'expand_templates_title' => 'Títol ta contestualizar ({{FULLPAGENAME}} etz.):',
+'expand_templates_input' => 'Testo ta espandir:',
+'expand_templates_output' => 'Resultau',
+'expand_templates_xml_output' => 'salida XML',
+'expand_templates_ok' => 'Confirmar',
+'expand_templates_remove_comments' => 'Sacar comentarios',
+'expand_templates_generate_xml' => "Amostrar l'árbol de parseyo XML",
+'expand_templates_preview' => 'Previsualización',
+
 );
index c2bc374..5cb5acd 100644 (file)
@@ -11,7 +11,9 @@
  * @author Espreon
  * @author Gott wisst
  * @author JJohnson
+ * @author JJohnson1701
  * @author Omnipaedista
+ * @author Shirayuki
  * @author Spacebirdy
  * @author Tsepelcory
  * @author Wōdenhelm
 
 $namespaceNames = array(
        NS_SPECIAL          => 'Syndrig',
-       NS_TALK             => 'Gesprec',
+       NS_TALK             => 'Mōtung',
        NS_FILE             => 'Biliþ',
-       NS_FILE_TALK        => 'Biliþgesprec',
+       NS_FILE_TALK        => 'Biliþmōtung',
        NS_TEMPLATE         => 'Bysen',
-       NS_TEMPLATE_TALK    => 'Bysengesprec',
+       NS_TEMPLATE_TALK    => 'Bysenmōtung',
        NS_HELP             => 'Help',
-       NS_HELP_TALK        => 'Helpgesprec',
+       NS_HELP_TALK        => 'Helpmōtung',
        NS_CATEGORY         => 'Flocc',
-       NS_CATEGORY_TALK    => 'Floccgesprec',
+       NS_CATEGORY_TALK    => 'Floccmōtung',
+);
+
+$namespaceAliases = array(
+       'Gesprec'      => NS_TALK,
+       'Biliþgesprec' => NS_FILE_TALK,
+       'Bysengesprec' => NS_TEMPLATE_TALK,
+       'Helpgesprec'  => NS_HELP_TALK,
+       'Floccgesprec' => NS_CATEGORY_TALK,
 );
 
 $messages = array(
@@ -236,7 +246,7 @@ $messages = array(
 'protect' => 'Beorgan',
 'protect_change' => 'Wendan',
 'protectthispage' => 'Beorgan þisne tramet',
-'unprotect' => 'Andwendan beorgunge',
+'unprotect' => 'Wendan beorgunge',
 'unprotectthispage' => 'Andwendan beorgune þisses trametes',
 'newpage' => 'Nīwe tramet',
 'talkpage' => 'Sprecan ymbe þisne tramet',
@@ -302,8 +312,6 @@ Seoh þone [[Special:Version|fadunge tramet]].',
 'ok' => 'Gōd lā',
 'retrievedfrom' => 'Fram "$1" begeten',
 'youhavenewmessages' => 'Þū hæfst $1 ($2).',
-'newmessageslink' => 'nīwu ǣrendgewritu',
-'newmessagesdifflink' => 'nīwost andwendung',
 'youhavenewmessagesfromusers' => 'Þū hafast $1 fram {{PLURAL:$3|ōðrum brūcende|$3 brūcenda}} ($2).',
 'youhavenewmessagesmanyusers' => 'Þū hafast $1 fram manigum brūcendum ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|nīwe ǣrendgewrit|nīwra ǣrendgewrita}}',
@@ -328,6 +336,8 @@ Seoh þone [[Special:Version|fadunge tramet]].',
 'page-rss-feed' => '$1 RSS strēam',
 'page-atom-feed' => '$1 Atom strēam',
 'red-link-title' => '$1 (tramet ne biþ)',
+'sort-descending' => 'sīgende behweorfan',
+'sort-ascending' => 'stīgende behweorfan',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Tramet',
@@ -367,11 +377,13 @@ Getæl gengra syndrigra trameta cann man findan be [[Special:SpecialPages|þǣm
 'badarticleerror' => 'Þēos dǣd ne cann bēon gefremed on þissum tramete.',
 'badtitle' => 'Nā genge titul',
 'viewsource' => 'Sēon fruman',
+'viewsource-title' => 'Fruman for $1 sēon',
 'cascadeprotected' => 'Þes trament wæs geborgen wiþ adihtunge, for þǣm þe hē is befangen in þissum {{PLURAL:$1|tramente, þe is| tramentum, þe sind}} geborgen settum wyrcende þǣm cyre "cascading": $2',
+'exception-nologin' => 'Ne inloggod',
 
 # Virus scanner
-'virus-badscanner' => '',
-'virus-unknownscanner' => '',
+'virus-badscanner' => 'Bad configuration: Unknown virus scanner: $1',
+'virus-unknownscanner' => 'uncūþ andgund:',
 
 # Login and logout pages
 'logouttext' => "'''Þū eart nū ūtmeldod.'''
@@ -382,6 +394,7 @@ Cnāw þæt sume trametas mihten gīet wesan geīwde swā þū wǣre gīet inmel
 'yourname' => 'Þīn brūcendnama:',
 'userlogin-yourname' => 'Brūcendnama:',
 'userlogin-yourname-ph' => 'Inwrīt þīnne brūcendnaman',
+'createacct-another-username-ph' => 'Wrīt þone brūcendnaman in',
 'yourpassword' => 'Þafungword:',
 'userlogin-yourpassword' => 'Þafungword',
 'userlogin-yourpassword-ph' => 'Inwrīt þīn þafungword',
@@ -401,13 +414,15 @@ Cnāw þæt sume trametas mihten gīet wesan geīwde swā þū wǣre gīet inmel
 'logout' => 'Ūtmeldian',
 'userlogout' => 'Ūtmeldian',
 'notloggedin' => 'Nā ingemeldod',
-'userlogin-noaccount' => '',
-'userlogin-joinproject' => '',
+'userlogin-noaccount' => 'Næfst þu hordcleofan?',
+'userlogin-joinproject' => 'Join {{SITENAME}}',
 'nologin' => 'Næfst þū reccinge? $1',
 'nologinlink' => 'Scieppan reccinge',
 'createaccount' => 'Scieppan reccinge',
 'gotaccount' => 'Hafast þū reccinge ǣr? $1.',
 'gotaccountlink' => 'Inmeldian',
+'userlogin-resetpassword-link' => 'Forgēate þū þīn gelēafword?',
+'helplogin-url' => 'Help:Inmeldung',
 'createaccountmail' => 'Notian sceortne tīman hlētlic þafungword and sendan hit to þǣm spearcǣrenda naman þe is niðer',
 'createaccountreason' => 'Racu:',
 'badretype' => 'Þā þafungword þe write þū, bēoþ ungelīc.',
@@ -426,7 +441,7 @@ Scēawa þīne wrītunge eft, oþþe [[Special:UserLogin/signup|sciepp nīwe rec
 'nosuchusershort' => 'Þǣr nis nān brūcend mid þǣm naman "$1".  Scēawa þīne wrītunge.',
 'passwordtooshort' => 'Þafungword sculon habban læst {{PLURAL:$1|1 stafan|$1 stafena}}.',
 'mailmypassword' => 'Sendan nīwe þafungword on spearcǣrende',
-'acct_creation_throttle_hit' => 'Hwæt, þu hæfst gēo geseted {{PLURAL:$1|1 hordcleofan|$1 -}}. Þu ne canst settan ǣnige māran.',
+'acct_creation_throttle_hit' => 'Nēosiende tō þissum wici, þe þīnne IP-Stōwe brȳcþ, hæfþ gesett {{PLURAL:$1|1 hordcleofan|$1 hordcleofan}} in þǣm læsten dæge. Þu ne canst settan ǣnige māran. Þǣrfram ne cunnon Nēosiende, þe þisne IP-Stōwe brȳcþ, settan ǣnige hordcleofan māran on þisse handhwīle.',
 'accountcreated' => 'Scōp reccinge',
 'loginlanguagelabel' => 'Sprǣc: $1',
 
@@ -438,6 +453,9 @@ Scēawa þīne wrītunge eft, oþþe [[Special:UserLogin/signup|sciepp nīwe rec
 'resetpass-submit-loggedin' => 'Andwendan þafungword',
 'resetpass-submit-cancel' => 'Undōn',
 
+# Special:PasswordReset
+'passwordreset-username' => 'Brūcendnama:',
+
 # Edit page toolbar
 'bold_sample' => 'Þicce traht',
 'bold_tip' => 'Þicce traht',
@@ -548,8 +566,8 @@ folclicum āgnunge oþþe gelīcum frēom horde (sēo $1 for āscungum).
 'revdelete-hide-comment' => 'Hȳdan adihtunge sceortnesse',
 'revdelete-hide-user' => 'Hȳdan adihtendes brūcendnaman/IP address',
 'revdelete-radio-same' => '(nā andwendan)',
-'revdelete-radio-set' => 'Gēa',
-'revdelete-radio-unset' => 'Nese',
+'revdelete-radio-set' => 'Gehȳdd',
+'revdelete-radio-unset' => 'Gesīene',
 'revdel-restore' => 'andwendan īwunge',
 'pagehist' => 'Trametes stǣr',
 'revdelete-reasonotherlist' => 'Ōðru racu',
@@ -608,7 +626,6 @@ folclicum āgnunge oþþe gelīcum frēom horde (sēo $1 for āscungum).
 # Preferences page
 'preferences' => 'Fōreberunga',
 'mypreferences' => 'Mīna fōreberunga',
-'prefsnologin' => 'Nā inmeldod',
 'prefs-skin' => 'Scynn',
 'skin-preview' => 'Fōrebysen',
 'prefs-datetime' => 'Tælmearc and tīd',
@@ -676,6 +693,7 @@ folclicum āgnunge oþþe gelīcum frēom horde (sēo $1 for āscungum).
 'recentchanges-label-newpage' => 'Þēos adihtung scōp nīwne tramet',
 'recentchanges-label-minor' => 'Þēos is lytel adihtung',
 'recentchanges-label-bot' => 'Searuþrǣl fremede þās adihtunge',
+'recentchanges-legend-newpage' => '$1 - nīƿu sīde',
 'rcnote' => "Beneoðan {{PLURAL:$1|is '''1''' andwendung|sind þā æftemestan '''$1''' andwendunga}} in {{PLURAL:$2|þǣm æftermestan dæge|þǣm æftemestum '''$2''' daga}}, fram $5 on $4.",
 'rcnotefrom' => "Niðer sind þā andwendunga fram '''$2''' (mǣst īweþ '''$1''').",
 'rclistfrom' => 'Īwan nīwa andwendunga fram $1 and siþþan',
@@ -907,7 +925,7 @@ Gif se brūcend asifte hine. synderlīce sind ymelan geīwda þǣre þe se brūc
 # Delete
 'deletepage' => 'Forlēosan tramet',
 'excontent' => 'innung wæs: "$1"',
-'excontentauthor' => 'innung wæs: \'$1\' (and se āna forðiend wæs "[[Special:Contributions/$2|$2]")',
+'excontentauthor' => 'innung wæs: \'$1\' (and se āna forðiend wæs "[[Special:Contributions/$2|$2]]")',
 'exblank' => 'tramet wæs æmettig',
 'historywarning' => "'''Warnung''': Se tramet þe þū wilt forlēosan hafaþ stǣr mid nēan $1 {{PLURAL:$1|fadunge|fadunga}}:",
 'actioncomplete' => 'Dǣd  is fulfyled',
@@ -1217,7 +1235,7 @@ Cēos ōðerne naman lā.',
 'exif-gpsdirection-t' => 'Sōþ rihtung',
 
 # External editor support
-'edit-externally-help' => '(Sēon þā [//www.mediawiki.org/wiki/Manual:External_editors gearwunge gewissunga] ymb mā cȳþþe)',
+'edit-externally-help' => '(Sēon þā [https://www.mediawiki.org/wiki/Manual:External_editors gearwunge gewissunga] ymb mā cȳþþe)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'eall',
index 1e82ec5..36905d8 100644 (file)
@@ -23,6 +23,7 @@
  * @author Bassem JARKAS
  * @author Chaos
  * @author Ciphers
+ * @author Claw eg
  * @author DRIHEM
  * @author DrFO.Tn
  * @author Elmondo21st
@@ -244,6 +245,7 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'عنوان_الصفحة_الكامل', 'عنوان_صفحة_كامل', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'اسم_الصفحة_الفرعي', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'عنوان_الصفحة_الفرعي', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'جذر_اسم_الصفحة', 'ROOTPAGENAME' ),
        'basepagename'              => array( '1', 'اسم_الصفحة_الأساسي', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'عنوان_الصفحة_الأساسي', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'اسم_صفحة_النقاش', 'TALKPAGENAME' ),
@@ -263,6 +265,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'مركز', 'center', 'centre' ),
        'img_framed'                => array( '1', 'إطار', 'بإطار', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'لاإطار', 'frameless' ),
+       'img_lang'                  => array( '1', 'لغة=$1', 'lang=$1' ),
        'img_page'                  => array( '1', 'صفحة=$1', 'صفحة_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'معدول', 'معدول=$1', 'معدول_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'حدود', 'border' ),
@@ -305,6 +308,7 @@ $magicWords = array(
        'revisionyear'              => array( '1', 'عام_المراجعة', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', 'طابع_وقت_المراجعة', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'مستخدم_المراجعة', 'REVISIONUSER' ),
+       'revisionsize'              => array( '1', 'حجم_المراجعة', 'REVISIONSIZE' ),
        'plural'                    => array( '0', 'جمع:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'عنوان_كامل:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'مسار_كامل:', 'FULLURLE:' ),
@@ -360,12 +364,12 @@ $magicWords = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'مستخدمون_نشطون' ),
        'Allmessages'               => array( 'كل_الرسائل' ),
+       'AllMyUploads'              => array( 'كل_ملفاتي' ),
        'Allpages'                  => array( 'كل_الصفحات' ),
        'Ancientpages'              => array( 'صفحات_قديمة' ),
        'Badtitle'                  => array( 'عنوان_سيئ' ),
        'Blankpage'                 => array( 'صفحة_فارغة' ),
        'Block'                     => array( 'منع', 'منع_أيبي', 'منع_مستخدم' ),
-       'Blockme'                   => array( 'منعي' ),
        'Booksources'               => array( 'مصادر_كتاب' ),
        'BrokenRedirects'           => array( 'تحويلات_مكسورة' ),
        'Categories'                => array( 'تصنيفات' ),
@@ -377,10 +381,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'إنشاء_حساب' ),
        'Deadendpages'              => array( 'صفحات_نهاية_مسدودة' ),
        'DeletedContributions'      => array( 'مساهمات_محذوفة' ),
-       'Disambiguations'           => array( 'توضيحات' ),
        'DoubleRedirects'           => array( 'تحويلات_مزدوجة' ),
        'EditWatchlist'             => array( 'تعديل_قائمة_المراقبة' ),
        'Emailuser'                 => array( 'مراسلة_المستخدم' ),
+       'ExpandTemplates'           => array( 'فرد_القوالب' ),
        'Export'                    => array( 'تصدير' ),
        'Fewestrevisions'           => array( 'الأقل_تعديلا' ),
        'FileDuplicateSearch'       => array( 'بحث_ملف_مكرر' ),
@@ -416,6 +420,7 @@ $specialPageAliases = array(
        'Myuploads'                 => array( 'رفوعاتي' ),
        'Newimages'                 => array( 'ملفات_جديدة', 'صور_جديدة' ),
        'Newpages'                  => array( 'صفحات_جديدة' ),
+       'PagesWithProp'             => array( 'صفحات_بخاصية' ),
        'PasswordReset'             => array( 'إعادة_ضبط_كلمة_السر' ),
        'PermanentLink'             => array( 'وصلة_دائمة', 'رابط_دائم' ),
        'Popularpages'              => array( 'صفحات_مشهورة' ),
@@ -424,10 +429,13 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'صفحات_محمية' ),
        'Protectedtitles'           => array( 'عناوين_محمية' ),
        'Randompage'                => array( 'عشوائي', 'صفحة_عشوائية' ),
+       'RandomInCategory'          => array( 'عشوائي_في_تصنيف' ),
        'Randomredirect'            => array( 'تحويلة_عشوائية' ),
        'Recentchanges'             => array( 'أحدث_التغييرات' ),
        'Recentchangeslinked'       => array( 'أحدث_التغييرات_الموصولة', 'تغييرات_مرتبطة' ),
-       'Revisiondelete'            => array( 'حذف_مراجعة' ),
+       'Redirect'                  => array( 'تحويل' ),
+       'ResetTokens'               => array( 'إعادة_ضبط_المفاتيح' ),
+       'Revisiondelete'            => array( 'حذف_مراجعة', 'حذف_نسخة' ),
        'Search'                    => array( 'بحث' ),
        'Shortpages'                => array( 'صفحات_قصيرة' ),
        'Specialpages'              => array( 'صفحات_خاصة' ),
@@ -624,7 +632,7 @@ $messages = array(
 'mypage' => 'صفحة',
 'mytalk' => 'نقاش',
 'anontalk' => 'نقاش عنوان الآي بي',
-'navigation' => 'إبحار',
+'navigation' => 'تصÙ\81Ø­',
 'and' => '&#32;و',
 
 # Cologne Blue skin
@@ -749,12 +757,10 @@ $1',
 'ok' => 'موافق',
 'retrievedfrom' => 'مجلوبة من "$1"',
 'youhavenewmessages' => 'لك $1 ($2).',
-'newmessageslink' => 'رسائل جديدة',
-'newmessagesdifflink' => 'أحدث تغيير',
 'youhavenewmessagesfromusers' => 'لديك $1 من {{PLURAL:$3|مستخدم واحد|مستخدم واحد|مستخدمين اثنين|$3 مستخدمين|$3 مستخدما|$3 مستخدم}} ($2).',
 'youhavenewmessagesmanyusers' => 'لديك $1 من مستخدمين كثر ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|رسالة جديدة|رسائل جديدة}}',
-'newmessagesdifflinkplural' => 'أحدث {{PLURAL:$1|تغيير|تغييرات}}',
+'newmessageslinkplural' => '{{PLURAL:$1|رسالة جديدة|999=رسائل جديدة}}',
+'newmessagesdifflinkplural' => 'أحدث {{PLURAL:$1|تغيير|999=تغييرات}}',
 'youhavenewmessagesmulti' => 'لديك رسائل جديدة في $1',
 'editsection' => 'عدل',
 'editold' => 'عدل',
@@ -888,7 +894,8 @@ $2',
 'invalidtitle-knownnamespace' => 'عنوان غير صالح في النطاق «$2» مع نص «$3»',
 'invalidtitle-unknownnamespace' => 'عنوان غير صالح ذو نطاق غير معروف رقم $1 ونص «$2»',
 'exception-nologin' => 'غير مسجل الدخول',
-'exception-nologin-text' => 'تتطلب هذه الصفحة أو الفعل منك القيام بتسجيل الدخول على هذه الويكي أولا.',
+'exception-nologin-text' => 'الرجاء [[Special:Userlogin|تسجيل الدخول]] لتتمكن من الوصول لهذه الصفحة أو أداء هذا الإجراء.',
+'exception-nologin-text-manual' => 'الرجاء $1 لتتمكن من الوصول لهذه الصفحة أو أداء هذا الإجراء.',
 
 # Virus scanner
 'virus-badscanner' => "ضبط سيء: ماسح فيروسات غير معروف: ''$1''",
@@ -935,7 +942,7 @@ $2',
 'gotaccount' => "لديك حساب؟ '''$1'''.",
 'gotaccountlink' => 'تسجيل الدخول',
 'userlogin-resetlink' => 'نسيت تفاصيل الدخول؟',
-'userlogin-resetpassword-link' => 'صفّر كلمة سرّك',
+'userlogin-resetpassword-link' => 'نسيت كلمة مرورك؟',
 'helplogin-url' => 'Help:تسجيل الدخول',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|المساعدة في تسجيل الدخول]]',
 'userlogin-loggedin' => 'أنت {{GENDER:$1|مسجل|مسجلة}} الدخول مسبقًا باسم $1. {{GENDER:$1|استخدم|استخدمي}} النموذج بالأسفل لتسجيل الدخول بحساب آخر.',
@@ -1005,14 +1012,14 @@ $2',
 من فضلك حاول تسجيل الدخول مرة ثانية بعد استلامها.',
 'blocked-mailpassword' => 'تم منع عنوان الأيبي الخاص بك من التحرير، ولمنع التخريب لا يمكنك أن تستخدم خاصية استرجاع كلمة السر.',
 'eauthentsent' => 'تم إرسال رسالة تأكيد إلكترونية إلى العنوان المسمى.
-حتى ترسل أي رسالة أخرى لذلك الحساب عليك أن تتبع التعليمات الواردة في الرسالة لتأكيد أن هذا الحساب هو لك بالفعل.',
+قبل إرسال أي رسالة أخرى لذلك الحساب، عليك أن تتبع التعليمات الواردة في الرسالة، لتأكيد أن هذا الحساب هو لك بالفعل.',
 'throttled-mailpassword' => 'تم بالفعل إرسال تذكير بكلمة السر، في ال{{PLURAL:$1||ساعة الماضية|ساعتين الماضيتين|$1 ساعات الماضية|$1 ساعة الماضية}}.
 لمنع التخريب، سيتم إرسال تذكير واحد كل {{PLURAL:$1||ساعة|ساعتين|$1 ساعات|$1 ساعة}}.',
 'mailerror' => 'خطأ أثناء إرسال البريد: $1',
 'acct_creation_throttle_hit' => 'أنشأ زوار هذه الويكي باستخدام عنوان آيبيك {{PLURAL:$1||حسابا واحدا|حسابين|$1 حسابات|$1 حسابا|$1 حساب}} في اليوم الماضي، وهو الحد الأقصى المسموح به في هذه الفترة الزمنية.
 وكنتيجة لذلك، لن يتمكن الزوار الذين يستخدمون عنوان الأيبي هذا من إنشاء أي حسابات أخرى حاليا.',
 'emailauthenticated' => 'تم تأكيد بريدك الإلكتروني في $2 الساعة $3.',
-'emailnotauthenticated' => 'Ù\84Ù\85 Ù\8aتÙ\85 Ø§Ù\84تحÙ\82Ù\82 Ù\85Ù\86 Ø¨Ø±Ù\8aدÙ\83 Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a.
+'emailnotauthenticated' => 'Ù\84Ù\85 Ù\8aؤÙ\83د Ø¨Ø±Ù\8aدÙ\83 Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a Ø­ØªÙ\89 Ø§Ù\84Ø¢Ù\86.
 لن يتم إرسال رسائل لأي من الميزات التالية.',
 'noemailprefs' => 'حدد عنوان بريد إلكتروني في تفضيلاتك لتفعيل هذه الخصائص.',
 'emailconfirmlink' => 'أكد عنوان بريدك الإلكتروني',
@@ -1112,6 +1119,7 @@ $2
 'resettokens-legend' => 'غير المفاتيح',
 'resettokens-tokens' => 'مفاتيح:',
 'resettokens-token-label' => '$1 (القيمة الحالية: $2)',
+'resettokens-watchlist-token' => 'رمز تغذية الوب (آتوم/آس إس إس) [[Special:Watchlist|للتغيرات التي على قائمة مراقبتك]]',
 'resettokens-done' => 'تغيير المفاتيح',
 'resettokens-resetbutton' => 'غير المفاتيح المختارة',
 
@@ -1452,19 +1460,20 @@ $2
 لكن أجزاء من محتواها لن يكون مسموحا للعامة برؤيتها.",
 'revdelete-confirm' => 'الإداريون الآخرون في {{SITENAME}} سيظل بإمكانهم رؤية المحتوى المخفي ويمكنهم استرجاعه مجددا من خلال هذه الواجهة نفسها، مالم يتم وضع قيود إضافية.
 من فضلك أكد أنك تنوي فعل هذا، وأنك تفهم العواقب، وأنك تفعل هذا بالتوافق مع [[{{MediaWiki:Policy-url}}|السياسة]].',
-'revdelete-suppress-text' => "الإخفاء ينبغي أن يتم استخدامه '''فقط''' في الحالات التالية:
+'revdelete-suppress-text' => "ينبغي للإخفاء أن يستخدم '''فقط''' في الحالات التالية:
+* معلومات يحتمل أن تكون تشهيرية
 * معلومات شخصية غير ملائمة
-*: ''عناوين المنازل وأرقام التليفونات، أرقام الضمان الاجتماعي، إلى آخره.''",
+*: ''عناوين المنازل وأرقام الهواتف وأرقام الهويات الوطنية إلى آخره.''",
 'revdelete-legend' => 'وضع ضوابط رؤية',
-'revdelete-hide-text' => 'أخف نص المراجعة',
+'revdelete-hide-text' => 'نص المراجعة',
 'revdelete-hide-image' => 'أخف محتوى الملف',
 'revdelete-hide-name' => 'أخف الفعل والهدف',
-'revdelete-hide-comment' => 'أخف تعليق التعديل',
-'revdelete-hide-user' => 'أخÙ\81 Ø§Ø³Ù\85/Ø¢Ù\8aبÙ\8a Ø§Ù\84Ù\85ستخدÙ\85',
+'revdelete-hide-comment' => 'ملخص التعديل',
+'revdelete-hide-user' => 'اسÙ\85 Ø§Ù\84Ù\85ستخدÙ\85/عÙ\86Ù\88اÙ\86 Ø§Ù\84Ø¢Ù\8aبÙ\8a',
 'revdelete-hide-restricted' => 'أخف البيانات عن الإداريين إضافة إلى الآخرين',
 'revdelete-radio-same' => '(لا تغير)',
-'revdelete-radio-set' => 'Ù\86عÙ\85',
-'revdelete-radio-unset' => 'Ù\84ا',
+'revdelete-radio-set' => 'Ù\85Ø®Ù\81Ù\8a',
+'revdelete-radio-unset' => 'Ù\85رئÙ\8a',
 'revdelete-suppress' => 'أخف البيانات عن مديري النظام والبقية',
 'revdelete-unsuppress' => 'إزالة الضوابط من المراجعات المسترجعة',
 'revdelete-log' => 'السبب:',
@@ -1623,8 +1632,7 @@ $1",
 'preferences' => 'تفضيلات',
 'mypreferences' => 'تفضيلات',
 'prefs-edits' => 'عدد التعديلات:',
-'prefsnologin' => 'غير مسجل الدخول',
-'prefsnologintext' => 'يجب أن تكون <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} مسجل الدخول]</span>  حتى تتمكن من تعديل تفضيلات المستخدم.',
+'prefsnologintext2' => 'الرجاء $1 لضبط تفضيلات المستخدم.',
 'changepassword' => 'غير كلمة السر',
 'prefs-skin' => 'واجهة',
 'skin-preview' => 'عرض مسبق',
@@ -1922,6 +1930,7 @@ $1",
 'recentchanges-label-minor' => 'هذا تعديل طفيف',
 'recentchanges-label-bot' => 'أُجْرِيَ هذا التعديل بواسطة بوت',
 'recentchanges-label-unpatrolled' => 'لم يراجع هذا التعديل إلى الآن',
+'recentchanges-legend-newpage' => '(راجع أيضا [[Special:NewPages|قائمة الصفحات الجديدة]])',
 'rcnote' => "بالأسفل {{PLURAL:$1|لا توجد تغييرات|التغيير الأخير|آخر تغييرين|آخر '''$1''' تغييرات|آخر '''$1''' تغييرا|آخر '''$1''' تغيير}} في {{PLURAL:$2||'''اليوم''' الماضي|'''اليومين''' الماضيين|ال'''$2''' أيام الماضية|ال'''$2''' يوما الماضيا|ال'''$2''' يوم الماضي}}، كما في $5، $4.",
 'rcnotefrom' => "بالأسفل التغييرات منذ '''$2''' (إلى '''$1''' معروضة).",
 'rclistfrom' => 'أظهر التغييرات بدءا من $1',
@@ -2729,7 +2738,7 @@ $UNWATCHURL
 آخر تعديل كان بواسطة [[User:$3|$3]] ([[User talk:$3|نقاش]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "ملخص التعديل كان: \"''\$1''\".",
 'revertpage' => 'استرجع تعديلات [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]]) حتى آخر مراجعة ل[[User:$1|$1]]',
-'revertpage-nouser' => 'استرجع تعديلات مستخدم مخفيّ حتى آخر مراجعة ل[[User:$1|$1]]',
+'revertpage-nouser' => 'استرجع تعديلات مستخدم مخفيّ حتى آخر مراجعة ل{{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'استرجع تعديلات $1؛
 استرجع حتى آخر نسخة بواسطة $2.',
 
@@ -2875,7 +2884,7 @@ $1',
 'contributions' => 'مساهمات {{GENDER:$1|المستخدم|المستخدمة}}',
 'contributions-title' => 'مساهمات {{GENDER:$1|المستخدم|المستخدمة}} $1',
 'mycontris' => 'مساهماتي',
-'contribsub2' => 'ل$1 ($2)',
+'contribsub2' => 'ل{{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'لم يتم العثور على تغييرات تطابق هذه المحددات.',
 'uctop' => 'حالي',
 'month' => 'من شهر (وأقدم):',
@@ -3192,7 +3201,7 @@ $1',
 'allmessagesdefault' => 'النص الافتراضي',
 'allmessagescurrent' => 'النص الحالي',
 'allmessagestext' => 'هذه قائمة برسائل النظام المتوفرة في نطاق ميدياويكي.
-من فضلك زر [//www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت ترغب في المساهمة في ترجمة ميدياويكي الأساسية.',
+من فضلك زر [https://www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت ترغب في المساهمة في ترجمة ميدياويكي الأساسية.',
 'allmessagesnotsupportedDB' => "هذه الصفحة لا يمكن استخدامها لأن '''\$wgUseDatabaseMessages''' تم تعطيله.",
 'allmessages-filter-legend' => 'المرشح',
 'allmessages-filter' => 'رشح حسب حالة التخصيص:',
@@ -3407,6 +3416,8 @@ $2',
 'spam_reverting' => 'استرجاع آخر نسخة ليس بها وصلات إلى $1',
 'spam_blanking' => 'كل النسخ احتوت على وصلات ل $1، إفراغ',
 'spam_deleting' => 'جميع النسخ تحوي رابطا إلى $1، يتم الحذف',
+'simpleantispam-label' => "اختبار ضد السبام.
+'''لا''' تملأ هذا!",
 
 # Info page
 'pageinfo-title' => 'المعلومات عن «$1»',
@@ -3505,7 +3516,7 @@ $1',
 'svg-long-desc' => 'ملف SVG، أبعاده $1 × $2 بكسل، حجم الملف: $3',
 'svg-long-desc-animated' => 'ملف SVG متحرك، بمقاسات  $1  ×  $2  بكسل، حجم الملف: $3',
 'svg-long-error' => 'ملف SVG غير صالح: $1',
-'show-big-image' => 'دÙ\82Ø© Ù\83اÙ\85Ù\84Ø©',
+'show-big-image' => 'اÙ\84Ù\85Ù\84Ù\81 Ø§Ù\84أصÙ\84Ù\8a',
 'show-big-image-preview' => 'حجم هذه المعاينة: $1.',
 'show-big-image-other' => '{{PLURAL:$2||البعد الآخر|البعدان الآخران|الأبعاد الأخرى}}: $1.',
 'show-big-image-size' => '$1 × $2 بكسل',
@@ -4007,7 +4018,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'عدل هذا الملف باستخدام تطبيق خارجي',
-'edit-externally-help' => '(انظر [//www.mediawiki.org/wiki/Manual:External_editors تعليمات الإعداد] لمزيد من المعلومات)',
+'edit-externally-help' => '(انظر [https://www.mediawiki.org/wiki/Manual:External_editors تعليمات الإعداد] لمزيد من المعلومات)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'الكل',
@@ -4286,7 +4297,7 @@ $5
 'version-version' => '(نسخة $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'الرخصة',
-'version-poweredby-credits' => "تدار هذه الويكي بواسطة '''[//www.mediawiki.org/ ميدياويكي]'''، حقوق النشر © 2001-$1 $2.",
+'version-poweredby-credits' => "تدار هذه الويكي بواسطة '''[https://www.mediawiki.org/ ميدياويكي]'''، حقوق النشر © 2001-$1 $2.",
 'version-poweredby-others' => 'آخرون',
 'version-poweredby-translators' => 'مترجمو translatewiki.net',
 'version-credits-summary' => 'نود أن نعرف بالأشخاص التالية أسماؤهم لمساهمتهم في [[Special:Version|ميدياويكي]].',
@@ -4307,7 +4318,7 @@ $5
 # Special:Redirect
 'redirect' => 'تحويل باسم ملف أو اسم مستخدم أو رقم مراجعة',
 'redirect-legend' => 'تحويل إلى ملف أو صفحة',
-'redirect-summary' => 'هذه الصفحة الخاصة تحوّل إلى ملف (باسمه) أو صفحة (برقم إحدى مراجعاتها) أو إلى صفحة مستخدم (برقمه التعريفي).',
+'redirect-summary' => 'هذه الصفحة الخاصة تحوّل إلى ملف (باسمه) أو صفحة (برقم إحدى مراجعاتها) أو إلى صفحة مستخدم (برقمه التعريفي). الاستخدام [[{{#Special:Redirect}}/file/Example.jpg]] أو [[{{#Special:Redirect}}/revision/328429]] أو [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'حوّل',
 'redirect-lookup' => 'ابحث في:',
 'redirect-value' => 'الوجهة',
@@ -4329,10 +4340,9 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'الصفحات الخاصة',
-'specialpages-note' => '----
-* صفحات خاصة عادية.
-* <span class="mw-specialpagerestricted">صفحات خاصة للمخولين.</span>
-* <span class="mw-specialpagecached">صفحات خاصة لبيانات مخزنة فقط (قد تكون مهجورة).</span>',
+'specialpages-note-top' => 'المفتاح',
+'specialpages-note' => '* صفحات خاصة عادية.
+* <span class="mw-specialpagerestricted">صفحات خاصة للمخولين.</span>',
 'specialpages-group-maintenance' => 'تقارير الصيانة',
 'specialpages-group-other' => 'صفحات خاصة أخرى',
 'specialpages-group-login' => 'دخول / إنشاء حساب',
@@ -4538,4 +4548,21 @@ $5
 'limitreport-postexpandincludesize-value' => '$1/$2 بايت',
 'limitreport-templateargumentsize-value' => '$1/$2 بايت',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'فرد القوالب',
+'expand_templates_intro' => 'تتعامل هذه الصفحة الخاصة مع نصوص الويكي وتقوم بفرد كل القوالب الموجودة به.
+وتقوم أيضا بفرد دوال القوالب مثل
+<nowiki>{{</nowiki>#language:...}}، والمتغيرات مثل
+<nowiki>{{</nowiki>يوم}}-- وتقوم التعامل مع كل ما بين الأقواس المزدوجة.
+تقوم بفعل هذا عن طريق استدعاء المعالج المناسب من الميدياويكي.',
+'expand_templates_title' => 'عنوان صفحة هذا النص، لأجل معالجة {{FULLPAGENAME}} إلخ.:',
+'expand_templates_input' => 'النص المدخل:',
+'expand_templates_output' => 'النتيجة',
+'expand_templates_xml_output' => 'خرج XML',
+'expand_templates_ok' => 'موافق',
+'expand_templates_remove_comments' => 'أزل التعليقات',
+'expand_templates_remove_nowiki' => 'أخفِ وسوم <nowiki> في الناتج',
+'expand_templates_generate_xml' => 'اعرض شجرة XML parse',
+'expand_templates_preview' => 'عرض مسبق',
+
 );
index 33b463c..01861cf 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ܒܪܝ_ܚܘܫܒܢܐ' ),
        'Deadendpages'              => array( 'ܦܐܬܬ̈ܐ_ܥܡ_ܚܪܬܐ_ܡܝܬܬܐ' ),
        'DeletedContributions'      => array( 'ܫܘܬܦܘ̈ܬܐ_ܫܝ̈ܦܬܐ' ),
-       'Disambiguations'           => array( 'ܬܘܚܡ̈ܐ_ܐܚܪ̈ܢܐ' ),
        'DoubleRedirects'           => array( 'ܨܘܝܒ̈ܐ_ܥܦܝ̈ܦܐ' ),
        'EditWatchlist'             => array( 'ܫܚܠܦ_ܪ̈ܗܝܬܐ' ),
        'Emailuser'                 => array( 'ܫܕܪ_ܒܝܠܕܪܐ_ܐܠܩܛܪܘܢܝܐ_ܠܡܦܠܚܢܐ' ),
@@ -307,7 +306,7 @@ $messages = array(
 'articlepage' => 'ܚܘܝܝܐ ܕܦܐܬܐ ܕܚܒܝܫܬ̈ܐ',
 'talk' => 'ܡܡܠܠܐ',
 'views' => 'ܚܙܝܬ̈ܐ',
-'toolbox' => 'ܣܢÜ\95Ü\98Ü©Ü\90 Ü\95Ü¡Ü\90Ü¢Ì\88Ü\90',
+'toolbox' => 'ܡܐܢ̈ܐ',
 'userpage' => 'ܚܙܝ ܦܐܬܐ ܕܡܦܠܚܢܐ',
 'projectpage' => 'ܚܙܝ ܦܐܬܐ ܕܬܪܡܝܬܐ',
 'imagepage' => 'ܚܙܝ ܦܐܬܐ ܕܠܦܦܐ',
@@ -358,12 +357,10 @@ $1',
 
 'ok' => 'ܛܒ',
 'youhavenewmessages' => 'ܐܝܬ ܠܟ $1 ($2).',
-'newmessageslink' => 'ܐܓܪ̈ܬܐ ܚܕ̈ܬܬܐ',
-'newmessagesdifflink' => 'ܫܘܚܠܦܐ ܐܚܪܝܐ',
 'youhavenewmessagesfromusers' => 'ܐܝܬ ܠܟ $1 ܡܢ {{PLURAL:$3|ܡܦܠܚܢܐ ܐܚܪܢܐ|$3 ܡܦܠܚܢ̈ܐ}} ($2).',
 'youhavenewmessagesmanyusers' => 'ܐܝܬ ܠܟ $1 ܡܢ ܡܦܠܚܢ̈ܐ ܣܓܝܐ̈ܐ ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|ܐܓܪܬܐ ܚܕܬܐ|ܐܓܪ̈ܬܐ ܚܕ̈ܬܬܐ}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|ܫܘܚܠܦܐ ܐܚܪܝܐ|ܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ܐܓܪܬܐ ܚܕܬܐ|999=ܐܓܪ̈ܬܐ ܚܕ̈ܬܬܐ}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|ܫܘܚܠܦܐ ܐܚܪܝܐ|999=ܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ}}',
 'youhavenewmessagesmulti' => 'ܐܝܬ ܠܟ ܐܓܪ̈ܬܐ ܚܕ̈ܬܬܐ ܒ $1',
 'editsection' => 'ܫܚܠܦ',
 'editold' => 'ܫܚܠܦ',
@@ -626,11 +623,11 @@ $1',
 'revdelete-hide-text' => 'ܛܫܝ ܟܬܒܬܐ ܕܬܢܝܬܐ',
 'revdelete-hide-image' => 'ܛܫܝ ܚܒܝܫܬ̈ܐ ܕܠܦܦܐ',
 'revdelete-hide-name' => 'ܛܫܝ ܥܒܕܐ ܘܢܘܦܐ',
-'revdelete-hide-comment' => 'Ü\9bÜ«Ü\9d ܟܪܝܘܬܐ ܕܫܘܚܠܦܐ',
-'revdelete-hide-user' => 'Ü\9bÜ«Ü\9d Ü«Ü¡Ü\90\90Ü\9d Ü¦Ü\9d (IP) Ü\95ܡܦܠÜ\9aÜ¢Ü\90',
+'revdelete-hide-comment' => 'Ü«Ü\9aܠܦ ܟܪܝܘܬܐ ܕܫܘܚܠܦܐ',
+'revdelete-hide-user' => 'Ü«Ü¡Ü\90 Ü\95ܡܦܠÜ\9aÜ¢Ü\90 Ü\95Ü¡Ü«Ü\9aܠܦܢÜ\90\90Ü\9d Ü¦Ü\9d (IP)',
 'revdelete-radio-same' => '(ܠܐ ܬܫܚܠܦ)',
-'revdelete-radio-set' => 'Ü\90Ü\9dÜ¢',
-'revdelete-radio-unset' => 'Ü ܐ',
+'revdelete-radio-set' => 'Ü\9bÜ«Ü\9dÜ\90',
+'revdelete-radio-unset' => 'Ü\93Ü Ü\9dܐ',
 'revdelete-log' => 'ܥܠܬܐ:',
 'revdel-restore' => 'ܫܚܠܦ ܚܙܝܬܐ',
 'revdel-restore-deleted' => 'ܬܢܝܬ̈ܐ ܫܝܦ̈ܐ',
@@ -727,7 +724,6 @@ $1',
 'preferences' => 'ܨܒܝܢܝܘܬ̈ܐ',
 'mypreferences' => 'ܨܒܝܢܝܘܬ̈ܐ',
 'prefs-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ:',
-'prefsnologin' => 'ܠܝܬܝܟ ܥܠܝܠܐ',
 'changepassword' => 'ܫܚܠܦ ܡܠܬܐ ܕܥܠܠܐ',
 'prefs-skin' => 'ܓܠܕܐ',
 'skin-preview' => 'ܚܝܪܐ ܩܕܡܝܐ',
@@ -892,6 +888,7 @@ $1',
 'recentchanges-label-minor' => 'ܗܢܘ ܫܘܚܠܦܐ ܙܥܘܪܐ',
 'recentchanges-label-bot' => 'ܒܘܬ (bot) ܥܒܕ ܗܢܐ ܫܘܚܠܦܐ',
 'recentchanges-label-unpatrolled' => 'ܫܘܚܠܦܐ ܗܢܐ ܠܐ ܗܘ ܟܪܝܟܐ ܠܗܫܐ',
+'recentchanges-legend-newpage' => '$1 - ܦܐܬܐ ܚܕܬܐ',
 'rcnotefrom' => "ܠܬܚܬ ܫܘܚܠܦ̈ܐ ܕܡܢ '''$2''' (ܥܕ '''$1''' ܡܬܚܙܝܢ̈ܐ).",
 'rclistfrom' => 'ܚܘܝ ܫܘܚܠܦ̈ܐ ܚܕ̈ܬܐ ܡܢ $1',
 'rcshowhideminor' => '$1 ܫܘܚܠܦ̈ܐ ܙܥܘܪ̈ܐ',
@@ -1628,7 +1625,7 @@ $1',
 'file-info-size' => '$1 × $2 ܦܩܣܠ، ܥܓܪܐ ܕܠܦܦܐ: $3، ܐܕܫܐ ܕ MIME: $4',
 'file-info-size-pages' => '$1 × $2 ܦܩܣܠ, ܥܓܪܐ ܕܠܦܦܐ: $3, ܐܕܫܐ ܕ MIME: $4, $5 {{PLURAL:$5|ܦܐܬܐ|ܦܐܬܬ̈ܐ}}',
 'file-nohires' => 'ܠܝܬ ܢܩܕܘܬܐ ܝܬܝܪ ܡܢ ܗܢܐ.',
-'show-big-image' => 'ܢܩÜ\95Ü\98ܬÜ\90 Ü\93Ü¡Ü\9dܪܬܐ',
+'show-big-image' => 'ܠܦܦÜ\90 Ü«ÜªÜ«Ü\9dܐ',
 'show-big-image-preview' => 'ܥܓܪܐ ܕܓܠܚܐ: $1.',
 'show-big-image-size' => '$1 × $2 ܦܩܣܠ',
 
@@ -1794,8 +1791,7 @@ $1',
 
 # Special:SpecialPages
 'specialpages' => 'ܦܐܬܬ̈ܐ ܕ̈ܝܠܢܝܬܐ',
-'specialpages-note' => '----
-* ܦܐܬܬ̈ܐ ܕ̈ܝܠܢܝܬܐ ܥܝܕ̈ܝܬܐ.
+'specialpages-note' => '* ܦܐܬܬ̈ܐ ܕ̈ܝܠܢܝܬܐ ܥܝܕ̈ܝܬܐ.
 * <span class="mw-specialpagerestricted">ܦܐܬܬ̈ܐ ܕ̈ܝܠܢܝܬܐ ܕܩܝܘܡ̈ܐ ܒܠܚܘܕ.</span>',
 'specialpages-group-maintenance' => 'ܬܫܪܪ̈ܐ ܕܚܕܬܘܬܐ',
 'specialpages-group-other' => 'ܦܐܬܬ̈ܐ ܕ̈ܝܠܢܝܬܐ ܐܚܪ̈ܢܝܬܐ',
@@ -1862,4 +1858,10 @@ $1',
 'searchsuggest-search' => 'ܒܨܝ',
 'searchsuggest-containing' => 'ܬܚܒܘܫ...',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'ܐܪܘܚ ܩܠܒ̈ܐ',
+'expand_templates_output' => 'ܦܠܛܐ',
+'expand_templates_ok' => 'ܛܒ',
+'expand_templates_preview' => 'ܚܝܪܐ ܩܕܡܝܐ',
+
 );
index fe0312a..5a727dc 100644 (file)
@@ -21,8 +21,8 @@ $messages = array(
 # User preference toggles
 'tog-underline' => 'Miñcewirilpe lasun',
 'tog-justify' => 'Xvrvmpe cijkantvkun',
-'tog-showtoolbar' => 'Pengelün kümeelün ñi chemkün (JavaScript duamyengey)',
-'tog-editondblclick' => 'Wirin pakina epu klik mew (JavaScript)',
+'tog-showtoolbar' => 'Pengelün kümeelün ñi chemkün',
+'tog-editondblclick' => 'Wirin pakina epu klik mew',
 'tog-rememberpassword' => 'Amulen tañi nülküwküleael tüfa mew (alürumechi $1 {{PLURAL:$1 antü}})',
 
 'underline-always' => 'Rumel',
@@ -203,8 +203,6 @@ $messages = array(
 'ok' => 'Feley',
 'retrievedfrom' => 'Nentungey "$1" mew',
 'youhavenewmessages' => 'Nieymi $1 ($2).',
-'newmessageslink' => 'weke werkün',
-'newmessagesdifflink' => 'we kalekünun',
 'newmessagesdifflinkplural' => 'we {{PLURAL:$1|kalekünuy|kalekünuy}}',
 'youhavenewmessagesmulti' => 'Nieymi we yefalzugu $1 mew.',
 'editsection' => 'Wirin',
@@ -430,9 +428,8 @@ Rulpakünuy feychi kangelkülelu dungu.",
 'powersearch-field' => 'Kintun',
 
 # Preferences page
-'mypreferences' => 'Tami dullin',
+'mypreferences' => 'Dullin',
 'prefs-edits' => 'Rakin Wirin:',
-'prefsnologin' => 'Mülelay Konün',
 'skin-preview' => 'Pen chum müley',
 'prefs-editing' => 'Wirin',
 'searchresultshead' => 'Kintun',
@@ -495,6 +492,7 @@ Rulpakünuy feychi kangelkülelu dungu.",
 'recentchanges-label-minor' => 'Tüfachi ta kiñe pichi wirin',
 'recentchanges-label-bot' => 'Kiñe kizuamukelu küzauwe dewmay tüfachi wirin.',
 'recentchanges-label-unpatrolled' => 'Pukintulelay tüfachi wirin.',
+'recentchanges-legend-newpage' => '$1 - We Pakina',
 'rcnote' => 'Nagpüle {{PLURAL:müley $1 kalekünun}}, rupalu {{PLURAL:$2 antü}}, $5, $4.',
 'rcnotefrom' => "Nagpüle müley fill wirin tuwülu '''$2''' mew (tripalu '''$1''' mew).",
 'rclistfrom' => 'Adkintun weke kalekünun amuamugelu $1',
@@ -903,7 +901,7 @@ Ka dungu ellkangeay wünedullin reke.
 
 # External editor support
 'edit-externally' => 'Kümeelün tüfachi eltukawün wekun küdauwe mew',
-'edit-externally-help' => '(Pen feychi [//www.mediawiki.org/wiki/Manual:External_editors adtukünun chumngechi pünengeael]  doy dungungeam)',
+'edit-externally-help' => '(Pen feychi [https://www.mediawiki.org/wiki/Manual:External_editors adtukünun chumngechi pünengeael]  doy dungungeam)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kom',
index 9f1b336..bc20c1c 100644 (file)
@@ -142,8 +142,6 @@ $messages = array(
 'noindex-category' => 'shat mamfhtsach',
 'broken-file-category' => 'ṣfaḫi fiha wṣlat milffaṫ mhrrsa',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'ala',
 'article' => 'sfht mohtawa',
 'newwindow' => '(kayṫḫell fe ċerjem weḫdaĥor)',
@@ -278,8 +276,6 @@ chof [[Special:Version|sfht lversion]]',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Mrejjĝa men "$1"',
 'youhavenewmessages' => 'Ĝendek $1 ($2).',
-'newmessageslink' => 'méṣajaṫ jdad',
-'newmessagesdifflink' => 'ṫ-ṫeġyir l-leĥĥer',
 'youhavenewmessagesmulti' => 'Jawek méṣajaṫ jdad fe $1',
 'editsection' => 'Ṣayeb',
 'editold' => 'ṣayeb',
@@ -955,8 +951,6 @@ Laḫed ana imken ikono l-indexaṫ dial {{SITENAME}} qdam o ma bqaoċ ṣalḫi
 'preferences' => 'ṫfḍilaṫ',
 'mypreferences' => 'Ḫajaṫ li kanfeḍḍel',
 'prefs-edits' => 'ĝadad ṫ-ṫĝdilaṫ:',
-'prefsnologin' => 'nta mamkoniktich',
-'prefsnologintext' => 'ĥaṣṣk ṫkon  <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} daĥol]</span> baċ ṫĝyyer ṫfḍilaṫ l-moṣṫĥdim.',
 'changepassword' => 'tbdl lmot de passe',
 'prefs-skin' => 'skin',
 'skin-preview' => 'L-Prévizualizasyon',
@@ -2459,7 +2453,7 @@ Ila ṫbeddel l-fiċyé men ḫalṫo l-'aṣliya, kaynin ċi ṫafaṣil ma mna
 
 # External editor support
 'edit-externally' => 'Ṣayeb had l-fiċyé be ċi aplikasyon ĥarijiya',
-'edit-externally-help' => '(Ċof [//www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d’installation] ila ḫṫajiṫi meĝlomaṫ ĥrin)',
+'edit-externally-help' => '(Ċof [https://www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d’installation] ila ḫṫajiṫi meĝlomaṫ ĥrin)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kolċi',
index 13b3f37..b8a6061 100644 (file)
@@ -52,7 +52,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'صفح_قديمه' ),
        'Blankpage'                 => array( 'صفحه_فارضيه' ),
        'Block'                     => array( 'بلوك', 'بلوك_IP', 'بلوك_يوزر' ),
-       'Blockme'                   => array( 'بلوك_لنفسى' ),
        'Booksources'               => array( 'مصادر_كتاب' ),
        'BrokenRedirects'           => array( 'تحويلات_مكسوره' ),
        'Categories'                => array( 'تصانيف' ),
@@ -62,7 +61,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ابتدى_حساب' ),
        'Deadendpages'              => array( 'صفح_نهايه_مسدوده' ),
        'DeletedContributions'      => array( 'مساهمات_ممسوحه' ),
-       'Disambiguations'           => array( 'توضيحات' ),
        'DoubleRedirects'           => array( 'تحويلات_دوبل' ),
        'Emailuser'                 => array( 'ابعت_ايميل_لليوزر' ),
        'Export'                    => array( 'تصدير' ),
@@ -244,8 +242,8 @@ $magicWords = array(
        'revisiontimestamp'         => array( '1', 'طابع_وقت_المراجعة', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'مستخدم_المراجعة', 'REVISIONUSER' ),
        'plural'                    => array( '0', 'جمع:', 'PLURAL:' ),
-       'fullurl'                   => array( '0', 'مسار_كامل:', 'عنوان_كامل:', 'FULLURL:' ),
-       'fullurle'                  => array( '0', 'عنوان_كامل:', 'مسار_كامل:', 'FULLURLE:' ),
+       'fullurl'                   => array( '0', 'عنوان_كامل:', 'FULLURL:' ),
+       'fullurle'                  => array( '0', 'مسار_كامل:', 'FULLURLE:' ),
        'lcfirst'                   => array( '0', 'عنوان_كبير:', 'LCFIRST:' ),
        'ucfirst'                   => array( '0', 'عنوان_صغير:', 'UCFIRST:' ),
        'lc'                        => array( '0', 'صغير:', 'LC:' ),
@@ -310,12 +308,12 @@ $messages = array(
 'tog-hidepatrolled' => 'خبى التعديلات المتراجعه من اخر التعديلات',
 'tog-newpageshidepatrolled' => 'خبى الصفح المتراجعه من ليستة الصفح الجديده',
 'tog-extendwatchlist' => 'وسع ليستة المراقبه علشان تبين كل التعديلات, مش بس اجدد تعديلات',
-'tog-usenewrc' => 'استعÙ\85Ù\84 Ø§Ø¬Ø¯Ø¯ ØªØºÙ\8aÙ\8aرات Ù\85تÙ\82Ù\88Ù\8aÙ\87 (بÙ\8aحتاج JavaScript).',
+'tog-usenewrc' => 'جÙ\85ع  Ø§Ù\84تغÙ\8aÙ\8aرات  Ø­Ø³Ø¨ Ø§Ù\84صÙ\81Ø­Ù\87 Ù\81 Ø§Ø¬Ø¯Ø¯ Ø§Ù\84تغÙ\8aÙ\8aرات Ù\88 Ù\84ستة Ø§Ù\84صÙ\81Ø­ Ø§Ù\84Ù\84Ù\89 Ø¨Ø§Ø±Ø§Ù\82بÙ\87ا',
 'tog-numberheadings' => 'رقم العناوين اوتوماتيك',
-'tog-showtoolbar' => 'بÙ\8aÙ\86 Ø§Ù\84toolbar Ø¨ØªØ§Ø¹ Ø§Ù\84تعدÙ\8aÙ\84 (بÙ\8aحتاج JavaScript)',
-'tog-editondblclick' => 'عدل الصفح لما تدوس مرتين (بيحتاج JavaScript)',
+'tog-showtoolbar' => 'بÙ\8aÙ\86 Ø´Ø±Ù\8aØ· Ø§Ù\84تعدÙ\8aÙ\84',
+'tog-editondblclick' => 'عدل الصفح لما تدوس مرتين',
 'tog-editsection' => 'اسمح بـ تعديل الاجزاء عن طريق لينكات [تعديل]',
-'tog-editsectiononrightclick' => 'اسمح بـ تعديل الاجزاء لما تعمل right-click بـ الماوس على عناوين الاجزاء (بيحتاج JavaScript)',
+'tog-editsectiononrightclick' => 'اسمح بـ تعديل الاجزاء لما تعمل كليك يمين بـالماوس على عناوين الاجزاء',
 'tog-showtoc' => 'بين جدول المحتويات (بتاع الصفح اللى فيها اكتر من 3 عناوين)',
 'tog-rememberpassword' => ' (لمدة   $1 {{PLURAL:$1|يوم|يوم}})خليك فاكر دخولى على الكمبيوتر دا',
 'tog-watchcreations' => 'زوّد الصفح اللى ابتديتها على ليستة الصفح اللى باراقبها.',
@@ -334,7 +332,7 @@ $messages = array(
 'tog-shownumberswatching' => 'بين عدد اليوزرز المراقبين',
 'tog-oldsig' => 'الامضا دلوقتى:',
 'tog-fancysig' => 'امضا خام (من غير لينك أوتوماتيك)',
-'tog-uselivepreview' => 'استخدم البروفة السريعة (جافاسكريبت) (تجريبي)',
+'tog-uselivepreview' => 'استخدم البروفه السريعه (تجريبي)',
 'tog-forceeditsummary' => 'نبهنى عند تدخيل ملخص للتعديل  فاضي',
 'tog-watchlisthideown' => 'خبى التعديلات بتاعتى من لستة المراقبة',
 'tog-watchlisthidebots' => 'خبى التعديلات بتاعة البوت من لستة المراقبة',
@@ -348,10 +346,11 @@ $messages = array(
 'tog-noconvertlink' => 'عطل تحويل عناوين الوصلات',
 'tog-norollbackdiff' => 'الغى الاختلافات بعد ما تعمل الرول باك',
 'tog-useeditwarning' => 'حذّرنى لما اسيب صفحة تعديل فيها تغييرات مش متسييڤه',
+'tog-prefershttps' => 'إستخدم  وصله متأمنه بعد الدخول',
 
 'underline-always' => 'دايما',
 'underline-never' => 'ابدا',
-'underline-default' => 'على حسب إعدادات المتصفح',
+'underline-default' => ' حسب  المظهر و لا البراوزر',
 
 # Font style option in Special:Preferences
 'editfont-style' => ':الفونت بتاع مساحة التعديل',
@@ -411,6 +410,18 @@ $messages = array(
 'oct' => 'اكتوبر',
 'nov' => 'نوفمبر',
 'dec' => 'ديسمبر',
+'january-date' => 'يناير $1',
+'february-date' => 'فبراير $1',
+'march-date' => 'مارس $1',
+'april-date' => 'ابريل $1',
+'may-date' => 'مايو $1',
+'june-date' => 'يونيه $1',
+'july-date' => 'يوليه $1',
+'august-date' => 'اغسطس $1',
+'september-date' => 'سبتمبر $1',
+'october-date' => 'اكتوبر $1',
+'november-date' => 'نوفمبر $1',
+'december-date' => 'ديسمبر $1',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|تصنيف|تصانيف}}',
@@ -429,12 +440,14 @@ $messages = array(
 'listingcontinuesabbrev' => 'متابعه',
 'index-category' => 'صفحات متفهرسه',
 'noindex-category' => 'صفحات مش متفهرسه',
+'broken-file-category' => 'صفحات  فيها روابط ملفات مش شغاله',
 
 'about' => 'عن',
 'article' => 'صفحة محتوى',
 'newwindow' => '(بتفتح ويندو جديده)',
 'cancel' => 'كانسل',
 'moredotdotdot' => 'اكتر...',
+'morenotlisted' => 'اللسته دى  مش كامله.',
 'mypage' => 'صفحه',
 'mytalk' => 'كلام',
 'anontalk' => 'المناقشة مع عنوان الأيبى دا',
@@ -458,6 +471,7 @@ $messages = array(
 'vector-action-protect' => 'حمايه',
 'vector-action-undelete' => 'الغى المسح',
 'vector-action-unprotect' => 'غير الحمايه',
+'vector-simplesearch-preference' => ' تشغيل شريط التدوير  المبسط (لمظهر فيكتور بس)',
 'vector-view-create' => 'اعمل',
 'vector-view-edit' => 'تعديل',
 'vector-view-history' => 'استعراض التاريخ',
@@ -467,6 +481,7 @@ $messages = array(
 'namespaces' => 'النطاقات',
 'variants' => 'المتغيرات',
 
+'navigation-heading' => 'لستة التصفح',
 'errorpagetitle' => 'غلطه',
 'returnto' => 'ارجع ل $1.',
 'tagline' => 'من ويكيبيديا, الموسوعه الحره',
@@ -481,13 +496,16 @@ $messages = array(
 'printableversion' => 'نسخه للطبع',
 'permalink' => 'لينك دايم',
 'print' => 'اطبع',
+'view' => 'شوف',
 'edit' => 'تعديل',
 'create' => 'إبتدى',
 'editthispage' => 'عدل الصفحه دى',
 'create-this-page' => 'أنشيء الصفحه دى',
 'delete' => 'مسح',
 'deletethispage' => 'امسح الصفحه دى',
+'undeletethispage' => 'استرجاع الصفحه دى',
 'undelete_short' => 'استرجاع {{PLURAL:$1|تعديل واحد|تعديلان|$1 تعديلات|$1 تعديل|$1 تعديلا}}',
+'viewdeleted_short' => '{{PLURAL:$1|}}{{PLURAL:$1|تعديل واحد ملغي|تعديلين ملغيين|$1 تعديلات ملغية|$1 تعديل ملغي|$1 تعديل ملغي}}',
 'protect' => 'حمايه',
 'protect_change' => 'غيّر',
 'protectthispage' => 'احمى الصفحه دى',
@@ -532,7 +550,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'عن {{SITENAME}}',
 'aboutpage' => 'Project:معلومات عن',
-'copyright' => 'اÙ\84Ù\85حتÙ\88Ù\89 Ù\85Ù\88جÙ\88د ØªØ­Øª $1.',
+'copyright' => 'اÙ\84Ù\83Ù\84اÙ\85 Ù\88 Ø§Ù\84صÙ\88ر Ù\85Ù\88جÙ\88دÙ\8aÙ\86 Ø­Ø³Ø¨  $ 1 Ù\85اعدا Ø§Ù\84حاÙ\84ات Ø¥Ù\84Ù\84Ù\89 Ù\85Ù\83تÙ\88ب Ø¹Ù\86دÙ\87ا Ø­Ø§Ø¬Ù\87 ØªØ§Ù\86Ù\8aÙ\87.',
 'copyrightpage' => '{{ns:project}}:حقوق النسخ',
 'currentevents' => 'الاخبار دلوقتى',
 'currentevents-url' => 'Project:الاخبار دلوقتى',
@@ -559,8 +577,10 @@ $1',
 'ok' => 'موافئ',
 'retrievedfrom' => 'اتجابت من "$1"',
 'youhavenewmessages' => 'عندك $1 ($2).',
-'newmessageslink' => 'رسايل جديده',
-'newmessagesdifflink' => 'اخر تعديل',
+'youhavenewmessagesfromusers' => 'عندك $1 من {{PLURAL:${{PLURAL:$3|}}3|يوزر واحد|يوزر واحد|اتنين يوزر |$3 مستخدمين|$3 يوزر|$3 يوزر}} ($2).',
+'youhavenewmessagesmanyusers' => 'عندك $1 من يوزرات كتير  ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|رساله جديده|999=رسايل جديده}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|}}{{PLURAL:$1|تعديل|تعديلين|$1 تعديلات|$1 تعديل|$1 تعديل}}',
 'youhavenewmessagesmulti' => 'عندك ميسيدج جديدة فى $1',
 'editsection' => 'تعديل',
 'editold' => 'تعديل',
@@ -571,6 +591,8 @@ $1',
 'toc' => 'المحتويات',
 'showtoc' => 'عرض',
 'hidetoc' => 'تخبية',
+'collapsible-collapse' => 'خبى',
+'collapsible-expand' => 'اتوسع',
 'thisisdeleted' => 'عرض او استرجاع $1؟',
 'viewdeleted' => 'عرض $1؟',
 'restorelink' => '{{PLURAL:$1|تعديل واحد ملغي|تعديلين ملغيين|$1 تعديلات ملغية|$1 تعديل ملغي|$1 تعديل ملغي}}',
@@ -582,6 +604,8 @@ $1',
 'page-rss-feed' => '"$1" ار‌ اس‌ اس فييد',
 'page-atom-feed' => '"$1" فييد أتوم',
 'red-link-title' => '$1 (الصفحه مالهاش وجود)',
+'sort-descending' => 'تنازلى',
+'sort-ascending' => 'تصاعدى',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'صفحه',
@@ -641,8 +665,8 @@ $1',
 'badtitle' => 'عنوان غلط',
 'badtitletext' => 'العنوان المطلوب للصفحه مش موجود او فاضى, او اللينك بين اللغات او بين المشاريع غلط.
 ممكن يكون موجود رمز او اكتر ما ينفع ش يستخدم فى العناوين.',
-'perfcached' => 'البيانات (الـ data) دى معمول لها كاش (cache) و ممكن ما تكونش متحدثه. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.',
-'perfcachedts' => 'البيانات (الـ data) دى معمول لها كاش (cache), و اخر تحديث ليها كان فى $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.',
+'perfcached' => 'البيانات  دى معمول لها كاش (cache) و ممكن ما تكونش متحدثه. 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' => 'التحديثات بتاعة الصفحه دى متعطله دلوقتى.
 البيانات (الـ data) اللى هنا مش ح تتحدث فى الوقت الحاضر.',
 'wrong_wfQuery_params' => 'محددات غلط فى wfQuery()<br />
@@ -651,10 +675,13 @@ $1',
 'viewsource' => 'عرض المصدر',
 'actionthrottled' => 'العمليه دى اتزنقت',
 'actionthrottledtext' => 'علشان نمنع ال سبام ،أنت ممنوع تعمل  الفعل دا عدد كبير من المرات فى فترة زمنية قصيرة، و انت ا تجاوزت  الحد دا . لو سمحت تحاول مرة ثانية بعد دقائق.',
-'protectedpagetext' => 'الصفحة دى اتقفلت فى وش التعديل.',
+'protectedpagetext' => 'الصفحة دى اتحمت من التعديل.',
 'viewsourcetext' => 'ممكن تشوف وتنسخ مصدر  الصفحه دى:',
-'protectedinterface' => 'الصفحة دى هى اللى بتوفر نص الواجهة بتاعة البرنامج،وهى مقفولة لمنع التخريب.',
-'editinginterface' => "'''تحذير''': أنت بتعدل صفحة بتستخدم فى الواجهة النصية  بتاعة البرنامج. التغييرات فى الصفحة دى ها تأثر على مظهر واجهة اليوزر لليوزرز التانيين. للترجمات، لو سمحت استخدم [//translatewiki.net/wiki/Main_Page?setlang=ar بيتاويكى]، مشروع ترجمة الميدياويكى.",
+'protectedinterface' => 'الصفحة دى هى اللى بتوفر نص الواجهة بتاعة البرنامج،وهى مقفولة لمنع التخريب.
+علشان إضافة أو تغيير الترجمات لجميع مشاريع الويكي،  لو سمحت روح على [//translatewiki.net/ translatewiki.net]، مشروع ترجمة ميدياويكى',
+'editinginterface' => "'''تحذير''': أنت بتعدل صفحة بتستخدم فى الواجهة النصية  بتاعة البرنامج. 
+التغييرات فى الصفحة دى ها تأثر على مظهر واجهة اليوزر لليوزرز التانيين. 
+علشان إضافة أو تغيير الترجمات لجميع مشاريع الويكي،  لو سمحت روح على [//translatewiki.net/ translatewiki.net]، مشروع ترجمة ميدياويكى",
 'cascadeprotected' => 'الصفحة دى محمية من التعديل، بسبب انها مدمجة فى {{PLURAL:$1|الصفحة|الصفحات}} دي، اللى مستعمل فيها خاصية "حماية الصفحات المدمجة" :
 $2',
 'namespaceprotected' => "ما عندكش صلاحية تعديل الصفحات  اللى فى نطاق '''$1'''.",
@@ -669,7 +696,7 @@ $2',
 # Login and logout pages
 'logouttext' => "'''أنت دلوقتى مش مسجل دخولك.'''
 
-تقدر تكمل استعمال {{SITENAME}} على انك مجهول، أو <span class='plainlinks'>[$1 الدخول مرة تانيه]</span> بنفس الاسم أو باسم تاني.
+تقدر تكمل استعمال {{SITENAME}} على انك مجهول، أو [[Special:UserLogin|الدخول مرة تانيه]] بنفس الاسم أو باسم تاني.
 ممكن تشوف بعض الصفحات  كأنك متسجل ، و دا علشان استعمال الصفحات المتخبية فى المتصفح بتاعك.",
 'yourname' => 'اليوزرنيم:',
 'yourpassword' => 'الباسوورد:',
@@ -691,7 +718,7 @@ $2',
 'gotaccount' => "عندك حساب؟ '''$1'''.",
 'gotaccountlink' => 'دخول',
 'userlogin-resetlink' => 'نسيت تفاصيل الدخول؟',
-'createaccountmail' => 'بÙ\80 Ø§Ù\84اÙ\8aÙ\85Ù\8aÙ\84',
+'createaccountmail' => 'استخدÙ\85 Ø¨Ø§Ø³Ù\88رد Ù\85ؤÙ\82تÙ\87 Ù\88 Ø¥Ø¨Ø¹ØªÙ\87ا Ø¹ Ø§Ù\84اÙ\8aÙ\85Ù\8aÙ\84 Ø§Ù\84Ù\85حدد Ø¯Ù\87',
 'createaccountreason' => 'السبب:',
 'badretype' => 'كلمتين السر اللى  كتبتهم مش  زى بعضهم',
 'userexists' => 'اسم اليوزر اللى كتبته بيستعمله يوزر غيرك.
@@ -741,7 +768,7 @@ $2',
 'mailerror' => 'غلط فى بعتان الايميل : $1',
 'acct_creation_throttle_hit' => 'الناس اللى دخلت ع الويكى دا باستعمال عنوان الاى بى بتاعك فتحو {{PLURAL:$1|1 حساب|$1 حساب}} ف اليوم اللى فات دا, يعنى وصلو للحد الاقصى المسموح بيه فى الفترة الزمنيه المحدده..
 و عشان كدا, الزوار اللى بيدخلو بعنوان الاى بى دا مش مسموح لهم يفتحو حسابات اكتر فى الوقت الحالى .',
-'emailauthenticated' => 'اتأÙ\83دÙ\86ا Ù\85Ù\86 Ø§Ù\84اÙ\8aÙ\85Ù\8aÙ\84 Ø¨ØªØ§Ø¹Ù\83 Ù\81Ù\89 $2 الساعة $3.',
+'emailauthenticated' => 'اتأÙ\83دÙ\86ا Ù\85Ù\86 Ø§Ù\84اÙ\8aÙ\85Ù\8aÙ\84 Ø¨ØªØ§Ø¹Ù\83 Ù\8aÙ\88Ù\85 $2 الساعة $3.',
 'emailnotauthenticated' => 'لسة ما اتكدناش من الايميل بتاعك.
 مش ح يتبعتلك اى  ايميلات بخصوص الميزات دي.',
 'noemailprefs' => 'علشان الخصايص دى تشتغل لازم تحددلك عنوان ايميل.',
@@ -755,7 +782,7 @@ $2',
 
 لو سمحت تتجاهل الرسالة دى اذا الحساب دا اتفتحلك بالغلط.',
 'usernamehasherror' => 'اسم اليوزر مش ممكن يكون فيه حروف هاش',
-'login-throttled' => 'انت عملت  محاولات لوجين كتيره حديثة على الحساب ده.
+'login-throttled' => 'انت عملت  محاولات لوجين كتيره  ع الحساب ده.
 من فضلك استنى قبل المحاولة مرة تانيه.',
 'loginlanguagelabel' => 'اللغة: $1',
 
@@ -768,7 +795,7 @@ $2',
 'newpassword' => 'الباسورد جديدة:',
 'retypenew' => 'اكتب الباسورد الجديده تانى:',
 'resetpass_submit' => 'اظبط الباسورد و ادخل',
-'changepassword-success' => 'الباسورد بتاعتك اتغيرت بنجاح! دلوقتى  بنسجل دخولك...',
+'changepassword-success' => 'الباسورد بتاعتك اتغيرت بنجاح!',
 'resetpass_forbidden' => 'مش ممكن تغيير الباسورد',
 'resetpass-no-info' => 'لازم تسجل دخولك علشان تقدر توصل للصفحة دى على طول.',
 'resetpass-submit-loggedin' => 'غير الباسورد',
@@ -857,7 +884,7 @@ $2',
 'accmailtitle' => ' كلمة السر اتبعتت .',
 'accmailtext' => "الباسورد العشوائيه اللى اتعملت لـ[[User talk:$1|$1]]  اتبعتت لـ $2.
 
-الباسورد بتاعة الحساب الجديد دا ممكن تتغير فى صفحة ''[[Special:ChangePassword|تغيير الباسورد]]''  وقت تسجيل الدخول.",
+الباسورد بتاعة الحساب الجديد دا ممكن تتغير فى صفحة ''[[Special:ChangePassword|تغيير الباسورد]]''   بعد  تسجيل الدخول.",
 'newarticle' => '(جديد)',
 'newarticletext' => "انت وصلت لصفحه مابتدتش لسه.
 علشان  تبتدى الصفحة ابتدى الكتابه فى الصندوق اللى تحت.
@@ -926,12 +953,12 @@ $2',
 'copyrightwarning2' => "لو سمحت تعمل حسابك ان كل مشاركاتك فى {{SITENAME}} ممكن المشاركين التانيين يعدلوها،يغيروها، او يمسحوها خالص. لو مانتش حابب ان كتاباتك تتعدل و تتغير بالشكل دا، فياريت ما تنشرهاش هنا.<br />.
 و كمان انت بتدينا كلمة شرف  انك صاحب الكتابات دي، او انك نقلتها من مكان مش خاضع لحقوق النشر .(شوف التفاصيل فى $1 ).
 '''لو سمحت ما تحطش هنا اى نص خاضع لحقوق النشر من غير تصريح!'''.",
-'longpageerror' => "'''غلط: النص اللى دخلته حجمه $1 كيلوبايت، ودا أكبر من الحد الأقصى و اللى هو $2 كيلوبايت.
+'longpageerror' => "'''غلط: النص اللى دخلته حجمه $1 كيلوبايت، ودا أكبر من الحد الأقصى و اللى هو {{PLURAL:$2|واحد كيلوبايت|$2 كيلوبايت}}.
 مش ممكن يتحفظ.'''",
-'readonlywarning' => "'''تحذير: قاعدة البيانات اتقفلت للصيانة، و علشان كدا انت مش ح تقدر تحفظ التعديلات اللى عملتها دلوقاي.
+'readonlywarning' => "'''تحذير: قاعدة البيانات اتقفلت للصيانة، و علشان كدا انت مش ح تقدر تحفظ التعديلات اللى عملتها دلواتى.
 لو حبيت ممكن  تنسخ النص وتحفظه فى ملف نصى علشان تستعمله بعدين.'''
 
-الإدارى اللى أغلقها أعطى هذا التفسير: $1",
+الإدارى اللى قفلها كتب السبب دا $1",
 'protectedpagewarning' => "'''تحذير:الصفحة دى اتقفلت بطريقه تخلى اليوزرات السيسوبات هما بس اللى يقدرو يعدلوها.'''
 اخر سجل محطوط تحت علشان المراجعه:",
 'semiprotectedpagewarning' => "'''ملاحظه:''' الصفحه دى اتقفلت بطريقه تخلّى اليوزرات المتسجلين بس هما اللى يقدرو يعدّلوها.
@@ -1031,7 +1058,7 @@ $2',
 حاول [[Special:Search|التدوير فى الويكى]] عن صفحات جديدة ليها صلة.',
 
 # Revision deletion
-'rev-deleted-comment' => '(التعليق اتشال)',
+'rev-deleted-comment' => '( ملخص التعديل اتمسح)',
 'rev-deleted-user' => '(اسم اليوزر اتشال)',
 'rev-deleted-event' => '(السجل إتشال)',
 'rev-deleted-user-contribs' => '[اسم اليوزر أو الآى بى اتشال - التعديل مخفى من المساهمات]',
@@ -1236,8 +1263,6 @@ $1",
 'preferences' => 'تفضيلات',
 'mypreferences' => 'تفضيلاتى',
 'prefs-edits' => 'عدد التعديلات:',
-'prefsnologin' => 'مش متسجل',
-'prefsnologintext' => 'لازم تكون <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} مسجل الدخول]</span> علشان تقدر تعدل تفضيلاتك.',
 'changepassword' => 'غير الباسورد',
 'prefs-skin' => 'الوش',
 'skin-preview' => 'بروفه',
@@ -1504,6 +1529,7 @@ $1",
 'recentchanges-label-minor' => 'ده تعديل صغير',
 'recentchanges-label-bot' => 'التعديل ده عمله بوت',
 'recentchanges-label-unpatrolled' => 'التعديل ده مإتراجعش لسه',
+'recentchanges-legend-newpage' => '$1 - صفحه جديده',
 'rcnote' => "فيه تحت {{PLURAL:$1|'''1''' تغيير|آخر '''$1''' تغيير}} فى آخر {{PLURAL:$2|يوم|'''$2''' يوم}}، بدءا من $5، $4.",
 'rcnotefrom' => "دى التعديلات من '''$2''' (ل '''$1''' معروضه).",
 'rclistfrom' => 'اظهر التعديلات بدايه من $1',
@@ -1525,7 +1551,7 @@ $1",
 'rc_categories' => 'حصر لتصنيفات (مفصولة برمز "|")',
 'rc_categories_any' => 'أى',
 'newsectionsummary' => '/* $1 */ قسم جديد',
-'rc-enhanced-expand' => 'عرض التفاصيل (يتطلب جافاسكريبت)',
+'rc-enhanced-expand' => '[اعرض التفاصيل]',
 'rc-enhanced-hide' => 'إخفاء التفاصيل',
 
 # Recent changes linked
@@ -2286,7 +2312,7 @@ $1',
 'contributions' => 'تعديلات اليوزر {{GENDER:$1|اليوزر|اليوزره}}',
 'contributions-title' => 'مساهمات اليوزر ل$1',
 'mycontris' => 'تعديلاتى',
-'contribsub2' => 'لليوزر $1 ($2)',
+'contribsub2' => 'ل{{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'مالقيناش   تغييرات تطابق المحددات دي.',
 'uctop' => '(آخر تعديل)',
 'month' => 'من شهر (واللى قبل كده):',
@@ -2558,7 +2584,7 @@ $1',
 'allmessagesdefault' => 'النص الاوتوماتيكي',
 'allmessagescurrent' => 'النص دلوقتى',
 'allmessagestext' => 'دى لستة برسايل النظام المتوفرة فى نطاق ميدياويكي.
-لو سمحت تزور[//www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت عايز تساهم فى ترجمة ميدياويكى الاصلية.',
+لو سمحت تزور[https://www.mediawiki.org/wiki/Localisation ترجمة ميدياويكي] و [//translatewiki.net بيتاويكي] لو كنت عايز تساهم فى ترجمة ميدياويكى الاصلية.',
 'allmessagesnotsupportedDB' => "الصفحة دى مش يمكن حد يستعملها علشان'''\$wgUseDatabaseMessages''' متعطل.",
 'allmessages-filter-legend' => 'فيلتر',
 'allmessages-filter' => 'فلتره بحالة التهيئه:',
@@ -2736,6 +2762,8 @@ $1',
 'spambot_username' => 'تنظيف سبام ميدياويكى',
 'spam_reverting' => 'ترجيع آخر نسخة مافيهاش لينكات لـ $1',
 'spam_blanking' => 'كل النسخ فيها لينكات ل $1، فضيها',
+'simpleantispam-label' => "اختبار انتي-سبام.
+'''ماتعبيش''' دا!",
 
 # Skin names
 'skinname-cologneblue' => 'كولون بلو',
@@ -2783,7 +2811,7 @@ $1',
 'file-info-size' => '$1 × $2 بكسل حجم الفايل: $3، نوع MIME: $4',
 'file-nohires' => 'مافيش  ريزوليوشن اعلى متوفر.',
 'svg-long-desc' => 'ملف SVG، اساسا $1 × $2 بكسل، حجم الملف: $3',
-'show-big-image' => 'الصورة بدقه كامله',
+'show-big-image' => 'الصوره الاصليه',
 'file-info-gif-looped' => 'ملفوف',
 'file-info-gif-frames' => '$1 {{PLURAL:$1|برواز|براويز}}',
 
@@ -3105,7 +3133,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'استعمل تطبيق من بره علشان تعدل الملف دا',
-'edit-externally-help' => '(بص على [//www.mediawiki.org/wiki/Manual:External_editors  تعليمات الاعداد] علشان معلومات اكتر.)',
+'edit-externally-help' => '(بص على [https://www.mediawiki.org/wiki/Manual:External_editors  تعليمات الاعداد] علشان معلومات اكتر.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'الكل',
@@ -3342,8 +3370,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'صفح مخصوصه',
-'specialpages-note' => '----
-* صفحات خاصة عادية.
+'specialpages-note' => '* صفحات خاصة عادية.
 * <strong class="mw-specialpagerestricted">صفحات خاصة للناس اللى مسموح لهم.</strong>',
 'specialpages-group-maintenance' => 'تقارير الصيانة',
 'specialpages-group-other' => 'صفحات خاصه تا نيه',
@@ -3419,4 +3446,20 @@ $5
 'searchsuggest-search' => 'تدوير',
 'searchsuggest-containing' => 'جوّاه...',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'تكبير القوالب',
+'expand_templates_intro' => 'الصفحة المخصوصة دى بتاخد بعض النصوص و بتفرد كل القوالب اللى موجودة فيها.
+و كمان بتفرد دوال القوالب زي
+<nowiki>{{</nowiki>#language:…}}, و المتغيرات زي
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;فى الحقيقة كل حاجة بين قوسين مزدوجين.
+و بتعمل دا عن طريق استعداء المعالج المناسب من الميدياويكى نفسها..',
+'expand_templates_title' => 'عنوان السياق, لـ {{FULLPAGENAME}} الخ.:',
+'expand_templates_input' => 'النص المدخل:',
+'expand_templates_output' => 'النتيجه',
+'expand_templates_xml_output' => 'خرج XML',
+'expand_templates_ok' => 'موافق',
+'expand_templates_remove_comments' => 'امسح التعليقات',
+'expand_templates_generate_xml' => 'اعرض شجرة XML',
+'expand_templates_preview' => 'بروفه',
+
 );
index ada0998..342676b 100644 (file)
@@ -75,7 +75,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'ভুল_শিৰোনাম' ),
        'Blankpage'                 => array( 'উকা_পৃষ্ঠা' ),
        'Block'                     => array( 'অৱৰোধ', 'আই_পি_অৱৰোধ', 'সদস্য_অৱৰোধ' ),
-       'Blockme'                   => array( 'মোক_অৱৰোধ_কৰক' ),
        'Booksources'               => array( 'গ্ৰন্থৰ_উত্স' ),
        'BrokenRedirects'           => array( 'ভঙা_পূণঃনিৰ্দেশনাসমূহ' ),
        'Categories'                => array( 'শ্ৰেণীসমূহ' ),
@@ -86,10 +85,10 @@ $specialPageAliases = array(
        'Contributions'             => array( 'বৰঙনিসমূহ', 'বৰঙনিদাতাসকল', 'বৰঙনি' ),
        'CreateAccount'             => array( 'সদস্যভুক্তি' ),
        'DeletedContributions'      => array( 'বিলোপ_কৰা_বৰঙনিসমূহ' ),
-       'Disambiguations'           => array( 'দ্ব্যৰ্থতা_দূৰীকৰণসমূহ' ),
        'DoubleRedirects'           => array( 'দ্বি_পুনৰ্নিৰ্দেশনাসমূহ' ),
        'EditWatchlist'             => array( 'লক্ষ্যতালিকা_সম্পাদনা_কৰক' ),
        'Emailuser'                 => array( 'সদস্যলৈ_ই-মেইল_পঠিয়াওক' ),
+       'ExpandTemplates'           => array( 'সাঁচবোৰ_প্ৰসাৰ_কৰক' ),
        'Export'                    => array( 'ৰপ্তানি' ),
        'Fewestrevisions'           => array( 'নূন্যতম_সংস্কৰণসমূহ' ),
        'FileDuplicateSearch'       => array( 'প্ৰতিলিপি_সনিবিষ্ট_নথি_অনুসন্ধান' ),
@@ -160,7 +159,6 @@ $specialPageAliases = array(
 );
 
 $magicWords = array(
-       'redirect'                  => array( '0', 'পুণঃনিৰ্দেশ', '#REDIRECT' ),
        'special'                   => array( '0', 'বিশেষ', 'special' ),
        'hiddencat'                 => array( '1', '__গোপন_শ্ৰেণী__', '__HIDDENCAT__' ),
        'pagesize'                  => array( '1', 'পৃষ্ঠাৰ_আকাৰ', 'PAGESIZE' ),
@@ -400,7 +398,7 @@ $messages = array(
 'articlepage' => 'সমল পৃষ্ঠা চাওক',
 'talk' => 'আলোচনা',
 'views' => 'দৰ্শন',
-'toolbox' => 'সা-সৰà¦\9eà§\8dà¦\9cাম',
+'toolbox' => 'সà¦\81à¦\9cà§\81লিসমà§\82হ',
 'userpage' => 'সদস্য পৃষ্ঠা চাওক',
 'projectpage' => 'প্ৰকল্প পৃষ্ঠা চাওক',
 'imagepage' => 'নথি পৃষ্ঠা চাওক',
@@ -430,7 +428,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}}ৰ বিষয়ে',
 'aboutpage' => 'Project:ইতিবৃত্ত',
-'copyright' => 'এই বিষয়বস্তু $1 ৰ আওতাত উপলব্ধ।',
+'copyright' => 'à¦\86ন à¦\8fà¦\95à§\8b à¦\89লà§\8dলà§\87à¦\96 à¦¨à¦¾à¦¥à¦¾à¦\95িলà§\87 à¦\8fà¦\87 à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à¦¸à§\8dতà§\81 $1 à§° à¦\86à¦\93তাত à¦\89পলবà§\8dধ।',
 'copyrightpage' => '{{ns:project}}:স্বত্ব',
 'currentevents' => 'সাম্প্ৰতিক ঘটনাৱলী',
 'currentevents-url' => 'Project:শেহতীয়া ঘটনাৱলী',
@@ -456,8 +454,6 @@ $1',
 'ok' => 'ঠিক আছে',
 'retrievedfrom' => '"$1"ৰ পৰা সংকলিত',
 'youhavenewmessages' => 'আপোনাৰ কাৰণে $1 আছে। ($2)',
-'newmessageslink' => 'নতুন সংবাদ',
-'newmessagesdifflink' => 'শেহতীয়া সাল-সলনি',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|আন এজন সদস্য|$3 জন সদস্য}}ৰ পৰা আপোনালৈ $1 আহিছে ($2)।',
 'youhavenewmessagesmanyusers' => 'কেইবাজনো সদস্যৰ পৰা আপোনালৈ $1 আহিছে ($2)।',
 'newmessageslinkplural' => '{{PLURAL:$1|এটা নতুন বাৰ্তা|নতুন বাৰ্তা}}',
@@ -516,6 +512,7 @@ $1',
 'databaseerror-text' => "এটা ডেটাবে'ছ কুৱেৰী ত্ৰুটি হৈছে।
 ইয়ে ছফ্টৱেৰটোত কিবা বাগ্‌ থকাটো সূচাব পাৰে।",
 'databaseerror-textcl' => "এটা ডেটাবে'ছ কুৱেৰী ত্ৰুটি হৈছে।",
+'databaseerror-query' => 'অনুসন্ধান: $1',
 'databaseerror-function' => 'ফাংচন: $1',
 'databaseerror-error' => 'ত্ৰুটি: $1',
 'laggedslavemode' => 'সাৱধানবাণী: ইয়াত সাম্প্ৰতিক সাল-সলনি নাথাকিব পাৰে',
@@ -637,9 +634,11 @@ $2',
 'gotaccount' => "আপুনি সদস্য হয়নে? '''$1'''",
 'gotaccountlink' => 'প্ৰৱেশ',
 'userlogin-resetlink' => 'আপোনাৰ প্ৰৱেশ তথ্য পাহৰিছে?',
-'userlogin-resetpassword-link' => 'à¦\86পà§\8bনাৰ à¦\97à§\81পà§\8dতশবà§\8dদ à¦¨-à¦\95à§\88 à¦¬à¦¹à§\81ৱাà¦\93à¦\95',
+'userlogin-resetpassword-link' => 'à¦\86পà§\8bনাৰ à¦\97à§\81পà§\8dতশবà§\8dদ à¦ªà¦¾à¦¹à§°à¦¿à¦\9bà§\87?',
 'helplogin-url' => 'Help:প্ৰৱেশ/লগ্‌-ইন',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|প্ৰৱেশ সম্পৰ্কীয় সাহায্য]]',
+'userlogin-loggedin' => 'আপুনি ইতিমধ্যে {{GENDER:$1|$1}} হিচাপে প্ৰৱেশ কৰিছে। তলৰ আন সদস্যৰূপে প্ৰৱেশ কৰিবলৈ তলৰ প্ৰপত্ৰ ব্যৱহাৰ কৰক।',
+'userlogin-createanother' => 'আন এটা একাউণ্ট সৃষ্টি কৰক',
 'createacct-join' => 'আপোনাৰ তথ্যসমূহ তলত লিখক।',
 'createacct-another-join' => 'নতুন একাউণ্টৰ তথ্যসমূহ তলত লিখক।',
 'createacct-emailrequired' => 'ই-মেইল ঠিকনা',
@@ -702,16 +701,16 @@ $2',
 'noemailcreate' => 'আপুনি এটা সঠিক ই-মেইল ঠিকনা দিব লাগিব',
 'passwordsent' => '"$1" ৰ ই-মেইল ঠিকনাত নতুন গুপ্তশব্দ এটা পঠোৱা হৈছে। অনুগ্ৰহ কৰি সেয়া পোৱাৰ পাছত পুনৰ প্ৰৱেশ কৰক।',
 'blocked-mailpassword' => 'আপোনাৰ আইপি ঠিকনাৰ পৰা সম্পাদনা কৰা বাৰণ কৰা হৈছে, এনে অৱস্থাত দুৰ্ব্যৱহাৰ ৰোধ কৰিবলৈ গুপ্তশব্দ পুনঃউদ্ধাৰ কৰা সুবিধাতো বাতিল কৰা হৈছে।',
-'eauthentsent' => 'সà¦\9eà§\8dà¦\9aিত à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95নাত à¦¨à¦¿à¦¶à§\8dà¦\9aিতà¦\95ৰণ à¦\87-মà§\87à¦\87ল à¦\8fà¦\96ন à¦ªà¦ à§\8bৱা হৈছে।
-à¦\86ৰà§\81 à¦\85নà§\8dযানà§\8dয à¦\87-মà§\87à¦\87ল à¦ªà¦ à§\8bৱাৰ à¦\86à¦\97তà§\87, à¦\86পà§\8bনাৰ à¦¸à¦¦à¦¸à§\8dযতাৰ নিশ্চিত কৰিবলৈ সেই ই-মেইলত দিয়া নিৰ্দেশনা আপুনি অনু্সৰণ কৰিব লাগিব।',
+'eauthentsent' => 'সà¦\9eà§\8dà¦\9aিত à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95নালà§\88 à¦¨à¦¿à¦¶à§\8dà¦\9aিতà¦\95ৰণ à¦\87-মà§\87à¦\87ল à¦\8fà¦\96ন à¦ªà¦ à¦¿à¦\93ৱা হৈছে।
+à¦\8fà¦\95াà¦\89ণà§\8dà¦\9fà¦\9fà§\8bলà§\88 à¦\86ন à¦\87-মà§\87à¦\87ল à¦ªà¦ à¦¿à¦\93ৱাৰ à¦\86à¦\97তà§\87 à¦\86পà§\8bনাৰ à¦¸à¦¦à¦¸à§\8dযতা নিশ্চিত কৰিবলৈ সেই ই-মেইলত দিয়া নিৰ্দেশনা আপুনি অনু্সৰণ কৰিব লাগিব।',
 'throttled-mailpassword' => "যোৱা {{PLURAL:$1|এঘণ্টাত|$1 ঘণ্টাত}} এখন গুপ্তশব্দ উদ্ধাৰ ইমেইল পঠিওৱা হৈছে।
 অবৈধ ব্যৱহাৰ ৰোধ কৰিবলৈ প্ৰতি {{PLURAL:$1|এঘণ্টাত|$1 ঘণ্টাত}} এবাৰহে গুপ্তশব্দ উদ্ধাৰ ইমেইল পঠিওৱা হ'ব।",
 'mailerror' => 'ই-মেইল পঠিওৱাত সমস্যা হৈছে: $1',
 'acct_creation_throttle_hit' => 'যোৱা ২৪ ঘন্টাত আপোনাৰ আই-পি ঠিকনাৰ পৰা এই ৱিকিৰ পঢ়োঁতাই  {{PLURAL:$1|১-টা একাউন্ট|$1-টা একাউন্ট}} সৃষ্টি কৰিলে, যিটো সৰ্বোচ্চ অনুমোদনকৃত ।
 এতেকে, এই আই-পি ঠিকনাৰ পৰা এই মূহুৰ্তত একাউন্ট সৃষ্টি কৰিব নোৱাৰিব ।',
-'emailauthenticated' => 'আপোনাৰ ই-মেইল ঠিকনাটো $2 তাৰিখৰ $3 বজাত নিশ্চিত কৰা হৈছিল ।',
-'emailnotauthenticated' => 'à¦\86পà§\8bনাৰ à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95নাতà§\8b à¦\8fতিয়ালà§\88 à¦ªà§\8dৰমাণিত à¦¹à§\8bৱা à¦¨à¦¾à¦\87 
-à¦\86পà§\81নি à¦¤à¦²à§° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à§\8bৰৰ à¦\95াৰণà§\87 à¦®à§\87à¦\87ল à¦ªà¦ à¦¾à¦¬ à¦¨à§\8bৱাৰà§\87 ।',
+'emailauthenticated' => 'আপোনাৰ ই-মেইল ঠিকনাটো $2 তাৰিখৰ $3 বজাত নিশ্চিত কৰা হৈছিল।',
+'emailnotauthenticated' => 'à¦\86পà§\8bনাৰ à¦\87-মà§\87à¦\87ল à¦ à¦¿à¦\95নাতà§\8b à¦\8fতিয়ালà§\88 à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦¹à§\8bৱা à¦¨à¦¾à¦\87
+à¦\86পà§\81নি à¦¤à¦²à§° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à§\8bৰৰ à¦\95াৰণà§\87 à¦®à§\87à¦\87ল à¦ªà¦ à¦¿à¦¯à¦¼à¦¾à¦¬ à¦¨à§\8bৱাৰà§\87।',
 'noemailprefs' => 'এই সুবিধাবোৰ ব্যৱহাৰ কৰিবলৈ এটা ই-মেইল ঠিকনা দিয়ক।',
 'emailconfirmlink' => 'আপোনাৰ ই-মেইল ঠিকনাটো প্ৰমাণিত কৰক',
 'invalidemailaddress' => 'এই ই-মেইল ঠিকনাতো গ্ৰহনযোগ্য নহয়, কাৰণ ই অবৈধ প্ৰকাৰৰ যেন লাগিছে।
@@ -760,6 +759,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'গুপ্তশব্দ ন-কৈ বহুৱাওক',
 'passwordreset-text-one' => 'আপোনাৰ গুপ্তশব্দ ন-কৈ বহুৱাবলৈ এই প্ৰপত্ৰ পূৰণ কৰক।',
+'passwordreset-text-many' => '{{PLURAL:$1|আপোনাৰ গুপ্তশব্দ ন-কৈ বহুৱাবলৈ এই তথ্যসমূহৰ যিকোনো এটা দিয়ক।}}',
 'passwordreset-legend' => 'গুপ্তশব্দ ন-কৈ বহাওক',
 'passwordreset-disabled' => 'এই ৱিকিত গুপ্তশব্দ নবীকৰণ নিষ্ক্ৰিয় কৰা হৈছে ।',
 'passwordreset-emaildisabled' => 'এই ৱিকিত ই-মেইল বৈশিষ্টসমূহ নিষ্ক্ৰিয় কৰা হৈছে।',
@@ -799,6 +799,15 @@ $2
 
 # Special:ResetTokens
 'resettokens' => "ট'কেন ৰিছে'ট কৰক",
+'resettokens-text' => "আপোনাৰ একাউণ্টৰ সৈতে জড়িত কিছুমান ব্যক্তিগত তথ্য চাবলৈ আপুনি ট'কেন ৰিছে'ট কৰিব পাৰে।
+
+আপুনি দুৰ্ঘটনাবশতঃ আন কাৰোবাক সেই ট'কেন দিলে বা আপোনাৰ একাউণ্টৰ বিসংগতি হ'লে আপুনি এনে কৰাটো উচিত।",
+'resettokens-no-tokens' => "ৰিছে'ট কৰিবলৈ কোনো ট'কেন নাই।",
+'resettokens-legend' => "ট'কেন ৰিছে'ট কৰক",
+'resettokens-tokens' => "ট'কেনসমূহ:",
+'resettokens-token-label' => '$1 (বর্তমান: $2)',
+'resettokens-done' => "ট'কেন ৰিছে'ট কৰা হ'ল।",
+'resettokens-resetbutton' => "নিৰ্বাচিত ট'কেনসমূহ ৰিছে'ট কৰক",
 
 # Edit page toolbar
 'bold_sample' => 'গাঢ় পাঠ্য',
@@ -876,8 +885,8 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'loginreqlink' => 'প্ৰৱেশ',
 'loginreqpagetext' => 'অন্যান্য পৃষ্ঠা চাবলৈ আপুনি $1 কৰিব লাগিব।',
 'accmailtitle' => "গুপ্তশব্দ পঠোৱা হ'ল।",
-'accmailtext' => "[[User talk:$1|$1]]-ৰ কাৰণে যাদৃচ্ছিক ভাৱে উৎপন্ন কৰা গুপ্তশব্দ $2লৈ পঠোৱা হ'ল । 
-à¦\8fà¦\87 à¦¨à¦¤à§\81ন à¦\8fà¦\95াà¦\89নà§\8dà¦\9fত à¦ªà§\8dৰৱà§\87শ à¦\95ৰি ''[[Special:ChangePassword|à¦\97à§\81পà§\8dতশবà§\8dদ à¦¸à¦²à¦¨à¦¿ à¦\95ৰà¦\95]]'' à¦ªà§\83ষà§\8dঠাà¦\96নত à¦\97à§\81পà§\8dতশবà§\8dদতà§\8b à¦¸à¦²à¦¨à¦¿ à¦\95ৰি à¦²â\80\99ব à¦ªà¦¾à§°à¦¿à¦¬ à¥¤",
+'accmailtext' => "[[User talk:$1|$1]]-ৰ কাৰণে যাদৃচ্ছিকভাৱে উৎপন্ন কৰা গুপ্তশব্দ $2লৈ পঠোৱা হ'ল । 
+এই নতুন একাউন্টত প্ৰৱেশ কৰি ''[[Special:ChangePassword|গুপ্তশব্দ সলনি কৰক]]'' পৃষ্ঠাখনত শব্দতো সলনি কৰি ল’ব পাৰিব ।",
 'newarticle' => '(নতুন)',
 'newarticletext' => "আপুনি বিচৰা প্ৰবন্ধটো বিচাৰি পোৱা নগ'ল।
 
@@ -991,7 +1000,7 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'nocreate-loggedin' => 'নতুন পৃষ্ঠা সৃষ্টি কৰিবলৈ আপোনাৰ অনুমতি নাই ।',
 'sectioneditnotsupported-title' => 'অনুচ্ছেদ সম্পাদনাৰ সমৰ্থন নাই',
 'sectioneditnotsupported-text' => 'এই পৃষ্ঠাত অনুচ্ছেদ সম্পাদনাৰ সমৰ্থন নাই',
-'permissionserrors' => 'à¦\85নà§\81মতি à¦­à§\81লসমà§\82হ',
+'permissionserrors' => 'à¦\85নà§\81মà§\8bদন à¦¤à§\8dৰà§\81à¦\9fি',
 'permissionserrorstext' => "আপোনাৰ এই কামটো কৰিবলৈ অনুমতি নাই, যাৰ {{PLURAL:$1|কাৰণ|কাৰণসমূহ}} হ'ল:",
 'permissionserrorstext-withaction' => "আপোনাৰ $2 কৰিবলৈ অনুমতি নাই, যাৰ {{PLURAL:$1|কাৰণ|কাৰণসমূহ}} হ'ল:",
 'recreate-moveddeleted-warn' => "'''সাৱধান: আগতে বিলোপ কৰা পৃষ্ঠা এটা আপুনি পুনঃনিৰ্মাণ কৰি আছে। '''
@@ -1050,6 +1059,7 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'undo-failure' => "এই সম্পাদনা মধ্যৱৰ্তী সম্পাদনাসমূহৰ দ্বন্দৰ কাৰণে পূৰ্ববৎ কৰা নহ'ব ।",
 'undo-norev' => "এই সম্পাদনাটি ৰদ কৰিব নোৱাৰি, কাৰণ ই আৰু নাই বা ইয়াক বাতিল কৰা হ'ল ।",
 'undo-summary' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|আলোচনা]]) সম্পাদিত $1 সংশোধনটি বাতিল কৰক',
+'undo-summary-username-hidden' => 'এজন গোপন ব্যৱহাৰকাৰীয়ে কৰা $1 সংশোধন বাতিল কৰক',
 
 # Account creation failure
 'cantcreateaccounttitle' => "একাউন্ট সৃষ্টি কৰা নহ'ব",
@@ -1140,17 +1150,17 @@ $3 য়ে আগবঢ়োৱা ইয়াৰ কাৰণ হৈছে
 'revdelete-suppress-text' => "নিবাৰণ '''কেৱল''' তলত দিয়া কাৰণসমূহত ব্যৱহৃত হ’ব:
 * সম্ভাব্য ক্ষতিকাৰক তথ্য 
 * অনুপযুক্ত ব্যক্তিগত তথ্য 
-* : ''à¦\98ৰৰ à¦ à¦¿à¦\95না à¦\86ৰà§\81 à¦\9fà§\87লিফà§\8bন à¦¸à¦\82à¦\96à§\8dযা, à¦¸à¦¾à¦®à¦¾à¦\9cিà¦\95 à¦¸à§\81ৰà¦\95à§\8dষা সংখ্যা, আদি । ''",
+* : ''à¦\98ৰৰ à¦ à¦¿à¦\95না à¦\86ৰà§\81 à¦\9fà§\87লিফà§\8bন à¦¸à¦\82à¦\96à§\8dযা, à§°à¦¾à¦·à§\8dà¦\9fà§\8dৰà§\80য় à¦ªà§°à¦¿à¦\9aয় সংখ্যা, আদি । ''",
 'revdelete-legend' => 'দৃষ্টিপাত সীমাবদ্ধ কৰক',
-'revdelete-hide-text' => 'সংশোধিত পাঠ গোপন কৰক',
+'revdelete-hide-text' => 'সংশোধিত পাঠ',
 'revdelete-hide-image' => 'ফাইলৰ বিষয়বস্তু গোপন কৰক',
 'revdelete-hide-name' => 'কাৰ্য আৰু লক্ষ্য গোপন কৰক',
-'revdelete-hide-comment' => 'সম্পাদনা সাৰাংশ গোপন কৰক',
-'revdelete-hide-user' => 'সম্পাদকৰ সদস্যনাম/আই-পি ঠিকনা গোপন কৰক',
+'revdelete-hide-comment' => 'সম্পাদনা সাৰাংশ',
+'revdelete-hide-user' => 'সম্পাদকৰ সদস্যনাম/আই-পি ঠিকনা',
 'revdelete-hide-restricted' => 'প্ৰশাসকবৃন্দৰ লগতে আনৰ পৰাও তথ্য ৰোধ কৰক',
 'revdelete-radio-same' => '(সলনি নকৰিব)',
-'revdelete-radio-set' => 'হয়',
-'revdelete-radio-unset' => 'নহয়',
+'revdelete-radio-set' => 'à¦\97à§\8bপন',
+'revdelete-radio-unset' => 'দà§\83শà§\8dযমান',
 'revdelete-suppress' => 'প্ৰশাসকবৃন্দৰ লগতে আনৰ পৰাও তথ্য ৰোধ কৰক',
 'revdelete-unsuppress' => 'পুনৰ্স্থাপন কৰা সংশোধনসমূহৰ সীমাবদ্ধতা আতৰাওক',
 'revdelete-log' => 'কাৰণ:',
@@ -1232,6 +1242,7 @@ $1",
 'compareselectedversions' => 'নিৰ্বাচিত কৰা সংকলন সমূহৰ মাজত পাৰ্থক্য চাওক',
 'showhideselectedversions' => 'নিৰ্বাচিত সংশোধনসমূহ দেখুৱাওক/আঁৰ কৰক',
 'editundo' => 'পূৰ্ববত কৰক',
+'diff-empty' => '(কোনো পাৰ্থক্য নাই)',
 'diff-multi' => '({{PLURAL:$2|এজন সদস্যৰ|$2জন সদস্যৰ}} দ্বাৰা {{PLURAL:$1|এটা মধ্যৱৰ্তী সংশোধন|$1-টা মধ্যৱৰ্তী সংশোধন}} দেখোৱা হোৱা নাই)',
 'diff-multi-manyusers' => '({{PLURAL:$2|এজনতকৈ|$2-জনতকৈ}} অধিক সদস্যৰ দ্বাৰা {{PLURAL:$1|এটা মধ্যৱৰ্তী সংশোধন|$1-টা মধ্যৱৰ্তী সংশোধন}} দেখুওৱা হোৱা নাই)',
 'difference-missing-revision' => '{{PLURAL:$2|এটা সংস্কৰণ|$2 সংস্কৰণসমূহৰ}} সংশোধনৰ পাৰ্থক্য  ($1) {{PLURAL:$2| পোৱা নগ’ল}}।
@@ -1309,8 +1320,6 @@ $1",
 'preferences' => 'পছন্দসমূহ',
 'mypreferences' => 'পছন্দসমূহ',
 'prefs-edits' => 'সম্পাদনাৰ সংখ্যা:',
-'prefsnologin' => 'প্ৰৱেশ কৰা নাই',
-'prefsnologintext' => 'আপোনাৰ পছন্দ সলনি কৰিবলৈ হ’লে <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} প্ৰৱেশ]</span> কৰাতো আৱশ্যক।',
 'changepassword' => 'গুপ্তশব্দ সলনি কৰক',
 'prefs-skin' => 'আৱৰণ',
 'skin-preview' => 'খচৰা',
@@ -1335,7 +1344,7 @@ $1",
 'prefs-rendering' => 'ৰূপ',
 'saveprefs' => 'সাঁচি থওক',
 'resetprefs' => 'অসঞ্চিত সাল-সলনি বাতিল কৰক',
-'restoreprefs' => 'সকলো পূৰ্বনিৰ্ধাৰিত ছেটিং ঘূৰাই আনক',
+'restoreprefs' => 'সকলো পূৰ্বনিৰ্ধাৰিত ছেটিং ঘূৰাই আনক (সকলো ছেক্‌শ্যনতে)',
 'prefs-editing' => 'সম্পাদন',
 'rows' => 'পথালী শাৰী:',
 'columns' => 'ঠিয় শাৰী:',
@@ -1347,6 +1356,8 @@ $1",
 'recentchangesdays-max' => 'সৰ্বোচ্চ $1 {{PLURAL:$1|দিন|দিন}}',
 'recentchangescount' => 'শেহতীয়া সাল-সলনি, ইতিহাস আৰু লগ পৃষ্ঠাত দেখুৱাব লগা সম্পাদনাৰ সংখ্যা:',
 'prefs-help-recentchangescount' => 'ইয়াত শেহতীয়া সাল-সলনি, পৃষ্ঠাৰ ইতিহাস আৰু লগ অন্তৰ্ভুক্ত ।',
+'prefs-help-watchlist-token2' => "এইটো আপোনাৰ লক্ষ্য-তালিকাৰ ৱেব্‌ ফীডৰ গোপন চাবি। এইটো জনা লোকে আপোনাৰ লক্ষ্য-তালিকা পঢ়িবলৈ সমৰ্থ হ'ব। গতিকে ইয়াক আনৰ আগত প্ৰকাশ নকৰিব।
+[[Special:ResetTokens|এইটো ৰিছে'ট কৰিবলৈ ইয়াত ক্লিক কৰক।]].",
 'savedprefs' => 'আপোনাৰ পছন্দসমূহ সাঁচি ৰখা হ’ল।',
 'timezonelegend' => 'সময় স্থান:',
 'localtime' => 'স্থানীয় সময়:',
@@ -1391,12 +1402,13 @@ $1",
 'badsig' => 'অনুপযোগী স্বাক্ষ্যৰ, HTML টেগ পৰীক্ষা কৰি লওক।',
 'badsiglength' => 'আপোনাৰ স্বাক্ষৰ অত্যাধিক দীঘলীয়া ।
 আপোনাৰ স্বাক্ষৰ {{PLURAL:$1|এটা আখৰৰ|টা আখৰৰ}} বেছি হ’ব নালাগে ।',
-'yourgender' => 'লিঙ্গ:',
-'gender-unknown' => 'অনিধাৰ্য্য',
-'gender-male' => 'পুৰুষ',
-'gender-female' => 'মহিলা',
-'prefs-help-gender' => 'বৈকল্পিক: ছফ্টৱেৰৰ দ্বাৰা কৰা সম্বোধনৰ লিংগ-শুদ্ধতাৰ বাবে ব্যৱহৃত ।
-এই তথ্য ৰাজহুৱা কৰা হ’ব ।',
+'yourgender' => 'আপুনি কিদৰে নিজৰ বৰ্ণনা দিবলৈ ভাল পাব?',
+'gender-unknown' => "ম‌ই ক'বলৈ বিচৰা নাই",
+'gender-male' => 'তেওঁ (পুৰুষ) ৱিকি পৃষ্ঠা সম্পাদনা কৰে',
+'gender-female' => 'তেওঁ (মহিলা) ৱিকি পৃষ্ঠা সম্পাদনা কৰে',
+'prefs-help-gender' => "এই পছন্দ ছে'ট কৰাটো বৈকল্পিক।
+এই ছফ্টৱেৰে আপোনাক সম্বোধন কৰিবলৈ আৰু আনৰ আগত আপোনাৰ উল্লেখ কৰিবলৈ উপযুক্ত ব্যাকৰণগত লিংগ ব্যৱহাৰ কৰিব পাৰে।
+এই তথ্য ৰাজহুৱা কৰা হ’ব ।",
 'email' => 'ই-মেইল',
 'prefs-help-realname' => 'আপোনাৰ আচল নাম দিয়াতো জৰুৰী নহয়, কিন্তু দিলে আপোনাৰ কামবোৰ আপোনাৰ নামত দেখুওৱা হব।',
 'prefs-help-email' => 'ই-মেইল ঠিকনা দিয়াটো বৈকল্পিক, কিন্তু আপুনি গুপ্তশব্দ পাহৰি গ’লে ন-কৈ বহুৱাবৰ বাবে ই প্ৰয়োজনীয়।',
@@ -1408,7 +1420,9 @@ $1",
 'prefs-signature' => 'স্বাক্ষৰ',
 'prefs-dateformat' => 'তাৰিখ বিন্যাস',
 'prefs-timeoffset' => 'সময় অফচেট',
-'prefs-advancedediting' => 'উচ্চতৰ বিকল্পসমূহ',
+'prefs-advancedediting' => 'সাধাৰণ বিকল্পসমূহ',
+'prefs-editor' => 'সম্পাদক',
+'prefs-preview' => 'প্ৰাক্‌দৰ্শন',
 'prefs-advancedrc' => 'উচ্চতৰ বিকল্পসমূহ',
 'prefs-advancedrendering' => 'উচ্চতৰ বিকল্পসমূহ',
 'prefs-advancedsearchoptions' => 'উচ্চতৰ বিকল্পসমূহ',
@@ -1416,7 +1430,9 @@ $1",
 'prefs-displayrc' => 'প্ৰদৰ্শন বিকল্পসমূহ',
 'prefs-displaysearchoptions' => 'বিকল্পসমূহ প্ৰদৰ্শন কৰক',
 'prefs-displaywatchlist' => 'বিকল্পসমূহ প্ৰদৰ্শন কৰক',
+'prefs-tokenwatchlist' => "ট'কেন",
 'prefs-diffs' => 'পাৰ্থক্য',
+'prefs-help-prefershttps' => "আপোনাৰ পৰৱৰ্তী প্ৰৱেশত এই পছন্দ কাৰ্যকৰী হ'ব।",
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'ই-মেইল ঠিকনাটো সঠিক',
@@ -1440,10 +1456,10 @@ $1",
 'userrights-no-interwiki' => 'আপোনাৰ অন্য ৱিকিত সদস্যৰ অধিকাৰ সম্পাদনা কৰাৰ অনুমতি নাই',
 'userrights-nodatabase' => '$1  তথ্যকোষৰ কোনো অস্তিত্ব নাই অথবা ই স্থানীয় নহয় ।',
 'userrights-nologin' => 'সদস্যৰ অধিকাৰ নিৰূপণ কৰিবলৈ আপুনি কোনো প্ৰশাসকৰ একাউণ্টৰ জৰিয়তে [[Special:UserLogin|প্ৰৱেশ]] কৰিব লাগিব ।',
-'userrights-notallowed' => 'সদসà§\8dযৰ à¦\85ধিà¦\95াৰ à¦¯à§\8bà¦\97 à¦\95ৰিবলà§\88 à¦¬à¦¾ à¦\86à¦\81তৰ à¦\95ৰিবলà§\88 à¦\86পà§\8bনাৰ à¦\8fà¦\95াà¦\89ণà§\8dà¦\9fৰ অনুমতি নাই ।',
+'userrights-notallowed' => 'সদসà§\8dযৰ à¦\85ধিà¦\95াৰ à¦¯à§\8bà¦\97 à¦¬à¦¾ à¦\86à¦\81তৰ à¦\95ৰিবলà§\88 à¦\86পà§\8bনাৰ অনুমতি নাই ।',
 'userrights-changeable-col' => 'আপুনি সলনি কৰিব পৰা গোটসমূহ',
 'userrights-unchangeable-col' => 'আপুনি সলনি কৰিব নোৱাৰা গোটসমূহ',
-'userrights-conflict' => 'সদসà§\8dয à¦\85ধিà¦\95াৰ à¦¦à§\8dবনà§\8dদà§\8dব! à¦\85নà§\81à¦\97à§\8dৰহ à¦\95ৰি à¦\86পà§\8bনাৰ à¦¸à¦¾à¦²à¦¸à¦²à¦¨à¦¿ à¦\86à¦\95à§\8c à¦\8fবাৰ à¦ªà§\8dৰয়à§\8bà¦\97 কৰক।',
+'userrights-conflict' => 'সদসà§\8dয à¦\85ধিà¦\95াৰ à¦¸à¦¾à¦²à¦¸à¦²à¦¨à¦¿à§° à¦¦à§\8dবনà§\8dদà§\8dব! à¦\85নà§\81à¦\97à§\8dৰহ à¦\95ৰি à¦ªà§\81নৰাà¦\87 à¦\9aà¦\95à§\81 à¦«à§\81ৰাà¦\87 à¦\86পà§\8bনাৰ à¦¸à¦¾à¦²à¦¸à¦²à¦¨à¦¿ à¦¨à¦¿à¦¶à§\8dà¦\9aিত কৰক।',
 'userrights-removed-self' => 'আপুনি সফলতাৰে নিজৰ অধিকাৰসমূহ আঁতৰ কৰিলে। গতিকে আপুনি এতিয়া এই পৃষ্ঠা চাব নোৱাৰে।',
 
 # Groups
@@ -1488,7 +1504,7 @@ $1",
 'right-reupload-shared' => 'উমৈহতীয়া মিডিয়া ভঁৰালত থকা ফাইলসমূহ স্থানীয়ভাৱে উপেক্ষা কৰক ।',
 'right-upload_by_url' => "ইউ-আৰ-এলৰ পৰা ফাইল আপল'ড কৰক",
 'right-purge' => 'চাইট কেচৰ পৰা নিশ্চয়তা নোহোৱা পৃষ্ঠা মচি পেলাওক ।',
-'right-autoconfirmed' => 'à¦\85ৰà§\8dদà§\8dধ-সà§\81ৰà¦\95à§\8dষিত à¦ªà§\83ষà§\8dঠা à¦¸à¦®à§\8dপাদনা à¦\95ৰà¦\95',
+'right-autoconfirmed' => 'à¦\86à¦\87-পি à¦­à¦¿à¦¤à§\8dতিà¦\95 à¦\97তি à¦¸à§\80মাৰ à¦¦à§\8dবাৰা à¦ªà§\8dৰভাৱিত à¦¨à¦¹â\80\99ব',
 'right-bot' => 'স্বয়ংক্ৰিয় প্ৰক্ৰিয়া হিচাপে ব্যৱহৃত হওক',
 'right-nominornewtalk' => 'আলোচনা পৃষ্ঠাৰ লঘূ সম্পাদনা হওঁতে নতুন সদস্য বাৰ্তা নালাগে',
 'right-apihighlimits' => 'API প্ৰশ্নৰ বাবে উচ্চতৰ সীমা ব্যৱহাৰ কৰক',
@@ -1509,7 +1525,7 @@ $1",
 'right-ipblock-exempt' => 'আই.পি. প্ৰতিবন্ধক, অট’-প্ৰতিবন্ধক আৰু ৰে’ঞ্জ-প্ৰতিবন্ধক এৰাই চলক',
 'right-proxyunbannable' => 'প্ৰক্সীৰ স্বয়ংক্ৰিয় প্ৰতিবন্ধক এৰাই চলক',
 'right-unblockself' => 'আপোনা-আপুনি খোলা',
-'right-protect' => 'সà§\81ৰà¦\95à§\8dষাৰ à¦®à¦¾à¦¤à§\8dৰা à¦ªà§°à¦¿à§±à§°à§\8dতন à¦\95ৰà¦\95 à¦\86ৰà§\81 সুৰক্ষিত পৃষ্ঠাসমূহ সম্পাদনা কৰক',
+'right-protect' => 'সà§\81ৰà¦\95à§\8dষাৰ à¦¸à§\8dতৰ à¦ªà§°à¦¿à§±à§°à§\8dতন à¦\95ৰà¦\95 à¦\86ৰà§\81 à¦ªà§\8dৰপাতাà¦\95াৰ-সুৰক্ষিত পৃষ্ঠাসমূহ সম্পাদনা কৰক',
 'right-editprotected' => 'সুৰক্ষিত পৃষ্ঠা (কেশ্বকেডিঙ সুৰক্ষাৰ অবিহনে) সম্পাদনা কৰক',
 'right-editinterface' => 'সদস্যৰ ইণ্টাৰফে’চ সম্পাদনা কৰক',
 'right-editusercssjs' => 'আন সদস্যৰ CSS আৰু JavaScript  সম্পাদনা কৰক',
@@ -1612,7 +1628,7 @@ $1",
 'rc_categories_any' => 'যিকোনো',
 'rc-change-size-new' => 'সালসলনিৰ পিছত $1 {{PLURAL:$1|বাইট|বাইট}}',
 'newsectionsummary' => '/* $1 */ নতুন অনুচ্ছেদ',
-'rc-enhanced-expand' => 'সবিশেষ দেখুৱাওক (জাভাস্ক্ৰিপ্টৰ প্ৰয়োজন)',
+'rc-enhanced-expand' => 'সবিশেষ দেখুৱাওক',
 'rc-enhanced-hide' => 'সবিশেষ  লুকুৱাওক',
 'rc-old-title' => 'পূৰ্বে "$1" নামেৰে সৃষ্ট',
 
@@ -1887,6 +1903,8 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization চাওক।",
 'listfiles_size' => 'আকাৰ',
 'listfiles_description' => 'বিৱৰণ',
 'listfiles_count' => 'সংস্কৰণ',
+'listfiles-latestversion-yes' => 'হয়',
+'listfiles-latestversion-no' => 'নহয়',
 
 # File description page
 'file-anchor-link' => 'চিত্ৰ',
@@ -1984,6 +2002,9 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization চাওক।",
 'randompage' => 'যিকোনো পৃষ্ঠা',
 'randompage-nopages' => 'তলত দিয়া {{PLURAL:$2|নামস্থানত|নামস্থানসমূহত}} কোনো পৃষ্ঠা নাই: $1 ।',
 
+# Random page in category
+'randomincategory' => 'শ্ৰেণীৰ যিকোনো পৃষ্ঠা',
+
 # Random redirect
 'randomredirect' => 'অনিৰ্ধাৰিত পুননিৰ্দেশ',
 'randomredirect-nopages' => '"$1" নামস্থানত কোনো পুননিৰ্দেশ নাই ।',
@@ -2517,7 +2538,7 @@ $1',
 'contributions' => '{{GENDER:$1|সদস্যৰ}} বৰঙণিসমূহ',
 'contributions-title' => '$1ৰ বৰঙণিসমূহ',
 'mycontris' => 'বৰঙণিসমূহ',
-'contribsub2' => '$1 ৰ কাৰণে ($2)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2)ৰ কাৰণে',
 'nocontribs' => 'এই গুণসমূহৰ লগত মিল থকা কোনো সালসলনি পোৱা নগ’ল ।',
 'uctop' => '(বৰ্তমান)',
 'month' => 'এই মাহৰ পৰা (আৰু আগৰ):',
@@ -2834,7 +2855,7 @@ $1ৰ অৱৰোধৰ কাৰণ: "$2"',
 'allmessagesdefault' => 'সাধাৰণ বাৰ্তা পাঠ্য',
 'allmessagescurrent' => 'বৰ্তমানৰ বাৰ্তাৰ পাঠ',
 'allmessagestext' => 'মিডিয়াৱিকি নামস্থানত থকা প্ৰণালী বাৰ্তাসমূহৰ তালিকা ইয়াত দিয়া হৈছে ।
-যদি আপুনি মিডিয়াৱিকিৰ স্থানীয়কৰণত আগ্ৰহী, তেন্তে অনুগ্ৰহ কৰি [//www.mediawiki.org/wiki/Localisation মিডিয়াৱিকি স্থানীয়কৰণ] আৰু [//translatewiki.net translatewiki.net] চাওক ।',
+যদি আপুনি মিডিয়াৱিকিৰ স্থানীয়কৰণত আগ্ৰহী, তেন্তে অনুগ্ৰহ কৰি [https://www.mediawiki.org/wiki/Localisation মিডিয়াৱিকি স্থানীয়কৰণ] আৰু [//translatewiki.net translatewiki.net] চাওক ।',
 'allmessagesnotsupportedDB' => "এই পৃষ্ঠা ব্যৱহাৰ কৰিব নোৱাৰি কাৰণ '''\$wgUseDatabaseMessages''' নিষ্ক্ৰিয় কৰা হৈছে ।",
 'allmessages-filter-legend' => 'ছেকনী',
 'allmessages-filter' => 'স্বনিৰ্বাচন অৱস্থাৰে পৰিস্ৰাৱন কৰক:',
@@ -3025,6 +3046,8 @@ $2',
 'spam_reverting' => '$1লৈ সংযোগ নথকা সৰ্বশেষ পুনৰীক্ষনলে উভতাই নিয়া হৈছে',
 'spam_blanking' => 'সকলো পুনৰীক্ষনৰ $1লৈ সংযোগ আছিল, ৰিক্ত কৰা হৈছে',
 'spam_deleting' => 'সকলো পুনৰীক্ষণৰ $1লৈ সংযোগ আছিল, বিলোপ কৰা হৈছে',
+'simpleantispam-label' => "এণ্টি-স্পাম পৰীক্ষা।
+এইখন পূৰণ '''নকৰিব'''!",
 
 # Info page
 'pageinfo-title' => '"$1" ৰ তথ্য',
@@ -3118,7 +3141,7 @@ $1',
 'svg-long-desc' => 'SVG ফাইল, সাধাৰণতঃ $1 × $2 পিক্সেল, ফাইল মাত্ৰা: $3',
 'svg-long-desc-animated' => 'এনিমেটেড SVG ফাইল, সাধাৰণতে $1 × $2 পিক্সেল, ফাইলৰ আকাৰ: $3',
 'svg-long-error' => 'অবৈধ SVG ফাইল: $1',
-'show-big-image' => "সম্পূৰ্ণ ৰিজ'লিউশ্যন",
+'show-big-image' => 'মূল ফাইল',
 'show-big-image-preview' => 'এই খচৰাৰ আকাৰ: $1.',
 'show-big-image-other' => "আন {{PLURAL:$2|ৰিজ'লিউশ্যন|ৰিজ'লিউশ্যনসমূহ}}: $1।",
 'show-big-image-size' => '$1 × $2 পিক্সেল',
@@ -3586,7 +3609,7 @@ Any subsequent links on the same line are considered to be exceptions, i.e. page
 
 # External editor support
 'edit-externally' => 'বাহিৰা আহিলা ব্যৱহাৰ কৰি এই ফাইলটো সম্পাদনা কৰক ।',
-'edit-externally-help' => 'অধিক তথ্যৰ কাৰণে [//www.mediawiki.org/wiki/Manual:External_editors প্ৰস্তুত কৰা নিৰ্দেশনা] চাওক ।',
+'edit-externally-help' => 'অধিক তথ্যৰ কাৰণে [https://www.mediawiki.org/wiki/Manual:External_editors প্ৰস্তুত কৰা নিৰ্দেশনা] চাওক ।',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'সকলো',
@@ -3775,7 +3798,7 @@ $5
 'version-hook-subscribedby' => 'চাবস্ক্ৰাইব কৰিছে',
 'version-version' => '(সংস্কৰণ $1)',
 'version-license' => 'অনুজ্ঞাপত্ৰ',
-'version-poweredby-credits' => "এই ৱিকি '''[//www.mediawiki.org/ মিডিয়াৱিকিৰ]''' দ্বাৰা প্ৰচলিত , কপিৰাইট © ২০০১-$1 $2.",
+'version-poweredby-credits' => "এই ৱিকি '''[https://www.mediawiki.org/ মিডিয়াৱিকিৰ]''' দ্বাৰা প্ৰচলিত , কপিৰাইট © ২০০১-$1 $2.",
 'version-poweredby-others' => 'অন্য',
 'version-credits-summary' => 'আমি নিম্নোক্ত ব্যক্তিসকলক তেওঁলোকে [[Special:Version|মিডিয়াৱিকি]]লৈ দিয়া দিয়া বৰঙনিৰ বাবে চিনাকী  কৰিব বিচাৰিছো।',
 'version-license-info' => "মিডিয়াৱিকি এটা বিনামূলীয়া চফ্টৱেৰ; আপুনি Free Software Foundation -ৰ দ্বাৰা প্ৰকাশিত GNU General Public License -ৰ চুক্তিসমূহৰ অন্তৰ্গত ইয়াক পুনৰ বিতৰণ কৰিব পাৰিব অথবা সলনি কৰিব পাৰিব; হয়তো অনুজ্ঞাপত্ৰৰ সংস্কৰণ ২ 
@@ -3817,8 +3840,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'বিশেষ পৃষ্ঠাসমূহ',
-'specialpages-note' => '----
-* সাধাৰণ বিশেষ পৃষ্ঠাসমূহ।
+'specialpages-note' => '* সাধাৰণ বিশেষ পৃষ্ঠাসমূহ।
 * <span class="mw-specialpagerestricted">সীমাবদ্ধ বিশেষ পৃষ্ঠাসমূহ।</span>
 * <span class="mw-specialpagecached">কেশ্ব কৰা বিশেষ পৃষ্ঠাসমূহ (অপ্ৰচলিতও হ\'ব পাৰে)।</span>',
 'specialpages-group-maintenance' => 'তত্বাৱধানৰ কাৰ্যবিৱৰণীসমূহ',
@@ -3857,7 +3879,10 @@ $5
 'tags-tag' => 'টেগ নাম',
 'tags-display-header' => 'পৰিৱৰ্তন তালিকাসমূহত ৰূপ',
 'tags-description-header' => 'অৰ্থৰ পূৰ্ণ বৰ্ণনা',
+'tags-active-header' => 'সক্ৰিয়?',
 'tags-hitcount-header' => 'টেগকৃত সালসলনি',
+'tags-active-yes' => 'হয়',
+'tags-active-no' => 'নহয়',
 'tags-edit' => 'সম্পাদনা',
 'tags-hitcount' => '$1 {{PLURAL:$1|সাল-সলনি|সাল-সলনিসমূহ}}',
 
@@ -3878,6 +3903,7 @@ $5
 'dberr-problems' => 'দুঃখিত! চাইটটোত কিছু কাৰিকৰী সমস্যা হৈছে ।',
 'dberr-again' => "অলপ সময় অপেক্ষা কৰি পুনৰ আপল'ডৰ চেষ্টা কৰক ।",
 'dberr-info' => '(তথ্যকোষৰ চাৰ্ভাৰৰ লগত যোগাযোগ কৰিব নোৱাৰি: $1)',
+'dberr-info-hidden' => '(তথ্যকোষৰ চাৰ্ভাৰৰ লগত যোগাযোগ কৰিব নোৱাৰি)',
 'dberr-usegoogle' => 'এই পৰিস্থিতিত আপুনি গুগলৰ মাধ্যমেৰে অনুসন্ধান কৰিব পাৰে ।',
 'dberr-outofdate' => "মন কৰক যে, আমাৰ বিষয়বস্তু সম্পৰ্কে তেওঁলোকৰ সূচী পুৰণা হ'ব পাৰে ।",
 'dberr-cachederror' => "এইখন অনুৰোধ কৰা পৃষ্ঠাৰ কেচ্‌ড লিপি, যিখন নবীকৰণ নকৰাও হ'ব পাৰে ।",
@@ -4013,4 +4039,12 @@ $5
 # Image rotation
 'rotate-comment' => 'ছবিখন ঘড়ীৰ কাটাৰ দিশত $1 {{PLURAL:$1|ডিগ্ৰী}} ঘূৰোৱা হৈছে।',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'সাঁচবোৰ বহলাওক',
+'expand_templates_input' => 'পাঠ্য ভৰাওক',
+'expand_templates_output' => 'ফলাফল',
+'expand_templates_ok' => 'ওকে',
+'expand_templates_remove_comments' => 'মন্তব্য গু়চাওক',
+'expand_templates_preview' => 'খচৰা',
+
 );
index 8923642..6d63136 100644 (file)
@@ -337,12 +337,10 @@ $1",
 'ok' => 'Aceutar',
 'retrievedfrom' => 'Sacáu de «$1»',
 'youhavenewmessages' => 'Tienes $1 ($2).',
-'newmessageslink' => 'mensaxes nuevos',
-'newmessagesdifflink' => 'cambéu postreru',
 'youhavenewmessagesfromusers' => "Tienes $1 {{PLURAL:$3|d'otru usuariu|de $3 usuarios}} ($2).",
 'youhavenewmessagesmanyusers' => 'Tienes $1 de munchos usuarios ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un mensaxe nuevu|$1 mensaxes nuevos}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|cambéu postreru|cambeos postreros}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un mensaxe nuevu|999=mensaxes nuevos}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|cambéu postreru|999=cambeos postreros}}',
 'youhavenewmessagesmulti' => 'Tienes mensaxes nuevos en $1',
 'editsection' => 'editar',
 'editold' => 'editar',
@@ -475,7 +473,8 @@ L'alministrador que lu bloquió dio esti motivu: «$3».",
 'invalidtitle-knownnamespace' => "Títulu inválidu col espaciu de nomes «$2» ya'l testu «$3»",
 'invalidtitle-unknownnamespace' => "Títulu inválidu col númberu $1 d'espaciu de nomes desconocíu ya'l testu «$2»",
 'exception-nologin' => 'Nun anició sesión',
-'exception-nologin-text' => "Esta páxina o aición necesita qu'anicies sesión nesta wiki.",
+'exception-nologin-text' => 'Por favor, [[Special:Userlogin|anicie sesión]] pa tener accesu a esta páxina o aición.',
+'exception-nologin-text-manual' => 'Por favor, $1 pa tener accesu a esta páxina o aición.',
 
 # Virus scanner
 'virus-badscanner' => "Fallu de configuración: Escáner de virus desconocíu: ''$1''",
@@ -522,7 +521,7 @@ Nun t'escaezas de camudar les tos [[Special:Preferences|preferencies de {{SITENA
 'gotaccount' => '¿Yá tienes una cuenta? $1.',
 'gotaccountlink' => 'Entrar',
 'userlogin-resetlink' => "¿Escaeció los datos d'accesu?",
-'userlogin-resetpassword-link' => 'Reaniciar la contraseña',
+'userlogin-resetpassword-link' => '¿Escaeció la contraseña?',
 'helplogin-url' => 'Help:Aniciar sesión',
 'userlogin-helplink' => "[[{{MediaWiki:helplogin-url}}|Ayuda p'aniciar sesión]]",
 'userlogin-loggedin' => "Yá anició sesión como {{GENDER:$1|$1}}.
@@ -579,7 +578,7 @@ Vuelvi a intentalo.',
 'passwordtooshort' => 'Les contraseñes han de tener polo menos {{PLURAL:$1|1 caráuter|$1 caráuteres}}.',
 'password-name-match' => "La contraseña tien de ser distinta del nome d'usuariu.",
 'password-login-forbidden' => "Ta torgao usar esti nome d'usuariu y contraseña.",
-'mailmypassword' => 'Unviar la clave nueva per corréu',
+'mailmypassword' => 'Reaniciar contraseña',
 'passwordremindertitle' => 'Nueva contraseña provisional pa {{SITENAME}}',
 'passwordremindertext' => "Daquién (seique tu, dende la direición IP $1) solicitó una contraseña
 nueva pa {{SITENAME}} ($4). Creóse una contraseña provisional
@@ -596,14 +595,14 @@ usando la contraseña antigua.",
 Por favor vuelvi a aniciar sesión depués de recibila.',
 'blocked-mailpassword' => 'Ta bloquiada la edición dende la to direición IP, polo que pa evitar abusos nun se pue usar la función de recuperación de contraseña.',
 'eauthentsent' => "Unvióse un corréu electrónicu de confirmación a la direición indicada.
-Enantes de que s'unvie nengún otru corréu a la cuenta, has de siguir les instrucciones del corréu electrónicu pa confirmar que la cuenta ye de to.",
+Enantes de que s'unvie nengún otru corréu a la cuenta, has de siguir les instrucciones d'esi corréu pa confirmar que la cuenta ye daveres de to.",
 'throttled-mailpassword' => "Yá s'unvió un corréu de reaniciu la clave {{PLURAL:$1|na postrer hora|nes postreres $1 hores}}.
 Pa evitar abusos, namái s'unviará un corréu de reaniciu cada {{PLURAL:$1|hora|$1 hores}}.",
 'mailerror' => 'Fallu al unviar el corréu: $1',
 'acct_creation_throttle_hit' => "Los visitantes d'esta wiki qu'usen la to direición IP yá crearon güei {{PLURAL:$1|1 cuenta|$1 cuentes}}, que ye'l máximu almitíu nesti periodu de tiempu.
 Poro, los visitantes qu'usen esta direición IP nun puen crear más cuentes de momentu.",
-'emailauthenticated' => "La to direición de corréu electrónicu confirmóse'l $2 a les $3.",
-'emailnotauthenticated' => "La to direición de corréu electrónicu inda nun se comprobó.
+'emailauthenticated' => "La so direición de corréu electrónicu confirmóse'l $2 a les $3.",
+'emailnotauthenticated' => "La so direición de corréu electrónicu inda nun se confirmó.
 Nun s'unviará corréu pa nenguna de les funciones siguientes.",
 'noemailprefs' => 'Conseña una direición de corréu electrónicu nes tos preferencies pa que funcionen eses carauterístiques.',
 'emailconfirmlink' => 'Confirmar la direición de corréu electrónicu',
@@ -655,7 +654,7 @@ Seique yá camudaras correutamente la contraseña o que pidieras una nueva contr
 # Special:PasswordReset
 'passwordreset' => 'Reaniciar contraseña',
 'passwordreset-text-one' => 'Complete esti formulariu pa reaniciar la contraseña.',
-'passwordreset-text-many' => '{{PLURAL:$1|Rellene unu de los campos pa reaniciar la contraseña.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Rellene unu de los campos pa recibir una contraseña temporal per corréu.}}',
 'passwordreset-legend' => 'Reaniciar contraseña',
 'passwordreset-disabled' => 'Los reanicios de contraseña tán desactivaos nesta wiki.',
 'passwordreset-emaildisabled' => 'Les funciones de corréu electrónicu tan desactivaes nesta wiki.',
@@ -1048,18 +1047,18 @@ Otros alministradores de {{SITENAME}} van siguir pudiendo acceder al conteníu a
 'revdelete-confirm' => "Confirma que quies facer esto, qu'entiendes les consecuencies, y que vas facer esto d'alcuerdo [[{{MediaWiki:Policy-url}}|cola política]].",
 'revdelete-suppress-text' => "La supresión '''namái''' tendría d'usase nos casos darréu:
 * Información que pudiere ser bilordiosa
-* Información personal non apropiada
-*: ''direiciones de llares y númberos de teléfonu, númberos de seguridá social, etc.''",
+* Información personal inapropiada
+*: ''direiciones de llares y númberos de teléfonu, númberos d'identidá nacional, etc.''",
 'revdelete-legend' => 'Establecer torgues de visibilidá',
-'revdelete-hide-text' => 'Tapecer testu de la revisión',
+'revdelete-hide-text' => 'Testu de la revisión',
 'revdelete-hide-image' => 'Tapecer el conteníu del ficheru',
 'revdelete-hide-name' => 'Tapecer aición y oxetivu',
-'revdelete-hide-comment' => "Tapecer el resume d'edición",
-'revdelete-hide-user' => "Tapecer el nome d'usuariu/IP del editor",
+'revdelete-hide-comment' => "Resume d'edición",
+'revdelete-hide-user' => 'Nome del editor/Direición IP',
 'revdelete-hide-restricted' => "Desaniciar datos de los alministradores y d'otros",
 'revdelete-radio-same' => '(ensin cambeos)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'Non',
+'revdelete-radio-set' => 'Tapecíu',
+'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => "Desaniciar datos de los alministradores igual que d'otros",
 'revdelete-unsuppress' => 'Desaniciar les torgues nes revisiones restauraes',
 'revdelete-log' => 'Motivu:',
@@ -1213,8 +1212,7 @@ Se puen alcontrar más detalles nel [{{fullurl:{{#Special:Log}}/delete|page={{FU
 'preferences' => 'Preferencies',
 'mypreferences' => 'Preferencies',
 'prefs-edits' => "Númberu d'ediciones:",
-'prefsnologin' => 'Nun anició sesión',
-'prefsnologintext' => 'Necesita <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aniciar sesión]</span> pa camudar la configuración d\'usuariu.',
+'prefsnologintext2' => "Por favor, $1 pa configurar les preferencies d'usuariu",
 'changepassword' => 'Camudar la clave',
 'prefs-skin' => 'Apariencia',
 'skin-preview' => 'Vista previa',
@@ -1512,6 +1510,9 @@ Esta información sedrá pública.',
 'recentchanges-label-minor' => 'Esta ye una edición menor',
 'recentchanges-label-bot' => 'Esta edición ta fecha por un bot',
 'recentchanges-label-unpatrolled' => 'Esta edición ta ensin patrullar entá',
+'recentchanges-label-plusminus' => "El tamañu d'esta páxina cambió nesti númberu de bytes",
+'recentchanges-legend-newpage' => '(ver tamién la  [[Special:NewPages|llista de páxines nueves]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Equí embaxo {{PLURAL:$1|pue vese '''1''' cambiu|puen vese los caberos '''$1''' cambios}} {{PLURAL:$2|del caberu día|de los caberos '''$2''' díes}}, a fecha de $5, $4.",
 'rcnotefrom' => "Abaxo tan los cambeos dende '''$2''' (s'amuesen fasta '''$1''').",
 'rclistfrom' => 'Amosar los nuevos cambios dende $1',
@@ -2249,7 +2250,7 @@ Ponte en contautu col editor:
 corréu: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-En casu de producise más cambios, nun habrá más notificaciones a nun ser que visites esta páxina. Tamién podríes reaniciar na to llista de vixilancia los marcadores de notificación de toles páxines que tengas vixilaes.
+En casu de producise más actividá, nun habrá más notificaciones a nun ser que visites esta páxina teniendo sesión aniciada. Tamién podríes reaniciar na to llista de vixilancia los marcadores de notificación de toles páxines que tengas vixilaes.
 
 El to abertable sistema de notificación de {{SITENAME}}
 
@@ -2769,7 +2770,7 @@ Por último, tamién pues usar un enllaz: p.e. [[{{#Special:Export}}/{{MediaWiki
 'allmessagesdefault' => 'Testu predetermináu',
 'allmessagescurrent' => 'Testu actual',
 'allmessagestext' => 'Esta ye una llista de los mensaxes de sistema disponibles nel espaciu de nomes de MediaWiki.
-Por favor visita [//www.mediawiki.org/wiki/Localisation Llocalización de MediaWiki] y [//translatewiki.net translatewiki.net] si quies contribuyer a la llocalización xenérica de MediaWiki.',
+Por favor visita [https://www.mediawiki.org/wiki/Localisation Llocalización de MediaWiki] y [//translatewiki.net translatewiki.net] si quies contribuyer a la llocalización xenérica de MediaWiki.',
 'allmessagesnotsupportedDB' => "Nun pue usase '''{{ns:special}}:Allmessages''' porque '''\$wgUseDatabaseMessages''' ta deshabilitáu.",
 'allmessages-filter-legend' => 'Peñerar',
 'allmessages-filter' => 'Peñerar por estáu de personalización:',
@@ -2932,6 +2933,7 @@ Pues ver el so códigu fonte.',
 'tooltip-undo' => '"Esfacer" revierte esta edición y abre\'l formulariu d\'edición en mou de vista previa. Permite añader un motivu nel resume.',
 'tooltip-preferences-save' => 'Guardar les preferencies',
 'tooltip-summary' => 'Escribi un resume curtiu',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => "/* Los CSS allugaos equí s'aplicarán a tolos aspeutos */",
@@ -2981,6 +2983,8 @@ Probablemente tea causao por un enllaz a un sitiu esternu de la llista prieta.',
 'spam_reverting' => 'Revirtiendo a la cabera versión que nun contién enllaces a $1',
 'spam_blanking' => 'Toles revisiones teníen enllaces a $1; dexando en blanco',
 'spam_deleting' => 'Toles revisiones teníen enllaces a $1, desaniciando',
+'simpleantispam-label' => "Comprobación anti-spam.
+¡'''NUN''' rellenes esto!",
 
 # Info page
 'pageinfo-title' => 'Información sobro "$1"',
@@ -2994,6 +2998,7 @@ Probablemente tea causao por un enllaz a un sitiu esternu de la llista prieta.',
 'pageinfo-length' => 'Llonxitú de la páxina (en bytes)',
 'pageinfo-article-id' => 'ID de la páxina',
 'pageinfo-language' => 'Llingua del conteníu de la páxina',
+'pageinfo-content-model' => 'Plantía del conteníu de la páxina',
 'pageinfo-robot-policy' => 'Indexación por robots',
 'pageinfo-robot-index' => 'Permitío',
 'pageinfo-robot-noindex' => 'Torgao',
@@ -3078,7 +3083,7 @@ Al executalu pues comprometer el to sistema.",
 'svg-long-desc' => 'ficheru SVG, $1 × $2 píxels nominales, tamañu de ficheru: $3',
 'svg-long-desc-animated' => 'Ficheru SVG animáu; nominalmente de $1 × $2 pixels; tamañu del ficheru: $3',
 'svg-long-error' => 'Ficheru SVG inválidu: $1',
-'show-big-image' => 'Resolución completa',
+'show-big-image' => 'Ficheru orixinal',
 'show-big-image-preview' => "Tamañu d'esta previsualización: $1.",
 'show-big-image-other' => '{{PLURAL:$2|Otra resolución|Otres resoluciones}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3550,7 +3555,7 @@ Los demás tarán anubríos de mou predetermináu.
 
 # External editor support
 'edit-externally' => 'Editar esti ficheru usando una aplicación esterna',
-'edit-externally-help' => '(Pa más información ver les [//www.mediawiki.org/wiki/Manual:External_editors instrucciones de configuración])',
+'edit-externally-help' => '(Pa más información ver les [https://www.mediawiki.org/wiki/Manual:External_editors instrucciones de configuración])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'too',
@@ -3650,6 +3655,9 @@ Por favor confirma que daveres quies volver a crear esta páxina.",
 'confirm-unwatch-button' => 'Aceutar',
 'confirm-unwatch-top' => '¿Desaniciar esta páxina de la to llista de vixilancia?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '«$1»',
+
 # Multipage image navigation
 'imgmultipageprev' => '← páxina anterior',
 'imgmultipagenext' => 'páxina siguiente →',
@@ -3737,7 +3745,7 @@ Tamién pues [[Special:EditWatchlist|usar l'editor estándar]].",
 'version-hook-subscribedby' => 'Suscritu por',
 'version-version' => '(Versión $1)',
 'version-license' => 'Llicencia',
-'version-poweredby-credits' => "Esta wiki funciona con '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Esta wiki funciona con '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'otros',
 'version-poweredby-translators' => 'los traductores de translatewiki.net',
 'version-credits-summary' => 'Nos prestaría dar reconocimientu a les siguientes persones pola so contribución a [[Special:Version|MediaWiki]].',
@@ -3756,7 +3764,7 @@ Tendría d'haber recibío [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia de la Llic
 # Special:Redirect
 'redirect' => "Redireición por nome de ficheru, o ID d'usuariu o de revisión",
 'redirect-legend' => 'Redirixir a un ficheru o una páxina',
-'redirect-summary' => "Esta páxina especial redirixe a un ficheru (dando'l nome), una páxina (dando una ID de revisión) o una páxina d'usuariu (dando una ID d'usuariu).",
+'redirect-summary' => "Esta páxina especial redirixe a un ficheru (dando'l so nome), una páxina (dando una ID de revisión) o una páxina d'usuariu (dando un númberu d'ID d'usuariu). Usu: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], o [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Dir',
 'redirect-lookup' => 'Buscar:',
 'redirect-value' => 'Valor:',
@@ -3778,10 +3786,9 @@ Tendría d'haber recibío [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia de la Llic
 
 # Special:SpecialPages
 'specialpages' => 'Páxines especiales',
-'specialpages-note' => '----
-* Páxines especiales normales.
-* <span class="mw-specialpagerestricted">Páxines especiales restrinxíes.</span>
-* <span class="mw-specialpagecached">Páxines especiales en caché (seique nun tean actualizaes).</span>',
+'specialpages-note-top' => 'Lleenda',
+'specialpages-note' => '* Páxines especiales normales.
+* <span class="mw-specialpagerestricted">Páxines especiales restrinxíes.</span>',
 'specialpages-group-maintenance' => 'Informes de mantenimientu',
 'specialpages-group-other' => 'Otres páxines especiales',
 'specialpages-group-login' => 'Entrar / crear cuenta',
@@ -3994,4 +4001,21 @@ D\'otra miente, pues usar el formulariu cenciellu d\'abaxo. El to comentariu apa
 'limitreport-expansiondepth' => "Máxima fondura d'espansión",
 'limitreport-expensivefunctioncount' => "Cuenta de funciones d'analís costoses",
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Esparder plantíes',
+'expand_templates_intro' => "Esta páxina especial toma un testu y espande toles plantíes del mesmu de forma recursiva.
+ Tamién espande les funciones d'análisis sintáuticu como
+<code><nowiki>{{</nowiki>#language:...}}</code>, y variables como
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+En realidá cuasi tolo qu'apaeza ente llaves dobles.",
+'expand_templates_title' => 'Títulu del contestu, pa {{FULLPAGENAME}}, etc.:',
+'expand_templates_input' => "Testu d'entrada:",
+'expand_templates_output' => 'Resultáu',
+'expand_templates_xml_output' => 'Salida XML',
+'expand_templates_ok' => 'Aceutar',
+'expand_templates_remove_comments' => 'Eliminar comentarios',
+'expand_templates_remove_nowiki' => 'Quitar les etiquetes <nowiki> nos resultaos',
+'expand_templates_generate_xml' => "Amosar l'árbole d'análisis sintáuticu XML",
+'expand_templates_preview' => 'Vista previa',
+
 );
index 3259115..b12e4f2 100644 (file)
@@ -329,8 +329,6 @@ $messages = array(
 'ok' => 'Tuenara',
 'retrievedfrom' => 'Dimnarin mal « $1 »',
 'youhavenewmessages' => 'Va $1 ($2) al kazawal.',
-'newmessageslink' => 'warzafa staksa',
-'newmessagesdifflink' => 'amid- gu ironokaf siatos',
 'youhavenewmessagesmulti' => 'Rin dil va warzafa staksa moe $1',
 'editsection' => 'betara',
 'editold' => 'betara',
@@ -854,8 +852,6 @@ Kan ''all:'' laganeyal ta varafa exulera (gon keyaksexo is teza ikz-), oke wetce
 'preferences' => 'Lodamaceem',
 'mypreferences' => 'Jinaf lodamaceem',
 'prefs-edits' => 'Ota va betaks :',
-'prefsnologin' => 'Dogluyariskaf',
-'prefsnologintext' => 'Ede va favesiklodamaceem djubetal, gotil <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} dogluyarakiraf]</span>.',
 'changepassword' => 'Betara va remravlem',
 'prefs-skin' => 'Laviuca',
 'skin-preview' => 'Abdiwira',
@@ -1810,7 +1806,7 @@ bu ika int me zo rotarrundar.',
 'allmessagescurrent' => 'Noelaf krent',
 'allmessagestext' => 'Batcoba tir vexala dem bolkstakseem koe MediaWiki yoltxo.
 
-Va [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] is [//translatewiki.net translatewiki.net] vay woral ede va tulizukara va Mediawiki co-rowebel.',
+Va [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] is [//translatewiki.net translatewiki.net] vay woral ede va tulizukara va Mediawiki co-rowebel.',
 'allmessagesnotsupportedDB' => "Batu bu me zo rofaver kire '''\$wgUseDatabaseMessages''' mea tir tegis.",
 
 # Thumbnails
@@ -2192,7 +2188,7 @@ Kotari milconyafi gluyasiki roklon zo krafiar.',
 
 # External editor support
 'edit-externally' => 'Betara va bat iyeltak faveson va divef talpey',
-'edit-externally-help' => '(Ta lo giva va [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] disukel !)',
+'edit-externally-help' => '(Ta lo giva va [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] disukel !)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kot',
index 7b345b3..4a96329 100644 (file)
@@ -17,6 +17,7 @@
  * @author Gulmammad
  * @author Kaganer
  * @author Khan27
+ * @author Mushviq Abdulla
  * @author PPerviz
  * @author PrinceValiant
  * @author Sortilegus
@@ -123,6 +124,8 @@ $messages = array(
 'tog-diffonly' => 'Versiyaların müqayisəsi zamanı səhifənin məzmununu göstərmə',
 'tog-showhiddencats' => 'Gizli kateqoriyaları göstər',
 'tog-norollbackdiff' => 'Geri qaytardıqdan sonra, edilmiş dəyişikikləri dəyişikliklər siyahısından sil',
+'tog-useeditwarning' => 'Qeyd edilməmiş dəyişikliyə sahib bir dəyişiklik səhifəsindən çıxarkən məni xəbərdar et',
+'tog-prefershttps' => 'Sessiya aaçarkən hər zaman etibarlı bağlantıdan istifadə et.',
 
 'underline-always' => 'Həmişə',
 'underline-never' => 'Heç vaxt',
@@ -186,6 +189,18 @@ $messages = array(
 'oct' => 'Oktyabr',
 'nov' => 'Noyabr',
 'dec' => 'Dekabr',
+'january-date' => '$1 Yanvar',
+'february-date' => '$1 Fevral',
+'march-date' => '$1 Mart',
+'april-date' => '$1 Aprel',
+'may-date' => '$1 May',
+'june-date' => '$1 İyun',
+'july-date' => '$1 İyul',
+'august-date' => '$1 Avqust',
+'september-date' => ' $1 Sentyabr',
+'october-date' => '$1 Oktyabr',
+'november-date' => '$1 Noyabr',
+'december-date' => '$1 Dekabr',
 
 # Categories related messages
 'pagecategories' => '$1 {{PLURAL:$1|Kateqoriya|Kateqoriya}}',
@@ -206,13 +221,12 @@ $messages = array(
 'noindex-category' => 'İndeksləşdirilməyən səhifələr',
 'broken-file-category' => 'İşləməyən fayl keçidləri olan səhifələr',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Haqqında',
 'article' => 'Mündəricat',
 'newwindow' => '(yeni pəncərədə açılır)',
 'cancel' => 'Ləğv et',
 'moredotdotdot' => 'Daha...',
+'morenotlisted' => 'Bu siyahı tam deyil.',
 'mypage' => 'Mənim səhifəm',
 'mytalk' => 'Danışıqlarım',
 'anontalk' => 'Bu IP-yə aid müzakirə',
@@ -268,6 +282,7 @@ $messages = array(
 'create-this-page' => 'Bu səhifəni yarat',
 'delete' => 'Sil',
 'deletethispage' => 'Bu səhifəni sil',
+'undeletethispage' => 'Bu səhifənin silmə əməliyyatını geri qaytar',
 'undelete_short' => '$1 {{PLURAL:$1|dəyişikliyi|dəyişiklikləri}} bərpa et',
 'viewdeleted_short' => '{{PLURAL:$1|bir silinmiş redaktəyə|$1 silinmiş redaktəyə}}',
 'protect' => 'Mühafizə et',
@@ -343,8 +358,10 @@ Bax: [[Special:Version|Versiyalar]].',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Mənbə — "$1"',
 'youhavenewmessages' => 'Hal-hazırda $1 var. ($2)',
-'newmessageslink' => 'yeni ismarıclar',
-'newmessagesdifflink' => 'Sonuncu və əvvəlki versiya arasındakı fərq',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başqa bir istifadəçidən|$3 istifadəçidən}} $1 var ($2).',
+'youhavenewmessagesmanyusers' => 'Bir çox istifadəçidən $1 var ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|yeni mesajınız|yeni mesajlarınız}}',
+'newmessagesdifflinkplural' => 'son {{PLURAL:$1|dəyişiklik|dəyişikliklər}}',
 'youhavenewmessagesmulti' => '"$1"da yeni mesajınız var.',
 'editsection' => 'redaktə',
 'editold' => 'redaktə',
@@ -398,6 +415,12 @@ Mövcud xüsusi səhifələrin siyahısı: [[Special:SpecialPages|Xüsusi səhif
 # General errors
 'error' => 'Xəta',
 'databaseerror' => 'Verilənlər bazası xətası',
+'databaseerror-text' => 'Bir verilənlər bazası sorğu xətası baş verdi.
+Bu proqramdan qaynaqlanan bir xətanı göstərmiş ola bilər.',
+'databaseerror-textcl' => 'Bir verilənlər bazası sorğu xətası baş verdi.',
+'databaseerror-query' => 'Sorğu: $1',
+'databaseerror-function' => 'Funksiya: $1',
+'databaseerror-error' => 'Xəta: $1',
 'laggedslavemode' => "'''Xəbərdarlıq:''' Səhifə son əlavələri əks etdirməyə bilər.",
 'readonly' => 'Verilənlər bazası bloklanıb',
 'enterlockreason' => 'Bloklamanın səbəbini və nəzərdə tutulan müddətini qeyd edin',
@@ -428,6 +451,9 @@ Xahiş edirik bunu bir [[Special:ListUsers/sysop|İdarəçilərə]], URL not ed
 'cannotdelete' => 'İstədiyiniz "$1" səhifə və ya faylını silmək mümkün deyil.
 Bu səhifə və ya fayl başqa bir istifadəçi tərəfindən silinmiş ola bilər.',
 'cannotdelete-title' => '"$1" səhifəsinin silinməsi mümkünsüzdür.',
+'delete-hook-aborted' => 'Silmə əməliyyatı qarmaq tərəfindən dayandırıldı. 
+Heç bir açıqlama edilmədi.',
+'no-null-revision' => '"$1" səhifəsi üçün yeni boş bir versiya yaradıla bilmədi',
 'badtitle' => 'Səhv başlıq',
 'badtitletext' => 'Axtarılan səhifə adı səhvdir və ya boşdur, ya da düzgün olmayan dillərarası, yaxud vikilərarası keçid istifadə edilib.
 Başlıqlarda istifadə edilməsi qadağan olunan bir və ya daha çox simvol istifadə edilmiş ola bilər.',
@@ -443,6 +469,7 @@ Sorğu: $2',
 'actionthrottledtext' => 'Anti-spam hərəkətləri səbəbilə, bir hərəkəti qısa bir zaman aralığında çoxetməniz əngəlləndi, və siz həddi aşmısınız. Lütfən bir neçə dəqiqə sonra yenidən yoxlayın.',
 'protectedpagetext' => 'Bu səhifə redaktə üçün bağlıdır.',
 'viewsourcetext' => 'Siz bu səhifənin məzmununu görə və köçürə bilərsiniz:',
+'viewyourtext' => "Bu səhifəyə '''etdiyiniz dəyişikliklərin''' mənbəyini görüntüləyib köçürə bilərsiniz:",
 'protectedinterface' => 'Bu səhifədə proqram təminatı üçün sistem məlumatları var və sui-istifadənin qarşısını almaq üçün mühafizə olunmalıdır.',
 'editinginterface' => "'''Diqqət!''' Siz proqram təminatı interfeysinin mətn olan səhifəsini redaktə edirsiniz.
 Onun dəyişdirilməsi digər istifadəçilərin interfeysinin xarici görünüşünə təsir göstərir.
@@ -450,9 +477,23 @@ Tərcümə üçün daha yaxşı olar ki, MediaWiki-nin lokallaşması üçün ol
 'cascadeprotected' => 'Səhifə mühafizə olunub, çünki o kaskad mühafizə olunan {{PLURAL:$1|növbəti səhifəyə|növbəti səhifələrə}} qoşulub:
 $2',
 'namespaceprotected' => 'Sizin adlarında $1 olan məqalələrdə redaktə etməyə icazəniz yoxdur.',
+'customcssprotected' => 'Bu səhifəni redaktə etmə izniniz yoxdur, çünki bu səhifə başqa bir istifadəçinin fərdi parametrlərinə sahibdir.',
+'customjsprotected' => 'Bu Java Script səhifəsini redaktə etmə izniniz yoxdur, çünki bu səhifə başqa bir istifadəçinin fərdi parametrlərinə sahibdir.',
+'mycustomcssprotected' => 'Bu CSS ssəhifəsini redaktə etmə izniniz yoxdur.',
+'mycustomjsprotected' => 'Bu JavaScript səhifəsini redaktə etmə izniniz yoxdur.',
+'myprivateinfoprotected' => 'Sizin özəl məlumatlarınızı redaktə etmə izniniz yoxdur.',
+'mypreferencesprotected' => 'Seçimlərinizi redaktə etmək üçün izniniz yoxdur.',
 'ns-specialprotected' => 'Xüsusi səhifələr redaktə oluna bilməz.',
 'titleprotected' => 'Bu adda səhifənin yaradılması istifadəçi [[User:$1|$1]] tərəfindən qadağan edilmişdir.
 Göstərilən səbəb: "\'\'$2\'\'".',
+'filereadonlyerror' => '"$2" fayl deposundakı "$1" faylı ancaq oxunula bilən rejimdə olduğuna görə dəyişdirmək üçün açıla bimir.
+
+Rejimi qoyan nəzarətçinin izahı: "$3".',
+'invalidtitle-knownnamespace' => '"$2" sahə adı üçün "$3" mətni keçərsiz bir başlıq',
+'invalidtitle-unknownnamespace' => 'Naməlum $1 ad sahəsi miqdarı və keçərsiz "$2" başlıq',
+'exception-nologin' => 'Giriş edilməmişdir',
+'exception-nologin-text' => 'Bu səhifəyə daxi olmaq üçün [[Special:Userlogin|özünüzü təqdim]], edin.',
+'exception-nologin-text-manual' => ' bu səhifəyə və ya hərəkətə daxil olmaq üçün $1 lazımdır.',
 
 # Virus scanner
 'virus-badscanner' => "Düzgün olmayan konfiqurasiya: naməlum ''$1'' virus yoxlayanı",
@@ -467,9 +508,19 @@ Siz {{SITENAME}} saytını anonim olaraq istifadə etməyə davam edə bilər v
 'welcomecreation-msg' => 'Hesabınız yaradıldı.
 [[Special:Preferences|{{SITENAME}} nizamlamalarınızı]] dəyişdirməyi unutmayın.',
 'yourname' => 'İstifadəçi adı',
+'userlogin-yourname' => 'İstifadəçi adı',
+'userlogin-yourname-ph' => 'İstifadəçi adınızı daxil edin',
+'createacct-another-username-ph' => 'İstifadəçi adınızı daxil edin:',
 'yourpassword' => 'Parol:',
+'userlogin-yourpassword' => 'Parol',
+'userlogin-yourpassword-ph' => 'Parolunuzu daxil edin',
+'createacct-yourpassword-ph' => 'Parol daxil edin',
 'yourpasswordagain' => 'Parolu təkrar yazın:',
+'createacct-yourpasswordagain' => 'Parolu təsdiqlə',
+'createacct-yourpasswordagain-ph' => 'Parolu təkrar daxil edin',
 'remembermypassword' => 'Məni bu kompyuterdə xatırla (maksimum $1 {{PLURAL:$1|gün|gün}})',
+'userlogin-remembermypassword' => 'Sistemdə qal',
+'userlogin-signwithsecure' => 'Etibarlı bağlantıdan istifadə edin',
 'yourdomainname' => 'Sizin domain',
 'password-change-forbidden' => 'Bu vikidə parolunuzu dəyişdirə bilməzsiniz.',
 'externaldberror' => 'Verilənlər bazasının doğruluğunu yoxlamada xəta baş verib və yaxud sizin xarici istifadəçi qeydiyyatını yeniləmək hüququnuz yoxdur.',
@@ -481,18 +532,44 @@ Siz {{SITENAME}} saytını anonim olaraq istifadə etməyə davam edə bilər v
 'logout' => 'Çıxış',
 'userlogout' => 'Çıxış',
 'notloggedin' => 'Daxil olmamısınız',
+'userlogin-noaccount' => 'İstifadəçi hesabınız yoxdur?',
+'userlogin-joinproject' => '{{SITENAME}} qoşulun',
 'nologin' => "İstifadəçi hesabınız yoxdur? '''$1'''.",
 'nologinlink' => 'hesab açın',
 'createaccount' => 'Hesab aç',
 'gotaccount' => "Giriş hesabınız varsa '''$1'''.",
 'gotaccountlink' => 'Daxil olun',
 'userlogin-resetlink' => 'Daxilolma məlumatlarınızı unutmusunuz?',
-'createaccountmail' => 'e-məktub ilə',
+'userlogin-resetpassword-link' => 'Parolu unutdunuzmu?',
+'helplogin-url' => 'Help:Sistemə daxil ol',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|daxil olma haqqında yardım alın]]',
+'userlogin-loggedin' => 'Siz artıq {{GENDER:$1|$1}} kimi daxil olmusunuz.
+Aşağıdakı formadan istifadə edərək, bağqa bir istifadəçi kimi daxil ola bilərsiniz.',
+'userlogin-createanother' => 'Başqa bir istifadəçi hesabı yarat',
+'createacct-join' => 'Aşağıda məlumatlarınızı daxil edin.',
+'createacct-another-join' => 'Aşağıda yeni hesabınızın məlumatlarını daxil edin.',
+'createacct-emailrequired' => 'E-poçt ünvanı',
+'createacct-emailoptional' => 'E-poçt ünvanı (istəyə bağlı)',
+'createacct-email-ph' => 'E-poçt ünvanınızı daxil edin',
+'createacct-another-email-ph' => 'E-poçt ünvanını daxil edin',
+'createaccountmail' => 'Müvəqqəti təsadüfi bir paroldan istifadə edə bilər və bu parolu göstərilən e-poçt ünvanına göndərə bilərsiniz',
+'createacct-realname' => 'Gərçək adı (istəyə bağlı)',
 'createaccountreason' => 'Səbəb:',
+'createacct-reason' => 'Səbəb',
+'createacct-reason-ph' => 'Niyə başqa bir hesab yaradırsınız',
+'createacct-captcha' => 'Təhlükəsizlik nəzarəti',
+'createacct-imgcaptcha-ph' => 'Yuxarıda gördüyünüz mətni daxil edin',
+'createacct-submit' => 'İstifadəçi hesabı yarat',
+'createacct-another-submit' => 'Başqa bir istifadəçi hesabı yarat',
+'createacct-benefit-heading' => '{{SITENAME}} sizin kimi insanlar tərəfindən yaradılır.',
+'createacct-benefit-body1' => '$1 {{PLURAL:$1|redaktə}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|səhifə|səhifə}}',
+'createacct-benefit-body3' => 'ən son {{PLURAL:$1|iştirakçılar|iştirakçılar}}',
 'badretype' => 'Daxil etdiyiniz parol uyğun gəlmir.',
 'userexists' => 'Daxil edilmiş ad artıq istifadədədir.
 Lütfən başqa ad seçin.',
 'loginerror' => 'Daxil olma xətası',
+'createacct-error' => 'Hesab yaratma xətası',
 'createaccounterror' => 'Bu istifadəçi adını yaratmaq mümkün olmadı: $1',
 'nocookiesnew' => 'İstifadəçi qeydiyyatı yaradıldı, lakin daxil ola bilmədiniz.
 {{SITENAME}} iştirakçıların təqdim olunması üçün "cookie"lərdən istifadə edir.
@@ -519,11 +596,17 @@ Düzgün yazdığına əmin ol.',
 'password-login-forbidden' => 'Bu istifadəçi adından və paroldan istifadə qadağan olunub.',
 'mailmypassword' => 'E-mail ilə yeni parol göndər',
 'passwordremindertitle' => '{{SITENAME}} parol xatırladıcı',
+'passwordremindertext' => 'Birisi (yəqin ki siz, $1 IP ünvanından) {{SITENAME}} ($4) üçün yeni bir parol göndərilməsini istədi. "$2" istifadəçisinə müvəqqəti olaraq "$3" parolu yaradıldı. Əgər bu sizin istyinizdirsə, hesab açıb yeni bir parol yaratmağınız vacibdir. Müvəqqəti parolunuzun müddəti {{PLURAL:$5|1 gün|$5 gün}} içində dolacaqdır.
+
+Parol dəyişdirməni siz istəməmisinizsə və ya parolunuzu xatırladınızsa və artıq parolunuzu dəyişdirmək isteəmirsinizsə; bu mesaja əhəmiyyət vermədən əski parolunuzdan istifadə etməyə davam edə bilərsiniz.',
 'noemail' => '"$1" adlı istifadəçi e-poçt ünvanını qeyd etməmişdir.',
 'noemailcreate' => 'Düzgün e-poçt ünvanı qeyd etməlisiniz',
 'passwordsent' => 'Yeni parol "$1" üçün qeydiyyata alınan e-poçt ünvanına göndərilmişdir.
 Xahiş edirik, e-məktubu aldıqdan sonra yenidən daxil olasınız.',
 'blocked-mailpassword' => 'İP ünvanınız bloklu olduğuna görə, yeni parol göndərmə mümkün deyil.',
+'eauthentsent' => 'Göstərilən bu e-poçt ünvanına məktub göndərildi. 
+Gələcəkdə e-poçt almaq üçün,bu e-poçtun sizə aid olması haqqındakı qaydalarla tanış olun.',
+'throttled-mailpassword' => 'Bir parol sıfırlama e-poçtu son {{PLURAL:$1|bir saat|$1 saat}} içində zatən göndərildi. Xidməti pis niyyətlə istifadə etməyi önləmək üçün, hər {{PLURAL:$1|bir saatda|$1 saatda}} sadəcə bir parol sıfırlama e-poçtu göndəriləcəkdir.',
 'mailerror' => 'Məktub göndərmə xətası: $1',
 'acct_creation_throttle_hit' => 'Sizin IP ünvanınızdan bu viki-də son bir gün ərzində {{PLURAL:$1|1 hesab|$1 hesab}} açılmışdır. Bu bir gün ərzində icazə verilən maksimum say olduğu üçün, indiki anda daha çox hesab aça bilməzsiniz.',
 'emailauthenticated' => 'E-poçt ünvanınız $2 saat $3 tarixində təsdiq edilib.',
@@ -533,19 +616,29 @@ Aşağıdakı xidmətlərin heç biri üçün Sizə e-məktub göndərilməyəc
 'emailconfirmlink' => 'E-poçt ünvanını təsdiq et',
 'invalidemailaddress' => 'E-poçt ünvanınızı qeyri-düzgün formatda olduğu üçün qəbul edə bilmirik.
 Xahiş edirik düzgün formatlı ünvan daxil edin və ya bu sahəni boş qoyun.',
+'cannotchangeemail' => 'Hesabın e-poçt ünvanı bu wiki üzərindən dəyişdirilə bilməz.',
 'emaildisabled' => 'Bu saytdan e-poçt göndərə bilməzsiniz.',
 'accountcreated' => 'Hesab yaradıldı',
 'accountcreatedtext' => '$1 üçün istifadəçi hesabı yaradıldı.',
 'createaccount-title' => '{{SITENAME}} hesabın yaradılması',
+'createaccount-text' => 'Biriləri {{SITENAME}} saytında ($4) sizin e-poçt ünvanınızdan istifadə edərək, parolu "$3" olan, "$2" adlı bir hesab yaratdı.
+
+Sayta daxil olmalı və parolunuzu dəyişdirməlisiniz.
+
+Əgər istifadəçi hesabını səhvən yaratmısınızsa, bu mesajı gözardı edə bilərsiniz.',
 'usernamehasherror' => 'İstifadəçi adında "diyez" simvolunun istifadəsi mümkün deyil',
 'login-throttled' => 'Sistemə daxil olmaq üçün həddən artıq cəhd etmisiniz.
 Yeni cəhd etməzdən əvvəl bir qədər gözləyin.',
 'login-abort-generic' => 'Giriş uğursuz alındı - Rədd',
 'loginlanguagelabel' => 'Dil: $1',
 'suspicious-userlogout' => 'Sizin çıxış üçün cəhdiniz uğursuz alındı. Bu, brouzerin yaxud proksi-keşləmənin düzgün işləməməsindən qaynaqlanır.',
+'createacct-another-realname-tip' => 'Gərçək adınız istəyə bağlıdır.
+Əgər gərçək adınızı göstərsəniz, çalışmalarınıza müraciət etmək üçün istifadə ediləcəkdir.',
 
 # Email sending
 'php-mail-error-unknown' => 'PHP-nin mail() funksiyasında naməlum xəta',
+'user-mail-no-addy' => 'Bir e-poçt ünvanı olmadan e-poçt göndərməyə çalışdı.',
+'user-mail-no-body' => 'Boş və ya keçərli olmayan bir şəkildə e-poçt göndərilməyə çalışıldı.',
 
 # Change password dialog
 'resetpass' => 'Parolu dəyiş',
@@ -565,11 +658,15 @@ Sistemə daxil olmanı yekunlaşdırmaq üçün yeni parolu bura yazmalısınız
 'resetpass-wrong-oldpass' => 'Müvəqqəti və ya daimi parolda yanlışlıq var.
 Ola bilər siz parolu müvəffəqiyyətlə dəyişmisiniz yaxud müvəqqəti parol üçün müraciət etmisiniz.',
 'resetpass-temp-password' => 'Müvəqqəti parol:',
+'resetpass-abort-generic' => 'Parol dəyişikliyi bir genişlənmə tərəfindən ləğv edildi.',
 
 # Special:PasswordReset
 'passwordreset' => 'Parolu yenilə',
+'passwordreset-text-one' => 'Parolunuzu sıfırlamaq üçün bu formanı doldurun.',
+'passwordreset-text-many' => '{{PLURAL:$1|Parolunuzu sıfırlamaq üçün sahələrdən birini doldurun.}}',
 'passwordreset-legend' => 'Parolu yenilə',
 'passwordreset-disabled' => 'Yenidən qurulma parolu bu vikidə işləmir',
+'passwordreset-emaildisabled' => 'Bu wiki-dəki e-poçt özəllikləri bağlandı.',
 'passwordreset-username' => 'İstifadəçi adı:',
 'passwordreset-domain' => 'Domen:',
 'passwordreset-email' => 'E-mail ünvanı:',
@@ -811,8 +908,8 @@ Mümkündür ki, bununla bağlı təfərrüatlar [{{fullurl:{{#Special:Log}}/del
 'revdelete-hide-user' => 'Redaktə müəllifinin istifadəçi adını/IP ünvanını gizlə',
 'revdelete-hide-restricted' => 'Məlumatları idarəçilərdən də gizlə',
 'revdelete-radio-same' => '(dəyişdirmə)',
-'revdelete-radio-set' => 'li',
-'revdelete-radio-unset' => 'Xeyr',
+'revdelete-radio-set' => 'Gizli',
+'revdelete-radio-unset' => 'Görünür',
 'revdelete-suppress' => 'Məlumatları idarəçilərdən də gizlə',
 'revdelete-unsuppress' => 'Bərpa olunan versiyalar üzərindən məhdudiyyətləri qaldır',
 'revdelete-log' => 'Səbəb:',
@@ -937,8 +1034,6 @@ $1",
 'preferences' => 'Nizamlamalar',
 'mypreferences' => 'Nizamlamalar',
 'prefs-edits' => 'Redaktələrin sayı:',
-'prefsnologin' => 'Daxil olmamısınız',
-'prefsnologintext' => 'Nizamlamaları dəyişmək üçün <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} daxil olmaq]</span> zəruridir.',
 'changepassword' => 'Parolu dəyiş',
 'prefs-skin' => 'Cild',
 'skin-preview' => 'Sınaq görüntüsü',
@@ -1197,6 +1292,7 @@ Həmçinin kimliyinizi gostərmədən belə, başqalarının sizinlə istifadə
 'recentchanges-label-minor' => 'Bu kiçik redaktədir',
 'recentchanges-label-bot' => 'Bu redaktə bot tərəfindən edilmişdir',
 'recentchanges-label-unpatrolled' => 'Bu redaktə hələ nəzərdən keçirilməmişdir',
+'recentchanges-legend-newpage' => '$1 - yeni səhifə',
 'rcnote' => "Aşağıdakı {{PLURAL:$1|'''1''' dəyişiklik|'''$1''' dəyişiklik}} saat $5, $4 tarixinə qədər son {{PLURAL:$2|gün|'''$2''' gün}} ərzində edilmişdir.",
 'rcnotefrom' => "Aşağıda '''$2'''-dən ('''$1'''-ə qədər) dəyişikliklər sadalanmışdır.",
 'rclistfrom' => '$1 vaxtından başlayaraq yeni dəyişiklikləri göstər',
@@ -1457,8 +1553,12 @@ $1',
 # Random page
 'randompage' => 'İxtiyari səhifə',
 
+# Random page in category
+'randomincategory-selectcategory-submit' => 'Keç',
+
 # Random redirect
 'randomredirect' => 'İxtiyari istiqamətləndirmə',
+'randomredirect-nopages' => '"$1" ad sahəsində heç bir yönləndirmə yoxdur.',
 
 # Statistics
 'statistics' => 'Statistika',
@@ -2119,7 +2219,7 @@ Zəhmət olmasa başqa ad seçin.',
 'allmessagesname' => 'Ad',
 'allmessagesdefault' => 'İlkin mətn',
 'allmessagescurrent' => 'İndiki mətn',
-'allmessagestext' => 'Bu MediaWiki-də olan sistem mesajlarının siyahısıdır. Əgər MediaWiki-ni lokallaşdırmaq işində kömək etmək isəyirsinizsə, lütfən [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] və [//translatewiki.net translatewiki.net]-ə baş çəkin.',
+'allmessagestext' => 'Bu MediaWiki-də olan sistem mesajlarının siyahısıdır. Əgər MediaWiki-ni lokallaşdırmaq işində kömək etmək isəyirsinizsə, lütfən [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] və [//translatewiki.net translatewiki.net]-ə baş çəkin.',
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter-unmodified' => 'Dəyişdirilməmiş',
 'allmessages-filter-all' => 'Hamısı',
@@ -2738,7 +2838,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => 'Bu faylı kənar proqram vasitəsilə redaktə et.',
-'edit-externally-help' => '(Daha ətraflı məlumat üçün [//www.mediawiki.org/wiki/Manual:External_editors tətbiqetmə qaydalarına] baxa bilərsiniz)',
+'edit-externally-help' => '(Daha ətraflı məlumat üçün [https://www.mediawiki.org/wiki/Manual:External_editors tətbiqetmə qaydalarına] baxa bilərsiniz)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'hamısını',
@@ -2838,7 +2938,7 @@ Variants for Chinese language
 'version-hook-subscribedby' => 'Abunə olan',
 'version-version' => '(Versiya $1)',
 'version-license' => 'Lisenziya',
-'version-poweredby-credits' => "Bu wiki '''[//www.mediawiki.org/ MediaWiki]''' proqramı istifadə edilərək yaradılmışdır, müəlliflik © 2001-$1 $2.",
+'version-poweredby-credits' => "Bu wiki '''[https://www.mediawiki.org/ MediaWiki]''' proqramı istifadə edilərək yaradılmışdır, müəlliflik © 2001-$1 $2.",
 'version-poweredby-others' => 'digərləri',
 'version-software-product' => 'Məhsul',
 'version-software-version' => 'Versiya',
@@ -2961,4 +3061,8 @@ Variants for Chinese language
 'duration-centuries' => '$1 {{PLURAL:$1|əsr|əsr}}',
 'duration-millennia' => '$1 {{PLURAL:$1|minillik|minillik}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Nəticə',
+'expand_templates_ok' => 'OK',
+
 );
index e9423fb..6a1fe51 100644 (file)
@@ -355,8 +355,6 @@ $1',
 'ok' => 'اولدو',
 'retrievedfrom' => '«$1»-دن آلینمیشدیر',
 'youhavenewmessages' => 'سیزین $1 ($2) وارینیزدیر.',
-'newmessageslink' => 'یئنی مئساژلار',
-'newmessagesdifflink' => 'سون دَییشیکلیک',
 'youhavenewmessagesfromusers' => 'سیزین {{PLURAL:$3|بیر آیری ایستیفاده‌چی‌دن|$3 ایستیفاده‌چی‌دن}} $1 وارینیزدیر ($2).',
 'youhavenewmessagesmanyusers' => 'سیزین چوخلو ایشلدنلردن $1 وارینیزدیر ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|بیر یئنی مئساژ|یئنی مئساژلار}}',
@@ -1174,8 +1172,6 @@ $1",
 'preferences' => 'ترجیحلر',
 'mypreferences' => 'ترجیحلر',
 'prefs-edits' => 'دَییشمه‌لرین سایی:',
-'prefsnologin' => 'گیرمه‌میسینیز',
-'prefsnologintext' => 'ایستیفاده‌چی تنظیملرینی دَییشمک اوچون، <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} گیرمه‌لیسینیز]</span>.',
 'changepassword' => 'رمزی دَییشدیر',
 'prefs-skin' => 'قابیق',
 'skin-preview' => 'اؤن‌گؤستریش',
@@ -2692,7 +2688,7 @@ $1 آدلی ایستیفاده‌چی‌نین باغلانما سببی: "$2"',
 'allmessagesname' => 'آد',
 'allmessagesdefault' => 'دفالت دانیشیق متنی',
 'allmessagescurrent' => 'ایندیکی متن',
-'allmessagestext' => 'بو مئدیا ویکی-ده اولان سیستئم مئساژلارینین سیاهی‌سی‌دیر. اگر مئدیا ویکی-نی لوکاللاش‌دیرماق ایشینده کؤمک ائتمک ایسییرسینیزسه، لطفاً [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net]-ا باش چکین.',
+'allmessagestext' => 'بو مئدیا ویکی-ده اولان سیستئم مئساژلارینین سیاهی‌سی‌دیر. اگر مئدیا ویکی-نی لوکاللاش‌دیرماق ایشینده کؤمک ائتمک ایسییرسینیزسه، لطفاً [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net]-ا باش چکین.',
 'allmessagesnotsupportedDB' => "'''\$ wgUseDatabaseMessages''' باغ‌لی اولدوغو اوچون '{{ns:special}}: Allmessages ایستیفاده‌یه آچیق دئییل.",
 'allmessages-filter-legend' => 'سۆزگَج',
 'allmessages-filter' => 'خصوصی ائتمک وضعیتینه گؤره فیلترلی:',
@@ -3442,7 +3438,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'بو فایلی خاریجی یازیلیم‌لا دَییشدیر',
-'edit-externally-help' => '(آرتیق بیلگیلر اوچون [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] صحیفه‌سینه باخ)',
+'edit-externally-help' => '(آرتیق بیلگیلر اوچون [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] صحیفه‌سینه باخ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'بوتون',
@@ -3625,7 +3621,7 @@ $5
 'version-hook-subscribedby' => 'طرفیندن گیریش‌‌میش',
 'version-version' => '(نسخه $1)',
 'version-license' => 'لیسانس',
-'version-poweredby-credits' => "بو wیکی ' ''[//www.mediawiki.org/ مئدیاwیکی]'ع' پروقرامی ایستیفاده ائدیله‌رک يارادیلمیشدیر، یاازارلار © 2001-$1 $2.",
+'version-poweredby-credits' => "بو wیکی ' ''[https://www.mediawiki.org/ مئدیاwیکی]'ع' پروقرامی ایستیفاده ائدیله‌رک يارادیلمیشدیر، یاازارلار © 2001-$1 $2.",
 'version-poweredby-others' => 'آیریلار',
 'version-credits-summary' => 'بو ایستفاده چیلر دییشدیر لرینه گوره [[Special:Version|مئدیاویکی]] تانیش ائدیرم.',
 'version-license-info' => 'مئدیاویکی بیر اؤزگور یازیلیم‌دیر؛ سیز اونو، اؤزگور یازیلیم قورولوشو یایان GNU گنل عمومی لیسانسی اساسی‌له یئنی‌دن داغیدیب یوخسا دَییشه بیلرسینیز؛ یا لیسانسین ۲-نجی نوسخه‌سی، یا دا (اؤز سئچدیگینیزله) هر هانکی سونراکی نوسخه‌سی.
@@ -3665,8 +3661,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'اؤزل صحیفه‌لر',
-'specialpages-note' => '----
-* نورمال اؤزل صحیفه‌لر.
+'specialpages-note' => '* نورمال اؤزل صحیفه‌لر.
 * <span class="mw-specialpagerestricted">محدودلاشدیریلمیش اؤزل صحیفه‌لر.</span>',
 'specialpages-group-maintenance' => 'جاری مروزه‌لر',
 'specialpages-group-other' => 'دیگر خصوصی صحیفه‌لر',
index 848a9b3..e8752a3 100644 (file)
@@ -66,7 +66,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Барлыҡ_битәр' ),
        'Blankpage'                 => array( 'Буш_бит' ),
        'Block'                     => array( 'Блоклау' ),
-       'Blockme'                   => array( 'Мине_блокла' ),
        'Booksources'               => array( 'Китап_сығанаҡтары' ),
        'BrokenRedirects'           => array( 'Өҙөлгән_йүнәлтеүҙәр' ),
        'Categories'                => array( 'Категориялар' ),
@@ -78,7 +77,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Иҫәп_яҙыуы_яһау' ),
        'Deadendpages'              => array( 'Көрсөк_биттәр' ),
        'DeletedContributions'      => array( 'Юйылған_өлөш' ),
-       'Disambiguations'           => array( 'Күп_мәғәнәлелек' ),
        'DoubleRedirects'           => array( 'Икеле_йүнәлтеүҙәр' ),
        'EditWatchlist'             => array( 'Күҙәтеү_исемлеген_мөхәррирләү' ),
        'Emailuser'                 => array( 'Ҡатнашыусыға_хат' ),
@@ -423,8 +421,6 @@ $1',
 'pagetitle' => '{{SITENAME}} проектынан',
 'retrievedfrom' => 'Сығанағы — «$1»',
 'youhavenewmessages' => 'Яңы $1 бар ($2).',
-'newmessageslink' => 'яңы хәбәр',
-'newmessagesdifflink' => 'һуңғы үҙгәртеү',
 'youhavenewmessagesfromusers' => 'Һеҙгә {{PLURAL:$3|башҡа ҡатнашыусынан|$3 ҡатнашыусынан}} $1 бар ($2).',
 'youhavenewmessagesmanyusers' => 'Һеҙгә күп ҡатнашыусынан $1 бар ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|яңы хәбәр|яңы хәбәр}}',
@@ -591,8 +587,8 @@ $2',
 'yourdomainname' => 'Һеҙҙең домен',
 'password-change-forbidden' => 'Был викила серһүҙегеҙҙе үҙгәртә алмайһығыҙ.',
 'externaldberror' => 'Тышҡы мәғлүмәт базаһы менән танылғанда хата барлыҡҡа килде йәки тышҡы үҙ көйләүҙәрегеҙҙе үҙгәртер өсөн хоҡуҡтарығыҙ етәрле түгел.',
-'login' => 'Танышыу йәки теркәлеү',
-'nav-login-createaccount' => 'Танышыу йәки теркәлеү',
+'login' => 'Танылыу',
+'nav-login-createaccount' => 'Танылыу йәки теркәлеү',
 'loginprompt' => '{{SITENAME}} проектына кереү өсөн «cookies» рөхсәт ителгән булырға тейеш.',
 'userlogin' => 'Танылыу йәки теркәлеү',
 'userloginnocreate' => 'Танылыу',
@@ -666,7 +662,7 @@ $2',
 
 Зинһар, серһүҙҙе алғас, системаға яңынан керегеҙ.',
 'blocked-mailpassword' => 'Һеҙҙең IP-адресығыҙҙан мөхәррирләү тыйылған, шул сәбәпле серһүҙ тергеҙеү ғәмәле лә блокланған.',
-'eauthentsent' => 'Күрһәтелгән электрон почта адресына адресты үҙгәртеүҙе раҫлауығыҙ өсөн хат ебәрелде. Хатта, был адрес һеҙҙеке булғанын раҫлау өсөн ниндәй ғәмәлдәрҙе үтәү кәрәкле икәне тураһында мәғлүмәт бар.',
+'eauthentsent' => 'Күрһәтелгән электрон почта адресына адресты үҙгәртеүҙе раҫлауығыҙ өсөн хат ебәрелде. Хатта был адрес һеҙҙеке булғанын раҫлау өсөн ниндәй ғәмәлдәрҙе үтәү кәрәклеге тураһында мәғлүмәт бар.',
 'throttled-mailpassword' => 'Серһүҙҙе иҫләтеү ғәмәле {{PLURAL:$1|һуңғы $1 сәғәт}} эсенде ҡулланылды инде.
 Насар ниәтле ҡулланыуҙарға ҡаршы, Серһүҙ иҫләтеү ғәмәлен {{PLURAL:$1|сәғәт|$1 сәғәт}} эсендә бер тапҡыр ғына ҡулланырға була.',
 'mailerror' => 'Хат ебәреү хатаһы: $1',
@@ -1269,8 +1265,6 @@ $1",
 'preferences' => 'Көйләүҙәр',
 'mypreferences' => 'Көйләүҙәр',
 'prefs-edits' => 'Төҙәтеүҙәр һаны:',
-'prefsnologin' => 'Танылмағанһығыҙ',
-'prefsnologintext' => 'Ҡатнашыусы көйләүҙәрен үҙгәртеү өсөн, һеҙ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}}танылырға]</span> тейешһегеҙ.',
 'changepassword' => 'Серһүҙҙе үҙгәртергә',
 'prefs-skin' => 'Күренеш',
 'skin-preview' => 'Алдан байҡау',
@@ -1570,6 +1564,7 @@ $1",
 'recentchanges-label-minor' => 'Был әҙ үҙгәреш',
 'recentchanges-label-bot' => 'Был төҙәтеү бот тарафынан башҡарылды',
 'recentchanges-label-unpatrolled' => 'Был төҙәтеү ҡаралмаған әле',
+'recentchanges-legend-newpage' => '$1 — яңы бит',
 'rcnote' => 'Аҫта $4 $5 тиклем эшләнгән, һуңғы {{PLURAL:$2|1|$2}} көн эсендәге һуңғы {{PLURAL:$1|1|$1}} үҙгәртеү күрһәтелгән.',
 'rcnotefrom' => "Түбәндә '''$2''' башлап ('''$1''' тиклем) үҙгәртеүҙәр күрһәтелгән.",
 'rclistfrom' => '$1 башлап яңы үҙгәртеүҙәрҙе күрһәт.',
@@ -2820,7 +2815,7 @@ $1 ҡатнашыусыһын бикләү сәбәбе: "$2"',
 'allmessagesdefault' => 'Ғәҙәттәге яҙма',
 'allmessagescurrent' => 'Хәҙерге яҙма',
 'allmessagestext' => 'Түбәндә MediaWiki исемдәр арауығында ҡулланылған система хәбәрҙәре исемлеге килтерелгән.
-Әгәр MediaWiki программаһын дөйөм локалләштереү эшенә үҙ өлөшөгөҙҙө керетергә теләһәгеҙ, [//www.mediawiki.org/wiki/Localisation MediaWiki программаһын локалләштереү] битен һәм [//translatewiki.net translatewiki.net] проектын ҡарап сығығыҙ.',
+Әгәр MediaWiki программаһын дөйөм локалләштереү эшенә үҙ өлөшөгөҙҙө керетергә теләһәгеҙ, [https://www.mediawiki.org/wiki/Localisation MediaWiki программаһын локалләштереү] битен һәм [//translatewiki.net translatewiki.net] проектын ҡарап сығығыҙ.',
 'allmessagesnotsupportedDB' => "Был бит ҡулланыла алмай, сөнки '''\$wgUseDatabaseMessages''' мөмкинлеге һүндерелгән.",
 'allmessages-filter-legend' => 'Һайлау',
 'allmessages-filter' => 'Үҙгәртеү торошо буйынса һайлау:',
@@ -3013,6 +3008,8 @@ The wiki server cannot provide data in a format your client can read.',
 'spam_reverting' => '$1 һылтанмаһыҙ һуңғы өлгөгә ҡайтарыу',
 'spam_blanking' => 'Бөтә өлгөләрҙә лә $1 һылтанмаһы бар, таҙартыу',
 'spam_deleting' => 'Бөтә өлгөләрҙә лә $1 һылтанма бар, таҙартыу бара',
+'simpleantispam-label' => "Спамға ҡаршы тикшереү.
+Быны '''ТУЛТЫРМАҒЫҘ'''!",
 
 # Info page
 'pageinfo-title' => '«$1» буйынса мәғлүмәт',
@@ -3578,7 +3575,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Был файлды тышҡы программа ҡулланып мөхәррирләргә',
-'edit-externally-help' => '(Тулыраҡ мәғлүмәт өсөн металағы [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] (инглизсә) битен ҡарағыҙ)',
+'edit-externally-help' => '(Тулыраҡ мәғлүмәт өсөн металағы [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] (инглизсә) битен ҡарағыҙ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'бөтә',
@@ -3763,7 +3760,7 @@ $5
 'version-hook-subscribedby' => 'Яҙҙырылған',
 'version-version' => '($1 өлгөһө)',
 'version-license' => 'Рөхсәтнамә',
-'version-poweredby-credits' => "Был вики проект '''[//www.mediawiki.org/ MediaWiki]''' нигеҙендә эшләй, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Был вики проект '''[https://www.mediawiki.org/ MediaWiki]''' нигеҙендә эшләй, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'башҡалар',
 'version-poweredby-translators' => 'translatewiki.net тәржемәселәре',
 'version-credits-summary' => '[[Special:Version|MediaWiki]] үҫешенә өлөш индергәндәре өсөн киләһе ҡатнашыусыларға рәхмәт әйтәбеҙ.',
@@ -3804,13 +3801,12 @@ MediaWiki файҙалы булыр, тигән өмөттә, ләкин БЕР
 
 # Special:SpecialPages
 'specialpages' => 'Махсус биттәр',
-'specialpages-note' => '----
-* Ябай махсус биттәр.
+'specialpages-note' => '* Ябай махсус биттәр.
 * <span class="mw-specialpagerestricted">Сикле махсус биттәр.</span>
 * <span class="mw-specialpagecached">Кешланған махсус биттәр (иҫкергән булыуы мөмкин).</span>',
 'specialpages-group-maintenance' => 'Техник хеҙмәтләндереү хисапламалары',
 'specialpages-group-other' => 'Башҡа махсус биттәр',
-'specialpages-group-login' => 'Танышыу йәки теркәлеү',
+'specialpages-group-login' => 'Танылыу йәки теркәлеү',
 'specialpages-group-changes' => 'Һуңғы үҙгәртеүҙәр һәм журналдар',
 'specialpages-group-media' => 'Медиа хисапламалары һәм тейәүҙәр',
 'specialpages-group-users' => 'Ҡатнашыусылар һәм хоҡуҡтар',
@@ -3901,7 +3897,7 @@ MediaWiki файҙалы булыр, тигән өмөттә, ләкин БЕР
 'logentry-delete-event-legacy' => '$1  $3 журналы яҙмаларының күренеүсәнлеген {{GENDER:$2|үҙгәртте}}',
 'logentry-delete-revision-legacy' => '$1  $3 битендә версияларҙың күренеүсәнлеген {{GENDER:$2|үҙгәртте}}',
 'logentry-suppress-delete' => '$1 $3 битен {{GENDER:$2|баҫырылдырҙы}}',
-'logentry-suppress-event' => '$1 журналдағы {{PLURAL:$5|$5 яҙманың}} күренеүсәнлеген $3 битендә йәшерен үҙгәртте: $4',
+'logentry-suppress-event' => '$1 журналдағы {{PLURAL:$5|$5 яҙманың}} күренеүсәнлеген $3 битендә йәшерен {{GENDER:$2|}}үҙгәртте: $4',
 'logentry-suppress-revision' => '$1 {{PLURAL:$5|$5 версияның}} күренеүсәнлеген $3 битендә йәшерен үҙгәртте: $4',
 'logentry-suppress-event-legacy' => '$1  журнал яҙмаларының күренеүсәнлеген йәшерен  {{GENDER:$2|үҙгәртте}}$3',
 'logentry-suppress-revision-legacy' => '$1 $3 битендә версияларҙың күренеүсәнлеген йәшерен {{GENDER:$2|}}',
@@ -4020,4 +4016,19 @@ MediaWiki файҙалы булыр, тигән өмөттә, ләкин БЕР
 'limitreport-expansiondepth' => 'Киңәйеүҙең иң ҙур тәрәнлеге',
 'limitreport-expensivefunctioncount' => 'Анализаторҙың "ҡиммәтле" функцияларының һаны',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Ҡалыптарҙы йәйелдереү',
+'expand_templates_intro' => 'Был махсус бит бирелгән тексттың бөтә ҡалыптарын ҡабатланмалы рәүештә йәйелдерә.
+Шулай уҡ <nowiki>{{</nowiki>#language:…}} һымаҡ уҡыу ҡоралдары һәм <nowiki>{{</nowiki>CURRENTDAY}} һымаҡ үҙгәреүсән дәүмәлдәр,— ғөмүмән, икәүле йәйәләр эсендә барыһы ла йәйелдерелә.
+Был MediaWiki-ның кәрәкле эшкәртеүсе ҡоралын саҡырыу ярҙамында эшләнә.',
+'expand_templates_title' => '{{FULLPAGENAME}} һ.б. өсөн бит исеме:',
+'expand_templates_input' => 'Сығанаҡ текст:',
+'expand_templates_output' => 'Һөҙөмтә',
+'expand_templates_xml_output' => 'XML һөҙөмтә',
+'expand_templates_ok' => 'Тамам',
+'expand_templates_remove_comments' => 'Аңлатмаларҙы юйырға',
+'expand_templates_remove_nowiki' => 'Һөҙөмтәлә <nowiki> билдәләрен йәшерергә',
+'expand_templates_generate_xml' => 'XML уҡыу ағасын күрһәтергә',
+'expand_templates_preview' => 'Ҡарап сығыу',
+
 );
index 1277b9a..3a53f74 100644 (file)
@@ -317,8 +317,6 @@ Schaug auf [[Special:Version|Versiónsseiten]]",
 'ok' => 'Passt',
 'retrievedfrom' => 'Vh „$1“',
 'youhavenewmessages' => 'Du host $1 ($2).',
-'newmessageslink' => 'neiche Nochrichtn',
-'newmessagesdifflink' => 'Letzte Endarung',
 'youhavenewmessagesmulti' => 'Du host neiche Nochrichtn: $1',
 'editsection' => 'Werkln',
 'editold' => 'Werkln',
@@ -1425,7 +1423,7 @@ Bittschee gib außadem druntn in '''neichn''' Nãm vu da Seitn ei und schreib ku
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'Aktuella Text',
 'allmessagestext' => 'Des is a Listen vo de MediaWiki-Systemtextt.
-Bsuach bittschee de Saiten [//www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisiarung] und [//translatewiki.net translatewiki.net], wånn du de ån da Lokalisiarung vo MediaWiki betailing mechadst.',
+Bsuach bittschee de Saiten [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisiarung] und [//translatewiki.net translatewiki.net], wånn du de ån da Lokalisiarung vo MediaWiki betailing mechadst.',
 'allmessagesnotsupportedDB' => "'''Special:Allmessages''' is im Moment net möglich, wei de Datenbank offline is.",
 
 # Thumbnails
@@ -1567,7 +1565,7 @@ Weidane wean standardmassi ned ozoagt.
 
 # External editor support
 'edit-externally' => 'De Datei mid am externa Programm beorbatn',
-'edit-externally-help' => '(Schaug unter [//www.mediawiki.org/wiki/Manual:External_editors Installationsoweisunga] fia weidane Infos)',
+'edit-externally-help' => '(Schaug unter [https://www.mediawiki.org/wiki/Manual:External_editors Installationsoweisunga] fia weidane Infos)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'olle',
@@ -1653,7 +1651,7 @@ Bittscheh d' noraale Vurschau bnutzen.",
 'version-hook-subscribedby' => 'Aufruaff voh',
 'version-version' => '(Versión $1)',
 'version-license' => 'Lizenz',
-'version-poweredby-credits' => "Dé Nétzseiten braucht '''[//www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Dé Nétzseiten braucht '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'åndre',
 
 # Special:FileDuplicateSearch
@@ -1667,8 +1665,7 @@ Bittscheh d' noraale Vurschau bnutzen.",
 
 # Special:SpecialPages
 'specialpages' => 'Spezialseitn',
-'specialpages-note' => '----
-* Reguläre Speziaalseiten
+'specialpages-note' => '* Reguläre Speziaalseiten
 * <span class="mw-specialpagerestricted">Zuagrifsbschränkde Speziaalseiten</span>
 * <span class="mw-specialpagecached">Cachegenerrirde Speziaalseiten (Da Inhoid is méglicherweis vaoiterd)</span>',
 'specialpages-group-maintenance' => 'Wartungslisten',
index 62d92e9..daacbe7 100644 (file)
@@ -63,7 +63,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'صفحات قدیمی' ),
        'Blankpage'                 => array( 'صفحه هالیک' ),
        'Block'                     => array( 'محدود آی پی' ),
-       'Blockme'                   => array( 'محدودیت من' ),
        'Booksources'               => array( 'منابع کتاب' ),
        'BrokenRedirects'           => array( 'پرشتگین غیرمستقیم' ),
        'Categories'                => array( 'دستجات' ),
@@ -72,7 +71,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'مشارکتان' ),
        'CreateAccount'             => array( 'شرکتن حساب' ),
        'Deadendpages'              => array( 'مرتگین صفحات' ),
-       'Disambiguations'           => array( 'رفع ابهام' ),
        'DoubleRedirects'           => array( 'دوبل غیر مستقیم' ),
        'Emailuser'                 => array( 'ایمیل کاربر' ),
        'Export'                    => array( 'درگیزگ' ),
@@ -382,8 +380,6 @@ $1',
 'ok' => 'هوبنت',
 'retrievedfrom' => 'درگیجگ بیت چه  "$1"',
 'youhavenewmessages' => 'شما هست  $1 ($2).',
-'newmessageslink' => 'نوکین کوله یان',
-'newmessagesdifflink' => 'اهری تغییر',
 'youhavenewmessagesmulti' => 'شما را نوکین کوله یان هست ته   $1',
 'editsection' => 'اصلاح',
 'editold' => 'اصلاح',
@@ -989,8 +985,6 @@ $1",
 'preferences' => 'ترجیحات',
 'mypreferences' => 'منی ترجیحات',
 'prefs-edits' => 'تعداد اصلاحات:',
-'prefsnologin' => 'وارد نهیت',
-'prefsnologintext' => 'شما بایدن  <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} وارد بیت]</span> په تنظیم کتن ترجیحات.',
 'changepassword' => 'کلمه رمز عوض کن',
 'prefs-skin' => 'پوست',
 'skin-preview' => 'بازین',
@@ -2209,7 +2203,7 @@ $1',
 'allmessagesdefault' => 'پیش فرضین متن',
 'allmessagescurrent' => 'هنوکین متن',
 'allmessagestext' => 'شی یک لیستی چه کوله یان موجود ته نام فضای مدیا وی کی انت.
-لطفا بچاریت  [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net] اگر شما لوٹیت ته ملکی کتن مدیا وی کی کمک کنیت.',
+لطفا بچاریت  [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] و [//translatewiki.net translatewiki.net] اگر شما لوٹیت ته ملکی کتن مدیا وی کی کمک کنیت.',
 'allmessagesnotsupportedDB' => "ای صفحه نه تونیت استفاده بیت په چی که'''\$wgUseDatabaseMessages''' غیر فعالنت.",
 'allmessages-filter-legend' => 'فیلتر',
 'allmessages-filter' => 'فیلتر گون حالت دلواهی',
@@ -2370,6 +2364,8 @@ $1',
 'spambot_username' => 'اسپم پاک کنوک مدیا وی کی',
 'spam_reverting' => 'عوض کتن په آهری نسحه که شامل لینکان می بیت په $1',
 'spam_blanking' => 'کل بازبینی آن شامل لینکان په $1, بوتت  هالیکی',
+'simpleantispam-label' => "کنترل ضد اسپم.
+ای شیء پر ''مکن''",
 
 # Skin names
 'skinname-cologneblue' => 'نیلی کولاجن',
@@ -2787,7 +2783,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => 'ای صفحه یا اصلاح کن گون یک درآین برنامه ای',
-'edit-externally-help' => '(په گیشترین اطلاعات بچار[//www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
+'edit-externally-help' => '(په گیشترین اطلاعات بچار[https://www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'کل',
@@ -3004,8 +3000,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'حاصین صفحات',
-'specialpages-note' => '----
-* نرمال صفحات حاص.
+'specialpages-note' => '* نرمال صفحات حاص.
 *  <strong class="mw-specialpagerestricted">محدودین صفحات حاص.</strong>',
 'specialpages-group-maintenance' => 'گزارشات دارگ',
 'specialpages-group-other' => 'دگر حاصین صفحات',
@@ -3071,4 +3066,20 @@ $5
 'revdelete-unrestricted' => 'به زور چه مدیران سیستم محدودیتان',
 'rightsnone' => '(هچ یک)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'پچ کن تمپلیت آنء',
+'expand_templates_intro' => 'ای صفحه حاص لهتی متنء گریت و کل تمپلتان ته آییء برگشتی مزنش کنت.
+آیی هنچوش عمگر تجزیه کنوکء مزن کنت په داب
+<nowiki>{{</nowiki>#language:…}}, و متغییرانی په داب
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash; در حقیقت هر چیزی که ته دو براکتن.
+آیی ای کارء گون توار کنگ تجزیه کنوک مناسب چه مدیا وی کی وت انجام دنت.',
+'expand_templates_title' => 'عنوان متن په {{FULLPAGENAME}} و دگه.:',
+'expand_templates_input' => 'ورودی متن',
+'expand_templates_output' => 'نتیجه',
+'expand_templates_xml_output' => 'خروجی XML',
+'expand_templates_ok' => 'هوبنت',
+'expand_templates_remove_comments' => 'بزور نظرات',
+'expand_templates_generate_xml' => 'پیش دار درچک تجزیه XMLء',
+'expand_templates_preview' => 'بازبین',
+
 );
index fee4441..4686e88 100644 (file)
@@ -314,7 +314,7 @@ $messages = array(
 'articlepage' => 'Tanawon an laog kan pahina',
 'talk' => 'Orolayan',
 'views' => 'Mga Tanawon',
-'toolbox' => 'Kagamitang kahon',
+'toolbox' => 'Mga gagamiton:',
 'userpage' => 'Tanawon an pahina kan parágamit',
 'projectpage' => 'Tanawon an pahina kan proyekto',
 'imagepage' => 'Hilngón an pahina nin sagunson (file)',
@@ -344,7 +344,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Dapít sa {{SITENAME}}',
 'aboutpage' => 'Project:Mapanonongód',
-'copyright' => 'An kalamnan manunumpungan sa laog kan $1.',
+'copyright' => 'An kalamnan manunumpungan sa laog kan $1 o baya notado na ining laen.',
 'copyrightpage' => '{{ns:project}}:Mga Katanosang pansurat',
 'currentevents' => 'Sa ngunyan na mga pangyayari',
 'currentevents-url' => 'Project:Mga pangyayari sa ngunyán',
@@ -370,12 +370,10 @@ $1',
 'ok' => 'Sige',
 'retrievedfrom' => 'Pinaghugot gikan sa "$1"',
 'youhavenewmessages' => 'Ika igwa nin $1 ($2).',
-'newmessageslink' => 'bàgong mga mensahe',
-'newmessagesdifflink' => 'huring kaliwatan',
 'youhavenewmessagesfromusers' => 'Ika igwa nin $1 gikan sa {{PLURAL:$3|ibang paragamit|$3 mga paragamit}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ika igwa nin $1 gikan sa kadakol na mga paragamit ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|sarong bagong mensahe|bagong mga mensahe}}',
-'newmessagesdifflinkplural' => 'huring {{PLURAL:$1|kaliwatan|mga kaliwatan}}',
+'newmessageslinkplural' => '{{PLURAL:$1|sarong baguhong mensahe|999=baguhong mga mensahe}}',
+'newmessagesdifflinkplural' => 'kahurihan na {{PLURAL:$1|kaliwatan|999=mga kaliwatan}}',
 'youhavenewmessagesmulti' => 'Igwa ka nin mga bàgong mensahe sa $1',
 'editsection' => 'liwatón',
 'editold' => 'Liwatón',
@@ -508,7 +506,8 @@ An administrador na iyo an nagkandado kaini nagpahayag kaining kapaliwanagan: "$
 'invalidtitle-knownnamespace' => 'Imbalidong titulo na igwang espasyadong ngaran na "$2" asin teksto na "$3"',
 'invalidtitle-unknownnamespace' => 'Imbalidong titulo na igwang nin bakong bistado na bilang kan espasyadong ngaran na $1 asin teksto na "$2"',
 'exception-nologin' => 'Dae ka nakalaog',
-'exception-nologin-text' => 'Ining pahina o aksyon minakaipo saimo na maglaog kaining wiki.',
+'exception-nologin-text' => 'Tabi man [[Special:Userlogin|maglaog]]na tanganing makalangkay sa pahinang ini o aksyon.',
+'exception-nologin-text-manual' => 'Tabi man $1 na tanganing makalangkay sa pahinang ini o aksyon.',
 
 # Virus scanner
 'virus-badscanner' => "Raot na kasalansanan: Bakong bistadong virus scanner: ''$1''",
@@ -555,9 +554,12 @@ Dae malingaw na liwaton an saimong [[Special:Preferences|{{SITENAME}} mga kamuya
 'gotaccount' => 'Igwa ka na tabi nin panindog? $1.',
 'gotaccountlink' => 'Maglaog',
 'userlogin-resetlink' => 'Nakalingaw ka sa panlaog mong detalye?',
-'userlogin-resetpassword-link' => 'Pakibaguha an saimong sekretong panlaog',
+'userlogin-resetpassword-link' => 'Nalingawan mo an saimong pasa-taramon?',
 'helplogin-url' => 'Help:Paglalaog',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Tabang sa paglalaog]]',
+'userlogin-loggedin' => 'Ika nakalaog na tabi bilang si {{GENDER:$1|$1}}.
+Gamita an porma sa ibaba sa paglaog bilang ibang paragamit.',
+'userlogin-createanother' => 'Magmukna nin ibang panindog',
 'createacct-join' => 'Pakikaag an saimong impormasyon sa ibaba.',
 'createacct-another-join' => 'Ikaag an impormasyon kan baguhong panindog sa ibaba.',
 'createacct-emailrequired' => 'Estada kan e-surat',
@@ -620,16 +622,16 @@ Kun ibang tawo an naghimo kaining kahagadan, o kun saimo nang nagiromdoman an sa
 'passwordsent' => 'Sarong baguhon na sekretong panlaog an ipinadara sa e-koreong address na nakarehistro para ki "$1".
 Tabi maglaog giraray matapos mong maresibe ini.',
 'blocked-mailpassword' => 'An saimong IP address pinagkubkob na magliwat, asin kaya dae tinutugutan na gumamit kan pambawi nin sekretong panlaog na punksyon tanganing makalikay sa abuso.',
-'eauthentsent' => 'Sarong e-koreong pankumpirmasyon an ipinadara sa nominadong e-koreong address.
-Bago an ibang e-koreo ipinadara sa panindog, ika igwang pagsunudong na mga instruksyon na yaon sa e-koreo, tanganing kumpirmaron na an panindog tunay talagang saimo.',
+'eauthentsent' => 'Sarong pankumpirmasyon na e-surat an ipinadara sa isinambit na estada nin e-surat.
+Bago an ibang e-surat ipinapadara sa panindog, ika igwang susunudon na mga instruksyon na yaon sa e-surat, tanganing kumpirmaron na an panindog tunay talagang saimo.',
 'throttled-mailpassword' => 'Sarong e-surat sa pagliliwat kan sekretong panlaog an ipinadara na, sa laog nin {{PLURAL:$1|hour|$1 hours}}.
 Tangarig malikayan an abuso, saro sanang e-surat sa pagliliwat kan sekretong panlaog an ipinapadara sa lambang {{PLURAL:$1|hour|$1 hours}}.',
 'mailerror' => 'Salâ an pagpadará kan koreo: $1',
 'acct_creation_throttle_hit' => 'Mga bisita kaining wiki na ginagamit an saimong IP address nagmukna nin {{PLURAL:$1|1 panindog|$1 mga panindog}} sa nakaaging aldaw, na iyo ngani an maximum na pinagtutugot sa laog kan peryodong panahon.
 Bilang resulta, an mga bisita na naggagamit kaining IP address dae nguna makakamukna nin mga panindog.',
-'emailauthenticated' => 'An saimong e-koreo awtentikado kan $2 sa $3.',
-'emailnotauthenticated' => 'An saimong e-surat dae pa tabi pinagpatunayan. 
-Mayong e-surat an ipapadara para sa arinman kan minasunod na estima.',
+'emailauthenticated' => 'An saimong e-surat na estada pinagkumpirma kan $2 mga alas $3.',
+'emailnotauthenticated' => 'An saimong e-surat na estada dae pa tabi pinagkumpirma.
+Mayo tabing e-surat na ipagpapadara para sa arinman kan mga minasunod na mga estima.',
 'noemailprefs' => 'Magkaag nin sarong e-koreong address sa saimong mga kabotan para gumana ining mga estima.',
 'emailconfirmlink' => 'Kompirmaron tabî an saimong e-koreong address',
 'invalidemailaddress' => 'An e-koreo dae akseptado habang ini minapahiling na igwa nin imbalidong panugmad.
@@ -1057,20 +1059,20 @@ Ika puwedeng makakatanaw kaining diff; mga detalye puwedeng mananagboan sa [{{fu
 'revdelete-text' => "'''Pinagpurang mga pagbabago asin mga pangyayari mahihiling pa man sa historiyang pahina asin mga talaan, pero an mga parte kan saindang laman dae puwedeng magamit kan publiko.'''
 An ibang administrador sa {{SITENAME}} puwede pa man makagamit sa pinagtagong laman asin balewalaon an pagpura kaini giraray sa paagi nin kaparehong panlaog-olay, laen lang kun may kadagdagang pangilin an inilapat.",
 'revdelete-confirm' => 'Pakikumpirma tabi na ika tuyong gumibo kaini, na saimong naintindihan an mga konsekuwensiya, asin ta ika pinaghihimo ini na uyon sa [[{{MediaWiki:Policy-url}}|an palisiya]].',
-'revdelete-suppress-text' => "An paglulubog dapat '''sana''' makakagamit sana para sa minasunod na mga kaso:
+'revdelete-suppress-text' => "An paglulubog dapat '''sana''' magagamit para sa minasunod na mga kaso:
 *Potensiyal na libeloso an impormasyon
 *Bakong angay an personal na impormasyon
-*: ''mga address kan harong asin mga numero kan telepono, sosyal na seguridad, iba pa.''",
+*:''mga estada nin ini-erokan asin mga numero kan telepono, nasyunal na numero nin kabistohan, asin iba pa.''",
 'revdelete-legend' => 'Ilapat an mga restriksyon sa bisibilidad',
-'revdelete-hide-text' => 'Tagoon an teksto kan pagpakaraháy',
+'revdelete-hide-text' => 'Teksto nin rebisyon',
 'revdelete-hide-image' => 'Tagoon an laog kan file',
 'revdelete-hide-name' => 'Tagoon an aksyon asin target',
-'revdelete-hide-comment' => 'Tagoon an komento sa paghirá',
-'revdelete-hide-user' => 'Tagoon an pangaran kan editor/IP',
+'revdelete-hide-comment' => 'Liwaton an sumaryo',
+'revdelete-hide-user' => 'Paraliwat na ngaran-paragamit/IP na estada',
 'revdelete-hide-restricted' => 'Ilubog an mga datos gikan sa mga administrador asin man kan iba',
 'revdelete-radio-same' => '(dae pagribayan)',
-'revdelete-radio-set' => 'Iyo tabi',
-'revdelete-radio-unset' => 'Bako tabi',
+'revdelete-radio-set' => 'Itinago',
+'revdelete-radio-unset' => 'Hiling-hiling',
 'revdelete-suppress' => 'Dai ipahilíng an mga datos sa mga sysops asin sa mga iba pa',
 'revdelete-unsuppress' => 'Halîon an mga restriksyón sa mga ibinalík na pagpakarhay',
 'revdelete-log' => 'Rason:',
@@ -1227,8 +1229,7 @@ Prubaran na panigmitan an saimong kahaputan nin ''all:'' sa paghanap kan gabos n
 'preferences' => 'Mga kabòtan',
 'mypreferences' => 'Mga Kamuyahan ko',
 'prefs-edits' => 'Bilang kan mga hirá:',
-'prefsnologin' => 'Dai nakalaog',
-'prefsnologintext' => 'Ika dapat na magin <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} nakalaog na]</span> tanganing tuytuyon an mga kabotan nin paragamit.',
+'prefsnologintext2' => 'Tabi man $1 tanganing maikaag an mga kamuyahan nin paragamit.',
 'changepassword' => 'Ribayan an sekretong panlaog',
 'prefs-skin' => "''Skin''",
 'skin-preview' => 'Tânawon',
@@ -1500,8 +1501,8 @@ An saimong e-surat na adres dae ipagbuyagyag kunsoarin na an ibang paragamit mak
 'action-block' => 'kubkubon ining paragamit gikan sa pagliliwat',
 'action-protect' => 'ribayan an kurit nin proteksyon para sa pahinang ini',
 'action-rollback' => 'hidaling ipagbalik an mga pagliwat kan huring paragamit na pinagliwat an sarong partikular na pahina',
-'action-import' => 'importaron ining pahina gikan sa ibang wiki',
-'action-importupload' => 'importaron ining pahina gikan sa sarong ikinargang sagunson',
+'action-import' => 'importaron an mga pahina gikan sa ibang wiki',
+'action-importupload' => 'importaron an mga pahina gikan sa sarong ikinargang sagunson',
 'action-patrol' => 'markahan an pagliwat kan iba bilang patrolyado',
 'action-autopatrol' => 'Giboha na an saimong pagliwat markado bilang patrolyado',
 'action-unwatchedpages' => 'tanawon an listahan kan mayong bantay na mga pahina',
@@ -1528,6 +1529,8 @@ An saimong e-surat na adres dae ipagbuyagyag kunsoarin na an ibang paragamit mak
 'recentchanges-label-minor' => 'Ini saro sanang menor na pagliwat',
 'recentchanges-label-bot' => 'Ining pagliwat pinaghimo bilang sarong bot',
 'recentchanges-label-unpatrolled' => 'Ining pagliwat dae pa tabi pinagpatrolyahan',
+'recentchanges-label-plusminus' => 'An kadakulaan nin pahina pinagliwat sa paagi kaining numero nin mga bayta',
+'recentchanges-legend-newpage' => '(hilngon man [[Special:NewPages|listahan kan mga baguhong pahina]])',
 'rcnote' => "Yaon sa ibaba iyo {{PLURAL:$1|an '''1''' pagbabago|an mga huring '''$1''' mga pagbabago}} kan nakaaging huring {{PLURAL:$2|aldaw|'''$2''' mga aldaw}}, poon pa kan $5, $4.",
 'rcnotefrom' => "Sa ibaba iyo an mga kaliwatan poon kan '''$2''' (sagkod sa '''$1''' na ipinapahiling).",
 'rclistfrom' => 'Ipahiling an baguhon na mga kaliwatan magpoon kan $1',
@@ -2025,6 +2028,7 @@ Ini ngunyan minatukdo-liwat pasiring sa [[$2]].',
 'listusers' => 'Lista nin paragamit',
 'listusers-editsonly' => 'Ipahiling sana an mga paragamit na igwang mga pinagliwat',
 'listusers-creationsort' => 'Salansanon sa paagi kan petsa nin pagmukna',
+'listusers-desc' => 'Salansanon sa paibabang pasurunod',
 'usereditcount' => '$1 {{PLURAL:$1|pigliwat|mga pigliwat}}',
 'usercreated' => '{{GENDER:$3|Minukna}} kan $1 sa $2',
 'newpages' => 'Mga bàguhong pahina',
@@ -2245,20 +2249,16 @@ Kontaka an paraliwat:
 e-surat: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Dae na magkakaigwa pa nin ibang pagpapaisi sa kaso na may kadagdagan pang mga pagbabago laen lang kun ika magbisita sa pahinang ini.
-Ika mapuwede man na makapagbago kan bandera nin pagpapaisi para sa gabos mong pinagbabantayan na mga pahina na yaon sa saimong bantay-listahan.
+Dae na magkakaigwa pa nin ibang pagpapaisi sa kaso na may kadagdagan pang aktibidad laen lang kun ika magbisita sa pahinang ini mantang ika nakalaog. Ika mapuwede man na makapagbago kan bandera nin pagpapaisi para sa gabos mong pinagbabantayan na mga pahina na yaon sa saimong bantay-listahan.
 
 An saimong mainamigong {{SITENAME}} sistema nin pagpapaisi
 
 --
-Sa pagbabago kan saimong e-surat na pagpapaising panuytoy, magbisita sa
-{{canonicalurl:{{#special:Mga Kagustuhan}}}}
+Sa pagbabago kan saimong e-surat na pagpapaising panuytoy, magbisita sa {{canonicalurl:{{#special:Mga Kagustuhan}}}}
 
-Sa pagbabago kan saimong bantay-listahang panuytoy, magbisita sa
-{{canonicalurl:{{#special:EditWatchlist}}}}
+Sa pagbabago kan saimong bantay-listahang panuytoy, magbisita sa {{canonicalurl:{{#special:EditWatchlist}}}}
 
-Sa pagpura ka pahina gikan sa saimong bantay-listahan, magbisita sa
-$UNWATCHURL
+Sa pagpura ka pahina gikan sa saimong bantay-listahan, magbisita sa $UNWATCHURL
 
 Balik-simbag asin kadagdagang asistensiya:
 {{canonicalurl:{{MediaWiki:Helppage}}}}',
@@ -2289,10 +2289,12 @@ Hilingón tabì an $2 para mahiling an lista nin mga kaaagi pa sanang pagparà.'
 'deletecomment' => 'Rason:',
 'deleteotherreason' => 'Iba/dugang na rason:',
 'deletereasonotherlist' => 'Ibang rason',
-'deletereason-dropdown' => '*Pirmehang rason nin pagpupura
-** Kahagadan nin Awtor/Parasurat
-** Kalapasan sa Copyright
-** Bandalismo',
+'deletereason-dropdown' => '*Kumon na mga rason nin pagpura
+**Ispam
+**Bandalismo
+**Kalapasan sa Katanosan nin pagsadiri
+**Kahagadan nin Awtor
+**Parasa na panlikwat',
 'delete-edit-reasonlist' => 'Pagliwat kan mga rason nin pagpupura',
 'delete-toobig' => 'Ining pahina igwa nin dakulaong historiya sa pagliwat, minasobrang $1 {{PLURAL:$1|rebisyon|mga rebisyon}}.
 An pagpupura kan nasambit na mga pahina dae pinagtutugot tanganing maiwasan an aksidenteng pagka-antala kan {{SITENAME}}.',
@@ -2313,7 +2315,7 @@ may iba na tabing nagliwat o nagbalik kan pahina.
 An huring pagliwat sa pahina ginibo ni [[User:$3|$3]] ([[User talk:$3|olay]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "An sumaryo kan pagliwat: \"''\$1''\".",
 'revertpage' => 'Ibinalik na mga pagliwat ni [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) sagkod sa huring rebisyon ni [[User:$1|$1]]',
-'revertpage-nouser' => 'Binalikwat na mga pagliliwat kan sarong nakatagong paragamit sa huring rebisyon ni [[User:$1|$1]]',
+'revertpage-nouser' => 'Binalikwat na mga pagliliwat kan sarong nakatagong paragamit sa huring rebisyon ni {{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'Binawî na mga paghirá ni $1; pigbalik sa dating bersyón ni $2.',
 
 # Edit tokens
@@ -2453,7 +2455,7 @@ $1",
 'contributions' => '{{GENDER:$1|Paragamit}} na mga kaambagan',
 'contributions-title' => 'Mga kontribusyon kan paragamit para sa $1',
 'mycontris' => 'Mga Kaarambagan',
-'contribsub2' => 'Para ki $1($2)',
+'contribsub2' => 'Para ki {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Mayong mga pagbabago na nahanap na kapadis sa ining mga criteria.',
 'uctop' => '(sa ngunyan)',
 'month' => 'Poon bulan (asin mas amay):',
@@ -2760,7 +2762,7 @@ Sa kaso kan huri, pwede ka man na maggamit nin takod, arog kan [[{{#Special:Expo
 'allmessagesdefault' => 'Panugmad na tekstong mensahe',
 'allmessagescurrent' => 'Presenteng teksto',
 'allmessagestext' => 'Ini sarong listahan nin pansistemang mga mensahe na mananagboan sa espasyong-pangaran kan MediaWiki.
-Pakibisita an [//www.mediawiki.org/wiki/Localisation Mediawiki Lokalisasyon] asin [//translatewiki.net translatewiki.net] kun boot mong mag-ambag sa henerikong lokalisasyon kan MediaWiki.',
+Pakibisita an [https://www.mediawiki.org/wiki/Localisation Mediawiki Lokalisasyon] asin [//translatewiki.net translatewiki.net] kun boot mong mag-ambag sa henerikong lokalisasyon kan MediaWiki.',
 'allmessagesnotsupportedDB' => "Dai pwedeng gamiton an '''{{ns:special}}:Allmessages''' ta sarado an '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'An Pansara',
 'allmessages-filter' => 'Pansara sa paagi kan estado nin kustomisasyon:',
@@ -2927,6 +2929,7 @@ Ika makakatanaw kan pinaggikanan',
 'tooltip-undo' => '"Gibohang ibalik" an mga pinagbagong pagliliwat asin bukasi an porma nin pagliliwat sa modong patanaw. Ini minatugot na magdadagdag nin rason sa sumaryo.',
 'tooltip-preferences-save' => 'Itagama an mga kagustuhan',
 'tooltip-summary' => 'Magkaag nin sarong halipot na sumaryo',
+'interlanguage-link-title' => '$1 - $2',
 
 # Stylesheets
 'common.css' => '/** an CSS na pigbugtak digdi maiaaplikar sa gabos na mga skin */',
@@ -2960,6 +2963,8 @@ Ini hurot na pinagkausa nin sarong sugpunan pasiring sa sarong pinagbawal na pan
 'spam_reverting' => 'Mabalik sa huring bersion na mayong takod sa $1',
 'spam_blanking' => 'An gabos na mga pahirá na may takod sa $1, pigblablanko',
 'spam_deleting' => 'An gabos na mga rebisyon na igwang mga kasugpunan sa $1, pinupura',
+'simpleantispam-label' => "Rikisa nin Kontra-Ispam.
+Giboha na '''DAE''' paglaogan digde!",
 
 # Info page
 'pageinfo-title' => 'Impormasyon para sa "$1"',
@@ -2973,6 +2978,7 @@ Ini hurot na pinagkausa nin sarong sugpunan pasiring sa sarong pinagbawal na pan
 'pageinfo-length' => 'Kalabaan kan pahina (yaon sa mga bayta)',
 'pageinfo-article-id' => 'ID kan pahina',
 'pageinfo-language' => 'Lengguwahe kan laog sa pahina',
+'pageinfo-content-model' => 'Modelo nin kalamnan nin pahina',
 'pageinfo-robot-policy' => 'Pinaghuhukdo sa paagi nin mga robot',
 'pageinfo-robot-index' => 'Pinagtutugotan',
 'pageinfo-robot-noindex' => 'Dae pinagtutugotan',
@@ -3056,7 +3062,7 @@ Sa pagpapa-andar kaini, an saimong sistema mapupuwedeng makompromiso.",
 'svg-long-desc' => 'SVG na sagunson, nangangaranan nin $1 x $2 na mga piksel, sukol nin sagunson: $3',
 'svg-long-desc-animated' => 'Animatadong SVG na sagunson, nangangaranang $1 x $2 piksel, kadakulaan nin sagunson: $3',
 'svg-long-error' => 'Imbalidong SVG na sagunson: $1',
-'show-big-image' => 'Todong resolusyon',
+'show-big-image' => 'Orihinal na sagunson',
 'show-big-image-preview' => 'Sukol kaining patanaw: $1.',
 'show-big-image-other' => 'Ibang {{PLURAL:$2|resolusyon|mga resoluyon}}: $1.',
 'show-big-image-size' => '$1 × $2 piksel',
@@ -3525,7 +3531,7 @@ Sublokas kan siyudad na ipinahiling',
 
 # External editor support
 'edit-externally' => 'Liwaton ining sagunson na pinaggagamit an panluwasan na aplikasyon',
-'edit-externally-help' => '(Hilngon an [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] para sa kadagdagang impormasyon)',
+'edit-externally-help' => '(Hilngon an [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] para sa kadagdagang impormasyon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'gabos',
@@ -3709,7 +3715,7 @@ Pwede mo man [[Special:EditWatchlist|gamiton an standard editor]].',
 'version-hook-subscribedby' => 'Pinaghaguhot ni',
 'version-version' => '(Bersyon na $1)',
 'version-license' => 'Lisensiya',
-'version-poweredby-credits' => "An wiking ini pinagpagana kan '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "An wiking ini pinagpagana kan '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'mga iba pa',
 'version-poweredby-translators' => 'translatewiki.net na mga paradakit-taramon',
 'version-credits-summary' => 'Gusto niyamong rekonosiron an minasunod na mga persona nin huli kan saindang ambag sa [[Special:Version|Mediawiki]].',
@@ -3728,7 +3734,7 @@ Ika dapat na nakapagresibe na kan [{{SERVER}}{{SCRIPTPATH}}/COPYING sarong kopya
 # Special:Redirect
 'redirect' => 'Palikwatong sa paagi nin sagunson, paragamit, or rebisyon kan ID',
 'redirect-legend' => 'Palikwatong pasiring sa sarong sagunson o pahina',
-'redirect-summary' => 'Ining espesyal na pahina minalikwat pasiring sa sarong sagunson (ipinagtao an ngaran kan sagunson), sarong pahina (ipinagtao an sarong rebisyon kan ID), o sarong pahina nin paragamit (ipinagtao an numerikong ID nin paragamit).',
+'redirect-summary' => 'Ining espesyal na pahina minalikwat pasiring sa sarong sagunson (ipinagtao an ngaran kan sagunson), sarong pahina (ipinagtao an sarong rebisyon kan ID), o sarong pahina nin paragamit (ipinagtao an numerikong ID nin paragamit). Pinaggamitan: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Dumani',
 'redirect-lookup' => 'Hanapon mo',
 'redirect-value' => 'Halaga:',
@@ -3750,8 +3756,8 @@ Ika dapat na nakapagresibe na kan [{{SERVER}}{{SCRIPTPATH}}/COPYING sarong kopya
 
 # Special:SpecialPages
 'specialpages' => 'Mga espesyal na pahina',
-'specialpages-note' => '----
-* Normal espesyal na mga pahina.
+'specialpages-note-top' => 'Balaynan',
+'specialpages-note' => '* Normal na espesyal na mga pahina.
 * <span class="mw-specialpagerestricted">Restriktadong espesyal na mga pahina.</span>',
 'specialpages-group-maintenance' => 'Mga talaan nin pagpangataman',
 'specialpages-group-other' => 'Iba pang mga espesyal na pahina',
@@ -3790,7 +3796,10 @@ Ika dapat na nakapagresibe na kan [{{SERVER}}{{SCRIPTPATH}}/COPYING sarong kopya
 'tags-tag' => 'Ngarang panmarka',
 'tags-display-header' => 'Kinaluwasan sa listahan nin kaliwatan',
 'tags-description-header' => 'Bilog na deskripsyon nin kahulugan',
+'tags-active-header' => 'Aktibo?',
 'tags-hitcount-header' => 'Pinagmarkahan na mga kaliwatan',
+'tags-active-yes' => 'Iyo',
+'tags-active-no' => 'Dae',
 'tags-edit' => 'liwatón',
 'tags-hitcount' => '$1 {{PLURAL:$1|kaliwatan|mga kaliwatan}}',
 
@@ -3956,10 +3965,23 @@ Kun bako man, ika makakagamit nin sayon na porma sa ibaba. An saimong komento id
 'limitreport-ppvisitednodes' => 'Bilang kan tagapagsumpay sa pangenot na tagapagprosesong pinagbisita',
 'limitreport-ppgeneratednodes' => 'Bilang kan tagapagsumpay sa pangenot na tagapagprosesong pinagpuyos',
 'limitreport-postexpandincludesize' => 'Bigak kan paskil kabali an sukol',
-'limitreport-postexpandincludesize-value' => '$1/$2 mga bayta',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bayta|mga bayta}}',
 'limitreport-templateargumentsize' => 'Sukol kan argumentong panguyog',
-'limitreport-templateargumentsize-value' => '$1/$2 mga bayta',
+'limitreport-templateargumentsize-value' => '$1/$2{{PLURAL:$2|bayta|mga bayta}}',
 'limitreport-expansiondepth' => 'Kinatugmadan kan pinakahalangkaw na kahiwasan',
 'limitreport-expensivefunctioncount' => 'Bilang kan hiro nin mamahalon na parabangay',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Bigwakon an mga panguyog',
+'expand_templates_intro' => 'Ining espesyal na pahina minakua nin teksto asin minabigwak kan gabos na mga panguyog na yaon kaini na paoro-otro.
+Ini man minabigwak sa punksyon kan suportadong parabangay na arog kan <code><nowiki>{{</nowiki>#language:…}}</code> asin mga kapilyangan arog kan <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Sa katunayan, ini minapabigwak kan gabos na bagay na yaon sa mga dobleng panandayan.',
+'expand_templates_title' => 'Kontekstong titulo, para sa {{FULLPAGENAME}}, ibpa.:',
+'expand_templates_input' => 'Ikaag an teksto:',
+'expand_templates_output' => 'Resulta',
+'expand_templates_xml_output' => 'Kinaluwasan na XML',
+'expand_templates_remove_comments' => 'Tanggalon an mga komento',
+'expand_templates_remove_nowiki' => 'Pugulan an mga taktak na <nowiki> kan resulta',
+'expand_templates_preview' => 'Patânaw',
+
 );
index 85dab07..1669855 100644 (file)
@@ -20,6 +20,7 @@
  * @author Urhixidur
  * @author Wizardist
  * @author Yury Tarasievich
+ * @author Дзяніс Тутэйшы
  * @author Тест
  * @author Хомелка
  * @author Чаховіч Уладзіслаў
@@ -105,10 +106,10 @@ $messages = array(
 'tog-editsectiononrightclick' => 'Праўка падраздзелаў па правым пстрыку на загалоўку (Яваскрыпт)',
 'tog-showtoc' => 'Паказваць змест (для старонак, дзе больш за 3 падзагалоўкі)',
 'tog-rememberpassword' => 'Памятаць уваходныя даныя ў гэтым браўзеры (не даўжэй за $1 {{PLURAL:$1|дзень|дні|дзён}})',
-'tog-watchcreations' => 'СÑ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b, Ñ\81Ñ\82воÑ\80анÑ\8bÑ\8f Ð¼Ð½Ð¾Ð¹, Ð´Ð°Ð´Ð°Ñ\8eÑ\86Ñ\86а Ð´Ð° Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'tog-watchdefault' => 'СÑ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b Ð¿Ð°Ñ\81лÑ\8f Ð¼Ð°Ñ\96Ñ\85 Ð¿Ñ\80авак Ð´Ð°Ð´Ð°Ñ\8eÑ\86Ñ\86а Ð´Ð° Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'tog-watchmoves' => 'СÑ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b, Ð¿ÐµÑ\80анеÑ\81енÑ\8bÑ\8f Ð¼Ð½Ð¾Ð¹ Ð¿Ð°Ð´ Ñ\96нÑ\88Ñ\83Ñ\8e Ð½Ð°Ð·Ð²Ñ\83, Ð´Ð°Ð´Ð°Ñ\8eÑ\86Ñ\86а Ð´Ð° Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'tog-watchdeletion' => 'СÑ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b, Ñ\81Ñ\86Ñ\91Ñ\80Ñ\82Ñ\8bÑ\8f Ð¼Ð½Ð¾Ð¹, Ð´Ð°Ð´Ð°Ñ\8eÑ\86Ñ\86а Ð´Ð° Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'tog-watchcreations' => 'Ð\94абаÑ\9eлÑ\8fÑ\86Ñ\8c Ñ\81Ñ\82воÑ\80анÑ\8bÑ\8f Ð¼Ð½Ð¾Ñ\8e Ñ\81Ñ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b Ñ\9e Ð¼Ð¾Ð¹ Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'tog-watchdefault' => 'Ð\94абаÑ\9eлÑ\8fÑ\86Ñ\8c Ñ\81Ñ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b Ð¿Ð°Ñ\81лÑ\8f Ð¼Ð°Ñ\96Ñ\85 Ð¿Ñ\80авак Ñ\83 Ð¼Ð¾Ð¹ Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'tog-watchmoves' => 'Ð\94абаÑ\9eлÑ\8fÑ\86Ñ\8c Ð¿ÐµÑ\80айменаванÑ\8bÑ\8f Ð¼Ð½Ð¾Ð¹ Ñ\81Ñ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b Ñ\9e Ð¼Ð¾Ð¹ Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'tog-watchdeletion' => 'Ð\94абаÑ\9eлÑ\8fÑ\86Ñ\8c Ñ\81Ñ\86Ñ\91Ñ\80Ñ\82Ñ\8bÑ\8f Ð¼Ð½Ð¾Ð¹ Ñ\81Ñ\82аÑ\80онкÑ\96 Ñ\96 Ñ\84айлÑ\8b Ñ\9e Ð¼Ð¾Ð¹ Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'tog-minordefault' => 'Пачынаць кожную праўку як дробную',
 'tog-previewontop' => 'Папярэдні паказ — над рэдактарскім полем',
 'tog-previewonfirst' => 'Папярэдні паказ пры першай праўцы',
@@ -125,9 +126,9 @@ $messages = array(
 'tog-watchlisthideown' => 'Не паказваць у назіраным сваіх правак',
 'tog-watchlisthidebots' => 'Не паказваць у назіраным правак, зробленых робатамі',
 'tog-watchlisthideminor' => 'Не паказваць у назіраным дробных правак',
-'tog-watchlisthideliu' => 'Ð\91ез Ð¿Ð°ÐºÐ°Ð·Ñ\83 Ð¿Ñ\80авак Ñ\83дзелÑ\8cнÑ\96каÑ\9e Ð· Ð»Ñ\96кÑ\83 Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'tog-watchlisthideanons' => 'Ð\91ез Ð¿Ð°ÐºÐ°Ð·Ñ\83 Ð°Ð½Ð°Ð½Ñ\96мнÑ\8bÑ\85 Ð¿Ñ\80авак Ð· Ð»Ñ\96кÑ\83 Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'tog-watchlisthidepatrolled' => 'Ð\91ез Ð¿Ð°ÐºÐ°Ð·Ñ\83 Ñ\9eÑ\85валенÑ\8bÑ\85 Ð¿Ñ\80авак Ñ\83 Ð¿ÐµÑ\80алÑ\96кÑ\83 Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'tog-watchlisthideliu' => 'Ð\9dе Ð¿Ð°ÐºÐ°Ð·Ð²Ð°Ñ\86Ñ\8c Ð¿Ñ\80авак Ð·Ð°Ñ\80Ñ\8dгÑ\96Ñ\81Ñ\82Ñ\80аванÑ\8bÑ\85 Ñ\83дзелÑ\8cнÑ\96каÑ\9e Ñ\83 Ð°Ñ\80Ñ\82Ñ\8bкÑ\83лаÑ\85 Ñ\81а Ñ\81пÑ\96Ñ\81а Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'tog-watchlisthideanons' => 'Ð\9dе Ð¿Ð°ÐºÐ°Ð·Ð²Ð°Ñ\86Ñ\8c Ð°Ð½Ð°Ð½Ñ\96мнÑ\8bÑ\85 Ð¿Ñ\80авак Ñ\83 Ð°Ñ\80Ñ\82Ñ\8bкÑ\83лаÑ\85 Ñ\81а Ñ\81пÑ\96Ñ\81а Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'tog-watchlisthidepatrolled' => 'Ð\9dе Ð¿Ð°ÐºÐ°Ð·Ð²Ð°Ñ\86Ñ\8c Ñ\83Ñ\85валенÑ\8bÑ\85 Ð¿Ñ\80авак Ñ\83 Ð°Ñ\80Ñ\82Ñ\8bкÑ\83лаÑ\85 Ñ\81а Ñ\81пÑ\96Ñ\81а Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'tog-ccmeonemails' => 'Слаць мне копіі маіх лістоў',
 'tog-diffonly' => 'Не паказваць рэшты старонкі пад розніцай',
 'tog-showhiddencats' => 'Паказаць схаваныя катэгорыі',
@@ -262,7 +263,7 @@ $messages = array(
 'vector-view-edit' => 'Правіць',
 'vector-view-history' => 'Паказаць гісторыю',
 'vector-view-view' => 'Чытаць',
-'vector-view-viewsource' => 'Ð\9fаказаÑ\86Ñ\8c Ð²Ñ\8bÑ\82оÑ\87ны тэкст',
+'vector-view-viewsource' => 'Ð\9fаказаÑ\86Ñ\8c Ð·Ñ\8bÑ\85одны тэкст',
 'actions' => 'Дзеянні',
 'namespaces' => 'Прасторы імёнаў',
 'variants' => 'Варыянты',
@@ -363,8 +364,6 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Узята з "$1"',
 'youhavenewmessages' => 'Вы маеце $1 ($2).',
-'newmessageslink' => 'новыя паведамленні',
-'newmessagesdifflink' => 'розн. з найноўшай версіяй',
 'youhavenewmessagesfromusers' => 'Вы атрымалі $1 ад {{PLURAL:$3|$3 ўдзельніка|$3 удзельнікаў}} ($2).',
 'youhavenewmessagesmanyusers' => 'Вы атрымалі $1 ад мноства карыстальнікаў ($2).',
 'youhavenewmessagesmulti' => 'У вас ёсць новыя паведамленні на $1',
@@ -417,7 +416,7 @@ $1',
 # General errors
 'error' => 'Памылка',
 'databaseerror' => 'Памылка базы дадзеных',
-'laggedslavemode' => 'Увага: Старонка можа не ўтрымліваць апошніх зменаў.',
+'laggedslavemode' => 'Увага: Старонка можа не ўтрымліваць апошніх змен.',
 'readonly' => 'База звестак заблакаваная',
 'enterlockreason' => 'Упішыце прычыну зачынення, а таксама меркаваны час адчынення',
 'readonlytext' => 'База даных не прыймае новых старонак і іншых змяненняў, таму што яна зараз зачынена, відаць, дзеля абслугоўвання, пасля чаго будзе вернута да нармальнай працы.
@@ -456,12 +455,12 @@ $1',
 
 Функцыя: $1<br />
 Зварот: $2',
-'viewsource' => 'Ð\9fаказаÑ\86Ñ\8c Ð²Ñ\8bÑ\82оÑ\87ны тэкст',
+'viewsource' => 'Ð\9fаказаÑ\86Ñ\8c Ð·Ñ\8bÑ\85одны тэкст',
 'viewsource-title' => 'Прагляд зыходнага тэксту старонкі $1',
 'actionthrottled' => 'Дзеянне прыгашана',
 'actionthrottledtext' => 'Дзеля абароны ад спаму, вам не дазваляецца выконваць гэтае дзеянне занадта часта за пэўны адрэзак часу, і вы гэты ліміт перасягнулі. Паспрабуйце ізноў праз некалькі мінут.',
 'protectedpagetext' => 'Старонка ахоўваецца, каб нельга было яе правіць.',
-'viewsourcetext' => 'Ð\9cожна Ð±Ð°Ñ\87Ñ\8bÑ\86Ñ\8c Ñ\96 ÐºÐ°Ð¿Ñ\96Ñ\80аваÑ\86Ñ\8c ÐºÑ\80Ñ\8bнÑ\96Ñ\87ны тэкст гэтай старонкі:',
+'viewsourcetext' => 'Ð\9cожна Ð±Ð°Ñ\87Ñ\8bÑ\86Ñ\8c Ñ\96 ÐºÐ°Ð¿Ñ\96Ñ\80аваÑ\86Ñ\8c Ð·Ñ\8bÑ\85одны тэкст гэтай старонкі:',
 'viewyourtext' => "Вы можаце праглядзець і скапіяваць зыходны тэкст '''вашых правак''' на гэтай старонцы:",
 'protectedinterface' => 'Старонка ахоўваецца, таму што ўваходзіць у склад інтэрфейсу гэтай праграмы.',
 'editinginterface' => "'''Увага:''' Вы правіце старонку, якая ўтрымлівае тэкст карыстальніцкага інтэрфейсу.
@@ -470,8 +469,8 @@ $1',
 'cascadeprotected' => 'Старонка знаходзіцца пад аховай ад правак, таму што яна ўлучана ў наступн{{PLURAL:$1|ую старонку|ыя старонкі}}, якія ахоўваюцца з магчымасцю "каскаднага распаўсюджвання" аховы:
 $2',
 'namespaceprotected' => "Вам не дазволена правіць старонкі ў прасторы назваў '''$1'''.",
-'customcssprotected' => 'У вас няма дазволу рэдагаваць гэтую CSS-старонку, таму што яна ўтрымлівае асабістыя настаўленні іншага ўдзельніка.',
-'customjsprotected' => 'У вас няма дазволу рэдагаваць гэтую JavaScript-старонку, таму што яна ўтрымлівае асабістыя настаўленні іншага ўдзельніка.',
+'customcssprotected' => 'У вас няма дазволу рэдагаваць гэтую CSS-старонку, бо яна ўтрымлівае асабістыя настройкі іншага ўдзельніка.',
+'customjsprotected' => 'У вас няма дазволу рэдагаваць гэтую JavaScript-старонку, таму што яна ўтрымлівае асабістыя настройкі іншага ўдзельніка.',
 'ns-specialprotected' => 'Не дазволена правіць старонкі ў прасторы назваў {{ns:special}}.',
 'titleprotected' => "Назва засцерагаецца ад стварэння; ахова пастаўлена ўдзельнікам: [[User:$1|$1]].
 Тлумачэнне пастаноўкі пад ахову: ''$2''.",
@@ -487,7 +486,7 @@ $2',
 Можна працягваць працу на {{SITENAME}} ананімна, або можна <span class='plainlinks'>[$1 ўвайсці ў сістэму ізноў]</span>, пад тым самым або пад іншым удзельніцкім імем. Заўважце, што некаторыя старонкі могуць паказвацца так, быццам вы яшчэ не выйшлі; у такім разе трэба ачысціць кэш вашага браўзера.",
 'welcomeuser' => 'Вітаем, $1!',
 'welcomecreation-msg' => 'Ваш рахунак быў створаны.
\9dе Ð·Ð°Ð±Ñ\83дзÑ\8cÑ\86еÑ\81Ñ\8f Ð´Ð°Ð¿Ð°Ñ\81аваÑ\86Ñ\8c [[Special:Preferences|пеÑ\80Ñ\81аналÑ\8cнÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленнÑ\96]] для {{SITENAME}}.',
\9dе Ð·Ð°Ð±Ñ\83дзÑ\8cÑ\86еÑ\81Ñ\8f Ð°Ð¶Ñ\8bÑ\86Ñ\86Ñ\8fвÑ\96Ñ\86Ñ\8c [[Special:Preferences|наÑ\81Ñ\82Ñ\80ойкÑ\83]] для {{SITENAME}}.',
 'yourname' => 'Імя ўдзельніка',
 'userlogin-yourname' => 'Імя ўліковага запісу',
 'userlogin-yourname-ph' => 'Увядзіце імя вашага ўліковага запісу',
@@ -734,10 +733,10 @@ $2
 'userpage-userdoesnotexist-view' => 'Уліковы запіс удзельніка " $1 "не зарэгістраваны.',
 'blocked-notice-logextract' => 'Гэты карыстальнік у дадзены момант заблакаваны. 
  Апошні запіс журнала блакіровак прыводзіцца ніжэй для даведкі:',
-'clearyourcache' => "'''Заўвага:''' Пасля замацоўвання, вам можа спатрэбіцца ачыстка кэшу браўзера, каб пабачыць унесеныя змяненні. 
+'clearyourcache' => "'''Заўвага:''' Пасля замацоўвання, вам можа спатрэбіцца ачыстка кэшу браўзера, каб убачыць унесеныя змяненні. 
 *'''Firefox / Safari:''' націсніце '''Reload''', утрымліваючы ''Shift'', або націсніце ''Ctrl-F5'' ці ''Ctrl-R'' (''Cmd-R'' на Макінтошах)
 * '''Konqueror:''': націсніце ''Reload'' або ''F5''
-* '''Opera''': увайдзіце ў настаўленні карыстальніка (меню ''Tools'', падпункт ''Preferences''), там ачысціце кэш; * '''Internet Explorer:''' націсніце ''Refresh'', утрымліваючы ''Ctrl'', або націсніце ''Ctrl-F5''
+* '''Opera''': увайдзіце ў настройкі карыстальніка (меню ''Tools'', падпункт ''Preferences''), там ачысціце кэш; * '''Internet Explorer:''' націсніце ''Refresh'', утрымліваючы ''Ctrl'', або націсніце ''Ctrl-F5''
 * '''Google Chrome:''' Націсніце ''Ctrl-Shift-R'' (''⌘-Shift-R'' на Mac)",
 'usercssyoucanpreview' => "'''Парада:''' Карыстайцеся кнопкай \"''{{int:showpreview}}''\" для выпрабоўвання новага коду CSS ''перад тым'', як яго запісваць.",
 'userjsyoucanpreview' => "'''Парада:''' Карыстайцеся кнопкай \"''{{int:showpreview}}''\" для выпрабоўвання новага коду JS ''перад тым'', як яго запісваць.",
@@ -768,10 +767,10 @@ $2
 'editingcomment' => 'Правім $1 (новы раздзел)',
 'editconflict' => 'Канфлікт правак: $1',
 'explainconflict' => "Нехта іншы змяніў старонку пасля таго, як вы пачалі працу з ёю.
\92еÑ\80Ñ\85нÑ\8fе Ñ\82Ñ\8dкÑ\81Ñ\82авае Ð¿Ð¾Ð»Ðµ Ð¿Ð°ÐºÐ°Ð·Ð²Ð°Ðµ Ð°ÐºÑ\82Ñ\83алÑ\8cнÑ\8b ÐºÑ\80Ñ\8bнÑ\96Ñ\87ны тэкст старонкі.
-Вашыя праўкі паказаныя ў ніжнім тэкставым полі.
\92ам Ñ\82Ñ\80Ñ\8dба Ð±Ñ\83дзе Ð´Ð°Ð»Ñ\83Ñ\87Ñ\8bÑ\86Ñ\8c Ñ\96Ñ\85 Ð´Ð° Ð°ÐºÑ\82Ñ\83алÑ\8cнага ÐºÑ\80Ñ\8bнÑ\96Ñ\87нага тэксту.
-'''Толькі''' тэкст у верхнім полі будзе замацаваны, калі націснуць \"{{int:savearticle}}\".",
\92еÑ\80Ñ\85нÑ\8fе Ñ\82Ñ\8dкÑ\81Ñ\82авае Ð¿Ð¾Ð»Ðµ Ð¿Ð°ÐºÐ°Ð·Ð²Ð°Ðµ Ð°ÐºÑ\82Ñ\83алÑ\8cнÑ\8b Ð·Ñ\8bÑ\85одны тэкст старонкі.
+Вашы праўкі паказаны ў ніжнім тэкставым полі.
\92ам Ñ\82Ñ\80Ñ\8dба Ð±Ñ\83дзе Ð´Ð°Ð»Ñ\83Ñ\87Ñ\8bÑ\86Ñ\8c Ñ\96Ñ\85 Ð´Ð° Ð°ÐºÑ\82Ñ\83алÑ\8cнага Ð·Ñ\8bÑ\85однага тэксту.
+Калі націснуць \"{{int:savearticle}}\", будзе запісаны '''толькі''' тэкст у верхнім полі.",
 'yourtext' => 'Свой тэкст',
 'storedversion' => 'Захаваная версія',
 'nonunicodebrowser' => "'''УВАГА: ваш браўзер не працуе з Унікодам. Каб вы маглі карэктна  правіць старонкі, ужываецца такая штука, што знакі з па-за абсягу ASCII паказваюцца ў рэдактарскім акне як шаснаццаткавыя коды.'''",
@@ -893,7 +892,7 @@ $2
 Паспрабуйце [[Special:Search|пашукаць яе на гэтай Вікі]] сярод новых старонак.',
 
 # Revision deletion
-'rev-deleted-comment' => '(выдаленае кароткае апісанне зменаў)',
+'rev-deleted-comment' => '(выдаленае кароткае апісанне змен)',
 'rev-deleted-user' => '(удзельнік выдалены)',
 'rev-deleted-event' => '(сцёртае дзеянне з журналам)',
 'rev-deleted-user-contribs' => '[імя ўдзельніка альбо IP-адрас выдалены — рэдагаванне скрытыя ад узносаў]',
@@ -1048,7 +1047,7 @@ $1",
 'nextn-title' => 'Наступны{{PLURAL:$1| вынік|я $1 вынікі(аў)}}',
 'shown-title' => 'Паказваць $1 {{PLURAL:$1|вынік|вынікі(аў)}} на старонку',
 'viewprevnext' => 'Гл. ($1 {{int:pipe-separator}} $2) ($3).',
-'searchmenu-legend' => 'Настаўленні пошуку',
+'searchmenu-legend' => 'Настройкі пошуку',
 'searchmenu-exists' => "'''На вікі ёсць старонка \"[[:\$1]]\"'''",
 'searchmenu-new' => "'''Стварыць на гэтай вікі старонку \"[[:\$1]]\"'''",
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|Паказаць старонкі з гэтым прэфіксам]]',
@@ -1093,11 +1092,9 @@ $1",
 'searchdisabled' => 'Функцыя пошуку {{SITENAME}} не працуе. Тымчасова можна шукаць з дапамогай Google. Заўважце, што тамтэйшыя індэксы зместу {{SITENAME}} могуць не быць актуальнымі.',
 
 # Preferences page
-'preferences' => 'Настаўленні',
-'mypreferences' => 'Настáўленні',
+'preferences' => 'Настройкі',
+'mypreferences' => 'Настройкі',
 'prefs-edits' => 'Колькасць правак:',
-'prefsnologin' => 'Не ўвайшлі',
-'prefsnologintext' => 'Належыць <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} увайсці ў сістэму]</span>, каб мяняць свае настаўленні.',
 'changepassword' => 'Пароль',
 'prefs-skin' => 'Вокладка',
 'skin-preview' => 'перадпаказ',
@@ -1107,7 +1104,7 @@ $1",
 'prefs-labs' => 'Эксперыментальныя магчымасці',
 'prefs-personal' => 'Удзельнік',
 'prefs-rc' => '{{:{{ns:mediawiki}}:Recentchanges/be}}',
-'prefs-watchlist' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'prefs-watchlist' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'prefs-watchlist-days' => 'За колькі дзён паказваць змяненні ў назіраным:',
 'prefs-watchlist-days-max' => '(найбольш $1 {{PLURAL:$1|дзень|дзён}})',
 'prefs-watchlist-edits' => 'Колькасць правак для паказу ў разгорнутым выглядзе:',
@@ -1133,7 +1130,7 @@ $1",
 'recentchangesdays-max' => '(найбольш $1 {{PLURAL:$1|дзень|дзён}})',
 'recentchangescount' => 'Прадвызначаная колькасць правак дзеля паказу:',
 'prefs-help-recentchangescount' => 'Гэта ўключае ў сябе апошнія змены, гісторыі старонак, журналы.',
-'savedprefs' => 'Настáўленні замацаваныя.',
+'savedprefs' => 'Настройкі замацаваныя.',
 'timezonelegend' => 'Часавы пояс:',
 'localtime' => 'Мясцовы час:',
 'timezoneuseserverdefault' => 'Карыстацца настаўленнямі серверу ($1)',
@@ -1160,7 +1157,7 @@ $1",
 'prefs-custom-css' => 'Уласны CSS',
 'prefs-custom-js' => 'Уласны JS',
 'prefs-common-css-js' => 'Агульны CSS/JavaScript для ўсіх вокладак:',
-'prefs-reset-intro' => 'Тут можна вярнуць свае настаўленні да прадвызначэнняў, прынятых на гэтай пляцоўцы.
+'prefs-reset-intro' => 'Тут можна вярнуць свае настройкі да прадвызначэнняў, прынятых на гэтай пляцоўцы.
 Адкаціць гэтае дзеянне нельга.',
 'prefs-emailconfirm-label' => 'Пацверджанне адрасу эл.пошты:',
 'youremail' => 'Эл.пошта *',
@@ -1174,7 +1171,7 @@ $1",
 'prefs-help-variant' => 'Упадабаны для адлюстравання змесціва старонак вікі варыянт мовы ці арфаграфія.',
 'yournick' => 'Псеўданім:',
 'prefs-help-signature' => 'Вашыя выказванні ў размоўных старонках павінны быць падпісаныя знакамі "<nowiki>~~~~</nowiki>", якія аўтаматычна ператвараюцца ў ваш подпіс і час запісу.',
-'badsig' => 'Ð\9dедапÑ\83Ñ\88Ñ\87алÑ\8cнÑ\8b ÐºÑ\80Ñ\8bнÑ\96Ñ\87ны тэкст подпісу; праверце тэгі HTML.',
+'badsig' => 'Ð\9dедапÑ\83Ñ\88Ñ\87алÑ\8cнÑ\8b Ð·Ñ\8bÑ\85одны тэкст подпісу; праверце тэгі HTML.',
 'badsiglength' => 'Занадта доўгі подпіс. Трэба, каб ён быў карацейшым за $1 {{PLURAL:$1|знак|знакаў}}.',
 'yourgender' => 'Пол:',
 'gender-unknown' => 'Нявызначаны',
@@ -1191,11 +1188,11 @@ $1",
 'prefs-signature' => 'Подпіс',
 'prefs-dateformat' => 'Фармат даты',
 'prefs-timeoffset' => 'Часавы пояс',
-'prefs-advancedediting' => 'УÑ\81кладненÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленні',
-'prefs-advancedrc' => 'УÑ\81кладненÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленні',
-'prefs-advancedrendering' => 'УÑ\81кладненÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленні',
-'prefs-advancedsearchoptions' => 'УÑ\81кладненÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленні',
-'prefs-advancedwatchlist' => 'УÑ\81кладненÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82аÑ\9eленні',
+'prefs-advancedediting' => 'Ð\90гÑ\83лÑ\8cнÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
+'prefs-advancedrc' => 'Ð\9fаÑ\88Ñ\8bÑ\80анÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
+'prefs-advancedrendering' => 'Ð\9fаÑ\88Ñ\8bÑ\80анÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
+'prefs-advancedsearchoptions' => 'Ð\9fаÑ\88Ñ\8bÑ\80анÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
+'prefs-advancedwatchlist' => 'Ð\9fаÑ\88Ñ\8bÑ\80анÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
 'prefs-displayrc' => 'Паказ',
 'prefs-displaysearchoptions' => 'Паказ',
 'prefs-displaywatchlist' => 'Паказ',
@@ -1358,7 +1355,7 @@ $1",
 'action-sendemail' => 'адпраўка электронных пісем',
 
 # Recent changes
-'nchanges' => '$1 {{PLURAL:$1|змена|змены|зменаў}}',
+'nchanges' => '$1 {{PLURAL:$1|змена|змены|змен}}',
 'recentchanges' => 'Апошнія змены',
 'recentchanges-legend' => 'Магчымасці паказу',
 'recentchanges-summary' => 'Гэта апошнія мены на пляцоўцы {{SITENAME}}.',
@@ -1367,6 +1364,7 @@ $1",
 'recentchanges-label-minor' => 'Гэта дробная па значэнні праўка',
 'recentchanges-label-bot' => 'Праўка была зробленая праграмай-робатам',
 'recentchanges-label-unpatrolled' => 'Праўка яшчэ не атрымала адзнакі ўхваленасці (за ёй не сочыць "патруль")',
+'recentchanges-legend-newpage' => '$1 - новая старонка',
 'rcnote' => "Ніжэй паказан{{PLURAL:$1|а '''1''' змяненне|ыя апошнія '''$1''' змяненняў}} за апошні{{PLURAL:$2| дзень|я '''$2''' дзён}}, паводле стану на $5, $4.",
 'rcnotefrom' => 'Ніжэй знаходзяцца змены з <b>$2</b> (да <b>$1</b> на старонку).',
 'rclistfrom' => 'Паказаць змены з $1',
@@ -1376,7 +1374,7 @@ $1",
 'rcshowhideanons' => '$1 ананімных удзельнікаў',
 'rcshowhidepatr' => '$1 ухваленых правак',
 'rcshowhidemine' => '$1 ўласных правак',
-'rclinks' => 'Паказаць апошнія $1 зменаў за мінулыя $2 дзён<br />$3',
+'rclinks' => 'Паказаць апошнія $1 змен за мінулыя $2 дзён<br />$3',
 'diff' => 'розн.',
 'hist' => 'гіст.',
 'hide' => 'без уліку',
@@ -1962,19 +1960,19 @@ $1',
 
 # Watchlist
 'watchlist' => 'Мой спіс назіранага',
-'mywatchlist' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'mywatchlist' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'watchlistfor2' => 'Для $1 $2',
-'nowatchlist' => 'Ð\92аÑ\88 Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага зараз пусты.',
-'watchlistanontext' => 'Ð\9aаб Ð±Ð°Ñ\87Ñ\8bÑ\86Ñ\8c Ð°Ð±Ð¾ Ð¿Ñ\80авÑ\96Ñ\86Ñ\8c Ñ\81кладнÑ\96кÑ\96 Ð½Ð°Ð·Ñ\96Ñ\80анага, трэба $1.',
+'nowatchlist' => 'Ð\92аÑ\88 Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f зараз пусты.',
+'watchlistanontext' => 'Ð\9aаб Ð¿Ð°Ð³Ð»Ñ\8fдзеÑ\86Ñ\8c Ñ\86Ñ\96 Ð·Ð¼Ñ\8fнÑ\96Ñ\86Ñ\8c Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f, трэба $1.',
 'watchnologin' => 'Без прадстаўлення',
-'watchnologintext' => 'Ð\9aаб Ð¿Ñ\80авÑ\96Ñ\86Ñ\8c Ñ\81вой Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага, трэба [[Special:UserLogin|ўвайсці ў сістэму]].',
+'watchnologintext' => 'Ð\9aаб Ð¿Ñ\80авÑ\96Ñ\86Ñ\8c Ñ\81вой Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f, трэба [[Special:UserLogin|ўвайсці ў сістэму]].',
 'addwatch' => 'Дадаць у назіранае',
 'addedwatchtext' => "Старонка \"[[:\$1]]\" была дададзена да [[Special:Watchlist|назіраных]] вамі.
 Змяненні, якія адбудуцца з гэтай старонкай і з Размовай пра яе, будуць паказвацца там, і старонка будзе '''вылучацца шрыфтам''' у [[Special:RecentChanges|спісе нядаўніх змяненняў]], каб лягчэй пазнаваць яе.
 
 Калі вы не пажадаеце больш назіраць за гэтай старонкай, націсніце \"Не назіраць\" у бакоўцы.",
 'removewatch' => 'Выдаліць са спісу назірання',
-'removedwatchtext' => 'Старонка "[[:$1]]" была вынятая з вашага [[Special:Watchlist|спісу назіранага]].',
+'removedwatchtext' => 'Старонка "[[:$1]]" была вынята з вашага [[Special:Watchlist|спіса назірання]].',
 'watch' => 'Назіраць',
 'watchthispage' => 'Назіраць за гэтай старонкай',
 'unwatch' => 'Не назіраць',
@@ -1986,14 +1984,14 @@ $1',
 'wlheader-showupdated' => "Старонкі, якія былі зменены пасля вашага апошняга іх наведвання, паказаны '''абрысам шрыфту'''.",
 'watchmethod-recent' => 'правяраем нядаўнія праўкі ў назіраных старонках',
 'watchmethod-list' => 'правяраем наяўнасць нядаўніх правак ў назіраных старонках',
-'watchlistcontains' => 'У Ð²Ð°Ñ\88Ñ\8bм Ñ\81пÑ\96Ñ\81е Ð½Ð°Ð·Ñ\96Ñ\80анага $1 {{PLURAL:$1|Ñ\81Ñ\82аÑ\80онка|старонак}}.',
+'watchlistcontains' => 'У Ð²Ð°Ñ\88Ñ\8bм Ñ\81пÑ\96Ñ\81е Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f $1 {{PLURAL:$1|Ñ\81Ñ\82аÑ\80онка|Ñ\81Ñ\82аÑ\80онкÑ\96|старонак}}.',
 'iteminvalidname' => "Праблема са складнікам '$1', недапушчальная назва...",
 'wlnote' => "Ніжэй {{PLURAL:$1|паказана апошняе $1 змена|паказаны апошнія $1 змены|паказаны апошнія $1 змен}} за {{PLURAL:$2|апошнюю|апошнія|апошнія}} '''$2''' {{plural:$2|гадзіну|гадзіны|гадзіны}}, на момант часу $3 $4.",
 'wlshowlast' => 'Паказваць апошнія $1 гадз. $2 дзён $3',
 'watchlist-options' => 'Магчымасці назірання',
 
 # Displayed when you click the "watch" button and it is in the process of watching
-'watching' => 'Дапісваецца да назіранага...',
+'watching' => 'Дапісваецца ў спіс назірання...',
 'unwatching' => 'Спыняем назіранне...',
 'watcherrortext' => 'Адбылася памылка пры змене настройкі назірання для «$1».',
 
@@ -2092,7 +2090,7 @@ $UNWATCHURL
 'protectedarticle' => 'пад аховай «[[$1]]»',
 'modifiedarticleprotection' => 'зменены ўзровень аховы "[[$1]]"',
 'unprotectedarticle' => 'знятая ахова з "[[$1]]"',
-'movedarticleprotection' => 'настаўленні аховы перанесеныя з "[[$2]]" у "[[$1]]"',
+'movedarticleprotection' => 'настройкі аховы перанесеныя з "[[$2]]" у "[[$1]]"',
 'protect-title' => 'Ахова «$1»',
 'protect-title-notallowed' => 'Прагляд узроўня аховы «$1»',
 'prot_1movedto2' => '[[$1]] перанесена ў [[$2]]',
@@ -2105,11 +2103,11 @@ $UNWATCHURL
 'protect_expiry_old' => 'Час сканчэння — у мінулым.',
 'protect-unchain-permissions' => 'Адкрыць падрабязныя магчымасці аховы',
 'protect-text' => "Тут можна пабачыць і паправіць узровень аховы для старонкі '''$1'''.",
-'protect-locked-blocked' => "Вы заблакаваны і не можаце мяняць узроўняў аховы. Вось актуальныя настаўленні для старонкі '''$1''':",
+'protect-locked-blocked' => "Вы заблакаваны і не можаце мяняць узроўняў аховы. Вось актуальныя настройкі для старонкі '''$1''':",
 'protect-locked-dblock' => "Немагчыма мяняць узроўні аховы, таму што база даных зараз зачынена.
-Вось актуальныя настаўленні аховы для старонкі '''$1''':",
-'protect-locked-access' => "Ð\92аÑ\88 Ñ\80аÑ\85Ñ\83нак Ð½Ðµ Ð¼Ð°Ðµ Ð´Ð°Ð·Ð²Ð¾Ð»Ð°ў, патрэбных каб мяняць ахову старонкі.
-Вось актуальныя настаўленні для старонкі '''$1''':",
+Вось актуальныя настройкі аховы для старонкі '''$1''':",
+'protect-locked-access' => "Ð\92аÑ\88 Ñ\80аÑ\85Ñ\83нак Ð½Ðµ Ð¼Ð°Ðµ Ð¿Ñ\80авоў, патрэбных каб мяняць ахову старонкі.
+Вось актуальныя настройкі для старонкі '''$1''':",
 'protect-cascadeon' => 'Старонка зараз ахоўваецца, таму што ўлучана ў наступн{{PLURAL:$1|ую старонку, на якую|ыя старонкі, на якія}} пастаўлена каскадная ахова. Можна змяніць узровень аховы гэтай старонкі, але вынікаў каскаднай аховы гэта не пераможа.',
 'protect-default' => 'Дазваляць усім удзельнікам',
 'protect-fallback' => 'Патрабуецца дазвол "$1"',
@@ -2211,7 +2209,7 @@ $1',
 'contributions-title' => 'Уклад удзельніка $1',
 'mycontris' => 'Уклад',
 'contribsub2' => 'Для $1 ($2)',
-'nocontribs' => 'Не знойдзена зменаў, адпаведных зададзеным параметрам.',
+'nocontribs' => 'Не знойдзена змен, адпаведных зададзеным параметрам.',
 'uctop' => '(апошн.)',
 'month' => 'Ад месяцу (і раней):',
 'year' => 'Ад году (і раней):',
@@ -2286,7 +2284,7 @@ $1',
 'ipbhidename' => 'Не паказваць імя ўдзельніка ў гісторыях правак і ў спісах',
 'ipbwatchuser' => 'Назіраць уласную і размоўную старонкі гэтага ўдзельніка',
 'ipb-disableusertalk' => 'Забараніць гэтаму ўдзельніку рэдагаваць сваю старонку размоў падчас блакіроўкі',
-'ipb-change-block' => 'Змяніць настаўленні блакавання ўдзельніка',
+'ipb-change-block' => 'Змяніць настройкі блакіравання ўдзельніка',
 'ipb-confirm' => 'Пацвердзіць блакіроўку',
 'badipaddress' => 'Недапушчальны адрас IP',
 'blockipsuccesssub' => 'Паспяховае блакаванне',
@@ -2327,7 +2325,7 @@ $1',
 'noautoblockblock' => 'аўтаблок не дазволены',
 'createaccountblock' => 'стварэнне рахунку заблакавана',
 'emailblock' => 'эл.пошта заблакавана',
-'blocklist-nousertalk' => 'не мае дазволу правіць уласную старонку размоваў',
+'blocklist-nousertalk' => 'не мае дазволу правіць уласную старонку размоў',
 'ipblocklist-empty' => 'Спіс блокаў зараз пусты.',
 'ipblocklist-no-results' => 'Няма блокаў на такі адрас IP або на такое імя ўдзельніка.',
 'blocklink' => 'заблакаваць',
@@ -2341,7 +2339,7 @@ $1',
 Ніжэй прыведзены журнал блакіровак:',
 'blocklog-showsuppresslog' => 'Гэты ўдзельнік ужо заблакаваны і скрыты. Журнал утойвання прыведзены ніжэй:',
 'blocklogentry' => 'пастаўлены блок на "[[$1]]", з часам трывання $2 $3',
-'reblock-logentry' => 'змененыя настаўленні блока для [[$1]] з часам згасання $2 $3',
+'reblock-logentry' => 'змененыя настройкі блока для [[$1]] з часам згасання $2 $3',
 'blocklogtext' => 'Журнал пастаноўкі і здымання блокаў. Аўтаматычна блакаваныя адрасы IP тут не паказваюцца. Спіс актуальных забарон і блокаў бач у [[Special:BlockList|спісе блокаў IP]].',
 'unblocklogentry' => 'зняты блок з $1',
 'block-log-flags-anononly' => 'толькі ананімныя ўдзельнікі',
@@ -2356,7 +2354,7 @@ $1',
 'ipb_expiry_temp' => 'Скрытыя блокі на імёны ўдзельнікаў мусяць быць сталымі.',
 'ipb_hide_invalid' => 'Немагчыма заглушыць гэты рахунак; магчыма, для яго маецца зашмат правак.',
 'ipb_already_blocked' => '"$1" ужо знаходзіцца пад блокам',
-'ipb-needreblock' => '$1 Ñ\83жо Ð·Ð½Ð°Ñ\85одзÑ\96Ñ\86Ñ\86а Ð¿Ð°Ð´ Ð±Ð»Ð¾ÐºÐ°Ð¼. Ð¦Ñ\96 Ð¶Ð°Ð´Ð°ÐµÑ\86е Ð·Ð¼Ñ\8fнÑ\96Ñ\86Ñ\8c Ð½Ð°Ñ\81Ñ\82аÑ\9eленнÑ\96 Ð±Ð»Ð¾ÐºÐ°?',
+'ipb-needreblock' => '$1 Ñ\83жо Ð·Ð°Ð±Ð»Ð°ÐºÑ\96Ñ\80аванÑ\8b. Ð\96адаеÑ\86е Ð·Ð¼Ñ\8fнÑ\96Ñ\86Ñ\8c Ð½Ð°Ñ\81Ñ\82Ñ\80ойкÑ\96 Ð±Ð»Ð°ÐºÑ\96Ñ\80оÑ\9eкÑ\96?',
 'ipb-otherblocks-header' => '{{PLURAL:$1|Іншая блакіроўка|Іншыя блакіроўкі}}',
 'unblock-hideuser' => 'Вы не можаце разблакаваць гэтага ўдзельніка, бо яго імя было ўтоена.',
 'ipb_cant_unblock' => 'Памылка: не знойдзены блок з ID $1. Магчыма, ён ўжо быў зняты.',
@@ -2377,9 +2375,9 @@ $1',
 # Developer tools
 'lockdb' => 'Замкнуць базу дадзеных',
 'unlockdb' => 'Адмыкнуць базу дадзеных',
-'lockdbtext' => 'Зачыненне базы даных прыпыніць для ўсіх удзельнікаў магчымасць правіць старонкі, настаўленні, спісы назіранага, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
-Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта, і што вы адчыніце базу даных па сканчэнні абслугоўвання.',
-'unlockdbtext' => 'Адчыненне базы даных верне ўсім удзельнікам магчымасць правіць старонкі, настаўленні, спісы назіранага, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
+'lockdbtext' => 'Зачыненне базы даных прыпыніць для ўсіх удзельнікаў магчымасць правіць старонкі, настройкі, спісы назірання, а таксама ажыццяўляць іншыя дзеянні, для якіх патрэбен доступ да базы даных.
+Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта, і што вы адчыніце базу даных па заканчэнні абслугоўвання.',
+'unlockdbtext' => 'Адчыненне базы даных верне ўсім удзельнікам магчымасць правіць старонкі, настройкі, спісы назірання, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
 Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта.',
 'lockconfirm' => 'Так, сапраўды жадаю зачыніць базу даных.',
 'unlockconfirm' => 'Так, сапраўды жадаю адмыкнуць базу дадзеных.',
@@ -2603,9 +2601,9 @@ $1',
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'Ваша ўласная старонка',
 'tooltip-pt-anonuserpage' => 'Старонка ўдзельніка для таго IP, з якога вы зараз працуеце',
-'tooltip-pt-mytalk' => 'Ваша старонка размоваў',
+'tooltip-pt-mytalk' => 'Ваша старонка размоў',
 'tooltip-pt-anontalk' => 'Размовы аб праўках, зробленых з гэтага адрасу IP',
-'tooltip-pt-preferences' => 'Свае Ð½Ð°Ñ\81Ñ\82áÑ\9eленні',
+'tooltip-pt-preferences' => 'Ð\92аÑ\88Ñ\8b Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі',
 'tooltip-pt-watchlist' => 'Пералік старонак, за змяненнямі ў якіх вы сочыце',
 'tooltip-pt-mycontris' => 'Пералік вашага ўкладу',
 'tooltip-pt-login' => 'Уваходзіць у сістэму неабавязкова, але вас вельмі запрашаюць гэтак зрабіць.',
@@ -2614,7 +2612,7 @@ $1',
 'tooltip-ca-talk' => 'Размовы пра змест гэтай старонкі',
 'tooltip-ca-edit' => 'Старонку можна правіць; ужывайце папярэдні паказ перад замацоўваннем.',
 'tooltip-ca-addsection' => 'Дадаць новы раздзел',
-'tooltip-ca-viewsource' => 'Ð\93Ñ\8dÑ\82аÑ\8f Ñ\81Ñ\82аÑ\80онка Ð°Ñ\85оÑ\9eваеÑ\86Ñ\86а, Ð°Ð»Ðµ Ð¼Ð¾Ð¶Ð½Ð° Ð¿Ð°Ð³Ð»Ñ\8fдзеÑ\86Ñ\8c Ñ\8fе ÐºÑ\80Ñ\8bнÑ\96Ñ\87ны тэкст.',
+'tooltip-ca-viewsource' => 'Ð\93Ñ\8dÑ\82аÑ\8f Ñ\81Ñ\82аÑ\80онка Ð°Ñ\85оÑ\9eваеÑ\86Ñ\86а, Ð°Ð»Ðµ Ð¼Ð¾Ð¶Ð½Ð° Ð¿Ð°Ð³Ð»Ñ\8fдзеÑ\86Ñ\8c Ñ\8fе Ð·Ñ\8bÑ\85одны тэкст.',
 'tooltip-ca-history' => 'Ранейшыя версіі гэтай старонкі.',
 'tooltip-ca-protect' => 'Паставіць ахову на старонку',
 'tooltip-ca-unprotect' => 'Змяніць ахову гэтай старонкі',
@@ -2622,7 +2620,7 @@ $1',
 'tooltip-ca-undelete' => 'Аднавіць праўкі, зробленыя на гэтай старонцы перад тым, як яна была сцёрта',
 'tooltip-ca-move' => 'Перанесці гэтую старонку пад іншую назву',
 'tooltip-ca-watch' => 'Дадаць гэтую старонку да свайго спісу назіраных старонак',
-'tooltip-ca-unwatch' => 'Выняць гэтую старонку з вашага спісу назіранага',
+'tooltip-ca-unwatch' => 'Выняць гэту старонку з вашага спіса назірання',
 'tooltip-search' => 'Знайсці ў {{SITENAME}}',
 'tooltip-search-go' => 'Перайсці да старонкі з дакладна такой назвай, калі такая наогул існуе',
 'tooltip-search-fulltext' => 'Знайсці гэты тэкст у тэкстах старонак',
@@ -2659,14 +2657,14 @@ $1',
 'tooltip-preview' => 'Паказаць, якім будзе вынік — ужывайце перад замацоўваннем!',
 'tooltip-diff' => 'Паказаць, што вы мяняеце ў тэксце.',
 'tooltip-compareselectedversions' => 'Паказаць розніцу паміж дзвюмя азначанымі версіямі гэтай старонкі.',
-'tooltip-watch' => 'Ð\94апÑ\96Ñ\81аÑ\86Ñ\8c Ñ\81Ñ\82аÑ\80онкÑ\83 Ð´Ð° Ñ\81пÑ\96Ñ\81Ñ\83 Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'tooltip-watch' => 'Ð\94абавÑ\96Ñ\86Ñ\8c Ñ\81Ñ\82аÑ\80онкÑ\83 Ñ\9e Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'tooltip-watchlistedit-normal-submit' => 'Выдаліць пазначаныя старонкі',
 'tooltip-watchlistedit-raw-submit' => 'Абнавіць спіс назірання',
 'tooltip-recreate' => 'Аднавіць старонку, хоць яна і была сцёрта',
 'tooltip-upload' => 'Пачаць укладанне',
 'tooltip-rollback' => '"Адкат" адным клікам вяртае тэкст, які быў тут перад адной ці некалькімі праўкамі апошняга аўтара.',
 'tooltip-undo' => '"Адкат" сцірае гэтую праўку і адкрывае для перадпаказу рэдактарскае акно. Так можна упісваць тлумачэнне адкату.',
-'tooltip-preferences-save' => 'Захаваць настаўленні',
+'tooltip-preferences-save' => 'Захаваць настройкі',
 'tooltip-summary' => 'Дайце кароткае апісанне',
 
 # Stylesheets
@@ -3207,7 +3205,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Правіць файл у вонкавай праграме',
-'edit-externally-help' => '(Гл. падрабязней [//www.mediawiki.org/wiki/Manual:External_editors пра настаўлянне старонніх праграм-рэдактараў])',
+'edit-externally-help' => '(Гл. падрабязней [https://www.mediawiki.org/wiki/Manual:External_editors пра настаўлянне старонніх праграм-рэдактараў])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'усе',
@@ -3292,9 +3290,9 @@ $5
 
 # action=watch/unwatch
 'confirm-watch-button' => 'ОК',
-'confirm-watch-top' => 'Ð\94апÑ\96Ñ\81аÑ\86Ñ\8c Ñ\81Ñ\82аÑ\80онкÑ\83 Ð´Ð° Ñ\81пÑ\96Ñ\81Ñ\83 Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'confirm-watch-top' => 'Ð\94абавÑ\96Ñ\86Ñ\8c Ñ\81Ñ\82аÑ\80онкÑ\83 Ñ\9e Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'confirm-unwatch-button' => 'ОК',
-'confirm-unwatch-top' => 'Выняць гэтую старонку з вашага спісу назіранага',
+'confirm-unwatch-top' => 'Выняць гэту старонку з вашага спіса назірання?',
 
 # Multipage image navigation
 'imgmultipageprev' => '← папярэдняя старонка',
@@ -3333,17 +3331,17 @@ $5
 # Watchlist editor
 'watchlistedit-numitems' => 'У назіраным {{PLURAL:$1|1 складнік|$1 складнікаў}}, без уліку размоўных старонак.',
 'watchlistedit-noitems' => 'Нічога не назіраецца.',
-'watchlistedit-normal-title' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'watchlistedit-normal-legend' => 'Ð\92Ñ\8bйманне Ñ\81кладнÑ\96каÑ\9e Ð· Ð½Ð°Ð·Ñ\96Ñ\80анага',
+'watchlistedit-normal-title' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'watchlistedit-normal-legend' => 'Ð\92Ñ\8bдаленне Ñ\81кладнÑ\96каÑ\9e Ñ\81а Ñ\81пÑ\96Ñ\81а Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
 'watchlistedit-normal-explain' => 'Назвы старонак з ліку назіраных паказаныя ніжэй. Каб нешта сцерці, адзначце клетку побач з адпаведным радком, пасля чаго націсніце "Выняць складнікі". Таксама можна правіць гэты спіс непасрэдна, [[Special:EditWatchlist/raw|без афармлення]].',
 'watchlistedit-normal-submit' => 'Выняць складнікі',
-'watchlistedit-normal-done' => 'Ð\97 Ð½Ð°Ð·Ñ\96Ñ\80анага Ð²Ñ\8bнÑ\8fÑ\82Ñ\8b{{PLURAL:$1| 1 Ñ\81кладнÑ\96к|Ñ\8f $1 складнікаў}}:',
-'watchlistedit-raw-title' => 'Ð\9dеÑ\84аÑ\80маÑ\82аванÑ\8b Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага',
-'watchlistedit-raw-legend' => 'Праца з нефарматаваным спісам назіранага',
+'watchlistedit-normal-done' => 'Ð\97 Ð²Ð°Ñ\88ага Ñ\81пÑ\96Ñ\81а Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f {{PLURAL:$1|бÑ\8bÑ\9e Ð²Ñ\8bдаленÑ\8b|бÑ\8bлÑ\96 Ð²Ñ\8bдаленÑ\8b|бÑ\8bло Ð²Ñ\8bдалена}} $1 {{PLURAL:$1|Ñ\81кладнÑ\96к|Ñ\81кладнÑ\96кÑ\96|складнікаў}}:',
+'watchlistedit-raw-title' => 'Ð\9dеÑ\84аÑ\80маÑ\82аванÑ\8b Ñ\81пÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f',
+'watchlistedit-raw-legend' => 'Правіць нефарматаваны спіс назірання',
 'watchlistedit-raw-explain' => 'Назвы старонак з ліку назіраных паказаныя ніжэй, без афармлення, адна назва на адзін радок; такім чынам, спіс можна правіць як звычайны тэкст. Па сканчэнні націсніце "{{int:Watchlistedit-raw-submit}}". Таксама гэта можна зрабіць праз [[Special:EditWatchlist|стандартны інтэрфейс]].',
 'watchlistedit-raw-titles' => 'Назвы:',
 'watchlistedit-raw-submit' => 'Абнавіць Назіранае',
-'watchlistedit-raw-done' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80анага абноўлены.',
+'watchlistedit-raw-done' => 'СпÑ\96Ñ\81 Ð½Ð°Ð·Ñ\96Ñ\80аннÑ\8f абноўлены.',
 'watchlistedit-raw-added' => 'Дапісаны{{PLURAL:$1| 1 складнік|я $1 складнікаў}}:',
 'watchlistedit-raw-removed' => 'Выняты{{PLURAL:$1| 1 складнік|я $1 складнікаў}}:',
 
@@ -3376,7 +3374,7 @@ $5
 'version-hook-subscribedby' => 'Сюды падпісаныя',
 'version-version' => '(Версія $1)',
 'version-license' => 'Ліцэнзія',
-'version-poweredby-credits' => "Пляцоўка працуе на '''[//www.mediawiki.org/ MediaWiki]''', капірайт © 2001-$1 $2.",
+'version-poweredby-credits' => "Пляцоўка працуе на '''[https://www.mediawiki.org/ MediaWiki]''', капірайт © 2001-$1 $2.",
 'version-poweredby-others' => 'іншыя',
 'version-license-info' => "MediaWiki з'яўляецца свабодным праграмным забеспячэннем. Такім чынам, вы можаце паўторна распаўсюджваць прадукт і(або) змяняць яго на ўмовах пагаднення GNU General Public License у тым выглядзе, у якім яно публікуецца фондам Free Software Foundation; сілу мае версія (выпуск) 2 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.
 
@@ -3402,8 +3400,7 @@ MediaWiki распаўсюджваецца, спадзеючыся на прыд
 
 # Special:SpecialPages
 'specialpages' => 'Адмысловыя старонкі',
-'specialpages-note' => '----
-* Звычайныя адмысловыя старонкі.
+'specialpages-note' => '* Звычайныя адмысловыя старонкі.
 * <span class="mw-specialpagerestricted">Адмысловыя старонкі з абмежаваным доступам.</span>
 * <span class="mw-specialpagecached">Закэшаваныя адмысловыя старонкі (могуць быць састарэлымі).</span>',
 'specialpages-group-maintenance' => 'Звесткі аб працы',
@@ -3444,7 +3441,7 @@ MediaWiki распаўсюджваецца, спадзеючыся на прыд
 'tags-description-header' => 'Поўнае апісанне значэння',
 'tags-hitcount-header' => 'Пазначаных правак',
 'tags-edit' => 'правіць',
-'tags-hitcount' => '$1 {{PLURAL:$1|змена|змены|зменаў}}',
+'tags-hitcount' => '$1 {{PLURAL:$1|змена|змены|змен}}',
 
 # Special:ComparePages
 'comparepages' => 'Параўнанне старонак',
index f3e431f..9e56101 100644 (file)
@@ -65,7 +65,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Стварыць_рахунак' ),
        'Deadendpages'              => array( 'Тупіковыя_старонкі' ),
        'DeletedContributions'      => array( 'Выдалены_ўнёсак' ),
-       'Disambiguations'           => array( 'Неадназначнасьці' ),
        'DoubleRedirects'           => array( 'Двайныя_перанакіраваньні' ),
        'Emailuser'                 => array( 'Даслаць_ліст' ),
        'Export'                    => array( 'Экспарт' ),
@@ -538,8 +537,6 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Атрымана з «$1»',
 'youhavenewmessages' => 'Вы атрымалі $1 ($2).',
-'newmessageslink' => 'новыя паведамленьні',
-'newmessagesdifflink' => 'апошняя зьмена',
 'youhavenewmessagesfromusers' => 'Вы атрымалі $1 ад {{PLURAL:$3|іншага ўдзельніка|$3 удзельнікаў}} ($2).',
 'youhavenewmessagesmanyusers' => 'Вы атрымалі $1 ад некалькіх удзельнікаў ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|новае паведамленьне|новыя паведамленьні}}',
@@ -783,7 +780,7 @@ $2',
 Калі ласка, увайдзіце ў сыстэму пасьля яго атрыманьня.',
 'blocked-mailpassword' => 'З Вашага IP-адрасу забароненыя рэдагаваньні, а таму таксама для прадухіленьня шкоды недаступная функцыя аднаўленьня паролю.',
 'eauthentsent' => 'Пацьверджаньне было дасланае на пазначаны адрас электроннай пошты.
-У лісьце ўтрымліваюцца інструкцыі, па выкананьні якіх, Вы зможаце пацьвердзіць, што адрас сапраўды належыць Вам, і на гэты адрас будзе дасылацца пошта адсюль.',
+У лісьце ўтрымліваюцца інструкцыі, па выкананьні якіх Вы зможаце пацьвердзіць, што адрас сапраўды належыць Вам, і на гэты адрас будзе дасылацца пошта адсюль.',
 'throttled-mailpassword' => 'Ліст пра скіданьне паролю ўжо было даслана за {{PLURAL:$1|$1 апошнюю гадзіну|$1 апошнія гадзіны|$1 апошніх гадзінаў}}.
 Для прадухіленьня злоўжываньняў напамін будзе дасылацца не часьцей як аднойчы ў $1 {{PLURAL:$1|гадзіну|гадзіны|гадзінаў}}.',
 'mailerror' => 'Памылка пры адпраўцы электроннай пошты: $1',
@@ -1388,8 +1385,6 @@ $1",
 'preferences' => 'Налады',
 'mypreferences' => 'Налады',
 'prefs-edits' => 'Колькасьць рэдагаваньняў:',
-'prefsnologin' => 'Вы не ўвайшлі ў сыстэму',
-'prefsnologintext' => 'Вам трэба <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ўвайсьці ў сыстэму]</span>, каб зьмяняць свае налады.',
 'changepassword' => 'Зьмяніць пароль',
 'prefs-skin' => 'Афармленьне',
 'skin-preview' => 'Папярэдні прагляд',
@@ -1689,6 +1684,7 @@ $1",
 'recentchanges-label-minor' => 'Гэтае рэдагаваньне — дробнае',
 'recentchanges-label-bot' => 'Гэтае рэдагаваньне зробленае робатам',
 'recentchanges-label-unpatrolled' => 'Гэтае рэдагаваньне яшчэ не было адпатруляванае',
+'recentchanges-legend-newpage' => '$1 — новая старонка',
 'rcnote' => "Ніжэй {{PLURAL:$1|пададзена '''$1''' апошняя зьмена|пададзеныя '''$1''' апошнія зьмены|пададзеныя '''$1''' апошніх зьменаў}} за {{PLURAL:$2|апошні '''$2''' дзень|апошнія '''$2''' дні|апошнія '''$2''' дзён}}, па стане на $5, $4.",
 'rcnotefrom' => "Ніжэй знаходзяцца зьмены з '''$2''' (да '''$1''' на старонку).",
 'rclistfrom' => 'Паказаць зьмены з $1',
@@ -2928,7 +2924,7 @@ $1',
 'allmessagesdefault' => 'Тэкст па змоўчаньні',
 'allmessagescurrent' => 'Цяперашні тэкст',
 'allmessagestext' => 'Сьпіс усіх сыстэмных паведамленьняў, якія існуюць у прасторы назваў MediaWiki.
-Калі ласка, наведайце [//www.mediawiki.org/wiki/Localisation старонку пра лякалізацыю MediaWiki] і [//translatewiki.net translatewiki.net], калі Вы жадаеце ўдзельнічаць у перакладзе MediaWiki.',
+Калі ласка, наведайце [https://www.mediawiki.org/wiki/Localisation старонку пра лякалізацыю MediaWiki] і [//translatewiki.net translatewiki.net], калі Вы жадаеце ўдзельнічаць у перакладзе MediaWiki.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:AllMessages''' не падтрымліваецца, таму што адключанае '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Фільтар',
 'allmessages-filter' => 'Фільтар па стане зьменаў:',
@@ -3120,6 +3116,8 @@ $2',
 'spam_reverting' => 'Адкат да апошняй вэрсіі без спасылак на $1',
 'spam_blanking' => 'Усе вэрсіі ўтрымліваюць спасылкі на $1, чыстка',
 'spam_deleting' => 'Усе вэрсіі ўтрымлівалі спасылкі на $1, выдаляем',
+'simpleantispam-label' => "Праверка анты-спаму.
+'''НЕ''' запаўняйце тут нічога!",
 
 # Info page
 'pageinfo-title' => 'Інфармацыя пра «$1»',
@@ -3693,7 +3691,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Рэдагаваць гэты файл з выкарыстаньнем вонкавай праграмы',
-'edit-externally-help' => '(Глядзіце падрабязнасьці ў [//www.mediawiki.org/wiki/Manual:External_editors інструкцыі па наладцы] (па-ангельску))',
+'edit-externally-help' => '(Глядзіце падрабязнасьці ў [https://www.mediawiki.org/wiki/Manual:External_editors інструкцыі па наладцы] (па-ангельску))',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'усё',
@@ -3884,7 +3882,7 @@ $5
 'version-version' => '(Вэрсія $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Ліцэнзія',
-'version-poweredby-credits' => "{{SITENAME}} працуе на праграмным забесьпячэньні '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "{{SITENAME}} працуе на праграмным забесьпячэньні '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'іншыя',
 'version-poweredby-translators' => 'перакладчыкі з translatewiki.net',
 'version-credits-summary' => 'Нам вельмі хацелася б адзначыць наступных асобаў, што зрабілі ўнёсак у [[Special:Version|MediaWiki]].',
@@ -3905,7 +3903,7 @@ MediaWiki распаўсюджваецца з надзеяй, што будзе
 # Special:Redirect
 'redirect' => 'Перанакіраваньне да файла, удзельніка або вэрсіі старонкі',
 'redirect-legend' => 'Перанакіраваньне да файла або старонкі',
-'redirect-summary' => 'Гэтая спэцыяльная старонка перанакіруе да файла (паводле імя файла), старонкі (паводле нумара вэрсіі) або старонкі ўдзельніка (паводле нумара ўдзельніка).',
+'redirect-summary' => 'Гэтая спэцыяльная старонка перанакіруе да файла (паводле імя файла), старонкі (паводле нумара вэрсіі) або старонкі ўдзельніка (паводле нумара ўдзельніка). Ужываньне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] або [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Перайсьці',
 'redirect-lookup' => 'Шукаць паводле:',
 'redirect-value' => 'Значэньне:',
@@ -3927,8 +3925,7 @@ MediaWiki распаўсюджваецца з надзеяй, што будзе
 
 # Special:SpecialPages
 'specialpages' => 'Спэцыяльныя старонкі',
-'specialpages-note' => '----
-* Звычайныя спэцыяльныя старонкі.
+'specialpages-note' => '* Звычайныя спэцыяльныя старонкі.
 * <strong class="mw-specialpagerestricted">Спэцыяльныя старонкі з абмежаваным доступам.</strong>
 * <span class="mw-specialpagecached">Кэшаваныя спэцыяльныя старонкі (могуць быць састарэлымі).</span>',
 'specialpages-group-maintenance' => 'Тэхнічныя справаздачы',
@@ -4143,4 +4140,21 @@ MediaWiki распаўсюджваецца з надзеяй, што будзе
 'limitreport-expansiondepth' => 'Найбольшая глыбіня разгортваньня',
 'limitreport-expensivefunctioncount' => 'Колькасьць дарагіх функцыяў парсэра',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Разгортваньне шаблёнаў',
+'expand_templates_intro' => 'Гэтая спэцыяльная старонка пераўтварае тэкст і разгортвае ўсе шаблёны рэкурсіўна.
+Адначасова разгортваюцца функцыі парсэра накшталт
+<code><nowiki>{{</nowiki>#language:…}}</code>, і зьменныя накшталт
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>
+Фактычна, гэтая старонка разгортвае амаль усё ўнутры падвойных фігурных дужак.',
+'expand_templates_title' => 'Загаловак старонкі, для {{FULLPAGENAME}} і г.д.:',
+'expand_templates_input' => 'Крынічны тэкст:',
+'expand_templates_output' => 'Вынік',
+'expand_templates_xml_output' => 'вынік у фармаце XML',
+'expand_templates_ok' => 'Добра',
+'expand_templates_remove_comments' => 'Выдаліць камэнтары',
+'expand_templates_remove_nowiki' => 'Падаўляць тэгі <nowiki> у выніку',
+'expand_templates_generate_xml' => 'Паказаць дрэва аналізу XML',
+'expand_templates_preview' => 'Папярэдні прагляд',
+
 );
index f3db6e5..f5dcc0d 100644 (file)
@@ -58,7 +58,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Стари_страници' ),
        'Blankpage'                 => array( 'Празна_страница' ),
        'Block'                     => array( 'Блокиране' ),
-       'Blockme'                   => array( 'Блокирай_ме' ),
        'Booksources'               => array( 'Източници_на_книги' ),
        'BrokenRedirects'           => array( 'Невалидни_пренасочвания' ),
        'Categories'                => array( 'Категории' ),
@@ -68,9 +67,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Създаване_на_сметка' ),
        'Deadendpages'              => array( 'Задънени_страници' ),
        'DeletedContributions'      => array( 'Изтрити_приноси' ),
-       'Disambiguations'           => array( 'Пояснителни_страници' ),
        'DoubleRedirects'           => array( 'Двойни_пренасочвания' ),
        'Emailuser'                 => array( 'Писмо_на_потребител' ),
+       'ExpandTemplates'           => array( 'Разгръщане_на_шаблони' ),
        'Export'                    => array( 'Изнасяне' ),
        'Fewestrevisions'           => array( 'Страници_с_най-малко_версии' ),
        'FileDuplicateSearch'       => array( 'Повтарящи_се_файлове' ),
@@ -109,6 +108,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Защитени_страници' ),
        'Protectedtitles'           => array( 'Защитени_заглавия' ),
        'Randompage'                => array( 'Случайна_страница' ),
+       'RandomInCategory'          => array( 'Случайна_страница_в_категория' ),
        'Randomredirect'            => array( 'Случайно_пренасочване' ),
        'Recentchanges'             => array( 'Последни_промени' ),
        'Recentchangeslinked'       => array( 'Свързани_промени' ),
@@ -246,7 +246,7 @@ $messages = array(
 'tog-hidepatrolled' => 'Скриване на патрулираните редакции от списъка с последните промени',
 'tog-newpageshidepatrolled' => 'Скриване на патрулираните редакции от списъка на новите страници',
 'tog-extendwatchlist' => 'Разширяване на списъка, така че да показва всички промени, не само най-скорошните',
-'tog-usenewrc' => 'Ð\93Ñ\80Ñ\83пиÑ\80ане Ð½Ð° Ð¿Ð¾Ñ\81ледниÑ\82е Ð¿Ñ\80омени Ð¸ Ñ\81пиÑ\81Ñ\8aка Ð·Ð° Ð½Ð°Ð±Ð»Ñ\8eдение Ð¿Ð¾ Ñ\81Ñ\82Ñ\80аниÑ\86и (изиÑ\81ква Ð\94жаваÑ\81кÑ\80ипÑ\82)',
+'tog-usenewrc' => 'Ð\93Ñ\80Ñ\83пиÑ\80ане Ð¿Ð¾ Ñ\81Ñ\82Ñ\80аниÑ\86и Ð½Ð° Ð¿Ñ\80омениÑ\82е Ð¸ Ñ\81пиÑ\81Ñ\8aка Ð·Ð° Ð½Ð°Ð±Ð»Ñ\8eдение',
 'tog-numberheadings' => 'Номериране на заглавията',
 'tog-showtoolbar' => 'Показване на инструментите за редактиране',
 'tog-editondblclick' => 'Редактиране на страниците чрез двойно щракване',
@@ -513,12 +513,10 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Взето от „$1“.',
 'youhavenewmessages' => 'Имате $1 ($2).',
-'newmessageslink' => 'нови съобщения',
-'newmessagesdifflink' => 'разлика с предишната версия',
 'youhavenewmessagesfromusers' => 'Имате $1 от {{PLURAL:$3|друг потребител|$3 потребители}} ($2).',
 'youhavenewmessagesmanyusers' => 'Имате $1 от много потребители ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|ново съобщение|нови съобщения}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|последна промяна|последни промени}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ново съобщение|999=нови съобщения}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|последна промяна|999=последни промени}}',
 'youhavenewmessagesmulti' => 'Имате нови съобщения в $1',
 'editsection' => 'редактиране',
 'editold' => 'редактиране',
@@ -690,7 +688,7 @@ $2',
 'gotaccount' => "Имате ли вече сметка? '''$1'''.",
 'gotaccountlink' => 'Влизане',
 'userlogin-resetlink' => 'Забравени данни за влизане в системата?',
-'userlogin-resetpassword-link' => 'Ð\92Ñ\8aзÑ\81Ñ\82ановÑ\8fване Ð½Ð° Ð¿Ð°Ñ\80олаÑ\82а',
+'userlogin-resetpassword-link' => 'Ð\97абÑ\80авена Ð¿Ð°Ñ\80ола?',
 'helplogin-url' => 'Help:Влизане',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Помощ за влизане]] в системата',
 'userlogin-loggedin' => 'Вече сте влезли в системата като {{GENDER:$1|$1}}.
@@ -757,7 +755,8 @@ $2',
 'acct_creation_throttle_hit' => 'През последното денонощие, през този IP-адрес посетители на това уики са създали {{PLURAL:$1|1 сметка |$1 сметки}}, което е максималният допустим брой за този период.
 В резултат, към момента не могат да създават повече потребителски сметки през този IP-адрес.',
 'emailauthenticated' => 'Адресът на електронната ви поща беше потвърден на $2 в $3.',
-'emailnotauthenticated' => 'Адресът на електронната ви поща <strong>не е потвърден</strong>. Няма да получавате писма за никоя от следните възможности.',
+'emailnotauthenticated' => 'Адресът на електронната ви поща все още не е потвърден.
+Няма да получавате писма за никоя от следните възможности.',
 'noemailprefs' => 'За да работят тези функционалности, трябва да посочите адрес на електронна поща в своите настройки.',
 'emailconfirmlink' => 'Потвърждаване на адреса за електронна поща',
 'invalidemailaddress' => 'Въведеният адрес не може да бъде приет, тъй като не съответства на формата на адрес за електронна поща. Въведете коректен адрес или оставете полето празно.',
@@ -771,7 +770,7 @@ $2',
 Можете да пренебрегнете това съобщение, ако сметката е създадена по грешка.',
 'usernamehasherror' => 'Потребителското име не може да съдържа хеш символи',
 'login-throttled' => 'Направили сте твърде много опити да въведете паролата за тази сметка.
\98зÑ\87акайÑ\82е Ð¸Ð·Ð²ÐµÑ\81Ñ\82но Ð²Ñ\80еме преди да опитате отново.',
\9dеобÑ\85одимо Ðµ Ð´Ð° Ð¸Ð·Ñ\87акаÑ\82е $1 преди да опитате отново.',
 'login-abort-generic' => 'Влизането беше неуспешно - Прекратено',
 'loginlanguagelabel' => 'Език: $1',
 'suspicious-userlogout' => 'Заявката ви за излизане от системата беше отхвърлена, тъй като изглежда е била изпратена погрешка от браузъра или кеширащото прокси.',
@@ -1037,8 +1036,8 @@ $2
 'edit-gone-missing' => 'Страницата не можа да се обнови.
 Вероятно междувременно е била изтрита.',
 'edit-conflict' => 'Редакционен конфликт.',
-'edit-no-change' => 'Ð\92аÑ\88аÑ\82а Ñ\80едакÑ\86иÑ\8f Ð±ÐµÑ\88е Ð¸Ð³Ð½Ð¾Ñ\80иÑ\80ана, Ñ\82Ñ\8aй ÐºÐ°то не съдържа промени по текста.',
-'postedit-confirmation' => 'Ð\92аÑ\88аÑ\82а Ñ\80едакÑ\86иÑ\8f беше съхранена',
+'edit-no-change' => 'РедакÑ\86иÑ\8fÑ\82а Ð²Ð¸ Ð±ÐµÑ\88е Ð¿Ñ\80енебÑ\80егнаÑ\82а, Ð·Ð°Ñ\89ото не съдържа промени по текста.',
+'postedit-confirmation' => 'РедакÑ\86иÑ\8fÑ\82а Ð²Ð¸ беше съхранена',
 'edit-already-exists' => 'Не можа да се създаде нова страница.
 Такава вече съществува.',
 'defaultmessagetext' => 'Текст на съобщението по подразбиране',
@@ -1169,8 +1168,8 @@ $2
 'revdelete-hide-text' => 'Скриване на текста на версията',
 'revdelete-hide-image' => 'Скриване на файловото съдържание',
 'revdelete-hide-name' => 'Скриване на действието и целта',
-'revdelete-hide-comment' => 'Скриване на коментара',
-'revdelete-hide-user' => 'СкÑ\80иване Ð½Ð° Ð¸Ð¼ÐµÑ\82о/IP-адÑ\80еÑ\81а Ð½Ð° Ð°Ð²тора',
+'revdelete-hide-comment' => 'Скриване на резюмето',
+'revdelete-hide-user' => 'Ð\9fоÑ\82Ñ\80ебиÑ\82елÑ\81ко Ð¸Ð¼Ðµ/IP Ð°Ð´Ñ\80еÑ\81 Ð½Ð° Ñ\80едактора',
 'revdelete-hide-restricted' => 'Прилагане на тези ограничения и за администраторите',
 'revdelete-radio-same' => '(да не се променя)',
 'revdelete-radio-set' => 'Да',
@@ -1322,13 +1321,12 @@ $1",
 'powersearch-togglenone' => 'Никои',
 'search-external' => 'Външно търсене',
 'searchdisabled' => 'Търсенето в {{SITENAME}} е временно изключено. Междувременно можете да търсите чрез Google. Обърнете внимание, че съхранените при тях страници най-вероятно са остарели.',
+'search-error' => 'Възникна грешка при търсене: $1',
 
 # Preferences page
 'preferences' => 'Настройки',
 'mypreferences' => 'Настройки',
 'prefs-edits' => 'Брой редакции:',
-'prefsnologin' => 'Не сте влезли',
-'prefsnologintext' => 'Необходимо е <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} да влезете]</span>, за да може да променяте потребителските си настройки.',
 'changepassword' => 'Смяна на парола',
 'prefs-skin' => 'Облик',
 'skin-preview' => 'предварителен преглед',
@@ -1458,7 +1456,7 @@ $1",
 'userrights-no-interwiki' => 'Нямате права да редактирате потребителските групи на други уикита.',
 'userrights-nodatabase' => 'Базата данни $1 не съществува или не е на локалния сървър.',
 'userrights-nologin' => 'За управление на потребителските права е необходимо [[Special:UserLogin|влизане]] с администраторска сметка.',
-'userrights-notallowed' => 'ТекÑ\83Ñ\89аÑ\82а Ñ\81меÑ\82ка Ð½Ñ\8fма Ð¿Ñ\80ава Ð´Ð° Ð´Ð¾Ð±Ð°Ð²Ñ\8f Ð¸Ð»Ð¸ Ð¿Ñ\80емаÑ\85ва потребителски права.',
+'userrights-notallowed' => 'Ð\9dÑ\8fмаÑ\82е Ð¿Ñ\80ава Ð´Ð° Ð´Ð¾Ð±Ð°Ð²Ñ\8fÑ\82е Ð¸Ð»Ð¸ Ð¿Ñ\80емаÑ\85ваÑ\82е потребителски права.',
 'userrights-changeable-col' => 'Групи, които можете да променяте',
 'userrights-unchangeable-col' => 'Групи, които не можете да променяте',
 
@@ -1596,7 +1594,7 @@ $1",
 'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|от последното посещение}}',
 'enhancedrc-history' => 'история',
 'recentchanges' => 'Последни промени',
-'recentchanges-legend' => 'Ð\9eпÑ\86ии на списъка с последни промени',
+'recentchanges-legend' => 'Ð\9dаÑ\81Ñ\82Ñ\80ойки на списъка с последни промени',
 'recentchanges-summary' => "Проследяване на последните промени в {{SITENAME}}.
 
 Легенда: '''тек''' = разлика на текущата версия,
@@ -1606,6 +1604,7 @@ $1",
 'recentchanges-label-minor' => 'Това е малка промяна',
 'recentchanges-label-bot' => 'Тази редакция е извършена от робот',
 'recentchanges-label-unpatrolled' => 'Тази редакция все още не е проверена',
+'recentchanges-legend-newpage' => '(вижте също [[Special:NewPages|списъка с нови страници]])',
 'rcnote' => "{{PLURAL:$1|Показана е '''1''' промяна|Показани са последните '''$1''' промени}} през {{PLURAL:$2|последния ден|последните '''$2''' дни}}, към $5, $4.",
 'rcnotefrom' => 'Дадени са промените от <strong>$2</strong> (до <strong>$1</strong> показани).',
 'rclistfrom' => 'Показване на промени, като се започва от $1.',
@@ -1836,8 +1835,7 @@ $1',
 'upload_source_file' => ' (файл на вашия компютър)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Тази специална страница показва всички качени файлове.
-При филтриране от потребителя се показват само файловете, за които потребителят е качил последната версия.',
+'listfiles-summary' => 'Тази специална страница показва всички качени файлове.',
 'listfiles_search_for' => 'Търсене по име на файла:',
 'imgfile' => 'файл',
 'listfiles' => 'Списък на файловете',
@@ -1943,6 +1941,11 @@ $1',
 'randompage' => 'Случайна страница',
 'randompage-nopages' => 'В {{PLURAL:$2|следното именно пространство|следните именни пространства}} няма страници: $1.',
 
+# Random page in category
+'randomincategory' => 'Случайна страница в категорията',
+'randomincategory-invalidcategory' => '„$1“ не е валидно име на категория.',
+'randomincategory-nopages' => 'В категория [[:Category:$1|$1]] няма страници.',
+
 # Random redirect
 'randomredirect' => 'Случайно пренасочване',
 'randomredirect-nopages' => 'В именно пространство „$1“ няма пренасочвания.',
@@ -2135,7 +2138,8 @@ $1',
 # Special:ListGroupRights
 'listgrouprights' => 'Права по потребителски групи',
 'listgrouprights-summary' => 'По-долу на тази страница е показан списък на групите потребители в това уики с асоциираните им права за достъп. Допълнителна информация за отделните права може да бъде намерена [[{{MediaWiki:Listgrouprights-helppage}}|тук]].',
-'listgrouprights-key' => '* <span class="listgrouprights-granted">Поверено право</span>
+'listgrouprights-key' => 'Легенда:
+* <span class="listgrouprights-granted">Поверено право</span>
 * <span class="listgrouprights-revoked">Отнето право</span>',
 'listgrouprights-group' => 'Група',
 'listgrouprights-rights' => 'Права',
@@ -2743,7 +2747,7 @@ $1',
 'allmessagesdefault' => 'Текст по подразбиране',
 'allmessagescurrent' => 'Текущ текст',
 'allmessagestext' => 'Тази страница съдържа списък на системните съобщения от именното пространство „МедияУики“.
-Посетете [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] и [//translatewiki.net translatewiki.net], ако желаете да допринесете за общата локализация на софтуера МедияУики.',
+Посетете [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] и [//translatewiki.net translatewiki.net], ако желаете да допринесете за общата локализация на софтуера МедияУики.',
 'allmessagesnotsupportedDB' => "Тази страница не може да бъде използвана, тъй като е изключена възможността '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Филтър',
 'allmessages-filter' => 'Филтриране по ниво на персонализация:',
@@ -2758,6 +2762,8 @@ $1',
 'thumbnail-more' => 'Увеличаване',
 'filemissing' => 'Липсващ файл',
 'thumbnail_error' => 'Грешка при създаване на миникартинка: $1',
+'thumbnail_error_remote' => 'Съобщение за грешка от $1:
+$2',
 'djvu_page_error' => 'Номерът на DjVu-страницата е извън обхвата',
 'djvu_no_xml' => 'Не е възможно вземането на XML за DjVu-файла',
 'thumbnail-temp-create' => 'Временния файл с миникартинка не може да бъде създаден.',
@@ -2926,9 +2932,12 @@ $1',
 'spam_reverting' => 'Връщане на последната версия, несъдържаща препратки към $1',
 'spam_blanking' => 'Всички версии, съдържащи препратки към $1, изчистване',
 'spam_deleting' => 'Всички версии съдържат препратки към $1, изтриване',
+'simpleantispam-label' => "Проверка за спам.
+Необходимо е да '''НЕ''' попълвате това поле!",
 
 # Info page
 'pageinfo-title' => 'Информация за "$1"',
+'pageinfo-not-current' => 'За съжаление тази информация не може да бъде предоставена за стари версии.',
 'pageinfo-header-basic' => 'Основна информация',
 'pageinfo-header-edits' => 'История на редакциите',
 'pageinfo-header-restrictions' => 'Защита на страницата',
@@ -3017,7 +3026,7 @@ $1',
 'svg-long-desc' => 'Файл във формат SVG, основен размер: $1 × $2 пиксела, големина на файла: $3',
 'svg-long-desc-animated' => 'Анимиран SVG файл, основен размер $1 × $2 пиксела, големина на файла: $3',
 'svg-long-error' => 'Невалиден SVG файл: $1',
-'show-big-image' => 'Ð\9fÑ\8aлна Ñ\80азделиÑ\82елна Ñ\81поÑ\81обноÑ\81Ñ\82',
+'show-big-image' => 'Ð\9eÑ\80игинален Ñ\84айл',
 'show-big-image-preview' => 'Размер на този преглед: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Друга разделителна способност|Други разделителни способности}}: $1.',
 'show-big-image-size' => '$1 × $2 пиксела',
@@ -3438,7 +3447,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Редактиране на файла чрез външно приложение',
-'edit-externally-help' => '(За повече информация прегледайте [//www.mediawiki.org/wiki/Manual:External_editors указанията за настройките]).',
+'edit-externally-help' => '(За повече информация прегледайте [https://www.mediawiki.org/wiki/Manual:External_editors указанията за настройките]).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'всички',
@@ -3487,7 +3496,7 @@ $5
 
 Валидността на този код за потвърждение ще важи до $4.',
 'confirmemail_body_set' => 'Някой, вероятно вие, от IP адрес $1,
-е посочил този адрес за електронната поща, свързан с потребителска сметка "$2" в {{SITENAME}}.
+е посочил този адрес за електронната поща, свързан с потребителска сметка „$2“ в {{SITENAME}}.
 
 За потвърждаване, че тази потребителска сметка наистина ви принадлежи и за да активирате отново функциите, свързани с електронна поща в {{SITENAME}}, необходимо е да отворите във вашия браузър следната препратка:
 
@@ -3525,6 +3534,9 @@ $5
 'confirm-unwatch-button' => 'Потвърждаване',
 'confirm-unwatch-top' => 'Премахване на страницата от списъка ви за наблюдение?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1“',
+
 # Multipage image navigation
 'imgmultipageprev' => '← предишна страница',
 'imgmultipagenext' => 'следваща страница →',
@@ -3608,7 +3620,7 @@ $5
 'version-hook-subscribedby' => 'Ползвана от',
 'version-version' => '(Версия $1)',
 'version-license' => 'Лиценз',
-'version-poweredby-credits' => "Това уики се задвиждва от '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Това уики се задвиждва от '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'други',
 'version-poweredby-translators' => 'преводачи в translatewiki.net',
 'version-credits-summary' => 'Бихме искали да изкажем признателност на следните хора за техните приноси към [[Special:Version|MediaWiki]].',
@@ -3641,8 +3653,7 @@ MediaWiki се разпространява с надеждата, че ще б
 
 # Special:SpecialPages
 'specialpages' => 'Специални страници',
-'specialpages-note' => '----
-* Обикновени специални страници.
+'specialpages-note' => '* Обикновени специални страници.
 * <strong class="mw-specialpagerestricted">Специални страници с ограничения.</strong>
 * <span class="mw-specialpagecached">Само складирани специални страници (възможно е да са остарели).</span>',
 'specialpages-group-maintenance' => 'Доклади по поддръжката',
@@ -3676,6 +3687,7 @@ MediaWiki се разпространява с надеждата, че ще б
 'tags' => 'Валидни етикети за промени',
 'tag-filter' => 'Филтър на [[Special:Tags|етикета]]:',
 'tag-filter-submit' => 'Филтриране',
+'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Етикет|Етикети}}]]: $2)',
 'tags-title' => 'Етикети',
 'tags-intro' => 'Тук са изброени всички етикети, които могат да се ползват за отбелязване на редакциите, както и тяхното значение.',
 'tags-tag' => 'Име на етикета',
@@ -3704,6 +3716,7 @@ MediaWiki се разпространява с надеждата, че ще б
 'dberr-problems' => 'Съжаляваме! Сайтът изпитва технически затруднения.',
 'dberr-again' => 'Изчакайте няколко минути и опитайте да презаредите.',
 'dberr-info' => '(Няма достъп до сървъра с базата данни: $1)',
+'dberr-info-hidden' => '(Няма връска със сървъра на базата данни)',
 'dberr-usegoogle' => 'Междувременно опитайте да потърсите в Google.',
 'dberr-outofdate' => 'Имайте предвид, че индексираното от Гугъл наше съдържание може вече да е неактуално.',
 'dberr-cachederror' => 'Следва складирано копие на поисканата страница. Възможно е складираното копие да не е актуално.',
@@ -3747,9 +3760,9 @@ MediaWiki се разпространява с надеждата, че ще б
 'logentry-newusers-create' => 'Потребителската сметка $1 беше {{GENDER:$2|създадена}}',
 'logentry-newusers-create2' => '$1 {{GENDER:$2|създаде}} потребителска сметка $3',
 'logentry-newusers-byemail' => '$1 {{GENDER:$2|създаде}} потребителската сметка $3, като паролата за нея беше изпратена по е-поща',
-'logentry-newusers-autocreate' => 'Сметката $1 беше създадена автоматично',
-'logentry-rights-rights' => '$1 промени потребителската група на $3 от $4 на $5',
-'logentry-rights-rights-legacy' => '$1 промени потребителската група на $3',
+'logentry-newusers-autocreate' => 'Сметката $1 беше {{GENDER:$2|създадена}} автоматично',
+'logentry-rights-rights' => '$1 {{GENDER:$2|промени}} потребителската група на $3 от $4 на $5',
+'logentry-rights-rights-legacy' => '$1 {{GENDER:$2|промени}} потребителската група на $3',
 'logentry-rights-autopromote' => '
 $1 е автоматично повишен от $4 до $5',
 'rightsnone' => '(никакви)',
@@ -3835,4 +3848,16 @@ $1 е автоматично повишен от $4 до $5',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|байт|байта}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|байт|байта}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Разгръщане на шаблони',
+'expand_templates_title' => 'Заглавие на страницата (напр. за {{FULLPAGENAME}}):',
+'expand_templates_input' => 'Входящ текст:',
+'expand_templates_output' => 'Резултат',
+'expand_templates_xml_output' => 'Изход на XML',
+'expand_templates_ok' => 'ОК',
+'expand_templates_remove_comments' => 'Премахване на коментари',
+'expand_templates_remove_nowiki' => 'Потискане на елементите <nowiki> в резултата',
+'expand_templates_generate_xml' => 'Показване на дървото от разбора на XML',
+'expand_templates_preview' => 'Преглед',
+
 );
index 3cc32d8..dac392c 100644 (file)
@@ -320,8 +320,6 @@ $1',
 'ok' => 'ठिक',
 'retrievedfrom' => '"$1" से लियल गईल',
 'youhavenewmessages' => 'रउआ लगे बा $1 ($2).',
-'newmessageslink' => 'नया सन्देश',
-'newmessagesdifflink' => 'अन्तिम परिवर्तन',
 'youhavenewmessagesfromusers' => 'रउआ खातिर {{PLURAL:$3|एगो अन्य सदस्य|$3 अन्य सदस्यन}} के $1 बा। ($2)',
 'youhavenewmessagesmanyusers' => 'रउआ खातिर कई सदस्यन द्वारा $1 बा। ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|एगो नया सन्देश बा|नया सन्देश बाड़न}}',
@@ -907,7 +905,6 @@ Legend: '''({{int:cur}})''' = हाल के संशोधन के सा
 'preferences' => 'वरीयता',
 'mypreferences' => 'राउर पसन्द',
 'prefs-edits' => 'सम्पादन संख्या',
-'prefsnologin' => 'खाता में प्रवेश नईखीं कईले',
 'changepassword' => 'गुप्त शब्द बदलीं',
 'prefs-skin' => 'त्वचा',
 'skin-preview' => 'पूर्वावलोकन',
index fe44b3a..fcf308d 100644 (file)
@@ -61,7 +61,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Judul_nang_buruk' ),
        'Blankpage'                 => array( 'Tungkaran_kusung' ),
        'Block'                     => array( 'Blukir_pamakai' ),
-       'Blockme'                   => array( 'Blukir_ulun' ),
        'Booksources'               => array( 'Sumbar_buku' ),
        'BrokenRedirects'           => array( 'Paugahan_rakai' ),
        'Categories'                => array( 'Daptar_tumbung' ),
@@ -73,8 +72,8 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Ulah_akun' ),
        'Deadendpages'              => array( 'Tungkaran_buntu' ),
        'DeletedContributions'      => array( 'Sumbangan_nang_dihapus' ),
-       'Disambiguations'           => array( 'Disambiguasi' ),
        'EditWatchlist'             => array( 'Babak_daptar_pantauan' ),
+       'ExpandTemplates'           => array( 'Kambangakan_citakan' ),
        'Fewestrevisions'           => array( 'Paubahan_tasadikit' ),
        'FileDuplicateSearch'       => array( 'Panggagaian_barakas_kambar' ),
        'Filepath'                  => array( 'Andakan_barakas' ),
@@ -110,6 +109,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Tungkaran_nang_dilindungi' ),
        'Protectedtitles'           => array( 'Judul_nang_dilindungi' ),
        'Randompage'                => array( 'Tungkaran_babarang' ),
+       'RandomInCategory'          => array( 'Babarang_di_tumbung' ),
        'Randomredirect'            => array( 'Paugahan_babarang' ),
        'Recentchanges'             => array( 'Paubahan_pahanyarnya' ),
        'Recentchangeslinked'       => array( 'Paubahan_tarait' ),
@@ -403,8 +403,6 @@ Lihati [[Special:Version|Tungkaran mudil]]',
 'ok' => 'OK',
 'retrievedfrom' => 'Dijumput matan "$1"',
 'youhavenewmessages' => 'Pian baisi $1 ($2)',
-'newmessageslink' => 'pasan hanyar',
-'newmessagesdifflink' => 'paubahan pauncitnya',
 'youhavenewmessagesfromusers' => 'Pian baisi $1 matan {{PLURAL:$3|$3 pamakai lain}} ($2).',
 'youhavenewmessagesmanyusers' => 'Pian baisi $1 matan pamakai lain ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|pasan hanyar}}',
@@ -1179,8 +1177,6 @@ Catatan nang dihaharnya matan isi {{SITENAME}} kawa-ai sudah kadaluarsa.',
 'preferences' => 'Kakatujuan',
 'mypreferences' => 'Nang ulun katuju',
 'prefs-edits' => 'Rikinan babakan-babakan:',
-'prefsnologin' => 'Balum babuat log',
-'prefsnologintext' => 'Pian harus <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} babuat log]</span> gasat mengeset kakatujuan Pian.',
 'changepassword' => 'Ubah katasunduk',
 'prefs-skin' => 'Kulimbit',
 'skin-preview' => 'Titilikan',
@@ -1453,6 +1449,7 @@ Amun Pian mamilih manyadiakan ini, ini akan dipuruk gasan paminanduan kulihan ga
 'recentchanges-label-minor' => 'Ngini sabuting babakan sapalih',
 'recentchanges-label-bot' => 'Babakan ngini digawi ulih saikung bot',
 'recentchanges-label-unpatrolled' => "Babakan ngini baluman ta'awasi",
+'recentchanges-legend-newpage' => '$1 - tungkaran puga',
 'rcnote' => "Di bawah ni {{PLURAL:$1|'''1'''|'''$1'''}} paubahan pahanyarnya dalam {{PLURAL:$2|'''1''' hari|'''$2''' hari}} tauncit, sampai $4 pukul $5.",
 'rcnotefrom' => "Di bawah ngini paubahan tumatan '''$2''' (ditampaiakan sampai '''$1''' paubahan)",
 'rclistfrom' => 'Tampaiakan paubahan pahanyarnya matan $1',
@@ -2655,7 +2652,7 @@ Dalam kasus pahanyarnya Pian kawa jua mamuruk sabuah tautanm gasan cuntuh [[{{#S
 'allmessagesdefault' => 'Naskah baku pasan',
 'allmessagescurrent' => 'Naskah pasan wayahini.',
 'allmessagestext' => 'Ngini adalah sabuah daptar pasan sistem tasadia dalam ruang-ngaran MediaWiki.
-Muhun ilangi [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] wan [//translatewiki.net translatewiki.net] amun Pian hakun manyumbang palukalan umum MediaWiki.',
+Muhun ilangi [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] wan [//translatewiki.net translatewiki.net] amun Pian hakun manyumbang palukalan umum MediaWiki.',
 'allmessagesnotsupportedDB' => "Tungkaran ngini kada kawa dipuruk karana '''\$wgUseDatabaseMessages''' sudah dipajahakan.",
 'allmessages-filter-legend' => 'Saringan',
 'allmessages-filter' => 'Saringan lawan kaadaan kustom:',
@@ -3369,7 +3366,7 @@ Tautan-tautan abis tu pada baris sama dipartimbangkan sabagai pangacualian, nang
 
 # External editor support
 'edit-externally' => 'Babak barakas ngini puruk sabuah aplikasi luar',
-'edit-externally-help' => '(Lihati [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] untuk panjalasan labih)',
+'edit-externally-help' => '(Lihati [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] untuk panjalasan labih)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'samunyaan',
@@ -3558,7 +3555,7 @@ Pian kawa jua [[Special:EditWatchlist|mamuruk si pambabak standar]].',
 'version-hook-subscribedby' => 'Dilanggani ulih',
 'version-version' => '(Pirsi $1)',
 'version-license' => 'Lisansi',
-'version-poweredby-credits' => "Wiki ngini disukung ulih '''[//www.mediawiki.org/ MediaWiki]''', hak salin © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki ngini disukung ulih '''[https://www.mediawiki.org/ MediaWiki]''', hak salin © 2001-$1 $2.",
 'version-poweredby-others' => 'lainnya',
 'version-credits-summary' => 'Kami ingin ma-akui urang-urang ini atas sumbangan pikiran-tanaga kapada [[Special:Version|MediaWiki]].',
 'version-license-info' => 'MediaWiki adalah parangkat lunak bibas; Pian kawa manyabarakan wan/atawa maubahi ngini di bawah syarat Lisansi Publik Umum sawagai tarbitan ulih Free Software Foundation; apakah Lisansi virsi 2, atawa (pilihan Pian) pahanyarnya.
@@ -3584,8 +3581,7 @@ Pian saharusnya [{{SERVER}}{{SCRIPTPATH}}/COPYING sabuting salinan Lisansi Publi
 
 # Special:SpecialPages
 'specialpages' => 'Tungkaran istimiwa',
-'specialpages-note' => '----
-* Tutungkaran istimiwa normal
+'specialpages-note' => '* Tutungkaran istimiwa normal
 * <span class="mw-specialpagerestricted">Tutungkaran istimiwa tabatas.</span>
 * <span class="mw-specialpagecached">Tutungkaran istimiwa timbuluk (pinanya bakulat).</span>',
 'specialpages-group-maintenance' => 'Lapuran pamaliharaan',
index e9a6f9e..e16248b 100644 (file)
@@ -344,12 +344,10 @@ $1',
 'ok' => 'ঠিক আছে',
 'retrievedfrom' => "'$1' থেকে আনীত",
 'youhavenewmessages' => 'আপনার $1 এসেছে ($2)৷',
-'newmessageslink' => 'নতুন বার্তা',
-'newmessagesdifflink' => 'সর্বশেষ পরিবর্তন',
 'youhavenewmessagesfromusers' => 'আপনি {{PLURAL:$3|অন্য ব্যবহারকারীর|$3 ব্যবহারকারীর}} কাছ থেকে $1 পেয়েছেন ($2)।',
 'youhavenewmessagesmanyusers' => 'আপনি অনেক ব্যবহারকারীর কাছ থেকে $1 পেয়েছেন ($2)।',
-'newmessageslinkplural' => '{{PLURAL:$1|একটি নতুন বার্তা|নতুন বার্তা}}',
-'newmessagesdifflinkplural' => 'সর্বশেষ {{PLURAL:$1|পরিবর্তন|পরিবর্তনসমূহ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|একটি নতুন বার্তা|999=নতুন বার্তা}}',
+'newmessagesdifflinkplural' => 'সর্বশেষ {{PLURAL:$1|পরিবর্তন|999=পরিবর্তনসমূহ}}',
 'youhavenewmessagesmulti' => 'আপনার $1টি নতুন বার্তা এসেছে',
 'editsection' => 'সম্পাদনা',
 'editold' => 'সম্পাদনা',
@@ -479,7 +477,8 @@ $2',
 'invalidtitle-knownnamespace' => 'অবৈধ শিরোনাম, যেখানে নামস্থান "$2" এবং লেখা হয়েছে "$3"',
 'invalidtitle-unknownnamespace' => 'অবৈধ শিরোনাম, যেখানে ব্যবহৃত হয়েছে অপরিচিত নামস্থান সংখ্যা $1 এবং লেখা হয়েছে "$2"',
 'exception-nologin' => 'লগইন করা হয়নি',
-'exception-nologin-text' => 'এই কাজটি করার জন্য উইকিতে লগইন করা প্রয়োজন।',
+'exception-nologin-text' => 'এই কাজটি করার জন্য উইকিতে [[Special:Userlogin|লগইন]] করা প্রয়োজন।',
+'exception-nologin-text-manual' => 'অনুগ্রহ করে এই পাতা দেখতে অথবা পরিবর্তন করতে $1 করুন।',
 
 # Virus scanner
 'virus-badscanner' => "ভুল কনফিগারেশন: অজ্ঞাত ভাইরাস স্কেনার: ''$1''",
@@ -526,7 +525,7 @@ $2',
 'gotaccount' => "আপনার কি ইতিমধ্যে একটি অ্যাকাউন্ট তৈরি করা আছে? '''$1''' করুন।",
 'gotaccountlink' => 'প্রবেশ',
 'userlogin-resetlink' => 'আপনার লগইনের বিস্তারিত তথ্যাদি ভুলে গেছেন?',
-'userlogin-resetpassword-link' => 'শবà§\8dদà¦\9aাবি à¦ªà§\81নরায় à¦§à¦¾à¦°à§\8dয à¦\95রà§\81ন',
+'userlogin-resetpassword-link' => 'শবà§\8dদà¦\9aাবি à¦­à§\81লà§\87 à¦\97à§\87à¦\9bà§\87ন?',
 'helplogin-url' => 'Help:প্রবেশ',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|লগইন সংক্রান্ত সাহায্য]]',
 'userlogin-loggedin' => 'আপনি বর্তমানে {{GENDER:$1|$1}} হিসাবে লগইন আছেন।
@@ -587,13 +586,14 @@ $2',
 'passwordsent' => 'একটি নতুন শব্দচাবি "$1" ব্যবহারকারীর ই-মেইল ঠিকানায় পাঠানো হয়েছে। দয়াকরে তা পাওয়ার পর আবার লগ-ইন করুন।',
 'blocked-mailpassword' => 'আপনার আইপি ঠিকানাটি থেকে সম্পাদনা করতে বাধা আছে, তাই এই ঠিকানার অপব্যবহার করে শব্দচাবি ফেরত আনতে দেয়া যাবে না।',
 'eauthentsent' => 'মনোনীত ই-মেইল ঠিকানায় একটি নিশ্চিতকরণ ই-মেইল পাঠানো হয়েছে।
-à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fিতà§\87 à¦\85নà§\8dয à¦¯à§\87 à¦\95à§\8bন à¦\87-মà§\87à¦\87ল à¦ªà¦¾à¦ à¦¾à¦¨à§\8bর à¦\86à¦\97à§\87 à¦\86পনাà¦\95à§\87 à¦\8fà¦\87 à¦\87-মà§\87à¦\87লà§\87র à¦¨à¦¿à¦°à§\8dদà§\87শà¦\97à§\81লি à¦\85নà§\81সরণ à¦\95রতà§\87 à¦¹à¦¬à§\87, à¦¯à¦¾à¦¤à§\87 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fি à¦¯à§\87 à¦\86সলà§\87à¦\87 à¦\86পনার, à¦¤à¦¾ à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦¹à¦¯à¦¼à¥¤',
+à¦\90 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fà§\87 à¦\85নà§\8dয à¦\95à§\8bন à¦\87-মà§\87à¦\87ল à¦ªà¦¾à¦ à¦¾à¦¨à§\8bর à¦\86à¦\97à§\87 à¦\86পনাà¦\95à§\87 à¦\87-মà§\87à¦\87লà§\87র à¦¨à¦¿à¦°à§\8dদà§\87শà¦\97à§\81লি à¦\85নà§\81সরণ à¦\95রতà§\87 à¦¹à¦¬à§\87, à¦¯à¦¾à¦¤à§\87 à¦\85à§\8dযাà¦\95াà¦\89নà§\8dà¦\9fà¦\9fি à¦¯à§\87 à¦\86সলà§\87à¦\87 à¦\86পনার, à¦¤à¦¾ à¦¨à¦¿à¦¶à§\8dà¦\9aিত à¦¹à¦¯à¦¼à¥¤',
 'throttled-mailpassword' => 'বিগত {{PLURAL:$1|ঘন্টার|$1 ঘন্টার}} মধ্যে ইতিমধ্যেই একবার শব্দচাবি বদলের তথ্য পাঠানো হয়েছে। অপব্যবহার রোধে প্রতি {{PLURAL:$1|ঘন্টায়|$1 ঘন্টায়}} কেবল একবার শব্দচাবি বদলের তথ্য পাঠানো যাবে।',
 'mailerror' => 'ইমেইল পাঠাতে সমস্যা: $1',
 'acct_creation_throttle_hit' => 'এই উইকির দর্শক আপনার IP থেকে বিগত সময়ে {{PLURAL:$1|1 টি অ্যাকাউন্ট|$1 গুলো অ্যাকাউন্ট}} তৈরি করেছেন, যা এই সময়ের জন্য সর্বোচ্চ অনুমোদনকৃত।
 ফলে, এই IP থেকে দর্শক এই সময়ে নতুন অ্যাকাউন্ট তৈরি করতে পারবেন না।',
-'emailauthenticated' => 'আপনার ই-মেইল ঠিকানাটি $2 তারিখের $3 এ নিশ্চিত করা হয়েছে।',
-'emailnotauthenticated' => 'আপনার ই-মেইলের ঠিকানা <strong>এখনও যাচাই করা হয়নি</strong>। নিচের বৈশিষ্ট্যগুলোর (features) জন্য কোনো ই-মেইল পাঠানো হবে না।',
+'emailauthenticated' => 'আপনার ইমেইল ঠিকানাটি $2 তারিখের $3 এ নিশ্চিত করা হয়েছে।',
+'emailnotauthenticated' => 'আপনার ই-মেইলের ঠিকানা এখনও যাচাই করা হয়নি।
+নিচের বৈশিষ্ট্যগুলোর (features) জন্য কোনো ই-মেইল পাঠানো হবে না।',
 'noemailprefs' => 'এই বৈশিষ্টটি কাজ করাতে হলে একটি ই-মেইল ঠিকানা নির্ধারণ করতে হবে।',
 'emailconfirmlink' => 'আপনার ই-মেইলের ঠিকানা নিশ্চিত করুন',
 'invalidemailaddress' => 'এই ই-মেইল ঠিকানাটি গ্রহণযোগ্য নয়, কারণ সম্ভবত এটি সঠিক ফরম্যাটে লেখা হয়নি। অনুগ্রহ করে সঠিক ফরম্যাটে লেখা ই-মেইল ঠিকানা দিন, অথবা ক্ষেত্রটি খালি রাখুন।',
@@ -712,6 +712,7 @@ $2
 'headline_tip' => '২য় স্তরের শিরোনাম',
 'nowiki_sample' => 'অ-ফরম্যাটকৃত টেক্সট এখানে প্রবিষ্ট করুন',
 'nowiki_tip' => 'উইকি ফরম্যাটিং উপেক্ষা করা হোক',
+'image_sample' => 'উদাহরণ.jpg',
 'image_tip' => 'গ্রথিত ফাইল',
 'media_tip' => 'ফাইল সংযোগ',
 'sig_tip' => 'সময় ও তারিখসহ আপনার স্বাক্ষর',
@@ -1020,20 +1021,20 @@ $3-এর দেয়া কারণ হল ''$2''",
 
 {{SITENAME}} এর অন্যান্য প্রশাসকগণ লুকানো এই বিষয়বস্তু দেখতে পাবেন এবং বাড়তি কোনো সীমাবদ্ধতা না থাকলে একই ইন্টারফেসের মাধ্যমে এটি পুনরুদ্ধার করতে পারবেন।",
 'revdelete-confirm' => 'অনুগ্রহ করে নিশ্চিত করুন যে আপনি এটি করতে চাচ্ছিলেন, আপনি এর ফলাফল সম্পর্কে অবগত আছেন, এবং [[{{MediaWiki:Policy-url}}|নীতিমালার]] উপর ভিত্তি করেই এই কাজটি করছেন।',
-'revdelete-suppress-text' => "'''কেবলমাত্র''' নিচের বিষয়গুলোর ক্ষেত্রেই চাপাচাপি করা যাবে:
+'revdelete-suppress-text' => "নিচের বিষয়গুলোর ক্ষেত্রেই '''কেবলমাত্র'''  চাপাচাপি করা যাবে:
 * সম্ভাব্য মানহানিকর তথ্য
 * ভুল ব্যক্তিগত তথ্য
-*:  ''বাসার ঠিকানা এবং ফোন নম্বর, সোসাল সিকিউরিটি নম্বর, ইত্যাদি।''",
+*: ''বাসার ঠিকানা এবং ফোন নম্বর, সোসাল সিকিউরিটি নম্বর, ইত্যাদি।''",
 'revdelete-legend' => 'দৃষ্টিপাত সীমাবদ্ধ করো',
-'revdelete-hide-text' => 'সà¦\82শà§\8bধিত à¦²à§\87à¦\96া à¦\86ড়াল à¦\95রà§\8b',
+'revdelete-hide-text' => 'সà¦\82সà§\8dà¦\95রণà§\87র à¦²à§\87à¦\96া',
 'revdelete-hide-image' => 'ফাইলের বিষয়বস্তু আড়াল করো',
 'revdelete-hide-name' => 'কাজ এবং লক্ষ্য আড়াল করো',
-'revdelete-hide-comment' => 'সম্পাদনা সারাংশ আড়াল করো',
-'revdelete-hide-user' => 'সম্পাদকে ব্যবহারকারীর নাম/আইপি আড়াল করো',
+'revdelete-hide-comment' => 'সম্পাদনা সারাংশ',
+'revdelete-hide-user' => 'সম্পাদকে ব্যবহারকারীর নাম/আইপি',
 'revdelete-hide-restricted' => 'প্রশাসকবৃন্দ এবং অন্যদের ক্ষেত্রে এই ডাটা রোধ করো',
 'revdelete-radio-same' => 'পরিবর্তন নয়',
-'revdelete-radio-set' => 'হà§\8dযাà¦\81',
-'revdelete-radio-unset' => 'না',
+'revdelete-radio-set' => 'লà§\81à¦\95ানà§\8b',
+'revdelete-radio-unset' => 'দà§\83শà§\8dযমান',
 'revdelete-suppress' => 'সব প্রশাসক ও অন্যান্যদের কাছ থেকে উপাত্ত লুকিয়ে রাখা হোক।',
 'revdelete-unsuppress' => 'সংশোধন পুনঃস্থাপনের উপর সীমাবদ্ধতা দূর করো',
 'revdelete-log' => 'কারণ:',
@@ -1188,8 +1189,7 @@ $1",
 'preferences' => 'আমার পছন্দ',
 'mypreferences' => 'পছন্দসমূহ',
 'prefs-edits' => 'সম্পাদনা সংখ্যা:',
-'prefsnologin' => 'আপনি লগ-ইন করেননি',
-'prefsnologintext' => 'ব্যবহারকারীর পছন্দ ঠিক করতে হলে আপনাকে অবশ্যই <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} লগইন]</span> করা অবস্থায় থাকতে হবে।',
+'prefsnologintext2' => 'ব্যবহারকারী পছন্দসমূহ নির্ধারনের জন্য $1 করুন।',
 'changepassword' => 'শব্দচাবি পরিবর্তন',
 'prefs-skin' => 'আবরণ (Skin)',
 'skin-preview' => 'প্রাকদর্শন',
@@ -1486,6 +1486,9 @@ $1",
 'recentchanges-label-minor' => 'এটি একটি অনুল্লেখিত সম্পাদনা',
 'recentchanges-label-bot' => 'এটি বট দ্বারা সম্পাদিত',
 'recentchanges-label-unpatrolled' => 'এই সম্পাদনাটি এখনও পরীক্ষিত নয়',
+'recentchanges-label-plusminus' => 'পাতার আকারে এই পরিমান বাইট পরিবর্তিত হয়েছে',
+'recentchanges-legend-newpage' => '(আরও দেখুন [[Special:NewPages|নতুন পাতার তালিকা]])',
+'recentchanges-legend-plusminus' => "(''±১২৩'')",
 'rcnote' => "বিগত {{PLURAL:$2|দিনে|'''$2''' দিনে}} সংঘটিত {{PLURAL:$1|'''১'''|'''$1'''}}টি পরিবর্তন নীচে দেখানো হল (যেখানে বর্তমান সময় ও তারিখ $5, $4)।",
 'rcnotefrom' => "'''$2'''-এর পরে সংঘটিত পরিবর্তনগুলো নিচে দেখানো হল ('''$1'''টি)।",
 'rclistfrom' => '$1-এর পর সংঘটিত নতুন পরিবর্তনগুলো দেখাও।',
@@ -2202,7 +2205,7 @@ $PAGEINTRO $NEWPAGE
 ইমেইল: $PAGEEDITOR_EMAIL
 উইকি: $PAGEEDITOR_WIKI
 
-পাতাটির পরবর্তী পরিবর্তনগুলো জন্য আর কোন বিজ্ঞপ্তি পাঠানো হবে না, যতক্ষণ না আপনি এই পাতায় ব্রাউজ করবেন। এছাড়া আপনি আপনার নজরতালিকায় রাখা সবগুলি পাতা জন্য বিজ্ঞপ্তি ফ্ল্যাগ শুরুর অবস্থায় ফিরিয়ে নিতে পারেন।
+পাতাà¦\9fির à¦ªà¦°à¦¬à¦°à§\8dতà§\80 à¦ªà¦°à¦¿à¦¬à¦°à§\8dতনà¦\97à§\81লà§\8b à¦\9cনà§\8dয à¦\86র à¦\95à§\8bন à¦¬à¦¿à¦\9cà§\8dà¦\9eপà§\8dতি à¦ªà¦¾à¦ à¦¾à¦¨à§\8b à¦¹à¦¬à§\87 à¦¨à¦¾, à¦¯à¦¤à¦\95à§\8dষণ à¦¨à¦¾ à¦\86পনি à¦²à¦\97 à¦\87ন à¦\95রার à¦¸à¦®à¦¯à¦¼ à¦\8fà¦\87 à¦ªà¦¾à¦¤à¦¾à¦¯à¦¼ à¦¬à§\8dরাà¦\89à¦\9c à¦\95রবà§\87ন। à¦\8fà¦\9bাড়া à¦\86পনি à¦\86পনার à¦¨à¦\9cরতালিà¦\95ায় à¦°à¦¾à¦\96া à¦¸à¦¬à¦\97à§\81লি à¦ªà¦¾à¦¤à¦¾ à¦\9cনà§\8dয à¦¬à¦¿à¦\9cà§\8dà¦\9eপà§\8dতি à¦«à§\8dলà§\8dযাà¦\97 à¦¶à§\81রà§\81র à¦\85বসà§\8dথায় à¦«à¦¿à¦°à¦¿à¦¯à¦¼à§\87 à¦¨à¦¿à¦¤à§\87 à¦ªà¦¾à¦°à§\87ন।
 
 {{SITENAME}} নোটিফিকেশন
 
@@ -2398,7 +2401,7 @@ $1',
 
 # Namespace form on various pages
 'namespace' => 'নামস্থান:',
-'invert' => 'বà§\8dযà§\81তà§\8dক্রমে নির্বাচন',
+'invert' => 'বিপরà§\80তক্রমে নির্বাচন',
 'tooltip-invert' => 'যে সকল নামস্থানের পাতাগুলোর পরিবর্তনসমূহর দেখতে চাচ্ছেন না সেগুলোর নামের পাশে টিক দিন',
 'namespace_association' => 'সংশ্লিষ্ট নামস্থান',
 'tooltip-namespace_association' => 'এখানে টিক দেয়ার মাধ্যমে সংশ্লিষ্ট নামস্থান এবং আলাপপাতাসমূহ অন্তর্ভুক্ত করছেন',
@@ -2714,7 +2717,7 @@ $1',
 'allmessagesdefault' => 'আদি টেক্সট',
 'allmessagescurrent' => 'বর্তমান টেক্সট',
 'allmessagestext' => 'এটি মিডিয়াউইকি নামস্থানে অন্তর্ভুক্ত সিস্টেম বার্তাগুলোর একটি তালিকা।
-আপনি যদি সাধারণ মিডিয়াউইকির স্থানীয়করণে অবদান রাখতে আগ্রহী হন, অনুগ্রহ করে [//www.mediawiki.org/wiki/Localisation মিডিয়াউইকি স্থানীয়করণ] এবং [//translatewiki.net translatewiki.net] দেখুন।',
+আপনি যদি সাধারণ মিডিয়াউইকির স্থানীয়করণে অবদান রাখতে আগ্রহী হন, অনুগ্রহ করে [https://www.mediawiki.org/wiki/Localisation মিডিয়াউইকি স্থানীয়করণ] এবং [//translatewiki.net translatewiki.net] দেখুন।',
 'allmessagesnotsupportedDB' => "এই পাতা ব্যবহার করা যাবে না কারণ '''\$wgUseDatabaseMessages''' বন্ধ করে রাখা আছে।",
 'allmessages-filter-legend' => 'ছাকনী',
 'allmessages-filter' => 'Filter by customization state:',
@@ -2901,6 +2904,8 @@ $2',
 'spam_reverting' => '$1-এর প্রতি কোন সংযোগ নেই, এমন সর্বশেষ সংস্করণে ফেরত নেওয়া হচ্ছে।',
 'spam_blanking' => '$1-এর প্রতি সংযোগ অন্তর্ভুক্ত আছে এমন সমস্ত সংশোধন খালি করা হচ্ছে',
 'spam_deleting' => '$1-এর প্রতি সংযোগ অন্তর্ভুক্ত আছে এমন সমস্ত সংশোধন অপসারণ করা হচ্ছে',
+'simpleantispam-label' => "এন্টি স্প্যাম যাচাই।
+এটা পূরণ করবেন '''না'''!",
 
 # Info page
 'pageinfo-title' => '"$1" এর তথ্য',
@@ -2914,6 +2919,7 @@ $2',
 'pageinfo-length' => 'পাতার দৈর্ঘ্য (বাইটে)',
 'pageinfo-article-id' => 'পাতার আইডি',
 'pageinfo-language' => 'পাতার তথ্যের ভাষা',
+'pageinfo-content-model' => 'পাতার বিষয়বস্তুর মডেল',
 'pageinfo-robot-policy' => 'রোবটের মাধ্যমে ইন্ডেক্স করা হচ্ছে',
 'pageinfo-robot-index' => 'অনুমোদিত',
 'pageinfo-robot-noindex' => 'অনুনমোদিন',
@@ -2999,7 +3005,7 @@ $1',
 'svg-long-desc' => 'এসভিজি ফাইল, সাধারণত $1 × $2 পিক্সেল, ফাইলের আকার: $3',
 'svg-long-desc-animated' => 'এনিমেটেড এসভিজি ফাইল, সাধারণত $1 × $2 পিক্সেল, ফাইলের আকার: $3',
 'svg-long-error' => 'অবৈধ SVG ফাইল: $1',
-'show-big-image' => 'পà§\82রà§\8dণ à¦°à§\87à¦\9cà§\8bলিà¦\89শন',
+'show-big-image' => 'মà§\82ল à¦«à¦¾à¦\87ল',
 'show-big-image-preview' => 'এই প্রিভিউ-এর আকার: $1।',
 'show-big-image-other' => 'অন্যান্য {{PLURAL:$2|আকার|আকারসমূহ}}: $1।',
 'show-big-image-size' => '$1 × $2 পিক্সেল',
@@ -3466,7 +3472,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ফাইলটি অন্য কোন সফটওয়্যার দিয়ে সম্পাদনা করুন',
-'edit-externally-help' => 'আরও তথ্যের জন্য [//www.mediawiki.org/wiki/Manual:External_editors সেটআপ নির্দেশমালা] দেখুন।',
+'edit-externally-help' => 'আরও তথ্যের জন্য [https://www.mediawiki.org/wiki/Manual:External_editors সেটআপ নির্দেশমালা] দেখুন।',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'সবগুলো',
@@ -3689,7 +3695,7 @@ $4-এ নিশ্চিতকরণ কোডটি মেয়াদোত
 'version-hook-subscribedby' => 'সাবস্ক্রাইব করেছেন',
 'version-version' => '(সংস্করণ $1)',
 'version-license' => 'লাইসেন্স',
-'version-poweredby-credits' => "এইক উইকিটি পরিচালিত হচ্ছে '''[//www.mediawiki.org/ মিডিয়াউইকি]'''-এর মাধ্যমে, কপিরাইট © ২০০১-$1 $2।",
+'version-poweredby-credits' => "এইক উইকিটি পরিচালিত হচ্ছে '''[https://www.mediawiki.org/ মিডিয়াউইকি]'''-এর মাধ্যমে, কপিরাইট © ২০০১-$1 $2।",
 'version-poweredby-others' => 'অন্যান্য',
 'version-poweredby-translators' => 'translatewiki.net অনুবাদকগণ',
 'version-credits-summary' => '[[Special:Version|মিডিয়াউইকি]] সফটওয়্যারে অবদানের জন্য আমরা এই ব্যক্তিকে স্বীকৃতি দিতে চাই।',
@@ -3708,7 +3714,7 @@ $4-এ নিশ্চিতকরণ কোডটি মেয়াদোত
 # Special:Redirect
 'redirect' => 'ফাইল, ব্যবহারকরী, অথবা রিভিশন আইডি দ্বারা পুনঃনির্দেশ করা হয়েছে',
 'redirect-legend' => 'একটি ফাইল অথবা পাতায় পুনঃনির্দেশ করা হয়েছে',
-'redirect-summary' => 'এই বিশেষ পাতাটি পুনঃনির্দেশিত হয়েছে একটি ফাইলে (ফাইলের নাম), একটি পাতা (রিভিশন আইডি), অথবা একটি ব্যবহারকরী পাতায় (সংখ্যায় লেখা ব্যবহারকারী আইডি)।',
+'redirect-summary' => 'এই বিশেষ পাতাটি পুনঃনির্দেশিত হয়েছে একটি ফাইলে (ফাইলের নাম), একটি পাতা (রিভিশন আইডি), অথবা একটি ব্যবহারকরী পাতায় (সংখ্যায় লেখা ব্যবহারকারী আইডি)। ব্যবহার: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]]।',
 'redirect-submit' => 'যাও',
 'redirect-lookup' => 'দেখুন:',
 'redirect-value' => 'মান:',
@@ -3730,8 +3736,8 @@ $4-এ নিশ্চিতকরণ কোডটি মেয়াদোত
 
 # Special:SpecialPages
 'specialpages' => 'বিশেষ পাতাসমূহ',
-'specialpages-note' => '----
-* সাধারণ বিশেষ পাতাসমূহ।
+'specialpages-note-top' => 'লিজেন্ড',
+'specialpages-note' => '* সাধারণ বিশেষ পাতাসমূহ।
 * <span class="mw-specialpagerestricted">সীমাবদ্ধ বিশেষ পাতা।</span>',
 'specialpages-group-maintenance' => 'রক্ষণাবেক্ষণের কার্যবিবরণীসমূহ',
 'specialpages-group-other' => 'অন্যান্য বিশেষ পাতাসমূহ',
@@ -3945,4 +3951,21 @@ $4-এ নিশ্চিতকরণ কোডটি মেয়াদোত
 'limitreport-expansiondepth' => 'সর্বোচ্চ গভীরতা বিস্তার',
 'limitreport-expensivefunctioncount' => 'ব্যয়বহুল পার্সার ফাংশন গণনা',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'টেমপ্লেট সম্প্রসারণ',
+'expand_templates_intro' => 'এই বিশেষ পাতাটি কিছু টেক্সট গ্রহণ করে এবং এর ভেতরের সব টেম্পলেট বারংবার সম্প্রসারিত করে।
+এছাড়াও এটি
+<code><nowiki>{{</nowiki>#language:...}}</code>-এর মত পার্সার ফাংশন,
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>-এর মত ভ্যারিয়েবল
+মোটকথা দ্বিতীয় বন্ধনীর মধ্যে অবস্থিত সবকিছুকেই সম্প্রসারিত করতে পারে।',
+'expand_templates_title' => 'প্রাতিবেশিক শিরোনাম, {{FULLPAGENAME}}, ইত্যাদির জন্য:',
+'expand_templates_input' => 'ইনপুটকৃত লেখা:',
+'expand_templates_output' => 'ফলাফল',
+'expand_templates_xml_output' => 'XML আউটপুট',
+'expand_templates_ok' => 'ঠিক আছে',
+'expand_templates_remove_comments' => 'মন্তব্য মুছে ফেলো',
+'expand_templates_remove_nowiki' => 'ফলাফলে <nowiki> ট্যাগগুলো বাতিল করো',
+'expand_templates_generate_xml' => 'XML পার্স বৃক্ষ দেখাও',
+'expand_templates_preview' => 'প্রাকদর্শন',
+
 );
index 8beff87..ffeb49f 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Freeyak
  * @author Jason (on bo.wikipedia.org)
+ * @author Phurbutsering
  * @author Shirayuki
  * @author YeshiTuhden
  */
@@ -36,8 +37,9 @@ $messages = array(
 'tog-extendwatchlist' => 'མཉམ་འཇོག་ཐོ་བཀྲམས་ཏེ་ཉེ་ལམ་ཙམ་མིན་པར་བཟོ་བཅོས་ཡོངས་རྫོགས་སྟོན་ཅིག',
 'tog-usenewrc' => 'ཡར་རྒྱས་ཅན་གྱི་ཉེ་བའི་བཟོ་བཅོས་བེད་སྤྱོད་པ།(Java ཡི་བརྡ་ཆད་དགོས)',
 'tog-numberheadings' => 'རང་སྒྲིག་ཨང་རྟགས་འགོ་བརྗོད།',
-'tog-showtoolbar' => 'རྩོམ་སྒྲིག་ལག་ཆ་སྟོན།(Java ཡི་བརྡ་ཆད་དགོས།)',
-'tog-editondblclick' => 'ཤོག་ངོས་རྩོམ་སྒྲིག་བྱེད་པར་ལན་གཉིས་རྡེབ།(Java ཡི་བརྡ་ཆད་དགོས།)',
+'tog-showtoolbar' => 'རྩོམ་སྒྲིག་ལག་ཆ་སྟོན།(JavaScript ཡི་བརྡ་ཆད་དགོས།)',
+'tog-editondblclick' => 'ཤོག་ངོས་རྩོམ་སྒྲིག་བྱེད་པར་ལན་གཉིས་རྡེབ།(JavaScript ཡི་བརྡ་ཆད་དགོས།)',
+'tog-editsection' => '[སྒྲིག་བཅོས།]འབྲེལ་མཐུད་གནོན་ཏེ་སྒྲིགབཅོས་སྡེ་ཚན་ཡོད་པར་འགྱིས།',
 'tog-rememberpassword' => 'ངའི་ནང་འཛུལ་བཤར་ལྟ་ཆས་འདི་རུ་མང་མཐའ་ཉིན $1 {{PLURAL:$1}} དྲན་པར་མཛོད།',
 'tog-watchcreations' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་གསར་བཟོ་བྱས་པ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
 'tog-watchdefault' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་རྩོམ་སྒྲིག་བྱས་པ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
@@ -136,7 +138,7 @@ $messages = array(
 'cancel' => 'རྩིས་མེད།',
 'moredotdotdot' => 'དེ་ལས་མང་བ་་་',
 'mypage' => 'ངའི་ཤོག་ངོས།',
-'mytalk' => 'à½\84འིà¼\8bà½\82ླེà½\84à¼\8bà½\98ོལ།',
+'mytalk' => 'à½\82à½\8fà½\98à¼\8bà½\82ླེà½\84།',
 'anontalk' => 'IP གནས་ཡུལ་འདི་ལ་གླེང་མོལ།',
 'navigation' => 'ཕྱོགས་ཁྲིད།',
 'and' => '&#32;དང་',
@@ -202,7 +204,7 @@ $messages = array(
 'articlepage' => 'ནང་དོན་ཤོག་ངོས་ལ་ལྟ་བ།',
 'talk' => 'གྲོས་བསྡུར།',
 'views' => 'མཐོང་རིས།',
-'toolbox' => 'ལà½\82à¼\8bà½\86འིà¼\8bསà¾\92ྲོà½\98à¼\8d',
+'toolbox' => 'ལག་ཆའི་སྒམ།',
 'userpage' => 'སྤྱོད་མིའི་ཤོག་ངོས་ལ་ལྟ་བ།',
 'projectpage' => 'ལས་འཆར་ཤོག་ངོས་ལ་ལྟ་བ།',
 'imagepage' => 'ཡིག་ཆའི་ཤོག་ངོས་ལ་ལྟ་བ།',
@@ -244,8 +246,6 @@ $messages = array(
 'ok' => 'འགྲིག',
 'retrievedfrom' => '"$1"ལས་རྙེད་པ།',
 'youhavenewmessages' => 'ཁྱེད་ལ་འཕྲིན་གསར་$1($2)ཡོད།',
-'newmessageslink' => 'འཕྲིན་གསར།',
-'newmessagesdifflink' => 'བཟོ་བཅོས་མཐའ་མ།',
 'youhavenewmessagesmulti' => 'ཁྱེད་ལ་ $1 སྟེང་དུ་འཕྲིན་ཡིག་འདུག',
 'editsection' => 'རྩོམ་སྒྲིག',
 'editold' => 'རྩོམ་སྒྲིག',
@@ -389,7 +389,7 @@ $messages = array(
 'loginreqpagetext' => 'ཤོག་ངོས་གཞན་རྣམས་ལྟ་བར་ངེས་པར་དུ་$1བྱ་དགོས།',
 'accmailtitle' => 'ལམ་ཡིག་བཏང་ཟིན།',
 'newarticle' => '(གསར་བ)',
-'previewnote' => '༼འདི་ནི་སྔོན་ལྟ་ཙམ་ཡིན་པ་མ་བརྗེད།༽ ཁྱེད་ཀྱི་བཟོ་བཅོས་ད་དུང་ཉར་ཚགས་བྱས་མི་འདུག',
+'previewnote' => '"འདི་ནི་སྔོན་ལྟ་ཙམ་ཡིན་པ་ཡིད་ལ་འཇགས་རོགས། "ཁྱེད་ཀྱི་བཟོ་བཅོས་ད་དུང་ཉར་ཚགས་བྱས་མི་འདུག',
 'editing' => '$1རྩོམ་སྒྲིག་བྱེད་བཞིན་པ།',
 'editingsection' => ' $1 (སྡེ་ཚན) ལ་རྩོམ་སྒྲིག་བྱེད་བཞིན་པ།',
 'yourtext' => 'ཁྱོད་ཀྱི་ཡིག་འབྲུ།',
@@ -411,8 +411,8 @@ $messages = array(
 'page_last' => 'མཐའ་མ།',
 'history-fieldset-title' => 'ལོ་རྒྱུས་བཤར་ལྟ།',
 'history-show-deleted' => 'དོར་ཟིན་ཁོ་ན།',
-'histfirst' => 'སྔ་ཤོས།',
-'histlast' => 'ཕྱི་ཤོས།',
+'histfirst' => 'à½\86ེསà¼\8bསà¾\94à¼\8bཤོསà¼\8d',
+'histlast' => 'à½\86ེསà¼\8bà½\95ྱིà¼\8bཤོསà¼\8d',
 'historyempty' => '༼སྟོང་པ།༽',
 
 # Revision deletion
@@ -447,6 +447,7 @@ $messages = array(
 'notextmatches' => 'ཤོག་ངོས་ཡིག་འབྲུ་མཚུངས་པ་མི་འདུག',
 'prevn' => 'སྔོན་མ་{{PLURAL:$1|$1}}',
 'nextn' => 'རྗེས་མ་{{PLURAL:$1|$1}}',
+'shown-title' => 'མིག་སྔར་སྟོན་པ། $1{{PLURAL:$1|གྲུབ་འབྲས།}}ཤོག་ངོས་ལྟར།',
 'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3)ལ་ལྟ་བ།',
 'searchmenu-legend' => 'འཚོལ་ཞིབ་འདེམས་ཚན།',
 'searchmenu-new' => 'ལྦེ་ཁེ་སྟེང་ལ་ཤོག་ལེ་ [[:$1]]བཟོས།',
@@ -476,9 +477,8 @@ $messages = array(
 'powersearch-togglenone' => 'མེད།',
 
 # Preferences page
-'mypreferences' => 'à½\84འིà¼\8bལེà½\82སà¼\8bསà¾\92ྲིà½\82',
+'mypreferences' => 'à½\91à½\82འà¼\8bའà½\91ེà½\98སà¼\8d',
 'prefs-edits' => 'རྩོམ་སྒྲིག་གྲངས་ཚད།',
-'prefsnologin' => 'ནང་འཛུལ་བྱས་མེད།',
 'changepassword' => 'ལམ་ཡིག་བརྗེ་བ།',
 'skin-preview' => 'སྔོན་ལྟ།',
 'prefs-personal' => 'སྤྱོད་མིའི་སྤྱི་ཁོག',
@@ -567,7 +567,7 @@ $messages = array(
 'minoreditletter' => 'སྒྲིག་ཆུང་།',
 'newpageletter' => 'ཤོག་གསར།',
 'rc_categories_any' => 'གང་རུང་།',
-'rc-enhanced-expand' => 'ཞིབ་ཕྲ་སྟོན།',
+'rc-enhanced-expand' => 'à½\9eིà½\96à¼\8bà½\95ྲརà¼\8bསà¾\9fོà½\93à¼\8d',
 'rc-enhanced-hide' => 'ཞིབ་ཕྲ་སྦས་བ།',
 
 # Recent changes linked
@@ -625,7 +625,7 @@ $messages = array(
 'filehist-filesize' => 'ཡིག་ཆའི་ཆེ་ཆུང་།',
 'filehist-comment' => 'བསམ་ཚུལ།',
 'filehist-missing' => 'ཡིག་ཆ་ཆད་པ།',
-'imagelinks' => 'à½\82à½\84à¼\8bལà¼\8bསྦྲེལà¼\8bà½\96།',
+'imagelinks' => 'ཡིà½\82à¼\8bà½\86à¼\8bà½\96ེà½\91à¼\8bསྤྱོà½\91à¼\8bà½\81ུལ།',
 'linkstoimage' => '{{PLURAL:$1|pagelinks|$1pagelink}} འདི་ལ་སྦྲེལ་ཡོད།',
 'shared-repo-from' => '$1 ནས།',
 
@@ -685,8 +685,8 @@ $messages = array(
 'emailmessage' => 'སྐད་ཆ།',
 
 # Watchlist
-'watchlist' => 'à½\84འིà¼\8bà½\98à½\89à½\98à¼\8bའà½\87ོà½\82་ཐོ།',
-'mywatchlist' => 'à½\84འིà¼\8bà½\98à½\89à½\98à¼\8bའà½\87ོà½\82་ཐོ།',
+'watchlist' => 'ལà¾\9fà¼\8bà½\9eིà½\96་ཐོ།',
+'mywatchlist' => 'ལà¾\9fà¼\8bà½\9eིà½\96་ཐོ།',
 'watchnologin' => 'ནང་འཛུལ་བྱས་མེད།',
 'watch' => 'མཉམ་འཇོག་ཐོ།',
 'watchthispage' => 'དྲ་ངོས་འདི་ལ་གཟིགས།',
@@ -748,8 +748,8 @@ $messages = array(
 'blanknamespace' => '༼གཙོ་ངོས།༽',
 
 # Contributions
-'contributions' => 'སྤྱོà½\91à¼\8bà½\98ིའིà¼\8bà½\96ྱསà¼\8bརà¾\97ེས།',
-'mycontris' => 'à½\84འིà¼\8bà½\96ྱསà¼\8bརà¾\97ེས།',
+'contributions' => 'à½\98à½\90ུà½\93à¼\8bའà½\82ྱུར།',
+'mycontris' => 'à½\98à½\90ུà½\93à¼\8bའà½\82ྱུར།',
 'month' => 'ཟླ་བ་འདི་ནས།',
 'year' => 'ལོ་འདི་ནས།',
 
@@ -761,7 +761,7 @@ $messages = array(
 'whatlinkshere-title' => '"$1" ལ སྦྲེལ་ཡོད་པའི་ཤོག་ངོས།',
 'whatlinkshere-page' => 'ཤོག་ངོས།',
 'linkshere' => "གཤམ་གྱི་ཤོག་ངོས་རྣམས་ '''[[:$1]]''': ལ་སྦྲེལ་ཡོད།",
-'isimage' => 'à½\96རà¾\99à½\93་རིས་སྦྲེལ་མཐུད།',
+'isimage' => 'ཡིà½\82་རིས་སྦྲེལ་མཐུད།',
 'whatlinkshere-links' => '← སྦྲེལ་མཐུད།',
 'whatlinkshere-hidelinks' => '$1 སྦྲེལ་མཐུད།',
 'whatlinkshere-filters' => 'ཡིག་ཚགས།',
@@ -855,7 +855,7 @@ $messages = array(
 'nextdiff' => 'རྩོམ་སྒྲིག་གསར་གྲས། →',
 
 # Media information
-'show-big-image' => 'à½\82à½\8fà½\93à¼\8bའà½\96ེà½\96à¼\8bà½\86à¼\8bà½\9aà½\84à¼\8b།',
+'show-big-image' => 'à½\90ོà½\82à¼\8bà½\98འིà¼\8bཡིà½\82à¼\8bà½\86།',
 
 # Special:NewFiles
 'ilsubmit' => 'འཚོལ།',
index 8025ce8..e0c5231 100644 (file)
@@ -303,8 +303,6 @@ $1',
 'ok' => 'চুমিসে',
 'retrievedfrom' => "'$1' -ত্ত আনানি অসে",
 'youhavenewmessages' => 'তরতা $1 ($2) আসে।',
-'newmessageslink' => 'নুৱা পৌ',
-'newmessagesdifflink' => 'গেলগা সিলপা',
 'youhavenewmessagesmulti' => 'তরতা নুৱা পৌ $1হান আহিসে',
 'editsection' => 'পতিক',
 'editold' => 'পতিক',
@@ -1449,7 +1447,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 'allmessagesdefault' => 'আদ্যকার টেক্সট',
 'allmessagescurrent' => 'হাদি এহানর ৱাহি',
 'allmessagestext' => 'তলে মিডিয়াউইকির নাঙরথাকে পানা একরের সিস্টেম পৌহানির তালিকাহান দেনা ইল।
-কৃপা করিয়া [//www.mediawiki.org/wiki/Localisation মিডিয়াউইকি অনুবাদর হেইচা পাতাত] বারো [//translatewiki.net translatewiki.net] মিডিয়াউইকি অনুবাদ করানির কা যানা পারর।',
+কৃপা করিয়া [https://www.mediawiki.org/wiki/Localisation মিডিয়াউইকি অনুবাদর হেইচা পাতাত] বারো [//translatewiki.net translatewiki.net] মিডিয়াউইকি অনুবাদ করানির কা যানা পারর।',
 'allmessages-filter-legend' => 'সাক',
 'allmessages-filter-unmodified' => 'নাসিলথাইতে',
 'allmessages-filter-all' => 'হাব্বি',
@@ -1586,7 +1584,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 
 # External editor support
 'edit-externally' => 'এর ফাইল এগ পতানির কা বারেদের এপ্লিকেশন আতা',
-'edit-externally-help' => 'আরাকউ হারপানির কা [//www.mediawiki.org/wiki/Manual:External_editors সেটাপর নির্দেশহানি] চা।',
+'edit-externally-help' => 'আরাকউ হারপানির কা [https://www.mediawiki.org/wiki/Manual:External_editors সেটাপর নির্দেশহানি] চা।',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'হাব্বি',
index daab6d4..e811410 100644 (file)
@@ -53,7 +53,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'PajennoùKozh' ),
        'Badtitle'                  => array( 'TitlFall' ),
        'Block'                     => array( 'Stankañ' ),
-       'Blockme'                   => array( 'MaStankañ' ),
        'Booksources'               => array( 'MammennoùLevr' ),
        'BrokenRedirects'           => array( 'AdkasoùTorr' ),
        'Categories'                => array( 'Rummadoù' ),
@@ -62,9 +61,9 @@ $specialPageAliases = array(
        'Confirmemail'              => array( 'KadarnaatPostel' ),
        'Contributions'             => array( 'Degasadennoù' ),
        'CreateAccount'             => array( 'KrouiñKont' ),
-       'Disambiguations'           => array( 'Disheñvelout' ),
        'DoubleRedirects'           => array( 'AdksaoùDoubl' ),
        'Emailuser'                 => array( 'PostelImplijer' ),
+       'ExpandTemplates'           => array( 'PatromoùAstennet' ),
        'Export'                    => array( 'Ezporzhiañ' ),
        'Import'                    => array( 'Enporzhiañ' ),
        'LinkSearch'                => array( 'KlaskLiamm' ),
@@ -187,12 +186,12 @@ $messages = array(
 'tog-hidepatrolled' => "Kuzhat ar c'hemmoù evezhiet e-touez ar c'hemmoù diwezhañ",
 'tog-newpageshidepatrolled' => 'Kuzhat ar pajennoù evezhiet diouzh roll ar pajennoù nevez',
 'tog-extendwatchlist' => 'Astenn ar roll evezhiañ a-benn diskouez an holl gemmoù ha neket ar re ziwezhañ hepken.',
-'tog-usenewrc' => "Diskouez ar c'hemmoù nevez en ur feson kempennoc'h (rekis eo JavaScript)",
+'tog-usenewrc' => "Diskouez ar c'hemmoù nevez en ur feson kempennoc'h",
 'tog-numberheadings' => 'Niverenniñ emgefre an titloù',
 'tog-showtoolbar' => 'Diskouez ar varrenn ostilhoù aozañ',
 'tog-editondblclick' => 'Daouglikañ evit kemmañ pajennoù',
 'tog-editsection' => 'Kemmañ ur rann dre al liammoù [kemmañ]',
-'tog-editsectiononrightclick' => 'Kemmañ ur rann dre glikañ a-zehou<br /> war titl ar rann',
+'tog-editsectiononrightclick' => 'Kemmañ ur rann dre glikañ a-zehou war titl ar rann',
 'tog-showtoc' => 'Diskouez an daolenn<br /> (evit ar pennadoù zo ouzhpenn 3 rann enno)',
 'tog-rememberpassword' => "Derc'hel soñj eus ma ger-tremen war an urzhiataer-mañ (evit $1 devezh{{PLURAL:$1||}} d'ar muiañ)",
 'tog-watchcreations' => "Ouzhpennañ ar pajennoù krouet ganin da'm roll evezhiañ",
@@ -398,7 +397,7 @@ $messages = array(
 'articlepage' => 'Sellet ouzh ar pennad',
 'talk' => 'Kaozeadenn',
 'views' => 'Gweladennoù',
-'toolbox' => 'Boest ostilhoù',
+'toolbox' => 'Ostilhoù',
 'userpage' => 'Pajenn implijer',
 'projectpage' => 'Pajenn meta',
 'imagepage' => 'Gwelet pajenn ar restr',
@@ -428,7 +427,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Diwar-benn {{SITENAME}}',
 'aboutpage' => 'Project:Diwar-benn',
-'copyright' => "Danvez a c'haller implijout dindan $1.",
+'copyright' => "Danvez a c'haller implijout dindan $1 nemet ha notet e vefe ar c'hontrol.",
 'copyrightpage' => '{{ns:project}}:Gwirioù aozer (Copyright)',
 'currentevents' => 'Keleier',
 'currentevents-url' => 'Project:Keleier',
@@ -454,12 +453,10 @@ $1',
 'ok' => 'Mat eo',
 'retrievedfrom' => 'Adtapet diwar « $1 »',
 'youhavenewmessages' => "$1 zo ganeoc'h ($2).",
-'newmessageslink' => 'Kemennoù nevez',
-'newmessagesdifflink' => "Diforc'hioù e-keñver ar stumm kent",
 'youhavenewmessagesfromusers' => '$1 ho peus eus {{PLURAL:$3|un implijer all|$3 implijer}} ($2).',
 'youhavenewmessagesmanyusers' => ' $1 ho peus implijerien a-leizh  ($2).',
-'newmessageslinkplural' => "{{PLURAL:$1ur c'hemennad nevez|kemennadoù nevez}}",
-'newmessagesdifflinkplural' => '{{PLURAL:$1|kemennad diwezhañ|kemennadoù diwezhañ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ur gemennad nevez|999=kemennadoù nevez}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|kemennad diwezhañ|999=kemennadoù diwezhañ}}',
 'youhavenewmessagesmulti' => "Kemennoù nevez zo ganeoc'h war $1",
 'editsection' => 'kemmañ',
 'editold' => 'kemmañ',
@@ -633,9 +630,10 @@ Na zisoñjit ket resisaat ho [[Special:Preferences|penndibaboù evit {{SITENAME}
 'gotaccount' => "Ur gont zo ganeoc'h dija ? '''$1'''.",
 'gotaccountlink' => 'Kevreañ',
 'userlogin-resetlink' => "Ha disoñjet eo bet ho titouroù kevreañ ganeoc'h ?",
-'userlogin-resetpassword-link' => 'Adderaouekaat ho ker-tremen',
+'userlogin-resetpassword-link' => 'Ankouaet ho peus ho ker-tremen ?',
 'helplogin-url' => 'Help:Kevreañ',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Skoazell evit kevreañ]]',
+'userlogin-createanother' => 'Krouiñ ur gont all',
 'createacct-join' => 'Skrivit ho titouroù amañ dindan.',
 'createacct-another-join' => 'Ebarzhiñ titouroù ar gont nevez amañ dindan.',
 'createacct-emailrequired' => "Chomlec'h postel",
@@ -700,7 +698,8 @@ A-raok na vije kaset postel ebet d'ar gont-se e vo ret deoc'h heuliañ ar c'huzu
 'mailerror' => 'Fazi en ur gas ar postel : $1',
 'acct_creation_throttle_hit' => "{{PLURAL:$1|1 gont|$1 kont}} zo bet krouet c'hoazh nevez zo dre ho chomlec'h IP gant gweladennerien d'ar wiki-mañ, ar pezh zo an niver brasañ aotreet. Dre se, n'hall ket ket ar weladennerien a implij an IP-mañ krouiñ kontoù mui evit ar mare.",
 'emailauthenticated' => "Gwiriet eo bet ho chomlec'h postel d'an $2 da $3.",
-'emailnotauthenticated' => "N'eo ket bet gwiriekaet ho chomlec'h postel evit c'hoazh. Ne vo ket tu da gas postel ebet deoc'h evit hini ebet eus an dezverkoù dindan.",
+'emailnotauthenticated' => "N'eo ket bet gwiriekaet ho chomlec'h postel evit c'hoazh.
+Ne vo ket tu da gas postel ebet deoc'h evit hini ebet eus an dezverkoù dindan.",
 'noemailprefs' => "Merkit ur chomlec'h postel mar fell deoc'h ez afe an arc'hwelioù-mañ en-dro.",
 'emailconfirmlink' => "Kadarnait ho chomlec'h postel",
 'invalidemailaddress' => "N'haller ket degemer ar chomlec'h postel-mañ rak faziek eo e furmad evit doare.
@@ -877,9 +876,7 @@ Moarvat ez eo bet dilerc'hiet pe dilamet abaoe ma oa bet lennet ganeoc'h.",
 'loginreqlink' => 'kevreañ',
 'loginreqpagetext' => "Ret eo deoc'h $1 evit gwelet pajennoù all.",
 'accmailtitle' => 'Ger-tremen kaset.',
-'accmailtext' => "Kaset ez eus bet ur ger-tremen dargouezhek evit [[User talk:$1|$1]] da $2.
-
-Cheñchet e c'hall ar ger-tremen evit ar gont nevez-mañ bezañ war ar bajenn ''[[Special:ChangePassword|cheñch ger-tremen]]'', ur wezh kevreet.",
+'accmailtext' => "Kaset ez eus bet ur ger-tremen dargouezhek evit [[User talk:$1|$1]] da $2. Cheñchet e c'hall ar ger-tremen evit ar gont nevez-mañ bezañ war ar bajenn ''[[Special:ChangePassword|cheñch ger-tremen]]'', ur wezh kevreet.",
 'newarticle' => '(Nevez)',
 'newarticletext' => "Heuliet hoc'h eus ul liamm a gas d'ur bajenn n'eo ket bet savet evit c'hoazh.
 A-benn krouiñ ar bajenn-se, krogit da skrivañ er prenestr skridaozañ dindan (gwelet ar [[{{MediaWiki:Helppage}}|bajenn skoazell]] evit gouzout hiroc'h).
@@ -1129,15 +1126,15 @@ Gouest e vo merourien all {{SITENAME}} da dapout krog en testennoù kuzhet ha da
 * Titouroù personel dizere
 *: ''chomlec'hioù, niverennoù pellgomz pe surentez sokial personel, hag all''",
 'revdelete-legend' => 'Lakaat strishadurioù gwelet',
-'revdelete-hide-text' => 'Kuzhat testenn ar stumm',
+'revdelete-hide-text' => 'Testenn ar stumm',
 'revdelete-hide-image' => 'Kuzhat danvez ar restr',
 'revdelete-hide-name' => 'Kuzhat an ober hag ar vukadenn',
-'revdelete-hide-comment' => "Kuzhat notenn ar c'hemm",
-'revdelete-hide-user' => "Kuzhat anv implijer pe chomlec'h IP an aozer",
+'revdelete-hide-comment' => "Notenn ar c'hemm",
+'revdelete-hide-user' => "Anv implijer pe chomlec'h IP an aozer",
 'revdelete-hide-restricted' => "Diverkañ ar roadennoù kement d'ar verourien ha d'ar re all",
 'revdelete-radio-same' => '(arabat cheñch)',
-'revdelete-radio-set' => 'Ya',
-'revdelete-radio-unset' => 'Ket',
+'revdelete-radio-set' => 'Kuzhet',
+'revdelete-radio-unset' => 'Hewel',
 'revdelete-suppress' => 'Diverkañ roadennoù ar verourien hag ar re all',
 'revdelete-unsuppress' => 'Lemel ar strishadurioù war ar stummoù assavet',
 'revdelete-log' => 'Abeg :',
@@ -1289,8 +1286,6 @@ Gallout a reot kavout munudoù e [{{fullurl:{{#Special:Log}}/delete|page={{FULLP
 'preferences' => 'Penndibaboù',
 'mypreferences' => 'Penndibaboù',
 'prefs-edits' => 'Niver a zegasadennoù :',
-'prefsnologin' => 'Digevreet',
-'prefsnologintext' => 'Ret eo deoc\'h bezañ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kevreet]</span> a-benn gellout cheñch ho tibaboù implijer.',
 'changepassword' => 'Kemmañ ar ger-tremen',
 'prefs-skin' => 'Gwiskadur',
 'skin-preview' => 'Rakwelet',
@@ -1583,6 +1578,7 @@ Ma skrivit anezhañ e vo implijet evit lakaat war wel ar pezh a vo bet degaset g
 'recentchanges-label-minor' => "Ur c'hemm dister eo hemañ",
 'recentchanges-label-bot' => "Gant ur bot eo bet degaset ar c'hemm-mañ.",
 'recentchanges-label-unpatrolled' => "N'eo ket bet gwiriet ar c'hemm-mañ evit c'hoazh.",
+'recentchanges-legend-newpage' => '$1 - pajenn nevez',
 'rcnote' => "Setu aze an {{PLURAL:$1|'''1''' change|'''$1''' kemm diwezhañ}} bet c'hoarvezet e-pad an {{PLURAL:$2|deiz|'''$2''' deiz}} diwezhañ, savet d'an $4 da $5.",
 'rcnotefrom' => "Setu aze roll ar c'hemmoù c'hoarvezet abaoe an '''$2''' ('''$1''' d'ar muiañ).",
 'rclistfrom' => "Diskouez ar c'hemmoù diwezhañ abaoe an $1.",
@@ -2821,7 +2817,7 @@ Mard eo se e c'hallit ivez implijout ul liamm a seurt gant [[{{#Special:Export}}
 'allmessagesdefault' => 'Kemennadenn dre ziouer',
 'allmessagescurrent' => 'Kemennadenn zo bremañ',
 'allmessagestext' => "Setu roll ar c'hemennadennoù reizhiad a c'haller kaout en esaouennoù anv MediaWiki.
-Kit da welet [//www.mediawiki.org/wiki/Localisation Lec'heladur MediaWiki] ha [//translatewiki.net translatewiki.net] mar fell deoc'h kemer perzh e lec'heladur boutin MediaWiki.",
+Kit da welet [https://www.mediawiki.org/wiki/Localisation Lec'heladur MediaWiki] ha [//translatewiki.net translatewiki.net] mar fell deoc'h kemer perzh e lec'heladur boutin MediaWiki.",
 'allmessagesnotsupportedDB' => "N'haller ket kaout {{ns:special}}:AllMessages rak diweredekaet eo bet wgUseDatabaseMessages.",
 'allmessages-filter-legend' => 'Sil',
 'allmessages-filter' => "Silañ dre stad ar c'hemmoù",
@@ -3027,6 +3023,8 @@ Sur a-walc'h abalamour d'ul liamm enni a gas d'ul lec'hienn ziavaez berzet.",
 'spam_reverting' => "Distreiñ d'ar stumm diwezhañ hep liamm davet $1",
 'spam_blanking' => 'Diverkañ an holl stummoù enno liammoù davet $1',
 'spam_deleting' => 'An holl stummoù enno liammoù war-zu $1, o tiverkañ',
+'simpleantispam-label' => "Taol gwiriañ eneb-strob.
+'''Arabat''' merkañ tra pe dra amañ !",
 
 # Info page
 'pageinfo-title' => 'Titouroù evit "$1"',
@@ -3588,7 +3586,7 @@ Kuzhet e vo ar re all dre ziouer.
 
 # External editor support
 'edit-externally' => 'Kemmañ ar restr-mañ dre un arload diavaez',
-'edit-externally-help' => "(Gwelet [//www.mediawiki.org/wiki/Manual:External_editors erbedadennoù staliañ an aozer diavaez] a-benn gouzout hiroc'h).",
+'edit-externally-help' => "(Gwelet [https://www.mediawiki.org/wiki/Manual:External_editors erbedadennoù staliañ an aozer diavaez] a-benn gouzout hiroc'h).",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'pep tra',
@@ -3791,7 +3789,7 @@ Gallout a rit [[Special:EditWatchlist|implijout an aozer boutin ivez]].',
 'version-hook-subscribedby' => 'Termenet gant',
 'version-version' => '(Stumm $1)',
 'version-license' => 'Aotre-implijout',
-'version-poweredby-credits' => "Mont a ra ar wiki-mañ en-dro a-drugarez da '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Mont a ra ar wiki-mañ en-dro a-drugarez da '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 're all',
 'version-poweredby-translators' => 'troerien translatewiki.net',
 'version-credits-summary' => 'Karout a rafemp trugarekaat an dud-mañ evit ho kenlabour e [[Special:Version|MediaWiki]].',
@@ -3830,8 +3828,8 @@ Sañset oc'h bezañ resevet [{{SERVER}}{{SCRIPTPATH}}/COPYING un eilskrid eus ar
 
 # Special:SpecialPages
 'specialpages' => 'Pajennoù dibar',
-'specialpages-note' => '----
-* Pajennoù dibar boutin.
+'specialpages-note-top' => "Alc'hwez",
+'specialpages-note' => '* Pajennoù dibar boutin.
 * <span class="mw-specialpagerestricted">Pajennoù dibar miret strizh.</span>
 * <span class="mw-specialpagecached">Pajennoù dibar krubuilhet hepken (a c\'hellfe bezañ re gozh).</span>',
 'specialpages-group-maintenance' => "Rentaoù-kont trezalc'h",
@@ -3922,14 +3920,14 @@ Sañset oc'h bezañ resevet [{{SERVER}}{{SCRIPTPATH}}/COPYING un eilskrid eus ar
 'logentry-delete-delete' => 'Diverket eo bet ar bajenn $3 gant $1',
 'logentry-delete-restore' => 'Assavet eo bet ar bajenn $3 gant $1',
 'logentry-delete-event' => "Kemmet eo bet gwelusted {{PLURAL:$5|un darvoud eus ar marilh|$5 darvoud eus ar marilh}} d'an $3 gant $1 : $4",
-'logentry-delete-revision' => 'Kemmet eo bet gwelusted {{PLURAL:$5|$5reizhadenn}} war ar bajenn $3 gant $1 : $4',
-'logentry-delete-event-legacy' => 'Kemmet eo bet gwelusted darvoudoù ar marilh $3 gant $1',
-'logentry-delete-revision-legacy' => 'Kemmet eo bet gwelusted ar reizhadennoù war ar bajenn $3 gant $1',
+'logentry-delete-revision' => '{{GENDER:$2|Kemmet}} eo bet gwelusted {{PLURAL:$5|reizhadenn|$5 reizhadenn}} war ar bajenn $3 gant $1 : $4',
+'logentry-delete-event-legacy' => '{{GENDER:$2|Kemmet}} eo bet gwelusted darvoudoù ar marilh $3 gant $1',
+'logentry-delete-revision-legacy' => '{{GENDER:$2|Kemmet}} eo bet gwelusted ar reizhadennoù war ar bajenn $3 gant $1',
 'logentry-suppress-delete' => '$1 {{GENDER:$2|en deus dilamet}} ar bajenn $3',
-'logentry-suppress-event' => "Kemmet eo bet dre guzh gwelusted {{PLURAL:$5|un darvoud eus ar marilh|$5 darvoud eus ar marilh}} d'an $3 gant $1 : $4",
+'logentry-suppress-event' => "{{GENDER:$2|Kemmet}} eo bet dre guzh gwelusted {{PLURAL:$5|un darvoud eus ar marilh|$5 darvoud eus ar marilh}} d'an $3 gant $1 : $4",
 'logentry-suppress-revision' => 'Kemmet eo bet dre guzh gwelusted {{PLURAL:$5|reizhadenn|$5 reizhadenn}} war ar bajenn $3 gant $1 : $4',
-'logentry-suppress-event-legacy' => "Kemmet eo bet dre guzh gwelusted darvoudoù ar marilh d'an $3 gant $1",
-'logentry-suppress-revision-legacy' => 'Kemmet eo bet dre guzh gwelusted ar reizhadennoù war ar bajenn $3 gant $1',
+'logentry-suppress-event-legacy' => "{{GENDER:$2|Kemmet}} eo bet dre guzh gwelusted darvoudoù ar marilh d'an $3 gant $1",
+'logentry-suppress-revision-legacy' => '{{GENDER:$2|Kemmet}} eo bet dre guzh gwelusted ar reizhadennoù war ar bajenn $3 gant $1',
 'revdelete-content-hid' => 'danvez kuzet',
 'revdelete-summary-hid' => 'kemmañ an diverrañ kuzhet',
 'revdelete-uname-hid' => 'anv implijer kuzhet',
@@ -3942,9 +3940,9 @@ Sañset oc'h bezañ resevet [{{SERVER}}{{SCRIPTPATH}}/COPYING un eilskrid eus ar
 'logentry-move-move-noredirect' => 'kaset ar bajenn $3 da $4 gant $1 hep adkas',
 'logentry-move-move_redir' => 'kaset ar bajenn $3 da $4 gant $1 dreist un adkas',
 'logentry-move-move_redir-noredirect' => 'kaset ar bajenn $3 da $4 gant $1 dreist un adkas hep lezel un adkas',
-'logentry-patrol-patrol' => 'Merket eo bet an adweladenn $4 eus ar bajenn $3 evel gwiriet gant $1',
-'logentry-patrol-patrol-auto' => 'Merket eo bet ent emgefre an adweladenn $4 eus ar bajenn $3 evel gwiriet gant $1',
-'logentry-newusers-newusers' => 'Krouet eo bet ar gont implijer $1',
+'logentry-patrol-patrol' => '{{GENDER:$2|Merket}} eo bet an adweladenn $4 eus ar bajenn $3 evel gwiriet gant $1',
+'logentry-patrol-patrol-auto' => '{{GENDER:$2|Merket}} eo bet ent emgefre an adweladenn $4 eus ar bajenn $3 evel gwiriet gant $1',
+'logentry-newusers-newusers' => '{{GENDER:$2|Krouet}} eo bet ar gont implijer $1',
 'logentry-newusers-create' => 'Krouet eo bet ar gont implijer $1',
 'logentry-newusers-create2' => 'Gant $1 eo bet krouet ar gont implijer $3',
 'logentry-newusers-byemail' => 'Krouet eo bet ar gont implijer $3 gant $1 ha kaset eo bet ar ger-tremen dre bostel',
@@ -4034,4 +4032,21 @@ A-hend-all e c'hallit ober gant ar furmskrid eeunaet dindan. Ouzhpennet e vo hoc
 'limitreport-templateargumentsize' => 'Ment arguzenn ar patrom',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|okted}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Emled ar patromoù',
+'expand_templates_intro' => "Kemer a ra ar bajenn dibar-mañ tammoù testenn hag astenn a ra an holl batromoù enni en un doare azkizat.
+Astenn a ra ivez an arc'hwelioù parser evel
+<nowiki>{{</nowiki>#language:…}}, hag an argemmoù evel
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash; e gwirionez, koulz lavaret kement tra zo etre briataennoù.
+Ober a ra kement-mañ dre c'hervel ar bazenn a zegouezh digant parser MediaWiki e-unan.",
+'expand_templates_title' => 'Titl ar gendestenn, evit {{FULLPAGENAME}} h.a. :',
+'expand_templates_input' => 'Merkañ ho testenn amañ :',
+'expand_templates_output' => "Disoc'h",
+'expand_templates_xml_output' => 'Ezvont XML',
+'expand_templates_ok' => 'Mat eo',
+'expand_templates_remove_comments' => 'Lemel an notennoù kuit',
+'expand_templates_remove_nowiki' => "Diverkañ a ra ar balizennoù <nowiki> en disoc'h",
+'expand_templates_generate_xml' => 'Gwelet ar gwezennadur XML',
+'expand_templates_preview' => 'Rakwelet',
+
 );
index 0db0d0c..cf8c6ca 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Losnaslov' ),
        'Blankpage'                 => array( 'PraznaStranica' ),
        'Block'                     => array( 'BlokirajIP' ),
-       'Blockme'                   => array( 'BlokirajMe' ),
        'Booksources'               => array( 'KnjizniIzvori' ),
        'BrokenRedirects'           => array( 'NedovršenaPreusmjerenja' ),
        'Categories'                => array( 'Kategorije' ),
@@ -71,10 +70,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'NapraviRačun' ),
        'Deadendpages'              => array( 'MrtveStranice' ),
        'DeletedContributions'      => array( 'ObrisaniDoprinosi' ),
-       'Disambiguations'           => array( 'Čvor' ),
        'DoubleRedirects'           => array( 'DvostrukaPreusmjerenja' ),
        'EditWatchlist'             => array( 'IzmjeniPraćeniSpisak' ),
        'Emailuser'                 => array( 'EmailKorisnika' ),
+       'ExpandTemplates'           => array( 'ProsirivanjeSablona' ),
        'Export'                    => array( 'Izvoz' ),
        'Fewestrevisions'           => array( 'Najmanje_uređivane_stranice' ),
        'FileDuplicateSearch'       => array( 'PotragaDuplihFajlova' ),
@@ -113,6 +112,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'ZasticeneStranice' ),
        'Protectedtitles'           => array( 'ZasticeniNazivi' ),
        'Randompage'                => array( 'Slučajna_stranica' ),
+       'RandomInCategory'          => array( 'SlucajnoUKategoriji' ),
        'Randomredirect'            => array( 'SlucajnoPreusmjerenje' ),
        'Recentchanges'             => array( 'NedavneIzmjene' ),
        'Recentchangeslinked'       => array( 'PovezaneNedavneIzmjene' ),
@@ -498,7 +498,7 @@ $messages = array(
 'articlepage' => 'Pogledaj članak',
 'talk' => 'Razgovor',
 'views' => 'Pregledi',
-'toolbox' => 'Traka sa alatima',
+'toolbox' => 'Alati',
 'userpage' => 'Pogledaj korisničku stranicu',
 'projectpage' => 'Pogledaj stranicu projekta',
 'imagepage' => 'Pogledajte stranicu datoteke',
@@ -528,7 +528,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'O projektu {{SITENAME}}',
 'aboutpage' => 'Project:O_projektu_{{SITENAME}}',
-'copyright' => 'Svi sadržaji podliježu "$1" licenci.',
+'copyright' => 'Sadržaj je dostupan pod licencom $1 osim ako je drugačije navedeno.',
 'copyrightpage' => '{{ns:project}}:Autorska_prava',
 'currentevents' => 'Trenutni događaji',
 'currentevents-url' => 'Project:Novosti',
@@ -554,8 +554,6 @@ $1',
 'ok' => 'U redu',
 'retrievedfrom' => 'Dobavljeno iz "$1"',
 'youhavenewmessages' => 'Imate $1 ($2).',
-'newmessageslink' => 'novih poruka',
-'newmessagesdifflink' => 'posljednja promjena',
 'youhavenewmessagesfromusers' => 'Imate $1 od {{PLURAL:$3|drugog korisnika|$3 korisnika}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od mnogo korisnika ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|nove poruke}}',
@@ -730,9 +728,11 @@ Ne zaboravite da prilagodite sebi svoja [[Special:Preferences|{{SITENAME}} pode
 'gotaccount' => 'Već imate korisnički račun? $1.',
 'gotaccountlink' => 'Prijavi se',
 'userlogin-resetlink' => 'Zaboravili ste detalje vaše prijave?',
-'userlogin-resetpassword-link' => 'Resetirajte svoju šifru/lozinku',
+'userlogin-resetpassword-link' => 'Zaboravili ste šifru/lozinku?',
 'helplogin-url' => 'Help:Prijavljivanje',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoć pri prijavljivanju]]',
+'userlogin-loggedin' => 'Već ste prijavljeni kao {{GENDER:$1|$1}}.
+Koristite donji obrazac da biste se prijavili kao drugi korisnik.',
 'userlogin-createanother' => 'Napravi još jedan račun',
 'createacct-join' => 'Unesite svoje podatke ispod.',
 'createacct-another-join' => 'Unesite informacije o novom računu ispod.',
@@ -790,16 +790,16 @@ Ako je neko drugi napravio ovaj zahtjev ili ako ste se sjetili vaše šifre i ne
 'passwordsent' => 'Nova šifra je poslata na adresu e-pošte korisnika "$1".
 Molimo Vas da se prijavite pošto je primite.',
 'blocked-mailpassword' => 'Da bi se spriječila nedozvoljena akcija, Vašoj IP adresi je onemogućeno uređivanje stranica kao i mogućnost zahtijevanje nove šifre.',
-'eauthentsent' => 'Na navedenu adresu poslan je e-mail s potvrdom.
-Prije nego što pošaljemo daljnje poruke, molimo vas da otvorite e-mail i slijedite u njemu sadržana uputstva da potvrdite da ste vi kreirali korisnički račun.',
+'eauthentsent' => 'Na navedenu adresu poslana je e-poruka s potvrdom.
+Prije nego što pošaljemo daljnje poruke, pratite uputstva s e-pošte da biste potvrdili da je račun zaista Vaša.',
 'throttled-mailpassword' => 'Već Vam je poslan e-mail za promjenu šifre u {{PLURAL:$1|zadnjih sat vremena|zadnja $1 sata|zadnjih $1 sati}}.
 Da bi se spriječila zloupotreba, može se poslati samo jedan e-mail za promjenu šifre {{PLURAL:$1|svakih sat vremena|svaka $1 sata|svakih $1 sati}}.',
 'mailerror' => 'Greška pri slanju e-pošte: $1',
 'acct_creation_throttle_hit' => 'Posjetioci na ovoj wiki koji koriste Vašu IP adresu su već napravili {{PLURAL:$1|$1 račun|$1 računa}} u zadnjih nekoliko dana, što je najveći broj dopuštenih napravljenih računa za ovaj period.
 Kao rezultat, posjetioci koji koriste ovu IP adresu ne mogu trenutno praviti više računa.',
-'emailauthenticated' => 'Vaša e-mail adresa je autentificirana na $2 u $3.',
-'emailnotauthenticated' => 'Vaša e-mail adresa još nije autentificirana.
-Nijedan e-mail neće biti poslan za bilo koju uslugu od slijedećih.',
+'emailauthenticated' => 'Vaša adresa e-pošte je potvrđena $2 u $3.',
+'emailnotauthenticated' => 'Vaša adresa e-pošte još nije potvrđena.
+Nijedna e-poruka neće biti poslana za bilo koju uslugu od slijedećih.',
 'noemailprefs' => 'Unesite e-mail adresu za osposobljavanje slijedećih usluga.',
 'emailconfirmlink' => 'Potvrdite Vašu e-mail adresu',
 'invalidemailaddress' => 'Ova e-mail adresa ne može biti prihvaćena jer je u neodgovarajućem obliku.
@@ -1233,15 +1233,15 @@ Drugi administratori projekta {{SITENAME}} će i dalje moći pristupiti sakriven
 * Osjetljive korisničke informacije
 *: ''kućne adrese, brojevi telefona, brojevi bankovnih kartica itd.''",
 'revdelete-legend' => 'Postavi ograničenja vidljivosti',
-'revdelete-hide-text' => 'Sakrij tekst revizije',
+'revdelete-hide-text' => 'Tekst revizije',
 'revdelete-hide-image' => 'Sakrij sadržaj datoteke',
 'revdelete-hide-name' => 'Sakrij akciju i cilj',
 'revdelete-hide-comment' => 'Sakrij izmjene komentara',
-'revdelete-hide-user' => 'Sakrij korisničko ime urednika/IP',
+'revdelete-hide-user' => 'Korisničko ime urednika/IP',
 'revdelete-hide-restricted' => 'Ograniči podatke za administratore kao i za druge korisnike',
 'revdelete-radio-same' => '(ne mijenjaj)',
-'revdelete-radio-set' => 'Da',
-'revdelete-radio-unset' => 'Ne',
+'revdelete-radio-set' => 'Vidljivo',
+'revdelete-radio-unset' => 'Sakriveno',
 'revdelete-suppress' => 'Sakrij podatke od administratora kao i od drugih',
 'revdelete-unsuppress' => 'Ukloni ograničenja na vraćenim revizijama',
 'revdelete-log' => 'Razlog:',
@@ -1396,8 +1396,6 @@ Pokušajte u Vaš upit uključiti prefiks ''all:'' da bi ste pretražili sav sad
 'preferences' => 'Postavke',
 'mypreferences' => 'Postavke',
 'prefs-edits' => 'Broj izmjena:',
-'prefsnologin' => 'Niste prijavljeni',
-'prefsnologintext' => 'Da biste mogli podešavati korisničke postavke, morate <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} biti prijavljeni]</span>.',
 'changepassword' => 'Promijeni šifru',
 'prefs-skin' => 'Koža',
 'skin-preview' => 'Pregled',
@@ -1679,6 +1677,7 @@ Ako izaberete da date ime, biće korišteno za pripisivanje za vaš rad.',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|promjena|promjene|promjena}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|izmjena od vaše posljedne posjete}}',
 'enhancedrc-history' => 'historija',
 'recentchanges' => 'Nedavne izmjene',
 'recentchanges-legend' => 'Postavke nedavnih izmjena',
@@ -1688,6 +1687,7 @@ Ako izaberete da date ime, biće korišteno za pripisivanje za vaš rad.',
 'recentchanges-label-minor' => 'Ovo je mala izmjena',
 'recentchanges-label-bot' => 'Ova izmjenu je načinio bot',
 'recentchanges-label-unpatrolled' => 'Ova izmjena još nije patrolirana',
+'recentchanges-legend-newpage' => '$1 - nova stranica',
 'rcnote' => "Ispod {{PLURAL:$1|je '''$1''' promjena|su '''$1''' zadnje promjene|su '''$1''' zadnjih promjena}} u {{PLURAL:$2|posljednjem '''$2''' danu|posljednja '''$2''' dana|posljednjih '''$2''' dana}}, od $4, $5.",
 'rcnotefrom' => 'Ispod su izmjene od <b>$2</b> (do <b>$1</b> prikazano).',
 'rclistfrom' => 'Prikaži nove izmjene počev od $1',
@@ -2925,7 +2925,7 @@ U drugom slučaju možete koristiti i vezu, npr. [[{{#Special:Export}}/{{MediaWi
 'allmessagesdefault' => 'Uobičajeni tekst',
 'allmessagescurrent' => 'Trenutni tekst',
 'allmessagestext' => 'Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.
-Molimo posjetite [//www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.',
+Molimo posjetite [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.',
 'allmessagesnotsupportedDB' => 'Ova stranica ne može biti korištena jer je <i>wgUseDatabaseMessages</i> isključen.',
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter po stanju podešavanja:',
@@ -3128,6 +3128,8 @@ Ovo je vjerovatno izazvao vezom ka vanjskoj nepoželjnoj stranici.',
 'spam_reverting' => 'Vraćanje na zadnju verziju koja ne sadrži linkove ka $1',
 'spam_blanking' => 'Sve revizije koje sadrže linkove ka $1, očisti',
 'spam_deleting' => 'Sve revizije koje sadrže linkove na $1, brišem',
+'simpleantispam-label' => "Provjera protiv spama.
+'''NE''' popunjavaj ovo!",
 
 # Info page
 'pageinfo-title' => 'Informacije za "$1"',
@@ -3694,7 +3696,7 @@ Svi drugi linkovi u istoj liniji se smatraju izuzecima, npr. kod stranica gdje s
 
 # External editor support
 'edit-externally' => 'Izmjeni ovu datoteku koristeći vanjski program',
-'edit-externally-help' => '(Pogledajte [//www.mediawiki.org/wiki/Manual:External_editors instrukcije za podešavanje] za više informacija)',
+'edit-externally-help' => '(Pogledajte [https://www.mediawiki.org/wiki/Manual:External_editors instrukcije za podešavanje] za više informacija)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sve',
@@ -3936,7 +3938,7 @@ Također možete [[Special:EditWatchlist|koristiti standardni uređivač]].',
 'version-hook-subscribedby' => 'Pretplaćeno od',
 'version-version' => '(Verzija $1)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Ova wiki je zasnovana na '''[//www.mediawiki.org/ MediaWiki]''', autorska prava zadržana © 2001-$1 $2.",
+'version-poweredby-credits' => "Ova wiki je zasnovana na '''[https://www.mediawiki.org/ MediaWiki]''', autorska prava zadržana © 2001-$1 $2.",
 'version-poweredby-others' => 'ostali',
 'version-credits-summary' => 'Željeli bismo se zahvaliti sljedećim ljudima na njihovom doprinosu [[Special:Version|MediaWikiju]].',
 'version-license-info' => 'Mediawiki je slobodni softver, možete ga redistribuirati i/ili mijenjati pod uslovima GNU opće javne licence kao što je objavljeno od strane Fondacije Slobodnog Softvera, bilo u verziji 2 licence, ili (po vašoj volji) nekoj od kasniji verzija.
@@ -3972,8 +3974,7 @@ Trebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU GNU opće javne licence] z
 
 # Special:SpecialPages
 'specialpages' => 'Posebne stranice',
-'specialpages-note' => '----
-* Normalne posebne stranice.
+'specialpages-note' => '* Normalne posebne stranice.
 * <strong class="mw-specialpagerestricted">Zaštićene posebne stranice.</strong>',
 'specialpages-group-maintenance' => 'Izvještaji za održavanje',
 'specialpages-group-other' => 'Ostale posebne stranice',
@@ -4012,6 +4013,7 @@ Trebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU GNU opće javne licence] z
 'tags-tag' => 'Naziv oznake',
 'tags-display-header' => 'Vidljivost na spisku izmjena',
 'tags-description-header' => 'Puni opis značenja',
+'tags-active-header' => 'Aktivna?',
 'tags-hitcount-header' => 'Označene izmjene',
 'tags-active-yes' => 'Da',
 'tags-active-no' => 'Ne',
@@ -4173,4 +4175,21 @@ Inače, možete ispuniti jednostavan obrazac ispod. Vaš komentar biti će dodan
 # Limit report
 'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekunda|sekunde|sekundi}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Proširi šablone',
+'expand_templates_intro' => 'Ova posebna stranica uzima neki tekst i proširuje sve šablone u njemu rekurzivno.
+Ona također proširuje parserske funkcije poput
+<nowiki>{{</nowiki>#language:…}} i varijable poput
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;u principu gotovo sve između dvostrukih zagrada.
+Ovo se uradi putem poziva relevantnog parserskog nivoa iz same MediaWiki.',
+'expand_templates_title' => 'Naslov konteksta, za {{FULLPAGENAME}} itd.:',
+'expand_templates_input' => 'Tekst unosa:',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'XML izlaz',
+'expand_templates_ok' => 'U redu',
+'expand_templates_remove_comments' => 'Ukloni komentare',
+'expand_templates_remove_nowiki' => 'Onemogući oznake <nowiki> u rezultatima',
+'expand_templates_generate_xml' => 'Prikaži XML stablo parsera',
+'expand_templates_preview' => 'Pregled',
+
 );
index 759a4c1..063bb3f 100644 (file)
@@ -15,6 +15,7 @@
  * @author Cedric31
  * @author Davidpar
  * @author El libre
+ * @author Fitoschido
  * @author Gemmaa
  * @author Grondin
  * @author Iradigalesc
@@ -26,6 +27,7 @@
  * @author Martorell
  * @author McDutchie
  * @author Nemo bis
+ * @author Papapep
  * @author Pasqual (ca)
  * @author Paucabot
  * @author PerroVerd
@@ -78,7 +80,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Títol_incorrecte' ),
        'Blankpage'                 => array( 'Pàgina_en_blanc', 'Blanc' ),
        'Block'                     => array( 'Bloca' ),
-       'Blockme'                   => array( 'Bloca\'m' ),
        'Booksources'               => array( 'Fonts_bibliogràfiques' ),
        'BrokenRedirects'           => array( 'Redireccions_rompudes' ),
        'ChangeEmail'               => array( 'Canvia_adreça_electrònica' ),
@@ -88,9 +89,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crea_compte' ),
        'Deadendpages'              => array( 'Atzucacs' ),
        'DeletedContributions'      => array( 'Contribucions_esborrades' ),
-       'Disambiguations'           => array( 'Desambiguacions' ),
        'DoubleRedirects'           => array( 'Redireccions_dobles' ),
        'Emailuser'                 => array( 'Envia_missatge' ),
+       'ExpandTemplates'           => array( 'Expansió_de_plantilles' ),
        'Export'                    => array( 'Exporta' ),
        'Fewestrevisions'           => array( 'Pàgines_menys_editades' ),
        'FileDuplicateSearch'       => array( 'Cerca_fitxers_duplicats' ),
@@ -373,11 +374,11 @@ $messages = array(
 'vector-action-undelete' => 'Restaura',
 'vector-action-unprotect' => 'Desprotegeix',
 'vector-simplesearch-preference' => 'Activar la barra de cerca simplificada (només aparença Vector)',
-'vector-view-create' => 'Inicia',
+'vector-view-create' => 'Crea',
 'vector-view-edit' => 'Modifica',
 'vector-view-history' => "Mostra l'historial",
 'vector-view-view' => 'Mostra',
-'vector-view-viewsource' => 'Mostra la font',
+'vector-view-viewsource' => 'Mostra el codi',
 'actions' => 'Accions',
 'namespaces' => 'Espais de noms',
 'variants' => 'Variants',
@@ -407,10 +408,10 @@ $messages = array(
 'undeletethispage' => "Desfés l'eliminació d'aquesta pàgina",
 'undelete_short' => "Restaura {{PLURAL:$1|l'edició eliminada|$1 edicions eliminades}}",
 'viewdeleted_short' => 'Mostra {{PLURAL:$1|una edició eliminada|$1 edicions eliminades}}',
-'protect' => 'Protecció',
+'protect' => 'Protegeix',
 'protect_change' => 'canvia',
-'protectthispage' => 'Protecció de la pàgina',
-'unprotect' => 'Desprotecció',
+'protectthispage' => 'Protegeix aquesta pàgina',
+'unprotect' => 'Desprotegeix',
 'unprotectthispage' => 'Desprotegeix aquesta pàgina',
 'newpage' => 'Pàgina nova',
 'talkpage' => 'Discussió',
@@ -434,7 +435,7 @@ $messages = array(
 'redirectedfrom' => "(S'ha redirigit des de: $1)",
 'redirectpagesub' => 'Pàgina de redirecció',
 'lastmodifiedat' => 'Darrera modificació de la pàgina: $1 a les $2.',
-'viewcount' => 'Aquesta pàgina ha estat visitada {{PLURAL:$1|una vegada|$1 vegades}}.',
+'viewcount' => "S'ha visitat aquesta pàgina {{PLURAL:$1|una vegada|$1 vegades}}.",
 'protectedpage' => 'Pàgina protegida',
 'jumpto' => 'Dreceres ràpides:',
 'jumptonavigation' => 'navegació',
@@ -477,12 +478,10 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Obtingut de «$1»',
 'youhavenewmessages' => 'Tens $1 ($2).',
-'newmessageslink' => 'nous missatges',
-'newmessagesdifflink' => 'últims canvis',
 'youhavenewmessagesfromusers' => "Tens $1 {{PLURAL:$3|d'un altre usuari|de $3 usuaris}} ($2).",
 'youhavenewmessagesmanyusers' => 'Tens $1 de molts usuaris ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un nou missatge|nous missatges}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|darrer canvi|darrers canvis}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un nou missatge|999=nous missatges}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|darrer canvi|999=darrers canvis}}',
 'youhavenewmessagesmulti' => 'Teniu nous missatges a $1',
 'editsection' => 'modifica',
 'editold' => 'modifica',
@@ -539,6 +538,7 @@ Això pot indicar un error en el programari.",
 'databaseerror-textcl' => "S'ha produït un error en la consulta de la base de dades.",
 'databaseerror-query' => 'Consulta: $1',
 'databaseerror-function' => 'Funció: $1',
+'databaseerror-error' => 'Error:$1',
 'laggedslavemode' => 'Avís: La pàgina podria mancar de modificacions recents.',
 'readonly' => 'La base de dades es troba bloquejada',
 'enterlockreason' => 'Escriviu una raó pel bloqueig, així com una estimació de quan tindrà lloc el desbloqueig',
@@ -567,8 +567,8 @@ Aviseu-ho llavors a un [[Special:ListUsers/sysop|administrador]], deixant-li cla
 'unexpected' => "S'ha trobat un valor imprevist: «$1»=«$2».",
 'formerror' => "Error: no s'ha pogut enviar les dades del formulari",
 'badarticleerror' => 'Aquesta operació no es pot dur a terme en aquesta pàgina',
-'cannotdelete' => "No s'ha pogut esborrar la pàgina o fitxer «$1».
-Potser ja ha estat esborrat per algú altre.",
+'cannotdelete' => "No s'ha pogut suprimir la pàgina o fitxer «$1».
+Potser ja l'ha suprimit algú altre.",
 'cannotdelete-title' => 'No es pot suprimir la pàgina " $1 "',
 'delete-hook-aborted' => 'Un «hook» ha interromput la supressió.
 No ha donat cap explicació.',
@@ -581,12 +581,12 @@ No ha donat cap explicació.',
 'wrong_wfQuery_params' => 'Paràmetres incorrectes per a wfQuery()<br />
 Funció: $1<br />
 Consulta: $2',
-'viewsource' => 'Mostra la font',
+'viewsource' => 'Mostra el codi',
 'viewsource-title' => 'Mostra la font per a $1',
 'actionthrottled' => 'Acció limitada',
 'actionthrottledtext' => "Com a mesura per a prevenir la propaganda indiscriminada (spam), no podeu fer aquesta acció tantes vegades en un període de temps tan curt. Torneu-ho a intentar d'ací uns minuts.",
 'protectedpagetext' => "S'ha protegit la pàgina per evitar-hi modificacions.",
-'viewsourcetext' => "Podeu visualitzar i copiar la font d'aquesta pàgina:",
+'viewsourcetext' => 'Podeu visualitzar i copiar el codi font d’aquesta pàgina:',
 'viewyourtext' => "Vostè pot veure i copiar la font de ' ' les modificacions ' ' d'aquesta pàgina:",
 'protectedinterface' => "Aquesta pàgina proporciona el text de la interfície del software d'aquest wiki i està protegida per evitar els abusos.
 Per agregar o canviar les traduccions per a tots els wikis, si us plau fes servir [//translatewiki.net/ translatewiki.net], el projecte de localització de MediaWiki.",
@@ -608,7 +608,8 @@ L\'administrador que l\'ha bloquejat ha donat aquesta explicació: "$3".',
 'invalidtitle-knownnamespace' => "El títol amb l'espai de noms «$2» i text «$3» no és vàlid",
 'invalidtitle-unknownnamespace' => 'Títol no vàlid amb espai de noms desconegut de número «$1» i text «$2»',
 'exception-nologin' => 'No has iniciat sessió',
-'exception-nologin-text' => 'Aquesta pàgina o acció requereix que iniciïs sessió a aquest wiki.',
+'exception-nologin-text' => '[[Special:Userlogin|Inicieu sessió]] per poder accedir a aquesta pàgina o acció.',
+'exception-nologin-text-manual' => 'Si us plau, $1 per poder accedir a aquesta pàgina o acció.',
 
 # Virus scanner
 'virus-badscanner' => "Mala configuració: antivirus desconegut: ''$1''",
@@ -655,7 +656,7 @@ No oblideu de canviar les vostres [[Special:Preferences|preferències de {{SITEN
 'gotaccount' => 'Ja teniu un compte? $1.',
 'gotaccountlink' => 'Inicia una sessió',
 'userlogin-resetlink' => "Heu oblidat les vostres dades d'accés?",
-'userlogin-resetpassword-link' => 'Reinicia la contrasenya',
+'userlogin-resetpassword-link' => 'Has oblidat la teva contrasenya?',
 'helplogin-url' => 'Help:Registrar-se',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ajuda]]',
 'userlogin-loggedin' => 'Heu iniciat una sessió com {{GENDER:$1|$1}}.
@@ -716,7 +717,7 @@ la vostra antiga contrasenya.",
 'passwordsent' => "S'ha enviat una nova contrasenya a l'adreça electrònica registrada per «$1».
 Inicieu una sessió després que la rebeu.",
 'blocked-mailpassword' => 'La vostra adreça IP ha estat blocada. Se us ha desactivat la funció de recuperació de contrasenya per a prevenir abusos.',
-'eauthentsent' => "S'ha enviat un correu electrònic a la direcció especificada. Abans no s'envïi cap altre correu electrònic a aquesta adreça, cal verificar que és realment vostra. Per tant, cal que seguiu les instruccions presents en el correu electrònic que se us ha enviat.",
+'eauthentsent' => "S'ha enviat un correu electrònic a la direcció especificada. Abans no s'env cap altre correu electrònic a aquesta adreça, cal verificar que és realment vostra. Per tant, cal que seguiu les instruccions presents en el correu electrònic que se us ha enviat.",
 'throttled-mailpassword' => "Ja se us ha enviat un correu electrònic de reinicialització de contrasenya en {{PLURAL:$1|l'última hora|les últimes $1 hores}}.
 Per a prevenir abusos, només s'envia un correu electrònic de reinicialització de contrasenya cada {{PLURAL:$1|hora|$1 hores}}.",
 'mailerror' => "S'ha produït un error en enviar el missatge: $1",
@@ -736,7 +737,7 @@ Introduïu una adreça amb un format adequat o bé buideu el camp.",
 'createaccount-text' => "Algú ha creat un compte d'usuari anomenat $2 al projecte {{SITENAME}}
 ($4) amb la vostra adreça de correu electrònic. La contrasenya per a l'usuari «$2» és «$3». Hauríeu d'accedir al compte i canviar-vos aquesta contrasenya quan abans millor.
 
-Si no hi teniu cap relació i aquest compte ha estat creat per error, simplement ignoreu el missatge.",
+Si no hi teniu cap relació i aquest compte s'ha creat per error, simplement ignoreu el missatge.",
 'usernamehasherror' => "El nom d'usuari no pot contenir caràcters hash",
 'login-throttled' => "Heu realitzat massa intents d'accés a la sessió.
 Espereu $1 abans de tornar-ho a provar.",
@@ -896,8 +897,8 @@ El número d'identificació de la vostra adreça IP és $3, i l'ID del bloqueig
 'whitelistedittext' => 'Heu de $1 per modificar pàgines.',
 'confirmedittext' => "Heu de confirmar la vostra adreça electrònica abans de poder modificar les pàgines. Definiu i valideu la vostra adreça electrònica a través de les vostres [[Special:Preferences|preferències d'usuari]].",
 'nosuchsectiontitle' => 'No es pot trobar la secció',
-'nosuchsectiontext' => 'Heu intentat editar una secció que no existeix.
-Potser ha estat moguda o eliminada mentre estàveu veient la pàgina.',
+'nosuchsectiontext' => "Heu intentat editar una secció que no existeix.
+Potser s'ha mogut o eliminat mentre estàveu veient la pàgina.",
 'loginreqtitle' => 'Cal que inicieu una sessió',
 'loginreqlink' => 'inicia una sessió',
 'loginreqpagetext' => "Cal que seguiu l'enllaç «$1» per a visualitzar altres pàgines.",
@@ -936,9 +937,9 @@ Per més detalls, la darrera entrada del registre es mostra a continuació:",
 '''Encara no s'ha desat!'''",
 'userjspreview' => "'''Recordeu que només estau provant/previsualitzant el vostre JavaScript, encara no ho heu desat!'''",
 'sitecsspreview' => "'''Adoneu-vos que esteu veient una vista prèvia d'aquest full d'estil CSS.'''
-'''No n'hi ha estat encara gravada!'''",
-'sitejspreview' => "'''Adoneu-vos que esteu veient una vista prèvia d'aquest codi Javascript.'''
-'''No n'hi ha estat encara gravat!'''",
+'''Encara no s'ha desat!'''",
+'sitejspreview' => "'''Tingueu present que esteu previsualitzant aquest codi Javascript.'''
+'''Encara no s'ha desat!'''",
 'userinvalidcssjstitle' => "'''Atenció:''' No existeix l'aparença «$1». Recordeu que les subpàgines personalitzades amb extensions .css i .js utilitzen el títol en minúscules, per exemple, {{ns:user}}:NOM/vector.css no és el mateix que {{ns:user}}:NOM/Vector.css.",
 'updated' => '(Actualitzat)',
 'note' => "'''Nota:'''",
@@ -1007,11 +1008,11 @@ Podeu modificar les planes ja existents o bé [[Special:UserLogin|entrar en un c
 'permissionserrors' => 'Error de permisos',
 'permissionserrorstext' => 'No teniu permisos per a fer-ho, {{PLURAL:$1|pel següent motiu|pels següents motius}}:',
 'permissionserrorstext-withaction' => 'No teniu permís per a $2, {{PLURAL:$1|pel motiu següent|pels motius següents}}:',
-'recreate-moveddeleted-warn' => "'''Avís: Esteu creant una pàgina que ha estat prèviament esborrada.'''
+'recreate-moveddeleted-warn' => "'''Avís: esteu creant una pàgina que ha estat prèviament suprimida.'''
 
 Hauríeu de considerar si és realment necessari continuar editant aquesta pàgina.
 A continuació s'ofereix el registre d'esborraments i de reanomenaments de la pàgina:",
-'moveddeleted-notice' => "Aquesta pàgina ha estat esborrada.
+'moveddeleted-notice' => "S'ha suprimit aquesta pàgina.
 A continuació us mostrem com a referència el registre d'esborraments i reanomenaments de la pàgina.",
 'log-fulllog' => 'Veure tot el registre',
 'edit-hook-aborted' => "Modificació avortada pel hook.
@@ -1019,8 +1020,8 @@ No s'ha donat cap explicació.",
 'edit-gone-missing' => "No s'ha pogut actualitzar la pàgina.
 Sembla haver estat esborrada.",
 'edit-conflict' => "Conflicte d'edició.",
-'edit-no-change' => 'La vostra modificació ha estat ignorada perquè no feia cap canvi al text.',
-'postedit-confirmation' => 'La modificació ha estat desada.',
+'edit-no-change' => "S'ha ignorat la vostra modificació perquè no feia cap canvi al text.",
+'postedit-confirmation' => "S'ha desat la modificació.",
 'edit-already-exists' => "No s'ha pogut crear una pàgina.
 Ja existeix.",
 'defaultmessagetext' => 'Missatge per defecte',
@@ -1061,7 +1062,7 @@ Se n'han omès els arguments.",
 # "Undo" feature
 'undo-success' => "Pot desfer-se la modificació. Si us plau, reviseu la comparació de sota per a assegurar-vos que és el que voleu fer; llavors deseu els canvis per a finalitzar la desfeta de l'edició.",
 'undo-failure' => 'No pot desfer-se la modificació perquè hi ha edicions entre mig que hi entren en conflicte.',
-'undo-norev' => "No s'ha pogut desfer l'edició perquè no existeix o ha estat esborrada.",
+'undo-norev' => "No s'ha pogut desfer l'edició perquè no existeix o s'ha suprimit.",
 'undo-summary' => 'Es desfà la revisió $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussió]])',
 'undo-summary-username-hidden' => "Desfés la revisió $1 d'un usuari ocult",
 
@@ -1099,9 +1100,9 @@ El motiu donat per $3 és ''$2''",
 'history-feed-title' => 'Historial de revisió',
 'history-feed-description' => 'Historial de revisió per a aquesta pàgina del wiki',
 'history-feed-item-nocomment' => '$1 a $2',
-'history-feed-empty' => 'La pàgina demanada no existeix.
-Potser ha estat esborrada o reanomenada.
-Intenteu [[Special:Search|cercar al mateix wiki]] per a noves pàgines rellevants.',
+'history-feed-empty' => "La pàgina demanada no existeix.
+Potser s'ha suprimit o reanomenat.
+Intenteu [[Special:Search|cercar al mateix wiki]] per a noves pàgines rellevants.",
 
 # Revision deletion
 'rev-deleted-comment' => "(resum d'edició eliminat)",
@@ -1110,26 +1111,26 @@ Intenteu [[Special:Search|cercar al mateix wiki]] per a noves pàgines rellevant
 'rev-deleted-user-contribs' => "[nom d'usuari o adreça IP esborrada - modificació ocultada de les contribucions]",
 'rev-deleted-text-permission' => "Aquesta versió de la pàgina ha estat '''eliminada'''.
 Hi poden haver més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].",
-'rev-deleted-text-unhide' => "La revisió d'aquesta pàgina ha estat '''eliminada'''.
+'rev-deleted-text-unhide' => "S'ha '''suprimit''' la revisió d'aquesta pàgina.
 Hi poden haver més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].
 Encara podeu [$1 veure aquesta revisió] si així ho desitgeu.",
-'rev-suppressed-text-unhide' => "Aquesta versió de la pàgina ha estat '''eliminada'''.
+'rev-suppressed-text-unhide' => "S'ha '''suprimit''' aquesta versió de la pàgina.
 Hi poden haver més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre d'esborrats].
 Encara podeu [$1 veure aquesta revisió] si així ho desitgeu.",
-'rev-deleted-text-view' => "Aquesta versió de la pàgina ha estat '''eliminada'''.
+'rev-deleted-text-view' => "S'ha '''suprimit''' aquesta versió de la pàgina.
 Podeu veure-la; vegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].",
 'rev-suppressed-text-view' => "Aquesta versió de la pàgina ha estat '''eliminada'''.
 Podeu veure-la; vegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre d'esborrats].",
-'rev-deleted-no-diff' => "No podeu veure aquesta comparativa perquè una de les versions ha estat '''esborrada'''.
+'rev-deleted-no-diff' => "No podeu veure aquesta comparativa perquè s'ha '''suprimit''' una de les versions.
 Potser trobareu detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].",
-'rev-suppressed-no-diff' => "No podeu veure aquesta diferència perquè una de les revisions ha estat '''esborrada'''.",
+'rev-suppressed-no-diff' => "No podeu veure aquesta diferència perquè s'ha '''suprimit''' una de les revisions.",
 'rev-deleted-unhide-diff' => "Una de les revisions d'aquesta comparativa ha estat '''eliminada'''.
 Potser trobareu detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborrats].
 Encara podeu [$1 veure aquesta comparativa] si així ho desitgeu.",
-'rev-suppressed-unhide-diff' => "Una de les revisions d'aquesta comparativa ha estat '''esborrada'''.
+'rev-suppressed-unhide-diff' => "S¡ha '''suprimit''' una de les revisions d'aquesta comparativa.
 Podeu veure'n més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre de supressions].
 Podeu seguir [$1 veient aquesta comparativa] si així ho desitgeu.",
-'rev-deleted-diff-view' => "Una de les revisions d'aquesta comparativa ha estat '''esborrada'''.
+'rev-deleted-diff-view' => "S'ha '''suprimit'' una de les revisions d'aquesta comparativa.
 Podeu veure aquesta comparativa; poden haver-hi més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre d'esborraments].",
 'rev-suppressed-diff-view' => "Una de les revisions d'aquesta comparativa ha estat '''esborrada'''.
 Podeu veure aquesta comparativa; pot haver-hi més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre de supressions].",
@@ -1152,18 +1153,19 @@ funció, la revisió especificada no existeix, o bé esteu provant d'amagar l'ac
 Els altres administradors de {{SITENAME}} encara podran accedir al contingut amagat i restituir-lo de nou mitjançant aquesta mateixa interfície, si no hi ha cap altra restricció addicional.",
 'revdelete-confirm' => "Si us plau, confirmeu que és això el que desitgeu fer, que enteneu les conseqüències, i que esteu fent-ho d'acord amb [[{{MediaWiki:Policy-url}}|les polítiques acordades]].",
 'revdelete-suppress-text' => "Les supressions '''només''' han de ser portades a terme en els següents casos:
+* Informació potencialment difamatòria
 * Informació personal inapropiada
-*: ''adreces personals, números de telèfon, números de la seguretat social, etc.''",
+*: ''adreces personals, números de telèfon, números d'identificació nacional, etc.''",
 'revdelete-legend' => 'Defineix restriccions en la visibilitat',
-'revdelete-hide-text' => 'Amaga el text de revisió',
+'revdelete-hide-text' => 'Text de la revisió',
 'revdelete-hide-image' => 'Amaga el contingut del fitxer',
 'revdelete-hide-name' => "Acció d'amagar i objectiu",
-'revdelete-hide-comment' => "Amaga el comentari de l'edició",
-'revdelete-hide-user' => "Amaga el nom d'usuari o la IP de l'editor",
+'revdelete-hide-comment' => 'Modifica el resum',
+'revdelete-hide-user' => "Nom d'usuari / adreça IP de l'editor",
 'revdelete-hide-restricted' => 'Suprimir les dades als administradors així com a la resta.',
 'revdelete-radio-same' => '(no modificar)',
-'revdelete-radio-set' => 'Si',
-'revdelete-radio-unset' => 'No',
+'revdelete-radio-set' => 'Oculta',
+'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => 'Suprimeix també les dades dels administradors',
 'revdelete-unsuppress' => 'Suprimir les restriccions de les revisions restaurades',
 'revdelete-log' => 'Motiu:',
@@ -1183,8 +1185,8 @@ $1",
 No es pot amagar.",
 'revdelete-show-no-access' => "Error en mostrar l'element del $1 a les $2: està marcat com a ''restringit''.
 No hi tens accés.",
-'revdelete-modify-no-access' => "Error en modificar l'element del $1 a les $2: aquest element ha estat marcat com a ''restringit''.
-No hi tens accés.",
+'revdelete-modify-no-access' => "S'ha produït un error en modificar l'element del $1 a les $2: aquest element s'ha marcat com a 'restringit''.
+No hi teniu accés.",
 'revdelete-modify-missing' => "Error en modificar l'element ID $1: no figura a la base de dades!",
 'revdelete-no-change' => "'''Atenció:''' la revisió del $1 a les $2 ja té les restriccions de visibilitat sol·licitades.",
 'revdelete-concurrent-change' => "Error en modificar l'element del $1 a les $2: el seu estat sembla haver estat canviat per algú altre quan intentaves modificar-lo.
@@ -1248,7 +1250,7 @@ Assegureu-vos que aquest canvi mantindrà la continuïtat històrica de la pàgi
 'diff-multi-manyusers' => "({{PLURAL:$1|Hi ha una revisió intermèdia|Hi ha $1 revisions intermèdies}} sense mostrar fetes per més {{PLURAL:$2|d'un usuari|de $2 usuaris}})",
 'difference-missing-revision' => "{{PLURAL:$2|Una revisió|$2 revisions}} d'aquesta diferència ($1) no {{PLURAL:$2|s'ha|s'han}} trobat.
 
-Això passa generalment en seguir un enllaç obsolet de diferències a una pàgina que ha estat esborrada.
+Això passa generalment en seguir un enllaç obsolet de diferències a una pàgina que s'ha suprimit.
 Es pot trobar més informació en el [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre de supressions].",
 
 # Search results
@@ -1317,8 +1319,7 @@ Es pot trobar més informació en el [{{fullurl:{{#Special:Log}}/delete|page={{F
 'preferences' => 'Preferències',
 'mypreferences' => 'Preferències',
 'prefs-edits' => "Nombre d'edicions:",
-'prefsnologin' => 'No heu iniciat cap sessió',
-'prefsnologintext' => 'Heu d\'estar <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} autenticats]</span> per a seleccionar les preferències d\'usuari.',
+'prefsnologintext2' => "Useu $1 per configurar preferències d'usuari.",
 'changepassword' => 'Canvia la contrasenya',
 'prefs-skin' => 'Aparença',
 'skin-preview' => 'prova',
@@ -1358,7 +1359,7 @@ Es pot trobar més informació en el [{{fullurl:{{#Special:Log}}/delete|page={{F
 'prefs-help-watchlist-token2' => 'Aquesta és la clau secreta pel canal de continguts de la vostra llista de seguiment.
 Qualsevol que la conegui podria llegir la vostra llista de seguiment, així que no la compartiu.
 [[Special:ResetTokens|Cliqueu aquí si voleu restaurar-la]].',
-'savedprefs' => "S'han desat les vostres preferències",
+'savedprefs' => 'S’han desat les vostres preferències.',
 'timezonelegend' => 'Fus horari:',
 'localtime' => 'Hora local:',
 'timezoneuseserverdefault' => "Utilitza l'hora per defecte del wiki ($1)",
@@ -1614,7 +1615,10 @@ Ha de tenir com a molt {{PLURAL:$1|un caràcter|$1 caràcters}}.',
 'recentchanges-label-newpage' => 'Aquesta modificació inicià una pàgina',
 'recentchanges-label-minor' => 'Aquesta és una modificació menor',
 'recentchanges-label-bot' => 'Aquesta modificació fou feta per un bot',
-'recentchanges-label-unpatrolled' => 'Aquesta modificació encara no ha estat patrullada',
+'recentchanges-label-unpatrolled' => "Aquesta modificació encara no s'ha patrullat",
+'recentchanges-label-plusminus' => 'La mida de la pàgina ha canviat aquest nombre de bytes',
+'recentchanges-legend-newpage' => '(vegeu també la  [[Special:NewPages|llista de pàgines noves]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => 'A continuació hi ha {{PLURAL:$1|el darrer canvi|els darrers <strong>$1</strong> canvis}} en {{PLURAL:$2|el darrer dia|els darrers <strong>$2</strong> dies}}, actualitzats a les $5 del $4.',
 'rcnotefrom' => 'A sota hi ha els canvis des de <b>$2</b> (es mostren fins <b>$1</b>).',
 'rclistfrom' => 'Mostra els canvis nous des de $1',
@@ -1702,7 +1706,7 @@ Vegeu la [[Special:NewFiles|galeria de nous fitxers]] per a una presentació mé
 'filename-tooshort' => 'El nom del fitxer és massa curt.',
 'filetype-banned' => 'Aquest tipus de fitxer està prohibit.',
 'verification-error' => 'Aquest fitxer no ha passat la verificació de fitxers.',
-'hookaborted' => "La modificació que vau tractar de fer ha estat canceŀlada per un lligam d'extensió.",
+'hookaborted' => "La modificació que vau tractar de fer l'ha canceŀlat un lligam d'extensió.",
 'illegal-filename' => 'El nom del fitxer no està permès.',
 'overwrite' => 'No es permet sobreescriure un fitxer existent.',
 'unknown-error' => "S'ha produït un error desconegut.",
@@ -1833,7 +1837,7 @@ No s'hi ha pogut comprovar la seguretat.",
 'uploadstash-clear' => 'Esborra els fitxers en reserva',
 'uploadstash-nofiles' => 'No teniu fitxers en reserva',
 'uploadstash-badtoken' => "No s'ha pogut realitzar l'acció, possiblement perquè han caducat la vostra identificació. Intenteu-ho de nou.",
-'uploadstash-errclear' => "No ha estat possible l'esborrat dels fitxers.",
+'uploadstash-errclear' => "No s'ha pogut suprimir els fitxers.",
 'uploadstash-refresh' => 'Actualitza la llista de fitxers',
 'invalid-chunk-offset' => 'El desplaçament del fragment no és vàlid',
 
@@ -1894,6 +1898,7 @@ Si filtreu per usuari només es mostraran els fitxers la versió més recent del
 'listfiles-show-all' => 'Inclou versions antigues de les imatges',
 'listfiles-latestversion' => 'Versió actual',
 'listfiles-latestversion-yes' => 'Sí',
+'listfiles-latestversion-no' => 'No',
 
 # File description page
 'file-anchor-link' => 'Fitxer',
@@ -1944,7 +1949,7 @@ Potser voleu modificar-ne la descripció en la seva [$2 pàgina de descripció].
 'filerevert-comment' => 'Motiu:',
 'filerevert-defaultcomment' => "S'ha revertit a la versió com de $2, $1",
 'filerevert-submit' => 'Reverteix',
-'filerevert-success' => "'''[[Media:$1|$1]]''' ha estat revertit a la [$4 versió de $3, $2].",
+'filerevert-success' => "S'ha revertit '''[[Media:$1|$1]]''' a la [$4 versió de $3, $2].",
 'filerevert-badversion' => "No hi ha cap versió local anterior d'aquest fitxer amb la marca horària que es proporciona.",
 
 # File deletion
@@ -2250,7 +2255,7 @@ L'adreça electrònica que vau indicar a [[Special:Preferences|les vostres prefe
 'emailccme' => "Envia'm una còpia del meu missatge.",
 'emailccsubject' => 'Còpia del vostre missatge a $1: $2',
 'emailsent' => 'Correu electrònic enviat',
-'emailsenttext' => 'El vostre correu electrònic ha estat enviat.',
+'emailsenttext' => "S'ha enviat el vostre correu electrònic.",
 'emailuserfooter' => "Aquest missatge de correu electrònic l'ha enviat $1 a $2 amb la funció «e-mail» del projecte {{SITENAME}}.",
 
 # User Messenger
@@ -2276,7 +2281,7 @@ S\'hi mostraran els canvis futurs que tinguin lloc en aquesta pàgina i la corre
 'unwatch' => 'Desatén',
 'unwatchthispage' => 'Desatén',
 'notanarticle' => 'No és una pàgina amb contingut',
-'notvisiblerev' => 'La versió ha estat esborrada',
+'notvisiblerev' => "S'ha suprimit la versió",
 'watchlist-details' => 'Teniu $1 {{PLURAL:$1|pàgina vigilada|pàgines vigilades}}, sense comptar les pàgines de discussió.',
 'wlheader-enotif' => 'La notificació per correu electrònic està habilitada.',
 'wlheader-showupdated' => "Les pàgines que s'han canviat des de la vostra darrera visita es mostren en '''negreta'''.",
@@ -2319,7 +2324,7 @@ Contacteu amb l\'editor:
 correu: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-No rebreu més notificacions de futurs canvis si no visiteu la pàgina.
+No rebreu més notificacions en cas de més activitat a menys que visiteu aquesta pàgina havent iniciat sessió.
 També podeu canviar el mode de notificació de les pàgines que vigileu en la vostra llista de seguiment.
 
 El servei de notificacions del projecte {{SITENAME}}
@@ -2354,8 +2359,8 @@ Confirmeu que realment ho voleu fer, que enteneu les
 conseqüències, i que el que esteu fent està d'acord amb la [[{{MediaWiki:Policy-url}}|política]] del projecte.",
 'actioncomplete' => "S'ha realitzat l'acció de manera satisfactòria.",
 'actionfailed' => "L'acció ha fallat",
-'deletedtext' => '«$1» ha estat esborrat.
-Vegeu $2 per a un registre dels esborrats més recents.',
+'deletedtext' => "S'ha suprimit «$1».
+Vegeu $2 per a un registre dels esborrats més recents.",
 'dellogpage' => "Registre d'eliminació",
 'dellogpagetext' => 'Davall hi ha una llista dels esborraments més recents.',
 'deletionlog' => "Registre d'esborrats",
@@ -2384,8 +2389,8 @@ Vegeu $2 per a un registre dels esborrats més recents.',
 'alreadyrolled' => "No es pot revertir la darrera modificació de [[:$1]]
 de l'usuari [[User:$2|$2]] ([[User talk:$2|Discussió]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]). Algú altre ja ha modificat o revertit la pàgina.
 
-La darrera modificació ha estat feta per l'usuari [[User:$3|$3]] ([[User talk:$3|Discussió]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
-'editcomment' => "El resum d'edició ha estat: «$1».",
+La darrera modificació l'ha fet l'usuari [[User:$3|$3]] ([[User talk:$3|Discussió]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+'editcomment' => "El resum d'edició és: «$1».",
 'revertpage' => "Revertides les edicions de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussió]]) a l'última versió de [[User:$1|$1]]",
 'revertpage-nouser' => "Edicions revertides per un usuari ocult a l'última revisió de {{GENDER:$1|[[User:$1|$1]]}}",
 'rollback-success' => "Edicions revertides de $1; s'ha canviat a la darrera versió de $2.",
@@ -2611,8 +2616,8 @@ quines pàgines en concret estan sent vandalitzades).",
 'ipb-confirm' => 'Confirma el blocatge',
 'badipaddress' => "L'adreça IP no té el format correcte.",
 'blockipsuccesssub' => "S'ha blocat amb èxit",
-'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] ha estat {{GENDER:$1|blocat|blocada}}.<br />
-Vegeu la [[Special:BlockList|llista de bloqueigs]] per revisar-los.',
+'blockipsuccesstext' => "S'ha {{GENDER:$1|blocat|blocada}} [[Special:Contributions/$1|$1]] .<br />
+Vegeu la [[Special:BlockList|llista de bloqueigs]] per revisar-los.",
 'ipb-blockingself' => 'Esteu a punt de blocar-vos a vós mateix! Esteu segurs de voler-ho fer?',
 'ipb-confirmhideuser' => "Esteu a punt de bloquejar un usuari que està marcat amb l'opció «amaga l'usuari». Això suprimirà el seu nom a totes les llistes i registres. Esteu segurs de voler-ho fer?",
 'ipb-edit-dropdown' => 'Edita les raons per a blocar',
@@ -2625,7 +2630,7 @@ Vegeu la [[Special:BlockList|llista de bloqueigs]] per revisar-los.',
 l'accés a l'escriptura a una adreça IP o un usuari prèviament bloquejat.",
 'ipusubmit' => 'Desbloca aquesta adreça',
 'unblocked' => "S'ha desbloquejat l'{{GENDER:$1|usuari|usuària}} [[User:$1|$1]]",
-'unblocked-range' => '$1 ha estat desblocat',
+'unblocked-range' => "s'ha desblocat $1",
 'unblocked-id' => "S'ha eliminat el bloqueig de $1",
 'blocklist' => 'Usuaris blocats',
 'ipblocklist' => 'Usuaris blocats',
@@ -2633,12 +2638,12 @@ l'accés a l'escriptura a una adreça IP o un usuari prèviament bloquejat.",
 'blocklist-userblocks' => 'Amaga bloquejos de compte',
 'blocklist-tempblocks' => 'Amaga bloquejos temporals',
 'blocklist-addressblocks' => "Amaga bloquejos d'una sola IP",
-'blocklist-rangeblocks' => 'Amaga els blocatges de rang',
+'blocklist-rangeblocks' => 'Amaga els bloquejos de rang',
 'blocklist-timestamp' => 'Marca horària',
 'blocklist-target' => 'Usuari blocat',
 'blocklist-expiry' => 'Caduca',
-'blocklist-by' => 'Administrador del blocatge',
-'blocklist-params' => 'Paràmetres del blocatge',
+'blocklist-by' => 'Administrador que ha blocat',
+'blocklist-params' => 'Paràmetres del bloqueig',
 'blocklist-reason' => 'Motiu',
 'ipblocklist-submit' => 'Cerca',
 'ipblocklist-localblock' => 'Bloqueig local',
@@ -2660,10 +2665,10 @@ l'accés a l'escriptura a una adreça IP o un usuari prèviament bloquejat.",
 'autoblocker' => "Heu estat blocat automàticament perquè la vostra adreça IP ha estat recentment utilitzada per l'usuari ''[[User:$1|$1]]''.
 El motiu del bloqueig de $1 és: ''$2''.",
 'blocklogpage' => 'Registre de bloquejos',
-'blocklog-showlog' => 'Aquest usuari ha estat blocat prèviament.
-Per més detalls, a sota es mostra el registre de bloquejos:',
-'blocklog-showsuppresslog' => 'Aquest usuari ha estat blocat i amagat prèviament.
-Per més detalls, a sota es mostra el registre de supressions:',
+'blocklog-showlog' => "S'ha blocat aquest usuari prèviament.
+Per més detalls, a sota es mostra el registre de bloquejos:",
+'blocklog-showsuppresslog' => "S'ha blocat i amagat aquest usuari prèviament.
+Per més detalls, a sota es mostra el registre de supressions:",
 'blocklogentry' => "ha blocat l'{{GENDER:$1|usuari|usuària}} [[$1]] per un període de: $2 $3",
 'reblock-logentry' => 'canviades les opcions del blocatge a [[$1]] amb caducitat a $2, $3',
 'blocklogtext' => 'Això és una relació de accions de bloqueig i desbloqueig. Les adreces IP bloquejades automàticament no apareixen. Vegeu la [[Special:BlockList|llista de bloqueigs]] per veure una llista dels actuals bloqueigs operatius.',
@@ -2688,7 +2693,7 @@ Per més detalls, a sota es mostra el registre de supressions:',
 'ip_range_invalid' => 'Rang de IP no vàlid.',
 'ip_range_toolarge' => 'No estan permesos el bloquejos de rangs més grans que /$1.',
 'proxyblocker' => 'Bloqueig de proxy',
-'proxyblockreason' => "La vostra adreça IP ha estat bloquejada perquè és un proxy obert. Si us plau contactau el vostre proveïdor d'Internet o servei tècnic i informau-los d'aquest seriós problema de seguretat.",
+'proxyblockreason' => "S'ha blocat la vostra adreça IP perquè és un proxy obert. Contactau el vostre proveïdor d'Internet o servei tècnic i informau-los d'aquest seriós problema de seguretat.",
 'sorbsreason' => "La vostra adreça IP està llistada com a servidor intermediari (''proxy'') obert dins la llista negra de DNS que fa servir el projecte {{SITENAME}}.",
 'sorbs_create_account_reason' => "La vostra adreça IP està llistada com a servidor intermediari (''proxy'') obert a la llista negra de DNS que utilitza el projecte {{SITENAME}}. No podeu crear-vos-hi un compte",
 'xffblockreason' => "Una adreça IP present en la capçalera X-Forwarded-For, ja sigui vostra o la d'un servidor proxy que esteu utilitzant, ha estat blocada. El motiu inicial del bloqueig és: $1",
@@ -2778,7 +2783,7 @@ Incorporeu-les manualment, si us plau.",
 'move-subpages' => "Desplaça'n també les subpàgines (fins a $1)",
 'move-talk-subpages' => 'Desplaça també les subpàgines de la pàgina de discussió (fins un màxim de $1)',
 'movepage-page-exists' => "La pàgina $1 ja existeix i no pot sobreescriure's automàticament.",
-'movepage-page-moved' => 'La pàgina $1 ha estat traslladada a $2.',
+'movepage-page-moved' => "La pàgina $1 s'ha traslladat a $2.",
 'movepage-page-unmoved' => "La pàgina $1 no s'ha pogut moure a $2.",
 'movepage-max-pages' => "{{PLURAL:$1|S'ha mogut una pàgina|S'han mogut $1 pàgines}} que és el nombre màxim, i per tant no se'n mourà automàticament cap més.",
 'movelogpage' => 'Registre de reanomenaments',
@@ -2841,7 +2846,7 @@ En el darrer cas, podeu fer servir un enllaç com ara [[{{#Special:Export}}/{{Me
 'allmessagesname' => 'Nom',
 'allmessagesdefault' => 'Text per defecte',
 'allmessagescurrent' => 'Text actual',
-'allmessagestext' => "Tot seguit hi ha una llista dels missatges del sistema que es troben a l'espai de noms ''MediaWiki''. La traducció genèrica d'aquests missatges no s'hauria de fer localment sinó a la traducció del programari MediaWiki. Si voleu ajudar-hi visiteu [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net].",
+'allmessagestext' => "Tot seguit hi ha una llista dels missatges del sistema que es troben a l'espai de noms ''MediaWiki''. La traducció genèrica d'aquests missatges no s'hauria de fer localment sinó a la traducció del programari MediaWiki. Si voleu ajudar-hi visiteu [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net].",
 'allmessagesnotsupportedDB' => "No es pot processar '''{{ns:special}}:Allmessages''' perquè la variable '''\$wgUseDatabaseMessages''' està desactivada.",
 'allmessages-filter-legend' => 'Filtre',
 'allmessages-filter' => "Filtra per l'estat de personalització:",
@@ -2890,7 +2895,7 @@ Deseu-lo al vostre ordinador i carregueu-ne una còpia ací.",
 'imported-log-entries' => "{{PLURAL:$1|S'ha importat una entrada del registre|S'han importat $1 entrades del registre}}.",
 'importfailed' => 'La importació ha fallat: $1',
 'importunknownsource' => "No es reconeix el tipus de la font d'importació",
-'importcantopen' => "No ha estat possible d'obrir el fitxer a importar",
+'importcantopen' => "No s'ha pogut obrir el fitxer a importar",
 'importbadinterwiki' => "Enllaç d'interwiki incorrecte",
 'importnotext' => 'Buit o sense text',
 'importsuccess' => 'Importació completada!',
@@ -3004,6 +3009,7 @@ Deseu-lo al vostre ordinador i carregueu-ne una còpia ací.",
 Permet afegir un motiu al resum.',
 'tooltip-preferences-save' => 'Desa preferències',
 'tooltip-summary' => 'Afegiu un breu resum',
+'interlanguage-link-title' => '$1 - $2',
 
 # Stylesheets
 'common.css' => '/* Editeu aquest fitxer per personalitzar totes les aparences per al lloc sencer */',
@@ -3036,6 +3042,8 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 'spam_reverting' => 'Es reverteix a la darrera versió que no conté enllaços a $1',
 'spam_blanking' => "Totes les revisions contenien enllaços $1, s'està deixant en blanc",
 'spam_deleting' => "S'estan suprimint totes les revisions que contenien enllaços a $1",
+'simpleantispam-label' => "Comprovació antispam.
+'''NO''' ho ompliu!",
 
 # Info page
 'pageinfo-title' => 'Informació de «$1»',
@@ -3049,6 +3057,7 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 'pageinfo-length' => 'Mida de la pàgina (en bytes)',
 'pageinfo-article-id' => 'ID de la pàgina',
 'pageinfo-language' => 'Llengua del contingut de la pàgina',
+'pageinfo-content-model' => 'Plantilla de contingut de pàgina',
 'pageinfo-robot-policy' => 'Indexació per robots',
 'pageinfo-robot-index' => 'Permès',
 'pageinfo-robot-noindex' => 'No permès',
@@ -3090,7 +3099,7 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 'markaspatrolleddiff' => 'Marca com a supervisat',
 'markaspatrolledtext' => 'Marca la pàgina com a supervisada',
 'markedaspatrolled' => 'Marca com a supervisat',
-'markedaspatrolledtext' => 'La revisió seleccionada de [[:$1]] ha estat marcada com a patrullada.',
+'markedaspatrolledtext' => "S'ha marcat com a patrullada la revisió seleccionada de [[:$1]].",
 'rcpatroldisabled' => "S'ha inhabilitat la supervisió dels canvis recents",
 'rcpatroldisabledtext' => 'La funció de supervisió de canvis recents està actualment inhabilitada.',
 'markedaspatrollederror' => 'No es pot marcar com a supervisat',
@@ -3132,7 +3141,7 @@ Si l'executeu, podeu comprometre la seguretat del vostre sistema.",
 'svg-long-desc' => 'fitxer SVG, nominalment $1 × $2 píxels, mida del fitxer: $3',
 'svg-long-desc-animated' => 'Fitxer SVG animat, nominalment $1 × $2 píxels, mida del fitxer: $3',
 'svg-long-error' => 'El fitxer SVG no és vàlid: $1',
-'show-big-image' => 'Imatge en màxima resolució',
+'show-big-image' => 'Fitxer original',
 'show-big-image-preview' => "Mida d'aquesta previsualització: $1.",
 'show-big-image-other' => '{{PLURAL:$2|Altra resolució|Altres resolucions}}: $1.',
 'show-big-image-size' => '$1 × $2 píxels',
@@ -3359,7 +3368,7 @@ La resta d'enllaços de la línia són les excepcions, és a dir, les pàgines o
 'exif-serialnumber' => 'Número de sèrie de la càmera',
 'exif-cameraownername' => 'Propietari de la càmera',
 'exif-label' => 'Etiqueta',
-'exif-datetimemetadata' => 'Data que la metadata ha estat modificada per última vegada',
+'exif-datetimemetadata' => "Data que s'ha modificat les metadades per última vegada",
 'exif-nickname' => "Nom informal de l'imatge",
 'exif-rating' => 'Valoració (sobre 5)',
 'exif-rightscertificate' => 'Certificat de gestió de drets',
@@ -3601,7 +3610,7 @@ La resta d'enllaços de la línia són les excepcions, és a dir, les pàgines o
 
 # External editor support
 'edit-externally' => 'Edita aquest fitxer fent servir una aplicació externa',
-'edit-externally-help' => '(Vegeu les [//www.mediawiki.org/wiki/Manual:External_editors instruccions de configuració] per a més informació)',
+'edit-externally-help' => '(Vegeu les [https://www.mediawiki.org/wiki/Manual:External_editors instruccions de configuració] per a més informació)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'totes',
@@ -3703,6 +3712,9 @@ Confirmeu que realment voleu tornar-la a crear.",
 'confirm-unwatch-button' => "D'acord",
 'confirm-unwatch-top' => 'Voleu treure aquesta pàgina de la llista de seguiment?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '«$1»',
+
 # Multipage image navigation
 'imgmultipageprev' => '← pàgina anterior',
 'imgmultipagenext' => 'pàgina següent →',
@@ -3732,8 +3744,8 @@ Confirmeu que realment voleu tornar-la a crear.",
 'livepreview-ready' => "S'està carregant… Preparat!",
 'livepreview-failed' => 'Ha fallat la vista ràpida!
 Proveu-ho amb la previsualització normal.',
-'livepreview-error' => 'La connexió no ha estat possible: $1 «$2»
-Proveu-ho amb la previsualització normal.',
+'livepreview-error' => "No s'ha pogut efectuar la connexió: $1 «$2»
+Proveu-ho amb la previsualització normal.",
 
 # Friendlier slave lag warnings
 'lag-warn-normal' => 'Els canvis més nous de $1 {{PLURAL:$1|segon|segons}} podrien no mostrar-se a la llista.',
@@ -3789,7 +3801,7 @@ També podeu [[Special:EditWatchlist|utilitzar l'editor estàndard]].",
 'version-hook-subscribedby' => 'Subscrit per',
 'version-version' => '(Versió $1)',
 'version-license' => 'Llicència',
-'version-poweredby-credits' => "El wiki funciona gràcies a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "El wiki funciona gràcies a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'altres',
 'version-poweredby-translators' => 'Traductors de translatewiki.net',
 'version-credits-summary' => 'El nostre reconeixement a les següents persones per la seva aportació a [[Special:Version|MediaWiki]]',
@@ -3808,7 +3820,7 @@ Amb aquest programa heu d'haver rebut [{{SERVER}}{{SCRIPTPATH}}/COPYING una còp
 # Special:Redirect
 'redirect' => 'Redirigeix per fitxer, usuari o ID de la revisió',
 'redirect-legend' => 'Redirigeix a un fitxer o a una pàgina',
-'redirect-summary' => "Aquesta pàgina especial redirigeix a un fitxer (donat el nom del fitxer), una pàgina (donada un ID de la revisió), o a una pàgina d'usuari (donat un ID numèric d'usuari).",
+'redirect-summary' => "Aquesta pàgina especial redirigeix a un fitxer (donat el nom del fitxer), una pàgina (donada un ID de la revisió), o a una pàgina d'usuari (donat un ID numèric d'usuari). Ús: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Vés-hi',
 'redirect-lookup' => 'Consulta:',
 'redirect-value' => 'Valor:',
@@ -3830,10 +3842,9 @@ Amb aquest programa heu d'haver rebut [{{SERVER}}{{SCRIPTPATH}}/COPYING una còp
 
 # Special:SpecialPages
 'specialpages' => 'Pàgines especials',
-'specialpages-note' => '----
-* Pàgines especials normals.
-* <span class="mw-specialpagerestricted">Pàgines especials restringides.</span>
-* <span class="mw-specialpagecached">Pàgines especials en memòria cau (poden ser obsoletes).</span>',
+'specialpages-note-top' => 'Llegenda',
+'specialpages-note' => '* Pàgines especials normals.
+* <span class="mw-specialpagerestricted">Pàgines especials restringides.</span>',
 'specialpages-group-maintenance' => 'Informes de manteniment',
 'specialpages-group-other' => 'Altres pàgines especials',
 'specialpages-group-login' => 'Iniciar sessió / Crear un compte',
@@ -3874,6 +3885,7 @@ Amb aquest programa heu d'haver rebut [{{SERVER}}{{SCRIPTPATH}}/COPYING una còp
 'tags-active-header' => 'Actiu?',
 'tags-hitcount-header' => 'Canvis etiquetats',
 'tags-active-yes' => 'Sí',
+'tags-active-no' => 'No',
 'tags-edit' => 'modifica',
 'tags-hitcount' => '$1 {{PLURAL:$1|canvi|canvis}}',
 
@@ -3992,7 +4004,7 @@ Altrament, podeu fer servir un senzill formulari a continuació. El vostre comen
 'api-error-filetype-banned' => 'Aquest tipus de fitxer està prohibit.',
 'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|no és un tipus de fitxer permès|no són tipus de fitxer permesos}}. {{PLURAL:$3|El tipus de fitxer permès és|Els tipus de fitxer permesos són}} $2.',
 'api-error-filetype-missing' => 'El nom de fitxer no té extensió.',
-'api-error-hookaborted' => "La modificació que heu intentat fer ha estat canceŀlada per un mòdul d'extensió.",
+'api-error-hookaborted' => "Un mòdul d'extensió ha cancel·lat la modificació que heu intentat fer.",
 'api-error-http' => 'Error intern: no es pot connectar al servidor.',
 'api-error-illegal-filename' => 'El nom del fitxer no està permès.',
 'api-error-internal-error' => 'Error intern: el procés de càrrega en el wiki no ha funcionat.',
@@ -4045,4 +4057,18 @@ Altrament, podeu fer servir un senzill formulari a continuació. El vostre comen
 'limitreport-expansiondepth' => "Profunditat màxima d'expansió",
 'limitreport-expensivefunctioncount' => "Número de funcions d'anàlisi dispendioses",
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expansió de plantilles',
+'expand_templates_intro' => "Aquesta pàgina especial expandeix de forma recursiva totes les plantilles d'un text donat.
+També expandeix les funcions sintàctiques, com ara <code><nowiki>{{</nowiki>#language:…}}</code>, i les variables predefinides, com <code><nowiki>{{</nowiki>CURRENTDAY}}</code> &mdash;de fet, gairebé tot que estigui entre claus dobles.",
+'expand_templates_title' => 'Títol per contextualitzar ({{FULLPAGENAME}}, etc):',
+'expand_templates_input' => 'El vostre text:',
+'expand_templates_output' => 'Resultat:',
+'expand_templates_xml_output' => 'Sortida XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Elimina els comentaris',
+'expand_templates_remove_nowiki' => "Suprimeix l'etiqueta <nowiki> en el resultat",
+'expand_templates_generate_xml' => "Mostra l'arbre XML",
+'expand_templates_preview' => 'Previsualitza',
+
 );
index 7c96e25..bd27279 100644 (file)
  * @author Yejianfei
  */
 
+$fallback = 'nan, zh-hant';
+
+$namespaceNames = array(
+       NS_MEDIA            => '媒體',
+       NS_SPECIAL          => '特殊',
+       NS_TALK             => '討論',
+       NS_USER             => '用戶',
+       NS_USER_TALK        => '用戶討論',
+       NS_PROJECT_TALK     => '$1討論',
+       NS_FILE             => '文件',
+       NS_FILE_TALK        => '文件討論',
+       NS_MEDIAWIKI        => '媒體維基',
+       NS_MEDIAWIKI_TALK   => '媒體維基討論',
+       NS_TEMPLATE         => '模板',
+       NS_TEMPLATE_TALK    => '模板討論',
+       NS_HELP             => '幫助',
+       NS_HELP_TALK        => '幫助討論',
+       NS_CATEGORY         => '分類',
+       NS_CATEGORY_TALK    => '分類討論',
+);
+
+$specialPageAliases = array(
+       'Activeusers'               => array( '活動用戶' ),
+       'Allmessages'               => array( '全部信息' ),
+       'Allpages'                  => array( '全部頁面' ),
+       'Ancientpages'              => array( '舊其頁面' ),
+       'Badtitle'                  => array( '呆其標題' ),
+       'Blankpage'                 => array( '空白頁面' ),
+       'Block'                     => array( '封鎖', '封鎖IP', '封鎖用戶' ),
+       'Booksources'               => array( '圖書源' ),
+       'BrokenRedirects'           => array( '呆其重定向' ),
+       'Categories'                => array( '分類' ),
+       'ChangeEmail'               => array( '改變電子郵件' ),
+       'ChangePassword'            => array( '改變密碼', '重置密碼' ),
+       'ComparePages'              => array( '比較頁面' ),
+       'Confirmemail'              => array( '確認電子郵件' ),
+       'Contributions'             => array( '貢獻' ),
+       'CreateAccount'             => array( '開賬戶' ),
+       'DeletedContributions'      => array( '刪掉其貢獻' ),
+       'DoubleRedirects'           => array( '雙重重定向' ),
+       'EditWatchlist'             => array( '修改監視單' ),
+       'Emailuser'                 => array( '共用戶發送電子郵件' ),
+       'Export'                    => array( '導出' ),
+       'Fewestrevisions'           => array( '最少其修訂' ),
+       'FileDuplicateSearch'       => array( '文件重複尋討' ),
+       'Filepath'                  => array( '文件路徑' ),
+       'Import'                    => array( '導底' ),
+       'Invalidateemail'           => array( '無效電子郵件' ),
+       'JavaScriptTest'            => array( 'JavaScript測試' ),
+       'BlockList'                 => array( '封鎖單' ),
+       'LinkSearch'                => array( '鏈接尋討' ),
+       'Listadmins'                => array( '管理員單單' ),
+       'Listbots'                  => array( '機器人單單' ),
+       'Listfiles'                 => array( '文件單', '圖片單' ),
+       'Listgrouprights'           => array( '小組權限單', '用戶組單單' ),
+       'Listredirects'             => array( '重定向單單' ),
+       'Listusers'                 => array( '用戶單' ),
+       'Lockdb'                    => array( '鎖定數據庫' ),
+       'Log'                       => array( '日誌' ),
+       'Lonelypages'               => array( '單獨其頁面' ),
+       'Longpages'                 => array( '長長其頁面' ),
+       'MergeHistory'              => array( '合併其歷史' ),
+       'MIMEsearch'                => array( 'MIME尋討' ),
+       'Mostcategories'            => array( '最価其分類' ),
+       'Mostimages'                => array( '最価鏈接其文件' ),
+       'Mostinterwikis'            => array( '最稠其跨維基' ),
+       'Mostlinked'                => array( '最価鏈接其頁面' ),
+       'Mostlinkedcategories'      => array( '最価鏈接其分類' ),
+       'Mostlinkedtemplates'       => array( '最価鏈接其模板' ),
+       'Mostrevisions'             => array( '最稠其版本' ),
+       'Movepage'                  => array( '移動其頁面' ),
+       'Mycontributions'           => array( '我其貢獻' ),
+       'Mypage'                    => array( '我其頁面' ),
+       'Mytalk'                    => array( '我其討論' ),
+       'Myuploads'                 => array( '我其上傳' ),
+       'Newimages'                 => array( '新其文件', '新其圖片' ),
+       'Newpages'                  => array( '新其頁面' ),
+       'PasswordReset'             => array( '密碼重置' ),
+       'PermanentLink'             => array( '永久鏈接' ),
+       'Popularpages'              => array( '受歡迎其頁面' ),
+       'Preferences'               => array( '喜好' ),
+       'Prefixindex'               => array( '前綴索引' ),
+       'Protectedpages'            => array( '受保護其頁面' ),
+       'Protectedtitles'           => array( '受保護其標題' ),
+       'Randompage'                => array( '隨便其頁面' ),
+       'Randomredirect'            => array( '隨便其重定向' ),
+       'Recentchanges'             => array( '最近其改變' ),
+       'Recentchangeslinked'       => array( '最近改變其鏈接' ),
+       'Redirect'                  => array( '重定向' ),
+       'ResetTokens'               => array( '重置令牌' ),
+       'Search'                    => array( '尋討' ),
+       'Shortpages'                => array( '短短其頁面' ),
+       'Specialpages'              => array( '特殊頁' ),
+       'Statistics'                => array( '統計' ),
+       'Tags'                      => array( '標籤' ),
+       'Unblock'                   => array( '取消封鎖' ),
+       'Uncategorizedcategories'   => array( '未分類其分類' ),
+       'Uncategorizedimages'       => array( '未分類其文件', '未分類其圖片' ),
+       'Uncategorizedpages'        => array( '未分類其頁面' ),
+       'Uncategorizedtemplates'    => array( '未分類其模板' ),
+       'Undelete'                  => array( '伓使刪除' ),
+       'Unlockdb'                  => array( '解鎖數據庫' ),
+       'Unusedcategories'          => array( '無乇使其分類' ),
+       'Unusedimages'              => array( '無乇使其文件', '無乇使其圖片' ),
+       'Unusedtemplates'           => array( '無乇使其模板' ),
+       'Unwatchedpages'            => array( '未監視其頁面' ),
+       'Upload'                    => array( '上傳' ),
+       'Userlogin'                 => array( '用戶躒底', '躒底' ),
+       'Userlogout'                => array( '用戶躒出', '躒出' ),
+       'Userrights'                => array( '用戶權限' ),
+       'Version'                   => array( '版本' ),
+       'Wantedcategories'          => array( '卜挃其分類' ),
+       'Wantedfiles'               => array( '卜挃其文件' ),
+       'Wantedpages'               => array( '卜挃其頁面' ),
+       'Wantedtemplates'           => array( '卜挃其模板' ),
+       'Watchlist'                 => array( '監視單' ),
+       'Whatlinkshere'             => array( '什乇鏈遘嚽塊' ),
+       'Withoutinterwiki'          => array( '無跨維基' ),
+);
+
 $datePreferences = array(
        'default',
        'ISO 8601',
@@ -287,8 +407,6 @@ $1',
 'ok' => '好',
 'retrievedfrom' => '趁「$1」退過來',
 'youhavenewmessages' => '汝有$1($2)。',
-'newmessageslink' => '新信息',
-'newmessagesdifflink' => '最後其改變',
 'youhavenewmessagesfromusers' => '汝有趁$3用戶($2)來其$1萆信息{{PLURAL:$3}}',
 'youhavenewmessagesmanyusers' => '汝有趁雅価用戶($2)其$1信息',
 'newmessageslinkplural' => '$1條新其信息{{PLURAL:$1}}',
@@ -437,7 +555,7 @@ Sō̤ kī só-gé̤ṳ-kó gì guāng-lī-uòng cūng-kuāng gāi-sék: $1',
 'gotaccount' => "已經有賬戶了?'''$1'''。",
 'gotaccountlink' => '躒底',
 'userlogin-resetlink' => '躒底其資料𣍐記咯?',
-'userlogin-resetpassword-link' => '重置汝其密碼',
+'userlogin-resetpassword-link' => '密码𣍐記?',
 'helplogin-url' => 'Help: 躒底',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|幫助躒底]]',
 'createacct-join' => '敆下底輸底汝其信息。',
@@ -692,7 +810,6 @@ Sō̤ kī só-gé̤ṳ-kó gì guāng-lī-uòng cūng-kuāng gāi-sék: $1',
 'preferences' => '設定',
 'mypreferences' => '我其設定',
 'prefs-edits' => '修改數量:',
-'prefsnologin' => '未躒底其',
 'changepassword' => '改變密碼',
 'prefs-skin' => '皮膚',
 'datedefault' => '無設定',
@@ -1179,7 +1296,7 @@ If a new page with the same name has been created since the deletion, the restor
 'allmessagesdefault' => '默認其消息文字',
 'allmessagescurrent' => '現時其文字',
 'allmessagestext' => '茲是敆媒體維基命名空間底裏系統消息其蜀萆單單。
-如果汝卜想貢獻通用其媒體維基本地化服務,請訪問[//www.mediawiki.org/wiki/Localisation 媒體維基本地化]共[//translatewiki.net translatewiki.net]。',
+如果汝卜想貢獻通用其媒體維基本地化服務,請訪問[https://www.mediawiki.org/wiki/Localisation 媒體維基本地化]共[//translatewiki.net translatewiki.net]。',
 'allmessagesnotsupportedDB' => "茲蜀頁𣍐使其,因為'''\$wgUseDatabaseMessages'''已經乞禁止去了。",
 
 # Thumbnails
@@ -1257,7 +1374,7 @@ If a new page with the same name has been created since the deletion, the restor
 
 # External editor support
 'edit-externally' => '使外程序來編輯茲文件',
-'edit-externally-help' => '(參考[//www.mediawiki.org/wiki/Manual:External_editors setup instructions]來瞭解更価信息)',
+'edit-externally-help' => '(參考[https://www.mediawiki.org/wiki/Manual:External_editors setup instructions]來瞭解更価信息)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '所有',
index 4e02782..7b3a267 100644 (file)
@@ -75,54 +75,53 @@ $specialPageAliases = array(
        'Activeusers'               => array( 'Жигара_декъашхой' ),
        'Allmessages'               => array( 'ГӀирса_хаамаш' ),
        'Allpages'                  => array( 'Массо_агӀонаш' ),
-       'Ancientpages'              => array( 'Яззамаш_оцу_терахьца_тяххьара_тадар_дина_долу' ),
+       'Ancientpages'              => array( 'Яззамаш_оцу_терахьца_тӀаьххьара_тадар_дина_долу' ),
        'Badtitle'                  => array( 'Хилийта_йиш_йоцу_цӀе' ),
        'Blankpage'                 => array( 'Еса_агӀо' ),
        'Block'                     => array( 'Блоктоха' ),
-       'Blockme'                   => array( 'Блоктоха_суна' ),
-       'Booksources'               => array( 'Жайнашан_хьосташ' ),
+       'Booksources'               => array( 'Жайнийн_хьосташ' ),
        'BrokenRedirects'           => array( 'ДIахаьдна_долу_дIасахьажораш' ),
        'Categories'                => array( 'Категореш' ),
        'ChangeEmail'               => array( 'Хийца_e-mail' ),
-       'ChangePassword'            => array( 'ХийÑ\86а_иÑ\88аÑ\80' ),
+       'ChangePassword'            => array( 'ХийÑ\86а_паÑ\80олÑ\8c' ),
        'ComparePages'              => array( 'АгӀонаш_юстар' ),
        'Confirmemail'              => array( 'Бакъе_e-mail' ),
        'Contributions'             => array( 'Къинхьегам' ),
-       'CreateAccount'             => array( 'Кхолла_декъашхон_дӀаяздар' ),
+       'CreateAccount'             => array( 'Кхолла_декъашхочун_дӀаяздар' ),
        'Deadendpages'              => array( 'Дика_йоцу_агӀонаш' ),
-       'DeletedContributions'      => array( 'ДӀабяхкина_къинхьегам' ),
-       'Disambiguations'           => array( 'Цхьатера_маьӀна_дерш' ),
-       'DoubleRedirects'           => array( 'ШалгӀа_дӀасахьажийнарш' ),
+       'DeletedContributions'      => array( 'ДӀабаьккхина_къинхьегам' ),
+       'DoubleRedirects'           => array( 'Шалха_дӀасахьажийнарш' ),
        'EditWatchlist'             => array( 'Табе_тергаме_могӀам' ),
        'Emailuser'                 => array( 'Декъашхочунга_кехат' ),
+       'ExpandTemplates'           => array( 'Кепаш_схьаястар' ),
        'Export'                    => array( 'Экспорт' ),
-       'Fewestrevisions'           => array( 'Наггахь_беш_болу_хицамаш' ),
+       'Fewestrevisions'           => array( 'Наггахь_беш_болу_хийцамаш' ),
        'FileDuplicateSearch'       => array( 'Цхьатера_файлаш_лахар' ),
        'Filepath'                  => array( 'Файл_йолче' ),
        'Import'                    => array( 'Импорт' ),
        'Invalidateemail'           => array( 'Адрес_бакъдар_юхадаккха' ),
        'JavaScriptTest'            => array( 'JavaScript_тестировать_ян' ),
        'BlockList'                 => array( 'Блоктоьхнарш' ),
-       'LinkSearch'                => array( 'Ð¥Ñ\8cажоÑ\80игаш_лахар' ),
-       'Listadmins'                => array( 'Куьгалхойн_могӀам' ),
+       'LinkSearch'                => array( 'Ð¥Ñ\8cажоÑ\80агаш_лахар' ),
+       'Listadmins'                => array( 'Ð\9aÑ\83Ñ\8cйгалÑ\85ойн_могÓ\80ам' ),
        'Listbots'                  => array( 'Шаболх_бечара_могӀам' ),
-       'Listfiles'                 => array( 'Файланши_могӀам' ),
-       'Listgrouprights'           => array( 'Декъашхошан_бакъонаш' ),
+       'Listfiles'                 => array( 'Файлаш' ),
+       'Listgrouprights'           => array( 'Декъашхойн_бакъонаш' ),
        'Listredirects'             => array( 'ДIасахьажоран_могIам' ),
        'Listusers'                 => array( 'Декъашхойн_могӀам' ),
        'Lockdb'                    => array( 'Хааман_базан_блоктохар' ),
        'Log'                       => array( 'Тептарш' ),
-       'Lonelypages'               => array( 'Байлахь_йисина_агIонаш' ),
+       'Lonelypages'               => array( 'Байлахь_йисина_агӀонаш' ),
        'Longpages'                 => array( 'Беха_яззамаш' ),
-       'MergeHistory'              => array( 'ЦÑ\85Ñ\8cаÑ\8cнаÑ\82оÑ\8cÑ\85на_каÑ\82егоÑ\80еÑ\88' ),
+       'MergeHistory'              => array( 'Ð\98Ñ\81Ñ\82оÑ\80и_Ñ\86Ñ\85Ñ\8cаÑ\8cнаÑ\82оÑ\85аÑ\80' ),
        'MIMEsearch'                => array( 'MIME_чухула_лахар' ),
        'Mostcategories'            => array( 'Дуккха_категореш_тӀе_тоьхна_йолу_агӀонаш' ),
        'Mostimages'                => array( 'Массарел_дуккха_лелайо_файлаш' ),
-       'Mostinterwikis'            => array( 'Ð\94Ñ\83кÑ\85а_Ñ\8eкÑ\8aаÑ\80вики_Ñ\85Ñ\8cажоÑ\80игаш' ),
-       'Mostlinked'                => array( 'Ð\94Ñ\83ккÑ\85а_Ñ\85Ñ\8cажоÑ\80игаÑ\88\82Iе_Ñ\82оÑ\8cÑ\85на_йолÑ\83_агIонаш' ),
+       'Mostinterwikis'            => array( 'Ð\94Ñ\83кÑ\85а_Ñ\8eкÑ\8aаÑ\80вики_Ñ\85Ñ\8cажоÑ\80агаш' ),
+       'Mostlinked'                => array( 'Ð\94Ñ\83ккÑ\85а_Ñ\85Ñ\8cажоÑ\80агаÑ\88\82Ó\80е_Ñ\82оÑ\8cÑ\85на_йолÑ\83_агÓ\80онаш' ),
        'Mostlinkedcategories'      => array( 'Дуккха_тӀе_хьажораш_йолу_категореш' ),
        'Mostlinkedtemplates'       => array( 'Массарел_дуккха_а_леладо_кепаш' ),
-       'Mostrevisions'             => array( 'Сих_сиха_нисйина_йолу_агIонаш' ),
+       'Mostrevisions'             => array( 'Сих_сиха_нисйина_йолу_агӀонаш' ),
        'Movepage'                  => array( 'АгӀона_цӀе_хийцар' ),
        'Mycontributions'           => array( 'Сан_къинхьегам' ),
        'Mypage'                    => array( 'Сан_агӀо' ),
@@ -130,26 +129,27 @@ $specialPageAliases = array(
        'Myuploads'                 => array( 'Сан_файлаш' ),
        'Newimages'                 => array( 'Керла_файлаш' ),
        'Newpages'                  => array( 'Керла_агӀонаш' ),
-       'PermanentLink'             => array( 'Гуттарлера_хьажориг' ),
-       'Popularpages'              => array( 'ГӀарялла_агӀонаш' ),
+       'PasswordReset'             => array( 'Пароль_кхоссар' ),
+       'PermanentLink'             => array( 'Гуттарлера_хьажораг' ),
+       'Popularpages'              => array( 'ГӀараяьлла_агӀонаш' ),
        'Preferences'               => array( 'ГӀирсаш' ),
-       'Prefixindex'               => array( 'Хьалха_агIонашан_цIераш_хIотто_йеза' ),
-       'Protectedpages'            => array( 'ГIаролла_дина_агIонаш' ),
-       'Protectedtitles'           => array( 'ГIаролла_дина_цIераш' ),
+       'Prefixindex'               => array( 'Хьалха_агӀонийн_цӀераш_хӀотто_еза' ),
+       'Protectedpages'            => array( 'ГӀаролла_дина_агӀонаш' ),
+       'Protectedtitles'           => array( 'ГӀаролла_дина_цӀераш' ),
        'Randompage'                => array( 'Цахууш_нисйелла_агIо' ),
        'Randomredirect'            => array( 'Цахууш_нисделла_дIасахьажор' ),
        'Recentchanges'             => array( 'Керла_нисдарш' ),
        'Recentchangeslinked'       => array( 'Кхуьнца_долу_нисдарш' ),
        'Revisiondelete'            => array( 'ДӀадяхна_нисдарш' ),
        'Search'                    => array( 'Лахар' ),
-       'Shortpages'                => array( 'Ð\91оÑ\86оа_Ñ\8fззамаÑ\88' ),
+       'Shortpages'                => array( 'Боца_яззамаш' ),
        'Specialpages'              => array( 'Леррина_агӀонаш' ),
        'Statistics'                => array( 'Бухехьдерг' ),
        'Tags'                      => array( 'Билгалонаш' ),
-       'Unblock'                   => array( 'БлокдӀаякхар' ),
+       'Unblock'                   => array( 'БлокдӀаяккхар' ),
        'Uncategorizedcategories'   => array( 'Категореш_йоцу_категореш' ),
        'Uncategorizedimages'       => array( 'Категореш_йоцу_файлаш' ),
-       'Uncategorizedpages'        => array( 'Категореш_йоцу_агIонаш' ),
+       'Uncategorizedpages'        => array( 'Категореш_йоцу_агӀонаш' ),
        'Uncategorizedtemplates'    => array( 'Категореш_йоцу_кепаш' ),
        'Undelete'                  => array( 'МеттахӀоттор' ),
        'Unlockdb'                  => array( 'БлокдӀаякхар_ХБ' ),
@@ -158,17 +158,17 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'Лелош_доцу_кепаш' ),
        'Upload'                    => array( 'Файл_чуяккхар' ),
        'UploadStash'               => array( 'ДӀахьулйина_файл_чуяккхар' ),
-       'Userlogin'                 => array( 'ЧÑ\83валаÑ\80\8fлар' ),
-       'Userlogout'                => array( 'Ð\90Ñ\80авалаÑ\80\8fлар' ),
+       'Userlogin'                 => array( 'ЧÑ\83далар' ),
+       'Userlogout'                => array( 'Ð\90Ñ\80адалар' ),
        'Userrights'                => array( 'Бакъона_урхалладар' ),
        'Version'                   => array( 'Верси' ),
        'Wantedcategories'          => array( 'Оьшуш_йолу_категореш' ),
        'Wantedfiles'               => array( 'Оьшуш_йолу_файлаш' ),
-       'Wantedpages'               => array( 'Оьшуш_йолу_агIонаш' ),
+       'Wantedpages'               => array( 'Оьшуш_йолу_агӀонаш' ),
        'Wantedtemplates'           => array( 'Оьшуш_йолу_кепаш' ),
        'Watchlist'                 => array( 'Тергаме_могӀам' ),
        'Whatlinkshere'             => array( 'Хьажоригаш_кхузе' ),
-       'Withoutinterwiki'          => array( 'Ð\9aÑ\85еÑ\87Ñ\83_меÑ\82Ñ\82анаÑ\88ан_Ñ\85Ñ\8cажоÑ\80иг_йоÑ\86Ñ\83_агIонаш' ),
+       'Withoutinterwiki'          => array( 'ЮкÑ\8aаÑ\80вики_Ñ\85Ñ\8cажоÑ\80агаÑ\88_йоÑ\86Ñ\83_агÓ\80онаш' ),
 );
 
 $magicWords = array(
@@ -202,7 +202,7 @@ $magicWords = array(
        'localhour'                 => array( '1', 'МЕТТИГАН_САХЬТ', 'МЕСТНЫЙ_ЧАС', 'LOCALHOUR' ),
        'numberofpages'             => array( '1', 'АГlОНИЙ_ДУКХАЛЛА', 'КОЛИЧЕСТВО_СТРАНИЦ', 'NUMBEROFPAGES' ),
        'numberofarticles'          => array( '1', 'ЯЗЗАМАШИ_ДУКХАЛЛА', 'КОЛИЧЕСТВО_СТАТЕЙ', 'NUMBEROFARTICLES' ),
-       'numberoffiles'             => array( '1', 'Ð¥lУÐ\9cÐ\9dÐ\98Ð\99_ДУКХАЛЛА', 'КОЛИЧЕСТВО_ФАЙЛОВ', 'NUMBEROFFILES' ),
+       'numberoffiles'             => array( '1', 'ФÐ\90Ð\99Ð\9bÐ\90Ð\9dШÐ\98_ДУКХАЛЛА', 'КОЛИЧЕСТВО_ФАЙЛОВ', 'NUMBEROFFILES' ),
        'numberofusers'             => array( '1', 'ДЕКЪАШХОЙ_ДУКХАЛЛА', 'КОЛИЧЕСТВО_УЧАСТНИКОВ', 'NUMBEROFUSERS' ),
        'numberofactiveusers'       => array( '1', 'ДУКХАЛЛА_ЖИГАРА_ДЕКЪАШХОЙ', 'КОЛИЧЕСТВО_АКТИВНЫХ_УЧАСТНИКОВ', 'NUMBEROFACTIVEUSERS' ),
        'numberofedits'             => array( '1', 'НИСДАРШИЙ_ДУКХАЛЛА', 'КОЛИЧЕСТВО_ПРАВОК', 'NUMBEROFEDITS' ),
@@ -233,12 +233,12 @@ $magicWords = array(
        'img_right'                 => array( '1', 'бакъхьа', 'справа', 'right' ),
        'img_left'                  => array( '1', 'харцхьа', 'слева', 'left' ),
        'img_none'                  => array( '1', 'йоцуш', 'без', 'none' ),
-       'img_width'                 => array( '1', '$1цинт', '$1пкс', '$1px' ),
+       'img_width'                 => array( '1', '$1пкс', '$1px' ),
        'img_center'                => array( '1', 'юккъ', 'центр', 'center', 'centre' ),
        'img_framed'                => array( '1', 'гурабе', 'обрамить', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'гурабоцаш', 'безрамки', 'frameless' ),
-       'img_page'                  => array( '1', 'агlо=$1', 'агlо_$1', 'page_$1', 'страница=$1', 'страница $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'бакъхьалакхо', 'бакъхьалакхо=$1', 'бакъхьалакхо_$1', 'upright_$1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'агlо=$1', 'агlо_$1', 'page_$1', 'страница=$1', 'страница_$1', 'страница $1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'бакъхьалакхо', 'бакъхьалакхо=$1', 'бакъхьалакхо_$1', 'upright_$1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа_$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'доза', 'граница', 'border' ),
        'img_baseline'              => array( '1', 'бух', 'основание', 'baseline' ),
        'img_sub'                   => array( '1', 'буха', 'под', 'sub' ),
@@ -285,8 +285,8 @@ $magicWords = array(
        'raw'                       => array( '0', 'ТАЙАНЗА:', 'НЕОБРАБ:', 'RAW:' ),
        'displaytitle'              => array( '1', 'ГАЙТА_КОЬРТАМОГl', 'ПОКАЗАТЬ_ЗАГОЛОВОК', 'DISPLAYTITLE' ),
        'rawsuffix'                 => array( '1', 'Т', 'Н', 'R' ),
-       'newsectionlink'            => array( '1', '__ХЬÐ\90Ð\96Ð\9eРÐ\98Г_ОЦ_КЕРЛАЧУ_ДЕКЪАН__', '__ССЫЛКА_НА_НОВЫЙ_РАЗДЕЛ__', '__NEWSECTIONLINK__' ),
-       'nonewsectionlink'          => array( '1', '__Ð\99Ð\9eЦÐ\90Ш_ХЬÐ\90Ð\96Ð\9eРÐ\98Г_ОЦ_КЕРЛАЧУ_ДЕКЪАН__', '__БЕЗ_ССЫЛКИ_НА_НОВЫЙ_РАЗДЕЛ__', '__NONEWSECTIONLINK__' ),
+       'newsectionlink'            => array( '1', '__ХЬÐ\90Ð\96Ð\9eРÐ\90Г_ОЦ_КЕРЛАЧУ_ДЕКЪАН__', '__ССЫЛКА_НА_НОВЫЙ_РАЗДЕЛ__', '__NEWSECTIONLINK__' ),
+       'nonewsectionlink'          => array( '1', '__Ð\99Ð\9eЦÐ\90Ш_ХЬÐ\90Ð\96Ð\9eРÐ\90Г_ОЦ_КЕРЛАЧУ_ДЕКЪАН__', '__БЕЗ_ССЫЛКИ_НА_НОВЫЙ_РАЗДЕЛ__', '__NONEWSECTIONLINK__' ),
        'currentversion'            => array( '1', 'ЙОЛШЙОЛУ_БАШХО', 'ТЕКУЩАЯ_ВЕРСИЯ', 'CURRENTVERSION' ),
        'urlencode'                 => array( '0', 'ИШАРЙИНА_МЕТТИГ:', 'ЗАКОДИРОВАННЫЙ_АДРЕС:', 'URLENCODE:' ),
        'anchorencode'              => array( '0', 'ИШАРЙАР_МЕТТИГАН', 'КОДИРОВАТЬ_МЕТКУ', 'ANCHORENCODE' ),
@@ -296,7 +296,7 @@ $magicWords = array(
        'language'                  => array( '0', '#МОТТ', '#ЯЗЫК:', '#LANGUAGE:' ),
        'contentlanguage'           => array( '1', 'МОТТ_ЧУЛАЦАМ', 'ЯЗЫК_СОДЕРЖАНИЯ', 'CONTENTLANGUAGE', 'CONTENTLANG' ),
        'pagesinnamespace'          => array( '1', 'АГlОНАШ_ОЦ_ЦlЕРАШКАХЬ:', 'СТРАНИЦ_В_ПРОСТРАНСТВЕ_ИМЁН:', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
-       'numberofadmins'            => array( '1', 'Ð\90Ð\94Ð\9cÐ\90Ð\9dÐ\9aУЬÐ\93Ð\90Ð\9bÐ¥Ð\9eÐ\99\94УÐ\9aÐ¥Ð\90Ð\9bÐ\9bÐ\90', 'Ð\9aÐ\9eÐ\9bÐ\98ЧÐ\95СТÐ\92Ð\9e\90Ð\94Ð\9cÐ\98Ð\9dÐ\98СТРÐ\90ТÐ\9eРÐ\9eÐ\92', 'NUMBEROFADMINS' ),
+       'numberofadmins'            => array( '1', 'КУЬГАЛХОЙ_ДУКХАЛЛА', 'КОЛИЧЕСТВО_АДМИНИСТРАТОРОВ', 'NUMBEROFADMINS' ),
        'formatnum'                 => array( '0', 'ТЕРАХЬАН_БАРАМХlОТТОР', 'ФОРМАТИРОВАТЬ_ЧИСЛО', 'FORMATNUM' ),
        'padleft'                   => array( '0', 'ЙУЗА_ХАРЦЕ', 'ЗАПОЛНИТЬ_СЛЕВА', 'PADLEFT' ),
        'padright'                  => array( '0', 'ЙУЗА_БАКЪЕ', 'ЗАПОЛНИТЬ_СПРАВА', 'PADRIGHT' ),
@@ -325,17 +325,17 @@ $messages = array(
 'tog-hidepatrolled' => 'Къайладаха гlаролладина нисдарш оц могlама керла нисдашкахь',
 'tog-newpageshidepatrolled' => 'Къайлайаха гlароллайина агlонаш оц могlама керла агlонашкахь',
 'tog-extendwatchlist' => 'Шорбина тlехьажарна могlам, ша беригге а хийцамаш чубогlуш, тlяхьабина боцурш а',
-'tog-usenewrc' => 'Лелабе дика могlам керла чу хийцамашна (оьшу JavaScript)',
+'tog-usenewrc' => 'Лелабе дика могӀам керла чу хийцамашна (оьшу JavaScript)',
 'tog-numberheadings' => 'Ша шех хlитто терахь корташна',
-'tog-showtoolbar' => 'Гайта лакхара гlирсан дакъа нисйеш аттон оц тадар чохь (JavaScript)',
-'tog-editondblclick' => 'Нисйе агlонаш шозза тlетаlийча (JavaScript)',
-'tog-editsection' => 'Ð\93айÑ\82а Ñ\85Ñ\8cажоÑ\80иг Â«Ð½Ð¸Ñ\81йе» Ð°Ñ\8cлла Ñ\85lоÑ\80а Ð°Ð³lона',
-'tog-editsectiononrightclick' => 'Нисде дакъа шозза бакъехьар дахка тlетаlийча оцу кортан (JavaScript)',
+'tog-showtoolbar' => 'Гайта лакхара гӀирсан дакъа нисйеш аттон оц тадар чохь (JavaScript)',
+'tog-editondblclick' => 'Нисйе агӀонаш шозза тӀетаӀийча (JavaScript)',
+'tog-editsection' => 'Ð\93айÑ\82а Ñ\85Ñ\8cажоÑ\80аг Â«Ð½Ð¸Ñ\81йе» Ð°Ñ\8cлла Ñ\85Ó\80оÑ\80а Ð°Ð³Ó\80она',
+'tog-editsectiononrightclick' => 'Нисде дакъа шозза бакъехьар дахка тӀетаӀийча оцу кортан (JavaScript)',
 'tog-showtoc' => 'Гойти коьртнаш (оцу агlонашна лаххара 3 коьртнашца)',
 'tog-rememberpassword' => 'Даглаца сан дӀаяздар хӀокху браузеран тӀяхь (цхьан $1 {{PLURAL:$1|де|ден|динахь}})',
-'tog-watchcreations' => 'Тlетоха ас кхоллина агlонаш тергаме могlам чу',
-'tog-watchdefault' => 'Тlетоха ас нисйина агlонаш тергаме могlам чу',
-'tog-watchmoves' => 'Тlетоха ас цlераш хийцина агlонаш тергаме могlам чу',
+'tog-watchcreations' => 'ТӀетоха ас кхоьллина агӀонаш тергаме могӀам чу',
+'tog-watchdefault' => 'ТӀетоха ас нисйина агӀонаш тергаме могӀам чу',
+'tog-watchmoves' => 'ТӀетоха ас цӀераш хийцина агӀонаш тергаме могӀам чу',
 'tog-watchdeletion' => 'Тlетоха ас дӀаяхина агlонаш тергаме могlам чу',
 'tog-minordefault' => 'Къастам бе нисйиначарн хlумцадеш кегийра долушсанна',
 'tog-previewontop' => 'Чуяккха хьалххьажар рéдоккхучу кора хьалха',
@@ -343,11 +343,11 @@ $messages = array(
 'tog-nocache' => 'Ма латае гойтучун къайлаха латториг',
 'tog-enotifwatchlistpages' => 'Хаам бо зlе чухул, тергаме могlаман хийцамах лаьцна',
 'tog-enotifusertalkpages' => 'Хаам бо зlе чухул, долахь йолу дийцаре агlон хийцамах лаьцна',
-'tog-enotifminoredits' => 'Хаам бо зlе чухул, цхьа жимма а хийцамаш биняхь',
+'tog-enotifminoredits' => 'Хаам бо зӀе чухул, цхьа жимма а хийцамаш биняхь',
 'tog-enotifrevealaddr' => 'Гайта сан зlе оцу хаамаш барехь',
 'tog-shownumberswatching' => 'Гайта декъашхойн терахь, агlо латийна болу шай тергаме могlам юкъа',
-'tog-oldsig' => 'Ð¥Ñ\8cалÑ\85Ñ\85Ñ\8cажаÑ\80 Ð´Ð¾Ð»Ñ\83Ñ\87Ñ\83 ÐºÑ\83Ñ\8cгÑ\82аlорна:',
-'tog-fancysig' => 'Шен вики-къастаман куьгтаlдар (ша шех хьажориг йоцуш)',
+'tog-oldsig' => 'Ð\9aаÑ\80аÑ\80а ÐºÑ\83Ñ\8cгÑ\82аÓ\80орна:',
+'tog-fancysig' => 'Шен вики-къастаман куьгтаӀдар (ша шех хьажораг йоцуш)',
 'tog-uselivepreview' => 'Лелайа чехка хьалха хьажа (JavaScript, муха ю хьажарна)',
 'tog-forceeditsummary' => 'Дага даийта, нагахь нисйарх лаьцна чохь язйина яцахь',
 'tog-watchlisthideown' => 'Къайлаяха ас нисйинарш оцу тергаме могlам чура',
@@ -359,9 +359,10 @@ $messages = array(
 'tog-ccmeonemails' => 'Дlадахьийта суна исанна кехат, аса дохьуьйтуш долу кхечу декъашхошна.',
 'tog-diffonly' => 'Ма гайта агlон чулацам шина башхонца цхьатерра йолуш',
 'tog-showhiddencats' => 'Гайта къайлаха йолу категореш',
-'tog-noconvertlink' => 'Хааман Ñ\85Ñ\8cажоÑ\80иг ÐºÑ\85Ñ\83ллÑ\83 Ð³lиÑ\80Ñ\81 Ð´lабайа',
+'tog-noconvertlink' => 'Хааман Ñ\85Ñ\8cажоÑ\80аг ÐºÑ\85Ñ\83ллÑ\83 Ð³Ó\80иÑ\80Ñ\81 Ð´Ó\80абайа',
 'tog-norollbackdiff' => 'Юха яккхиначул тӀаьхьа ма гайта версешан башхо',
 'tog-useeditwarning' => 'Хаамбе бина хийцамаш дӀаязцабеш аса болх дӀатосучу хенахь',
+'tog-prefershttps' => 'Даима лела йе лардина системин чудалар',
 
 'underline-always' => 'Даимна',
 'underline-never' => 'Цкъа а',
@@ -458,8 +459,6 @@ $messages = array(
 'broken-file-category' => '{{#switch:{{NAMESPACE}}
  |{{ns:0}}=Болх цабеш файлийн хьажорагаш йолу агӀонаш}}',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Цуьнах лаьцна',
 'article' => 'Яззам',
 'newwindow' => '(керлачу корехь)',
@@ -512,7 +511,7 @@ $messages = array(
 'history_short' => 'Истори',
 'updatedmarker' => 'Керла яккхина сона гинчултӀаьхьа',
 'printableversion' => 'Зорба туху верси',
-'permalink' => 'Ð\94аиман Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80иг',
+'permalink' => 'Ð\94аиман Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг',
 'print' => 'Зорба тоха',
 'view' => 'Хьажа',
 'edit' => 'Нисйé',
@@ -551,7 +550,7 @@ $messages = array(
 'redirectedfrom' => '(ДӀасахьажийна кху $1)',
 'redirectpagesub' => 'АгӀо-дӀасахьажайар',
 'lastmodifiedat' => 'ХӀокху агӀон тӀаьххьаралера хийцам: $2, $1.',
-'viewcount' => 'ХӀокху агӀонга хьойсина $1 {{PLURAL:$1|за|за|за}}.',
+'viewcount' => 'ХӀокху агӀонга хьойсина $1 {{PLURAL:$1|за}}.',
 'protectedpage' => 'ГӀароллийца йолу агӀо',
 'jumpto' => 'Дехьа гӀо:',
 'jumptonavigation' => 'Навигаци',
@@ -596,8 +595,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Хьост — «$1»',
 'youhavenewmessages' => 'Хьуна кхечи $1 ($2).',
-'newmessageslink' => 'керла хаамаш',
-'newmessagesdifflink' => 'тӀаьххьара хийцамаш',
 'youhavenewmessagesfromusers' => 'Хьуна кхачанна $1 {{PLURAL:$3|$3 декъашхочунгара|$3 декъашхошкара|$3 декъашхошкара}} ($2).',
 'youhavenewmessagesmanyusers' => 'Хьона еъна $1 дукху декъашхошкар ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|керла хаам}}',
@@ -616,7 +613,7 @@ $1',
 'collapsible-expand' => 'хьайаста',
 'thisisdeleted' => 'Хьажа йа меттахlоттайé $1?',
 'viewdeleted' => 'Хьалххьожи $1?',
-'restorelink' => '{{PLURAL:$1|$1 дӀадяккхина нийсдар|$1 дӀадяхна нийсдарш|$1 дӀадяхна нийсдарш}}',
+'restorelink' => '{{PLURAL:$1|$1 дӀадаьккхина нийсдар|$1 дӀадяхна нийсдарш}}',
 'feedlinks' => 'Оцу хатlаьхь:',
 'feed-invalid' => 'Тайпан нийсадоцу талол оцу куьгтаlорна.',
 'feed-unavailable' => 'Хаитарца йолу асанаш тlекхочучехь яц',
@@ -652,6 +649,9 @@ $1',
 # General errors
 'error' => 'Гlалат',
 'databaseerror' => 'Гlалат хаамийн бухера',
+'databaseerror-query' => 'Дехар: $1',
+'databaseerror-function' => 'Функци: $1',
+'databaseerror-error' => 'ГӀалат: $1',
 'laggedslavemode' => 'Тергам бе: агӀона чохь керла йаьхинарш ца хила мега.',
 'readonly' => 'Блоктоьхна дӀайаздар хаамийн бухе',
 'enterlockreason' => 'Билгал де блоктохаран бахьна а и чекх йолу хан а.',
@@ -703,6 +703,8 @@ $1',
 'customjsprotected' => 'Хьан бакъо яц хӀара JavaScript-агӀо тая, иза кхечу декъашхочун гӀерс болу дера.',
 'mycustomcssprotected' => 'Хьан бакъо яц хӀара CSS агӀо тая.',
 'mycustomjsprotected' => 'Хьан бакъо яц JavaScript агӀо тая.',
+'myprivateinfoprotected' => 'Хьайн долара хаамна хийцам ба хьа йиш яц',
+'mypreferencesprotected' => 'Хьай гӀирс нисбан хьа бакъо яц.',
 'exception-nologin' => 'Ахьа хӀой вовзийтина/йовзийтина вац/яц',
 
 # Virus scanner
@@ -710,13 +712,14 @@ $1',
 'virus-unknownscanner' => 'йозуш йоцу антивирус:',
 
 # Login and logout pages
-'logouttext' => "'''Ð¥Ñ\8cо Ð°Ñ\80авела/ела.'''
-Хьан йиш ю {{grammar:genitive|{{SITENAME}}}} чохь хьой ца вовзийташ/йовзийташ болх бан я <span class='plainlinks'>[$1 кхин чувала/яла ]</span> хьой чохь хила цӀарца я кхин цӀарца.
-Цхьа йолу агӀонаш чохь хьо хьай цӀарца болх беш сана хила тарло ишта ца хилийта керлаякха браузеран кэш.",
+'logouttext' => "'''Ð\90Ñ\85Ñ\8cа Ð±Ð¾Ð»Ñ\85 Ð´Ó\80абеÑ\80зийна.'''
+
+Цхьайолу агӀонаш чохь хьо хьай цӀарца болх беш сана хила тарло ишта ца хилийта керлаякха браузеран кэш.",
 'welcomeuser' => 'Марша ДогӀийла, $1!',
 'yourname' => 'Декъашхочун цӀе:',
 'userlogin-yourname' => 'Декъашхочун цӀе',
 'userlogin-yourname-ph' => 'Язъе декъашхочун цӀе',
+'createacct-another-username-ph' => 'Язъе декъашхочун цӀе',
 'yourpassword' => 'Пароль:',
 'userlogin-yourpassword' => 'Пароль',
 'userlogin-yourpassword-ph' => 'Язъе хьай пароль',
@@ -748,18 +751,24 @@ $1',
 'userlogin-resetpassword-link' => 'Пароль кхоссар',
 'helplogin-url' => 'Help:Системин довзийтар',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Системин чудаха гӀодар]]',
+'userlogin-loggedin' => 'Хьо {{GENDER:$1|$1}} цӀарца чохь ву/ю.
+Лахара форманца кхин цӀарца чугӀо.',
+'userlogin-createanother' => 'Кхолла декъашхочун кхин дӀаяздар',
 'createacct-join' => 'ДӀаязбе лахахь хай хаам.',
+'createacct-another-join' => 'Язбе лахахь керлачу декъашхочун дӀаяздаран хаам.',
 'createacct-emailrequired' => 'Электронни почтан адрес',
 'createacct-emailoptional' => 'Электронни почтан адрес (ца яздича мега)',
 'createacct-email-ph' => 'ДӀаязде электронни почтан адрес',
+'createacct-another-email-ph' => 'ДӀаязде электронни почтан адрес',
 'createaccountmail' => 'хааман зӀене хула',
 'createacct-realname' => 'Хьан цӀе (ца язйича мега)',
 'createaccountreason' => 'Бахьан:',
 'createacct-reason' => 'Бахьна',
-'createacct-reason-ph' => '{{PLURAL:$1|агӀо|агӀонаш}}‎',
+'createacct-reason-ph' => 'Стен кхуллуш ду ахьа керла декъашхочун дӀаяздар',
 'createacct-captcha' => 'Кхерамзалла хьажар',
 'createacct-imgcaptcha-ph' => 'ДӀаязде хьайна лакхахь гуш долу йоза',
 'createacct-submit' => 'Кхолла декъашхочун дӀаяздар',
+'createacct-another-submit' => 'Кхолла декъашхочун кхин дӀаяздар',
 'createacct-benefit-heading' => '{{SITENAME}} кхолийна хьо санначу наха.',
 'createacct-benefit-body1' => '{{PLURAL:$1|нисдар|нисдарш}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|яззам|яззамаш}}',
@@ -788,6 +797,8 @@ $1',
 'noemailcreate' => 'Ахьа нийса электронни почтан адрес дӀаяздан деза',
 'passwordsent' => 'Керла пароль декъашхочун $1 электронни адрес тӀе дӀахьажина. Дехар до, керла пароль еъча юху системин чугӀо.',
 'blocked-mailpassword' => 'Хьан IP-адрес ца тадарш дан магийна дац, цуьндела пароль меттахӀотош йолу функци блоктоьхна ю.',
+'throttled-mailpassword' => 'Пароль дага йоуьйту функци {{PLURAL:$1|тӀехьара $1 сахьтехь}} лелина.
+Зулам цахилийта $1 {{PLURAL:$1|сахьтан чохь}} цӀа бен функци лело йиш яц.',
 'mailerror' => 'Кехат дохьуьйтуш гӀалат ду: $1',
 'emailauthenticated' => 'Хьан почтан адрес бакъдина $2 $3.',
 'accountcreated' => 'Декъашхочун дӀаяздар кхоьллина',
@@ -845,8 +856,8 @@ $1',
 'italic_sample' => 'Сеттан до йоза',
 'italic_tip' => 'Сеттан до йоза',
 'link_sample' => 'Хьажориган коьрта могlа',
-'link_tip' => 'ЧоÑ\8cÑ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80иг',
-'extlink_sample' => 'http://www.example.com Ñ\85Ñ\8cажоÑ\80иг корта',
+'link_tip' => 'ЧоÑ\8cÑ\85Ñ\8cа Ñ\85Ñ\8cажоÑ\80аг',
+'extlink_sample' => 'http://www.example.com Ñ\85Ñ\8cажоÑ\80аг корта',
 'extlink_tip' => 'Арахьара хьажораг (йиц ма йе хӀотталушерг http://)',
 'headline_sample' => 'Йозан корта',
 'headline_tip' => 'Корта 2-гlа локхаллийца',
@@ -855,7 +866,7 @@ $1',
 'image_sample' => 'Example.jpg',
 'image_tip' => 'Чохь йолу файл',
 'media_sample' => 'Example.ogg',
-'media_tip' => 'Ð¥Ñ\8cажоÑ\80иг медиа-файлан тӀе',
+'media_tip' => 'Ð¥Ñ\8cажоÑ\80аг медиа-файлан тӀе',
 'sig_tip' => 'Хьан куьгтаlор аъ хlоттина хан',
 'hr_tip' => 'Ана сиз (сих сиха ма леладайша)',
 
@@ -945,7 +956,7 @@ $1',
 'template-semiprotected' => '(дуьззина доцуш гlаролла)',
 'hiddencategories' => 'ХӀара агӀо чуйогӀуш ю оцу $1 {{PLURAL:$1|къайлаха категори чу|къайлаха категореш чу}}:',
 'edittools' => '<!-- Кхузе буха диллина йоза гуш хир ду редоккхуче бухахь а хlума чуйоккхуче бухахь. -->',
-'permissionserrors' => 'ТӀекхачарехь гӀалат',
+'permissionserrors' => 'ТӀекхачаре бакъона гӀалат',
 'permissionserrorstext' => 'Хьан бакъо яц кхочуш хилийта хийцам оцу {{PLURAL:$1|шолгlа бахьанца|шолгlа бахьанашца}}:',
 'permissionserrorstext-withaction' => "Хьан бакъо яц хlумда «'''$2'''» оцу {{PLURAL:$1|шолгlа бахьанца|шолгlа бахьанашца}}:",
 'recreate-moveddeleted-warn' => "'''Тидам бе. Ахьа кхуллуш ю, хьалхо дӀаяккхина йолу агӀо.'''
@@ -970,6 +981,7 @@ $1',
 
 # "Undo" feature
 'undo-success' => 'Нисйинарг а тlе цалаца мега. Дехар до, хьажа цхьатерра йуй башхо, тешна хила, баккъалла иза хийцам буйте хьуна безарг, тlакха тlе таlайе «дlайазйе агlо», хийцам хlотта ба.',
+'undo-failure' => 'Юккъера хийцамаш бахьнехь нисдар юхадаккха йиш яц.',
 'undo-summary' => 'Юхадаьккхина {{GENDER:$2|декъашхочун}} [[Special:Contributions/$2|$2]] ([[User talk:$2|дийц.]]) нисдар $1',
 'undo-summary-username-hidden' => 'Юхадаьккхина декъашхочун нисдарш $1, цунна цӀе дӀахьулйина',
 
@@ -1051,6 +1063,7 @@ $1',
 'compareselectedversions' => 'Хаьржина версеш муха ю хьажа',
 'showhideselectedversions' => 'Гайта/къайлайаха хаьржина башхонаш',
 'editundo' => 'цаоьшу',
+'diff-empty' => '(башхалла яц)',
 'diff-multi' => '({{PLURAL:$1|гайтина яц $1 юккъера верси|гайтина яц $1 юккъера версеш}} {{PLURAL:$2|$2 декъашхочун|$2 декъашхой}})',
 
 # Search results
@@ -1116,7 +1129,7 @@ $1',
 'prefs-skin' => 'Кечяран тема',
 'skin-preview' => 'Хьалха муха ю хьажа',
 'datedefault' => 'Iад йитарца',
-'prefs-beta' => 'Ð\93lоле таронаш',
+'prefs-beta' => 'Ð\91еÑ\82а-таронаш',
 'prefs-datetime' => 'Терахь а хан а',
 'prefs-labs' => 'Муха ю хьажарна таронаш',
 'prefs-user-pages' => 'Декъашхочун агӀо',
@@ -1141,11 +1154,13 @@ $1',
 'columns' => 'БӀогӀамаш:',
 'searchresultshead' => 'Лаха',
 'resultsperpage' => 'Карийначу дӀаяздаршан дукхалла:',
-'stub-threshold' => 'Ð\9aеÑ\87 Ñ\8fÑ\80ан Ð´Ð¾Ð·Ð° <a href="#" class="stub">коÑ\8cÑ\80Ñ\82амогÓ\80амна Ñ\85Ñ\8cажоÑ\80игаш</a> (байташках):',
+'stub-threshold' => 'Ð\9aеÑ\87 Ñ\8fÑ\80ан Ð´Ð¾Ð·Ð° <a href="#" class="stub">коÑ\8cÑ\80Ñ\82амогÓ\80амна Ñ\85Ñ\8cажоÑ\80агаш</a> (байташках):',
 'recentchangesdays' => 'Керла нисдар гайта динахь:',
 'recentchangesdays-max' => 'Къезиг  $1 {{PLURAL:$1|дена}}',
 'recentchangescount' => 'Iад йитарца гойтуш долу нисдаршан дукхалла',
 'prefs-help-recentchangescount' => 'Гойту керла нисдарш, агӀонашан истори, тептарш.',
+'prefs-help-watchlist-token2' => 'Иза хьан тергаме могӀан къайла догӀа ду.
+Муьлха и хуучунна йиш ю хьан тергаме могӀам беша, цундела ма хаийта иза кхечаьрга. [[Special:ResetTokens|ТӀетаӀа йе кхуза и хьайга кхосса лууш делахь]].',
 'savedprefs' => 'Хьан гӀирс Ӏалашбина.',
 'timezonelegend' => 'Сахьатан аса:',
 'localtime' => 'Меттигера хан:',
@@ -1270,13 +1285,13 @@ $1',
 'right-nominornewtalk' => 'агӀонашкахь къезиг нисдарш цахиларо хуьлуьйту керла хаамийн хӀоттам',
 'right-apihighlimits' => 'API-дехарш кхочушдан кӀезиг дихкар',
 'right-writeapi' => 'дӀаяздеш лелойо API',
-'right-delete' => 'агӀош дӀаяхар',
+'right-delete' => 'агӀонаш дӀаяхар',
 'right-bigdelete' => 'еха хийцаман истори йолу агӀонаш дӀаяхар',
 'right-deletelogentry' => 'тептар чура билгала дӀаяздарш дӀадахар а меттахӀиттадар а.',
 'right-deleterevision' => 'агӀонийн билгала версеш дӀаяхар а меттахӀиттаяр а',
 'right-deletedhistory' => 'дӀаяхна агӀонийн исторега хьажар дӀадаьккхина йоза тӀекхочехь доцуш',
 'right-deletedtext' => 'дӀадаьккхина йозане а хийцамашка а хьажар агӀонийн дӀаяхна версин юккъахь',
-'right-browsearchive' => 'Ð\94Ӏаяхна агӀонаш лахар',
+'right-browsearchive' => 'дӀаяхна агӀонаш лахар',
 'right-undelete' => 'АгӀонаш меттахӀоттор',
 'right-suppressrevision' => 'куьйгалхойх хьулйина йолу агӀонийн версеш меттахӀиттаяр а хьажар а',
 'right-suppressionlog' => 'долара тептаршка хьажар',
@@ -1329,6 +1344,7 @@ $1',
 'action-move-rootuserpages' => 'декъашхочун ораман агӀонийн цӀераш хийцар',
 'action-delete' => 'дӀаяккха хӀара агӀо',
 'action-deletedhistory' => 'хӀокху агӀона дӀаяккхинцу исторега хьажар',
+'action-browsearchive' => 'ДӀаяхна агӀонаш лахар',
 'action-undelete' => 'хӀара агӀо меттахӀоттор',
 'action-patrol' => 'кхечера нисдарш хьаьжна сана билгалдар',
 'action-autopatrol' => 'шен нисдарш хьаьжна сана билгалдар',
@@ -1345,6 +1361,7 @@ $1',
 'recentchanges-label-minor' => 'Хlара нисдинарг къастийна жимо долушсан',
 'recentchanges-label-bot' => 'ХӀара нисдар шаболх бечо дина',
 'recentchanges-label-unpatrolled' => 'ХӀара нисдар хӀинца цхьано патрулировать дина дац',
+'recentchanges-legend-newpage' => '$1 — керла агlо',
 'rcnote' => "{{PLURAL:$1|Тlаьххьара '''$1''' хийцам|Тlаьххьара '''$1''' хийцамаш|Тlаьххьара '''$1''' хийцамаш}} за '''$2''' {{PLURAL:$2|де|дийнахь|дийнахь}}, оцу хан чохь $5 $4.",
 'rcnotefrom' => "Лахахь гайтина тӀера '''$2''' хийцамаш ('''$1''' къезиг).",
 'rclistfrom' => 'Гайта хийцам оцу $1.',
@@ -1376,7 +1393,7 @@ $1',
 'recentchangeslinked-summary' => "Хlара хийцам биначу агlонашан могlам бу, тlетовжар долуш хьагучу агlон (йа хьагойтуш йолучу категорена).
 Агlонаш юькъайогlуш йолу хьан [[Special:Watchlist|тергаме могlам чохь]] '''къастийна йу'''.",
 'recentchangeslinked-page' => 'Агlон цlе:',
-'recentchangeslinked-to' => 'Кхечу агlор, гайта хийцамаш агlонашца, хlоттийначу агlонтlе хьажориг йолуш',
+'recentchangeslinked-to' => 'Кхечу агӀор, гайта хийцамаш агӀонашца, хӀоттийначу агӀонтӀе хьажораг йолуш',
 
 # Upload
 'upload' => 'Файл чуяккхар',
@@ -1384,7 +1401,7 @@ $1',
 'reuploaddesc' => 'Юху гӀо файл чуйоккху агӀоне',
 'upload-tryagain' => 'ДӀадахьийта хийцина файлах лаьцнарг',
 'uploadnologintext' => 'Серверан чу файлаш яха хьо $1.',
-'upload-permitted' => 'Ð\9cагийна Ñ\84айлаÑ\88ан тайпанаш: $1.',
+'upload-permitted' => 'Ð\9cагийна Ñ\84айлийн тайпанаш: $1.',
 'uploadlogpage' => 'Чуяхаран тéптар',
 'uploadlogpagetext' => 'Лахахьа гойтуш бу могlам тlаьххьара чуяхна файлаши. Ишта хьажа. [[Special:ImageList|файлаши могlам]] йа [[Special:NewImages|галеларе файлаши]].',
 'filename' => 'Файлан цӀе',
@@ -1396,6 +1413,10 @@ $1',
 'ignorewarnings' => 'ДӀахедар тергал ца дан',
 'badfilename' => 'Файлан цӀе оцу $1.',
 'emptyfile' => 'Ахьа чуйоккхуш йолу файл еса хийла там бу. Иза гӀалат хийла мега файлан цӀе нийса язйина йоцу дела. Дехар до хьажа бакъалла и юьй ахьа чуйоккхуш йолу файл.',
+'fileexists' => 'Иштта цӀе йолу файл йолуш ю. Дехар до, хьажа <strong>[[:$1]]</strong>, лаьий хьуна и хийца. 
+[[$1|thumb]]',
+'fileexists-forbidden' => 'Иштта цӀе йолу файл йолуш ю цундела тӀехула дӀаязян йиш яц.
+ТӀаккха а хьара файл чуяккха лууш делахь, дехар до, юха а гӀой файлан цӀе хийца а яй чуяккха файл. [[File:$1|thumb|center|$1]]',
 'file-deleted-duplicate' => 'Иштта файл ([[:$1]]) хӀинцале дӀаяьккхина хилла. Дехар до, юху файл чуяккхале файл дӀаяккхаран историга хьажа.',
 'uploadwarning' => 'Дlахьедар',
 'uploadedimage' => 'чуяккхина «[[$1]]»',
@@ -1407,6 +1428,7 @@ $1',
 'upload-description' => 'Файлах лаьцна',
 'upload-options' => 'Чуякхаран параметраш',
 'watchthisupload' => 'Латайе хӀара файл тергаме могӀам юкъахь',
+'filewasdeleted' => 'Иштта цӀе йолуш файл хьалха чуяьккхина хила, амма дӀаяьккхина. Дехар до, юху чуяккхале $1 хьажа.',
 'filename-prefix-blacklist' => '#<!-- битийша хlара могlа ша мабарра --> <pre>
 # Бухасиз шолгlа:
 #  * Массо, саболчунтlийра йуьлалуш ерш «#» хуьлу хетаме дерг (могlа чекх балац)
@@ -1435,7 +1457,7 @@ PICT # тайп тайпан
 Декъашхо къастичи, цун керла файлаш гойту.',
 'listfiles_search_for' => 'Лаха хIуман цIарца:',
 'imgfile' => 'файл',
-'listfiles' => 'Файлийн Ð¼Ð¾Ð³Ó\80ам',
+'listfiles' => 'ФайлаÑ\88',
 'listfiles_date' => 'Терахь',
 'listfiles_name' => 'Файлан цӀе',
 'listfiles_user' => 'Декъашхо',
@@ -1457,7 +1479,7 @@ PICT # тайп тайпан
 'filehist-dimensions' => 'Файлан барам',
 'filehist-filesize' => 'Файлан барам',
 'filehist-comment' => 'Билгалдаккхар',
-'imagelinks' => 'Ð¥Ñ\8cажоÑ\80игаÑ\88 Ð¾Ñ\86Ñ\83 Ñ\84айлан',
+'imagelinks' => 'Файл Ð»ÐµÐ»Ð¾Ñ\80',
 'linkstoimage' => '{{PLURAL:$1|ТӀаьхьайогӀу $1 агӀо тӀетойжина|ТӀаьхьайогӀу $1 агӀонаш тӀетойжина|ТӀаьхьайогlу $1 агӀонаш тӀетойжина}} хӀокху файлан:',
 'nolinkstoimage' => 'АгӀонашчохь файл лелош яц.',
 'sharedupload' => 'Хlара хlума оцун $1 чура ю иза хила мега лелош кхечу кхолламашкахь.',
@@ -1476,6 +1498,7 @@ PICT # тайп тайпан
 'filerevert-success' => "Юхаерзина файл '''[[Media:$1|$1]]''' оцу [$4 верси $3, $2].",
 
 # File deletion
+'filedelete' => '$1 — дӀаяккхар',
 'filedelete-legend' => 'ДӀаяккха файл',
 'filedelete-intro' => "Хьо файл '''[[Media:$1|$1]]''' дӀаяккха гӀерта цунна массо истори цхьан.",
 'filedelete-comment' => 'Бахьан:',
@@ -1535,10 +1558,13 @@ PICT # тайп тайпан
 'pageswithprop-text' => 'Кхузахь гойтуш ю агӀонаш цхьадолу къастамаш куьйга юху билгал даьхнарш.',
 'pageswithprop-prop' => 'Къастаман цӀе:',
 
-'doubleredirects' => 'ШалгIа дIасахьажийнарш',
+'doubleredirects' => 'Шалха дIасахьажийнарш',
+'doubleredirectstext' => 'ХӀокху агӀонехь ю дӀасахьажорашан тӀе хьажийна йолу дӀасахьажораш.
+<del>ТӀехула сиз хаькхна </del>нисйина чарна.',
 'double-redirect-fixed-move' => 'Агlон [[$1]] цlе хийцна, хlинца иза дlахьажийна оцу [[$2]]',
 
 'brokenredirects' => 'ДIахаьдна долу дIасахьажораш',
+'brokenredirectstext' => 'Лахара дӀасахьажийнарш ю йоцучу агӀонийн тӀе хьажийна:',
 'brokenredirects-edit' => 'нисйé',
 'brokenredirects-delete' => 'дӀаяккха',
 
@@ -1551,13 +1577,14 @@ PICT # тайп тайпан
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|байт|байташ|байт}}',
 'ncategories' => '$1 {{PLURAL:$1|категори|категореш|категореш}}',
-'ninterwikis' => '$1 {{PLURAL:$1|Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80иг|Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80игаш}}',
-'nlinks' => '$1 {{PLURAL:$1|Ñ\85Ñ\8cажоÑ\80иг|Ñ\85Ñ\8cажоÑ\80игаш}}',
+'ninterwikis' => '$1 {{PLURAL:$1|Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80аг|Ñ\8eкÑ\8aаÑ\80вики-Ñ\85Ñ\8cажоÑ\80агаш}}',
+'nlinks' => '$1 {{PLURAL:$1|Ñ\85Ñ\8cажоÑ\80аг|Ñ\85Ñ\8cажоÑ\80агаш}}',
 'nmembers' => '$1 {{PLURAL:$1|хӀума|хӀумнаш}}',
 'nimagelinks' => 'Лелош ю $1 {{PLURAL:$1|агӀоначохь|агӀонашкахь|агӀонашкахь}}',
 'ntransclusions' => 'лелош ю $1 {{PLURAL:$1|агӀоначохь|агӀонашкахь|агӀонашкахь}}',
 'specialpage-empty' => 'Дехаро хӀумма ца елла.',
 'lonelypages' => 'Байлахь йисина агIонаш',
+'lonelypagestext' => 'Кхузахь ю {{grammar:genitive|{{SITENAME}}}} кхечу агӀонашкахь тӀе хьажийна хьажорагаш йоцу агӀонаш.',
 'uncategorizedpages' => 'Категореш йоцу агIонаш',
 'uncategorizedcategories' => 'Категореш йоцу категореш',
 'uncategorizedimages' => 'Категореш йоцу файлаш',
@@ -1571,12 +1598,12 @@ PICT # тайп тайпан
 Кхин йоцу файлаш гойту [[:$1]] чохь',
 'wantedfiletext-nocat' => 'Лахара йоцу файлаш лело гӀерта. Оцу могӀам юкъа ца хууш файлаш кхета там бу, кхечу проекташ чохь йолу. Ишта ца хууш юкъа нийса елачарна тӀехула <del>сиз</del> хира ду.',
 'wantedtemplates' => 'Оьшуш долу кепаш',
-'mostlinked' => 'Ð\94Ñ\83ккÑ\85а Ñ\85Ñ\8cажоÑ\80игаш тIе тоьхна йолу агIонаш',
+'mostlinked' => 'Ð\94Ñ\83ккÑ\85а Ñ\85Ñ\8cажоÑ\80агаш тIе тоьхна йолу агIонаш',
 'mostlinkedcategories' => 'Дуккха тӀе хьажораш йолу категореш',
 'mostlinkedtemplates' => 'Массарел дуккха а леладо кепаш',
 'mostcategories' => 'Дуккха категореш тӀе тоьхна йолу агӀонаш',
 'mostimages' => 'Массарел дуккха лелайо файлаш',
-'mostinterwikis' => 'Ð\94Ñ\83ккÑ\85а Ñ\8eкÑ\8aаÑ\80вики Ñ\85Ñ\8cажоÑ\80игаш тӀе тоьхна йолу агӀонаш',
+'mostinterwikis' => 'Ð\94Ñ\83ккÑ\85а Ñ\8eкÑ\8aаÑ\80вики Ñ\85Ñ\8cажоÑ\80агаш тӀе тоьхна йолу агӀонаш',
 'mostrevisions' => 'Сих сиха нисйина йолу агIонаш',
 'prefixindex' => 'Хьалха агlонашан цlераш хlотто йеза',
 'prefixindex-namespace' => 'Хьалха агӀонашан цӀераш хӀотто еза («{{ns:$1}}»)',
@@ -1596,7 +1623,7 @@ PICT # тайп тайпан
 'ancientpages' => 'Яззамаш оцу терахьца тӀаьххьара тадар дина долу',
 'move' => 'Цlе хийца',
 'movethispage' => 'Хlокху агlон цlе хийца',
-'unusedimagestext' => 'Дехар до, тидаме эца, кхин йолу дуьнана машан-меттигаш а лелош хила мега нисса йогlу хьажориг (URL) хlокху хlуман, хlокху могlаме йогlуш ялахь яцахь а иза хила мега жигара лелош.',
+'unusedimagestext' => 'Дехар до, тидаме эца, кхин йолу дуьнана машан-меттигаш а лелош хила мега нийсса йогӀу хьажораг (URL) хӀокху хӀуман, хӀокху могӀаме йогӀуш ялахь яцахь а иза хила мега жигара лелош.',
 'notargettitle' => 'Ӏалашо билгал йина яц',
 'nopagetitle' => 'Ишта агӀо яц',
 'nopagetext' => 'Ишта агӀо яц.',
@@ -1652,7 +1679,7 @@ PICT # тайп тайпан
 'linksearch-text' => 'Лело мега хӀоттош йолу символаш, масала, <code>*.wikipedia.org</code>.
 Лакхара даржан домен мукъа хила еза , масала<code>*.org</code><br />
 Ловш йолу {{PLURAL:$2|протокол|протоколаш}}: <code>$1</code> (Iад йитарца http://, протокол бакъалла язъен яцахь).',
-'linksearch-line' => '$2 â\80\94 Ñ\85Ñ\8cажоÑ\80иг кху $1',
+'linksearch-line' => '$2 â\80\94 Ñ\85Ñ\8cажоÑ\80аг кху $1',
 
 # Special:ListUsers
 'listusersfrom' => 'Гучé баха декъашхой, болалуш болу тӀера:',
@@ -1679,6 +1706,8 @@ PICT # тайп тайпан
 'emailuser' => 'Декъашхочун хааман кехат',
 'emailuser-title-target' => 'Декъашхочунга кехат яздар',
 'emailuser-title-notarget' => 'Декъашхочунга кехат яздар',
+'emailpagetext' => 'ХӀокху агӀона гӀоьнца йиш ю {{GENDER:$1|декъашхочун}} электронан почте хаам бахьийта.
+Хьоьга жоп лур ду ахьа [[Special:Preferences|хьайн гӀирса чу]] дӀаяздина долу адрес тӀе.',
 'defemailsubject' => 'Хаам {{grammar:genitive|{{SITENAME}}}} чура бу',
 'emailusername' => 'Декъашхочун цӀе:',
 'emailusernamesubmit' => 'ДӀадахьийта',
@@ -1686,6 +1715,8 @@ PICT # тайп тайпан
 'emailfrom' => 'Хьаьнгара',
 'emailto' => 'Хьаьнга:',
 'emailmessage' => 'Хаам:',
+'emailsend' => 'ДӀадахьийта',
+'emailccme' => 'Соьга а кхосса хааман копи.',
 'emailsent' => 'Кехат дӏадахьийтина',
 'emailsenttext' => 'Хьан электроннан хаам дӏабахьийтина.',
 
@@ -1726,16 +1757,7 @@ PICT # тайп тайпан
 'delete-confirm' => '$1 — дӀаяккхар',
 'delete-legend' => 'ДӀаяккхар',
 'historywarning' => "'''Тергам:''' хӀокху агӀона герггарчу хьесапехь $1 {{PLURAL:$1|версеш|верси|верси}} ю:",
-'confirmdeletetext' => "<div id=\"confirmdeletetext\">
-Хьо гӀерта '''[[Википеди:АгӀонаш дӀаяхар|хӀара агӀо дӀаяккха]]'''; '''дехар до''', хьажа [[Special:Whatlinkshere/{{FULLPAGENAMEE}}|хьажориг юй кхузе хьажийна]], дӀаяккхале хьалха уьш нисйа деза.
-{{#switch:{{NAMESPACE}}|{{ns:File talk}}=
-<br />Хила мега, хӀара дийцаре агӀо
-{{#ifexist:Media:{{PAGENAME}}
-|{{#ifexist:File:{{PAGENAME}}|цигара файлан.|оц [[ВикидӀайуьллуче]]ра.}}
-|йоцуш йолу файлан]]
-}}
-}}
-</div>",
+'confirmdeletetext' => "Хьо гӀерта агӀо я файл дӀаяккха '''дехар до''', дӀаяккхале хьалха хьажа [[{{MediaWiki:Policy-url}}|кхуза]].",
 'actioncomplete' => 'Дешдерг кхочушди',
 'actionfailed' => 'Кхочушъ дина дац',
 'deletedtext' => '«$1» дӀаяккхина яра.
@@ -1765,7 +1787,7 @@ PICT # тайп тайпан
 'protectedarticle' => 'гlаролла дина агlо «[[$1]]»',
 'modifiedarticleprotection' => 'агlонан гlаролли локхалла хийцина «[[$1]]»',
 'unprotectedarticle' => 'ГӀоролла дӀадаьстина «[[$1]]»',
-'movedarticleprotection' => '«[[$2]]» Ð³Ó\80аÑ\80олла Ñ\81еÑ\85Ñ\8cадаккÑ\85а Â«[[$1]]»',
+'movedarticleprotection' => '«[[$2]]» Ð°Ð³Ó\80она Ñ\82Ó\80еÑ\80а Ð³Ó\80аÑ\80олла Â«[[$1]]» Ð°Ð³Ó\80она Ñ\82Ó\80е Ð´Ð°Ñ\8cккÑ\85ина',
 'protect-title' => 'Оцунна «$1» гӀоралла дар',
 'prot_1movedto2' => '«[[$1]]» цlе хийцина оцу «[[$2]]»',
 'protect-legend' => 'Бакъде гӀоралла дар',
@@ -1815,7 +1837,7 @@ PICT # тайп тайпан
 'undelete' => 'ДIайайина йолу агIонашка хьажар',
 'undeletepage' => 'ДӀаяхина агӀонашка хьажар а меттахӀоттор а',
 'undeletepagetitle' => "'''Лахахь гайтина хӀокху [[:$1]] агӀона дӀаяхина версеш'''.",
-'viewdeletedpage' => 'ДIайайина йолу агIонашка хьажар',
+'viewdeletedpage' => 'ДӀаяхна йолу агӀонашка хьажар',
 'undelete-fieldset-title' => 'МеттахӀоттае версеш',
 'undeleteextrahelp' => "Ерриге агӀонан истори меттахӀоттая массо а билгалонаш еса а йити '''«{{int:undeletebtn}}»''' тӀетаӀае.
 ЦхӀайолу агӀонан версеш меттахӀоттая хьалха меттахӀоттош йолу версеш билгалъяьхна тӀетагӀе '''«{{int:undeletebtn}}»'''.",
@@ -1835,6 +1857,9 @@ PICT # тайп тайпан
 'undeletedpage' => "'''МеттахӀоттайина агӀо «$1».'''
 
 ДӀадяхнарш долу могӀане [[Special:Log/delete|тéптаре хьажа]].",
+'undelete-header' => 'Дукху хан йоцуш дӀаяхна агӀонаш хьажа мега [[Special:Log/delete|дӀадаьхьнарш долу тептар чохь]].',
+'undelete-search-title' => 'ДӀаяхна агӀонаш лахар',
+'undelete-search-box' => 'ДӀаяхна агӀонаш лахар',
 'undelete-search-submit' => 'Лаха',
 'undelete-show-file-submit' => 'Хlаъ',
 
@@ -1870,22 +1895,22 @@ PICT # тайп тайпан
 'sp-contributions-submit' => 'Лаха',
 
 # What links here
-'whatlinkshere' => 'Ð¥Ñ\8cажоÑ\80игаш кхузе',
-'whatlinkshere-title' => 'Ð\90гlонаÑ\88, Ñ\85Ñ\8cажоÑ\80игÑ\86а Ð¾Ñ\86Ñ\83 Â«$1»',
+'whatlinkshere' => 'Ð¥Ñ\8cажоÑ\80агаш кхузе',
+'whatlinkshere-title' => 'Ð¥Ó\80окÑ\85Ñ\83нÑ\86а Â«$1» Ð¹Ð¾Ð»Ñ\83 Ð°Ð³Ó\80онаÑ\88',
 'whatlinkshere-page' => 'Агlо:',
-'linkshere' => "Тlаьхьайогlу агlонаш хьажоригца ю оцу '''[[:$1]]''':",
-'nolinkshere' => "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашчохь хьажоригаш яц",
+'linkshere' => "ТӀаьхьайогӀу агӀонаш оцу '''[[:$1]]''': хьажорагца ю",
+'nolinkshere' => "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажорагаш яц.",
 'nolinkshere-ns' => "Хаьржинчу анахь яц '''[[:$1]]''' цӀе йолу агӀонаш",
 'isredirect' => 'агlо-дlасахьажайар',
 'istemplate' => 'лата йe',
-'isimage' => 'Ð\9eÑ\86Ñ\83 Ñ\81Ñ\83Ñ\8cÑ\80Ñ\82ан Ñ\85Ñ\8cажоÑ\80иг',
+'isimage' => 'Файлан Ñ\85Ñ\8cажоÑ\80аг',
 'whatlinkshere-prev' => '{{PLURAL:$1|хьалхайодарг|хьалхайодарш|хьалхайодарш}} $1',
 'whatlinkshere-next' => '{{PLURAL:$1|тlаьхьайогlург|тlаьхьайогlурш|тlаьхьайогlурш}} $1',
-'whatlinkshere-links' => 'â\86\90 Ñ\85Ñ\8cажоÑ\80игаш',
+'whatlinkshere-links' => 'â\86\90 Ñ\85Ñ\8cажоÑ\80агаш',
 'whatlinkshere-hideredirs' => '$1 дlасахьажйар',
 'whatlinkshere-hidetrans' => '$1 латораш',
-'whatlinkshere-hidelinks' => '$1 Ñ\85Ñ\8cажоÑ\80игаш',
-'whatlinkshere-hideimages' => '$1 Ñ\84айлаÑ\88ан Ñ\85Ñ\8cажоÑ\80игаш',
+'whatlinkshere-hidelinks' => '$1 Ñ\85Ñ\8cажоÑ\80агаш',
+'whatlinkshere-hideimages' => '$1 Ñ\84айлийн Ñ\85Ñ\8cажоÑ\80агаш',
 'whatlinkshere-filters' => 'Литтарш',
 
 # Block/unblock
@@ -1975,18 +2000,19 @@ PICT # тайп тайпан
 # Move page
 'move-page' => '$1 — цlе хийцар',
 'move-page-legend' => 'ЦӀe хийца яр',
-'movepagetext' => "Леладан лахар хатlаьхь, хьо агlон цlе хуьйцуш ву, цхьатерра дехьа а докхуш цуьнан хийцаман тептар.
-Тиша цlе хира ю дlасахьажйарехь керлачун тlе хьажийна.
-Хьега далур ду ша шех дlасахьажор керла яккхар, хьалхалерачуьна метта йиллина йолу.
-Нагахь ахьа иза цадинехь, дехар до, хьажа йуйла [[Special:DoubleRedirects|шалгlа]] а [[Special:BrokenRedirects|хадийначу дlасахьажориш]].
-Ахьа жоп лур ду кхин дlа а хьажориг хьажийна хилийта, хила йезаче.
-
-Тергамбеш хила, иза агlо '''хира яц''' цlе хийцина, нагахь иза цlе йолуш керла агlо йалахь, цхьа йолу хенахь, нагахь иза йалахь цхьан тlе хьажийна йа йаьсса а нисйарца истори йоцуш.
-Иза бохург ду, хьега хийцалур ю оцу агlон цlе оцу цlарца, хlинц цуьна хилла йолу, нагахь ахьа гlалатонца цlе хийцанехь, йолуш йолу агlо цахууш йа мега хьа.
-
-'''ДlАХЬЕДАР!'''
-Цlе хийцарца хила тарло барамашкахь а цамётту хийцам ''гlар йойлачу'' агlонашна.
-Дехар до, кхин дlа хьо вахале, дика ойла йе, хьо кхеташ хиларехь тlаьхьа хиндолучунах.",
+'movepagetext' => "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман журнал кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.
+
+Хьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажорагаш]] юй техь аьлла.
+
+Шу жоьпехь ду хьажорагаш нийса некъ гойтуш хиларан.
+
+Тидам бе хьалхалера агӀон цӀе ‘’’хийцалур яц’’’ иштта цӀе йолу агӀо йолуш елахь. Юкъардаккхар: йолуш йолу агӀо кхоьчухьа хьажораг елахь, я еса елахь а, цуьна хьийцаме истори яцахь а.
+
+И бохург ду шун агӀонан цӀе юха а хьалха хилларгчунтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.
+
+'''ДӀАХЬЕДАР!'''
+
+ЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
 'movepagetext-noredirectfixer' => "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман журнал кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.
 
 Хьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажорагаш]] юй техь аьлла.
@@ -2025,6 +2051,7 @@ PICT # тайп тайпан
 'movepage-page-moved' => 'АгӀона $1 цӀе хийцина оцу $2.',
 'movelogpage' => 'Цlераш хийцаран тептар',
 'movesubpage' => '{{PLURAL:$1|Бухара агӀо|Бухара агӀонаш}}',
+'movesubpagetext' => 'ХӀокху агӀона $1 {{PLURAL:$1|бухара агӀо ю|бухара агӀонаш ю}}.',
 'movenosubpage' => 'ХӀокху агӀона бухара агӀонаш яц.',
 'movereason' => 'Бахьан:',
 'revertmove' => 'юхаяккха',
@@ -2045,11 +2072,11 @@ PICT # тайп тайпан
 
 # Export
 'export' => 'АгӀонаш араяхар',
-'exporttext' => 'Шуьга далур ду кхечу меттера чудахарш, йоза а хийцаме тептарш билгалла йолу агlонаш йа гулдина йолу агlонаш хlокх XML барамца, йуха тlяхьа чура [[Special:Import|хьаэцалурдолш]] кхечу вики-хьалхен, болх беш йолу хlокху MediaWiki гlирсаца.
+'exporttext' => 'Шуьга далур ду кхечу меттера чудахарш, йоза а хийцаме тептарш билгалла йолу агӀонаш йа гулдина йолу агӀонаш хӀокх XML барамца, юха тӀяхьа чура [[Special:Import|хьаэцалурдолш]] кхечу вики-хьалхен, болх беш йолу хlокху MediaWiki гlирсаца.
 
-Кхечу меттера яззамаш чуйаха, чуязйе цlе редокхчу метте, цlхьа могlан цlе могlаршкахь, йуха харжа лаьи шуна Кхечу меттер чуйаха массо яззамашна истори хийцамбарш йа тlяхьаралера яззамна башхо.
+Кхечу меттера яззамаш чуйаха, чуязйе цӀе тадечу метте, цӀхьа могӀан цӀе могӀаршкахь, юха харжа лаьи шуна Кхечу меттер чуйаха массо яззамашна истори хийцамбарш йа тӀяхьаралера яззамна башхо.
 
-ШÑ\83Ñ\8cга ÐºÑ\85и Ð´Ð°Ð»Ð°Ð½Ð´ÐµÑ\80г, Ð»ÐµÐ»Ð°ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ð¼ÐµÑ\82Ñ\82иг ÐºÑ\8aаÑ\81Ñ\82аман Ð¼Ð°Ñ\88ан Ñ\85Ñ\8cажоÑ\80иг ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83даÑ\85а Ñ\82\8fÑ\85Ñ\8cаÑ\80леÑ\80а Ð±Ð°Ñ\88Ñ\85он Ñ\8fззамаÑ\88. Ð\9cаÑ\81Ñ\81ала Ð¾Ñ\86Ñ\83 Ñ\8fззамна [[{{MediaWiki:Mainpage}}]] Ñ\85lаÑ\80а Ñ\85иÑ\80а Ð¹Ñ\83 Ñ\85Ñ\8cажоÑ\80иг [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].',
+ШÑ\83Ñ\8cга ÐºÑ\85и Ð´Ð°Ð»Ð°Ð½Ð´ÐµÑ\80г, Ð»ÐµÐ»Ð°ÐµÑ\88 Ð¹Ð¾Ð»Ñ\83 Ð¼ÐµÑ\82Ñ\82иг ÐºÑ\8aаÑ\81Ñ\82аман Ð¼Ð°Ñ\88ан Ñ\85Ñ\8cажоÑ\80аг ÐºÑ\85еÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83даÑ\85а Ñ\82Ó\80аÑ\8cÑ\85Ñ\8cаÑ\80леÑ\80аÑ\87Ñ\83 Ð±Ð°Ñ\88Ñ\85он Ñ\8fззамаÑ\88. Ð\9cаÑ\81ала Ð¾Ñ\86Ñ\83 Ñ\8fззамна [[{{MediaWiki:Mainpage}}]] Ñ\85Ó\80аÑ\80а Ñ\85иÑ\80а Ñ\8e Ñ\85Ñ\8cажоÑ\80аг [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].',
 'exportcuronly' => 'Карара верси бен юкъа ма тоха, юзийна хьалхалерра истори йоцуш',
 'export-submit' => 'Экспорт ян',
 'export-addcattext' => 'ТӀетоха агӀонаш категори чура:',
@@ -2062,7 +2089,7 @@ PICT # тайп тайпан
 'allmessagesdefault' => 'Шаьшха йоза',
 'allmessagescurrent' => 'Карарчу хенан йоза',
 'allmessagestext' => 'ХӀара «MediaWiki» цӀерийн меттигера системан хаамийн могӀа бу.
-Хьайна MediaWiki тая лууш делахь, дехар до, проект [//translatewiki.net translatewiki.net] [//www.mediawiki.org/wiki/Localisation юьйцучу хьажа].',
+Хьайна MediaWiki тая лууш делахь, дехар до, проект [//translatewiki.net translatewiki.net] [https://www.mediawiki.org/wiki/Localisation юьйцучу хьажа].',
 'allmessages-filter-legend' => 'Литтар',
 'allmessages-filter' => 'Литтар оцу хьола хийцамца:',
 'allmessages-filter-unmodified' => 'Хийцан йоцурш',
@@ -2126,7 +2153,7 @@ PICT # тайп тайпан
 'tooltip-t-upload' => 'Чуйаха файлаш',
 'tooltip-t-specialpages' => 'Белха агlонаши могlам',
 'tooltip-t-print' => 'Хlокху агlонна зорба туху башхо',
-'tooltip-t-permalink' => 'Ð\94аимна Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80иг Ñ\85lокÑ\85Ñ\83 Ð±Ð°Ñ\88Ñ\85а Ð°Ð³lонна',
+'tooltip-t-permalink' => 'Ð\94аима Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг Ñ\85Ó\80окÑ\85Ñ\83 Ð±Ð°Ñ\88Ñ\85а Ð°Ð³Ó\80онна',
 'tooltip-ca-nstab-main' => 'Яззамна чулацам',
 'tooltip-ca-nstab-user' => 'ХӀора декъашхочун долахь йолу агӀо ю',
 'tooltip-ca-nstab-media' => 'Медиа-файл',
@@ -2165,12 +2192,14 @@ PICT # тайп тайпан
 # Spam protection
 'spamprotectiontitle' => 'Совбиларна литтар',
 'spamprotectiontext' => 'Хьо дӀаязъян гӀерта агӀо спам-литтаро дӀакъоьвлина.
-ЦÑ\83на Ð±Ð°Ñ\85Ñ\8cна Ñ\85ила Ñ\82ам Ð±Ñ\83 Ð°Ð³Ó\80она Ñ\87оÑ\85Ñ\8c Ð·Ñ\83лам Ð»Ð¸Ñ\82Ñ\82аÑ\80ан Ñ\87Ñ\83Ñ\82оÑ\8cÑ\85на Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80иг хилар.',
+ЦÑ\83на Ð±Ð°Ñ\85Ñ\8cна Ñ\85ила Ñ\82ам Ð±Ñ\83 Ð°Ð³Ó\80она Ñ\87оÑ\85Ñ\8c Ð·Ñ\83лам Ð»Ð¸Ñ\82Ñ\82аÑ\80ан Ñ\87Ñ\83Ñ\82оÑ\8cÑ\85на Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80аг хилар.',
 
 # Info page
 'pageinfo-header-basic' => 'Коьрта хаам',
 'pageinfo-language' => 'АгӀона мотт',
 'pageinfo-toolboxlink' => 'Агlонах болу бовзам',
+'pageinfo-redirectsto-info' => 'Хаам',
+'pageinfo-category-info' => 'Категорех лаьцна хаам',
 
 # Skin names
 'skinname-cologneblue' => 'Кёльнин сингаттам',
@@ -2205,7 +2234,7 @@ PICT # тайп тайпан
 'show-big-image-size' => '$1 × $2 пикселш',
 
 # Special:NewFiles
-'newimages' => 'Ð\9aеÑ\80лаÑ\87Ñ\83 Ñ\84айлийн Ð³Ð°Ð»ÐµÑ\80ий',
+'newimages' => 'Ð\9aеÑ\80лаÑ\87Ñ\83 Ñ\84айлийн Ð³Ð°Ð»ÐµÑ\80ей',
 'newimages-summary' => 'ХӀокху белхан агӀона чохь гойтуш ю дукха хан йоццуш чуйаьхна файлаш.',
 'newimages-legend' => 'Литтар',
 'showhidebots' => '$1 шабелхалой',
@@ -2214,13 +2243,24 @@ PICT # тайп тайпан
 
 # Video information, used by Language::formatTimePeriod() to format lengths in the above messages
 'seconds-abbrev' => '$1оцу',
+'hours' => '{{PLURAL:$1|1 сахьт}}',
+'days' => '{{PLURAL:$1|$1 де}}',
+'weeks' => '{{PLURAL:$1|$1 кӀира}}',
+'years' => '$1 {{PLURAL:$1|шо}}',
+'ago' => '$1 хьалха',
+
+# Human-readable timestamps
+'hours-ago' => '$1 {{PLURAL:$1|сахьт}} хьалха',
+'minutes-ago' => '$1 {{PLURAL:$1|минут}} хьалха',
+'seconds-ago' => '$1 {{PLURAL:$1|секунд}} хьалха',
+'yesterday-at' => 'селхана $1 даьлча',
 
 # Bad image list
 'bad_image_list' => 'Барам хила беза ишта:
 
-Лораш хира йу могlамяхь йолу хlумнаш (могlийн, йола луш йолу сабол тlира *).
\94Ñ\83Ñ\8cÑ\85Ñ\8cаÑ\80алеÑ\80а Ñ\85Ñ\8cажоÑ\80иг Ð¼Ð°Ð³lаÑ\80Ñ\88и Ñ\85ила Ð±ÐµÐ·Ð° Ñ\85Ñ\8cажоÑ\80иг кху цамагдо сурт дуьлаче.
lяхьа йогlуш йолу хьажориг оцу могlарехь хира йу магóш, билгалла аьлча яззамаш долуче, сурт хьаллаточехь.',
+Лораш хира ю могӀамяхь йолу хӀумнаш (могӀийн, йола луш йолу символ тӀира *).
\94Ñ\83Ñ\8cÑ\85Ñ\85Ñ\8cаÑ\80алеÑ\80а Ñ\85Ñ\8cажоÑ\80аг Ð¼Ð°Ð³Ó\80аÑ\80Ñ\88и Ñ\85ила Ð±ÐµÐ·Ð° Ñ\85Ñ\8cажоÑ\80аг кху цамагдо сурт дуьлаче.
Ӏяхьа йогӀуш йолу хьажораг оцу могӀарехь хира ю магóш, билгалла аьлча яззамаш долуче, сурт хьаллаточехь.',
 
 # Metadata
 'metadata' => 'Метахаамаш',
@@ -2311,7 +2351,7 @@ PICT # тайп тайпан
 
 # External editor support
 'edit-externally' => 'Рéдаккха хlокху хlуман, арахьара диллагlарам лелош',
-'edit-externally-help' => '(мадарра хьажа. оцу [//www.mediawiki.org/wiki/Manual:External_editors куьйгалийца дlахlотторе])',
+'edit-externally-help' => '(мадарра хьажа. оцу [https://www.mediawiki.org/wiki/Manual:External_editors куьйгалийца дlахlотторе])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'массо',
@@ -2404,8 +2444,7 @@ PICT # тайп тайпан
 
 # Special:SpecialPages
 'specialpages' => 'Леррина агlонаш',
-'specialpages-note' => '----
-* Гуттарлера белха агlонаш.
+'specialpages-note' => '* Гуттарлера белха агlонаш.
 * <strong class="mw-specialpagerestricted">Кlеззиг таронаш йолу леррина агlонаш.</strong>',
 'specialpages-group-maintenance' => 'Жамlаш гlирса хьашташ кхочушдар',
 'specialpages-group-other' => 'Кхин гlуллакхан агlонаш',
@@ -2461,7 +2500,7 @@ PICT # тайп тайпан
 'htmlform-selectorother-other' => 'Кхин',
 
 # New logging system
-'logentry-delete-delete' => '$1 {{GENDER:$2|дӀаякхина|дӀаякхина}} агӀо $3',
+'logentry-delete-delete' => '$1 {{GENDER:$2|дӀаяьккхина}} агӀо $3',
 'logentry-delete-restore' => '$1 {{GENDER:$2|меттахӀоттайина|меттахӀоттайина}} агӀо $3',
 'logentry-move-move' => '$1 {{GENDER:$2|цӀе хийцина|цӀе хийцина}} $3 оцу $4',
 'logentry-move-move-noredirect' => '$1 {{GENDER:$2|цӀе хийцина|цӀе хийцина}} $3 оцу $4 дӀасахьажийнарг цаюьтуш',
@@ -2480,6 +2519,10 @@ PICT # тайп тайпан
 # Search suggestions
 'searchsuggest-search' => 'Лаха',
 
+# Durations
+'duration-hours' => '$1 {{PLURAL:$1|сахьт}}',
+'duration-days' => '$1 {{PLURAL:$1|де}}',
+
 # Limit report
 'limitreport-title' => 'АгӀона хӀоттам къасторан хаамаш:',
 'limitreport-cputime' => 'Процессоран хан лелор',
@@ -2493,4 +2536,10 @@ PICT # тайп тайпан
 'limitreport-expansiondepth' => 'Шордаларан уггар йокха кӀоргалла',
 'limitreport-expensivefunctioncount' => 'АгӀона хӀоттам къасторан «еза» функцеш',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Кепаш схьаястар',
+'expand_templates_output' => 'Хилам',
+'expand_templates_remove_comments' => 'ДӀаяха комментареш',
+'expand_templates_preview' => 'Хьалха муха ю хьажа',
+
 );
index 7bb494f..af987a3 100644 (file)
@@ -48,7 +48,6 @@ $specialPageAliases = array(
        'Categories'                => array( 'Mga Kategoriya' ),
        'Contributions'             => array( 'Mga Tampo' ),
        'CreateAccount'             => array( 'Paghimo\'gAkawnt' ),
-       'Disambiguations'           => array( 'Mga Pagklaro' ),
        'DoubleRedirects'           => array( 'DoblengRedirekta' ),
        'Listfiles'                 => array( 'Listahan sa Imahen' ),
        'Lonelypages'               => array( 'Nag-inusarangPanid', 'Sinagop nga Panid' ),
@@ -314,8 +313,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Gikuha gikan sa "$1"',
 'youhavenewmessages' => 'Aduna kay $1 ($2).',
-'newmessageslink' => 'bag-ong mensahe',
-'newmessagesdifflink' => 'ulahing pag-usab',
 'youhavenewmessagesmulti' => 'Adunay kay bag-ong mensahe sa $1',
 'editsection' => 'usba',
 'editold' => 'usba',
@@ -724,8 +721,6 @@ Hinumdomi nga ang ilang indeks sa sulod sa {{SITENAME}} mahimong dugay-dugay na.
 'preferences' => 'Mga preperensiya',
 'mypreferences' => 'Akong preperensiya',
 'prefs-edits' => 'Gidaghanon sa nausab:',
-'prefsnologin' => 'Wala maka-log-in',
-'prefsnologintext' => 'Kinahanglan ikaw <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} naka-log-in]</span> aron ma-set ang imong mga preperensiya.',
 'changepassword' => 'Usba ang pasword',
 'prefs-skin' => 'Panit',
 'skin-preview' => 'Paunang tan-aw',
@@ -1203,7 +1198,7 @@ Ang uban default nga nakatago.
 
 # External editor support
 'edit-externally' => 'Usba kining payl gamit ang eksternal nga aplikasyon',
-'edit-externally-help' => '(Tan-awa ang [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] para sa dugang nga impormasyon)',
+'edit-externally-help' => '(Tan-awa ang [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] para sa dugang nga impormasyon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tanan',
index 53e4306..b71a07b 100644 (file)
@@ -12,6 +12,7 @@
  * @author Jatrobat
  * @author Magalahi
  * @author MisterWiki
+ * @author Shirayuki
  */
 
 $namespaceNames = array(
@@ -231,8 +232,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Ginen "$1"',
 'youhavenewmessages' => 'Guåha $1 ($2).',
-'newmessageslink' => 'mannuebu na mensåhe',
-'newmessagesdifflink' => 'tinilaika mas nuebu',
 'youhavenewmessagesmulti' => 'Guåha nuebu mensahe-mu gi $1',
 'editsection' => 'tulaika',
 'editold' => 'tulaika',
@@ -658,8 +657,6 @@ Fanapunta na fana'an ti gus nuebu i listan-ñiha i guinahan {{SITENAME}}.",
 'preferences' => "I ga'ña-mu",
 'mypreferences' => "I ga'ña-hu",
 'prefs-edits' => 'Numirun tinilaika:',
-'prefsnologin' => "Ti ma'log in",
-'prefsnologintext' => "Un nesisita [[Special:UserLogin|muna'log in]] para un tulaika i ga'ña-mu muna'sesetbi.",
 'changepassword' => 'Tulaika password',
 'prefs-skin' => 'Låssas',
 'skin-preview' => "Na'annok",
@@ -1086,7 +1083,7 @@ Ti mantattiyi i areklo ni sigienten ina'chetton siha gi mismo liña, i.e. i påh
 
 # External editor support
 'edit-externally' => 'Tulaika i atkibu yan un aplikasion sanhiyong',
-'edit-externally-help' => 'Hånao para [//www.mediawiki.org/wiki/Manual:External_editors i plantan chinachalani] para mas infotmasion.',
+'edit-externally-help' => 'Hånao para [https://www.mediawiki.org/wiki/Manual:External_editors i plantan chinachalani] para mas infotmasion.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todu',
index 6716b78..3ccaa28 100644 (file)
@@ -88,7 +88,7 @@ $specialPageAliases = array(
        'Mostlinkedcategories'      => array( 'پۆلەکانی_زیاترین_بەستەردراون،_پۆلەکانی_زیاترین_بەکارھێنراون' ),
        'Mostlinkedtemplates'       => array( 'داڕێژەکانی_زیاترین_بەستەردراون،_داڕێژەکانی_زیاترین_بەکارھێنراون' ),
        'Mostrevisions'             => array( 'زیاترین_پێداچوونەوەکان' ),
-       'Movepage'                  => array( 'پەڕە_گواستنەوە' ),
+       'Movepage'                  => array( 'گواستنەوەی_پەڕە' ),
        'Mycontributions'           => array( 'بەشدارییەکانم' ),
        'Mypage'                    => array( 'پەڕەکەم' ),
        'Mytalk'                    => array( 'لێدوانەکانم' ),
@@ -275,9 +275,9 @@ $messages = array(
 'subcategories' => 'ژێرپۆلەکان',
 'category-media-header' => 'میدیای پۆلی «$1»',
 'category-empty' => "''ئەم پۆلە ھەنووکە ھیچ پەڕە یان پەڕگەیەک لە خۆ ناگرێت.‌''",
-'hidden-categories' => '{{PLURAL:$1|Ù¾Û\86Ù\84Û\8c Ø´Ø§Ø±Ø§Ù\88Û\95|Ù¾Û\86Ù\84Û\8c Ø´Ø§Ø±Ø§Ù\88Û\95}}',
+'hidden-categories' => '{{PLURAL:$1|Ù¾Û\86Ù\84Û\8c Ø´Ø§Ø±Ø¯Ø§Ù\88Û\95|Ù¾Û\86Ù\84Û\95 Ø´Ø§Ø±Ø¯Ø§Ù\88Û\95کاÙ\86}}',
 '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|ژێرهاوپۆلی}} لەخۆ گرتووە.',
 'category-article-count' => '{{PLURAL:$2|ئەم پۆلە تەنھا ئەم پەڕەی لەخۆگرتووە.|{{PLURAL:$1|پەڕە|$1 پەڕە}} لەم پۆلەدا، لە سەرجەم $2 پەڕە.}}',
 'category-article-count-limited' => 'ئەم {{PLURAL:$1|لاپەڕە|$1 لاپەڕانە}}، لەم هاوپۆلەدان.',
@@ -367,7 +367,7 @@ $messages = array(
 'articlepage' => 'پەڕەی ناوەرۆک ببینە',
 'talk' => 'وتووێژ',
 'views' => 'بینینەکان',
-'toolbox' => 'ئامرازدان',
+'toolbox' => 'ئامرازەکان',
 'userpage' => 'بینینی پەڕەی بەکارھێنەر',
 'projectpage' => 'په‌ڕه‌ی پرۆژه‌ نیشانبده‌',
 'imagepage' => 'پەڕەی پەڕگە نیشان بدە',
@@ -425,8 +425,6 @@ $1',
 'backlinksubtitle' => '→ $1',
 'retrievedfrom' => 'وەرگیراو لە «$1»',
 'youhavenewmessages' => '$1ت ھەیە ($2).',
-'newmessageslink' => 'پەیامی نوێ',
-'newmessagesdifflink' => 'دوایین گۆڕانکاری',
 'youhavenewmessagesfromusers' => 'لە {{PLURAL:$3|بەکارھێنەرێک|$3 بەکارھێنەران}} $1ت ھەیە ($2).',
 'youhavenewmessagesmanyusers' => '$1ت  لە ژمارەیەک بەکارھێنەر ھەیە ( $2 ).',
 'newmessageslinkplural' => '{{PLURAL:$1|پەیامێکی نوێ|پەیامی نوێ}}',
@@ -872,8 +870,8 @@ $2
 ئەمە بڕێ‌جار کاتێ ڕوو ئەدات کە لە خزمەتی پرۆکسی سەر وێب کەڵک وەر بگریت.",
 'editing' => 'دەستکاریکردنی $1',
 'creating' => 'دروستکردنی $1',
-'editingsection' => 'دەستکاریکردنی: $1 (بەش)',
-'editingcomment' => 'دەستکاریکردنی $1 (بەشی  نوێ)',
+'editingsection' => 'دەستکاریکردنی $1 (بەش)',
+'editingcomment' => 'دەستکاریکردنی $1 (بەشی نوێ)',
 'editconflict' => 'کێشەی دەستکاری: $1',
 'explainconflict' => "کەسێکی تر ئەم پەڕەیە گۆڕیوە لەو کاتەوە تۆ دەستکاریکردنیت دەستپێکردووە.
 بەشی سەرەوەی دەق، شێوازی ئێستای پەڕەکە لە خۆ ئەگرێت.
@@ -1170,7 +1168,7 @@ $1",
 'searchmenu-new' => "'''لەم ویکییەدا پەڕەی « [[:$1]] » دروست بکە!'''",
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|گەڕیان لە پەڕەکانی بەم پێشگرەوە]]',
 'searchprofile-articles' => 'پەڕە بە ناوەڕۆکەکان',
-'searchprofile-project' => 'پەڕەکانی یارمەتی و پڕۆژە',
+'searchprofile-project' => 'پەڕەکانی یارمەتی و پرۆژە',
 'searchprofile-images' => 'ڕەنگاڵە',
 'searchprofile-everything' => 'ھەموو شتێک',
 'searchprofile-advanced' => 'پێشکەوتوو',
@@ -1182,7 +1180,7 @@ $1",
 'search-result-size' => '$1 ({{PLURAL:$2|یەک وشە|$2 وشە}})',
 'search-result-category-size' => '{{PLURAL:$1|١ ئەندام|$1 ئەندام}} ({{PLURAL:$2|١ ژێرپۆل|$2 ژێرپۆل}}, {{PLURAL:$3|١ پەڕگە|$3 پەڕگە}})',
 'search-result-score' => 'پەیوەندی: $1%',
-'search-redirect' => '(ئاڵوگۆڕ $1)',
+'search-redirect' => '(ڕەوانەکەر $1)',
 'search-section' => '(بەشی $1)',
 'search-suggest' => 'ئایا مەبەستت ئەمە بوو: $1',
 'search-interwiki-caption' => 'پرۆژە خوشکەکان',
@@ -1195,16 +1193,16 @@ $1",
 'searchall' => 'ھەموو',
 'showingresults' => "لە خوارەوە {{PLURAL:$1|'''یەک''' ئەنجام|'''$1''' ئەنجام}} نیشان دراوە، بە دەست پێ کردن لە ژمارەی '''$2'''ەوە.",
 'showingresultsnum' => "لە خوارەوە {{PLURAL:$3|'''١''' ئەنجام|'''$3''' ئەنجام}} دەبینن کە لە ئەنجامی ژمارە '''$2'''ەوە دەست{{PLURAL:$3|پێدەکات|پێدەکەن}}",
-'showingresultsheader' => "{{PLURAL:$5|ئەنجامی '''$1''' لە '''$3'''|ئەنجامەکانی '''$1 - $2''' لە '''$3'''}} بۆ '''$4'''",
+'showingresultsheader' => "{{PLURAL:$5|ئاکامی '''$1''' لە '''$3'''|ئاکامەکانی '''$1 - $2''' لە '''$3'''}} بۆ '''$4'''",
 'nonefound' => "'''تێبینی''': لە حاڵەتی بنچینەیی تەنھا لە ھەندێک لە بۆشایی‌ناوەکان گەڕان دەکرێت.
 وشەی ''all:'' بکە بە پێشگری پرسەکە بۆ گەڕان لە نێو ھەموو کەرستەکان (پەڕەکانی وتووێژ، داڕێژەکان و هتد)، یان بۆشایی‌ناوێکی دڵخواز وەک پێشگر بەکار بێنە.",
 'search-nonefound' => 'ھیچ ئاکامێک کە بە داواکارییەکەت بخوا نەدۆزرایەوە.',
 'powersearch' => 'پێشکەوتوو بگەڕێ',
 'powersearch-legend' => 'گەڕانی پێشکەوتوو',
-'powersearch-ns' => 'گەڕان لە بۆشاییناوەکانی:',
-'powersearch-redir' => 'ڕەوانەکراوەکان لیست بکرێن',
+'powersearch-ns' => 'گەڕان لە بۆشاییی ناوەکانی:',
+'powersearch-redir' => 'ڕەوانەکەرەکان پێرست بکە',
 'powersearch-field' => 'گەڕان بۆ',
-'powersearch-togglelabel' => 'پشکنینی:',
+'powersearch-togglelabel' => 'تاوتوێ بکە:',
 'powersearch-toggleall' => 'ھەموو',
 'powersearch-togglenone' => 'ھیچیان',
 'search-external' => 'گەڕانی دەرەکی',
@@ -1216,13 +1214,11 @@ $1",
 'preferences' => 'ھەڵبژاردەکان',
 'mypreferences' => 'ھەڵبژاردەکان',
 'prefs-edits' => 'ژمارەی گۆڕانکارییەکان:',
-'prefsnologin' => 'لەژوورەوە نیت',
-'prefsnologintext' => 'بۆ دانانی هەڵبژاردەکانی بەکارهێنەر دەبێ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} بچیتە ژوورەوە]</span>.',
 'changepassword' => 'تێپەڕوشە بگۆڕە',
 'prefs-skin' => 'پێستە',
 'skin-preview' => 'پێش بینین',
 'datedefault' => 'ھەڵنەبژێردراو',
-'prefs-beta' => 'کەرەسەکانی بیتا',
+'prefs-beta' => 'تایبەتمەندییەکانی بیتا',
 'prefs-datetime' => 'کات و ڕێکەوت',
 'prefs-labs' => 'کەرەسەکانی تاقیگەکان',
 'prefs-user-pages' => 'پەڕە بەکارھێنەرییەکان',
@@ -1498,6 +1494,7 @@ $1",
 'recentchanges-label-minor' => 'ئەمە دەستکارییەکی بچووکە',
 'recentchanges-label-bot' => 'ئەم دەستکاریە لە لایەن بۆتەوە پێک هاتووە',
 'recentchanges-label-unpatrolled' => 'ئەم دەستکارییە ھێشتا پاس نەدراوە',
+'recentchanges-legend-newpage' => '$1 - لاپەڕەی نوێ',
 'rcnote' => "لە خوارەوەدا {{PLURAL:$1|'''۱''' گۆڕانکاری |دوایین '''$1''' گۆڕانکارییەکان}} لە دوایین {{PLURAL:$2|ڕۆژ|'''$2''' ڕۆژەوە}} ، تا $5، $4 دەبینن.",
 'rcnotefrom' => "ئەوی‌ خوارەوە گۆڕانکارییەکانە لە '''$2'''ەوە (ھەتا '''$1''' نیشاندراو).",
 'rclistfrom' => 'گۆڕانکارییە نوێکان نیشان بدە بە دەستپێکردن لە $1',
@@ -2319,9 +2316,9 @@ $1',
 'month' => 'لە مانگی (و پێشترەوە):',
 'year' => 'لە ساڵی (و پێشترەوە):',
 
-'sp-contributions-newbies' => 'تەنھا بەشدارییەکانی بەکارھێنەرە تازەکان نیشان بدە',
-'sp-contributions-newbies-sub' => 'لە بەکارھێنەرە تازەکانەوە',
-'sp-contributions-newbies-title' => 'هاوبەشیەکانی بەکارهێنەر بۆ هەژمارە نوێکان',
+'sp-contributions-newbies' => 'تەنیا بەشدارییەکانی ھەژمارە نوێکان نیشان بدە',
+'sp-contributions-newbies-sub' => 'بۆ ھەژمارە نوێکان',
+'sp-contributions-newbies-title' => 'بەشدارییەکانی بەکارھێنەر بۆ ھەژمارە نوێکان',
 'sp-contributions-blocklog' => 'لۆگی بەربەستن',
 'sp-contributions-deleted' => 'بەشدارییە سڕاوەکان',
 'sp-contributions-uploads' => 'بارکردنەکان',
@@ -2530,7 +2527,7 @@ $1',
 'cant-move-user-page' => 'ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەکانی بەکارهێنەر (جیاواز لە ژێرلاپەڕەکان).',
 'cant-move-to-user-page' => 'ڕێگەت پێ‌نەدراوە بۆ گواستنەوەی لاپەڕەیەک بۆ لاپەڕەی بەکارهێنەر (غەیری بۆ ژێرلاپەڕەی بەکارهێنەر).',
 'newtitle' => 'بۆ ناوی نوێی:',
-'move-watch' => 'ئەم پەڕەیە بخە ژێر چاودێری',
+'move-watch' => 'پەڕەی سەرچاوە و مەبەست بخە ژێر چاودێری',
 'movepagebtn' => 'ئەم پەڕەیە بگوازەوە',
 'pagemovedsub' => 'گواستنەوە بە سەرکەوتوویی جێبەجێ کرا',
 'movepage-moved' => "'''«$1» گوازرایەوە بۆ «$2»'''",
@@ -2607,7 +2604,7 @@ $1',
 'allmessagesdefault' => 'دەقی بنەڕەتی',
 'allmessagescurrent' => 'دەقی ھەنووکە',
 'allmessagestext' => 'ئەمە لیستێکە لە پەیامەکانی بەردەست لە بۆشایی‌ناوی میدیاویکی.
-تکایە سەردانی [//www.mediawiki.org/wiki/Localisation ناوچەیی‌کردنی میدیاویکی] و [//translatewiki.net translatewiki.net] بکە ئەگەر دەتەوێ لە ناوچەیی‌کردنی میدیاویکی بە گشتی بەشداری بکەیت.',
+تکایە سەردانی [https://www.mediawiki.org/wiki/Localisation ناوچەیی‌کردنی میدیاویکی] و [//translatewiki.net translatewiki.net] بکە ئەگەر دەتەوێ لە ناوچەیی‌کردنی میدیاویکی بە گشتی بەشداری بکەیت.',
 'allmessagesnotsupportedDB' => "ئەم لاپەڕە ناتوانی بەکاربێت لەبەر ئەوەی '''\$wgUseDatabaseMessages''' لەکار خستراوە.",
 'allmessages-filter-legend' => 'پاڵێو',
 'allmessages-filter-unmodified' => 'نەگۆڕدراو',
@@ -2810,6 +2807,7 @@ $1',
 'pageinfo-authors' => 'ژمارەی نووسەرە جیاوازەکان',
 'pageinfo-recent-edits' => 'ژمارەی دوایین دەستکارییەکان (لە $1ی ڕابردوودا)',
 'pageinfo-recent-authors' => 'ژمارەی دوایین نووسەرە جیاوازەکان',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|پۆلی شاردراوە|پۆلە شاردراوەکان}} ($1)',
 'pageinfo-templates' => 'داڕێژە{{PLURAL:$1|ی بەکارگیراو| بەکارگیراوەکان}} ($1)',
 'pageinfo-toolboxlink' => 'زانیاریی پەڕە',
 'pageinfo-redirectsto-info' => 'زانیاری',
@@ -3175,7 +3173,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'دەستکاریی ئەم پەڕەیە بکە بە بەکارھێنانی پڕۆگرامێکی دەرەکی',
-'edit-externally-help' => '(بۆ زانیاریی زیاتر سەیری [//www.mediawiki.org/wiki/Manual:External_editors  ڕێنماییەکانی دامەزراندن] بکە)',
+'edit-externally-help' => '(بۆ زانیاریی زیاتر سەیری [https://www.mediawiki.org/wiki/Manual:External_editors  ڕێنماییەکانی دامەزراندن] بکە)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ھەموو',
@@ -3408,8 +3406,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'پەڕە تایبەتەکان',
-'specialpages-note' => '----
-* پەڕە تایبەتە ئاسایییەکان.
+'specialpages-note' => '* پەڕە تایبەتە ئاسایییەکان.
 * <span class="mw-specialpagerestricted">پەڕە تایبەتە بەرگری‌لێکراوەکان.</span>',
 'specialpages-group-maintenance' => 'ڕاپۆرتەکانی چاکسازی',
 'specialpages-group-other' => 'پەڕە تایبەتەکانی دیکە',
@@ -3448,6 +3445,8 @@ $5
 'tags-display-header' => 'دیمەن لەسەر لیستەکانی گۆڕان',
 'tags-description-header' => 'پێناسەی تەواوی مەبەست',
 'tags-hitcount-header' => 'گۆڕانکاریە تاگ‌کراوەکان',
+'tags-active-yes' => 'بەڵێ',
+'tags-active-no' => 'نا',
 'tags-edit' => 'دەستکاری',
 'tags-hitcount' => '$1 {{PLURAL:$1|گۆڕان|گۆڕانکاری}}',
 
@@ -3480,6 +3479,8 @@ $5
 'htmlform-submit' => 'ناردن',
 'htmlform-reset' => 'پووچەڵکردنەوەی دەستکارییەکان',
 'htmlform-selectorother-other' => 'دیکە',
+'htmlform-no' => 'نا',
+'htmlform-yes' => 'بەڵێ',
 
 # New logging system
 'logentry-delete-delete' => '$1 پەڕەی $3ی {{GENDER:$2|سڕییەوە}}',
@@ -3540,4 +3541,7 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|سەدە|سەدە}}',
 'duration-millennia' => '$1 {{PLURAL:$1|ھەزارە|ھەزارە}}',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'باشە',
+
 );
index 17de57f..0988bbf 100644 (file)
@@ -270,8 +270,6 @@ Tan-awon ang [[Special:Version|pahina sang bersyon]].',
 'ok' => 'Sige',
 'retrievedfrom' => 'Nakuha halin sa "$1"',
 'youhavenewmessages' => 'May ara ka sang $1 ($2).',
-'newmessageslink' => 'mga bag-o nga mensahe',
-'newmessagesdifflink' => 'katapusan nga pag-ilis',
 'youhavenewmessagesmulti' => 'May mga bag-o ka nga mensahe sa $1',
 'editsection' => 'bag-uhon',
 'editold' => 'bag-uhon',
@@ -953,7 +951,7 @@ Ang iban ay pagataguon sang default.
 
 # External editor support
 'edit-externally' => 'Islan ang mini nga file gamit ang panluwas nga aplikasyon',
-'edit-externally-help' => '(Tan-awa ang [//www.mediawiki.org/wiki/Manual:External_editors mga pama-agi sa paghanda kag pag-ayos] para sa mga dugang nga impormasyon)',
+'edit-externally-help' => '(Tan-awa ang [https://www.mediawiki.org/wiki/Manual:External_editors mga pama-agi sa paghanda kag pag-ayos] para sa mga dugang nga impormasyon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tanan',
index a582b18..f60d84a 100644 (file)
@@ -103,6 +103,7 @@ $dateFormats = array(
 
 $separatorTransformTable = array( ','  => '.', '.' => ',' );
 $linkTrail = '/^([a-zâçğıñöşüа-яё“»]+)(.*)$/sDu';
+$linkPrefixCharset = 'a-zâçğıñöşüA-ZÂÇĞİÑÖŞÜa-яёА-ЯЁ«„';
 
 $messages = array(
 # User preference toggles
@@ -230,8 +231,6 @@ $messages = array(
 'noindex-category' => 'Индекссиз саифелер',
 'broken-file-category' => 'Ичинде бозукъ файл багълантылары олгъан саифелер',
 
-'linkprefix' => '/^(.*?)([a-zâçğıñöşüA-ZÂÇĞİÑÖŞÜa-яёА-ЯЁ«„]+)$/sDu',
-
 'about' => 'Акъкъында',
 'article' => 'Саифе',
 'newwindow' => '(янъы бир пенджереде ачылыр)',
@@ -362,8 +361,6 @@ $1',
 'ok' => 'Ок',
 'retrievedfrom' => 'Менба – "$1"',
 'youhavenewmessages' => 'Янъы $1 бар ($2).',
-'newmessageslink' => 'беянатынъыз',
-'newmessagesdifflink' => 'музакере саифенъизнинъ сонъки денъиштирильмеси',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Башкъа бир къулланыджыдан|$3 къулланыджыдан}} $1 бар. ($2)',
 'youhavenewmessagesmanyusers' => 'Бир къач къулланыджыдан $1 бар. ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|янъы беянатынъыз|янъы беянатларынъыз}}',
@@ -880,8 +877,6 @@ $3 мына бу себепни бильдирди: ''$2''",
 'preferences' => 'Сазламалар',
 'mypreferences' => 'Сазламалар',
 'prefs-edits' => 'Денъиштирмелер сайысы:',
-'prefsnologin' => 'Отурым ачмадынъыз',
-'prefsnologintext' => 'Шахсий сазламаларынъызны денъиштирмек ичюн <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} отурым ачмакъ]</span> керексинъиз.',
 'changepassword' => 'Пароль денъиштир',
 'prefs-skin' => 'Ресимлеме',
 'skin-preview' => 'Бакъып чыкъув',
@@ -1028,6 +1023,7 @@ $3 мына бу себепни бильдирди: ''$2''",
 'recentchanges-label-minor' => 'Бу, кичик бир денъиштирме',
 'recentchanges-label-bot' => 'Бу бир ботнынъ япкъан денъиштирмеси',
 'recentchanges-label-unpatrolled' => 'Бу денъиштирме аля даа тешкерильмеген',
+'recentchanges-legend-newpage' => '$1 - янъы саифе',
 'rcnote' => "$4 $5 тарихында сонъки {{PLURAL:$2|куньде|'''$2''' куньде}} япылгъан '''{{PLURAL:$1|1|$1}}''' денъиштирме:",
 'rcnotefrom' => "'''$2''' тарихындан итибарен япылгъан денъиштирмелер ашагъыдадыр (энъ чокъ '''$1''' дане саифе косьтериле).",
 'rclistfrom' => '$1 тарихындан берли япылгъан денъиштирмелерни косьтер',
@@ -1681,7 +1677,7 @@ $UNWATCHURL
 'allmessagesdefault' => 'Оригиналь метин',
 'allmessagescurrent' => 'Шимди къулланылгъан метин',
 'allmessagestext' => 'Ишбу джедвель MediaWiki-де мевджут олгъан бутюн система беянатларынынъ джедвелидир.
-MediaWiki интерфейсининъ чешит тиллерге терджиме этювде иштирак этмеге истесенъиз [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ве [//translatewiki.net translatewiki.net] саифелерине зиярет этинъиз.',
+MediaWiki интерфейсининъ чешит тиллерге терджиме этювде иштирак этмеге истесенъиз [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ве [//translatewiki.net translatewiki.net] саифелерине зиярет этинъиз.',
 
 # Thumbnails
 'thumbnail-more' => 'Буют',
@@ -1918,7 +1914,7 @@ MediaWiki интерфейсининъ чешит тиллерге терджи
 
 # External editor support
 'edit-externally' => 'Файл узеринде компьютеринъизде булунгъан программалар иле денъишикликлер япынъыз',
-'edit-externally-help' => '(Даа зияде малюмат ичюн [//www.mediawiki.org/wiki/Manual:External_editors бу саифеге] (Инглиздже) бакъып оласынъыз.)',
+'edit-externally-help' => '(Даа зияде малюмат ичюн [https://www.mediawiki.org/wiki/Manual:External_editors бу саифеге] (Инглиздже) бакъып оласынъыз.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'эписини',
index bd6306f..aa405a5 100644 (file)
@@ -97,6 +97,7 @@ $dateFormats = array(
 
 $separatorTransformTable = array( ',' => '.', '.' => ',' );
 $linkTrail = '/^([a-zâçğıñöşüа-яё“»]+)(.*)$/sDu';
+$linkPrefixCharset = 'a-zâçğıñöşüA-ZÂÇĞİÑÖŞÜa-яёА-ЯЁ«„';
 
 $messages = array(
 # User preference toggles
@@ -224,8 +225,6 @@ $messages = array(
 'noindex-category' => 'İndekssiz saifeler',
 'broken-file-category' => 'İçinde bozuq fayl bağlantıları olğan saifeler',
 
-'linkprefix' => '/^(.*?)([a-zâçğıñöşüA-ZÂÇĞİÑÖŞÜa-яёА-ЯЁ«„]+)$/sDu',
-
 'about' => 'Aqqında',
 'article' => 'Saife',
 'newwindow' => '(yañı bir pencerede açılır)',
@@ -357,8 +356,6 @@ $1',
 'ok' => 'Ok',
 'retrievedfrom' => 'Menba – "$1"',
 'youhavenewmessages' => 'Yañı $1 bar ($2).',
-'newmessageslink' => 'beyanatıñız',
-'newmessagesdifflink' => 'muzakere saifeñizniñ soñki deñiştirilmesi',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başqa bir qullanıcıdan|$3 qullanıcıdan}} $1 bar. ($2)',
 'youhavenewmessagesmanyusers' => 'Bir qaç qullanıcıdan $1 bar. ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|yañı beyanatıñız|yañı beyanatlarıñız}}',
@@ -876,8 +873,6 @@ Vikide bu saifege oşağan saifelerni [[Special:Search|tapıp baqıñız]].',
 'preferences' => 'Sazlamalar',
 'mypreferences' => 'Sazlamalar',
 'prefs-edits' => 'Deñiştirmeler sayısı:',
-'prefsnologin' => 'Oturım açmadıñız',
-'prefsnologintext' => 'Şahsiy sazlamalarıñıznı deñiştirmek içün <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} oturım açmaq]</span> kereksiñiz.',
 'changepassword' => 'Parol deñiştir',
 'prefs-skin' => 'Resimleme',
 'skin-preview' => 'Baqıp çıquv',
@@ -1024,6 +1019,7 @@ Eger bildirseñiz, saifelerdeki deñiştirmelerni kimniñ yapqanını köstermek
 'recentchanges-label-minor' => 'Bu, kiçik bir deñiştirme',
 'recentchanges-label-bot' => 'Bu bir botnıñ yapqan deñiştirmesi',
 'recentchanges-label-unpatrolled' => 'Bu deñiştirme alâ daa teşkerilmegen',
+'recentchanges-legend-newpage' => '$1 - yañı saife',
 'rcnote' => "$4 $5 tarihında soñki {{PLURAL:$2|künde|'''$2''' künde}} yapılğan '''{{PLURAL:$1|1|$1}}''' deñiştirme:",
 'rcnotefrom' => "'''$2''' tarihından itibaren yapılğan deñiştirmeler aşağıdadır (eñ çоq '''$1''' dane saife kösterile).",
 'rclistfrom' => '$1 tarihından berli yapılğan deñiştirmelerni köster',
@@ -1675,7 +1671,7 @@ Jurnalnıñ soñki yazısı aşağıda berilgen:",
 'allmessagesdefault' => 'Original metin',
 'allmessagescurrent' => 'Şimdi qullanılğan metin',
 'allmessagestext' => 'İşbu cedvel MediaWikide mevcut olğan bütün sistema beyanatlarınıñ cedvelidir.
-MediaWiki interfeysiniñ çeşit tillerge tercime etüvde iştirak etmege isteseñiz [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ve [//translatewiki.net translatewiki.net] saifelerine ziyaret etiñiz.',
+MediaWiki interfeysiniñ çeşit tillerge tercime etüvde iştirak etmege isteseñiz [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ve [//translatewiki.net translatewiki.net] saifelerine ziyaret etiñiz.',
 
 # Thumbnails
 'thumbnail-more' => 'Büyüt',
@@ -1912,7 +1908,7 @@ Er satır * işaretinen başlamalı. Satırnıñ birinci bağlantısı qоşmağ
 
 # External editor support
 'edit-externally' => 'Fayl üzerinde kompyuteriñizde bulunğan programmalar ile deñişiklikler yapıñız',
-'edit-externally-help' => '(Daa ziyade malümat içün [//www.mediawiki.org/wiki/Manual:External_editors bu saifege] (İnglizce)  baqıp olasıñız.)',
+'edit-externally-help' => '(Daa ziyade malümat içün [https://www.mediawiki.org/wiki/Manual:External_editors bu saifege] (İnglizce)  baqıp olasıñız.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'episini',
index c4277c2..e49ffaf 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-/** Czech (česky)
+/** Czech (čeština)
  *
  * See MessagesQqq.php for message documentation incl. usage of parameters
  * To improve a translation please visit http://translatewiki.net
@@ -80,7 +80,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Nejstarší_stránky', 'Staré_stránky', 'Stare_stranky' ),
        'Blankpage'                 => array( 'Prázdná_stránka' ),
        'Block'                     => array( 'Blokování', 'Blokovani', 'Blokovat_uživatele', 'Blokovat_IP', 'Blokovat_uzivatele' ),
-       'Blockme'                   => array( 'Zablokuj_mě', 'Zablokuj_me' ),
        'Booksources'               => array( 'Zdroje_knih' ),
        'BrokenRedirects'           => array( 'Přerušená_přesměrování', 'Prerusena_presmerovani' ),
        'Categories'                => array( 'Kategorie' ),
@@ -92,9 +91,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Vytvořit_účet', 'Vytvorit_ucet' ),
        'Deadendpages'              => array( 'Slepé_stránky', 'Slepe_stranky' ),
        'DeletedContributions'      => array( 'Smazané_příspěvky', 'Smazane_prispevky' ),
-       'Disambiguations'           => array( 'Rozcestníky', 'Rozcestniky' ),
        'DoubleRedirects'           => array( 'Dvojitá_přesměrování', 'Dvojita_presmerovani' ),
        'Emailuser'                 => array( 'E-mail' ),
+       'ExpandTemplates'           => array( 'Testy_šablon' ),
        'Export'                    => array( 'Exportovat_stránky' ),
        'Fewestrevisions'           => array( 'Stránky_s_nejméně_editacemi', 'Stranky_s_nejmene_editacemi', 'Stránky_s_nejmenším_počtem_editací' ),
        'FileDuplicateSearch'       => array( 'Hledání_duplicitních_souborů', 'Hledani_duplicitnich_souboru' ),
@@ -230,7 +229,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'střed', 'center', 'centre' ),
        'img_framed'                => array( '1', 'rám', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'bezrámu', 'frameless' ),
-       'img_page'                  => array( '1', 'strana=$1', 'strana $1', 'page=$1', 'page $1' ),
+       'img_lang'                  => array( '1', 'jazyk=$1', 'lang=$1' ),
+       'img_page'                  => array( '1', 'strana=$1', 'strana_$1', 'page=$1', 'page $1' ),
        'img_border'                => array( '1', 'okraj', 'border' ),
        'sitename'                  => array( '1', 'NÁZEVWEBU', 'SITENAME' ),
        'ns'                        => array( '0', 'JMENNÝPROSTOR:', 'NS:' ),
@@ -282,6 +282,7 @@ $magicWords = array(
        'noindex'                   => array( '1', '__NEINDEXOVAT__', '__NOINDEX__' ),
        'staticredirect'            => array( '1', '__STATICKÉPŘESMĚROVÁNÍ__', '__STATICREDIRECT__' ),
        'protectionlevel'           => array( '1', 'ÚROVEŇZAMČENÍ', 'PROTECTIONLEVEL' ),
+       'pagesincategory_files'     => array( '0', 'soubory', 'files' ),
 );
 
 /**
@@ -637,12 +638,10 @@ $1',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Citováno z „$1“',
 'youhavenewmessages' => 'Máte $1 ($2).',
-'newmessageslink' => 'nové zprávy',
-'newmessagesdifflink' => 'rozdíl oproti předchozí verzi',
 'youhavenewmessagesfromusers' => 'Máte $1 od {{PLURAL:$3|jiného uživatele|$3 jiných uživatelů}} ($2).',
 'youhavenewmessagesmanyusers' => 'Máte $1 od mnoha dalších uživatelů ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|novou zprávu|nové zprávy}}',
-'newmessagesdifflinkplural' => 'poslední {{PLURAL:$1|změna|změny}}',
+'newmessageslinkplural' => '{{PLURAL:$1|novou zprávu|999=nové zprávy}}',
+'newmessagesdifflinkplural' => 'poslední {{PLURAL:$1|změna|999=změny}}',
 'youhavenewmessagesmulti' => 'Na $1 máte nové zprávy',
 'editsection' => 'editovat',
 'editold' => 'editovat',
@@ -769,7 +768,8 @@ Správce serveru, který úložiště zamkl, poskytl toto zdůvodnění: „''$3
 'invalidtitle-knownnamespace' => 'Neplatný název se jmenným prostorem „$2“ a textem „$3“',
 'invalidtitle-unknownnamespace' => 'Neplatný název s neznámým číslem jmenného prostoru $1 a textem „$2“',
 'exception-nologin' => 'Nejste přihlášen(a)',
-'exception-nologin-text' => 'Tato stránka nebo akce vyžaduje, abyste byli na této wiki přihlášeni.',
+'exception-nologin-text' => 'Pro přístup na tuto stránku nebo k této akci se prosím [[Special:Userlogin|přihlaste]].',
+'exception-nologin-text-manual' => 'Pro přístup na tuto stránku nebo k této akci se musíte $1.',
 
 # Virus scanner
 'virus-badscanner' => "Špatná konfigurace: neznámý antivirový program: ''$1''",
@@ -816,7 +816,7 @@ Nezapomeňte si upravit své [[Special:Preferences|nastavení {{grammar:2sg|{{SI
 'gotaccount' => "Už jste registrováni? '''$1'''.",
 'gotaccountlink' => 'Přihlaste se',
 'userlogin-resetlink' => 'Zapomněli jste přihlašovací údaje?',
-'userlogin-resetpassword-link' => 'Obnovit heslo',
+'userlogin-resetpassword-link' => 'Zapomněli jste heslo?',
 'helplogin-url' => 'Help:Přihlášení',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Nápověda k přihlašování]]',
 'userlogin-loggedin' => 'Již jste {{GENDER:$1|přihlášen|přihlášena}} jako $1.
@@ -885,8 +885,9 @@ a používat staré heslo.',
 Kvůli prevenci zneužívání lze heslo zaslat jen jednou za $1 {{PLURAL:$1|hodinu|hodiny|hodin}}.',
 'mailerror' => 'Chyba při zasílání e-mailu: $1',
 'acct_creation_throttle_hit' => 'Uživatelé přicházející z vaší IP adresy už dnes vytvořili $1 {{PLURAL:$1|účet|účty|účtů}}, což je dovolené maximum. Proto v tuto chvíli není dovoleno z této IP adresy další účty zakládat.',
-'emailauthenticated' => 'Vaše e-mailová adresa byla ověřena dne $2 v $3.',
-'emailnotauthenticated' => 'Vaše e-mailová adresa dosud nebyla ověřena a e-mailové funkce do té doby nejsou dostupné.',
+'emailauthenticated' => 'Vaše e-mailová adresa byla ověřena $2 v $3.',
+'emailnotauthenticated' => 'Vaše e-mailová adresa dosud nebyla ověřena.
+U následujících funkcí nebudou zasílány žádné e-maily.',
 'noemailprefs' => 'Pro zprovoznění následujících možností musíte zadat svou e-mailovou adresu.',
 'emailconfirmlink' => 'Podvrďte svou e-mailovou adresu',
 'invalidemailaddress' => 'Zadaná e-mailová adresa nemůže být přijata, neboť nemá správný formát. Zadejte platnou e-mailovou adresu nebo obsah tohoto pole vymažte.',
@@ -1316,16 +1317,16 @@ pokud nebyla nastavena další omezení.",
 * Potenciálně pomlouvačné informace
 * Nevhodné osobní údaje
 *: ''adresy bydliště a telefonní čísla, rodná čísla apod.''",
-'revdelete-legend' => 'Nastavit omezení k revizi',
-'revdelete-hide-text' => 'Skrýt text revize',
+'revdelete-legend' => 'Nastavit omezení viditelnosti',
+'revdelete-hide-text' => 'Text revize',
 'revdelete-hide-image' => 'Skrýt obsah souboru',
 'revdelete-hide-name' => 'Skrýt událost a cíl',
-'revdelete-hide-comment' => 'Skrýt editační komentář',
-'revdelete-hide-user' => 'Skrýt uživatelské jméno/IP adresu',
+'revdelete-hide-comment' => 'Editační komentář',
+'revdelete-hide-user' => 'Uživatelské jméno / IP adresa',
 'revdelete-hide-restricted' => 'Utajit data i před správci',
 'revdelete-radio-same' => '(neměnit)',
-'revdelete-radio-set' => 'Ano',
-'revdelete-radio-unset' => 'Ne',
+'revdelete-radio-set' => 'Skrytý',
+'revdelete-radio-unset' => 'Viditelný',
 'revdelete-suppress' => 'Utajit data i před správci',
 'revdelete-unsuppress' => 'Odstranit omezení na vrácené verze',
 'revdelete-log' => 'Důvod:',
@@ -1480,8 +1481,7 @@ Pokud na začátek dotazu přidáte ''all:'', bude se hledat všude (včetně di
 'preferences' => 'Nastavení',
 'mypreferences' => 'Nastavení',
 'prefs-edits' => 'Počet editací:',
-'prefsnologin' => 'Nejste přihlášen(a)!',
-'prefsnologintext' => 'Pokud chcete měnit uživatelská nastavení, musíte se <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} přihlásit]</span>.',
+'prefsnologintext2' => 'Pro změnu uživatelských nastavení se musíte $1.',
 'changepassword' => 'Změna hesla',
 'prefs-skin' => 'Vzhled',
 'skin-preview' => 'Náhled',
@@ -1520,7 +1520,7 @@ Pokud na začátek dotazu přidáte ''all:'', bude se hledat všude (včetně di
 'prefs-help-recentchangescount' => 'Týká se posledních změn, historie stránek a protokolovacích záznamů.',
 'prefs-help-watchlist-token2' => 'Toto je tajný klíč k webovému kanálu vašich sledovaných stránek. Kdokoli, kdo bude tento klíč znát, bude moci váš seznam sledovaných stránek číst, takže ho nešiřte.
 [[Special:ResetTokens|Kliknutím sem ho můžete reinicializovat.]]',
-'savedprefs' => 'Vaše nastavení bylo uloženo.',
+'savedprefs' => 'Nastavení byla uložena.',
 'timezonelegend' => 'Časové pásmo:',
 'localtime' => 'Místní čas:',
 'timezoneuseserverdefault' => 'Použít časové pásmo wiki ($1)',
@@ -1780,6 +1780,9 @@ Vaše adresa v takovém případě není prozrazena.',
 'recentchanges-label-minor' => 'Toto je malá editace',
 'recentchanges-label-bot' => 'Tuto editaci provedl bot',
 'recentchanges-label-unpatrolled' => 'Tato změna dosud nebyla prověřena',
+'recentchanges-label-plusminus' => 'Velikost stránky se změnila o tolik bajtů',
+'recentchanges-legend-newpage' => '(vizte též [[Special:NewPages|seznam nových stránek]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => 'Níže {{plural:$1|je poslední|jsou poslední|je posledních}} <strong>$1</strong> {{plural:$1|změna|změny|změn}} za {{PLURAL:$2|poslední|poslední|posledních}} <strong>$2</strong> {{plural:$2|den|dny|dnů}} před $4, $5.',
 'rcnotefrom' => 'Níže {{PLURAL:$1|je|jsou|je}} nejvýše <b>$1</b> {{PLURAL:$1|změna|změny|změn}} od <b>$2</b>.',
 'rclistfrom' => 'Ukázat nové změny, počínaje od $1',
@@ -2502,9 +2505,9 @@ Uživatele, který změnu provedl, můžete kontaktovat:
 e-mailem: $PAGEEDITOR_EMAIL
 na wiki: $PAGEEDITOR_WIKI
 
-Dokud stránku nenavštívíte, nebudou vám zasílána další oznámení o změnách této stránky. Případně si můžete vynulovat příznaky ve svém seznamu sledovaných stránek.
+Do doby, než stránku navštívíte jako přihlášený uživatel, vám další oznámení k této stránce nebudou zasílána. Případně si můžete vynulovat příznaky ve svém seznamu sledovaných stránek.
 
-       S pozdravem váš zasílač hlášení {{grammar:2sg|{{SITENAME}}}}
+S pozdravem váš zasílač hlášení {{grammar:2sg|{{SITENAME}}}}
 
 --
 Změnit nastavení e-mailových oznámení můžete na
@@ -3004,7 +3007,7 @@ V druhém případě můžete také používat přímý odkaz, např. pomocí [[
 'allmessagesdefault' => 'Původní text',
 'allmessagescurrent' => 'Aktuální text',
 'allmessagestext' => 'Toto je seznam všech hlášení dostupných ve jmenném prostoru MediaWiki.
-Pokud si přejete přispívat k lokalizaci softwaru MediaWiki, navštivte [//www.mediawiki.org/wiki/Localisation lokalizační stránku na mediawiki.org] a [//translatewiki.net server translatewiki.net].',
+Pokud si přejete přispívat k lokalizaci softwaru MediaWiki, navštivte [https://www.mediawiki.org/wiki/Localisation lokalizační stránku na mediawiki.org] a [//translatewiki.net server translatewiki.net].',
 'allmessagesnotsupportedDB' => '{{ns:special}}:AllMessages není podporováno, neboť wgUseDatabaseMessages je vypnuto.',
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter' => 'Filtr podle stavu:',
@@ -3164,6 +3167,7 @@ Uložte jej na svůj disk a nahrajte ho sem.',
 'tooltip-undo' => '„Zrušit editaci“ otevře okno editace, které neobsahuje změny provedené v rušené editaci. Je možné doplnit zdůvodnění do shrnutí editace.',
 'tooltip-preferences-save' => 'Uložit nastavení',
 'tooltip-summary' => 'Zadejte stručné shrnutí',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* Zde uvedené CSS bude ovlivňovat všechny styly */',
@@ -3212,6 +3216,8 @@ Uložte jej na svůj disk a nahrajte ho sem.',
 'spam_reverting' => 'Revert na poslední verzi neobsahující odkazy na $1',
 'spam_blanking' => 'Všechny verze obsahovaly odkazy na $1, vyprázdněno',
 'spam_deleting' => 'Všechny verze obsahovaly odkazy na $1, smazáno',
+'simpleantispam-label' => "Antispamová kontrola.
+'''NEVYPLŇUJTE''' následující!",
 
 # Info page
 'pageinfo-title' => 'Informace o stránce „$1“',
@@ -3225,6 +3231,7 @@ Uložte jej na svůj disk a nahrajte ho sem.',
 'pageinfo-length' => 'Velikost stránky (v bajtech)',
 'pageinfo-article-id' => 'ID stránky',
 'pageinfo-language' => 'Jazyk obsahu stránky',
+'pageinfo-content-model' => 'Model obsahu stránky',
 'pageinfo-robot-policy' => 'Indexování roboty',
 'pageinfo-robot-index' => 'Dovoleno',
 'pageinfo-robot-noindex' => 'Zakázáno',
@@ -3311,7 +3318,7 @@ Otevřením souboru můžete ohrozit svůj počítač.",
 'svg-long-desc' => 'soubor SVG, nominální rozměr: $1 × $2 pixelů, velikost souboru: $3',
 'svg-long-desc-animated' => 'Animovaný soubor SVG, nominální rozměr: $1 × $2 pixelů, velikost souboru: $3',
 'svg-long-error' => 'Neplatný soubor SVG: $1',
-'show-big-image' => 'Obrázek ve vyšším rozlišení',
+'show-big-image' => 'Původní soubor',
 'show-big-image-preview' => 'Velikost tohoto náhledu: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Jiné|Jiná}} rozlišení: $1.',
 'show-big-image-size' => '$1 × $2 pixelů',
@@ -3775,7 +3782,7 @@ Obsahuje pouze seznam s odrážkami (řádka začíná s *). První odkaz na ř
 
 # External editor support
 'edit-externally' => 'Editovat tento soubor v externím programu',
-'edit-externally-help' => '(Více informací najdete v [//www.mediawiki.org/wiki/Manual:External_editors nápovědě pro nastavení].)',
+'edit-externally-help' => '(Více informací najdete v [https://www.mediawiki.org/wiki/Manual:External_editors nápovědě pro nastavení].)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'všechny',
@@ -3878,6 +3885,7 @@ Opravdu si přejete znovu tuto stránku založit?',
 # Separators for various lists, etc.
 'ellipsis' => '…',
 'percent' => '$1&#160;%',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← předchozí stránka',
@@ -4021,7 +4029,7 @@ Seznam editovaných stránek můžete také [[Special:EditWatchlist|editovat ve
 'version-hook-subscribedby' => 'Volán z',
 'version-version' => '(Verze $1)',
 'version-license' => 'Licence',
-'version-poweredby-credits' => "Tato wiki běží na '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Tato wiki běží na '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'další',
 'version-poweredby-translators' => 'překladatelé na translatewiki.net',
 'version-credits-summary' => 'Následujícím lidem bychom rádi poděkovali za jejich příspěvky [[Special:Version|MediaWiki]].',
@@ -4042,7 +4050,7 @@ MediaWiki je distribuována v naději, že bude užitečná, avšak BEZ JAKÉKOL
 # Special:Redirect
 'redirect' => 'Přesměrování podle souboru, uživatele nebo ID revize',
 'redirect-legend' => 'Přesměrování na soubor či stránku',
-'redirect-summary' => 'Tato speciální stránka přesměrovává na soubor (podle názvu), stránku (podle ID revize) nebo uživatele (podle číselného uživatelského ID).',
+'redirect-summary' => 'Tato speciální stránka přesměrovává na soubor (podle názvu), stránku (podle ID revize) nebo uživatele (podle číselného uživatelského ID). Použití: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] nebo [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Přejít',
 'redirect-lookup' => 'Najít:',
 'redirect-value' => 'Hodnota:',
@@ -4064,8 +4072,8 @@ MediaWiki je distribuována v naději, že bude užitečná, avšak BEZ JAKÉKOL
 
 # Special:SpecialPages
 'specialpages' => 'Speciální stránky',
-'specialpages-note' => '----
-* Normální speciální stránky
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Normální speciální stránky
 * <span class="mw-specialpagerestricted">Speciální stránky s&nbsp;vyhrazeným přístupem</span>',
 'specialpages-group-maintenance' => 'Údržba',
 'specialpages-group-other' => 'Ostatní',
@@ -4279,4 +4287,21 @@ Jinak můžete využít jednoduchý formulář níže. Váš komentář bude př
 'limitreport-expansiondepth' => 'Největší hloubka expanze',
 'limitreport-expensivefunctioncount' => 'Počet náročných funkcí parseru',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Substituce šablon',
+'expand_templates_intro' => 'Tato speciální stránka vezme text a rekurzivně rozbalí všechny použité šablony.
+Také rozbalí podporované funkce parseru jako
+<code><nowiki>{{</nowiki>#language:…}}</code> a proměnné jako
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+V podstatě rozbalí prakticky všechno v dvojitých složených závorkách.',
+'expand_templates_title' => 'Název stránky kvůli kontextu pro {{FULLPAGENAME}} apod.:',
+'expand_templates_input' => 'Vstupní text:',
+'expand_templates_output' => 'Výstup',
+'expand_templates_xml_output' => 'Výstup XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Odstranit komentáře',
+'expand_templates_remove_nowiki' => 'Potlačit ve výsledku značky <nowiki>',
+'expand_templates_generate_xml' => 'Zobrazit syntaktický strom v XML',
+'expand_templates_preview' => 'Náhled',
+
 );
index 2d2d4bf..53ea9be 100644 (file)
@@ -278,8 +278,6 @@ $messages = array(
 'ok' => 'Jo!',
 'retrievedfrom' => 'Z "$1"',
 'youhavenewmessages' => 'Môsz $1 ($2).',
-'newmessageslink' => 'nowe wiadła',
-'newmessagesdifflink' => 'slédnô zmiana',
 'youhavenewmessagesmulti' => 'Môsz nowé klëczi: $1',
 'editsection' => 'Edicëjô',
 'editold' => 'Edicëjô',
@@ -583,7 +581,6 @@ Spróbùjë szëkbë z przëdôwkã ''all:'' dlô całowny zamkłoscë starnów
 'preferences' => 'Preferencëje',
 'mypreferences' => 'Mòje nastôwë',
 'prefs-edits' => 'Lëczba edicëjów:',
-'prefsnologin' => 'Felënk logòwóniô',
 'changepassword' => 'Zmiana parolë',
 'prefs-skin' => 'Wëzdrzatk',
 'skin-preview' => 'Pòdzérk',
@@ -1090,7 +1087,7 @@ W taczich przëtrôfkach zamkłosc diskùsëji mòże przeniesc blós rãczno.',
 'allmessagesdefault' => 'Domëslny tekst',
 'allmessagescurrent' => 'Aktualny tekst',
 'allmessagestext' => 'To je zestôwk systemòwëch ògłosów przistãpnëch w rumie mionów MediaWiki.
-Proszã zazdrzë na [//www.mediawiki.org/wiki/Localisation Lokalizacëjô MediaWiki] ë [//translatewiki.net translatewiki.net] jeżlë chcesz dolmaczëc softwôrã MediaWiki.',
+Proszã zazdrzë na [https://www.mediawiki.org/wiki/Localisation Lokalizacëjô MediaWiki] ë [//translatewiki.net translatewiki.net] jeżlë chcesz dolmaczëc softwôrã MediaWiki.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' nie mòże bëc brëkòwónô, temù że '''\$wgUseDatabaseMessages''' je wëłączony.",
 
 # Thumbnails
@@ -1224,7 +1221,7 @@ Jinszé pòla bãdą domëslno zataconé.
 
 # External editor support
 'edit-externally' => 'Editëjë nen lopk brëkùjąc bùtnowi aplikacëji',
-'edit-externally-help' => '(Zdrzë na [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] dlô dobëcô wicy wëdowiédzë).',
+'edit-externally-help' => '(Zdrzë na [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] dlô dobëcô wicy wëdowiédzë).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'wszëtczé',
index e9c7e05..d08e017 100644 (file)
@@ -97,6 +97,7 @@ $dateFormats = array(
 );
 
 $linkTrail = '/^([a-zабвгдеєжѕзїіıићклмнопсстѹфхѡѿцчшщъыьѣюѥѧѩѫѭѯѱѳѷѵґѓђёјйљњќуўџэ҄я“»]+)(.*)$/sDu';
+$linkPrefixCharset = '„«';
 
 $messages = array(
 # User preference toggles
@@ -180,8 +181,6 @@ $messages = array(
 'category-subcat-count' => '{{PLURAL:$2|Сѥи катигорїи тъкъмо сꙗ подъкатигорїꙗ ѥстъ|Сѥи катигорїи {{PLURAL:$1|ѥдина подъкатигорїꙗ ѥстъ|2 подъкатигорїи ѥстє|$1 подъкатигорїѩ сѫтъ}} · а вьсѩ жє подъкатигорїѩ число $2 ѥстъ}}',
 'listingcontinuesabbrev' => '· вѧщє',
 
-'linkprefix' => '/^(.*?)(„|«)$/sD',
-
 'about' => 'опьсаниѥ',
 'article' => 'члѣнъ',
 'newwindow' => '(иномь окънѣ)',
@@ -270,10 +269,8 @@ $messages = array(
 'pagetitle' => '$1 · {{SITENAME}}',
 'retrievedfrom' => 'поѩто иꙁ ⁖ $1 ⁖',
 'youhavenewmessages' => '$1 тєбѣ напьсанꙑ сѫтъ ($2)',
-'newmessageslink' => 'нови напьсаниꙗ',
-'newmessagesdifflink' => 'послѣдьнꙗ мѣна',
-'newmessageslinkplural' => '{{PLURAL:$1|ново напьсаниѥ|нова напьсании|новꙑ напьсаниꙗ}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|послѣдьнꙗ мѣна|послѣдьни мѣни|послѣдьн҄ь мѣнъ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ново напьсаниѥ|нова напьсании|999=новꙑ напьсаниꙗ}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|послѣдьнꙗ мѣна|послѣдьни мѣни|999=послѣдьн҄ь мѣнъ}}',
 'editsection' => 'исправи',
 'editold' => 'исправи',
 'viewsourceold' => 'страницѧ источьнъ обраꙁъ',
@@ -432,8 +429,8 @@ $messages = array(
 'rev-delundel' => 'каꙁаниѥ / съкрꙑтиѥ',
 'rev-showdeleted' => 'виждь',
 'revdelete-show-file-submit' => 'да',
-'revdelete-radio-set' => 'да',
-'revdelete-radio-unset' => 'нѣÑ\82Ñ\8a',
+'revdelete-radio-set' => 'съкрꙑто',
+'revdelete-radio-unset' => 'каê\99\81ано',
 'revdelete-log' => 'какъ съмꙑслъ :',
 'pagehist' => 'страницѧ їсторїꙗ',
 'deletedhist' => 'поничьжєна їсторїꙗ',
@@ -928,7 +925,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'дѣла иꙁмѣнѥниѥ вънѣщьниимь орѫдиѥмь',
-'edit-externally-help' => '(ꙁьри [//www.mediawiki.org/wiki/Manual:External_editors помощь] вѧщєи плирофорїѩ дѣлꙗ)',
+'edit-externally-help' => '(ꙁьри [https://www.mediawiki.org/wiki/Manual:External_editors помощь] вѧщєи плирофорїѩ дѣлꙗ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'вьсꙗ',
index ef5f4f1..ff06707 100644 (file)
@@ -42,6 +42,7 @@ $namespaceGenderAliases = array();
 
 $linkPrefixExtension = true;
 $linkTrail = '/^([a-zа-яĕçăӳ"»]+)(.*)$/sDu';
+$linkPrefixCharset = 'a-zA-Z"\\x{80}-\\x{10ffff}';
 
 $messages = array(
 # User preference toggles
@@ -153,8 +154,6 @@ $messages = array(
 'category-file-count-limited' => 'Ку категоринче $1 файл.',
 'listingcontinuesabbrev' => '(малалли)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff«"]+)$/sD',
-
 'about' => 'Ăнлантаркăч',
 'article' => 'Статья',
 'newwindow' => '(çĕнĕ чӳречере)',
@@ -270,8 +269,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Çăлкуç — «$1»',
 'youhavenewmessages' => 'Сирĕн $1 пур ($2).',
-'newmessageslink' => 'çĕнĕ пĕлтерӳсем',
-'newmessagesdifflink' => 'юлашки улшăну',
 'youhavenewmessagesmulti' => '$1-та çĕнĕ пĕлтерӳсем пур.',
 'editsection' => 'тӳрлет',
 'editold' => 'тӳрлет',
@@ -576,7 +573,6 @@ $1 хутшăнакан патне, е ытти [[{{MediaWiki:Grouppage-sysop}}|
 'preferences' => 'Ĕнерлевсем',
 'mypreferences' => 'Ман ĕнерлевсем',
 'prefs-edits' => 'Тӳрлетӳсен шучĕ:',
-'prefsnologin' => 'Эсир сайта кĕмен',
 'changepassword' => 'Пароле улăштар',
 'prefs-skin' => 'Ерешленӳ',
 'skin-preview' => 'Малтанхи курăну',
@@ -647,6 +643,7 @@ $1 хутшăнакан патне, е ытти [[{{MediaWiki:Grouppage-sysop}}|
 'recentchanges' => 'Улшăнусем',
 'recentchanges-legend' => 'Çĕнĕ улшăнусен ĕнерлевĕ',
 'recentchanges-label-bot' => 'Ку улшăнăва бот тунă',
+'recentchanges-legend-newpage' => '$1 — çĕнĕ страница',
 'rcnote' => 'Юлашки <strong>$2</strong> кун хушшинчи <strong>$1</strong> улшăнусем. Халě пěтěмпе  <strong>{{NUMBEROFARTICLES}}</strong> статья.',
 'rclistfrom' => 'Юлашки улшăнусене $1 вăхăтран пуçласа кăтартнă',
 'rcshowhideminor' => 'пĕчĕк тӳрлетӳсене $1',
index e7c3818..c956e90 100644 (file)
@@ -33,7 +33,7 @@ $namespaceNames = array(
        NS_TEMPLATE         => 'Nodyn',
        NS_TEMPLATE_TALK    => 'Sgwrs_Nodyn',
        NS_HELP             => 'Cymorth',
-       NS_HELP_TALK        => 'Sgwrs Cymorth',
+       NS_HELP_TALK        => 'Sgwrs_Cymorth',
        NS_CATEGORY         => 'Categori',
        NS_CATEGORY_TALK    => 'Sgwrs_Categori',
 );
@@ -64,14 +64,14 @@ $magicWords = array(
        'subpagenamee'              => array( '1', 'ENWISDUDALENE', 'SUBPAGENAMEE' ),
        'talkpagename'              => array( '1', 'ENWTUDALENSGWRS', 'TALKPAGENAME' ),
        'talkpagenamee'             => array( '1', 'ENWTUDALENSGWRSE', 'TALKPAGENAMEE' ),
-       'img_thumbnail'             => array( '1', 'ewin bawd', 'bawd', 'mân-lun', 'thumbnail', 'thumb' ),
+       'img_thumbnail'             => array( '1', 'ewin_bawd', 'bawd', 'mân-lun', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'mân-lun=$1', 'bawd=$1', 'thumbnail=$1', 'thumb=$1' ),
        'img_right'                 => array( '1', 'de', 'right' ),
        'img_left'                  => array( '1', 'chwith', 'left' ),
        'img_none'                  => array( '1', 'dim', 'none' ),
        'img_center'                => array( '1', 'canol', 'center', 'centre' ),
-       'img_page'                  => array( '1', 'tudalen=$1', 'tudalen $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'unionsyth', 'unionsyth=$1', 'unionsyth $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'tudalen=$1', 'tudalen_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'unionsyth', 'unionsyth=$1', 'unionsyth_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_sub'                   => array( '1', 'is', 'sub' ),
        'img_super'                 => array( '1', 'uwch', 'super', 'sup' ),
        'img_top'                   => array( '1', 'brig', 'top' ),
@@ -159,7 +159,7 @@ $messages = array(
 'tog-diffonly' => "Peidio â dangos cynnwys y dudalen islaw'r gymhariaeth ar dudalennau cymharu",
 'tog-showhiddencats' => 'Dangos categorïau cuddiedig',
 'tog-norollbackdiff' => 'Hepgor dangos cymhariaeth ar ôl gwrthdroi golygiad',
-'tog-useeditwarning' => "Tynnwch fy sylw pan wyf ar fin gadael tudalen olygu heb roi'r newidiadau ar gadw",
+'tog-useeditwarning' => "Tynnu fy sylw pan wyf ar fin gadael tudalen olygu heb roi'r newidiadau ar gadw",
 'tog-prefershttps' => 'Defnyddio cysylltiad diogel bob amser tra fy mod wedi mewngofnodi',
 
 'underline-always' => 'Bob amser',
@@ -390,8 +390,6 @@ $1',
 'ok' => 'Iawn',
 'retrievedfrom' => 'Wedi dod o "$1"',
 'youhavenewmessages' => 'Mae gennych chi $1 ($2).',
-'newmessageslink' => 'Neges(eueon) newydd',
-'newmessagesdifflink' => 'y newid diweddaraf',
 'youhavenewmessagesfromusers' => 'Mae gennych $1 oddi wrth {{PLURAL:$3||ddefnyddiwr arall|$2 ddefnyddiwr arall|$3 defnyddiwr arall|$3 defnyddiwr arall|$3 defnyddiwr arall}} ($2).',
 'youhavenewmessagesmanyusers' => 'Mae gennych $1 oddi wrth lu o ddefnyddwyr eraill ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|neges newydd|neges newydd|negeseuon newydd}}',
@@ -523,7 +521,8 @@ Y rheswm a roddwyd gan y gweinyddwr a roddodd y ffeil dan glo yw "\'\'$3\'\'".',
 'invalidtitle-knownnamespace' => 'Teitl annilys o\'r enw "$3" yn y parth "$2"',
 'invalidtitle-unknownnamespace' => 'Teitl annilys ag iddi\'r rhif parth anhysbys $1 a\'r enw "$2"',
 'exception-nologin' => 'Nid ydych wedi mewngofnodi',
-'exception-nologin-text' => "Rhaid mewngofnodi i'r wici er mwyn gweld y dudalen neu gyflawni'r weithred.",
+'exception-nologin-text' => "[[Special:Userlogin|Mewngofnodwch]] er mwyn gweld y dudalen neu gyflawni'r weithred.",
+'exception-nologin-text-manual' => "Mae angen $1 er mwyn gweld y dudalen neu gyflawni'r weithred.",
 
 # Virus scanner
 'virus-badscanner' => "Cyfluniad gwael: sganiwr firysau anhysbys: ''$1''",
@@ -569,7 +568,7 @@ Sylwer y bydd rhai tudalennau yn parhau i ymddangos fel ag yr oeddent pan oeddec
 'gotaccount' => 'Oes cyfrif gennych eisoes? $1.',
 'gotaccountlink' => 'Mewngofnodi',
 'userlogin-resetlink' => 'Ydych chi wedi anghofio eich manylion mewngofnodi?',
-'userlogin-resetpassword-link' => 'Ailosod eich cyfrinair',
+'userlogin-resetpassword-link' => 'Wedi anghofio eich cyfrinair?',
 'helplogin-url' => 'Help:Mewngofnodi',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Cymorth i fewngofnodi]]',
 'userlogin-loggedin' => 'Rydych eisoes wedi mewngofnodi wrth yr enw {{GENDER:$1|$1}}.
@@ -629,14 +628,14 @@ Os mai rhywun arall a holodd am y cyfrinair, ynteu eich bod wedi cofio\'r hen gy
 'passwordsent' => 'Mae cyfrinair newydd wedi\'i ddanfon at gyfeiriad e-bost cofrestredig "$1". Mewngofnodwch eto ar ôl i chi dderbyn y cyfrinair, os gwelwch yn dda.',
 'blocked-mailpassword' => 'Gan fod eich cyfeiriad IP wedi ei atal rhag golygu, ni ellir adfer y cyfrinair.',
 'eauthentsent' => 'Anfonwyd e-bost o gadarnhâd at y cyfeiriad a benwyd.
-Cyn y gellir anfon unrhywbeth arall at y cyfeiriad hwnnw rhaid i chi ddilyn y cyfarwyddiadau yn yr e-bost hwnnw er mwyn cadarnhau bod y cyfeiriad yn un dilys.',
+Cyn y gellir anfon unrhywbeth arall at y cyfeiriad hwnnw rhaid i chi ddilyn y cyfarwyddiadau yn yr e-bost er mwyn cadarnhau mai chi sydd berchen y cyfeiriad hwnnw.',
 'throttled-mailpassword' => "Anfonwyd e-bost atoch eisoes i'ch atgoffa o'ch cyfrinair, a hynny yn ystod y $1 {{PLURAL:$1|awr}} diwethaf.
 Er mwyn rhwystro camddefnydd, dim ond un e-bost i'ch atgoffa o'ch cyfrinair gaiff ei anfon bob yn $1 {{PLURAL:$1|awr}}.",
 'mailerror' => 'Gwall wrth ddanfon yr e-bost: $1',
 'acct_creation_throttle_hit' => "Mae ymwelwyr sy'n defnyddio'ch cyfeiriad IP wedi creu $1 {{PLURAL:$1|cyfrif|cyfrif|gyfrif|chyfrif|chyfrif|cyfrif}} yn ystod y diwrnod diwethaf, sef y mwyafswm a ganiateir mewn diwrnod.
 Felly ni chaiff defnyddwyr sy'n defnyddio'r cyfeiriad IP hwn greu rhagor o gyfrifon ar hyn o bryd.",
 'emailauthenticated' => 'Cadarnhawyd eich cyfeiriad e-bost am $3 ar $2.',
-'emailnotauthenticated' => "Nid yw eich cyfeiriad e-bost wedi'i ddilysu eto. Ni fydd unrhyw negeseuon e-bost yn cael eu hanfon atoch ar gyfer y nodweddion canlynol.",
+'emailnotauthenticated' => "Nid yw eich cyfeiriad e-bost wedi'i gadarnhau eto. Ni fydd unrhyw negeseuon e-bost yn cael eu hanfon atoch ar gyfer y nodweddion canlynol.",
 'noemailprefs' => "Mae'n rhaid i chi gynnig cyfeiriad e-bost er mwyn i'r nodweddion hyn weithio.",
 'emailconfirmlink' => 'Cadarnhewch eich cyfeiriad e-bost',
 'invalidemailaddress' => 'Ni allwn dderbyn y cyfeiriad e-bost gan fod ganddo fformat annilys. Mewnbynnwch cyfeiriad dilys neu gwagiwch y maes hwnnw, os gwelwch yn dda.',
@@ -898,7 +897,7 @@ Cynigiodd y gweinyddwr a glodd y gronfa ddata y rheswm hwn dros ei chloi: $1",
 Dyma'r cofnod lòg diweddaraf, er gwybodaeth:",
 'semiprotectedpagewarning' => "'''Sylwer:''' Mae'r dudalen hon wedi ei chloi; dim ond defnyddwyr cofrestredig a allant ei golygu.
 Dyma'r cofnod lòg diweddaraf, er gwybodaeth:",
-'cascadeprotectedwarning' => "'''Dalier sylw:''' Mae'r dudalen hon wedi ei diogelu fel nad ond defnyddwyr â galluoedd gweinyddwyr sy'n gallu ei newid, oherwydd ei bod yn rhan o'r {{PLURAL:$1|dudalen ganlynol|dudalen ganlynol|tudalennau canlynol|tudalennau canlynol|tudalennau canlynol|tudalennau canlynol}} sydd wedi {{PLURAL:$1|ei sgydol-ddiogelu|ei sgydol-ddiogelu|eu sgydol-diogelu}}.",
+'cascadeprotectedwarning' => "'''Dalier sylw:''' Mae'r dudalen hon wedi ei diogelu fel nad ond defnyddwyr â galluoedd gweinyddwyr sy'n gallu ei newid, oherwydd ei bod yn rhan o'r {{PLURAL:$1|dudalen ganlynol|dudalen ganlynol|tudalennau canlynol}} sydd wedi {{PLURAL:$1|ei sgydol-ddiogelu|ei sgydol-ddiogelu|eu sgydol-diogelu}}.",
 'titleprotectedwarning' => "'''RHYBUDD:  Mae'r dudalen hon wedi ei chloi; dim ond rhai defnyddwyr sydd â'r [[Special:ListGroupRights|gallu]] i'w chreu.'''
 Dyma'r cofnod lòg diweddaraf, er gwybodaeth:",
 'templatesused' => 'Defnyddir y {{PLURAL:$1|nodyn hwn|nodyn hwn|nodiadau hyn|nodiadau hyn|nodiadau hyn|nodiadau hyn}} yn y dudalen hon:',
@@ -1059,18 +1058,19 @@ Serch hyn, gallwch eu cymharu o hyd; cewch weld y manylion ar y [{{fullurl:{{#Sp
 Fe fydd gweinyddwyr eraill {{SITENAME}} o hyd yn gallu gweld yr hyn a guddiwyd. Fe allant ei ddatguddio trwy ddefnyddio'r dudalen arbennig hon, cyhyd ag nad oes cyfyngiadau ychwanegol wedi eu gosod.",
 'revdelete-confirm' => "Byddwch gystal â chadarnhau eich bod yn bwriadu gwneud hyn, eich bod yn deall yr effaith a gaiff, a'ch bod yn ei wneud yn ôl y [[{{MediaWiki:Policy-url}}|y polisi]].",
 'revdelete-suppress-text' => "'''Dim ond''' yn yr achosion sy'n dilyn y dylech fentro cuddio gwybodaeth:
+* Gwybodaeth a all fod yn enllib
 * Gwybodaeth bersonol anaddas
 *: ''cyfeiriad cartref, rhif ffôn, rhif yswiriant cenedlaethol, ayb.''",
 'revdelete-legend' => 'Gosod cyfyngiadau ar y gallu i weld',
-'revdelete-hide-text' => 'Cuddio testun y diwygiad',
+'revdelete-hide-text' => 'Testun y diwygiad',
 'revdelete-hide-image' => 'Cuddio cynnwys y ffeil',
 'revdelete-hide-name' => "Cuddio'r weithred a'r targed",
-'revdelete-hide-comment' => 'Cuddio sylwad golygu',
-'revdelete-hide-user' => 'Cuddio enw defnyddiwr/IP y golygydd',
+'revdelete-hide-comment' => 'Sylw golygu',
+'revdelete-hide-user' => 'Enw defnyddiwr/IP y golygydd',
 'revdelete-hide-restricted' => 'Gosod y cyfyngiadau gweld data ar weinyddwyr yn ogystal ag eraill',
 'revdelete-radio-same' => '(peidier â newid)',
-'revdelete-radio-set' => 'Cuddier',
-'revdelete-radio-unset' => 'Na chuddier',
+'revdelete-radio-set' => 'Cudd',
+'revdelete-radio-unset' => 'Gweladwy',
 'revdelete-suppress' => 'Atal data oddi wrth Weinyddwyr yn ogystal ag eraill',
 'revdelete-unsuppress' => "Tynnu'r cyfyngiadau ar y golygiadau a adferwyd",
 'revdelete-log' => 'Rheswm:',
@@ -1226,8 +1226,7 @@ Cofiwch y gall mynegeion Google o gynnwys {{SITENAME}} fod ar ei hôl hi.",
 'preferences' => 'Dewisiadau',
 'mypreferences' => 'Dewisiadau',
 'prefs-edits' => 'Nifer y golygiadau:',
-'prefsnologin' => 'Nid ydych wedi mewngofnodi',
-'prefsnologintext' => 'Rhaid i chi <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} fewngofnodi]</span> er mwyn gosod eich dewisiadau defnyddiwr.',
+'prefsnologintext2' => 'Mae angen $1 er mwyn gosod eich dewisiadau personol.',
 'changepassword' => 'Newid y cyfrinair',
 'prefs-skin' => 'Gwedd',
 'skin-preview' => 'Rhagolwg',
@@ -1526,6 +1525,9 @@ Mae'r wybodaeth hon ar gael i'r cyhoedd.",
 'recentchanges-label-minor' => 'Mân olygiad',
 'recentchanges-label-bot' => 'Golygwyd gan fot',
 'recentchanges-label-unpatrolled' => "Nid yw'r golygiad hwn wedi derbyn ymweliad patrôl eto",
+'recentchanges-label-plusminus' => "Newidiodd maint y dudalen o'r nifer hwn o feitiau",
+'recentchanges-legend-newpage' => '(gweler hefyd [[Special:NewPages|restr y tudalennau newydd]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Isod mae'r '''$1''' newid diweddaraf yn ystod y {{PLURAL:$2|diwrnod|diwrnod|deuddydd|tridiau|'''$2''' diwrnod|'''$2''' diwrnod}} diwethaf, hyd at $5, $4.",
 'rcnotefrom' => "Isod rhestrir pob newid ers '''$2''' (hyd at '''$1''' ohonynt).",
 'rclistfrom' => 'Dangos newidiadau newydd, gan ddechrau ers $1',
@@ -2245,7 +2247,7 @@ Cysylltu â\'r golygydd:
 e-bost: $PAGEEDITOR_EMAIL
 wici: $PAGEEDITOR_WIKI
 
-Os bydd mwy o drin a thrafod ar y dudalen cyn i chi ymweld â hi, ni chewch ragor o negeseuon hysbysu. Nodwn bod modd i chi ailosod y fflagiau hysbysu ar eich rhestr wylio, ar gyfer y tudalennau rydych yn eu gwylio.
+Os bydd mwy o drin a thrafod ar y dudalen cyn i chi ymweld â hi tra eich bod wedi mewngofnodi, ni chewch ragor o negeseuon hysbysu. Nodwn bod modd i chi ailosod y fflagiau hysbysu ar eich rhestr wylio, ar gyfer y tudalennau rydych yn eu gwylio.
 
              Sustem hysbysu {{SITENAME}}
 
@@ -2451,7 +2453,7 @@ $1',
 
 # Contributions
 'contributions' => "{{GENDER:$1|Cyfraniadau'r defnyddiwr}}",
-'contributions-title' => "Cyfraniadau'r defnyddiwr am $1",
+'contributions-title' => "Cyfraniadau'r defnyddiwr $1",
 'mycontris' => 'Cyfraniadau',
 'contribsub2' => 'Gan {{GENDER:$3|$1}} ($2)',
 'nocontribs' => "Heb ddod o hyd i newidiadau gyda'r meini prawf hyn.",
@@ -2766,7 +2768,7 @@ Yn achos yr ail ddewis, mae modd defnyddio cyswllt, e.e. [[{{#Special:Export}}/{
 'allmessagesdefault' => 'Testun rhagosodedig',
 'allmessagescurrent' => 'Testun cyfredol',
 'allmessagestext' => "Dyma restr o'r holl negeseuon yn y parth MediaWici.
-Os ydych am gyfrannu at y gwaith o gyfieithu ar gyfer holl prosiectau MediaWiki ar y cyd, mae croeso i chi ymweld â [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net].",
+Os ydych am gyfrannu at y gwaith o gyfieithu ar gyfer holl prosiectau MediaWiki ar y cyd, mae croeso i chi ymweld â [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net].",
 'allmessagesnotsupportedDB' => "Nid yw '''{{ns:special}}:PobNeges''' yn cael ei gynnal gan fod '''\$wgUseDatabaseMessages''' wedi ei ddiffodd.",
 'allmessages-filter-legend' => 'Hidl',
 'allmessages-filter' => 'Hidlo yn ôl eu cyflwr addasu:',
@@ -2931,7 +2933,7 @@ Mae ffolder dros dro yn eisiau.',
 Gellir ychwanegu rheswm dros y dadwneud yn y crynodeb.',
 'tooltip-preferences-save' => 'Rhodder y dewisiadau ar gadw',
 'tooltip-summary' => 'Rhowch grynodeb byr',
-'tooltip-iwiki' => '$1 - $2',
+'interlanguage-link-title' => '$1 - $2',
 
 # Metadata
 'notacceptable' => "Dydy gweinydd y wici ddim yn medru rhoi'r data mewn fformat darllenadwy i'ch cleient.",
@@ -2957,6 +2959,8 @@ Achos hyn yn fwy na thebyg yw presenoldeb cysylltiad i wefan ar y rhestr wahardd
 'spam_reverting' => 'Wedi adfer y diwygiad diweddaraf na sydd yn cynnwys cysylltiadau i $1',
 'spam_blanking' => 'Roedd cysylltiadau i $1 gan bob golygiad, felly gwacawyd y dudalen',
 'spam_deleting' => 'Roedd pob diwygiad yn cynnwys cysylltiadau â $1, felly fe ddilëwyd y dudalen',
+'simpleantispam-label' => "Prawf gwrth-sbam.
+'''Peidiwch''' â llenwi hwn!",
 
 # Info page
 'pageinfo-title' => 'Manylion "$1"',
@@ -2970,6 +2974,7 @@ Achos hyn yn fwy na thebyg yw presenoldeb cysylltiad i wefan ar y rhestr wahardd
 'pageinfo-length' => 'Hyd y dudalen (beitiau)',
 'pageinfo-article-id' => 'ID y dudalen',
 'pageinfo-language' => 'Iaith cynnwys y dudalen',
+'pageinfo-content-model' => 'Ffurf cynnwys y dudalen',
 'pageinfo-robot-policy' => 'Rhestrwyd gan robot',
 'pageinfo-robot-index' => 'Caniateir',
 'pageinfo-robot-noindex' => 'Gwrthodedig',
@@ -3053,7 +3058,7 @@ Mae'n bosib y bydd eich cyfrifiadur yn cael ei danseilio wrth ddefnyddio'r ffeil
 'svg-long-desc' => 'Ffeil SVG, maint mewn enw $1 × $2 picsel, maint y ffeil: $3',
 'svg-long-desc-animated' => 'Ffeil SVG animeiddiedig, maint mewn enw $1 × $2 picsel, maint y ffeil: $3',
 'svg-long-error' => 'Ffeil SVG annilys: $1',
-'show-big-image' => 'Maint llawn',
+'show-big-image' => 'Y ffeil gwreiddiol',
 'show-big-image-preview' => 'Maint y rhagolwg: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Datrysiad arall|Datrysiad arall|Datrysiadau eraill|Datrysiadau eraill|Datrysiadau eraill|Datrysiadau eraill}}: $1.',
 'show-big-image-size' => '$1 × $2 picsel',
@@ -3523,7 +3528,7 @@ Cuddir y meysydd eraill trwy ragosodiad.
 
 # External editor support
 'edit-externally' => 'Golygwch y ffeil gyda rhaglen allanol',
-'edit-externally-help' => '(Gwelwch y [//www.mediawiki.org/wiki/Manual:External_editors cyfarwyddiadau gosod] am fwy o wybodaeth)',
+'edit-externally-help' => '(Gwelwch y [https://www.mediawiki.org/wiki/Manual:External_editors cyfarwyddiadau gosod] am fwy o wybodaeth)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'holl',
@@ -3611,6 +3616,9 @@ Cadarnhewch eich bod chi wir am ail-greu'r dudalen.",
 'confirm-unwatch-button' => 'Iawn',
 'confirm-unwatch-top' => 'Tynner y dudalen hon oddi ar eich rhestr wylio?',
 
+# Separators for various lists, etc.
+'quotation-marks' => "'$1'",
+
 # Multipage image navigation
 'imgmultipageprev' => "← i'r dudalen gynt",
 'imgmultipagenext' => "i'r dudalen nesaf →",
@@ -3695,7 +3703,7 @@ Gallwch hefyd [[Special:EditWatchlist|ddefnyddio\'r rhestr arferol]].',
 'version-hook-subscribedby' => 'Tanysgrifwyd gan',
 'version-version' => '(Fersiwn $1)',
 'version-license' => 'Trwydded',
-'version-poweredby-credits' => "Mae'r wici hwn wedi'i nerthu gan '''[//www.mediawiki.org/ MediaWiki]''', hawlfraint © 2001 - $1 $2.",
+'version-poweredby-credits' => "Mae'r wici hwn wedi'i nerthu gan '''[https://www.mediawiki.org/ MediaWiki]''', hawlfraint © 2001 - $1 $2.",
 'version-poweredby-others' => 'eraill',
 'version-poweredby-translators' => 'cyfieithwyr translatewiki.net',
 'version-credits-summary' => 'Hoffem gydnabod cyfraniad y bobl canlynol i [[Special:Version|MediaWiki]].',
@@ -3714,7 +3722,9 @@ Dylech fod wedi derbyn [{{SERVER}}{{SCRIPTPATH}}/COPYING gopi o GNU General Publ
 # Special:Redirect
 'redirect' => 'Ailgyfeirio yn ôl enw ffeil, ID defnyddiwr neu ID diwygiad tudalen',
 'redirect-legend' => 'Ailgyfeirio i ffeil neu dudalen',
-'redirect-summary' => "Mae'r dudalen arbennig hon yn arwain at ffeil (o roi enw'r ffeil), at dudalen (o roi ID rhyw ddidwygiad o'r dudalen), neu at dudalen defnyddiwr (o roi rhif y defnyddiwr).",
+'redirect-summary' => "Mae'r dudalen arbennig hon yn ailgyfeirio at ffeil (o roi enw'r ffeil), at dudalen (o roi ID rhyw ddiwygiad o'r dudalen), neu at dudalen defnyddiwr (o roi rhif ID y defnyddiwr).
+Defnydd: 
+[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], neu [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Ati',
 'redirect-lookup' => 'Chwilio drwy:',
 'redirect-value' => 'Chwilio am:',
@@ -3736,10 +3746,9 @@ Dylech fod wedi derbyn [{{SERVER}}{{SCRIPTPATH}}/COPYING gopi o GNU General Publ
 
 # Special:SpecialPages
 'specialpages' => 'Tudalennau arbennig',
-'specialpages-note' => '----
-* Tudalennau arbennig ar gael i bawb.
-* <span class="mw-specialpagerestricted">Tudalennau arbennig cyfyngedig.</span>
-* <span class="mw-specialpagecached">Tudalennau arbennig wedi eu cynhyrchu o\'r celc (gallant fod heb eu harfer rhagor).</span>',
+'specialpages-note-top' => 'Allwedd',
+'specialpages-note' => '* Tudalennau arbennig ar gael i bawb.
+* <span class="mw-specialpagerestricted">Tudalennau arbennig cyfyngedig.</span>',
 'specialpages-group-maintenance' => 'Adroddiadau cynnal a chadw',
 'specialpages-group-other' => 'Eraill',
 'specialpages-group-login' => 'Mewngofnodi / creu cyfrif',
@@ -3951,4 +3960,14 @@ Dylech fod wedi derbyn [{{SERVER}}{{SCRIPTPATH}}/COPYING gopi o GNU General Publ
 'limitreport-expansiondepth' => 'Uchafswm dyfnder yr ehangu',
 'limitreport-expensivefunctioncount' => "Nifer y ffwythiannau dosrannu sy'n dreth ar adnoddau",
 
+# Special:ExpandTemplates
+'expandtemplates' => "Ehangu'r nodynnau",
+'expand_templates_input' => 'Cynnwys y mewnbwn:',
+'expand_templates_output' => 'Y canlyniad',
+'expand_templates_xml_output' => 'Yr allbwn XML',
+'expand_templates_ok' => 'Iawn',
+'expand_templates_remove_comments' => 'Peidio â dangos sylwadau',
+'expand_templates_remove_nowiki' => "Cuddio'r tagiau <nowiki> wrth ehangu",
+'expand_templates_preview' => 'Rhagolwg',
+
 );
index d090089..175e3c8 100644 (file)
@@ -35,6 +35,7 @@
  * @author Morten LJ
  * @author Najami
  * @author Nghtwlkr
+ * @author Overlaet
  * @author Palnatoke
  * @author Peter Alberti
  * @author Peter Andersen
@@ -42,6 +43,7 @@
  * @author Qaqqalik
  * @author Remember the dot
  * @author Sarrus
+ * @author Shirayuki
  * @author Simeondahl
  * @author Sir48
  * @author Slomox
@@ -86,7 +88,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Ældste_sider' ),
        'Blankpage'                 => array( 'Tom_Side' ),
        'Block'                     => array( 'Bloker_adresse' ),
-       'Blockme'                   => array( 'Proxyspærring' ),
        'Booksources'               => array( 'ISBN-søgning' ),
        'BrokenRedirects'           => array( 'Defekte_omdirigeringer' ),
        'Categories'                => array( 'Kategorier' ),
@@ -97,7 +98,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Opret_konto' ),
        'Deadendpages'              => array( 'Blindgydesider' ),
        'DeletedContributions'      => array( 'Slettede_bidrag' ),
-       'Disambiguations'           => array( 'Flertydige_sider' ),
        'DoubleRedirects'           => array( 'Dobbelte_omdirigeringer' ),
        'Emailuser'                 => array( 'E-mail' ),
        'Export'                    => array( 'Eksporter' ),
@@ -361,7 +361,7 @@ $messages = array(
 'vector-action-move' => 'Flyt',
 'vector-action-protect' => 'Beskyt',
 'vector-action-undelete' => 'Gendan',
-'vector-action-unprotect' => 'Ændre beskyttelse',
+'vector-action-unprotect' => 'Ændr beskyttelse',
 'vector-simplesearch-preference' => 'Aktivér forenklet søgefelt (kun Vector-udseendet)',
 'vector-view-create' => 'Opret',
 'vector-view-edit' => 'Redigér',
@@ -383,7 +383,7 @@ $messages = array(
 'searcharticle' => 'Gå til',
 'history' => 'Historik',
 'history_short' => 'Historik',
-'updatedmarker' => '(ændret)',
+'updatedmarker' => 'opdateret siden sidste besøg',
 'printableversion' => 'Udskriftsvenlig udgave',
 'permalink' => 'Permanent henvisning',
 'print' => 'Udskriv',
@@ -398,9 +398,9 @@ $messages = array(
 'undelete_short' => 'Fortryd sletning af {{PLURAL:$1|én version|$1 versioner}}',
 'viewdeleted_short' => 'Vis {{PLURAL:$1|en slettet redigering|$1 slettede redigeringer}}',
 'protect' => 'Beskyt',
-'protect_change' => 'ændre',
+'protect_change' => 'ændr',
 'protectthispage' => 'Beskyt side',
-'unprotect' => 'Ændre beskyttelse',
+'unprotect' => 'Ændr beskyttelse',
 'unprotectthispage' => 'Ændre beskyttelsen af denne side',
 'newpage' => 'Ny side',
 'talkpage' => 'Diskussion',
@@ -467,12 +467,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Hentet fra "$1"',
 'youhavenewmessages' => 'Du har $1 ($2).',
-'newmessageslink' => 'nye beskeder',
-'newmessagesdifflink' => 'ændringer siden sidste visning',
 'youhavenewmessagesfromusers' => 'Du har $1 fra {{PLURAL:$3|en anden bruger| $3 brugere}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du har $1 fra mange brugere ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|en ny besked|nye beskeder}}',
-'newmessagesdifflinkplural' => 'seneste {{PLURAL:$1|ændring|ændringer}}',
+'newmessageslinkplural' => '{{PLURAL:$1|en ny besked|999=nye beskeder}}',
+'newmessagesdifflinkplural' => 'seneste {{PLURAL:$1|ændring|999=ændringer}}',
 'youhavenewmessagesmulti' => 'Du har nye beskeder på $1',
 'editsection' => 'redigér',
 'editold' => 'redigér',
@@ -532,9 +530,9 @@ Dette kan indikere en fejl i softwaren.',
 'laggedslavemode' => "'''Bemærk:''' Den viste side indeholder muligvis ikke de nyeste ændringer.",
 'readonly' => 'Databasen er skrivebeskyttet',
 'enterlockreason' => 'Skriv en begrundelse for skrivebeskyttelsen, med samt en vurdering af, hvornår skrivebeskyttelsen ophæves igen',
-'readonlytext' => 'Databasen er midlertidigt skrivebeskyttet. Forsøg venligst senere.
+'readonlytext' => 'Databasen er i øjeblikket låst for nye poster og andre ændringer, sandsynligvis for rutinemæssig databasevedligeholdelse, hvorefter den vil være tilbage til normal.
 
-Årsag til spærringen: $1',
+Den administrator som har låst, gav denne forklaring: $1',
 'missing-article' => 'Databasen burde indeholde siden "$1" $2, men det gør den ikke.
 
 Den sandsynlige årsag er at du har fulgt et forældet link til en forskel eller en gammel version af en side der er blevet slettet.
@@ -580,7 +578,7 @@ Forespørgsel: $2',
 'viewsourcetext' => 'Du kan se og kopiere kildekoden til siden:',
 'viewyourtext' => "Du kan se og kopiere kildekoden for '''dine redigeringer''' til denne side:",
 'protectedinterface' => 'Denne side indeholder teksten i brugergrænsefladen til softwaren på denne wiki, og er beskyttet for at forhindre misbrug.
-Hvis du vil tilføje eller ændre oversættelser til alle wiki-websteder, brug venligst [//translatewiki.net/ translatewiki.net], MediaWiki lokalisering projektet.',
+Hvis du vil tilføje eller ændre oversættelser for alle wiki-websteder, så brug venligst [//translatewiki.net/ translatewiki.net], projektet for oversættelse af MediaWiki.',
 'editinginterface' => "'''Advarsel:''' Du redigerer en side som bruges i programmets grænseflade. Ændringer på denne side vil påvirke udseendet af grænsefladen for andre brugere af denne wiki.
 For at tilføje eller ændre oversættelser på alle wikier bedes du benytte [//translatewiki.net/ translatewiki.net], projektet for oversættelse af MediaWiki.",
 'cascadeprotected' => 'Denne side er skrivebeskyttet, da den er indeholdt i nedenstående {{PLURAL:$1|side|sider}}, som er skrivebeskyttet med tilvalg af "nedarvende sidebeskyttelse":
@@ -590,17 +588,18 @@ $2',
 'customjsprotected' => 'Du har ikke tilladelse til at redigere denne JavaScript-side, da den indeholder en anden brugers personlige indstillinger.',
 'mycustomcssprotected' => 'Du har ikke rettigheder til at redigere denne CSS-side.',
 'mycustomjsprotected' => 'Du har ikke rettigheder til at redigere denne JavaScript-side.',
-'myprivateinfoprotected' => 'Du har ikke tilladelse til at redigere dine private oplysninger.',
-'mypreferencesprotected' => 'Du har ikke tilladelse til at redigere dine præferencer.',
+'myprivateinfoprotected' => 'Du har ikke rettigheder til at redigere dine private oplysninger.',
+'mypreferencesprotected' => 'Du har ikke rettigheder til at redigere dine indstillinger.',
 'ns-specialprotected' => 'Sider i navnerummet {{ns:special}} kan ikke redigeres.',
-'titleprotected' => "Dette sidenavn er beskyttet mod oprettelse af [[User:$1|$1]]. Begrundelsen for beskyttelsen er ''$2''.",
+'titleprotected' => 'Dette sidenavn er blevet beskyttet mod oprettelse af [[User:$1|$1]]. Begrundelsen for beskyttelsen er "\'\'$2\'\'".',
 'filereadonlyerror' => 'Ude af stand til at redigere filen "$1", fordi fildatabasen "$2" er skrivebeskyttet.
 
 Administratoren, som skrivebeskyttede den, gav følgende begrundelse: "$3".',
 'invalidtitle-knownnamespace' => 'Ugyldig titel med navnerummet "$2" og teksten "$3"',
 'invalidtitle-unknownnamespace' => 'Ugyldig titel med ukendt navnerum nummer $1 og tekst "$2"',
 'exception-nologin' => 'Ikke logget på',
-'exception-nologin-text' => 'Denne side eller handling kræver, at du er logget på denne wiki.',
+'exception-nologin-text' => 'Du skal [[Special:Userlogin|logge på]] for at få adgang til denne side eller handling.',
+'exception-nologin-text-manual' => 'Du skal $1 for at få adgang til denne side eller handling.',
 
 # Virus scanner
 'virus-badscanner' => "Konfigurationsfejl: ukendt virus-scanner: ''$1''",
@@ -621,10 +620,10 @@ Glem ikke at ændre dine [[Special:Preferences|{{SITENAME}} indstillinger]].',
 'yourpassword' => 'Din adgangskode:',
 'userlogin-yourpassword' => 'Adgangskode',
 'userlogin-yourpassword-ph' => 'Indtast din adgangskode',
-'createacct-yourpassword-ph' => 'Indtast kodeord',
+'createacct-yourpassword-ph' => 'Indtast en adgangskode',
 'yourpasswordagain' => 'Gentag adgangskode',
-'createacct-yourpasswordagain' => 'Bekræft kodeord',
-'createacct-yourpasswordagain-ph' => 'Indtast kodeord igen',
+'createacct-yourpasswordagain' => 'Bekræft adgangskode',
+'createacct-yourpasswordagain-ph' => 'Indtast adgangskode igen',
 'remembermypassword' => 'Husk mit brugernavn i denne browser (højst $1 {{PLURAL:$1|dag|dage}})',
 'userlogin-remembermypassword' => 'Husk mig',
 'userlogin-signwithsecure' => 'Brug sikker forbindelse',
@@ -647,7 +646,7 @@ Glem ikke at ændre dine [[Special:Preferences|{{SITENAME}} indstillinger]].',
 'gotaccount' => 'Har du allerede en konto? $1.',
 'gotaccountlink' => 'Log på',
 'userlogin-resetlink' => 'Har du glemt dine login oplysninger?',
-'userlogin-resetpassword-link' => 'Nulstil din adgangskode',
+'userlogin-resetpassword-link' => 'Glemt din adgangskode?',
 'helplogin-url' => 'Help:Logge på',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hjælp til at logge på]]',
 'userlogin-loggedin' => 'Du er allerede logget på som {{GENDER:$1|$1}}.
@@ -655,19 +654,19 @@ Brug formularen nedenfor til at logge på som en anden bruger.',
 'userlogin-createanother' => 'Opret en anden konto',
 'createacct-join' => 'Indtast dine oplysninger nedenfor.',
 'createacct-another-join' => 'Angiv den nye kontos oplysninger nedenfor.',
-'createacct-emailrequired' => 'Mailadresse',
-'createacct-emailoptional' => 'Mailadresse (valgfri)',
-'createacct-email-ph' => 'Indtast din mailadresse',
+'createacct-emailrequired' => 'E-mailadresse',
+'createacct-emailoptional' => 'E-mailadresse (valgfri)',
+'createacct-email-ph' => 'Indtast din e-mailadresse',
 'createacct-another-email-ph' => 'Indtast e-mailadresse',
 'createaccountmail' => 'Brug en midlertidig tilfældig adgangskode og send den til den angivne e-mailadresse',
-'createacct-realname' => 'Dit rigtige navn',
+'createacct-realname' => 'Dit rigtige navn (valgfrit)',
 'createaccountreason' => 'Begrundelse:',
 'createacct-reason' => 'Årsag',
-'createacct-reason-ph' => 'Hvorfor vil du oprette endnu en konto',
+'createacct-reason-ph' => 'Hvorfor du vil oprette endnu en konto',
 'createacct-captcha' => 'Sikkerhedskontrol',
 'createacct-imgcaptcha-ph' => 'Indtast venligst ovenstående tekst',
 'createacct-submit' => 'Opret din konto',
-'createacct-another-submit' => 'Oprette en anden konto',
+'createacct-another-submit' => 'Opret en anden konto',
 'createacct-benefit-heading' => '{{SITENAME}} laves af mennesker som dig.',
 'createacct-benefit-body1' => '{{PLURAL:$1|redigering|redigeringer}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|side|sider}}',
@@ -678,7 +677,7 @@ Vælg venligst et andet brugernavn.',
 'loginerror' => 'Logon mislykket',
 'createacct-error' => 'Fejl ved kontooprettelse',
 'createaccounterror' => 'Kunne ikke oprette brugerkonto: $1',
-'nocookiesnew' => 'Din brugerkonto er nu oprettet, men du er ikke logget på. {{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Vær venlig at slå cookies til, og derefter kan du logge på med dit nye brugernavn og kodeord.',
+'nocookiesnew' => 'Din brugerkonto er nu oprettet, men du er ikke logget på. {{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Vær venlig at slå cookies til, og derefter kan du logge på med dit nye brugernavn og adgangskode.',
 'nocookieslogin' => '{{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Slå dem venligst til og prøv igen.',
 'nocookiesfornew' => 'Denne brugerkonto er ikke oprettet, da vi ikke kunne bekræfte dens kilde.
 Sørg for, at du har aktivereret cookies, genindlæs siden og prøv igen.',
@@ -690,18 +689,18 @@ Der skelnes mellem store og bogstaver i brugernavne.
 Kontrollér stavemåden, eller [[Special:UserLogin/signup|opret en ny konto]].',
 'nosuchusershort' => 'Der er ingen bruger ved navn "$1". Tjek din stavning.',
 'nouserspecified' => 'Angiv venligst et brugernavn.',
-'login-userblocked' => 'Denne bruger er blokeret. Login er ikke tilladt',
+'login-userblocked' => 'Denne bruger er blokeret. Det er ikke tilladt at logge på.',
 'wrongpassword' => 'Den indtastede adgangskode var forkert. Prøv igen.',
-'wrongpasswordempty' => 'Du glemte at indtaste password. Prøv igen.',
+'wrongpasswordempty' => 'Du glemte at indtaste adgangskode. Prøv igen.',
 'passwordtooshort' => 'Adgangskoden skal mindst være på $1 {{PLURAL:$1|tegn|tegn}}.',
-'password-name-match' => 'Kodeordet må ikke være det samme som brugernavnet.',
+'password-name-match' => 'Adgangskoden må ikke være det samme som brugernavnet.',
 'password-login-forbidden' => 'Brugen af dette brugernavn og adgangskode er blevet forbudt.',
-'mailmypassword' => 'Send nyt password',
-'passwordremindertitle' => 'Nyt password til {{SITENAME}}',
+'mailmypassword' => 'Send ny adgangskode',
+'passwordremindertitle' => 'Ny midlertidig adgangskode til {{SITENAME}}',
 'passwordremindertext' => 'Nogen (sandsynligvis dig, fra IP-adressen $1)
 har bedt om at vi sender dig en ny adgangskode til at logge på {{SITENAME}} ($4).
 En midlertidig adgangskode for bruger "$2" er blevet lavet, den er "$3".
-Hvis dette var din mening, skal du logge ind og vælge en ny adgangskode nu.
+Hvis dette var din mening, skal du logge  og vælge en ny adgangskode nu.
 Din midlertidige adgangskode vil udløbe om {{PLURAL:$5|en dag|$5 dage}}.
 
 Hvis en anden har bestilt den nye adgangskode, eller hvis du er kommet i tanke om din gamle adgangskode og ikke længere vil ændre den,
@@ -710,26 +709,27 @@ kan du bare ignorere denne e-mail og fortsætte med at bruge din gamle adgangsko
 'noemailcreate' => 'Du skal angive en gyldig e-mailadresse',
 'passwordsent' => 'En ny adgangskode er sendt til e-mailadressen, som er registreret for "$1".
 Du bør logge på og ændre din adgangskode straks efter du har modtaget e-mailen.',
-'blocked-mailpassword' => 'Din IP-adresse er spærret for ændring af sider. For at forhindre misbrug, er det heller ikke muligt, at bestille et nyt password.',
-'eauthentsent' => 'En bekræftelsesmail er sendt til den angivne e-mailadresse.
+'blocked-mailpassword' => 'Din IP-adresse er spærret for ændring af sider. For at forhindre misbrug, er det heller ikke muligt, at bestille en ny adgangskode.',
+'eauthentsent' => 'En e-mailbekræftelse er sendt til den angivne e-mailadresse.
 
-Før en e-mail kan modtages af andre brugere af {{SITENAME}}-mailfunktionen, skal adressen og dens tilhørsforhold til denne bruger bekræftes. Følg venligst anvisningerne i denne mail.',
+Før flere e-mails bliver sendt til kontoen, skal du følge instruktionerne i e-mailen, for at bekræfte at kontoen rent faktisk er din.',
 'throttled-mailpassword' => 'Indenfor {{PLURAL:$1|den sidste time|de sidste $1 timer}} er der allerede sendt en ny adgangskode. For at forhindre misbrug af funktionen, kan der kun bestilles en ny adgangskode én gang for hver {{PLURAL:$1|time|$1 timer}}.',
 'mailerror' => 'Fejl ved afsendelse af e-mail: $1',
 'acct_creation_throttle_hit' => 'Besøgende med samme IP-adresse som dig har oprettet {{PLURAL:$1|en konto|$1 kontoer}} det sidste døgn, og det er ikke tilladt at oprette flere.
 Derfor kan besøgende ikke oprette flere kontoer fra denne IP-adresse i øjeblikket.',
-'emailauthenticated' => 'Din e-mailadresse blev bekræftet $2 $3.',
-'emailnotauthenticated' => 'Din e-mail-adresse er endnu ikke bekræftet og de avancerede e-mail-funktioner er slået fra indtil bekræftelse har fundet sted (d.u.a.). Log ind med den midlertidige adgangskode, der er blevet sendt til dig, for at bekræfte, eller bestil et nyt på loginsiden.',
+'emailauthenticated' => 'Din e-mailadresse blev bekræftet den $2 kl. $3.',
+'emailnotauthenticated' => 'Din e-mailadresse er endnu ikke bekræftet.
+Ingen e-mail vil blive sendt for de følgende funktioner.',
 'noemailprefs' => 'Angiv en e-mailadresse, så følgende funktioner er til rådighed.',
 'emailconfirmlink' => 'Bekræft din e-mailadresse',
 'invalidemailaddress' => 'E-mailadressen kan ikke accepteres da den tilsyneladende har et ugyldigt format. Skriv venligst en e-mailadresse med et korrekt format eller tøm feltet.',
 'cannotchangeemail' => 'De e-mailadresser, der er tilknyttet brugerkontoer, kan ikke ændres på denne wiki.',
-'emaildisabled' => 'Denne hjemmeside kan ikke sende emails.',
+'emaildisabled' => 'Denne hjemmeside kan ikke sende e-mails.',
 'accountcreated' => 'Brugerkonto oprettet',
 'accountcreatedtext' => 'Brugerkontoen for [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|diskussion]]) er oprettet.',
 'createaccount-title' => 'Opret brugerkonto på {{SITENAME}}',
-'createaccount-text' => 'Nogen har oprettet en konto for din e-post-adresse på {{SITENAME}} ($4) med navnet "$2". Adgangskoden er "$3".
-Du opfordres til at logge ind og ændre adgangskoden med det samme.
+'createaccount-text' => 'Nogen har oprettet en konto for din e-mailadresse på {{SITENAME}} ($4) med navnet "$2". Adgangskoden er "$3".
+Du opfordres til at logge  og ændre adgangskoden med det samme.
 
 Du kan ignorere denne besked hvis kontoen blev oprettet ved en fejl.',
 'usernamehasherror' => 'Brugernavn må ikke indeholde #',
@@ -737,18 +737,18 @@ Du kan ignorere denne besked hvis kontoen blev oprettet ved en fejl.',
 Vent venligst $1, før du prøver igen.',
 'login-abort-generic' => 'Det lykkedes dig ikke at logge på - afbrudt',
 'loginlanguagelabel' => 'Sprog: $1',
-'suspicious-userlogout' => 'Din anmodning om at logge ud blev nægtet, fordi det ser ud som den blev sendt af en ødelagt browser eller caching proxy.',
+'suspicious-userlogout' => 'Din anmodning om at logge af blev nægtet, fordi det ser ud som den blev sendt af en ødelagt browser eller caching proxy.',
 'createacct-another-realname-tip' => 'Angivelse af rigtigt navn er valgfrit.
 Hvis du vælger at oplyse dit navn, vil det blive brugt til at tilskrive dig dit arbejde.',
 
 # Email sending
-'php-mail-error-unknown' => "Ukendt fejl i PHP's mail()-funtion",
+'php-mail-error-unknown' => 'Ukendt fejl i PHP funktionen mail()',
 'user-mail-no-addy' => 'Forsøgte at sende e-mail uden en e-mailadresse',
 'user-mail-no-body' => 'Forsøgte at sende en e-mail med tomt eller urimeligt kort indhold.',
 
 # Change password dialog
 'resetpass' => 'Skift adgangskode',
-'resetpass_announce' => 'Log på med den via e-mail tilsendte password. For at afslutte tilmeldingen, skal du nu vælge et nyt password.',
+'resetpass_announce' => 'Du loggede på med den via e-mail tilsendte adgangskode. For at afslutte tilmeldingen, skal du nu vælge en ny adgangskode.',
 'resetpass_text' => '<!-- Tilføj tekst her -->',
 'resetpass_header' => 'Skift adgangskode',
 'oldpassword' => 'Gammel adgangskode:',
@@ -763,19 +763,19 @@ Hvis du vælger at oplyse dit navn, vil det blive brugt til at tilskrive dig dit
 'resetpass-wrong-oldpass' => 'Ugyldig midlertidig eller gældende adgangskode.
 Du har muligvis allerede skiftet din adgangskode eller anmodet om en ny midlertidig kode.',
 'resetpass-temp-password' => 'Midlertidig adgangskode',
-'resetpass-abort-generic' => 'Ændring af kodeord er blevet afbrudt af udvidelse',
+'resetpass-abort-generic' => 'Ændring af adgangskode er blevet afbrudt af en udvidelse',
 
 # Special:PasswordReset
 'passwordreset' => 'Nulstil adgangskode',
 'passwordreset-text-one' => 'Udfyld denne formular for at nulstille din adgangskode.',
-'passwordreset-text-many' => '{{PLURAL:$1|Udfyld en af felterne nedenfor for at nulstille din adgangskode.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Udfyld et af felterne nedenfor for at nulstille din adgangskode.}}',
 'passwordreset-legend' => 'Nulstil adgangskode',
-'passwordreset-disabled' => 'Nulstilling af kodeord er slået fra på denne wiki.',
+'passwordreset-disabled' => 'Nulstilling af adgangskode er slået fra på denne wiki.',
 'passwordreset-emaildisabled' => 'E-mailfunktioner er slået fra på denne wiki.',
 'passwordreset-username' => 'Brugernavn:',
 'passwordreset-domain' => 'Domæne:',
 'passwordreset-capture' => 'Se den resulterende e-mail?',
-'passwordreset-capture-help' => 'Hvis du krydser dette felt af, vil emailen (med den midlertidige adgangskode) blive vist til dig i tillæg til at blive sendt til brugeren.',
+'passwordreset-capture-help' => 'Hvis du krydser dette felt af, vil e-mailen (med den midlertidige adgangskode) blive vist til dig i tillæg til at blive sendt til brugeren.',
 'passwordreset-email' => 'E-mailadresse:',
 'passwordreset-emailtitle' => 'Kontooplysninger på {{SITENAME}}',
 'passwordreset-emailtext-ip' => 'Nogen (sandsynligvis dig, fra IP-adressen $1) har anmodet om at få nulstillet din adgangskode til {{SITENAME}} ($4). {{PLURAL:$3|Den følgende brugerkonto er associeret|De følgende brugerkonti er associerede}} med denne e-mailadresse:
@@ -799,7 +799,7 @@ Midlertidig adgangskode: $2',
 # Special:ChangeEmail
 'changeemail' => 'Ændre e-mailadresse',
 'changeemail-header' => 'Ændre kontoens e-mailadresse',
-'changeemail-text' => 'Udfyld denne formular for at ændre din e-mailadresse. Du skal indtaste dit kodeord for at bekræfte denne ændring.',
+'changeemail-text' => 'Udfyld denne formular for at ændre din e-mailadresse. Du skal indtaste din adgangskode for at bekræfte denne ændring.',
 'changeemail-no-info' => 'Du skal være logget på for at komme direkte til denne side.',
 'changeemail-oldemail' => 'Nuværende e-mailadresse:',
 'changeemail-newemail' => 'Ny e-mailadresse:',
@@ -816,7 +816,7 @@ Du bør gøre det, hvis du ved et uheld deler dem med nogen, eller hvis din kont
 'resettokens-no-tokens' => 'Der er ingen nøgler at nulstille.',
 'resettokens-legend' => 'Nulstil nøgler',
 'resettokens-tokens' => 'Nøgler:',
-'resettokens-token-label' => '$1(aktuel værdi: $2)',
+'resettokens-token-label' => '$1 (aktuel værdi: $2)',
 'resettokens-watchlist-token' => 'Nøgle for web-feed (Atom/RSS) af [[Special:Watchlist|ændringer af sider på din overvågningsliste]]',
 'resettokens-done' => 'Nøgler er nulstillet.',
 'resettokens-resetbutton' => 'Nulstil valgte nøgler',
@@ -828,16 +828,16 @@ Du bør gøre det, hvis du ved et uheld deler dem med nogen, eller hvis din kont
 'italic_tip' => 'Kursiv tekst',
 'link_sample' => 'Henvisning',
 'link_tip' => 'Intern henvisning',
-'extlink_sample' => 'http://www.example.com Titel på henvisning',
+'extlink_sample' => 'http://www.example.com titel på henvisning',
 'extlink_tip' => 'Ekstern henvisning (husk http:// præfiks)',
 'headline_sample' => 'Tekst til overskrift',
 'headline_tip' => 'Type 2-overskrift',
 'nowiki_sample' => 'Indsæt tekst her som ikke skal wikiformateres',
 'nowiki_tip' => 'Ignorer wikiformatering',
 'image_sample' => 'Eksempel.jpg',
-'image_tip' => 'Indlejret billede',
+'image_tip' => 'Indlejret fil',
 'media_sample' => 'Eksempel.ogg',
-'media_tip' => 'Henvisning til multimediefil',
+'media_tip' => 'Henvisning til fil',
 'sig_tip' => 'Din signatur med tidsstempel',
 'hr_tip' => 'Horisontal linje (brug den sparsomt)',
 
@@ -851,11 +851,11 @@ Du bør gøre det, hvis du ved et uheld deler dem med nogen, eller hvis din kont
 'showpreview' => 'Forhåndsvisning',
 'showlivepreview' => 'Live-forhåndsvisning',
 'showdiff' => 'Vis ændringer',
-'anoneditwarning' => 'Du arbejder uden at være logget på. Istedet for brugernavn vises din IP-adresse i versionshistorikken.',
-'anonpreviewwarning' => "''Du er ikke logget ind. Hvis du gemmer, registreres din IP-adresse i versionshistorikken.''",
-'missingsummary' => "'''Påmindelse:''' Du har ikke angivet en redigeringsbeskrivelse. Hvis du igen trykker på \"Gem\", gemmes ændringerne uden en beskrivelse.",
-'missingcommenttext' => 'Indtast venligst et resume.',
-'missingcommentheader' => "'''Bemærk:''' Du har ikke angivet en overskrift i feltet „Emne:“ for denne kommentar. Hvis du trykker „Gem side“ én gang til, gemmes dine ændringer uden overskrift.",
+'anoneditwarning' => "'''Advarsel:''' Du er ikke logget på. I stedet for brugernavn vises din IP-adresse i versionshistorikken.",
+'anonpreviewwarning' => "''Du er ikke logget . Hvis du gemmer, registreres din IP-adresse i versionshistorikken.''",
+'missingsummary' => "'''Bemærk:''' Du har ikke angivet en redigeringsbeskrivelse. Hvis du igen trykker på \"{{int:savearticle}}\", gemmes ændringerne uden en beskrivelse.",
+'missingcommenttext' => 'Skriv venligst en kommentar nedenfor.',
+'missingcommentheader' => "'''Bemærk:''' Du har ikke angivet en overskrift/emne for denne kommentar. Hvis du trykker \"{{int:savearticle}}\" én gang til, gemmes dine ændringer uden overskrift/emne.",
 'summary-preview' => 'Forhåndsvisning af beskrivelsen:',
 'subject-preview' => 'Forhåndsvisning af emnet:',
 'blockedtitle' => 'Brugeren er blokeret',
@@ -893,12 +893,12 @@ Angiv venligst alle de ovenstående detaljer ved eventuelle henvendelser.',
 'whitelistedittext' => 'Du skal $1 for at kunne redigere sider.',
 'confirmedittext' => 'Du skal først bekræfte e-mailadressen, før du kan lave ændringer. Udfyld og bekræft din e-mailadresse i dine [[Special:Preferences|indstillinger]].',
 'nosuchsectiontitle' => 'Kan ikke finde afsnittet',
-'nosuchsectiontext' => 'Du forsøgte at ændre et ikke-eksisterende afsnit. Det kan være flyttet eller slettet, siden du hentede siden.',
+'nosuchsectiontext' => 'Du forsøgte at ændre et afsnit der ikke findes. Det kan være flyttet eller slettet, siden du hentede siden.',
 'loginreqtitle' => 'Log på nødvendigt',
 'loginreqlink' => 'logge på',
 'loginreqpagetext' => 'Du skal $1 for at se andre sider.',
 'accmailtitle' => 'Adgangskode sendt.',
-'accmailtext' => "En tilfældigt dannet adgangskode for [[User talk:$1|$1]] er sendt til $2. Den kan ændres på siden ''[[Special:ChangePassword|skift adgangskode]]'', når du logger ind.",
+'accmailtext' => "En tilfældigt dannet adgangskode for [[User talk:$1|$1]] er sendt til $2. Den kan ændres på siden ''[[Special:ChangePassword|skift adgangskode]]'', når du logger .",
 'newarticle' => '(Ny)',
 'newarticletext' => "Du har fulgt en henvisning til en side som endnu ikke findes.
 For at oprette siden skal du begynde at skrive i boksen nedenfor
@@ -998,7 +998,7 @@ Den seneste logpost vises nedenfor:",
 'template-protected' => '(skrivebeskyttet)',
 'template-semiprotected' => '(delvist beskyttet)',
 'hiddencategories' => 'Denne side er i {{PLURAL:$1|en skjult kategori|$1 skjulte kategorier}}:',
-'edittools' => '<!-- Denne tekst vises under formularen „Ændre“ samt "Upload". -->',
+'edittools' => '<!-- Denne tekst vises under formularen "Redigér" samt "Læg en fil op". -->',
 'nocreatetext' => 'Serveren har begrænset oprettelse af nye sider. Bestående sider kan ændres eller [[Special:UserLogin|logge på]].',
 'nocreate-loggedin' => 'Du har ikke rettigheder til at oprette nye sider.',
 'sectioneditnotsupported-title' => 'Afsnitsredigering understøttes ikke',
@@ -1141,19 +1141,20 @@ Du kan se denne forskel; der kan findes detaljer i [{{fullurl:{{#Special:Log}}/s
 'revdelete-text' => "'''Slettede versioner vil fortsat vises i sidehistorik og på logsider, men dele af deres indhold vil ikke være offentligt tilgængeligt.'''
 Andre administratorer på {{SITENAME}} vil fortsat være i stand til at se det skjulte indhold og kan gendanne det igen, medmindre der laves yderligere restriktioner.",
 'revdelete-confirm' => 'Vær venlig at bekræfte at du vil gøre dette, at du forstår konsekvenserne, og at du gør det i overensstemmelse med [[{{MediaWiki:Policy-url}}|retningslinjerne]].',
-'revdelete-suppress-text' => "Skjulning bør '''kun''' bruges i de følgende tilfælde:
+'revdelete-suppress-text' => "Der bør '''kun''' skjules i de følgende tilfælde:
+* Potentielt injurierende oplysninger
 * Upassende personlige oplysninger
-*: ''hjemadresser og -telefonnumre, CPR-numre og lign.''",
+*: ''hjemmeadresser og -telefonnumre, CPR-numre og lign.''",
 'revdelete-legend' => 'Fastlægge begrænsninger for versionerne:',
-'revdelete-hide-text' => 'Skjul versionens tekst',
+'revdelete-hide-text' => 'Tekst for versionen',
 'revdelete-hide-image' => 'Skjul filindhold',
 'revdelete-hide-name' => 'Skjul handling og mål',
-'revdelete-hide-comment' => 'Skjul ændringskommentar',
-'revdelete-hide-user' => 'Skjul brugerens brugernavn/IP',
+'revdelete-hide-comment' => 'Redigeringssammendrag',
+'revdelete-hide-user' => 'Brugerens brugernavn/IP-adrsse',
 'revdelete-hide-restricted' => 'Skjul også informationen for administratorer',
-'revdelete-radio-same' => '(ikke ændre)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nej',
+'revdelete-radio-same' => '(ingen ændring)',
+'revdelete-radio-set' => 'Skjult',
+'revdelete-radio-unset' => 'Synligt',
 'revdelete-suppress' => 'Skjul også informationen for administratorer',
 'revdelete-unsuppress' => 'Ophæv begrænsninger for gendannede versioner',
 'revdelete-log' => 'Begrundelse:',
@@ -1164,7 +1165,7 @@ $1",
 'logdelete-success' => "'''Synlighed ændret med success.'''",
 'logdelete-failure' => "'''Kunne ikke ændre logsynligheden.'''
 $1",
-'revdel-restore' => 'Ã\86ndre synlighed',
+'revdel-restore' => 'ændre synlighed',
 'revdel-restore-deleted' => 'slettede redigeringer',
 'revdel-restore-visible' => 'synlige ændringer',
 'pagehist' => 'Sidehistorik',
@@ -1310,8 +1311,7 @@ Du kan prøve at bruge \"all:\" som præfiks for at søge i alt indhold (inkl. d
 'preferences' => 'Indstillinger',
 'mypreferences' => 'Indstillinger',
 'prefs-edits' => 'Antal redigeringer:',
-'prefsnologin' => 'Ikke logget på',
-'prefsnologintext' => 'Du skal være <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logget på]</span> for at ændre brugerindstillinger.',
+'prefsnologintext2' => 'Du skal $1 for at ændre brugerindstillinger.',
 'changepassword' => 'Skift adgangskode',
 'prefs-skin' => 'Udseende',
 'skin-preview' => 'Forhåndsvisning',
@@ -1445,9 +1445,9 @@ Hvis du vælger at oplyse dit navn, vil det blive brugt til at tilskrive dig dit
 * Et umarkeret felt betyder at brugeren ikke er medlem af gruppen.
 * En * betyder at du ikke kan fravælge gruppen, når den først er tilføjet og omvendt.',
 'userrights-reason' => 'Årsag:',
-'userrights-no-interwiki' => 'Du kan ikke ændre brugerrettigheder på andre wikier.',
+'userrights-no-interwiki' => 'Du har ikke tilladelse til at redigere brugerrettigheder på andre wikier.',
 'userrights-nodatabase' => 'Databasen $1 eksisterer ikke lokalt.',
-'userrights-nologin' => 'Du skal [[Special:UserLogin|logge på]] med en administrativ konto, før du kan ændre brugerettigheder.',
+'userrights-nologin' => 'Du skal [[Special:UserLogin|logge på]] med en administrativ konto, før du kan ændre brugerrettigheder.',
 'userrights-notallowed' => 'Du har ikke tilladelse til at tilføje eller fjerne brugerrettigheder.',
 'userrights-changeable-col' => 'Redigerbare grupper',
 'userrights-unchangeable-col' => 'Uredigerbare grupper',
@@ -1547,7 +1547,7 @@ Vær venlig at gennemse og bekræft dine ændringer.',
 'right-siteadmin' => 'Låse og frigive databasen',
 'right-override-export-depth' => 'Eksportere sider inkl. henviste sider op til en dybde på 5',
 'right-sendemail' => 'Sende e-mail til andre brugere',
-'right-passwordreset' => 'Se emails til nulstilling af adgangskoder',
+'right-passwordreset' => 'Se e-mails til nulstilling af adgangskoder',
 
 # Special:Log/newusers
 'newuserlogpage' => 'Brugeroprettelseslog',
@@ -1611,6 +1611,8 @@ Vær venlig at gennemse og bekræft dine ændringer.',
 'recentchanges-label-minor' => 'Dette er en mindre ændring',
 'recentchanges-label-bot' => 'Denne redigering blev udført af en bot',
 'recentchanges-label-unpatrolled' => 'Denne redigering er endnu ikke blevet patruljeret',
+'recentchanges-label-plusminus' => 'Størrelsen på siden blev ændret med dette antal bytes',
+'recentchanges-legend-newpage' => '(se også [[Special:NewPages|listen over nye sider]])',
 'rcnote' => "Herunder ses {{PLURAL:$1|'''1''' ændring|de sidste '''$1''' ændringer}} fra {{PLURAL:$2|i dag|de sidste '''$2''' dage}} fra den $4, kl. $5.",
 'rcnotefrom' => "Nedenfor er op til '''$1''' ændringer siden '''$2''' vist.",
 'rclistfrom' => 'Vis nye ændringer startende fra $1',
@@ -1707,7 +1709,7 @@ Brug en henvisning af en de følgende typer for at bruge en fil på en side:
 'largefileserver' => 'Filen er større end den på serveren indstillede maksimale størrelse.',
 'emptyfile' => 'Filen du lagde op lader til at være tom. Det kan skyldes en slåfejl i filnavnet. Kontroller om du virkelig ønsker at lægge denne fil op.',
 'windows-nonascii-filename' => 'Denne wiki understøtter ikke filnavne, der indeholder specialtegn.',
-'fileexists' => 'En fil med det navn findes allerede, tjek venligst [[:$1]] om du er sikker på du vil ændre den.
+'fileexists' => 'En fil med det navn findes allerede, tjek venligst <strong>[[:$1]]</strong> om du er sikker på du vil ændre den.
 [[$1|thumb]]',
 'filepageexists' => 'Siden med beskrivelse af denne fil er allerede oprettet på <strong>[[:$1]]</strong>, men der eksisterer ikke en fil med dette navn.
 Den beskrivelse du kan angive nedenfor vil derfor ikke blive brugt.
@@ -2377,11 +2379,12 @@ Bekræft venligst at du virkelig vil gøre dette, at du forstår konsekvenserne,
 'deletecomment' => 'Begrundelse:',
 'deleteotherreason' => 'Anden/uddybende begrundelse:',
 'deletereasonotherlist' => 'Anden begrundelse',
-'deletereason-dropdown' => '
-*Hyppige sletningsårsager
-** Efter forfatters ønske
+'deletereason-dropdown' => '* Hyppige sletningsårsager
+** Spam
+** Hærværk
 ** Overtrædelse af ophavsret
-** Hærværk',
+** Efter forfatters ønske
+** Brudt omdirigering',
 'delete-edit-reasonlist' => 'Rediger sletningsårsager',
 'delete-toobig' => 'Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}}. Sletning af sådanne sider er begrænset, for at forhindre utilsigtet forstyrrelse af {{SITENAME}}.',
 'delete-warning-toobig' => 'Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}} versioner, slettes den kan det forstyrre driften af {{SITENAME}}, gå forsigtigt frem.',
@@ -2463,7 +2466,7 @@ Se [[Special:ProtectedPages|listen over beskyttede sider]] for listen over sideb
 'pagesize' => '(bytes)',
 
 # Restrictions (nouns)
-'restriction-edit' => 'ændre',
+'restriction-edit' => 'Redigér',
 'restriction-move' => 'flytte',
 'restriction-create' => 'oprette',
 'restriction-upload' => 'oplægge',
@@ -2623,7 +2626,7 @@ Angiv en konkret begrundelse herunder (for eksempel med angivelse af sider der h
 Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'ipb-blockingself' => 'Du er ved at blokere dig selv! Er du sikker på, du vil gøre det?',
 'ipb-confirmhideuser' => 'Du er ved at blokere en bruger med "skjul bruger" aktiveret. Dette vil skjule brugerens navn på alle lister og logposter. Er du sikker på du vil gøre det?',
-'ipb-edit-dropdown' => 'Ændre spærreårsager',
+'ipb-edit-dropdown' => 'Rediger blokeringsbegrundelser',
 'ipb-unblock-addr' => 'Ophæv blokeringen af "$1"',
 'ipb-unblock' => 'Frigive IP-adresse/bruger',
 'ipb-blocklist' => 'Vis alle blokeringer som er i kraft',
@@ -2661,7 +2664,7 @@ Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'ipblocklist-no-results' => 'Den angivene IP-addresse eller brugernavn er ikke blokeret.',
 'blocklink' => 'bloker',
 'unblocklink' => 'ophæv blokering',
-'change-blocklink' => 'ændre blokering',
+'change-blocklink' => 'ændring af blokering',
 'contribslink' => 'bidrag',
 'emaillink' => 'send e-mail',
 'autoblocker' => 'Du er automatisk blokeret, fordi du deler IP-adresse med "[[User:$1|$1]]".
@@ -2689,7 +2692,7 @@ Se [[Special:BlockList|blokeringslisten]] for den nuværende liste med aktuelle
 'ipb_expiry_temp' => 'Brugernavnet kan kun skjules ved permanente blokeringer.',
 'ipb_hide_invalid' => 'Kan ikke skjule denne konto; den kan have for mange redigeringer.',
 'ipb_already_blocked' => '„$1“ er allerede blokeret',
-'ipb-needreblock' => '$1 er allerede blokkeret. Vil du ændre indstillingene?',
+'ipb-needreblock' => '$1 er allerede blokeret. Vil du ændre indstillingerne?',
 'ipb-otherblocks-header' => 'Yderligere {{PLURAL:$1|blokering|blokeringer}}',
 'unblock-hideuser' => 'Du kan ikke ophæve denne brugers blokering, da brugernavnet er blevet skjult.',
 'ipb_cant_unblock' => 'Fejl: Spærre-ID $1 ikke fundet. Spærringen er allerede ophævet.',
@@ -2843,7 +2846,7 @@ Hvis du kun vil have den seneste version, kan du også bruge en henvisning, for
 'allmessagesdefault' => 'Standardtekst',
 'allmessagescurrent' => 'Nuværende tekst',
 'allmessagestext' => 'Dette er en liste med alle systembeskeder i MediaWiki-navnerummet.
-Besøg venligst [//www.mediawiki.org/wiki/Localisation MediaWiki-lokalisering] og [//translatewiki.net translatewiki.net] hvis du ønsker at bidrage til den generelle lokalisering (oversættelse og andre lokale tilpasninger) af MediaWiki.',
+Besøg venligst [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisering] og [//translatewiki.net translatewiki.net] hvis du ønsker at bidrage til den generelle lokalisering (oversættelse og andre lokale tilpasninger) af MediaWiki.',
 'allmessagesnotsupportedDB' => '{{ns:special}}:AllMessages ikke understøttet fordi wgUseDatabaseMessages er slået fra.',
 'allmessages-filter-legend' => 'Filtrér',
 'allmessages-filter' => 'Filtrér efter tilpasningsstatus:',
@@ -3039,6 +3042,8 @@ Dette skyldes sandsynligvis en henvisning til et sortlistet eksternt websted.',
 'spam_reverting' => 'Sidste version uden henvisning til $1 gendannet.',
 'spam_blanking' => 'Alle versioner, som indeholdt henvisninger til $1, er renset.',
 'spam_deleting' => 'Alle versioner indeholder henvisninger til $1, sletter',
+'simpleantispam-label' => "Anti-spam tjek.
+Udfyld '''IKKE''' dette!",
 
 # Info page
 'pageinfo-title' => 'Information om "$1"',
@@ -3052,6 +3057,7 @@ Dette skyldes sandsynligvis en henvisning til et sortlistet eksternt websted.',
 'pageinfo-length' => 'Sidelængde (i bytes)',
 'pageinfo-article-id' => 'Side-ID',
 'pageinfo-language' => 'Sprog for sideindholdet',
+'pageinfo-content-model' => 'Sidens indhold er',
 'pageinfo-robot-policy' => 'Indeksering af robotter',
 'pageinfo-robot-index' => 'Tilladt',
 'pageinfo-robot-noindex' => 'Ikke tilladt',
@@ -3137,7 +3143,7 @@ Du kan beskadige dit system hvis du udfører den.",
 'svg-long-desc' => 'SVG fil, basisstørrelse $1 × $2 punkters, størrelse: $3',
 'svg-long-desc-animated' => 'Animeret SVG-fil, basisstørrelse $1 × $2 punkter, filstørrelse: $3',
 'svg-long-error' => 'Ugyldig SVG-fil: $1',
-'show-big-image' => 'Version i større opløsning',
+'show-big-image' => 'Oprindelige fil',
 'show-big-image-preview' => 'Størrelse af denne forhåndsvisning: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Anden opløsning|Andre opløsninger}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3604,7 +3610,7 @@ Kun indholdet af lister (linjer startende med *) bliver brugt. Den første henvi
 
 # External editor support
 'edit-externally' => 'Rediger denne fil med en ekstern editor',
-'edit-externally-help' => '(Se [//www.mediawiki.org/wiki/Manual:External_editors setup instruktionerne] for mere information)',
+'edit-externally-help' => '(Se [https://www.mediawiki.org/wiki/Manual:External_editors setup instruktionerne] for mere information)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
@@ -3678,10 +3684,10 @@ Denne bekræftelseskode vil udløbe den $4.',
 'scarytranscludetoolong' => "[URL'en er for lang]",
 
 # Delete conflict
-'deletedwhileediting' => 'Bemærk: Det blev forsøgt at slette denne side, efter at du var begyndt, at ændre den!
+'deletedwhileediting' => "'''Advarsel:''' Denne side er blevet slettet efter du begyndte at redigere den!
 Kig i [{{fullurl:Special:Log|type=delete&page=}}{{FULLPAGENAMEE}} slette-loggen],
-hvorfor siden blev slettet. Hvis du gemmer siden bliver den oprettet igen.',
-'confirmrecreate' => "Bruger [[User:$1|$1]] ([[User talk:$1|Diskussion]]) har slettet denne side, efter at du begyndte at ændre den. Begrundelsen lyder:
+hvorfor siden blev slettet. Hvis du gemmer siden bliver den oprettet igen.",
+'confirmrecreate' => "Brugeren [[User:$1|$1]] ([[User talk:$1|Diskussion]]) har slettet denne side, efter at du begyndte at redigere den. Begrundelsen lyder:
 : ''$2''
 Bekræft venligst, at du virkelig vil oprette denne side igen.",
 'confirmrecreate-noreason' => '[[User:$1|$1]] ([[User talk:$1|diskussion]]) har slettet denne side, efter du begyndte at redigere. Bekræft venligst, at du gerne vil genoprette siden.',
@@ -3767,7 +3773,7 @@ Du kan også [[Special:EditWatchlist|bruge standard editoren]].',
 'duplicate-defaultsort' => 'Advarsel: Standardsorteringsnøglen "$2" tilsidesætter den tidligere sorteringsnøgle "$1".',
 
 # Special:Version
-'version' => 'Version',
+'version' => 'Information om MediaWiki',
 'version-extensions' => 'Installerede udvidelser',
 'version-specialpages' => 'Specialsider',
 'version-parserhooks' => 'Oversætter-funktioner',
@@ -3783,7 +3789,7 @@ Du kan også [[Special:EditWatchlist|bruge standard editoren]].',
 'version-hook-subscribedby' => 'Brugt af',
 'version-version' => '(Version $1)',
 'version-license' => 'Licens',
-'version-poweredby-credits' => "Denne wiki er drevet af '''[//www.mediawiki.org/ MediaWiki ]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Denne wiki er drevet af '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'andre',
 'version-poweredby-translators' => 'translatewiki.net oversættere',
 'version-credits-summary' => 'Vi vil gerne anerkende følgende personer for deres bidrag til [[Special:Version|MediaWiki]].',
@@ -3802,7 +3808,7 @@ Du skulle have modtaget [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopi af GNU General
 # Special:Redirect
 'redirect' => 'Omdirigering pga. fil, bruger eller udgave ID',
 'redirect-legend' => 'Omstilling til en fil eller en side',
-'redirect-summary' => "Denne side omdirigerer en (hvis filnavnet er angivet), en side (hvis udgave ID'et er angivet) eller en brugerside (hvis et numerisk brugernummer er angivet).",
+'redirect-summary' => "Denne specialside omdirigerer til en fil (hvis filnavnet er angivet), en side (hvis udgave ID'et er angivet) eller en brugerside (hvis et numerisk brugernummer er angivet). Eksempler på brug: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] eller [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Kør',
 'redirect-lookup' => 'Slå op:',
 'redirect-value' => 'Værdi:',
@@ -3824,8 +3830,8 @@ Du skulle have modtaget [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopi af GNU General
 
 # Special:SpecialPages
 'specialpages' => 'Specialsider',
-'specialpages-note' => '----
-* Normale specialsider.
+'specialpages-note-top' => 'Forklaring',
+'specialpages-note' => '* Normale specialsider.
 * <span class="mw-specialpagerestricted">Specialsider med begrænset adgang.</span>',
 'specialpages-group-maintenance' => 'Vedligeholdelsesside',
 'specialpages-group-other' => 'Andre specialsider',
@@ -3867,7 +3873,7 @@ Du skulle have modtaget [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopi af GNU General
 'tags-hitcount-header' => 'Taggede ændringer',
 'tags-active-yes' => 'Ja',
 'tags-active-no' => 'Nej',
-'tags-edit' => 'Redigér',
+'tags-edit' => 'redigér',
 'tags-hitcount' => '{{PLURAL:$1|en ændring|$1 ændringer}}',
 
 # Special:ComparePages
@@ -4036,4 +4042,21 @@ Ellers kan du bruge den enkle formular nedenfor. Din kommentar vil blive tilføj
 'limitreport-expansiondepth' => 'Største udvidelsesdybde',
 'limitreport-expensivefunctioncount' => 'Antal dyre parserfunktioner',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Udfold skabeloner',
+'expand_templates_intro' => 'Denne specialside tager en tekst og udfolder alle benyttede skabeloner rekursivt.
+Den udfolder også understøttede parserfunktioner så som
+<code><nowiki>{{</nowiki>#language:…}}</code> og variabler så som 
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>
+Faktisk udfolder den stort set alt i dobbelte tuborgklammer.',
+'expand_templates_title' => 'Sammenhængstitel, for {{FULLPAGENAME}} osv.:',
+'expand_templates_input' => 'Inputtekst:',
+'expand_templates_output' => 'Resultat',
+'expand_templates_xml_output' => 'XML-kode',
+'expand_templates_ok' => 'Udfold',
+'expand_templates_remove_comments' => 'Fjern kommentarer',
+'expand_templates_remove_nowiki' => 'Undertryk <nowiki>-tags i resultatet',
+'expand_templates_generate_xml' => 'Vis analysetræ som XML',
+'expand_templates_preview' => 'Forhåndsvisning',
+
 );
index baba696..dee1540 100644 (file)
@@ -111,12 +111,12 @@ $namespaceGenderAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Aktive_Benutzer' ),
        'Allmessages'               => array( 'MediaWiki-Systemnachrichten', 'Systemnachrichten' ),
+       'AllMyUploads'              => array( 'Alle_meine_Dateien' ),
        'Allpages'                  => array( 'Alle_Seiten' ),
        'Ancientpages'              => array( 'Älteste_Seiten' ),
        'Badtitle'                  => array( 'Ungültiger_Seitenname' ),
        'Blankpage'                 => array( 'Leerseite', 'Leere_Seite' ),
        'Block'                     => array( 'Sperren' ),
-       'Blockme'                   => array( 'Proxy-Sperre' ),
        'Booksources'               => array( 'ISBN-Suche' ),
        'BrokenRedirects'           => array( 'Defekte_Weiterleitungen', 'Kaputte_Weiterleitungen' ),
        'Categories'                => array( 'Kategorien' ),
@@ -128,10 +128,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Benutzerkonto_anlegen' ),
        'Deadendpages'              => array( 'Sackgassenseiten' ),
        'DeletedContributions'      => array( 'Gelöschte_Beiträge' ),
-       'Disambiguations'           => array( 'Begriffsklärungsverweise' ),
        'DoubleRedirects'           => array( 'Doppelte_Weiterleitungen' ),
        'EditWatchlist'             => array( 'Beobachtungsliste_bearbeiten' ),
        'Emailuser'                 => array( 'E-Mail_senden', 'Mailen', 'E-Mail' ),
+       'ExpandTemplates'           => array( 'Vorlagen_expandieren' ),
        'Export'                    => array( 'Exportieren' ),
        'Fewestrevisions'           => array( 'Wenigstbearbeitete_Seiten' ),
        'FileDuplicateSearch'       => array( 'Dateiduplikatsuche', 'Datei-Duplikat-Suche' ),
@@ -176,10 +176,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Geschützte_Seiten' ),
        'Protectedtitles'           => array( 'Geschützte_Titel', 'Gesperrte_Titel' ),
        'Randompage'                => array( 'Zufällige_Seite' ),
+       'RandomInCategory'          => array( 'Zufällige_Seite_in_Kategorie' ),
        'Randomredirect'            => array( 'Zufällige_Weiterleitung' ),
        'Recentchanges'             => array( 'Letzte_Änderungen' ),
        'Recentchangeslinked'       => array( 'Änderungen_an_verlinkten_Seiten' ),
        'Redirect'                  => array( 'Weiterleitung' ),
+       'ResetTokens'               => array( 'Tokens_zurücksetzen' ),
        'Revisiondelete'            => array( 'Versionslöschung' ),
        'Search'                    => array( 'Suche' ),
        'Shortpages'                => array( 'Kürzeste_Seiten' ),
@@ -278,6 +280,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'zentriert', 'center', 'centre' ),
        'img_framed'                => array( '1', 'gerahmt', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'rahmenlos', 'frameless' ),
+       'img_lang'                  => array( '1', 'sprache=$1', 'lang=$1' ),
        'img_page'                  => array( '1', 'seite=$1', 'seite_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'hochkant', 'hochkant=$1', 'hochkant_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'rand', 'border' ),
@@ -318,6 +321,7 @@ $magicWords = array(
        'revisionyear'              => array( '1', 'REVISIONSJAHR', 'VERSIONSJAHR', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', 'REVISIONSZEITSTEMPEL', 'VERSIONSZEITSTEMPEL', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'REVISIONSBENUTZER', 'VERSIONSBENUTZER', 'REVISIONUSER' ),
+       'revisionsize'              => array( '1', 'VERSIONSGRÖSSE', 'REVISIONSIZE' ),
        'fullurl'                   => array( '0', 'VOLLSTÄNDIGE_URL:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'VOLLSTÄNDIGE_URL_C:', 'FULLURLE:' ),
        'canonicalurl'              => array( '0', 'KANONISCHE_URL:', 'CANONICALURL:' ),
@@ -694,12 +698,10 @@ Siehe die [[Special:Version|Versionsseite]]',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Von „$1“',
 'youhavenewmessages' => 'Du hast $1 ($2).',
-'newmessageslink' => 'neue Nachrichten',
-'newmessagesdifflink' => 'Letzte Änderung',
 'youhavenewmessagesfromusers' => 'Du hast $1 von {{PLURAL:$3|einem anderen Benutzer|$3 Benutzern}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du hast $1 von vielen Benutzern ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|eine neue Nachricht|neue Nachrichten}}',
-'newmessagesdifflinkplural' => 'letzte {{PLURAL:$1|Änderung|Änderungen}}',
+'newmessageslinkplural' => '{{PLURAL:$1|eine neue Nachricht|999=neue Nachrichten}}',
+'newmessagesdifflinkplural' => 'letzte {{PLURAL:$1|Änderung|999=Änderungen}}',
 'youhavenewmessagesmulti' => 'Du hast neue Nachrichten: $1',
 'editsection' => 'Bearbeiten',
 'editold' => 'Bearbeiten',
@@ -830,7 +832,8 @@ Der Administrator, der den Schreibzugriff sperrte, gab folgenden Grund an: „$3
 'invalidtitle-knownnamespace' => 'Ungültiger Titel mit Namensraum „$2“ und Text „$3“',
 'invalidtitle-unknownnamespace' => 'Ungültiger Titel mit unbekannter Namensraumnummer $1 und Text „$2“',
 'exception-nologin' => 'Nicht angemeldet',
-'exception-nologin-text' => 'Diese Seite oder Aktion erfordert, dass du auf diesem Wiki angemeldet bist.',
+'exception-nologin-text' => 'Du musst dich [[Special:Userlogin|anmelden]], um auf diese Seite oder Aktion zugreifen zu können.',
+'exception-nologin-text-manual' => 'Du musst dich $1, um auf diese Seite oder Aktion zugreifen zu können.',
 
 # Virus scanner
 'virus-badscanner' => "Fehlerhafte Konfiguration: unbekannter Virenscanner: ''$1''",
@@ -877,7 +880,7 @@ Vergiss nicht, deine [[Special:Preferences|{{SITENAME}}-Einstellungen]] zu ände
 'gotaccount' => "Du hast bereits ein Benutzerkonto? '''$1'''.",
 'gotaccountlink' => 'Anmelden',
 'userlogin-resetlink' => 'Die Anmeldedaten vergessen?',
-'userlogin-resetpassword-link' => 'Passwort zurücksetzen',
+'userlogin-resetpassword-link' => 'Passwort vergessen?',
 'helplogin-url' => 'Help:Anmelden',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hilfe beim Anmelden]]',
 'userlogin-loggedin' => 'Du bist bereits als {{GENDER:$1|$1}} angemeldet.
@@ -925,7 +928,7 @@ Es muss sichergestellt sein, dass Cookies aktiviert sind. Danach diese Seite ern
 'passwordtooshort' => 'Passwörter müssen mindestens {{PLURAL:$1|1 Zeichen|$1 Zeichen}} lang sein.',
 'password-name-match' => 'Dein Passwort muss sich von deinem Benutzernamen unterscheiden.',
 'password-login-forbidden' => 'Die Verwendung dieses Benutzernamens und Passwortes ist nicht erlaubt.',
-'mailmypassword' => 'Neues Passwort zusenden',
+'mailmypassword' => 'Passwort zurücksetzen',
 'passwordremindertitle' => 'Neues Passwort für ein {{SITENAME}}-Benutzerkonto',
 'passwordremindertext' => 'Jemand mit der IP-Adresse $1, wahrscheinlich du selbst, hat ein neues Passwort für die Anmeldung bei {{SITENAME}} ($4) angefordert.
 
@@ -949,7 +952,8 @@ Bevor eine E-Mail von anderen Benutzern über die E-Mail-Funktion empfangen werd
 
 Besucher, die diese IP-Adresse verwenden, können momentan keine Benutzerkonten mehr erstellen.',
 'emailauthenticated' => 'Deine E-Mail-Adresse wurde am $2 um $3 Uhr bestätigt.',
-'emailnotauthenticated' => 'Deine E-Mail-Adresse ist noch nicht bestätigt. Die folgenden E-Mail-Funktionen stehen erst nach erfolgreicher Bestätigung zur Verfügung.',
+'emailnotauthenticated' => 'Deine E-Mail-Adresse ist noch nicht bestätigt.
+Die folgenden E-Mail-Funktionen stehen erst nach erfolgreicher Bestätigung zur Verfügung.',
 'noemailprefs' => 'Gib eine E-Mail-Adresse in den Einstellungen an, damit die nachfolgenden Funktionen zur Verfügung stehen.',
 'emailconfirmlink' => 'E-Mail-Adresse bestätigen (authentifizieren).',
 'invalidemailaddress' => 'Die E-Mail-Adresse wird nicht akzeptiert, weil sie ein ungültiges Format (eventuell ungültige Zeichen) zu haben scheint. Bitte gib eine korrekte Adresse ein oder leere das Feld.',
@@ -997,7 +1001,7 @@ Möglicherweise hast du dein Passwort bereits erfolgreich geändert oder ein neu
 # Special:PasswordReset
 'passwordreset' => 'Passwort zurücksetzen',
 'passwordreset-text-one' => 'Fülle dieses Formular aus, um dein Passwort zurückzusetzen.',
-'passwordreset-text-many' => '{{PLURAL:$1|Füll eines der Felder aus, um dein Passwort zurückzusetzen.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Füll eines der Felder aus, um ein temporäres Passwort per E-Mail zugesandt zu bekommen.}}',
 'passwordreset-legend' => 'Passwort zurücksetzen',
 'passwordreset-disabled' => 'Das Zurücksetzen von Passwörtern wurde in diesem Wiki deaktiviert.',
 'passwordreset-emaildisabled' => 'Die E-Mail-Funktionen wurden auf diesem Wiki deaktiviert.',
@@ -1374,18 +1378,19 @@ Du kannst diesen Versionsunterschied einsehen, sofern du möchtest. Nähere Anga
 Andere Administratoren auf {{SITENAME}} haben Zugriff auf den versteckten Inhalt und können ihn mit der gleichen Seite wiederherstellen, sofern nicht zusätzliche Einschränkungen bestehen.",
 'revdelete-confirm' => 'Bitte bestätige, dass du beabsichtigst, dies zu tun, die Konsequenzen verstehst und es in Übereinstimmung mit den [[{{MediaWiki:Policy-url}}|Richtlinien]] tust.',
 'revdelete-suppress-text' => "Unterdrückungen sollten '''nur''' in den folgenden Fällen vorgenommen werden:
+* Potentiell beleidigende Informationen
 * Unangebrachte persönliche Informationen
 *: ''Adressen, Telefonnummern, Sozialversicherungsnummern etc.''",
 'revdelete-legend' => 'Setzen der Sichtbarkeitseinschränkungen',
-'revdelete-hide-text' => 'Text der Version verstecken',
+'revdelete-hide-text' => 'Text der Version',
 'revdelete-hide-image' => 'Dateiinhalt verstecken',
 'revdelete-hide-name' => 'Logbuchaktion und Ziel verstecken',
-'revdelete-hide-comment' => 'Bearbeitungszusammenfassung verstecken',
-'revdelete-hide-user' => 'Benutzername/IP-Adresse des Bearbeiters verstecken',
+'revdelete-hide-comment' => 'Bearbeitungszusammenfassung',
+'revdelete-hide-user' => 'Benutzername/IP-Adresse des Bearbeiters',
 'revdelete-hide-restricted' => 'Daten sowohl vor Administratoren als auch anderen Benutzern unterdrücken',
 'revdelete-radio-same' => '(nicht ändern)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nein',
+'revdelete-radio-set' => 'Versteckt',
+'revdelete-radio-unset' => 'Sichtbar',
 'revdelete-suppress' => 'Grund der Löschung auch vor Administratoren verstecken',
 'revdelete-unsuppress' => 'Einschränkungen für wiederhergestellte Versionen aufheben',
 'revdelete-log' => 'Grund:',
@@ -1539,8 +1544,7 @@ Einzelheiten sind im [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}
 'preferences' => 'Einstellungen',
 'mypreferences' => 'Einstellungen',
 'prefs-edits' => 'Anzahl der Bearbeitungen:',
-'prefsnologin' => 'Nicht angemeldet',
-'prefsnologintext' => 'Du musst <span class="plainlinks">[{{fullurl:{{#special:UserLogin}}|returnto=$1}} angemeldet]</span> sein, um deine Einstellungen ändern zu können.',
+'prefsnologintext2' => 'Du musst dich $1, um Benutzereinstellungen festzulegen.',
 'changepassword' => 'Passwort ändern',
 'prefs-skin' => 'Benutzeroberfläche',
 'skin-preview' => 'Vorschau',
@@ -1841,6 +1845,9 @@ Diese Information ist öffentlich.',
 'recentchanges-label-minor' => 'Kleine Änderung',
 'recentchanges-label-bot' => 'Änderung durch einen Bot',
 'recentchanges-label-unpatrolled' => 'Nicht-kontrollierte Änderung',
+'recentchanges-label-plusminus' => 'Die geänderte Seitengröße (Anzahl in Bytes)',
+'recentchanges-legend-newpage' => '(siehe auch die [[Special:NewPages|Liste neuer Seiten]])',
+'recentchanges-legend-plusminus' => "''(±123)''",
 'rcnote' => "{{PLURAL:$1|'''1''' Änderung|'''$1''' Änderungen}} in den {{PLURAL:$2|letzten 24 Stunden|letzten '''$2''' Tagen}}.
 Stand: $4, $5 Uhr.",
 'rcnotefrom' => "Angezeigt werden die Änderungen seit '''$2''' (max. '''$1''' Einträge).",
@@ -2566,7 +2573,7 @@ Kontakt zum Bearbeiter:
 E-Mail: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
-Bei weiterer Aktivität auf der Seite werden dir so lange keine weiteren Benachrichtigungs-E-Mails gesendet, bis du die Seite wieder besucht hast. Auf deiner Beobachtungsliste kannst du alle Benachrichtigungsmarkierungen zusammen zurücksetzen.
+Bei weiterer Aktivität auf der Seite werden dir so lange keine weiteren Benachrichtigungs-E-Mails gesendet, bis du die Seite wieder angemeldet besucht hast. Auf deiner Beobachtungsliste kannst du alle Benachrichtigungsmarkierungen zusammen zurücksetzen.
 
 Dein freundliches {{SITENAME}}-Benachrichtigungssystem
 
@@ -3070,7 +3077,7 @@ Alternativ ist der Export auch mit der Syntax [[{{#Special:Export}}/{{MediaWiki:
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'Aktueller Text',
 'allmessagestext' => 'Dies ist eine Liste der MediaWiki-Systemtexte.
-Bitte besuche die Seiten [//www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], sofern du dich an der Lokalisierung von MediaWiki beteiligen möchtest.',
+Bitte besuche die Seiten [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], sofern du dich an der Lokalisierung von MediaWiki beteiligen möchtest.',
 'allmessagesnotsupportedDB' => 'Diese Spezialseite steht nicht zur Verfügung, da sie über den Parameter <tt>$wgUseDatabaseMessages</tt> deaktiviert wurde.',
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter für angepassten Zustand:',
@@ -3232,7 +3239,7 @@ Diese auf dem lokalen Rechner speichern und danach hier hochladen.',
 'tooltip-undo' => 'Macht lediglich diese eine Änderung rückgängig und zeigt das Resultat in der Vorschau an, damit in der Zusammenfassungszeile eine Begründung angegeben werden kann.',
 'tooltip-preferences-save' => 'Einstellungen speichern',
 'tooltip-summary' => 'Gib eine kurze Zusammenfassung ein.',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* Das folgende CSS wird für alle Benutzeroberflächen geladen. */',
@@ -3282,6 +3289,8 @@ Das liegt wahrscheinlich an einem Link auf eine externe Seite.',
 'spam_reverting' => 'Letzte Version ohne Links zu $1 wiederhergestellt.',
 'spam_blanking' => 'Alle Versionen mit einem Link zu $1 wurden bereinigt.',
 'spam_deleting' => 'Alle Versionen mit einem Link zu $1 wurden gelöscht.',
+'simpleantispam-label' => "Spamschutzprüfung.
+Hier '''NICHTS''' eintragen!",
 
 # Info page
 'pageinfo-title' => 'Informationen zu „$1“',
@@ -3295,6 +3304,7 @@ Das liegt wahrscheinlich an einem Link auf eine externe Seite.',
 'pageinfo-length' => 'Seitenlänge (in Bytes)',
 'pageinfo-article-id' => 'Seitenkennnummer',
 'pageinfo-language' => 'Seiteninhaltssprache',
+'pageinfo-content-model' => 'Seiteninhaltsmodell',
 'pageinfo-robot-policy' => 'Indexierung durch Robots',
 'pageinfo-robot-index' => 'Erlaubt',
 'pageinfo-robot-noindex' => 'Nicht erlaubt',
@@ -3382,7 +3392,7 @@ Durch das Herunterladen und Öffnen der Datei kann dein Computer beschädigt wer
 'svg-long-desc' => 'SVG-Datei, Basisgröße: $1 × $2 Pixel, Dateigröße: $3',
 'svg-long-desc-animated' => 'Animierte SVG-Datei, Basisgröße $1 × $2 Pixel, Dateigröße: $3',
 'svg-long-error' => 'Ungültige SVG-Datei: $1',
-'show-big-image' => 'Volle Auflösung',
+'show-big-image' => 'Originaldatei',
 'show-big-image-preview' => 'Größe dieser Vorschau: $1.',
 'show-big-image-other' => 'Weitere {{PLURAL:$2|Auflösung|Auflösungen}}: $1.',
 'show-big-image-size' => '$1 × $2 Pixel',
@@ -3848,7 +3858,7 @@ Weitere werden standardmäßig nicht angezeigt.
 
 # External editor support
 'edit-externally' => 'Diese Datei mit einem externen Programm bearbeiten',
-'edit-externally-help' => '(weitere Informationen in den [//www.mediawiki.org/wiki/Manual:External_editors Installationsanweisungen])',
+'edit-externally-help' => '(weitere Informationen in den [https://www.mediawiki.org/wiki/Manual:External_editors Installationsanweisungen])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
@@ -3949,6 +3959,7 @@ Bitte bestätige, dass du diese Seite wirklich neu erstellen möchten.",
 # Separators for various lists, etc.
 'ellipsis' => '…',
 'percent' => '$1&#160;%',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← vorherige Seite',
@@ -4051,7 +4062,7 @@ Du kannst auch die [[Special:EditWatchlist|Standardseite]] zum Bearbeiten benutz
 'version-version' => '(Version $1)',
 'version-svn-revision' => '(Version $2)',
 'version-license' => 'Lizenz',
-'version-poweredby-credits' => "Diese Website nutzt '''[//www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Diese Website nutzt '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'andere',
 'version-poweredby-translators' => 'Übersetzer von translatewiki.net',
 'version-credits-summary' => 'Wir danken folgenden Personen für ihre Beiträge zu [[Special:Version|MediaWiki]].',
@@ -4072,7 +4083,7 @@ Eine [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie der ''GNU General Public License'']
 # Special:Redirect
 'redirect' => 'Weiterleitung auf Benutzerseite, Seitenversion oder Datei',
 'redirect-legend' => 'Weiterleitung auf eine Benutzerseite, Seitenversion oder Datei',
-'redirect-summary' => 'Diese Spezialseite leitet auf eine Benutzerseite (numerische Benutzerkennung angegeben), Seitenversion (Versionskennung angegeben) oder Datei (Dateiname angegeben) weiter.',
+'redirect-summary' => 'Diese Spezialseite leitet auf eine Benutzerseite (numerische Benutzerkennung angegeben), Seitenversion (Versionskennung angegeben) oder Datei (Dateiname angegeben) weiter. Benutzung: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] oder [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Los',
 'redirect-lookup' => 'Suchen:',
 'redirect-value' => 'Kennung oder Dateiname:',
@@ -4094,10 +4105,9 @@ Eine [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie der ''GNU General Public License'']
 
 # Special:SpecialPages
 'specialpages' => 'Spezialseiten',
-'specialpages-note' => '----
-* Reguläre Spezialseiten
-* <span class="mw-specialpagerestricted">Zugriffsbeschränkte Spezialseiten</span>
-* <span class="mw-specialpagecached">Gecachte Spezialseiten (Deren Inhalt ist möglicherweise veraltet.)</span>',
+'specialpages-note-top' => 'Legende',
+'specialpages-note' => '* Normale Spezialseiten.
+* <span class="mw-specialpagerestricted">Spezialseiten mit beschränktem Zugang.</span>',
 'specialpages-group-maintenance' => 'Wartungslisten',
 'specialpages-group-other' => 'Andere Spezialseiten',
 'specialpages-group-login' => 'Benutzerkonto',
@@ -4298,7 +4308,7 @@ Anderenfalls kannst du auch das untenstehende einfache Formular nutzen. Dein Kom
 'rotate-comment' => 'Bild um $1 {{PLURAL:$1|Grad}} im Uhrzeigersinn gedreht',
 
 # Limit report
-'limitreport-title' => 'Parser-Profiling-Daten:',
+'limitreport-title' => 'Profilingdaten des Parsers:',
 'limitreport-cputime' => 'CPU-Zeit-Nutzung',
 'limitreport-cputime-value' => '{{PLURAL:$1|Eine Sekunde|$1 Sekunden}}',
 'limitreport-walltime' => 'Echtzeitnutzung',
@@ -4315,4 +4325,21 @@ Anderenfalls kannst du auch das untenstehende einfache Formular nutzen. Dein Kom
 'limitreport-expansiondepth-value' => '$1/$2',
 'limitreport-expensivefunctioncount' => 'Anzahl aufwändiger Parserfunktionen',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Vorlagen expandieren',
+'expand_templates_intro' => 'Auf dieser Spezialseite kann Text eingegeben werden. Alle enthaltenen Vorlagen werden dabei rekursiv expandiert.
+Auch Parserfunktionen wie
+<code><nowiki>{{</nowiki>#language:…}}</code> und Variablen wie
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code> werden ausgewertet –
+faktisch alles was in doppelten geschweiften Klammern enthalten ist.',
+'expand_templates_title' => 'Kontexttitel, für {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Eingabefeld:',
+'expand_templates_output' => 'Ergebnis',
+'expand_templates_xml_output' => 'XML-Ausgabe',
+'expand_templates_ok' => 'Okay',
+'expand_templates_remove_comments' => 'Kommentare entfernen',
+'expand_templates_remove_nowiki' => '<nowiki>-Tags in der Ausgabe unterdrücken',
+'expand_templates_generate_xml' => 'XML-Parser-Baum zeigen',
+'expand_templates_preview' => 'Vorschau',
+
 );
index bf37f54..15c1cec 100644 (file)
@@ -14,6 +14,7 @@
  * @author George Animal
  * @author Gorizon
  * @author Kaganer
+ * @author Marmase
  * @author Mirzali
  * @author Nemo bis
  * @author Neribij
 
 $namespaceNames = array(
        NS_MEDIA            => 'Medya',
-       NS_SPECIAL          => 'Xısusi',
-       NS_TALK             => 'Mesac',
+       NS_SPECIAL          => 'Bağse',
+       NS_TALK             => 'Vaten',
        NS_USER             => 'Karber',
-       NS_USER_TALK        => 'Karber_mesac',
-       NS_PROJECT_TALK     => '$1_mesac',
+       NS_USER_TALK        => 'Karber_vaten',
+       NS_PROJECT_TALK     => '$1_vaten',
        NS_FILE             => 'Dosya',
-       NS_FILE_TALK        => 'Dosya_mesac',
+       NS_FILE_TALK        => 'Dosya_vaten',
        NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'MediaWiki_mesac',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_vaten',
        NS_TEMPLATE         => 'Şablon',
-       NS_TEMPLATE_TALK    => 'Şablon_mesac',
-       NS_HELP             => 'Peşti',
-       NS_HELP_TALK        => 'Peşti_mesac',
-       NS_CATEGORY         => 'Kategoriye',
-       NS_CATEGORY_TALK    => 'Kategoriye_mesac',
+       NS_TEMPLATE_TALK    => 'Şablon_vaten',
+       NS_HELP             => 'Desteg',
+       NS_HELP_TALK        => 'Desteg_vaten',
+       NS_CATEGORY         => 'Kategori',
+       NS_CATEGORY_TALK    => 'Kategori_vaten',
 );
 
 $namespaceAliases = array(
+       'Xısusi'               => NS_SPECIAL,
        'Werênayış'            => NS_TALK,
+       'Mesac'                => NS_TALK,
        'Karber_werênayış'     => NS_USER_TALK,
+       'Karber_mesac'         => NS_USER_TALK,
        '$1_werênayış'         => NS_PROJECT_TALK,
+       '$1_mesac'             => NS_PROJECT_TALK,
        'Dosya_werênayış'      => NS_FILE_TALK,
+       'Dosya_mesac'          => NS_FILE_TALK,
        'MediaWiki_werênayış'  => NS_MEDIAWIKI_TALK,
+       'MediaWiki_mesac'      => NS_MEDIAWIKI_TALK,
        'Şablon_werênayış'     => NS_TEMPLATE_TALK,
+       'Şablon_mesac'         => NS_TEMPLATE_TALK,
        'Desteg'               => NS_HELP,
        'Desteg_werênayış'     => NS_HELP_TALK,
+       'Peşti'                => NS_HELP,
+       'Peşti_mesac'          => NS_HELP_TALK,
        'Peşti_werênayış'      => NS_HELP_TALK,
        'Kategori'             => NS_CATEGORY,
        'Kategori_werênayış'   => NS_CATEGORY_TALK,
+       'Kategoriye'           => NS_CATEGORY,
+       'Kategoriye_mesac'     => NS_CATEGORY_TALK,
        'Kategoriye_werênayış' => NS_CATEGORY_TALK,
 );
 
 $specialPageAliases = array(
-       'Activeusers'               => array( 'KarberéAktivi', 'AktivKarberi' ),
+       'Activeusers'               => array( 'KarberéAktivi' ),
        'Allmessages'               => array( 'MesaciPéro' ),
-       'Allpages'                  => array( 'PeleyPéro' ),
-       'Ancientpages'              => array( 'PeleyKehani' ),
-       'Badtitle'                  => array( 'SernameyoXırab' ),
+       'AllMyUploads'              => array( 'DosyeyMı' ),
+       'Allpages'                  => array( 'PeriPéro' ),
+       'Ancientpages'              => array( 'PeréKehani' ),
+       'Badtitle'                  => array( 'SernameyoXirab' ),
        'Blankpage'                 => array( 'PeréVengi' ),
-       'Block'                     => array( 'Bloqe', 'BloqeIP', 'BloqeyéKarber' ),
-       'Blockme'                   => array( 'BloqeyéMe' ),
-       'Booksources'               => array( 'KıtabeÇıme' ),
-       'BrokenRedirects'           => array( 'HeténayışoXırab' ),
-       'Categories'                => array( 'Kategoriyan' ),
-       'ChangeEmail'               => array( 'EpostaVırnayış' ),
-       'ChangePassword'            => array( 'ParolaBıvırné', 'ParolaResetke' ),
-       'ComparePages'              => array( 'PeraPéverke' ),
-       'Confirmemail'              => array( 'EpostayAraştke' ),
+       'Block'                     => array( 'Bloke', 'BlokeIP', 'BlokeyéKarberi' ),
+       'Booksources'               => array( 'ÇımeyéKıtabi' ),
+       'BrokenRedirects'           => array( 'HetenayışoXırab' ),
+       'Categories'                => array( 'Kategoriy' ),
+       'ChangeEmail'               => array( 'EpostaVurnayış' ),
+       'ChangePassword'            => array( 'ParolaBıvırn', 'ParolaResetk' ),
+       'ComparePages'              => array( 'PeraAteberd' ),
+       'Confirmemail'              => array( 'EpostaAraştk' ),
        'Contributions'             => array( 'Dekerdışi' ),
-       'CreateAccount'             => array( 'HesabVırazé' ),
-       'Deadendpages'              => array( 'PeraBıgiré' ),
-       'DeletedContributions'      => array( 'DekerdışékeBesterneyayé' ),
-       'Disambiguations'           => array( 'Arézekerdış' ),
-       'DoubleRedirects'           => array( 'HetanayışoDılet' ),
-       'EditWatchlist'             => array( 'ListeyaSeyrkerdışiVırnayış' ),
+       'CreateAccount'             => array( 'HesabVıraz' ),
+       'Deadendpages'              => array( 'PeréMerdey' ),
+       'DeletedContributions'      => array( 'DekerdışékBesterneyayé' ),
+       'DoubleRedirects'           => array( 'HetenayışoDilet' ),
+       'EditWatchlist'             => array( 'VırnayışanéListeyaTemaşek' ),
        'Emailuser'                 => array( 'EpostayaKarberi' ),
-       'Export'                    => array( 'Ateberde' ),
-       'Fewestrevisions'           => array( 'TewrtaynRewizyon' ),
-       'FileDuplicateSearch'       => array( 'KopyaydosyaCıgeyrayış', 'DıletdosyaCıgeyrayış' ),
-       'Filepath'                  => array( 'RayaDosya', 'HerunaDosya', 'CayêDosya' ),
-       'Import'                    => array( 'Azeredé', 'Atewrke' ),
-       'Invalidateemail'           => array( 'EpostaAraştkerdışiBıterkné' ),
-       'BlockList'                 => array( 'ListeyéBloqan', 'IPBloqi', 'Blokqeyé_IP' ),
-       'LinkSearch'                => array( 'GreCıgeyrayış' ),
-       'Listadmins'                => array( 'Listeyaİdarekaran' ),
+       'ExpandTemplates'           => array( 'ŞablonaHerake' ),
+       'Export'                    => array( 'Ateberd' ),
+       'Fewestrevisions'           => array( 'TewrtaynRewizyoni' ),
+       'FileDuplicateSearch'       => array( 'KopyadosyaCigérayış', 'DiletdosyaCigérayış' ),
+       'Filepath'                  => array( 'RayaDosya', 'CayDosya' ),
+       'Import'                    => array( 'Azerek' ),
+       'Invalidateemail'           => array( 'EpostayaBetale' ),
+       'BlockList'                 => array( 'ListeyaBloki', 'ListeyaBlokan', 'ListeyaBlokeyéIPi' ),
+       'LinkSearch'                => array( 'GireCıgeyrayış' ),
+       'Listadmins'                => array( 'ListeyaHeténkaran' ),
        'Listbots'                  => array( 'ListeyaBotan' ),
-       'Listfiles'                 => array( 'ListeyaDosyayan', 'DosyayaListeke', 'ListeyéResiman' ),
-       'Listgrouprights'           => array( 'ListeyaHeqandéGruban', 'HeqéGrubdeKarberan' ),
+       'Listfiles'                 => array( 'ListeyDosyayan', 'DosyayaListek', 'ListeyResiman' ),
+       'Listgrouprights'           => array( 'ListeyaHeqanéGruban', 'HeqéGrubéKarberan' ),
        'Listredirects'             => array( 'ListeyaArézekerdışan' ),
-       'Listusers'                 => array( 'ListeyaKarberan', 'KarberaListeke' ),
-       'Lockdb'                    => array( 'DBKilitke' ),
+       'Listusers'                 => array( 'ListeyaKarberan', 'KarberaListek' ),
+       'Lockdb'                    => array( 'DBKilitk' ),
        'Log'                       => array( 'Qeyd', 'Qeydi' ),
        'Lonelypages'               => array( 'PeréBéwayıri' ),
        'Longpages'                 => array( 'PeréDergi' ),
@@ -123,6 +135,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'PerékeStaryayé' ),
        'Protectedtitles'           => array( 'SernameyékeStaryayé' ),
        'Randompage'                => array( 'Raştameye', 'PelayakeRaştamé' ),
+       'RandomInCategory'          => array( 'KategoriyaXoseri' ),
        'Randomredirect'            => array( 'HetenayışoRaştameye' ),
        'Recentchanges'             => array( 'VırnayışéPeyéni' ),
        'Recentchangeslinked'       => array( 'GreyéVırnayışéPeyénan' ),
@@ -139,7 +152,7 @@ $specialPageAliases = array(
        'Uncategorizedpages'        => array( 'PeleyékeKategoriyanébiyé' ),
        'Uncategorizedtemplates'    => array( 'ŞablonékeKategoriyanébiyé' ),
        'Undelete'                  => array( 'Peyserbiya' ),
-       'Unlockdb'                  => array( 'DBKılitiAke' ),
+       'Unlockdb'                  => array( 'DBKılitiAk' ),
        'Unusedcategories'          => array( 'KategoriyayékeNékariyayé' ),
        'Unusedimages'              => array( 'DosyeyékeNékariyayé' ),
        'Unusedtemplates'           => array( 'ŞablonékeNékariyayé' ),
@@ -361,6 +374,7 @@ $messages = array(
 'tog-noconvertlink' => 'Greyê sernami çerx kerdışi bıqefılne',
 'tog-norollbackdiff' => 'Peyserardışi ra dıme ferqi caverde',
 'tog-useeditwarning' => 'Wexto ke mı yew pela nizami be vurnayışanê nêqeydbiyayeyan caverdê, hay be mı ser de',
+'tog-prefershttps' => 'Ronışten akerden de  greyo itimadın bıkarne',
 
 'underline-always' => 'Tım',
 'underline-never' => 'Qet',
@@ -374,50 +388,50 @@ $messages = array(
 'editfont-serif' => 'Babetê serifi',
 
 # Dates
-'sunday' => 'Kırê',
-'monday' => 'Dışeme',
-'tuesday' => 'Sêşeme',
-'wednesday' => 'Çeharşeme',
-'thursday' => 'Pancşeme',
-'friday' => 'Ã\8ane',
-'saturday' => 'Şeme',
-'sun' => 'Krê',
-'mon' => 'Dış',
-'tue' => 'Sêş',
+'sunday' => 'Bazar',
+'monday' => 'Berarek',
+'tuesday' => 'Telete',
+'wednesday' => 'Çarşeme',
+'thursday' => 'Panşeme',
+'friday' => 'Ã\89ne',
+'saturday' => 'Bahdé éni',
+'sun' => 'Baz',
+'mon' => 'Bbz',
+'tue' => 'Tlt',
 'wed' => 'Çrş',
 'thu' => 'Pşm',
 'fri' => 'Êne',
-'sat' => 'Şem',
+'sat' => 'Bdé',
 'january' => 'Çele',
-'february' => 'Sıbate',
-'march' => 'Adar',
-'april' => 'Nisane',
-'may_long' => 'Gulane',
+'february' => 'Zemherı',
+'march' => 'Mert',
+'april' => 'Lisan',
+'may_long' => 'Gúlan',
 'june' => 'Heziran',
-'july' => 'Temuze',
-'august' => 'Tebaxe',
+'july' => 'Temuz',
+'august' => 'Ağustos',
 'september' => 'Keşkelun',
-'october' => 'Tışrino Verên',
-'november' => 'Tışrino Peyên',
-'december' => 'Kanun',
+'october' => 'Cetan',
+'november' => 'Kelverdan',
+'december' => 'Gağand',
 'january-gen' => 'Çele',
-'february-gen' => 'Sıbate',
-'march-gen' => 'Adar',
-'april-gen' => 'Nisane',
-'may-gen' => 'Gulane',
+'february-gen' => 'Zemherı',
+'march-gen' => 'Mert',
+'april-gen' => 'Lisan',
+'may-gen' => 'Gúlan',
 'june-gen' => 'Heziran',
-'july-gen' => 'Temuze',
-'august-gen' => 'Tebaxe',
+'july-gen' => 'Temuz',
+'august-gen' => 'Ağustos',
 'september-gen' => 'Keşkelun',
-'october-gen' => 'Tışrino Verên',
-'november-gen' => 'Tışrino Peyên',
-'december-gen' => 'Kanun',
+'october-gen' => 'Cetan',
+'november-gen' => 'Kelverdan',
+'december-gen' => 'Gağand',
 'jan' => 'Çel',
 'feb' => 'Sbt',
 'mar' => 'Adr',
 'apr' => 'Nsn',
 'may' => 'Gln',
-'jun' => 'Hzr',
+'jun' => 'Hez',
 'jul' => 'Tmz',
 'aug' => 'Tbx',
 'sep' => 'Kşk',
@@ -438,8 +452,8 @@ $messages = array(
 'december-date' => 'Kanun $1',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|Kategoriye|Kategoriy}}',
-'category_header' => 'Pelê ke kategoriya "$1" derê',
+'pagecategories' => '{{PLURAL:$1|Kategori|Kategoriy}}',
+'category_header' => 'Perré ke kategori da "$1" de yé',
 'subcategories' => 'Kategoriyê bınêni',
 'category-media-header' => 'Dosyeyê ke kategoriya "$1" derê',
 'category-empty' => "''Ena kategoriye de hewna qet nuştey ya zi medya çıniyê.''",
@@ -452,71 +466,69 @@ $messages = array(
 'category-file-count' => '<noinclude>{{PLURAL:$2|Na kategoriye tenya dosyayanê cêrênan muhtewa kena.}}</noinclude>
 *Na kategoriye de $2 dosyayan ra {{PLURAL:$1|yew dosya tenêka esta| $1 dosyey asenê}}.',
 'category-file-count-limited' => '{{PLURAL:$1|Dosya cêrêne|$1 Dosyê cêrêni}} na kategoriye derê.',
-'listingcontinuesabbrev' => '(dewam)',
+'listingcontinuesabbrev' => 'dewam...',
 'index-category' => 'Pelê endeksıni',
 'noindex-category' => 'Pelê ke zerrekê cı çıniyo',
 'broken-file-category' => 'Peleye ke gıreyê dosyeyanê ğeletan muhtewa kenê',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => "'''MediaWiki niya ro.'''",
-
-'about' => 'Heqa cı de',
+'about' => 'Heqdé cı',
 'article' => 'Wesiqe',
 'newwindow' => '(pençereyê newey de beno a)',
-'cancel' => 'Bıtexelne',
+'cancel' => 'Bıterkne',
 'moredotdotdot' => 'Vêşi...',
 'morenotlisted' => 'Vêşi lista nêbi...',
-'mypage' => 'Pele',
-'mytalk' => 'Werênayış',
+'mypage' => 'Per',
+'mytalk' => 'Vaten',
 'anontalk' => 'Pela werênayışê nê IPy',
-'navigation' => 'Geyrayış',
+'navigation' => 'Pusula',
 'and' => '&#32;u',
 
 # Cologne Blue skin
 'qbfind' => 'Bıvêne',
 'qbbrowse' => 'Rovete',
-'qbedit' => 'Bıvurne',
+'qbedit' => 'Timar ke',
 'qbpageoptions' => 'Ena pele',
-'qbmyoptions' => 'Pe mı',
+'qbmyoptions' => 'Pe mı',
 'qbspecialpages' => 'Pelê xısusiy',
 'faq' => 'PZP (Persê ke zehf persiyenê)',
 'faqpage' => 'Project: PZP',
 
 # Vector skin
 'vector-action-addsection' => 'Mewzu vıraze',
-'vector-action-delete' => 'Bestere',
-'vector-action-move' => 'Berê',
-'vector-action-protect' => 'Bıpawe',
+'vector-action-delete' => 'Bestern',
+'vector-action-move' => 'Ber',
+'vector-action-protect' => 'Star ke',
 'vector-action-undelete' => 'Esterıtışi peyser bıgê',
 'vector-action-unprotect' => 'Starkerdışi bıvurne',
 'vector-simplesearch-preference' => 'Çuweya cı geyreyış de rehater aktiv ke (Tenya vector skin de)',
-'vector-view-create' => 'Vıraze',
-'vector-view-edit' => 'Bıvurne',
-'vector-view-history' => 'Vurnayışê verêni',
-'vector-view-view' => 'Bıwane',
-'vector-view-viewsource' => 'Çımey bıvêne',
-'actions' => 'Kerdışi',
+'vector-view-create' => 'İycad ke',
+'vector-view-edit' => 'Timar ke',
+'vector-view-history' => 'Verénan bıvin',
+'vector-view-view' => 'Buwan',
+'vector-view-viewsource' => 'Çımi bıvin',
+'actions' => 'Hereketi',
 'namespaces' => 'Cayê namey',
 'variants' => 'Varyanti',
 
 'navigation-heading' => 'Menuya Navigasyoni',
-'errorpagetitle' => 'Xırab',
+'errorpagetitle' => 'Ğeta',
 'returnto' => 'Peyser şo $1.',
 'tagline' => '{{SITENAME}} ra',
-'help' => 'Peşti',
+'help' => 'Desteg',
 'search' => 'Cı geyre',
 'searchbutton' => 'Cı geyre',
 'go' => 'Şo',
 'searcharticle' => 'Şo',
 'history' => 'Verora perer',
-'history_short' => 'Vurnayışê verêni',
+'history_short' => 'Verén',
 'updatedmarker' => 'cıkewtena mına peyêne ra dıme biyo rocane',
-'printableversion' => 'Asayışê çapkerdışi',
+'printableversion' => 'Versiyona Nusnayışi',
 'permalink' => 'Gıreyo jûqere',
 'print' => 'Nusten ke',
 'view' => 'Bıvin',
-'edit' => 'Bıvurnên',
-'create' => 'Vıraze',
+'edit' => 'Timar ke',
+'create' => 'İycad ke',
 'editthispage' => 'Ena pele bıvurne',
 'create-this-page' => 'Na pele bınuse',
 'delete' => 'Bestere',
@@ -524,19 +536,19 @@ $messages = array(
 'undeletethispage' => 'Na perer mebesterne',
 'undelete_short' => '{{PLURAL:$1|Yew vurnayışi|$1 Vurnayışan}} mestere',
 'viewdeleted_short' => '{{PLURAL:$1|Yew vurnayışo esterıte|$1 Vurnayışanê esterıtan}} bımocne',
-'protect' => 'Bıpawe',
+'protect' => 'Star ke',
 'protect_change' => 'bıvurne',
 'protectthispage' => 'Ena pele bıpawe',
 'unprotect' => 'Starkerdışi bıvurne',
 'unprotectthispage' => 'Starkerdışe ena peler bıvurne',
 'newpage' => 'Pera newiye',
 'talkpage' => 'Ena pele sero werêne',
-'talkpagelinktext' => 'Mesac',
+'talkpagelinktext' => 'Vaten',
 'specialpage' => 'Pela xısusiye',
 'personaltools' => 'Hacetê şexsiy',
 'postcomment' => 'Qısımo newe',
 'articlepage' => 'Pela zerreki bıvêne',
-'talk' => 'Werênayış',
+'talk' => 'Vaten',
 'views' => 'Asayışi',
 'toolbox' => 'Haceti',
 'userpage' => 'Pela karberi bıvêne',
@@ -554,7 +566,7 @@ $messages = array(
 'viewcount' => 'Ena pele {{PLURAL:$1|rae|$1 rey}} vêniya.',
 'protectedpage' => 'Pela pawıtiye',
 'jumpto' => 'Şo:',
-'jumptonavigation' => 'karfiyê',
+'jumptonavigation' => 'Pusula',
 'jumptosearch' => 'cı geyre',
 'view-pool-error' => 'Qaytê qısuri mekerên, serverê ma enıka zêde bar gırewto xo ser.
 Hedê xo ra zêde karberi kenê ke seyrê na pele bıkerê.
@@ -566,18 +578,18 @@ $1',
 'pool-errorunknown' => 'Xeta nêzanıtiye',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
-'aboutsite' => 'Heqa {{SITENAME}}i de',
+'aboutsite' => 'Heqdé {{SITENAME}}',
 'aboutpage' => 'Project:Heqdê cı',
 'copyright' => 'Zerrekacı $1 bındı not biya.',
 'copyrightpage' => '{{ns:project}}:Heqa telifi',
 'currentevents' => 'Veng u vac',
-'currentevents-url' => 'Project:Veng u vac',
-'disclaimers' => 'Redê mesuliyeti',
+'currentevents-url' => 'Project:Rocani hadisey',
+'disclaimers' => 'Reddiya mesuliyeti',
 'disclaimerpage' => 'Project:Reddê mesuliyetê bıngey',
 'edithelp' => 'Peştdariya vurnayışi',
-'helppage' => 'Help:Estêni',
+'helppage' => 'Help:Zerrek',
 'mainpage' => 'Pera Seri',
-'mainpage-description' => 'Pela Seri',
+'mainpage-description' => 'Pera Seri',
 'policy-url' => 'Project:Terzê hereketi',
 'portal' => 'Portalê cemaeti',
 'portal-url' => 'Project:Portalê cemaeti',
@@ -598,18 +610,16 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => '"$1" ra ard',
 'youhavenewmessages' => 'To rê $1 esto ($2).',
-'newmessageslink' => 'mesacê şıma',
-'newmessagesdifflink' => 'vurnayışo peyên',
 'youhavenewmessagesfromusers' => 'Zey $1 ra {{PLURAL:$3|zewbi karber|$3 karberi}} ($2) esto.',
 'youhavenewmessagesmanyusers' => '$1 ra tay karberi ($2) dı estê.',
-'newmessageslinkplural' => '{{PLURAL:$1|yew mesac|mesacê newey}}',
-'newmessagesdifflinkplural' => 'peyni {{PLURAL:$1|vurnayış|vurnayışi}}',
+'newmessageslinkplural' => '{{PLURAL:$1|yew mesaco newe|999=mesacê newey}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|vırnayışa|999=vırnayışé}} peyéni',
 'youhavenewmessagesmulti' => '$1 mesaco newe esto',
 'editsection' => 'bıvurne',
 'editold' => 'bıvurne',
 'viewsourceold' => 'çımey cı bıvinê',
 'editlink' => 'bıvurne',
-'viewsourcelink' => 'çımey bıvêne',
+'viewsourcelink' => 'Ã\87ımi bıvin',
 'editsectionhint' => 'Leteyo ke bıvuriyo: $1',
 'toc' => 'Sernameyê meselan',
 'showtoc' => 'bımocne',
@@ -628,21 +638,21 @@ $1',
 'page-atom-feed' => '"$1" Cıresnayışê atomi',
 'feed-atom' => 'Atom',
 'feed-rss' => 'RSS',
-'red-link-title' => '$1 (çınîya)',
+'red-link-title' => '$1 (çınya)',
 'sort-descending' => 'Ratnayışê qemeyayışi',
 'sort-ascending' => 'Ratnayışê Zeydnayışi',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Pele',
+'nstab-main' => 'Wesiqe',
 'nstab-user' => 'Pera Karberi',
-'nstab-media' => 'Pela Medya',
-'nstab-special' => 'Pela xısusiye',
+'nstab-media' => 'Pera Medya',
+'nstab-special' => 'Pera bağsi',
 'nstab-project' => 'Pera proci',
 'nstab-image' => 'Dosya',
 'nstab-mediawiki' => 'Mesac',
 'nstab-template' => 'Şablon',
 'nstab-help' => 'Pela peşti',
-'nstab-category' => 'Kategoriye',
+'nstab-category' => 'Kategori',
 
 # Main script and global functions
 'nosuchaction' => 'Fealiyeto wınasi çıniyo',
@@ -655,8 +665,10 @@ Keyepelê {{SITENAME}} eşkeno xeta eşkera bıkero.',
 Seba lista pelanê xasanê vêrdeyan reca kena: [[Special:SpecialPages|{{int:specialpages}}]].',
 
 # General errors
-'error' => 'Xırab',
-'databaseerror' => 'Xeta serveri',
+'error' => 'Ğeta',
+'databaseerror' => 'Ğetay ardoği',
+'databaseerror-text' => 'Tabanda malumati de ğırabiya persayışi bi
+Na nusteber  zew ğırabin asınena.',
 'databaseerror-query' => 'Perskerdış:$1',
 'databaseerror-function' => 'Fonksiyon: $1',
 'databaseerror-error' => 'Xırab: $1',
@@ -700,7 +712,7 @@ Beno ke, tede yew ya zi zêdê işareti estê ke sernaman de nêxebetiyenê.',
 'wrong_wfQuery_params' => 'wfQuery() parametreyo şaş<br />
 Fonksiyon: $1<br />
 Perse: $2',
-'viewsource' => 'Çımey bıvêne',
+'viewsource' => 'Çımi bıvin',
 'viewsource-title' => "Cı geyrayışê $1'i bıvin",
 'actionthrottled' => 'Kerden peysnaya',
 'actionthrottledtext' => 'Riyê tedbirê anti-spami ra,  wextê do kılmek de şıma nê fealiyeti nêşkenê zaf zêde bıkerê, şıma ki no hedi viyarna ra.
@@ -719,6 +731,8 @@ $2',
 'customjsprotected' => 'Mısadeyê şıma çıniyo ke na pela Java Scripti bıvurnên, çıke na pela xısusiye eyaranê karberan muhtewa kena.',
 'mycustomcssprotected' => "Na pera CSS'i re tenya idarekari şene bıvurne",
 'mycustomjsprotected' => "Na pera JavaScript'i re tenya idarekari şene bıvurne",
+'myprivateinfoprotected' => 'Ğısusi malumatana ğo timar kerdışire icazeta şıma çıniya.',
+'mypreferencesprotected' => 'Terciha timar kerdışire icazeta şıam çıniya.',
 'ns-specialprotected' => 'Pelê xısusiy nênê vurnayış.',
 'titleprotected' => 'Eno [[User:$1|$1]] zerreyê ena peli nişeno vuriye.
 Sebeb: "\'\'$2\'\'".',
@@ -728,7 +742,7 @@ Xızmetkarê  kılitkerdışi wa bewni ro enay wa çımra ravyarno: "$3".',
 'invalidtitle-knownnamespace' => 'Canemey "$2" u metnê "$3" xırabo',
 'invalidtitle-unknownnamespace' => 'Sernameye nêşınasiya yana amraiya canameyo  $1 u metno "$2" xırab',
 'exception-nologin' => 'Şıma cıkewtış nêvıraşto',
-'exception-nologin-text' => 'Na pele ya zi nê karkerdışi rê nê wiki de cıkewtış icab keno.',
+'exception-nologin-text' => 'Na pera ya zi na karkerdışi de  na wiki de [[Special:Userlogin|cıkewtış]] icab keno.',
 
 # Virus scanner
 'virus-badscanner' => "Eyaro şaş: no virus-cıgerayox nêzanyeno: ''$1''",
@@ -739,12 +753,12 @@ Xızmetkarê  kılitkerdışi wa bewni ro enay wa çımra ravyarno: "$3".',
 'logouttext' => "'''Şıma hesabra newke vicyay.'''
 
 Wexta ke verhafızayê cıgerayoxê şıma pak beno no benate de taye peli de hesabe şıma akerde aseno.",
-'welcomeuser' => 'Xeyr ameyê $1',
+'welcomeuser' => 'Ğeyr amey, $1!',
 'welcomecreation-msg' => 'Hesabê şıma abiyo.
 [[Special:Preferences|{{SITENAME}} vurnayişê tercihanê xo]], xo vir ra mekere.',
 'yourname' => 'Nameyê karberi:',
 'userlogin-yourname' => 'Nameyê karberi',
-'userlogin-yourname-ph' => 'Nameyê xoye karberi cıkewe',
+'userlogin-yourname-ph' => 'Namey ğoyé karberi cı kewe',
 'createacct-another-username-ph' => 'Namey karberi de fi',
 'yourpassword' => 'Parola',
 'userlogin-yourpassword' => 'Parola',
@@ -773,12 +787,14 @@ Wexta ke verhafızayê cıgerayoxê şıma pak beno no benate de taye peli de he
 'nologinlink' => 'Yew hesab ake',
 'createaccount' => 'Hesab vıraze',
 'gotaccount' => "Hesabê şıma esto? '''$1'''.",
-'gotaccountlink' => 'Cı kewe',
+'gotaccountlink' => 'Dekewtış',
 'userlogin-resetlink' => 'Melumatê cıkewtışi xo vira kerdê?',
-'userlogin-resetpassword-link' => 'Parolaya xo reset ke',
+'userlogin-resetpassword-link' => 'Şıma parola ke ğo vira?',
 'helplogin-url' => 'Help:Qeydbiyayış',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Desteg be qeydbiyayış ra]]',
+'userlogin-createanother' => 'Zewbi hesab vıraz',
 'createacct-join' => 'Cêr melumatê xo cı ke',
+'createacct-another-join' => 'Malumata hesabdé ğoye newi dekeré cér.',
 'createacct-emailrequired' => 'Adresa e-postey',
 'createacct-emailoptional' => 'Adresa e-postey (mecburi niya)',
 'createacct-email-ph' => 'Adresa e-posteyê xo cıkewe',
@@ -835,24 +851,24 @@ Eke vurnayişê parolayi, şıma nêwaşt ya zi parolayê şıma ameyo şıma vi
 'noemailcreate' => 'Şıma gani yew parolayo meqbul peda bıkeri',
 'passwordsent' => '"$1" No name de yew e-posta erşawiya (ruşya). hesabê xo, şıma wext mesaj gırewt u çax akere.',
 'blocked-mailpassword' => 'Cıkewetışê na keyepel de şıma qedexe biye, ey ra newe yew şifre nêerşawyeno.',
-'eauthentsent' => 'Adreso ke şıma dayo ma, ma yew e-posta rışt uca, o e-posta de kodê araşt kerdış esto.
-Heta ke şıma o e-postaaraşt nêkeri ma yewna e-posta şıma ri nêrışêno.',
+'eauthentsent' => 'Adresok şıma qeyd kerdo wıcayré e-posta rışiyé.
+Hetana şıma ne e-posta néwweyniyé, şımaé zewbi e-posta do nérışiyo.',
 'throttled-mailpassword' => 'Eyarkerdışê parola xora zerreyê {{PLURAL:$1|yew saete|$1 saetan}} erşawiya.
 Seba xırabgurenayışê xızmete ra, her {{PLURAL:$1|yew saete|$1 saetan}} de rey tenya yew eyarkerdışê parola erşawiyeno.',
 'mailerror' => 'Erşawıtışe xetayê e-posta: $1',
 'acct_creation_throttle_hit' => 'Yew ten IP adresê şıma xebıtnayo u kewto no wiki, roco peyin de {{PLURAL:$1|1 hesab|$1 hesab}} vıraşto.
 xulasa ney kesê ke IP adresê şıma xebıtneni hini nêeşkeni ney ra zêdêr hesab akeri.',
-'emailauthenticated' => "Adresê E-posta da şıma '''$2''' seate $3 dı kerdo araşt.",
-'emailnotauthenticated' => 'No format de nuştışê e-postayi qebul nêbeno.
-Yew formato meqbul de adresê e-posta bınuse ya zi veng bıverde.',
+'emailauthenticated' => 'E-postay şıma $2 sehat $3 dı biya araşt',
+'emailnotauthenticated' => 'Adresa e-pota da şıma qebul nébiya.
+Qandé céréna şımaré teba do nérışiyo.',
 'noemailprefs' => 'Hesab biyo a.',
 'emailconfirmlink' => 'E-postayê xo araşt kerê',
 'invalidemailaddress' => 'No format de nuştışê e-postayi qebul nêbeno. Yew formato meqbul de adresê e-posta bınuse ya zi veng bıverde.',
 'cannotchangeemail' => 'E-postay hesabi ena wiki sera nêvurneyêno.',
 'emaildisabled' => 'Na site ra e-posta nêrışêno.',
-'accountcreated' => 'Hesab vıraciya',
+'accountcreated' => 'Hesab iycat bı',
 'accountcreatedtext' => 'Qandê [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) hesabê karberi vıraziyayo.',
-'createaccount-title' => 'Qey {{SITENAME}} newe yew heab vıraştış',
+'createaccount-title' => 'Qandé  {{SITENAME}} hesabé karberi iycat kerdış',
 'createaccount-text' => 'Kesê, be e-posteyê şıma ra {{SITENAME}} ($4) de, ebe nameyê "$2" u parola "$3" ra yew hesab vıraşto.
 Şıma gani cı kewê u parola xo nıka bıvurnê.',
 'usernamehasherror' => 'Namey karberi de karakteri gani têmiyan ra mebê',
@@ -880,7 +896,7 @@ Bıne vındere u newe ra dest pê bıkere.',
 'resetpass_forbidden' => 'parolayi nêvuryayi',
 'resetpass-no-info' => 'şıma gani hesab akere u hona bıeşke bırese cı',
 'resetpass-submit-loggedin' => 'Parola bıvurne',
-'resetpass-submit-cancel' => 'Bıtexelne',
+'resetpass-submit-cancel' => 'Bıterkne',
 'resetpass-wrong-oldpass' => 'parolayo parola maqbul niyo.
 şıma ya parolaye xo vurnayo ya zi parolayo muwaqqat waşto.',
 'resetpass-temp-password' => 'parolayo muweqet:',
@@ -892,6 +908,7 @@ Bıne vındere u newe ra dest pê bıkere.',
 'passwordreset-text-many' => '{{PLURAL:$1|Qande parola reset kerdışi cayanra taynın pırkeri}}',
 'passwordreset-legend' => 'Parola reset ke',
 'passwordreset-disabled' => 'Parola reset kerdış ena viki sera qefılneyayo.',
+'passwordreset-emaildisabled' => 'Na wikid hısusiyeté e-posta dewera vıcyayé',
 'passwordreset-username' => 'Nameyê karberi:',
 'passwordreset-domain' => 'Domain:',
 'passwordreset-capture' => 'neticey e-postay bımocne?',
@@ -926,7 +943,7 @@ Parola vêrdiye: $2',
 'changeemail-none' => '(Çıno)',
 'changeemail-password' => 'Parolaya şımaya {{SITENAME}}i:',
 'changeemail-submit' => 'E-postay xo bıvurne',
-'changeemail-cancel' => 'Bıtexelne',
+'changeemail-cancel' => 'Bıterkne',
 
 # Special:ResetTokens
 'resettokens' => 'Reset fi ye',
@@ -934,6 +951,7 @@ Parola vêrdiye: $2',
 'resettokens-legend' => 'Reset fi ye',
 'resettokens-tokens' => 'Beli kerdeni:',
 'resettokens-token-label' => '$1 (weziyeta newki: $2)',
+'resettokens-watchlist-token' => 'Qandé [[Special:Watchlist|Per vırnayışa lista da temaşan]]  web wari kerdeni (Atom/RSS)',
 'resettokens-done' => 'Reset fi',
 'resettokens-resetbutton' => 'Reset fiyayış weçin',
 
@@ -960,8 +978,8 @@ Parola vêrdiye: $2',
 # Edit pages
 'summary' => "<font style=\"color:Blue\">'''Xulasa:'''</font>",
 'subject' => 'Mewzu/sernuşte:',
-'minoredit' => "<font style=\"color:Green\">'''Eno vurnayışo de qıckeko'''</font>",
-'watchthis' => "<font style=\"color:Green\">'''Ena pele seyr ke'''</font>",
+'minoredit' => "'''Eno vurnayışo de qıckeko'''",
+'watchthis' => "'''Ena pele seyr ke'''",
 'savearticle' => 'Pele qeyd ke',
 'preview' => 'Verqayt',
 'showpreview' => 'Verqayti bımocne',
@@ -1052,7 +1070,7 @@ Cıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:',
 '''hewna qayd nebı!'''",
 'userinvalidcssjstitle' => "'''Teme:''' Mewzuyê \"\$1\" çıniyo.
 Dosyanê be namey .css u .js'i de herfa werdiye bıgurêne, mesela herında {{ns:user}}:Foo/Vector.css'i de {{ns:user}}:Foo/vector.css bınuse.",
-'updated' => '(Newenyaya)',
+'updated' => '(Rozeneya)',
 'note' => "'''Not:'''",
 'previewnote' => "'''Xo vira mekerê ke ena yew verqayta.'''
 Vurnayışê şıma hona qeyd nêbiyo!",
@@ -1118,8 +1136,8 @@ Loge peniye cor de este:",
 'recreate-moveddeleted-warn' => "'''Hişyari: no pel o ke şıma vırazeni vere cû vırazyayo.'''
 
 Diqet bıkeri no vurnayişê şıma re gerek esto:",
-'moveddeleted-notice' => 'Ma ena pele wederna.
-Qe referansi logê wedernayışi bın de mocnayiya.',
+'moveddeleted-notice' => 'Na per besternyaya.
+Qeydé  besternayışi uq hewadayışi cér dé deyayo.',
 'log-fulllog' => 'Temamê rocaneyi bıvine',
 'edit-hook-aborted' => 'Vurnayiş vınderiya.
 Yew sebeb beyan nibı.',
@@ -1188,7 +1206,7 @@ Sebebo ke terefê $3 ra diyao ''$2''",
 'nextrevision' => 'Rewizyono newên →',
 'currentrevisionlink' => 'Tewr halê rocaniye bımocne',
 'cur' => 'ferq',
-'next' => 'badên',
+'next' => 'bahdoyên',
 'last' => 'peyên',
 'page_first' => 'verên',
 'page_last' => 'peyên',
@@ -1200,7 +1218,7 @@ Lecant: '''({{int:cur}})''' = ferqê versiyonê peyêni,
 'histfirst' => 'Verênêr',
 'histlast' => 'Peyênêr',
 'historysize' => '({{PLURAL:$1|1 bayt|$1 bayti}})',
-'historyempty' => '(thal)',
+'historyempty' => '(veng)',
 
 # Revision feed
 'history-feed-title' => 'Tarixê çımraviyarnayışi',
@@ -1251,7 +1269,7 @@ Eke şıma serkari u devam bıkeri [$1 no vurnayiş şıma eşkeni bıvini].",
 'revdelete-nologid-text' => 'Şıma vıraştışê nê fonksiyoni rê ya yew cıkewtışo waşte diyar nêkerdo, ya ki çıkewtışo diyarkerde çıniyo.',
 'revdelete-no-file' => 'Dosya diyarkerdiye çıniya.',
 'revdelete-show-file-confirm' => 'Şıma eminê ke wazenê çımraviyarnayışê esterıtey na dosya "<nowiki>$1</nowiki>" $2 ra $3 de bıvênê?',
-'revdelete-show-file-submit' => 'Eya',
+'revdelete-show-file-submit' => 'E',
 'revdelete-selected' => "'''[[:$1]]: ra {{PLURAL:$2|çımraviyarnayışo weçinıte|çımraviyarnayışê weçinıtey}}'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Qeydbiyayışo weçinıte|Qeydbiyayışê weçinıtey}}:'''",
 'revdelete-text' => "'''Çımraviyarnayışê esterıtey u kerdışi hewna tarixê pele u qeydan de asenê, hema parçeyê zerrekê dinan areze nêbenê.'''
@@ -1262,15 +1280,15 @@ Eke şertê ilawekerdey ke niyê ro, idarekerê bini {{SITENAME}} de nêşenê h
 * Melumatê şexio bêmınasıb
 *: ''adresa keyey u numreyê têlefoni, numreyê siğorta sosyale, uêb.''",
 'revdelete-legend' => 'Şertanê vênayışi rone',
-'revdelete-hide-text' => 'Nuştey çımraviyarnayışi bınımne',
+'revdelete-hide-text' => 'Nuştey revizyoni',
 'revdelete-hide-image' => 'zerreyê dosyay bınımnê',
 'revdelete-hide-name' => "hedef u vaqa' bınımne",
-'revdelete-hide-comment' => 'kılmvatış memocne',
-'revdelete-hide-user' => 'Karber u IP ê ke vurnayiş kerdo bınım.',
+'revdelete-hide-comment' => 'Menıni timar ke',
+'revdelete-hide-user' => 'IP asresa/namey  vırnoği',
 'revdelete-hide-restricted' => 'Malumatan pa serkaran u karberan ra bınım.',
 'revdelete-radio-same' => '(mevurne)',
-'revdelete-radio-set' => 'Eya',
-'revdelete-radio-unset' => '',
+'revdelete-radio-set' => 'Nımnaye',
+'revdelete-radio-unset' => 'Aseno',
 'revdelete-suppress' => 'Hem ê binan ra hem zi serkaran ra malumatan bınım',
 'revdelete-unsuppress' => 'reizyonê ke tepiya anciye serbest ker',
 'revdelete-log' => 'Sebeb:',
@@ -1316,7 +1334,7 @@ Listey xırabi u bloki re pelay [[Special:BlockList|IP'yê ke bloke biyê]] bivi
 'mergehistory-header' => 'No pel, reviyonê yew peli eşkeno yewna pelo newe de piyawano.
 no vurnayişo ke şıma keni kontrol bıkere yew pelo kehen nêbo.',
 'mergehistory-box' => 'revizyonê pelanî yew bike:',
-'mergehistory-from' => 'Pela çimeyî',
+'mergehistory-from' => 'Para Çımi:',
 'mergehistory-into' => 'Pela destinasyonî',
 'mergehistory-list' => 'tarixê vurnayîşî ke eşkeno yew bi.',
 'mergehistory-merge' => '[[:$1]] qey ney revizyonê cêrini [[:$2]] şıma ekeni piyawani. Benatê wexto muwaqqet de piyayanayişê rezizyonan de tuşa radyo bıxebitne.',
@@ -1336,7 +1354,7 @@ no vurnayişo ke şıma keni kontrol bıkere yew pelo kehen nêbo.',
 'mergehistory-revisionrow' => '$1 ($2) $3 . . $4 $5 $6',
 
 # Merge log
-'mergelog' => 'Logê yew kerdişî',
+'mergelog' => 'Qeydé zew kerdışi',
 'pagemerge-logentry' => '[[$1]] u [[$2]] yew kerd (revizyonî heta $3)',
 'revertmerge' => 'Abırnê',
 'mergelogpagetext' => 'Cêr de yew liste esta ke mocnena ra, raya tewr peyêne kamci pela tarixi be a bine ra şanawa pê.',
@@ -1349,7 +1367,7 @@ no vurnayişo ke şıma keni kontrol bıkere yew pelo kehen nêbo.',
 'lineno' => 'Xeta $1i:',
 'compareselectedversions' => 'Rewizyonanê weçineyan pêver ke',
 'showhideselectedversions' => 'Revizyonanê weçinıtan bımocne/bınımne',
-'editundo' => 'peyser bia',
+'editundo' => 'peyser bıgi',
 'diff-empty' => '(Babetna niyo)',
 'diff-multi' => '({{PLURAL:$1|Yew revizyono miyanên|$1 revizyonê miyanêni}} terefê {{PLURAL:$2|yew karberi|$2 karberan}} nêmocno)',
 'diff-multi-manyusers' => '({{PLURAL:$1|jew timar kerdışo qıckeko|$1 timar kerdışo qıckeko}} timar kerdo, $2 {{PLURAL:$2|Karber|karberi}} memocne)',
@@ -1359,7 +1377,7 @@ No normal de werênayış dê pelanê besterneyan dı ena xırabin asena.
 Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} tiya dı] aseno.',
 
 # Search results
-'searchresults' => 'Neticeyê geyrayışi',
+'searchresults' => 'Neticeya geyrayışi',
 'searchresults-title' => 'Qandê "$1" neticeyê geyrayışi',
 'searchresulttext' => 'Zerrey {{SITENAME}} de heqa cıgeyrayışi de seba melumat gırewtışi, şenay qaytê [[{{MediaWiki:Helppage}}|{{int:help}}]] ke.',
 'searchsubtitle' => 'Tı semedê \'\'\'[[:$1]]\'\'\' cıgeyra. ([[Special:Prefixindex/$1|pelê ke pêro be "$1" ra dest niyaê pıra]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|pelê ke pêro be "$1"\' ra gırê xo esto]])',
@@ -1379,11 +1397,11 @@ Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'searchmenu-exists' => "''Ena 'Wikipediya de ser \"[[:\$1]]\" yew pel esto'''",
 'searchmenu-new' => "''Na Wiki de pelay \"[[:\$1]]\" vıraze!'''",
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|pê eno prefix ser pelan de bigêre]]',
-'searchprofile-articles' => 'Pelê tedeestey',
-'searchprofile-project' => 'Pelê yardım u procey',
+'searchprofile-articles' => 'Perré muhteway',
+'searchprofile-project' => 'Pera Destegi uw Procan',
 'searchprofile-images' => 'Multimedya',
-'searchprofile-everything' => 'Her çi',
-'searchprofile-advanced' => 'Raverşiyaye',
+'searchprofile-everything' => 'Heme çi',
+'searchprofile-advanced' => 'Ravérden',
 'searchprofile-articles-tooltip' => '$1 de bigêre',
 'searchprofile-project-tooltip' => '$1 de bigêre',
 'searchprofile-images-tooltip' => 'Dosya cı geyr',
@@ -1397,8 +1415,8 @@ Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'search-suggest' => 'To va: $1',
 'search-interwiki-caption' => 'Projey Bıray',
 'search-interwiki-default' => '$1 neticeyan:',
-'search-interwiki-more' => '(hona)',
-'search-relatedarticle' => 'Eqreba',
+'search-interwiki-more' => '(véşi)',
+'search-relatedarticle' => 'Eleqeyın',
 'mwsuggest-disable' => 'Tewsiyay AJAXi bıgê',
 'searcheverything-enable' => 'cayê nameyê hemi de bigêre',
 'searchrelated' => 'eleqeyın',
@@ -1424,8 +1442,7 @@ Pe verbendi ''all:'', vaceyê xo bıvurni ki contenti hemi cıgeyro (pelanê mı
 'preferences' => 'Tercihi',
 'mypreferences' => 'Tercihi',
 'prefs-edits' => 'Amarê vurnayışan:',
-'prefsnologin' => 'Şıma cıkewtış nêvıraşto',
-'prefsnologintext' => 'Şıma gani be <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} cikewte]</span> ke tercihanê karberi xo eyar bıkerê.',
+'prefsnologintext2' => 'Reca kem  sazé tercihané karberi $1.',
 'changepassword' => 'Parola bıvurne',
 'prefs-skin' => 'Çerme',
 'skin-preview' => 'Verasayış',
@@ -1462,7 +1479,7 @@ Pe verbendi ''all:'', vaceyê xo bıvurni ki contenti hemi cıgeyro (pelanê mı
 'recentchangesdays-max' => 'Tewr zaf $1 {{PLURAL:$1|roc|roci}}',
 'recentchangescount' => 'Amarê vurnayışê ke hesıbyaye deye bımocneyê:',
 'prefs-help-recentchangescount' => 'Ney de vurnayışê peyêni, tarixê pelan u cıkewteni asenê.',
-'savedprefs' => 'Tecihê şıma qeyd biy.',
+'savedprefs' => 'Tecihey şıma qeyd biyey.',
 'timezonelegend' => 'Warey saete:',
 'localtime' => 'saeta mehelliye:',
 'timezoneuseserverdefault' => 'Zey karkerdışê Wiki ($1)',
@@ -1504,26 +1521,25 @@ Na game tepeya nêerziyena.',
 'yourvariant' => 'Varyante miyandê zuwani:',
 'prefs-help-variant' => 'Zerrey ena viki mocnayışi rê varyant yana ortografi re şıre tercihan dê xo.',
 'yournick' => 'imza:',
-'prefs-help-signature' => 'mesajê ke pelê werenayişi de gani pê ney "<nowiki>~~~~</nowiki>" imza bıbi.',
+'prefs-help-signature' => 'Peran de vatenana de vatışi"<nowiki>~~~~</nowiki>" ya do imza bé, no bahdo beno çerğé imza u wahdey zemani',
 'badsig' => 'Îmzayê tu raşt niyo.
 Etiketê HTMLî kontrol bike.',
 'badsiglength' => 'İmzayê şıma zaf dergo.
 $1 gani bınê no {{PLURAL:$1|karakter|karakter}} de bıbo.',
 'yourgender' => 'Çıçiy cı esto?',
 'gender-unknown' => 'Ez detay nivana',
-'gender-male' => 'Ey pera viki vurni',
-'gender-female' => 'Ay pera wiki vurni',
-'prefs-help-gender' => 'Eyar kerdış keyfiyo.
- sofware qey adersê cinsiyet şuxulneno, no malumat umumiyo.Şaryayış malumat wazem.',
+'gender-male' => 'Perané wiki camérd deyne ezo vırnena',
+'gender-female' => 'Perané wiki cıni deyne eza vırnena',
+'prefs-help-gender' => 'Na tercih keyfiya.
+Na nustenek ercana qısan de qandé grameri karneyéna, na malumater herkes şeno bıvino .',
 'email' => 'E-posta',
 'prefs-help-realname' => 'Nameyo raşt waştena şıma rê mendo.
 Eka tu wazene ke nameyo raşt xo bide, ma nameyo raşt ti iştirakanê ti de mocnenê.',
 'prefs-help-email' => 'Dayışê adresa e-postey keyfiyo, labelê seba eyarê parola lazıma, wexto ke şıma naye xo vira kerê.',
-'prefs-help-email-others' => 'Şıma şenê weçinê ke ê bini be yew gırey pela şımaya karberi ya zi pela werênayışi sera şıma de ebe e-poste irtıbat kewê.
-Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena.',
+'prefs-help-email-others' => 'Pera ğoya kerderi de zew link vırazése karberé bini şımaré şenê mesac bırşé. Lakin e-posta adresa şıma héç cayé de niasena.',
 'prefs-help-email-required' => 'E-mail adrese mecburiya.',
-'prefs-info' => 'Melumato bıngeh',
-'prefs-i18n' => 'Beynelmılelkerdış',
+'prefs-info' => 'Melumata şıma',
+'prefs-i18n' => 'Şar şélıg kerdış',
 'prefs-signature' => 'İmza',
 'prefs-dateformat' => 'Formatê tarixi',
 'prefs-timeoffset' => 'Wext offset',
@@ -1539,6 +1555,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'prefs-displaywatchlist' => 'Weçinayışê mocnayışi',
 'prefs-tokenwatchlist' => 'Morge',
 'prefs-diffs' => 'Ferqi',
+'prefs-help-prefershttps' => 'Na tercih, fına dekewten dı bena aktiv.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'e-posta adresi raştayo',
@@ -1570,7 +1587,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 # Groups
 'group' => 'Grube:',
 'group-user' => 'Karberi',
-'group-autoconfirmed' => 'Karberê ke xob xo biyê araşt',
+'group-autoconfirmed' => 'Karberê ke otomatikmen biyê araşt',
 'group-bot' => 'Boti',
 'group-sysop' => 'İdarekari',
 'group-bureaucrat' => 'Burokrati',
@@ -1578,21 +1595,21 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'group-all' => '(pêro)',
 
 'group-user-member' => '{{GENDER:$1|karber}}',
-'group-autoconfirmed-member' => '{{GENDER:$1|Karberê ke xob xo biyê araşt}}',
+'group-autoconfirmed-member' => '{{GENDER:$1|Karberê ke otomatikmen biyê araşt}}',
 'group-bot-member' => '{{GENDER:$1|bot}}',
 'group-sysop-member' => '{{GENDER:$1|İdarekar}}',
 'group-bureaucrat-member' => '{{GENDER:$1|buroqrat}}',
 'group-suppress-member' => '{{GENDER:$1|Temaşekar}}',
 
 'grouppage-user' => '{{ns:project}}:Karberi',
-'grouppage-autoconfirmed' => '{{ns:project}}:Karberê ke xob xo biyê araşt',
+'grouppage-autoconfirmed' => '{{ns:project}}:Karberê ke otomatikmen biyê araşt',
 'grouppage-bot' => '{{ns:project}}:Boti',
 'grouppage-sysop' => '{{ns:project}}:İdarekeri',
 'grouppage-bureaucrat' => '{{ns:project}}:Burokrati',
 'grouppage-suppress' => '{{ns:project}}:Qontrol',
 
 # Rights
-'right-read' => 'Pelan bıwane',
+'right-read' => 'Pera bıwané',
 'right-edit' => 'Pele bıvurne',
 'right-createpage' => 'Pele vıraze (pelê ke ê werênayışi niyê)',
 'right-createtalk' => 'Pela werênayışi vıraze',
@@ -1637,7 +1654,13 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'right-editusercssjs' => 'CSS u dosyanê JSiê karberanê binan sero bıgureye',
 'right-editusercss' => 'Dosyanê CSSiê karberanê binan sero bıgureye',
 'right-edituserjs' => 'Dosyanê JSiê karberanê binan sero bıgureye',
+'right-editmyusercss' => 'CSS dosyaya karberinda ğo timar ke',
+'right-editmyuserjs' => 'JavaScript dosyaya karberinda ğo timar ke',
 'right-viewmywatchlist' => 'Lista seyr de xo bıvin',
+'right-editmywatchlist' => 'Listeya temaşiya karberinda ğo timar ke.Not  tay karfinayışi na icazet nédeyo zi pera dekeno de.',
+'right-viewmyprivateinfo' => 'Bağse malumatané ğo bıasne (e-posta, nameyo raştay vs.)',
+'right-editmyprivateinfo' => 'Bağse malumatané ğo bıvırn (e-posta, nameyo raştay vs.)',
+'right-editmyoptions' => 'Tercihané ğo bıvırn',
 'right-rollback' => 'Lez/herbi vurnayışanê karberê peyêni tekrar bıke, oyo ke yew be yew pelê sero gureyao',
 'right-markbotedits' => 'Vurnayışanê peyd ameyan, vurnayışê boti deye nışan kerê',
 'right-noratelimit' => 'Sinoranê xızi (rate limit) ra tesir nêbi',
@@ -1685,7 +1708,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'action-browsearchive' => 'pelanê esterıteyan bıgeyre',
 'action-undelete' => 'ena pele reyna biyere',
 'action-suppressrevision' => 'revizyone ki nimnaye biye reyna bivîne u restore bike',
-'action-suppressionlog' => 'ena logê xasî bivîne',
+'action-suppressionlog' => 'Ena bağse qeydi bıvin',
 'action-block' => 'enê karberi vurnayışi ra bıreyne',
 'action-protect' => 'seviyeyê pawitişî se ena pele bivurne',
 'action-rollback' => 'Lez/herbi vurnayışanê karberê peyêni tekrar bıke, oyo ke yew be yew pelê sero gureyao',
@@ -1711,25 +1734,29 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'recentchanges' => 'Vurnayışê peyêni',
 'recentchanges-legend' => 'Tercihê vurnayışanê peyênan',
 'recentchanges-summary' => 'Ena pele de wiki sero vurnayışanê peyênan teqib ke.',
+'recentchanges-noresult' => 'Zey kiterandé şıma vırnayış névineya',
 'recentchanges-feed-description' => 'Ena feed dı vurnayişanê tewr peniyan teqip bık.',
 'recentchanges-label-newpage' => 'Enê vurnayışi pelaya newi vıraşt',
 'recentchanges-label-minor' => 'Eno yew vurnayışo qıckeko',
 'recentchanges-label-bot' => 'Yew boti xo het ra no vurnayış vıraşto',
 'recentchanges-label-unpatrolled' => 'Eno vurnayış hewna dewriya nêbiyo',
-'rcnote' => "Bıni dı {{PLURAL:$1|'''1''' vurnayış|peyni de '''$1''' vurnayışi estê}} {{PLURAL:$2|roc|'''$2''' roci}}, hetana $5, $4.",
+'recentchanges-label-plusminus' => 'Ebata na perer ebatta na nımra de vırneya',
+'recentchanges-legend-newpage' => '(Zewbi bıvin [[Special:NewPages|Listeya peran de newan]])',
+'recentchanges-legend-plusminus' => "''(±123)''",
+'rcnote' => "Bıni dı  {{PLURAL:$2|roc|'''$2''' rocan}}  ra {{PLURAL:$1|'''1''' vurnayış|'''$1''' vurnayışi}} éyé cér de yé , $5 ra hetana $4.",
 'rcnotefrom' => "Cêr de '''$2''' ra nata vurnayışiyê asenê (tewr vêşi <b> '''$1'''</b> asenê).",
-'rclistfrom' => '$1 ra vurnayışanê neweyan bımocne',
+'rclistfrom' => '$1 ra tepya vırnayışané newan bıasne',
 'rcshowhideminor' => 'Vurnayışanê werdiyan $1',
 'rcshowhidebots' => 'Botan $1',
 'rcshowhideliu' => 'Karberanê qeydınan $1',
 'rcshowhideanons' => 'Karberê bênamey $1',
 'rcshowhidepatr' => '$1 vurnayışê ke dewriya geyrayê',
 'rcshowhidemine' => 'Vurnayışanê mı $1',
-'rclinks' => 'Peyniya $2 rocan de $1 vurnayışan bımocne <br />$3',
+'rclinks' => '$2 rocan peynira $1 vurnayışan bıasne <br />$3',
 'diff' => 'ferq',
 'hist' => 'verên',
 'hide' => 'Bınımne',
-'show' => 'Bımocne',
+'show' => 'Bıasne',
 'minoreditletter' => 'q',
 'newpageletter' => 'N',
 'boteditletter' => 'b',
@@ -2012,6 +2039,7 @@ keyepel nıka zaf meşğulo yew dema herayi de newe ra tesel bıkerê.',
 'listfiles_size' => 'Gırdiye',
 'listfiles_description' => 'Sılasnayış',
 'listfiles_count' => 'Versiyoni',
+'listfiles-show-all' => 'Asayışa versiyonandé verénan',
 'listfiles-latestversion' => 'Versiyono verin',
 'listfiles-latestversion-yes' => 'E',
 'listfiles-latestversion-no' => 'Nê',
@@ -2112,6 +2140,8 @@ listeya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocn
 # Random page in category
 'randomincategory' => 'Ğoseri pera kategoriya',
 'randomincategory-invalidcategory' => '"$1" namedı kategori çıniya',
+'randomincategory-nopages' => 'Kategori da [[:Category:$1|$1]] de qet  per çıniya.',
+'randomincategory-selectcategory' => 'Pera ke cıra raşt ameye kategori do bıgéri yo: $1 $2.',
 'randomincategory-selectcategory-submit' => 'Şo',
 
 # Random redirect
@@ -2129,7 +2159,7 @@ listeya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocn
 'statistics-pages' => 'Peli',
 'statistics-pages-desc' => 'Pelanê hemî ke wîkî de estê, pelanê mineqeşeyî, redireksiyon ucb... dehil o.',
 'statistics-files' => 'Dosyayê bar biye',
-'statistics-edits' => 'Amarê vurnayîşî ke wextê {{SITENAME}} ronayîşî ra',
+'statistics-edits' => '{{SITENAME}} saz kerdış ra hetana newke amora vırnayışan',
 'statistics-edits-average' => 'Ser her pele de amarê vurnayîşîyê averageyî',
 'statistics-views-total' => 'Yekunî bivîne',
 'statistics-views-total-desc' => 'Peleyê ke çınyê yana xısusiyê e nina zerre nêkerdê',
@@ -2144,6 +2174,8 @@ listeya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocn
 'pageswithprop-text' => 'Na per pimanen pera kena liste.',
 'pageswithprop-prop' => 'Nameyo xısusi:',
 'pageswithprop-submit' => 'Şo',
+'pageswithprop-prophidden-long' => 'Erca metinda derger nımneya ($1)',
+'pageswithprop-prophidden-binary' => 'Erca dıdıyına ($1) nımneyé',
 
 'doubleredirects' => 'Hetenayışê dıletıni',
 'doubleredirectstext' => 'no pel pelê ray motışani liste keno.
@@ -2167,7 +2199,7 @@ gıreyê her satıri de gıreyi; raş motışê yewın u dıyıni esto.
 
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|bayt|bayti}}',
-'ncategories' => '$1 {{PLURAL:$1|Kategoriye|Kategoriy}}',
+'ncategories' => '$1 {{PLURAL:$1|Kategori|Kategoriy}}',
 'ninterwikis' => '$1 {{PLURAL:$1|interwiki|interwikiy}}',
 'nlinks' => '$1 {{PLURAL:$1|link|linkî}}',
 'nmembers' => '$1 {{PLURAL:$1|eza|ezayan}}',
@@ -2201,6 +2233,7 @@ gıreyê her satıri de gıreyi; raş motışê yewın u dıyıni esto.
 'mostrevisions' => 'Pelan ke tewr zaf revizyonî biyê.',
 'prefixindex' => 'Veroleya peley pêro',
 'prefixindex-namespace' => 'Peleyê Veroleyıni ($1 cay nami)',
+'prefixindex-strip' => 'Listeya réz bıyayışi',
 'shortpages' => 'Pelê kılmeki',
 'longpages' => 'Peleyê dergeki',
 'deadendpages' => 'Pelê nêgıredayey',
@@ -2216,13 +2249,14 @@ gıreyê her satıri de gıreyi; raş motışê yewın u dıyıni esto.
 'listusers' => 'Listeyê Karberan',
 'listusers-editsonly' => 'Teyna karberan bimucne ke ey nuştê',
 'listusers-creationsort' => 'goreyê wextê vıraştışi rêz ker',
+'listusers-desc' => 'Kemeyen rézed ratn',
 'usereditcount' => '$1 {{PLURAL:$1|vurnayîş|vurnayîşî}}',
 'usercreated' => '$2 de $1 {{GENDER:$3|viraziya}}',
-'newpages' => 'Pe newey',
+'newpages' => 'Pe newey',
 'newpages-username' => 'Nameyê karberi:',
 'ancientpages' => 'Wesiqeyê ke vurnayışê ciyê peyeni tewr kehani',
-'move' => 'Berdış',
-'movethispage' => 'Ena pele bere',
+'move' => 'Ber',
+'movethispage' => 'Na perer ber',
 'unusedimagestext' => 'Enê dosyey estê, feqet zerrey yew pele de wedardey niyê.
 Xo vira mekerê ke, sıteyê webiê bini şenê direkt ebe URLi yew dosya ra gırê bê, u wına şenê verba gurênayışo feal de tiya hewna lista bê.',
 'unusedcategoriestext' => 'kategoriyê cêrıni bıbo zi çı nêşuxulyena.',
@@ -2294,7 +2328,7 @@ hem zi bıewnê [[Special:WantedCategories|kategori yê ke waziyeni]].',
 # Special:LinkSearch
 'linksearch' => 'Gıreyê teberi cı geyrê',
 'linksearch-pat' => 'bıgêr motif:',
-'linksearch-ns' => 'Cayê namey:',
+'linksearch-ns' => 'Heruna naman:',
 'linksearch-ok' => 'Cı geyre',
 'linksearch-text' => 'Jokeri ê zey "*.wikipedia.org"i benê ke bıgureniyê.
 Tewr senık yew sewiya serêna cayê tesiri lazıma, mesela "*.org".<br />
@@ -2429,14 +2463,12 @@ Ena deme ra, ma qe vurnayışan ser ena pele tı haberdar keni.',
 'enotif_anon_editor' => 'karbero anonim $1',
 'enotif_body' => 'Erciyayê $WATCHINGUSERNAME,
 
-{{SITENAME}} keyepel de no $PAGETITLE pelo sernameyın re $PAGEEDITDATE no tarix de $PAGEEDITOR no karberi $CHANGEDORCREATED. şıma eşkeni bıresi halê no peli re $PAGETITLE_URL na adresi ra.
-
-$NEWPAGE
+$PAGEINTRO $NEWPAGE
 
-beyanatê karber o ke vurnayiş kerdo: $PAGESUMMARY $PAGEMINOREDIT
+eniya timaroği: $PAGESUMMARY $PAGEMINOREDIT
 
-cıresayişê karber o ke vurnayiş kerdo:
-e-posta: $PAGEEDITOR_EMAIL
+Timaroğiya irtibat:
+mail: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
 no pel o ke behs beno heta ziyaret kerdışê yewna heli, mesajê vuriyayişi nêşawiyeno.
@@ -2481,10 +2513,12 @@ Qe qeydê wedarnayışi, $2 bevinin.',
 'deletecomment' => 'Sebeb:',
 'deleteotherreason' => 'Sebebo bin:',
 'deletereasonotherlist' => 'Sebebo bin',
-'deletereason-dropdown' => '*sebebê hewnakerdışê pêroyî
-** talebê nuştekari
-** ihlalê heqê telifi
-** Vandalizm',
+'deletereason-dropdown' => '*Sebebé esterıti
+** Spam
+** Vandalizm
+** İhlala heqdé telifi
+** Waştışé nustoği
+** Xırab hetenayış',
 'delete-edit-reasonlist' => 'Sebebê vurnayışan bıvurne',
 'delete-toobig' => 'no pel, pê $1 {{PLURAL:$1|tene vuriyayiş|tene vuriyayiş}}i wayirê yew tarixo kehen o.
 qey hewna nêşiyayişi wina pelani u {{SITENAME}}nêxerebnayişê keyepeli yew hed niyaya ro.',
@@ -2576,8 +2610,8 @@ Tı eşkeno seviyeye kılit kerdışi bıvurno, feqat tı nıeşken "cascading p
 
 # Restrictions (nouns)
 'restriction-edit' => 'Bıvurne',
-'restriction-move' => 'Berê',
-'restriction-create' => 'Vıraze',
+'restriction-move' => 'Ber',
+'restriction-create' => 'İycad ke',
 'restriction-upload' => 'Bar ke',
 
 # Restriction levels
@@ -2635,10 +2669,9 @@ belka cıwa ver hewn a biyo..',
 $1',
 'undelete-show-file-confirm' => '"<nowiki>$1</nowiki>" şıma emin î dosyaya revizyonê no $2 $3 tarixi bıvini?',
 'undelete-show-file-submit' => 'E',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
-'namespace' => 'Cayê namey:',
+'namespace' => 'Heruna naman:',
 'invert' => 'Weçinıtışo peyserki',
 'tooltip-invert' => 'nameyo ke nışan biyo (u nameyo elekeyın zi nışanyyayo se) vurnayışan  zerrekan nımtışi re ena dore tesdiqi nışan kerê',
 'namespace_association' => 'Cayê nameyanê elaqedaran',
@@ -2769,7 +2802,7 @@ Cıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:',
 'ipblocklist-empty' => 'Lista kılitkerdışi venga.',
 'ipblocklist-no-results' => 'Adresa IPya waştiye ya zi namey karberi kılit nêbiyo.',
 'blocklink' => 'kılit ke',
-'unblocklink' => 'a ke',
+'unblocklink' => 'bloqi hewad',
 'change-blocklink' => 'kılitkerdışi bıvurne',
 'contribslink' => 'iştıraqi',
 'emaillink' => 'e-poste bırışe',
@@ -2897,14 +2930,14 @@ Yewna name bınus.',
 'movepage-page-moved' => 'pelê $1i kırışiya pelê $2i.',
 'movepage-page-unmoved' => 'pelê $1i nêkırışiyeno sernameyê $2i.',
 'movepage-max-pages' => 'tewr ziyed $1 {{PLURAL:$1|peli|peli}} kırışiya u hıni ziyedê ıney otomotikmen nêkırışiyeno.',
-'movelogpage' => 'Qeydê berdışi',
+'movelogpage' => 'Qeydé berdışi',
 'movelogpagetext' => 'nameyê liste ya ke cêr de yo, pelê vuriyayeyani mocneno',
 'movesubpage' => '{{PLURAL:$1|Subpage|pelê bınıni}}',
 'movesubpagetext' => '{{PLURAL:$1|pelê bınıni yê|pelê bınıni yê}} no $1 peli cer de yo.',
 'movenosubpage' => 'pelê bınıni yê no peli çino.',
 'movereason' => 'Sebeb:',
 'revertmove' => 'peyser bia',
-'delete_and_move' => 'Bestere u bere',
+'delete_and_move' => 'Bestern u ber',
 'delete_and_move_text' => '==gani hewn a bıbıo/bıesteriyo==
 
 " no [[:$1]]" name de yew pel ca ra esto. şıma wazeni pê hewn a kerdışê ey peli vurnayişê nameyi bıkeri?',
@@ -2959,7 +2992,7 @@ ma vaci: qey pelê "[[{{MediaWiki:Mainpage}}]]i " [[{{#Special:Export}}/{{MediaW
 'allmessagesdefault' => 'Metnê mesacê hesabiyayey',
 'allmessagescurrent' => 'Nuşteyê mesacê rocaney',
 'allmessagestext' => 'na liste, listeya mesajê cayê nameyê wikimedya yo.
-eke şıma qayili paşt bıdi mahalli kerdışê wikimedyayi, kerem kerê pelê [//www.mediawiki.org/wiki/Localisation mahalli kerdışê wikimedyayi] u [//translatewiki.net translatewiki.net] ziyaret bıkerê.',
+eke şıma qayili paşt bıdi mahalli kerdışê wikimedyayi, kerem kerê pelê [https://www.mediawiki.org/wiki/Localisation mahalli kerdışê wikimedyayi] u [//translatewiki.net translatewiki.net] ziyaret bıkerê.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' qefelnaye yo u ey ra '''{{ns:special}}:Allmessages''' karkerdışi re akerde niyo.",
 'allmessages-filter-legend' => 'Avrêc',
 'allmessages-filter' => 'goreyê xususi kerdışi re filtre bıker',
@@ -3055,16 +3088,16 @@ dosyaya emaneti vindbiyo',
 'javascripttest-qunit-heading' => 'MediaWiki JavaScript QUnit test suite',
 
 # Tooltip help for the actions
-'tooltip-pt-userpage' => 'Pelaya karberi',
+'tooltip-pt-userpage' => 'Pera şımaya karberi',
 'tooltip-pt-anonuserpage' => 'pelê karberê IPyi',
-'tooltip-pt-mytalk' => 'Pela ya Qıse vatışi',
+'tooltip-pt-mytalk' => 'Pera şımaya vaten',
 'tooltip-pt-anontalk' => 'vurnayiş ê ke no Ipadresi ra biyo muneqeşa bıker',
 'tooltip-pt-preferences' => 'Tercihê to',
 'tooltip-pt-watchlist' => 'Lista pelanê ke to gırewtê seyrkerdış',
 'tooltip-pt-mycontris' => 'Yew lista iştıraqanê şıma',
 'tooltip-pt-login' => 'Mayê şıma ronıştış akerdışi rê dawet keme; labelê ronıştış mecburi niyo',
 'tooltip-pt-anonlogin' => 'Seba cıkewtışê şıma rê dewato; labelê, no zeruri niyo',
-'tooltip-pt-logout' => 'Bıveciye',
+'tooltip-pt-logout' => 'Vıcyayış',
 'tooltip-ca-talk' => 'Zerrey pela sero werênayış',
 'tooltip-ca-edit' => 'Tı şenay na pele bıvurnê.
 Kerem ke, qeydkerdış ra ver gocega verqayti bıxebetne.',
@@ -3083,7 +3116,7 @@ Kerem ke, qeydkerdış ra ver gocega verqayti bıxebetne.',
 'tooltip-search-go' => 'Ebe nê namey tami şo yew pela ke esta',
 'tooltip-search-fulltext' => 'Nê  metni peran dı cı geyre',
 'tooltip-p-logo' => 'Pela seri bıvênên',
-'tooltip-n-mainpage' => 'Şo pela seri',
+'tooltip-n-mainpage' => 'Şo pera seri',
 'tooltip-n-mainpage-description' => 'Şo pela seri',
 'tooltip-n-portal' => 'Heqa projey de, kes çı şeno bıkero, çıçiyo koti deyo',
 'tooltip-n-currentevents' => 'Vurnayışanê peyênan de melumatê pey bıvêne',
@@ -3125,6 +3158,7 @@ Kerem ke, qeydkerdış ra ver gocega verqayti bıxebetne.',
 Tı eşkeno yew sebeb bınus.',
 'tooltip-preferences-save' => 'Terciha qeyd ke',
 'tooltip-summary' => 'Yew xulasaya kilm binuse',
+'interlanguage-link-title' => '$1 - $2',
 
 # Scripts
 'common.js' => '/* Any JavaScript here will be loaded for all users on every page load. */',
@@ -3152,12 +3186,14 @@ Tı eşkeno yew sebeb bınus.',
 'spam_reverting' => 'agêriyeno revizyon o ke tawayê $1 ıney piya çiniyo',
 'spam_blanking' => 'Revizyonê gredê $1 vineyay, wa weng kero',
 'spam_deleting' => 'Revizyonê gredê $1 vineyay, wa besterneyê',
+'simpleantispam-label' => "Cerbnayışa anti-spami.
+Ney '''Mefiyé de'''!",
 
 # Info page
 'pageinfo-title' => 'Heq tê "$1"\'i',
 'pageinfo-not-current' => 'Qısur de mevêne, rewizyonanê verênan rê nê melumatan dayış mumkın niyo',
 'pageinfo-header-basic' => 'Seron zanayış',
-'pageinfo-header-edits' => 'Vurnayışê verêni',
+'pageinfo-header-edits' => 'Veréna timar kerdışi',
 'pageinfo-header-restrictions' => 'Sıtarkerdışê pele',
 'pageinfo-header-properties' => 'Xısusiyetê pele',
 'pageinfo-display-title' => 'Sernuştey bımocne',
@@ -3165,6 +3201,7 @@ Tı eşkeno yew sebeb bınus.',
 'pageinfo-length' => 'Derdeya pela (bayti heta)',
 'pageinfo-article-id' => 'Kamiya pele',
 'pageinfo-language' => 'Zıwanê zerreyê pele',
+'pageinfo-content-model' => 'Modela zerreka perer',
 'pageinfo-robot-policy' => 'Weziyetê motor de cıgeyrayışi',
 'pageinfo-robot-index' => 'İndeksbiyayen',
 'pageinfo-robot-noindex' => 'İndeksnêbiyayen',
@@ -3220,9 +3257,9 @@ Tı eşkeno yew sebeb bınus.',
 'markedaspatrollederrornotify' => 'Nışan kerdışê dewriyey nêbı',
 
 # Patrol log
-'patrol-log-page' => 'Logê devriye',
+'patrol-log-page' => 'Qeydé çımsernayoğan',
 'patrol-log-header' => 'Ena listeyê logi revizyonê devriyeyi mocneno.',
-'log-show-hide-patrol' => '$1 logê devriye',
+'log-show-hide-patrol' => 'Qeydé Çımsernayoğan $1',
 
 # Image deletion
 'deletedrevision' => 'Veriyono kihan $1 wederna',
@@ -3253,7 +3290,7 @@ Gurênayışê nae de, beno ke sistemê şıma zerar bıvêno.",
 'svg-long-desc' => 'Dosyay SVG, zek vanê $1 × $2 piksela, ebatê dosya: $3',
 'svg-long-desc-animated' => 'SVG dosya, nominalin $1 × $2 piksela, ebatê dosya: $3',
 'svg-long-error' => "Nêmeqbul dosyaya SVG'i: $1",
-'show-big-image' => 'Tam agoznayen',
+'show-big-image' => 'Oricinal dosya',
 'show-big-image-preview' => "Verqayd dergiya: $1'i.",
 'show-big-image-other' => 'Zewmi{{PLURAL:$2|Vılêşnayış|Vılêşnayışê}}: $1.',
 'show-big-image-size' => '$1 × $2 piksel',
@@ -3275,7 +3312,7 @@ Gurênayışê nae de, beno ke sistemê şıma zerar bıvêno.",
 'noimages' => 'Çik çini yo.',
 'ilsubmit' => 'Cı geyre',
 'bydate' => 'goreyê zemani',
-'sp-newimages-showfrom' => 'Dosyayê newi ke $2, $1 ra dest pe keni bimocne',
+'sp-newimages-showfrom' => '$1, sehat $2 ra tepya dosyayané newan bıasné',
 
 # Video information, used by Language::formatTimePeriod() to format lengths in the above messages
 'video-dims' => '$1, $2 × $3',
@@ -3535,7 +3572,7 @@ Eg ena dosya, kondisyonê orcinali ra bıvuriya, belki detayanê hemi nıeseno.'
 'exif-writer' => 'Nuştekar',
 'exif-languagecode' => 'Zıwan',
 'exif-iimversion' => 'Verqaydê IIM',
-'exif-iimcategory' => 'Kategoriye',
+'exif-iimcategory' => 'Kategori',
 'exif-iimsupplementalcategory' => 'Oleyê Kategoriyan',
 'exif-datetimeexpires' => 'No peyra mekarênê',
 'exif-datetimereleased' => 'Bıroşe',
@@ -3822,7 +3859,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'Ena dosya bıvurne pe yew programê harici',
-'edit-externally-help' => '(Qe informasyonê zafyer ena bevinin [//www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
+'edit-externally-help' => '(Qe informasyonê zafyer ena bevinin [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'pêro',
@@ -3931,6 +3968,7 @@ Ma rica keno tesdiq bike ke ti raştî wazeno eno pel bivirazo.",
 'percent' => '$1%',
 'parentheses' => '($1)',
 'brackets' => '[$1]',
+'quotation-marks' => '"$1".',
 
 # Multipage image navigation
 'imgmultipageprev' => '← peleyê verin',
@@ -4100,7 +4138,7 @@ Ti hem zi eşkeno [[Special:EditWatchlist|use the standard editor]].',
 'version-version' => '(Versiyon $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Lisans',
-'version-poweredby-credits' => "Ena wiki, dezginda '''[//www.mediawiki.org/ MediaWiki]''' ya piya vıraziyaya, heqê telifi © 2001-$1 $2.",
+'version-poweredby-credits' => "Ena wiki, dezginda '''[https://www.mediawiki.org/ MediaWiki]''' ya piya vıraziyaya, heqê telifi © 2001-$1 $2.",
 'version-poweredby-others' => 'Zewmi',
 'version-poweredby-translators' => "Açernere translatewiki.net'i",
 'version-credits-summary' => 'Ma qayılime ke [[Special:Version|MediaWiki]] rê ke kami destek dayo wa mayê vanime inan bışınasne.',
@@ -4121,10 +4159,11 @@ enê programiya piya [{{SERVER}}{{SCRIPTPATH}}/COPYING jew kopyay lisans dê GNU
 # Special:Redirect
 'redirect' => "Hetenayışa dosyay, karberi yana  rewizyona ID'i",
 'redirect-legend' => 'Hetenayışa dosya yana pela',
+'redirect-summary' => "Na pera bağsi şıma bena dosya (cıré namey dosya deyeno), zu per (zu ID'A rewizyoni deyaya) yana cıré zu pera karberi beno herın (kamiya karberiya amoriyen). Karkerden: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], yana  [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Şo',
 'redirect-lookup' => 'Bewni',
 'redirect-value' => 'Erc:',
-'redirect-user' => "ID'ê Karberi",
+'redirect-user' => 'Kamiya Karberi:',
 'redirect-revision' => 'Rewizyona pela',
 'redirect-file' => 'Namey dosya',
 'redirect-not-exists' => 'Erc nêvineyê',
@@ -4142,10 +4181,9 @@ enê programiya piya [{{SERVER}}{{SCRIPTPATH}}/COPYING jew kopyay lisans dê GNU
 
 # Special:SpecialPages
 'specialpages' => 'Pelê xısusiy',
-'specialpages-note' => '----
-* Xısusi pelaya normal
-* <span class="mw-specialpagerestricted">Xısusi peleyê keı rê ray nê deyaya.</span>
-* <strong class="mw-specialpagerestricted">Peleya xısusiya ke grota verhefıza.</strong>',
+'specialpages-note-top' => 'Kıtabek',
+'specialpages-note' => '*Normal pera bağsi.
+* <span class="mw-specialpagerestricted">Peré bağseyé ke groté ver hafıza.</span>',
 'specialpages-group-maintenance' => 'Raporê tepıştışi',
 'specialpages-group-other' => 'Pelê xasiyê bini',
 'specialpages-group-login' => 'Cı kewe / hesab vıraze',
@@ -4207,6 +4245,7 @@ satır ê ke pê ney # # destpêkenê zey mışore/mıjore muamele vineno.
 'dberr-problems' => 'Mayê muxulêm! Ena sita dı newke xırabiya teknik esta.',
 'dberr-again' => 'Yew di dekika vinder u hin bar bike.',
 'dberr-info' => '(Erzmelumati ra xızmetkari nêreseno: $1)',
+'dberr-info-hidden' => '(Ardendé erz malumatiya gredayışo nébeno)',
 'dberr-usegoogle' => 'Ti eşkeno hem zi ser Google de bigêre.',
 'dberr-outofdate' => 'Ekê raten da ma deyê belki zi newen niyo qandê coy diqet kerê.',
 'dberr-cachederror' => 'Pel ke ti wazeno yew kopyayê cacheyî ay esto, ay belki rocaniyeyo.',
@@ -4347,10 +4386,30 @@ satır ê ke pê ney # # destpêkenê zey mışore/mıjore muamele vineno.
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|saniye|saniyeyan}}',
 'limitreport-walltime' => 'Raştay demdı bıkarn',
 'limitreport-walltime-value' => '$1 {{PLURAL:$1|saniye|saniyeyan}}',
+'limitreport-ppvisitednodes' => 'Amariya ziyaretda gozgıreya verkarkerdoği',
+'limitreport-ppgeneratednodes' => 'Amariya vıraştışda gozgırandé vekarkerdoği',
+'limitreport-postexpandincludesize' => 'Ebata herayina rışteri dahil a.',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bayt|bayti}}',
 'limitreport-templateargumentsize' => 'Ebata hacetandi şablonan',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bayt|bayti}}',
 'limitreport-expansiondepth' => 'Tewr veşi herayina dergbiyayışi',
 'limitreport-expensivefunctioncount' => 'Amoriya fonksiyonde vay agozni',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'şablonan hêra ker',
+'expand_templates_intro' => 'Na pela xususi metın geno u şablonê ke tedeyê reyna reyna hêra keno.
+U hem zi nê fonksiyonan hêra keno
+<nowiki>{{</nowiki>#language:…}}</code>, u zey nê parametreyan
+<nowiki>{{</nowiki>CURRENTDAY}}</code>
+Eneri Medya wiki sera xo keno.',
+'expand_templates_title' => 'Sernameyê weziyeti, misal qandê {{FULLPAGENAME}}.:',
+'expand_templates_input' => 'sernameyê cıkewtışi:',
+'expand_templates_output' => 'netice',
+'expand_templates_xml_output' => 'XML vıraştış',
+'expand_templates_ok' => 'temam',
+'expand_templates_remove_comments' => 'Tefsiran wedare',
+'expand_templates_remove_nowiki' => 'neticeyan de etiketê <nowiki> yan çap bıker',
+'expand_templates_generate_xml' => 'Dara XML arêdayoği bımocne',
+'expand_templates_preview' => 'Verqayt',
+
 );
index ef04517..9f63fc2 100644 (file)
@@ -62,7 +62,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Nejstarše_boki' ),
        'Blankpage'                 => array( 'Prozny_bok' ),
        'Block'                     => array( 'Blokěrowaś' ),
-       'Blockme'                   => array( 'Proksy-blokěrowanje' ),
        'Booksources'               => array( 'Pytaś_pó_ISBN' ),
        'BrokenRedirects'           => array( 'Njefunkcioněrujuce_dalejpósrědnjenja' ),
        'Categories'                => array( 'Kategorije' ),
@@ -72,7 +71,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Wužywarske_konto_załožyś' ),
        'Deadendpages'              => array( 'Boki_kenž_su_slěpe_gasy' ),
        'DeletedContributions'      => array( 'Wulašowane_pśinoski' ),
-       'Disambiguations'           => array( 'Wótkaze_ku_rozjasnjenju_wopśimjeśa' ),
        'DoubleRedirects'           => array( 'Dwójne_dalejpósrědnjenja' ),
        'Emailuser'                 => array( 'E-mail' ),
        'Export'                    => array( 'Eksportěrowaś' ),
@@ -168,12 +166,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Doglědowane změny w aktualnych změnach schowaś',
 'tog-newpageshidepatrolled' => 'Doglědowane boki z lisćiny nowych bokow schowaś',
 'tog-extendwatchlist' => 'Wobglědowańku wócyniś, aby wšě změny pokazał, nic jano nejnowše',
-'tog-usenewrc' => 'Kupkowe změny pó boku w aktualnych změnach a wobglědowanjach (trjeba JavaScript)',
+'tog-usenewrc' => 'Kupkowe změny pó boku w aktualnych změnach a wobglědowanjach',
 'tog-numberheadings' => 'Nadpisma awtomatiski numerěrowaś',
-'tog-showtoolbar' => 'Wobźěłańsku lejstwu pokazaś (pótrjebujo JavaScript)',
-'tog-editondblclick' => 'Boki z dwójnym kliknjenim wobźěłaś (pótrjebujo JavaScript)',
+'tog-showtoolbar' => 'Wobźěłowańsku rědku pokazaś',
+'tog-editondblclick' => 'Boki z dwójnym kliknjenim wobźěłaś',
 'tog-editsection' => 'Wobźěłanje wótstawkow pśez wótkaze [wobźěłaś] zmóžniś',
-'tog-editsectiononrightclick' => 'Wobźěłanje wótstawkow pśez kliknjenje z pšaweju tastu myški zmóžniś (JavaScript)',
+'tog-editsectiononrightclick' => 'Wobźěłowanje wótrězkow pśez kliknjenje z pšaweju tastu myški zmóžniś',
 'tog-showtoc' => 'Wopśimjeśe pokazaś, jolic ma bok wěcej nježli 3 nadpisma',
 'tog-rememberpassword' => 'Z toś tym wobglědowakom pśizjawjony wóstaś (za maksimalnje $1 {{PLURAL:$1|źeń|dnja|dny|dnjow}})',
 'tog-watchcreations' => 'Boki, kótarež napórajom a dataje, kótarež nagrawam, wobglědowaś',
@@ -191,7 +189,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Licbu wobglědujucych wužywarjow pokazaś',
 'tog-oldsig' => 'Eksistěrujuca signatura:',
 'tog-fancysig' => 'Ze signaturu kaž z wikitekstom wobchadaś (bźez awtomatiskego wótkaza)',
-'tog-uselivepreview' => 'Live-pśeglěd wužywaś (JavaScript) (eksperimentelnje)',
+'tog-uselivepreview' => 'Live-pśeglěd wužywaś (eksperimentelnje)',
 'tog-forceeditsummary' => 'Warnowaś, gaž pśi składowanju zespominanje felujo',
 'tog-watchlisthideown' => 'Móje změny na wobglědowańskej lisćinje schowaś',
 'tog-watchlisthidebots' => 'Změny awtomatiskich programow (botow) na wobglědowańskej lisćinje schowaś',
@@ -204,6 +202,7 @@ $messages = array(
 'tog-showhiddencats' => 'Schowane kategorije pokazaś',
 'tog-norollbackdiff' => 'Rozdźěl pó slědkstajenju zanjechaś',
 'tog-useeditwarning' => 'Warnowaś, gaž bok spušća se z njeskłaźonymi změnami',
+'tog-prefershttps' => 'Pśi pśizjawjenju pśecej wěsty zwisk wužywaś',
 
 'underline-always' => 'pśecej',
 'underline-never' => 'žednje',
@@ -267,6 +266,18 @@ $messages = array(
 'oct' => 'okt',
 'nov' => 'now',
 'dec' => 'dec',
+'january-date' => '$1. januara',
+'february-date' => '$1. februara',
+'march-date' => '$1. měrca',
+'april-date' => '$1. apryla',
+'may-date' => '$1. maja',
+'june-date' => '$1. junija',
+'july-date' => '$1. julija',
+'august-date' => '$1. awgusta',
+'september-date' => '$1. septembra',
+'october-date' => '$1. oktobra',
+'november-date' => '$1. nowembra',
+'december-date' => '$1. decembra',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Kategorija|Kategoriji|Kategorije}}',
@@ -292,7 +303,7 @@ $messages = array(
 'newwindow' => '(se wótcynijo w nowem woknje)',
 'cancel' => 'Pśetergnuś',
 'moredotdotdot' => 'Wěcej…',
-'morenotlisted' => 'Dalšne njepódane...',
+'morenotlisted' => 'Toś ta lisćina njejo dopołna.',
 'mypage' => 'Bok',
 'mytalk' => 'Diskusija',
 'anontalk' => 'Diskusija z toś teju IP',
@@ -348,6 +359,7 @@ $messages = array(
 'create-this-page' => 'Bok wuźěłaś',
 'delete' => 'Wulašowaś',
 'deletethispage' => 'Toś ten bok wulašowaś',
+'undeletethispage' => 'Toś ten bok wótnowiś',
 'undelete_short' => '{{PLURAL:$1|1 wersiju|$1 wersiji|$1 wersije}} nawrośiś.',
 'viewdeleted_short' => '{{PLURAL:$1|jadnu wulašowanu změnu|$1 wulašowanej změnje|$1 wulašowane změny|$1 wulašowanych změnow}} se woglědaś',
 'protect' => 'Šćitaś',
@@ -364,7 +376,7 @@ $messages = array(
 'articlepage' => 'Nastawk',
 'talk' => 'Diskusija',
 'views' => 'Naglědy',
-'toolbox' => 'Pomocne srědki',
+'toolbox' => 'Rědy',
 'userpage' => 'Wužywarski bok pokazaś',
 'projectpage' => 'Projektowy bok pokazaś',
 'imagepage' => 'Datajowy bok se woglědaś',
@@ -394,7 +406,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Wó {{GRAMMAR:lokatiw|{{SITENAME}}}}',
 'aboutpage' => 'Project:Wó_{{GRAMMAR:lokatiw|{{SITENAME}}}}',
-'copyright' => 'Wopśimjeśe stoj pód $1.',
+'copyright' => 'Wopśimjeśe stoj pód $1 k dispoziciji, jolic njejo se hynac pódało.',
 'copyrightpage' => '{{ns:project}}:Stwóriśelske pšawo',
 'currentevents' => 'Aktualne tšojenja',
 'currentevents-url' => 'Project:Aktualne tšojenja',
@@ -420,12 +432,10 @@ $1',
 'ok' => 'Pytaś',
 'retrievedfrom' => 'Z {{GRAMMAR:genitiw|$1}}',
 'youhavenewmessages' => 'Maš $1 ($2).',
-'newmessageslink' => 'nowe powěsći',
-'newmessagesdifflink' => 'slědna změna',
 'youhavenewmessagesfromusers' => 'Maš $1 wót {{PLURAL:$3|drugego wužywarja|$3 wužywarjowu|$3 wužywarjow|$3 wužywarjow}} ($2).',
 'youhavenewmessagesmanyusers' => 'Maš $1 wót wjele wužywarjow ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|nowa powěsć|nowej powěsći|nowe powěsći|nowe powěsći}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|slědna změna|slědnej změnje|slědne změny|slědne změny}}',
+'newmessageslinkplural' => '{{PLURAL:$1|nowa powěsć|nowej powěsći|nowe powěsći}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|slědna změna|slědnej změnje|slědne změny}}',
 'youhavenewmessagesmulti' => 'Maš nowe powěsći: $1',
 'editsection' => 'wobźěłaś',
 'editold' => 'wobźěłaś',
@@ -477,6 +487,12 @@ Płaśece specialne boki namakaju se pód [[Special:SpecialPages|lisćinu specia
 # General errors
 'error' => 'Zmólka',
 'databaseerror' => 'Zmólka w datowej bance',
+'databaseerror-text' => 'Zmólka w datowej bance jo nastała.
+To móžo na programowu zmólku w softwarje pokazaś.',
+'databaseerror-textcl' => 'Zmólka w datowej bance jo nastała.',
+'databaseerror-query' => 'Wótpšašanje: $1',
+'databaseerror-function' => 'Funkcija: $1',
+'databaseerror-error' => 'Zmólka: $1',
 'laggedslavemode' => 'Glědaj: Jo móžno, až pokazany bok nejaktualnjejše změny njewopśimjejo.',
 'readonly' => 'Datowa banka jo zacynjona',
 'enterlockreason' => 'Pšosym zapódaj pśicynu za zacynjenje datoweje banki a informaciju, ga buźo zasej pśistupna',
@@ -509,6 +525,7 @@ Pšosym daj to a pśisłušny URL [[Special:ListUsers/sysop|administratoroju]] k
 'cannotdelete-title' => 'Bok "$1" njedajo se lašowaś',
 'delete-hook-aborted' => 'Wulašowanje pśez kokulu pśetergnjone.
 Njejo žedno wujasnjenje.',
+'no-null-revision' => 'Nowa nulowa wersija za bok "$1" njedajo se napóraś',
 'badtitle' => 'Njepłaśecy nadpis',
 'badtitletext' => 'Nadpis pominanego boka jo był njepłaśecy, prozny abo njekorektny nadpis, póchadajucy z mjazyrěcnego abo interwikijowego wótkaza. Snaź wopśimjejo jadno abo wěcej znamuškow, kótarež njejsu w nadpisach dowólone.',
 'perfcached' => 'Toś te daty póchadaju z pufrowaka a mógu snaź njeaktualne byś. Maksimalnje {{PLURAL:$1|jaden wuslědk stoj|$1 wuslědka stojtej|$1 wuslědki stoje|$1 wuslědkow stoj}} w pufrowaku k dispoziciji.',
@@ -532,6 +549,10 @@ Aby pśełožki za wšykne wikije pśidał abo změnił, wužywaj pšosym [//tra
 'namespaceprotected' => "Njejsy wopšawnjony, boki w rumje: '''$1''' wobźěłaś.",
 'customcssprotected' => 'Njamaš pšawo, aby toś ten CSS-bok wobźěłał, dokulaž wopśimujo  wósobinske nastajenja drugego wužywarja.',
 'customjsprotected' => 'Njamaš pšawo, aby toś ten JavaScriptowy bok wobźěłał, dokulaž wopśimujo  wósobinske nastajenja drugego wužywarja.',
+'mycustomcssprotected' => 'Njamaš pšawo toś ten CSS-bok wobźěłaś.',
+'mycustomjsprotected' => 'Njamaš pšawo toś ten JavaScript-bok wobźěłaś.',
+'myprivateinfoprotected' => 'Njamaš pšawo swóje priwatne informacije wobźěłaś.',
+'mypreferencesprotected' => 'Njamaš pšawo swóje nastajenja wobźěłaś.',
 'ns-specialprotected' => 'Njejo móžno, boki w rumje {{ns:special}} wobźěłaś.',
 'titleprotected' => "Bok z toś tym mjenim bu wót [[User:$1|$1]] pśeśiwo napóranjeju šćitany. Pśicyna jo ''$2''.",
 'filereadonlyerror' => 'Njejo móžno dataju "$1" změniś, dokulaž datajowy repozitorium "$2" jo jano cytajobny.
@@ -540,7 +561,8 @@ Administrator, kenž jo jen zastajił, jo toś tu pśicynu pódał: "$3".',
 'invalidtitle-knownnamespace' => 'Njepłaśiwy titel z mjenjowym rumom "$2" a tekstom "$3"',
 'invalidtitle-unknownnamespace' => 'Njepłaśiwy titel z njeznatym mjenjowym rumom $1 a tekstom "$2"',
 'exception-nologin' => 'Njejsy se pśizjawił',
-'exception-nologin-text' => 'Toś ten bok abo toś ta akcija pomina, až sy na toś tom wikiju pśizjawjony.',
+'exception-nologin-text' => 'Pšosym [[Special:Userlogin|pśizjaw se]], aby pśistup na toś ten bok abo akciju měł.',
+'exception-nologin-text-manual' => 'Aby pśistup na toś ten bok abo akciju měł, musyš $1.',
 
 # Virus scanner
 'virus-badscanner' => "Špatna konfiguracija: njeznaty wirusowy scanner: ''$1''",
@@ -548,15 +570,15 @@ Administrator, kenž jo jen zastajił, jo toś tu pśicynu pódał: "$3".',
 'virus-unknownscanner' => 'njeznaty antiwirus:',
 
 # Login and logout pages
-'logouttext' => "'''Sy se něnto wótzjawił.'''
+'logouttext' => "'''{{GENDER:|Sy|Sy}} něnto {{GENDER:|wótzjawjony|wótzjawjona}}.'''
 
-Móžoš {{SITENAME}} anomymnje dalej wužywaś abo móžoš <span class='plainlinks'>[$1 se znowego pśizjawiś]</span> ako samski abo hynakšy wužywaŕ.
-Źiwaj na to, až někotare boki se dalej tak zwobraznjuju ako by hyšći pśizjawjeny był, až njewuproznijoš cache swójego wobglědowaka.",
+Glědaj: Jo móžno, až někotare boki pokazuju se snaź tak, ako by ty hyšći pśizjawjony był, až njewuproznijoš pufrowak twójogo wobglědowaka.",
 'welcomeuser' => 'Witaj $1',
 'welcomecreation-msg' => 'Twójo konto jo se załožyło. Njezabydni změniś swóje [[Special:Preferences|nastajenja za {{SITENAME}}]].',
 'yourname' => 'mě wužywarja',
 'userlogin-yourname' => 'Wužywarske mě',
 'userlogin-yourname-ph' => 'Zapódaj swójo wužywarske mě',
+'createacct-another-username-ph' => 'Wužywarske mě zapódaś',
 'yourpassword' => 'šćitne gronidło:',
 'userlogin-yourpassword' => 'Gronidło',
 'userlogin-yourpassword-ph' => 'Zapódaj swójo gronidło',
@@ -586,15 +608,35 @@ Móžoš {{SITENAME}} anomymnje dalej wužywaś abo móžoš <span class='plainl
 'gotaccount' => "Maš južo wužywarske konto? '''$1'''.",
 'gotaccountlink' => 'Pśizjawiś se',
 'userlogin-resetlink' => 'Sy pśizjawjeńske daty zabył?',
-'userlogin-resetpassword-link' => 'Gronidło anulěrowaś',
+'userlogin-resetpassword-link' => 'Sy swójo gronidło zabył?',
 'helplogin-url' => 'Help:Pśizjawiś',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoc za pśizjawjenje]]',
-'createaccountmail' => 'Nachylne pśidatne gronidło wužywaś a jo na slědujucu e-mailowu adresu pósłaś',
+'userlogin-loggedin' => 'Sy južo ako {{GENDER:$1|$1 pśizjawjony|$1 pśizjawjona}}. Wužyj slědujucy formular, aby se ako drugi wužywaŕ pśizjawił.',
+'userlogin-createanother' => 'Druge konto załožyś',
+'createacct-join' => 'Zapódaj dołojce swóje informacije.',
+'createacct-another-join' => 'Zapódaj dołojce informacije nowego konta.',
+'createacct-emailrequired' => 'E-mailowa adresa',
+'createacct-emailoptional' => 'E-mailowa adresa (opcionalny)',
+'createacct-email-ph' => 'Zapódaj swóju e-mailowu adresu',
+'createacct-another-email-ph' => 'E-mailowu adresu zapódaś',
+'createaccountmail' => 'Nachylne pśipadne gronidło wužywaś a jo na pódanu e-mailowu adresu pósłaś',
+'createacct-realname' => 'Napšawdne mě (opcionalny)',
 'createaccountreason' => 'Pśicyna:',
+'createacct-reason' => 'Pśicyna',
+'createacct-reason-ph' => 'Cogodla załožujoš druge konto?',
+'createacct-captcha' => 'Wěstotna kontrola',
+'createacct-imgcaptcha-ph' => 'Zapódaj tekst, kótaryž wiźeš dołojce',
+'createacct-submit' => 'Twójo konto załožyś',
+'createacct-another-submit' => 'Druge konto załožyś',
+'createacct-benefit-heading' => '{{SITENAME}} jo se wót luźi ako ty napórała.',
+'createacct-benefit-body1' => '{{PLURAL:$1|změna|změnje|změny}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|bok|boka|boki}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|aktiwny sobuskatkujucy|aktiwnej sobustatkucujej|aktiwne sobustatkujuce}}',
 'badretype' => 'Šćitnej gronidle, kótarejž sy zapódał, se njemakajotej.',
 'userexists' => 'Wužywarske mě se južo wužywa.
 Pšosym wubjeŕ druge mě.',
 'loginerror' => 'Zmólka pśi pśizjawjenju',
+'createacct-error' => 'Zmólka pśi załožowanju konta',
 'createaccounterror' => 'Wužywarske konto njejo se napóraś dało: $1',
 'nocookiesnew' => 'Wužywarske konto jo se južo wutwóriło, ale wužywaŕ njejo pśizjawjony. {{SITENAME}} wužywa cookije za pśizjawjenja. Jo notne, cookije zmóžniś a se wótnowotki pśizjawiś.',
 'nocookieslogin' => '{{SITENAME}} wužywa cookije za pśizjawjenja. Jo notne, cookije zmóžniś a se wótnowotki pśizjawiś.',
@@ -624,15 +666,13 @@ Jolic jo něchten drugi wó nowe šćitne gronidło pšosył abo ty sy se zasej
 'passwordsent' => 'Nowe šćitne gronidło jo se wótpósłało na e-mailowu adresu wužywarja „$1“.
 Pšosym pśizjaw se zasej, gaž jo dostanjoš.',
 'blocked-mailpassword' => 'Twója IP-adresa jo se za wobźěłowanje bokow blokěrowała a teke pśipósłanje nowego šćitnego gronidła jo se znjemóžniło, aby se znjewužywanjeju zadorało.',
-'eauthentsent' => 'Wobkšuśenje jo se na e-mailowu adresu wótposłało.
-
-Nježli až wótpósćelo se dalšna e-mail na to wužywarske konto, dejš slědowaś instrukcije w powěsći a tak wobkšuśiś, až konto jo wót wěrnosći twójo.',
+'eauthentsent' => 'Wobkšuśenje jo se na pódanu e-mailowu adresu wótposłało. Nježli až wótpósćelo se dalšna e-mail na to wužywarske konto, dejš slědowaś instrukcije w e-mailu, aby wobkšuśił, až konto jo napšawdu twójo.',
 'throttled-mailpassword' => 'E-mail za anulěrowanje gronidła jo se za {{PLURAL:$1|slědnu góźinu|slědnej $1 góźinje|slědne $1 góźiny|slědnych $1 góźin}} pósłała. Aby znjewužywanjeju zasajźało, se jano jadna e-mail za anulěrowanje gronidła na {{PLURAL:$1|góźinu|$1 góźinje|$1 góźiny|$1 góźin}} pósćelo.',
 'mailerror' => 'Zmólka pśi wótpósłanju e-maila: $1',
 'acct_creation_throttle_hit' => 'Woglědowarje toś togo wikija, kótarež wužywaju twóju IP-adresu su napórali {{PLURAL:$1|1 konto|$1 konśe|$1 konta|$1 kontow}} slědny źeń. To jo maksimalna dowólona licba za toś tu periodu.
 Woglědowarje, kótarež wužywaju toś tu IP-adresu njamógu tuchylu dalšne konta napóraś.',
 'emailauthenticated' => 'Twója e-mailowa adresa jo se $2 $3 goź. wobkšuśiła.',
-'emailnotauthenticated' => 'Twója e-mailowa adresa njejo hyšći wobkšuśona. E-mailowe funkcije móžoš aklej pó wuspěšnem wobkšuśenju wužywaś.',
+'emailnotauthenticated' => 'Twója e-mailowa adresa hyšći njejo wobkšuśona. Žedna e-mail buźo se za slědujuce funkcije słaś.',
 'noemailprefs' => 'Zapódaj e-mailowu adresu w swójich nastajenjach, aby toś te funkcije stali k dispoziciji.',
 'emailconfirmlink' => 'Wobkšuś swóju e-mailowu adresu.',
 'invalidemailaddress' => 'Toś ta e-mailowa adresa njamóžo se akceptěrowaś, dokulaž zda se, až jo njepłaśiwy format. Pšošym zapódaj adresu w korektnem formaśe abo wuprozń to pólo.',
@@ -645,10 +685,12 @@ Woglědowarje, kótarež wužywaju toś tu IP-adresu njamógu tuchylu dalšne ko
 
 Móžoš toś te zdźělenje ignorowaś, jolic toś te konto jo se jano zamólnje wutwóriło.',
 'usernamehasherror' => 'Wužywarske mě njesmějo hašowe znamuška wopśimjeś',
-'login-throttled' => 'Sy pśecesto wopytał se pśizjawiś. Pócakaj pšosym, nježli až wopytajoš znowego.',
+'login-throttled' => 'Sy pśecesto wopytał se pśizjawiś. Pócakaj pšosym $1, nježli až wopytajoš znowego.',
 'login-abort-generic' => 'Twójo pśizjawjenje njejo wuspěšne było - pśetergnjone',
 'loginlanguagelabel' => 'Rěc: $1',
 'suspicious-userlogout' => 'Twójo póžedanje za wótzjawjenim jo se wótpokazało, dokulaž zda se, až jo se pósłało pśez wobškóźony wobglědowak abo pufrowański proksy',
+'createacct-another-realname-tip' => 'Napšawdne mě jo opcionalne.
+Jolic jo pódajoš, buźo se to wužywaś, aby pśinoski pśirědowało.',
 
 # Email sending
 'php-mail-error-unknown' => 'Njeznata zmólka w PHP-funkciji mail()',
@@ -664,7 +706,7 @@ Móžoš toś te zdźělenje ignorowaś, jolic toś te konto jo se jano zamólnj
 'newpassword' => 'Nowe šćitne gronidło:',
 'retypenew' => 'Nowe šćitne gronidło (hyšći raz):',
 'resetpass_submit' => 'Šćitne gronidło nastajiś a se pśizjawiś',
-'changepassword-success' => 'Twójo nowe šćitne gronidło jo nastajone. Něnto se pśizjaw …',
+'changepassword-success' => 'Twóje gronidło jo se wuspěšnje změniło!',
 'resetpass_forbidden' => 'Gronidła njedaju se změniś',
 'resetpass-no-info' => 'Dejš pśizjawjony byś, aby direktny pśistup na toś ten bok měł.',
 'resetpass-submit-loggedin' => 'Gronidło změniś',
@@ -672,11 +714,15 @@ Móžoš toś te zdźělenje ignorowaś, jolic toś te konto jo se jano zamólnj
 'resetpass-wrong-oldpass' => 'Njepłaśiwe nachylne abo aktualne gronidło.
 Sy snaź swójo gronidło južo wuspěšnje změnił abo nowe nachylne gronidło pominał.',
 'resetpass-temp-password' => 'Nachylne gronidło:',
+'resetpass-abort-generic' => 'Změnjanje gronidła jo se pśez rozšyrjenje pśetergnuło.',
 
 # Special:PasswordReset
 'passwordreset' => 'Gronidło slědk stajiś',
+'passwordreset-text-one' => 'Wupołni toś ten formular, aby swójo gronidło anulěrował.',
+'passwordreset-text-many' => '{{PLURAL:$1|Zapódaj jadne z pólow, aby swójo gronidło slědk stajił.}}',
 'passwordreset-legend' => 'Gronidło slědk stajiś',
 'passwordreset-disabled' => 'Slědkstajenja gronidłow su se znjemóžnili na toś tom wikiju.',
+'passwordreset-emaildisabled' => 'E-mailowe funkcije su se na toś tom wikiju znjemóžnili.',
 'passwordreset-username' => 'Wužywarske mě:',
 'passwordreset-domain' => 'Domena:',
 'passwordreset-capture' => 'E-mail se woglědaś?',
@@ -699,7 +745,7 @@ Ty by měł se něnto pśizjawiś a nowe gronidło wustajiś. Jolic něchten dru
 Nachylne gronidło: $2',
 'passwordreset-emailsent' => 'E-mail za anulěrowanje gronidła jo se pósłała.',
 'passwordreset-emailsent-capture' => 'E-mail za anulěrowanje gronidła jo se pósłała, kótaraž pokazujo se dołojce.',
-'passwordreset-emailerror-capture' => 'E-mail za anulěrowanje gronidła jo se generěrowała, kótaraž pokazujo se dołojce, ale jeje słanje wužywarjeju jo se njeraźiło: $1',
+'passwordreset-emailerror-capture' => 'E-mail za anulěrowanje gronidła jo se napórała, kótaraž se dołojce pokazujo, ale słanje {{GENDER:$2|wužywarjeju|wužywarce}} jo se njeraźiło: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'E-mailowu adresu změniś',
@@ -713,6 +759,19 @@ Nachylne gronidło: $2',
 'changeemail-submit' => 'E-mailowu adresu změniś',
 'changeemail-cancel' => 'Pśetergnuś',
 
+# Special:ResetTokens
+'resettokens' => 'Tokeny slědk stajiś',
+'resettokens-text' => 'Móžoš tokeny slědk stajiś, kótarež dowóluju pśistup na wěste priwatne daty, kótarež su z twójim kontom zwězane.
+
+Ty by dejał to cyniś, jolic sy je zmylnje z někim źělił abo jolic twóje konto jo se nadpadało.',
+'resettokens-no-tokens' => 'Tokeny za slědkstajenje njejsu.',
+'resettokens-legend' => 'Tokeny slědk stajiś',
+'resettokens-tokens' => 'Tokeny:',
+'resettokens-token-label' => '$1 (aktualna gódnota: $2)',
+'resettokens-watchlist-token' => 'Token za webkanal (Atom/RSS) [[Special:Watchlist|změnow na bokach w twójich woglědowankach]]',
+'resettokens-done' => 'Tokeny slědk stajone.',
+'resettokens-resetbutton' => 'Wubrane tokeny slědk stajiś',
+
 # Edit page toolbar
 'bold_sample' => 'Tucny tekst',
 'bold_tip' => 'Tucny tekst',
@@ -789,9 +848,7 @@ Jo se snaź pśesunuł abo wulašował, mjaztym až woglědujoš se bok.',
 'loginreqlink' => 'se pśizjawiś',
 'loginreqpagetext' => 'Dejš $1, aby mógł boki pšawje cytaś.',
 'accmailtitle' => 'Šćitne gronidło jo se wótpósłało.',
-'accmailtext' => "Pśipadnje napórane gronidło za [[User talk:$1|$1]] jo se pósłało k $2.
-
-Gronidło za toś to nowe konto dajo se na boku ''[[Special:ChangePassword|Gronidło změniś]]'' pśi pśizjawjenju změniś.",
+'accmailtext' => "Pśipadnje napórane gronidło za [[User talk:$1|$1]] jo se pósłało k $2. Dajo se na boku ''[[Special:ChangePassword|Gronidło změniś]]'' pśi pśizjawjenju změniś.",
 'newarticle' => '(Nowy nastawk)',
 'newarticletext' => "Sy slědował wótkaz na bok, kótaryž hyšći njeeksistěrujo.
 Aby bok napórał, zapiš do kašćika dołojce (glědaj [[{{MediaWiki:Helppage}}|bok pomocy]] za dalšne informacije). Jolic sy zamólnje how, klikni na tłocašk '''Slědk''' w swójom wobglědowaku.",
@@ -880,7 +937,7 @@ Nejnowšy protokolowy zapisk jo dołojce ako referenca pódany:",
 'nocreate-loggedin' => 'Njamaš pšawo nowe boki napóraś.',
 'sectioneditnotsupported-title' => 'Wobźěłowanje wótrězka se njepódpěra',
 'sectioneditnotsupported-text' => 'Wobźěłowanje wótrězka njepódpěra se na toś tom wobźěłowańskem boku.',
-'permissionserrors' => 'Problem z pšawami',
+'permissionserrors' => 'Wopšawnjeńska zmólka',
 'permissionserrorstext' => 'Njamaš pšawo to cyniś. {{PLURAL:$1|Pśicyna|Pśicynje|Pśicyny}}:',
 'permissionserrorstext-withaction' => 'Njamaš pšawo $2. {{PLURAL:$1|Pśicyna|Pśicynje|Pśicyny|Pśicyny}}:',
 'recreate-moveddeleted-warn' => "'''Glědaj: Ty wótžywijoš bok, kótaryž jo pjerwjej se wulašował.'''
@@ -902,7 +959,8 @@ Eksistěrujo južo.',
 'content-failed-to-parse' => 'Parsowanje wopśimjeśa $2 za model $1 jo se njeraźiło: $3',
 'invalid-content-data' => 'Njepłaśiwe wopśimjeśowe daty',
 'content-not-allowed-here' => 'Wopśimjeśe "$1" njejo na boku [[$2]] dowólone',
-'editwarning-warning' => 'Gaž toś ten bok se spušća, mógu se změny zgubiś, kótarež sy pśewjadł. Jolic sy pśizjawjeny, móžoš toś to warnowanje we wótrězku {{int:prefs-editing}} swójich nastajenjow znjemóžniś.',
+'editwarning-warning' => 'Gaž toś ten bok se spušća, mógu se změny zgubiś, kótarež sy pśewjadł.
+Jolic sy pśizjawjeny, móžoš toś to warnowanje we wótrězku „Wobźěłaś“ swójich nastajenjow znjemóžniś.',
 
 # Content models
 'content-model-wikitext' => 'wikitekst',
@@ -935,6 +993,7 @@ Njesmějo daś wěcej nježli $2 {{PLURAL:$2|wołanja|wołanjowu|wołanjow|woła
 'undo-failure' => 'Změna njejo se mógała wótpóraś, dokulaž jo něchten pótrjefjony wótrězk mjaztym změnił.',
 'undo-norev' => 'Změna njeda se wótwrośiś, dokulaž njeeksistěčujo abo jo se wulašowała.',
 'undo-summary' => 'Wersija $1 wót [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) jo se anulěrowała',
+'undo-summary-username-hidden' => 'Změna $1 schowanego wužywarja jo se anulěrowała',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Njejo móžno wužywarske konto wutwóriś',
@@ -1023,19 +1082,20 @@ Móžoš se toś ten rozdźěl woglědaś; drobnostki glědaj w [{{fullurl:{{#Sp
 'revdelete-text' => "'''Wulašowane wersije a tšojenja budu se dalej w stawiznach boka a w protokolach pokazaś, ale źěle jich wopśimjeśa njebudu pśistupne za zjawnosć.'''
 Dalšne administratory na {{GRAMMAR:lokatiw|{{SITENAME}}}} mógu ale pśecej hyšći pśistup na schowane wopśimjeśe měś a mógu jo pśez samki interfejs wótnowiś,  snaźkuli su pśidatne wobgranicowanja.",
 'revdelete-confirm' => 'Pšosym wobkšuś, až coš to cyniś, až rozmějoš konsekwence a až cyniš to pó [[{{MediaWiki:Policy-url}}|pšawidłach]].',
-'revdelete-suppress-text' => "Pódtłocenje by se dejał '''jano''' za slědujuce pady wužywaś:
-* Njegóźece se wósobinske informacije
-*: ''bydleńske adrese a telefonowe numery, numery socialnego zawěsćenja atd.''",
+'revdelete-suppress-text' => "Pódtłocenje by dejało se '''jano''' za slědujuce pady wužywaś:
+* Potencielnje ranjece informacije
+* Njepśigódne wósobinske informacije
+*: ''Bydleńske adrese a telefonowe numery, numery socialnego zawěsćenja atd.''",
 'revdelete-legend' => 'wobgranicowanja widobnosći póstajiś',
-'revdelete-hide-text' => 'Tekst wersije schowaś',
+'revdelete-hide-text' => 'Tekst wersije',
 'revdelete-hide-image' => 'Wopśimjeśe dataje schowaś',
 'revdelete-hide-name' => 'Akciju log-lisćiny schowaś',
-'revdelete-hide-comment' => 'Komentar wobźěłanja schowaś',
-'revdelete-hide-user' => 'mě/IP-adresu wobźěłarja schowaś',
+'revdelete-hide-comment' => 'Zespominanje wobźěłanja',
+'revdelete-hide-user' => 'Mě/IP-adresa wobźěłarja',
 'revdelete-hide-restricted' => 'Daty wót administratorow ako teke te drugich wužywarjow pódtłocyś',
 'revdelete-radio-same' => '(njezměniś)',
-'revdelete-radio-set' => 'Jo',
-'revdelete-radio-unset' => '',
+'revdelete-radio-set' => 'Schowany',
+'revdelete-radio-unset' => 'Widobny',
 'revdelete-suppress' => 'Pśicynu wulašowanja teke za administratorow schowaś',
 'revdelete-unsuppress' => 'Wobgranicowanja za wótnowjone wersije zasej zwignuś.',
 'revdelete-log' => 'Pśicyna:',
@@ -1114,6 +1174,7 @@ Zaruc, až historija wersijow nastawka jo njepśetergnjona.',
 'compareselectedversions' => 'Wuzwólonej wersiji pśirownaś',
 'showhideselectedversions' => 'Wubrane wersije pokazaś/schowaś',
 'editundo' => 'wótwrośiś',
+'diff-empty' => '(Žeden rozdźěl)',
 'diff-multi' => '({{PLURAL:$1|Jadna mjazywersija|$1 mjazywersiji|$1 mjazywersije|$1 mjazywersijow}} wót {{PLURAL:$2|jadnogo wužywarja|$2 wužywarjowu|$2 wužywarjow|$2 wužywarjow}} {{PLURAL:$1|njepokazana|njepokazanej|njepokazane|njepokazane}})',
 'diff-multi-manyusers' => '({{PLURAL:$1|Jadna mjazywersija|$1 mjazywersiji|$1 mjazywersije|$1 mjazywersijow}} wót wěcej ako {{PLURAL:$2|jadnogo wužywarja|$2 wužywarjowu|$2 wužywarjow|$2 wužywarjow}} {{PLURAL:$1|njepokazana|njepokazanej|njepokazane|njepokazane}})',
 'difference-missing-revision' => '{{PLURAL:$2|Jadna wersija|$2 wersiji|$2 wersije|$2 wersijow}} toś togo rozdźěla ($1) {{PLURAL:$2|njejo se namakała|njejstej se namakałej|njejsu namakali|njejo se namakało}}.
@@ -1181,13 +1242,13 @@ Drobnostki móžoš w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'powersearch-togglenone' => 'Žeden',
 'search-external' => 'Eksterne pytanje',
 'searchdisabled' => 'Pytanje we {{SITENAME}} jo se deaktiwěrowało. Tak dłujko móžoš w googlu pytaś. Pšosym wobmysli, až móžo pytanski indeks za {{SITENAME}} njeaktualny byś.',
+'search-error' => 'Pśi pytanju jo se zmólka nastała: $1',
 
 # Preferences page
 'preferences' => 'Nastajenja',
 'mypreferences' => 'Nastajenja',
 'prefs-edits' => 'Licba wobźěłanjow:',
-'prefsnologin' => 'Njejsy pśizjawjony',
-'prefsnologintext' => 'Musyš se <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} pśizjawiś]</span>, aby mógał swóje nastajenja změniś.',
+'prefsnologintext2' => 'Musyš $1, aby wužywarske nastajenja póstajił.',
 'changepassword' => 'Šćitne gronidło změniś',
 'prefs-skin' => 'Šat',
 'skin-preview' => 'Pśeglěd',
@@ -1212,7 +1273,7 @@ Drobnostki móžoš w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'prefs-rendering' => 'Naglěd',
 'saveprefs' => 'Składowaś',
 'resetprefs' => 'Njeskłaźone změny zachyśiś',
-'restoreprefs' => 'Wše standardne nastajenja wobnowiś',
+'restoreprefs' => 'Wšykne standardne nastajenja wótnowiś (we wšych wótrězkach)',
 'prefs-editing' => 'Wobźěłaś',
 'rows' => 'Rědki:',
 'columns' => 'Słupy:',
@@ -1224,6 +1285,9 @@ Drobnostki móžoš w [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'recentchangesdays-max' => '(maksimalnje $1 {{PLURAL:$1|źeń|dnja|dny|dnjow}})',
 'recentchangescount' => 'Licba změnow, kótaraž ma se pó standarźe pokazaś:',
 'prefs-help-recentchangescount' => 'To wopśimujo aktualne změny, stawizny bokow a protokole.',
+'prefs-help-watchlist-token2' => 'To jo pótajmny kluc k webkanaloju twójich wobglědowańkow.
+Něchten, kótaryž jen znajo, móžo twóje wobglědowańki cytaś, njeźěl jen togodla.
+[[Special:ResetTokens|Klikni how, jolic musyš jen slědk stajiś]].',
 'savedprefs' => 'Twóje nastajenja su se składowali.',
 'timezonelegend' => 'Casowa cona:',
 'localtime' => 'Městny cas:',
@@ -1267,11 +1331,13 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'prefs-help-signature' => 'Komentary na diskusijnych bokach měli se pśez "<nowiki>~~~~</nowiki>" pódpisaś, kótarež konwertěrujo se do twójeje signatury a casowego kołka.',
 'badsig' => 'Signatura njejo dobra; pšosym HTML pśekontrolěrowaś.',
 'badsiglength' => 'Twója signatura jo pśedłujka. Musy mjenjej ako $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} měś.',
-'yourgender' => 'Rod:',
-'gender-unknown' => 'Njepódany',
-'gender-male' => 'Muskecy',
-'gender-female' => 'Žeńscyny',
-'prefs-help-gender' => 'Opcionalny: wužywa se za pó roźe specifiske nagronjenje pśez softwaru. Toś ta informacija buźo zjawna.',
+'yourgender' => 'Co coš pódaś?',
+'gender-unknown' => 'Njok nic wó tom pódaś',
+'gender-male' => 'Wón wobźěłujo wikiboki',
+'gender-female' => 'Wóna wobźěłujo wikiboki',
+'prefs-help-gender' => 'Toś to pódaśe jo opcionalne:
+Softwara wuyiwa jogo gódnotu, aby śi z pomocu wótpowědnego gramatikaliskego roda groniła a drugich na tebje pokazała.
+Toś ta informacija buźo zjawna.',
 'email' => 'E-mail',
 'prefs-help-realname' => 'Realne mě jo opcionalne. Jolic až jo zapódajośo wužywa se za pódpisanje wašych pśinoskow.',
 'prefs-help-email' => 'E-mailowa adresa jo opcionalna, ale zmóžnja śi nowe gronidło emailowaś, jolic sy zabył swójo gronidło.',
@@ -1282,7 +1348,9 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'prefs-signature' => 'Pódpis',
 'prefs-dateformat' => 'Datumowy format',
 'prefs-timeoffset' => 'Casowy rozdźěl',
-'prefs-advancedediting' => 'Rozšyrjone opcije',
+'prefs-advancedediting' => 'Powšykne nastajenja',
+'prefs-editor' => 'Editor',
+'prefs-preview' => 'Pśeglěd',
 'prefs-advancedrc' => 'Rozšyrjone opcije',
 'prefs-advancedrendering' => 'Rozšyrjone opcije',
 'prefs-advancedsearchoptions' => 'Rozšyrjone opcije',
@@ -1290,7 +1358,9 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'prefs-displayrc' => 'Zwobraznjowańske opcije',
 'prefs-displaysearchoptions' => 'Zwobraznjowańske opcije',
 'prefs-displaywatchlist' => 'Zwobraznjowańske opcije',
+'prefs-tokenwatchlist' => 'Token',
 'prefs-diffs' => 'Rozdźěle',
+'prefs-help-prefershttps' => 'Toś to nastajenje wustatkujo se pó twójom pśiducem pśizjawjenju.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Zda se, až e-mailowa adresa jo płaśiwa',
@@ -1314,9 +1384,11 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'userrights-no-interwiki' => 'Njamaš pšawo wužywarske pšawa w drugich wikijach změniś.',
 'userrights-nodatabase' => 'Datowa banka $1 njeeksistěrujo abo njejo lokalna.',
 'userrights-nologin' => 'Musyš se z administratorowym kontom [[Special:UserLogin|pśizjawiś]], aby wužywarske pšawa změnił.',
-'userrights-notallowed' => 'Twóje konto njama pšawa, aby wužywarske pšawa pśidało abo wótpórało.',
+'userrights-notallowed' => 'Njamaš trěbne pšawa, aby wužywarske pšawa pśipokazało abo zajmjeł.',
 'userrights-changeable-col' => 'Kupki, kótarež móžoš změniś',
 'userrights-unchangeable-col' => 'Kupki, kótarež njamóžoš změniś',
+'userrights-conflict' => 'Konflikt změnow wužywarskich pšawow! Pšosym pśeglědaj a wobkšuś swóje změny.',
+'userrights-removed-self' => 'Sy swóje pšawa wuspěšnje wótpórał. Togodla njamaš južo pśistup na toś ten bok měś.',
 
 # Groups
 'group' => 'Kupka:',
@@ -1360,7 +1432,7 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'right-reupload-shared' => 'Dataje w zgromadnje wužywanem repozitoriju lokalnje pśepisaś',
 'right-upload_by_url' => 'Dataju z URL-adrese nagraś',
 'right-purge' => 'Sedłowy cache za bok bźez wobkšuśenja prozniś',
-'right-autoconfirmed' => 'Połšćitane boki wobźěłaś',
+'right-autoconfirmed' => 'Žedne wobgranicowanje pśez IP-bazěrowane limity',
 'right-bot' => 'Wobchadanje ako awtomatiski proces',
 'right-nominornewtalk' => 'Snadne změny na diskusijnych bokach njedowjedu k pokazanjeju "Nowe powěsći"',
 'right-apihighlimits' => 'Wuše limity w API-wótpšašanjach wužywaś',
@@ -1380,13 +1452,21 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'right-hideuser' => 'Wužywarske mě blokěrowaś a schowaś',
 'right-ipblock-exempt' => 'Blokěrowanja IP, awtomatiske blokěrowanja a blokěrowanja wobcerkow se wobinuś',
 'right-proxyunbannable' => 'Awtomatiske blokěrowanje proksyjow se wobinuś',
-'right-unblockself' => 'Wótblokěrowaś se samogo',
-'right-protect' => 'Šćitowe schójźeńki změniś a šćitane boki wobźěłaś',
-'right-editprotected' => 'Šćitane boki wobźěłaś (bśez kaskadowego šćita)',
+'right-unblockself' => 'Wótblokěrowaś se',
+'right-protect' => 'Šćitowe schojźeńki změniś a z kaskadami šćitane boki wobźěłaś',
+'right-editprotected' => 'Boki wobźěłaś, kótarež su pśez "{{int:protect-level-sysop}}" šćitane',
+'right-editsemiprotected' => 'Boki wobźěłaś, kótarež su pśez "{{int:protect-level-autoconfirmed}}" šćitane',
 'right-editinterface' => 'Wužywański pówjerch wobźěłaś',
 'right-editusercssjs' => 'Dataje CSS a JS drugich wužywarjow wobźěłaś',
 'right-editusercss' => 'Dataje CSS drugich wužywarjow wobźěłaś',
 'right-edituserjs' => 'Dataje JS drugich wužywarjow wobźěłaś',
+'right-editmyusercss' => 'Twóje swójske wužywarske CSS-dataje wobźěłaś',
+'right-editmyuserjs' => 'Twóje swójske wužywarske JavaScript-dataje wobźěłaś',
+'right-viewmywatchlist' => 'Se swójske wobglědowańki woglědaś',
+'right-editmywatchlist' => 'Swóje wobglědowańki wobźěłaś. Wobglěduj, až někotare akcije hyšći pśidawaju boki bźez toś togo pšawa.',
+'right-viewmyprivateinfo' => 'Swójske priwatne daty se woglědaś (na pś. e-mailowu adresu, napšawdne mě)',
+'right-editmyprivateinfo' => 'Swójske priwatne daty wobźěłaś (na pś. e-mailowu adresu, napšawdne mě)',
+'right-editmyoptions' => 'Swójske nastajenja wobźěłaś',
 'right-rollback' => 'Spěšne anulěrowanje změnow slědnego wužywarja, kótaryž jo dany bok wobźěłał',
 'right-markbotedits' => 'Spěšnje anulěrowane změny ako botowe změny markěrowaś',
 'right-noratelimit' => 'Pśez žedne limity wobgranicowany',
@@ -1438,8 +1518,8 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'action-block' => 'Toś tomu wužiwarjeju wobźěłowanje zawoboraś',
 'action-protect' => 'Šćitowe stopnje za toś ten bok změniś',
 'action-rollback' => 'změny slědnego wužywarja, kótaryž jo wobźěłał wěsty bok, malsnje slědk stajiś',
-'action-import' => 'toś ten bok z drugego wikija importěrowaś',
-'action-importupload' => 'toś ten bok z datajowego nagraśa importěrowaś',
+'action-import' => 'boki z drugego wikija importěrowaś',
+'action-importupload' => 'boki z datajowego nagraśa importěrowaś',
 'action-patrol' => 'změny drugich wužywarjow ako doglědowane markěrowaś',
 'action-autopatrol' => 'twóju změnu ako doglědowanu markěrowaś daś',
 'action-unwatchedpages' => 'lisćinu njewobglědowanych bokow zwobrazniś',
@@ -1448,17 +1528,27 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'action-userrights-interwiki' => 'wužywarske pšawa wužywarjow w drugich wikijach wobźěłaś',
 'action-siteadmin' => 'datowu banku zastajiś abo wótworiś',
 'action-sendemail' => 'E-maile pósłaś',
+'action-editmywatchlist' => 'swóje wobglědowańki wobźěłaś',
+'action-viewmywatchlist' => 'swóje wobglědowańki se woglědaś',
+'action-viewmyprivateinfo' => 'twóje priwatne informacije se woglědaś',
+'action-editmyprivateinfo' => 'twóje priwatne informacije wobźěłaś',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|změna|změnje|změny}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|wót slědnego woglěda}}',
+'enhancedrc-history' => 'historija',
 'recentchanges' => 'Aktualne změny',
 'recentchanges-legend' => 'Opcije aktualnych změnow',
 'recentchanges-summary' => "How móžoš slědne změny we '''{{GRAMMAR:lokatiw|{{SITENAME}}}}''' slědowaś.",
+'recentchanges-noresult' => 'Žedne změny za dany cas njewótpowědujo toś tym kriterijam.',
 'recentchanges-feed-description' => 'Slěduj z toś tym zapódaśim nejaktualnjejše změny we {{GRAMMAR:lokatiw|{{SITENAME}}}}.',
 'recentchanges-label-newpage' => 'Toś ta změna jo nowy bok napórała.',
 'recentchanges-label-minor' => 'To jo snadna změna',
 'recentchanges-label-bot' => 'Toś ta změna jo se pśez bośik wuwjadła.',
 'recentchanges-label-unpatrolled' => 'Toś ta změna hyšći njejo se pśekontrolěrowała',
+'recentchanges-label-plusminus' => 'Změnjona wjelikosc boka (licba bajtow)',
+'recentchanges-legend-newpage' => '(glej teke [[Special:NewPages|lisćinu nowych bokow]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Dołojce {{PLURAL:$1|jo '''1''' změna|stej slědnej '''$1''' změnje|su slědne '''$1''' změny}} w {{PLURAL:$2|slědnem dnju|slědnyma '''$2''' dnjoma|slědnych '''$2''' dnjach}}, staw wót $4, $5.",
 'rcnotefrom' => "Dołojce pokazuju se změny wót '''$2''' (maks. '''$1''' zapisow).",
 'rclistfrom' => 'Nowe změny wót $1 pokazaś.',
@@ -1481,7 +1571,7 @@ Móžoš toś ten bok wužywaś, aby slědk stajił swóje nastajenja na standar
 'rc_categories_any' => 'wše',
 'rc-change-size-new' => '$1 {{PLURAL:$1|byte|byta|byty|bytow}} pó změnje',
 'newsectionsummary' => 'Nowy wótrězk /* $1 */',
-'rc-enhanced-expand' => 'Drobnosći pokazaś (pomina se JavaScript)',
+'rc-enhanced-expand' => 'Drobnostki pokazaś',
 'rc-enhanced-hide' => 'Drobnosći schowaś',
 'rc-old-title' => 'spócetnje napórany ako "$1"',
 
@@ -1740,8 +1830,7 @@ Za optimalnu wěstotu img_auth.php jo znjemóžnjony.',
 'upload_source_file' => ' (dataja na twójom kompjuterje)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Toś ten specialny bok pokazujo wšykne nagrate dataje.
-Jolic se pó wužywarju filtrujo, budu se jano dataje pokazowaś, pśi kótarychž ten wužywaŕ jo nejnowšu wersiju nagrał.',
+'listfiles-summary' => 'Toś ten specialny bok pokazujo wšykne nagrate dataje.',
 'listfiles_search_for' => 'Za medijowym mjenim pytaś:',
 'imgfile' => 'dataja',
 'listfiles' => 'Lisćina datajow',
@@ -1752,6 +1841,10 @@ Jolic se pó wužywarju filtrujo, budu se jano dataje pokazowaś, pśi kótarych
 'listfiles_size' => 'Wjelikosć (byte)',
 'listfiles_description' => 'Zespominanje',
 'listfiles_count' => 'Wersije',
+'listfiles-show-all' => 'Stare wersije wobrazow zapśimjeś',
+'listfiles-latestversion' => 'Aktualna wersija',
+'listfiles-latestversion-yes' => 'Jo',
+'listfiles-latestversion-no' => 'Ně',
 
 # File description page
 'file-anchor-link' => 'Dataja',
@@ -1844,6 +1937,13 @@ Snaź coš wopisanje na jeje [$2 boku datajowego wopisanja] wobźěłaś.',
 'randompage' => 'Pśipadny nastawk',
 'randompage-nopages' => 'W {{PLURAL:$2|slědujucem mjenjowem rumje|slědujucyma mjenjowyma rumoma|slědujucych mjenjowych rumach|slědujucych mjenjowych rumach}} žedne boki njejsu: $1',
 
+# Random page in category
+'randomincategory' => 'Pśipadny bok w kategoriji',
+'randomincategory-invalidcategory' => '"$1" njejo płaśiwe kategorijowe mě.',
+'randomincategory-nopages' => 'W kategoriji [[:Category:$1|$1]] žedne boki njejsu.',
+'randomincategory-selectcategory' => 'Pśipadny bok z kategorija: $1 $2',
+'randomincategory-selectcategory-submit' => 'Wótpósłaś',
+
 # Random redirect
 'randomredirect' => 'Pśipadne dalejpósrědnjenje',
 'randomredirect-nopages' => 'W mjenjowem rumje "$1" njejsu dalejpósrědnjenja.',
@@ -1874,6 +1974,8 @@ Snaź coš wopisanje na jeje [$2 boku datajowego wopisanja] wobźěłaś.',
 'pageswithprop-text' => 'Toś ten bok nalicyjo boki, kótarež wužywaju wěstu kakosć boka.',
 'pageswithprop-prop' => 'Mě kakosći:',
 'pageswithprop-submit' => 'Wótpósłaś',
+'pageswithprop-prophidden-long' => 'Gódnota kakosći dłujkego teksta schowana ($1)',
+'pageswithprop-prophidden-binary' => 'binarna kakostna gódnota schowana ($1)',
 
 'doubleredirects' => 'Dwójne dalejpósrědnjenja',
 'doubleredirectstext' => 'Toś ten bok nalicujo boki, kótarež dalej pósrědnjaju na druge dalejpósrědnjenja.
@@ -1910,7 +2012,7 @@ Kužda smužka wopśimjejo wótkaze na prědne a druge dalejpósrědnjenje a tek
 {{GRAMMAR:lokatiw|{{SITENAME}}}}.',
 'uncategorizedpages' => 'Boki bźez kategorijow',
 'uncategorizedcategories' => 'Njekategorizěrowane kategorije',
-'uncategorizedimages' => 'Njekategorizěrowane dataje.',
+'uncategorizedimages' => 'Njekategorizěrowane dataje',
 'uncategorizedtemplates' => 'Njekategorizěrowane pśedłogi',
 'unusedcategories' => 'Njewužywane kategorije',
 'unusedimages' => 'Njewužywane dataje',
@@ -1931,6 +2033,7 @@ Kužda smužka wopśimjejo wótkaze na prědne a druge dalejpósrědnjenje a tek
 'mostrevisions' => 'Boki z nejwěcej wersijami',
 'prefixindex' => 'Wšykne boki z prefiksom',
 'prefixindex-namespace' => 'Wšykne boki z prefiksom (mjenjowy rum $1)',
+'prefixindex-strip' => 'Prefiks w lisćinje wótrězaś',
 'shortpages' => 'Krotke nastawki',
 'longpages' => 'Dłujke nastawki',
 'deadendpages' => 'Nastawki bźez wótkazow',
@@ -1946,6 +2049,7 @@ Kužda smužka wopśimjejo wótkaze na prědne a druge dalejpósrědnjenje a tek
 'listusers' => 'Lisćina wužywarjow',
 'listusers-editsonly' => 'Jano wužywarjow ze změnami pokazaś',
 'listusers-creationsort' => 'Pó datumje napóranja sortěrowaś',
+'listusers-desc' => 'We wóstupujucem porěźe sortěrowaś',
 'usereditcount' => '$1 {{PLURAL:$1|změna|změnje|změny|změnow}}',
 'usercreated' => 'jo se $1 $2 góź. {{GENDER:$3|napórał|napórała}}',
 'newpages' => 'Nowe boki',
@@ -2048,7 +2152,8 @@ Jo nanejmjenjej głowna domena trěbna, na pśikład "*.org"<br />
 # Special:ListGroupRights
 'listgrouprights' => 'Pšawa wužywarskeje kupki',
 'listgrouprights-summary' => 'To jo lisćina wužywarskich kupkow definěrowanych w toś tom wikiju z jich zwězanymi pśistupnymi pšawami. Móžo [[{{MediaWiki:Listgrouprights-helppage}}|pśidatne informacije]] wó jadnotliwych pšawach daś.',
-'listgrouprights-key' => '* <span class="listgrouprights-granted">Zagarantěrowane pšawo</span>
+'listgrouprights-key' => 'Legenda:
+* <span class="listgrouprights-granted">Zagarantěrowane pšawo</span>
 * <span class="listgrouprights-revoked">Slědk wzete pšawo</span>',
 'listgrouprights-group' => 'Kupka',
 'listgrouprights-rights' => 'Pšawa',
@@ -2120,7 +2225,7 @@ Pózdźejšne změny na toś tom boku a w pśisłušecej diskusiji se tam nalicu
 'notanarticle' => 'To njejo žeden nastawk',
 'notvisiblerev' => 'Wersija bu wulašowana',
 'watchlist-details' => 'Wobglědujoš {{PLURAL:$1|$1 bok|$1 boka|$1 boki|$1 bokow}}, bźez diskusijnych bokow.',
-'wlheader-enotif' => 'E-mailowe powěsće su aktiwizěrowane.',
+'wlheader-enotif' => 'E-mailowa zdźěleńska słužba jo zmóžnjona.',
 'wlheader-showupdated' => "Boki, kótarež su wót twójogo slědnego woglěda se změnili, pokazuju se '''tucnje'''.",
 'watchmethod-recent' => 'Kontrolěrowanje aktualnych změnow we wobglědowańce',
 'watchmethod-list' => 'Pśepytanje wobglědowanych bokow za aktualnymi změnami',
@@ -2153,7 +2258,9 @@ Pózdźejšne změny na toś tom boku a w pśisłušecej diskusiji se tam nalicu
 'enotif_anon_editor' => 'anonymny wužywaŕ $1',
 'enotif_body' => 'Luby $WATCHINGUSERNAME,
 
-$PAGEINTRO $NEWPAGE
+$PAGEEDITOR jo bok $PAGETITLE na {{GRAMMAR:lokatiw|{{SITENAME}}}} $PAGEEDITDATE $CHANGEDORCREATED, glědaj $PAGETITLE_URL za aktualnu wersiju.
+
+$NEWPAGE
 
 Zespominanje wobźěłarja: $PAGESUMMARY $PAGEMINOREDIT
 
@@ -2161,9 +2268,10 @@ Kontakt z wobźěłarjom:
 E-mail: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
-Njebudu žedne dalšne powěźeńki w paźe dalšnych změnow, snaźkuli woglědujoš se toś ten bok. Móźoś teke chórgojcki powěźeńkow za wšykne twóje wobglědowane boki slědk stajiś.
+Njebudu žedne dalšne powěźeńki w paźe aktiwity, snaźkuli woglědujoš se toś ten bok, mjaztym sy pśizjawjony.
+Móźoś teke chórgojcki powěźeńkow za wšykne twóje wobglědowane boki slědk stajiś.
 
-Twój pśijaśelny powěsćowy system {{SITENAME}}
+             Twój pśijaśelny powěsćowy system {{SITENAME}}
 --
 Aby swoje nastajenja za e-mailowe zdźělenja změnił, woglědaj
 {{canonicalurl:{{#special:Preferences}}}}
@@ -2200,10 +2308,12 @@ Pšašanja a dalšna pomoc:
 'deletecomment' => 'Pśicyna:',
 'deleteotherreason' => 'Druga/pśidatna pśicyna:',
 'deletereasonotherlist' => 'Druga pśicyna',
-'deletereason-dropdown' => '* Powšykne pśicyny za lašowanja
-** Žycenje awtora
-** Pśekśiwjenje stworiśelskego pšawa
-** Wandalizm',
+'deletereason-dropdown' => '* Zwucone pśicyny za wulašowanje
+** Spam
+** Wandalizm
+** Pśekśiwjenje awtorskego pšawa
+** Pominanje awtora
+** Defektne dalejpósrědnjenje',
 'delete-edit-reasonlist' => 'Pśicyny za lašowanje wobźěłaś',
 'delete-toobig' => 'Toś ten bok ma z wěcej nježli $1 {{PLURAL:$1|wersiju|wersijomaj|wersijami|wersijami}} dłujku historiju. Lašowanje takich bokow bu wobgranicowane, aby wobškoźenju {{GRAMMAR:genitiw|{{SITENAME}}}} z pśigódy zajźowało.',
 'delete-warning-toobig' => 'Toś ten bok ma z wěcej ako $1 {{PLURAL:$1|wersiju|wersijomaj|wersijami|wersijami}} dłujke stawizny. Jich wulašowanje móžo źěło datoweje banki na {{SITENAME}} kazyś;
@@ -2222,7 +2332,7 @@ póstupujśo z glědanim.',
 Slědnu změnu k bokoju jo pśewjadł [[User:$3|$3]] ([[User talk:$3|diskusija]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Zapominanje k slědnej změnje jo było: \"''\$1''\".",
 'revertpage' => 'Změny wužywarja [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) su se wótwrośili a slědna wersija wužywarja [[User:$1|$1]] jo se wótnowiła.',
-'revertpage-nouser' => 'Jo změny wót (wužywarske mě wótpórane) na slědnu wersiju wót [[User:$1|$1]] slědk stajił',
+'revertpage-nouser' => 'Změny su se wót schowanego wužywarja anulěrowali a pjerwjejšna wersija wužywarja {{GENDER:$1|[[User:$1|$1]]}} jo se wótnowiła',
 'rollback-success' => 'Změny wót $1 su se slědk wzeli a slědna wersija wót $2 jo zasej se nawrośiła.',
 
 # Edit tokens
@@ -2358,7 +2468,7 @@ $1',
 'contributions' => 'Pśinoski {{GENDER:$1|wužywarja|wužywarki}}',
 'contributions-title' => 'Wužywarske pśinoski wót $1',
 'mycontris' => 'Pśinoski',
-'contribsub2' => 'Za $1 ($2)',
+'contribsub2' => 'Za {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Za toś te kriterije njejsu žedne změny se namakali.',
 'uctop' => '(aktualny)',
 'month' => 'wót mjaseca (a jěsnjej):',
@@ -2655,7 +2765,7 @@ W slědnem padźe móžoš teke wótkaz wužywaś, na pś. [[{{#Special:Export}}
 'allmessagesdefault' => 'Standardny tekst',
 'allmessagescurrent' => 'Aktualny tekst',
 'allmessagestext' => 'How jo lisćina systemowych powěsćow w mjenowem rumje MediaWiki.
-Pšosym wobglědaj [//www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jolic coš k lokalizaciji MediaWiki pśinosowaś.',
+Pšosym wobglědaj [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jolic coš k lokalizaciji MediaWiki pśinosowaś.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' njejo tuchylu móžno, dokulaž jo datowa banka offline.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Pó pśiměrjeńskem stawje filtrěrowaś:',
@@ -2670,6 +2780,8 @@ Pšosym wobglědaj [//www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki
 'thumbnail-more' => 'Pówětšyś',
 'filemissing' => 'Dataja felujo',
 'thumbnail_error' => 'Zmólka pśi stwórjenju pśeglěda: $1',
+'thumbnail_error_remote' => 'Zmólkowa powěźeńka wót $1:
+$2',
 'djvu_page_error' => 'DjVu-bok pśesegujo wobłuk.',
 'djvu_no_xml' => 'Njejo móžno, XML za DjVu-dataju wótwołaś.',
 'thumbnail-temp-create' => 'Temporerna dataja za miniaturny wobrazk njedajo se napóraś',
@@ -2751,7 +2863,7 @@ Wšykne transwiki-importowe akcije protokolěruju se w [[Special:Log/import|log-
 'tooltip-pt-anonuserpage' => 'Wužywarski bok za IP-adresu, z kótarejuž bok wobźěłajoš',
 'tooltip-pt-mytalk' => 'Twój diskusijny bok',
 'tooltip-pt-anontalk' => 'Diskusija wó změnach z tuteje IP-adresy.',
-'tooltip-pt-preferences' => 'Móje pśistajenja',
+'tooltip-pt-preferences' => 'Móje nastajenja',
 'tooltip-pt-watchlist' => 'Lisćina bokow, kótarež se wobglěduju',
 'tooltip-pt-mycontris' => 'Lisćina twójich pśinoskow',
 'tooltip-pt-login' => 'Pśizjawjenje njejo obligatoriske, ale lubje witane.',
@@ -2815,6 +2927,7 @@ Wšykne transwiki-importowe akcije protokolěruju se w [[Special:Log/import|log-
 W zespominanju dajo se pśicyna pódaś.',
 'tooltip-preferences-save' => 'Nastajenja składowaś',
 'tooltip-summary' => 'Zapódaj krotke zespominanje',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/** Na toś tom městnje wustatkujo se CSS na wšykne šaty. */',
@@ -2847,6 +2960,8 @@ W zespominanju dajo se pśicyna pódaś.',
 'spam_reverting' => 'Nawrośijo se slědna wersija, kótaraž njejo wopśimjeła wótkaz na $1.',
 'spam_blanking' => 'Wšykne wersije su wopśimowali wótkaze na $1, do rěcha spórane.',
 'spam_deleting' => 'Wšykne wersije z wótkazami do $1 so lašuju',
+'simpleantispam-label' => "Kontrola pśeśiwo spamoju.
+HOW '''NIC''' njezapisaś!",
 
 # Info page
 'pageinfo-title' => 'Informacije za bok "$1"',
@@ -2860,13 +2975,14 @@ W zespominanju dajo se pśicyna pódaś.',
 'pageinfo-length' => 'Dłujkosć boka (w bajtach)',
 'pageinfo-article-id' => 'ID boka',
 'pageinfo-language' => 'Rěc bokowego wopśimjeśa',
-'pageinfo-robot-policy' => 'Status pytawy',
-'pageinfo-robot-index' => 'Indeksěrujobny',
-'pageinfo-robot-noindex' => 'Njeindeksěrujobny',
+'pageinfo-content-model' => 'Bokowy wopśimjeśowy model',
+'pageinfo-robot-policy' => 'Indicěrowanje pśez roboty',
+'pageinfo-robot-index' => 'Dowólony',
+'pageinfo-robot-noindex' => 'Zakazany',
 'pageinfo-views' => 'Licba zwobraznjenjow',
 'pageinfo-watchers' => 'Licba  wobglědowarjow boka',
 'pageinfo-few-watchers' => 'Mjenjej ako $1 {{PLURAL:$1|wobglědowaŕ|wobglědowarja|wobglědowarje|wobglědowarjow}}',
-'pageinfo-redirects-name' => 'Dalejpósrědnjenja k toś tomu bokoju',
+'pageinfo-redirects-name' => 'Licba dalejpósrědnjenjow k toś tomu bokoju',
 'pageinfo-redirects-value' => '$1',
 'pageinfo-subpages-name' => 'Pódboki toś togo boka',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|dalejpósrědnjenja|dalejpósrědnjeni|dalejpósrědnjenja|dalejpósrědnjenjow}}; $3 {{PLURAL:$3|njedalejpósrědnjenja|njedalejpósrědnjeni|njedalejpósrědnjenja|njedalejpósrědnjenjow}})',
@@ -2945,7 +3061,7 @@ $1',
 'svg-long-desc' => 'dataja SVG, nominalnje: $1 × $2 piksele, wjelikosć dataje: $3',
 'svg-long-desc-animated' => 'Animěrowana SVG-dataja, zakładnej wótměra $1 × $2 pikselow, datajowa wjelikosć: $3',
 'svg-long-error' => 'Njepłaśiwa SVG-dataja: $1',
-'show-big-image' => 'Połne optiske wótgranicowanje.',
+'show-big-image' => 'Originalna dataja',
 'show-big-image-preview' => 'Wjelikosć toś togo pśeglěda: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Druge rozeznaśe||Drugej rozeznaśi|Druge rozeznaśa|Druge rozeznaśa}}: $1.',
 'show-big-image-size' => '$1 × $2 pikselow',
@@ -2974,11 +3090,25 @@ $1',
 'minutes' => '{{PLURAL:$1|$1 minutu|$1 minutoma|$1 minutami|$1 minutami}}',
 'hours' => '{{PLURAL:$1|$1 góźinu|$1 góźinoma|$1 góźinami|$1 góźinami}}',
 'days' => '{{PLURAL:$1|$1 dnjom|$1 dnjoma|$1 dnjami|$1 dnjami}}',
+'weeks' => '{{PLURAL: $1|$1 tyźeń|$1 tyźenja|$1 tyźenje|$1 tyźenjow}}',
 'months' => '{{PLURAL:$1|$1 mjasecom|$1 mjasecoma|$1 mjasecami}}',
 'years' => '{{PLURAL:$1|$1 lětom|$1 lětoma|$1 lětami}}',
 'ago' => 'pśed $1',
 'just-now' => 'rowno',
 
+# Human-readable timestamps
+'hours-ago' => 'pśed $1 {{PLURAL:$1|goźinu|goźinoma|goźinami}}',
+'minutes-ago' => 'pśed $1 {{PLURAL:$1|minutu|minutoma|minutami}}',
+'seconds-ago' => 'pśed $1 {{PLURAL:$1|sekundu|sekundoma|sekundami}}',
+'monday-at' => 'Pónjeźele $1',
+'tuesday-at' => 'Wałtora $1',
+'wednesday-at' => 'Srjoda $1',
+'thursday-at' => 'Stwórtk $1',
+'friday-at' => 'Pětk $1',
+'saturday-at' => 'Sobota $1',
+'sunday-at' => 'Njeźela $1',
+'yesterday-at' => 'Cora $1',
+
 # Bad image list
 'bad_image_list' => 'Format jo slědujucy:
 
@@ -3190,7 +3320,7 @@ Slědujuce wótkaze w tej samej smužce se za wuwześa naglědaju, w kótarychž
 'exif-compression-4' => 'CCITT kupka 4 faksowe koděrowanje',
 
 'exif-copyrighted-true' => 'Pśez awtorske pšawo šćitany',
-'exif-copyrighted-false' => 'Zjawnosći pśistupny',
+'exif-copyrighted-false' => 'Status awtorskego pšawa njepóstajony',
 
 'exif-unknowndate' => 'Njeznaty datum',
 
@@ -3398,7 +3528,7 @@ Slědujuce wótkaze w tej samej smužce se za wuwześa naglědaju, w kótarychž
 
 # External editor support
 'edit-externally' => 'Dataje z eksternym programom wobźěłaś',
-'edit-externally-help' => '(Za dalšne informacije glědaj [//www.mediawiki.org/wiki/Manual:External_editors instalaciske instrukcije]).',
+'edit-externally-help' => '(Za dalšne informacije glědaj [https://www.mediawiki.org/wiki/Manual:External_editors instalaciske instrukcije]).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'wšykne',
@@ -3486,6 +3616,9 @@ Pšosym wobkšuś, až napšawdu coš toś ten bok zasej napóraś.',
 'confirm-unwatch-button' => 'W pórěźe',
 'confirm-unwatch-top' => 'Toś ten bok z twójeje wobglědowańki wulašowaś?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '← slědny bok',
 'imgmultipagenext' => 'pśiducy bok →',
@@ -3582,8 +3715,9 @@ Móžoš teke [[Special:EditWatchlist|standardny wobźěłowański bok wužywaś
 'version-hook-subscribedby' => 'Aboněrowany wót',
 'version-version' => '(Wersija $1)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Toś ten wiki spěchujo se wót '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Toś ten wiki spěchujo se wót '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'druge',
+'version-poweredby-translators' => 'Pśełožowarje na translatewiki.net',
 'version-credits-summary' => 'Źěkujomy se slědujucym wósobam za jich pśinoski k [[Special:Version|MediaWiki]]',
 'version-license-info' => 'MediaWiki jo licha softwara: móžoš ju pód wuměnjenjami licence GNU General Public License, wózjawjeneje wót załožby Free Software Foundation, rozdźěliś a/abo změniś: pak pód wersiju 2 licence pak pód někakeju pózdźejšeju wersiju.
 
@@ -3597,6 +3731,19 @@ Ty by dejał [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licence GNU General Public
 'version-entrypoints-header-entrypoint' => 'Zastupny dypk',
 'version-entrypoints-header-url' => 'URL',
 
+# Special:Redirect
+'redirect' => 'Pó datajowem mjenju, wužywarju abo wersijowem ID dalej pósrědniś',
+'redirect-legend' => 'Do dataje abo boka dalej pósrědniś',
+'redirect-summary' => 'Toś ten specialny bok pósrědnja se do dataje (datajowe mě jo pódane), boka (wersijowy ID jo pódany) abo wužywarskego boka (numeriski wužywarski ID jo pódany) dalej. Wužyśe:
+[[{{#Special:Redirect}}/file/Pśikład.jpg]], [[{{#Special:Redirect}}/revision/328429]] abo [[{{#Special:Redirect}}/user/101]].',
+'redirect-submit' => 'Pytaś',
+'redirect-lookup' => 'Pytaś:',
+'redirect-value' => 'Gódnota:',
+'redirect-user' => 'ID wužywarja',
+'redirect-revision' => 'Bokowa wersija',
+'redirect-file' => 'Datajowe mě',
+'redirect-not-exists' => 'Gódnota njejo se namakała',
+
 # Special:FileDuplicateSearch
 'fileduplicatesearch' => 'Za duplikatnymi datajami pytaś',
 'fileduplicatesearch-summary' => 'Za datajowymi duplikatami na zakłaźe gótnoty hash pytaś.',
@@ -3610,8 +3757,8 @@ Ty by dejał [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licence GNU General Public
 
 # Special:SpecialPages
 'specialpages' => 'Specialne boki',
-'specialpages-note' => '----
-* Normalne specialne boki
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Normalne specialne boki.
 * <span class="mw-specialpagerestricted">Specialne boki z wobgranicowanym pśistupom.</span>',
 'specialpages-group-maintenance' => 'Wótwardowańske lisćiny',
 'specialpages-group-other' => 'Druge specialne boki',
@@ -3644,12 +3791,16 @@ Ty by dejał [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licence GNU General Public
 'tags' => 'Płaśiwe toflicki změnow',
 'tag-filter' => 'Filter [[Special:Tags|toflickow]]:',
 'tag-filter-submit' => 'Filter',
+'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Wobznamjenje|Wobznamjeni|Wobznamjenja}}]]: $2)',
 'tags-title' => 'Toflicki',
 'tags-intro' => 'Toś ten bok nalicyjo toflicki, z kótarymiž softwara móžo změnu markěrowaś a jich wóznam.',
 'tags-tag' => 'Mě toflicki',
 'tags-display-header' => 'Naglěd na lisćinach změnow',
 'tags-description-header' => 'Dopołne wopisanje wóznama',
+'tags-active-header' => 'Aktiwny?',
 'tags-hitcount-header' => 'Změny z toflickami',
+'tags-active-yes' => 'Jo',
+'tags-active-no' => 'Ně',
 'tags-edit' => 'wobźěłaś',
 'tags-hitcount' => '$1 {{PLURAL:$1|změna|změnje|změny|změnow}}',
 
@@ -3670,6 +3821,7 @@ Ty by dejał [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licence GNU General Public
 'dberr-problems' => 'Wódaj! Toś to sedło ma techniske śěžkosći.',
 'dberr-again' => 'Pócakaj někotare minuty a aktualizěruj bok.',
 'dberr-info' => '(Njejo móžno ze serwerom datoweje banki zwězaś: $1)',
+'dberr-info-hidden' => '(Njejo móžno ze serwerom datoweje banki zwězaś)',
 'dberr-usegoogle' => 'Móžoš mjaztym pśez Google pytaś.',
 'dberr-outofdate' => 'Źiwaj na to, až jich indekse našogo wopśimjeśa by mógli zestarjone byś.',
 'dberr-cachederror' => 'Slědujuca jo pufrowana kopija pominanego boka a by mógła zestarjona byś.',
@@ -3685,6 +3837,9 @@ Ty by dejał [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licence GNU General Public
 'htmlform-submit' => 'Wótpósłaś',
 'htmlform-reset' => 'Změny anulěrowaś',
 'htmlform-selectorother-other' => 'Druge',
+'htmlform-no' => 'Ně',
+'htmlform-yes' => 'Jo',
+'htmlform-chosen-placeholder' => 'Wubjeŕ móžnosć',
 
 # SQLite database support
 'sqlite-has-fts' => 'Wersija $1 z pódpěru za połnotekstowe pytanje',
@@ -3802,4 +3957,32 @@ Hować móžoš slědujucy jadnory formular wužywaś. Twój komentar pśidajo s
 # Image rotation
 'rotate-comment' => 'Wobraz wó $1 {{PLURAL:$1|stopjeń|stopnja|stopnje|stopnjow}} ako špěra źo wobwjertnjony',
 
+# Limit report
+'limitreport-title' => 'Profilěrowańske daty parsera:',
+'limitreport-cputime' => 'Casowe wužywanje CPU',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|sekunda|sekunźe|sekundy|sekundow}}',
+'limitreport-walltime' => 'Wužywanje napšawdnego casa',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekunda|sekunźe|sekundy|sekundow}}',
+'limitreport-ppvisitednodes' => 'Licba woglědanych sukow preprocesora',
+'limitreport-ppgeneratednodes' => 'Napórana licba sukow  preprocesora',
+'limitreport-postexpandincludesize' => 'Wjelikosć zapśěgowanja pó ekspanděrowanju',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bajt|bajtaj|bajty|bajtow}}',
+'limitreport-templateargumentsize' => 'Wjelikosć pśedłogowego argumenta',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bajt|bajtaj|bajty|bajtow}}',
+'limitreport-expansiondepth' => 'Nejwuša ekspansijowa dłymokosć',
+'limitreport-expensivefunctioncount' => 'Licba wupominańskich parserowych funkcijow',
+
+# Special:ExpandTemplates
+'expandtemplates' => 'Pśedłogi ekspanděrowaś',
+'expand_templates_intro' => 'Na toś tom boku dajo se tekst zapódaś a wšykne pśedłogi na njom se rekursiwnje ekspanděruju. Teke parserowe funkcije kaž <code><nowiki>{{</nowiki>#language:…}}</code> a wariable kaž <code><nowiki>{{</nowiki>CURRENTDAY}}</code> se ekspanděruju - faktiski wšo, což stoj mjazy dwójnymi wugibnjonymi spinkami.',
+'expand_templates_title' => 'Kontekstowy titel, za {{FULLPAGENAME}} atd.',
+'expand_templates_input' => 'Zapódany tekst:',
+'expand_templates_output' => 'Wuslědk',
+'expand_templates_xml_output' => 'Wudany XML',
+'expand_templates_ok' => 'W pórěźe',
+'expand_templates_remove_comments' => 'Komentary wótwónoźeś',
+'expand_templates_remove_nowiki' => 'Toflicki <nowiki> we wuslědku pódtłocyś',
+'expand_templates_generate_xml' => 'Parsowański bom XML pokazaś',
+'expand_templates_preview' => 'Pśeglěd',
+
 );
index 2ec192b..2a69fee 100644 (file)
@@ -273,8 +273,6 @@ Intaai [[Special:Version|bolikon dinolinan]].',
 'ok' => 'Oboh',
 'retrievedfrom' => 'Naanu mantad "$1"',
 'youhavenewmessages' => 'Kiharo $1 montok dia ($2).',
-'newmessageslink' => 'pason kawawagu',
-'newmessagesdifflink' => 'naalanan kawawagu',
 'youhavenewmessagesfromusers' => 'Nakaramit ko do $1 mantad {{PLURAL:$3|momomoguno suai|$3 tongomomomoguno}} ($2).',
 'youhavenewmessagesmanyusers' => 'Nakaramit koh do $1 mantad do tongomomomoguno ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|pason kawawagu|tangapason kawawagu}}',
@@ -977,7 +975,6 @@ Imurai no do indik suang diti {{SITENAME}} nopo nga nokolipas.',
 'preferences' => 'Pipilion',
 'mypreferences' => 'Pipilion',
 'prefs-edits' => 'Ginumu niditan:',
-'prefsnologin' => 'Amu nokolog sumuang',
 'changepassword' => 'Alanai kaatalib',
 'prefs-skin' => 'Kulit',
 'skin-preview' => 'Kokitanan',
@@ -1477,7 +1474,7 @@ Iri suai sinandad do poinlisok.
 
 # External editor support
 'edit-externally' => 'Idito pail diti momoguno do kangkaraja pongi-ngidit poinlabus',
-'edit-externally-help' => '(Intaai [//www.mediawiki.org/wiki/Manual:External_editors karalan-ralanon papasang] do lobi gumu kointalangan)',
+'edit-externally-help' => '(Intaai [https://www.mediawiki.org/wiki/Manual:External_editors karalan-ralanon papasang] do lobi gumu kointalangan)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'oinsanan',
index 87c5aeb..b194d54 100644 (file)
@@ -285,8 +285,6 @@ $1',
 'ok' => 'ރަނގަޅު',
 'retrievedfrom' => '$1 އިން',
 'youhavenewmessages' => 'ތިޔަބޭފުޅާއަށް $1 ($2)',
-'newmessageslink' => 'އައު މެސެޖުތައް',
-'newmessagesdifflink' => 'އެންމެ ފަހުގެ ބަދަލު',
 'youhavenewmessagesfromusers' => 'ތިބޭފުޅާއަށް {{PLURAL:$3|މެމްބަރެއް|$3 މެމްބަރުން}} $1 ފޮނުއްވާފައިވެއެވެ. ($2)',
 'youhavenewmessagesmanyusers' => 'ތިބޭފުޅާއަށް ގިނަ މެމްބަރުން $1 ފޮނުއްވާފައިވެއެވެ. ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|އާ މެސެޖެއް|މެސެޖުތައް}}',
index ab4f228..f2c5cde 100644 (file)
@@ -10,6 +10,7 @@
  * @author AK
  * @author Aitolos
  * @author Assassingr
+ * @author Astralnet
  * @author Azimout
  * @author Badseed
  * @author Chomwitt
@@ -36,6 +37,7 @@
  * @author Protnet
  * @author Reedy
  * @author Remember the dot
+ * @author Sfyrakis
  * @author Sinopeus
  * @author Tifa93
  * @author Urhixidur
@@ -104,7 +106,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'ΚακόςΤίτλος' ),
        'Blankpage'                 => array( 'ΚενήΣελίδα' ),
        'Block'                     => array( 'Φραγή', 'ΦραγήIP', 'ΦραγήΧρήστη' ),
-       'Blockme'                   => array( 'ΦραγήΕμένα' ),
        'Booksources'               => array( 'ΠηγέςΒιβλίων' ),
        'BrokenRedirects'           => array( 'ΚατεστραμμένεςΑνακατευθύνσεις' ),
        'Categories'                => array( 'Κατηγορίες' ),
@@ -116,9 +117,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ΔημιουργίαΛογαριασμού' ),
        'Deadendpages'              => array( 'ΑδιέξοδεςΣελίδες' ),
        'DeletedContributions'      => array( 'ΔιαγραμμένεςΣυνεισφορές' ),
-       'Disambiguations'           => array( 'Αποσαφηνίσεις' ),
        'DoubleRedirects'           => array( 'ΔιπλέςΑνακατευθύνσεις' ),
        'Emailuser'                 => array( 'EmailΧρήστη' ),
+       'ExpandTemplates'           => array( 'ΕπέκτασηΠροτύπων' ),
        'Export'                    => array( 'Εξαγωγή' ),
        'Fewestrevisions'           => array( 'ΛιγότεροΕπεξεργασίες' ),
        'FileDuplicateSearch'       => array( 'ΑναζήτησηΔιπλώνΑρχείων' ),
@@ -161,6 +162,7 @@ $specialPageAliases = array(
        'Randomredirect'            => array( 'ΤυχαίαΑνακατεύθυνση' ),
        'Recentchanges'             => array( 'ΠρόσφατεςΑλλαγές' ),
        'Recentchangeslinked'       => array( 'ΣυνδεδεμένεςΠρόσφατεςΑλλαγές', 'ΣχετικέςΑλλαγές' ),
+       'Redirect'                  => array( 'Ανακατεύθυνση' ),
        'Revisiondelete'            => array( 'ΔιαγραφήΈκδοσης' ),
        'Search'                    => array( 'Αναζήτηση' ),
        'Shortpages'                => array( 'ΜικρέςΣελίδες' ),
@@ -193,12 +195,12 @@ $specialPageAliases = array(
 
 $magicWords = array(
        'redirect'                  => array( '0', '#ΑΝΑΚΑΤΕΥΘΥΝΣΗ', '#REDIRECT' ),
-       'notoc'                     => array( '0', '__ΧΩΡΙΣΠΠ__', '__NOTOC__' ),
+       'notoc'                     => array( '0', '__ΧΩΡΙΣΠΠ__', '__ΧΩΡΙΣΠΙΝΑΚΑΠΕΡΙΕΧΟΜΕΝΩΝ__', '__NOTOC__' ),
        'nogallery'                 => array( '0', '__ΧΩΡΙΣΠΙΝΑΚΟΘΗΚΗ__', '__NOGALLERY__' ),
-       'forcetoc'                  => array( '0', '__ΜΕΠΠ__', '__FORCETOC__' ),
-       'toc'                       => array( '0', '__ΠΠ__', '__TOC__' ),
-       'noeditsection'             => array( '0', '__ΧΩΡΙΣΕΠΕΞΕΝΟΤ__', '__NOEDITSECTION__' ),
-       'currentmonth'              => array( '1', 'ΤΡΕΧΩΝΜΗΝΑΣ', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'forcetoc'                  => array( '0', '__ΜΕΠΠ__', '__ΜΕΠΙΝΑΚΑΠΕΡΙΕΧΟΜΕΝΩΝ__', '__FORCETOC__' ),
+       'toc'                       => array( '0', '__ΠΠ__', '__ΠΙΝΑΚΑΣΠΕΡΙΕΧΟΜΕΝΩΝ__', '__TOC__' ),
+       'noeditsection'             => array( '0', '__ΧΩΡΙΣΕΠΕΞΕΝΟΤ__', '__ΧΩΡΙΣΕΠΕΞΕΡΓΑΣΙΑΕΝΟΤΗΤΩΝ__', '__NOEDITSECTION__' ),
+       'currentmonth'              => array( '1', 'ΤΡΕΧΩΝΜΗΝΑΣ', 'ΤΡΕΧΩΝΜΗΝΑΣ2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
        'currentmonth1'             => array( '1', 'ΤΡΕΧΩΝΜΗΝΑΣ1', 'CURRENTMONTH1' ),
        'currentmonthname'          => array( '1', 'ΤΡΕΧΩΝΜΗΝΑΣΟΝΟΜΑ', 'CURRENTMONTHNAME' ),
        'currentmonthnamegen'       => array( '1', 'ΤΡΕΧΩΝΜΗΝΑΣΓΕΝΙΚΗ', 'CURRENTMONTHNAMEGEN' ),
@@ -231,7 +233,7 @@ $magicWords = array(
        'pagenamee'                 => array( '1', 'ΟΝΟΜΑΣΕΛΙΔΑΣΚ', 'PAGENAMEE' ),
        'namespace'                 => array( '1', 'ΠΕΡΙΟΧΗ', 'NAMESPACE' ),
        'namespacee'                => array( '1', 'ΠΕΡΙΟΧΗΚ', 'NAMESPACEE' ),
-       'namespacenumber'           => array( '1', 'ΑΡΙΘΜΟΣΟΝΟΜΑΤΟΣΧΩΡΟΥ', 'NAMESPACENUMBER' ),
+       'namespacenumber'           => array( '1', 'ΑΡΙΘΜΟΣΟΝΟΜΑΤΟΣΧΩΡΟΥ', 'ΑΡΙΘΜΟΣΟΝΟΜΑΤΟΧΩΡΟΥ', 'NAMESPACENUMBER' ),
        'talkspace'                 => array( '1', 'ΠΕΡΙΟΧΗΣΥΖΗΤΗΣΕΩΝ', 'TALKSPACE' ),
        'talkspacee'                => array( '1', 'ΠΕΡΙΟΧΗΣΥΖΗΤΗΣΕΩΝΚ', 'TALKSPACEE' ),
        'subjectspace'              => array( '1', 'ΠΕΡΙΟΧΗΘΕΜΑΤΩΝ', 'SUBJECTSPACE', 'ARTICLESPACE' ),
@@ -258,8 +260,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'κέντρο', 'center', 'centre' ),
        'img_framed'                => array( '1', 'με-πλαίσιο', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'χωρίς-πλαίσιο', 'frameless' ),
-       'img_page'                  => array( '1', 'σελίδα=$1', 'σελίδα $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'κατακόρυφα', 'κατακόρυφα=$1', 'κατακόρυφα $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'σελίδα=$1', 'σελίδα_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'κατακόρυφα', 'κατακόρυφα=$1', 'κατακόρυφα_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'πλαίσιο', 'border' ),
        'img_baseline'              => array( '1', 'γραμμήβάσης', 'baseline' ),
        'img_sub'                   => array( '1', 'δείκτης', 'sub' ),
@@ -273,12 +275,13 @@ $magicWords = array(
        'img_alt'                   => array( '1', 'εναλλ.=$1', 'alt=$1' ),
        'int'                       => array( '0', 'ΕΣΩΤ:', 'INT:' ),
        'sitename'                  => array( '1', 'ΙΣΤΟΧΩΡΟΣ', 'SITENAME' ),
-       'ns'                        => array( '0', 'ΧΟ:', 'NS:' ),
+       'ns'                        => array( '0', 'ΧΟ:', 'ΧΩΡΟΣΟΝΟΜΑΤΩΝ:', 'ΟΧ:', 'ΟΝΟΜΑΤΟΧΩΡΟΣ:', 'NS:' ),
        'localurl'                  => array( '0', 'ΤΟΠΙΚΟURL:', 'LOCALURL:' ),
        'localurle'                 => array( '0', 'ΤΟΠΙΚΟURLΚ:', 'LOCALURLE:' ),
        'server'                    => array( '0', 'ΕΞΥΠΗΡΕΤΗΤΗΣ', 'SERVER' ),
        'servername'                => array( '0', 'ΟΝΟΜΑΕΞΥΠΗΡΕΤΗΤΗ', 'SERVERNAME' ),
        'scriptpath'                => array( '0', 'ΔΙΑΔΡΟΜΗΠΡΟΓΡΑΜΜΑΤΟΣ', 'SCRIPTPATH' ),
+       'stylepath'                 => array( '0', 'ΔΙΑΔΡΟΜΗΣΤΥΛ', 'STYLEPATH' ),
        'grammar'                   => array( '0', 'ΓΡΑΜΜΑΤΙΚΗ:', 'GRAMMAR:' ),
        'gender'                    => array( '0', 'ΦΥΛΟ:', 'GENDER:' ),
        'notitleconvert'            => array( '0', '__ΧΩΡΙΣΜΕΤΑΤΡΟΠΗΤΙΤΛΟΥ__', '__NOTITLECONVERT__', '__NOTC__' ),
@@ -291,17 +294,21 @@ $magicWords = array(
        'revisionday'               => array( '1', 'ΜΕΡΑΑΛΛΑΓΗΣ', 'REVISIONDAY' ),
        'revisionday2'              => array( '1', 'ΜΕΡΑΑΛΛΑΓΗΣ2', 'REVISIONDAY2' ),
        'revisionmonth'             => array( '1', 'ΜΗΝΑΣΑΛΛΑΓΗΣ', 'REVISIONMONTH' ),
+       'revisionmonth1'            => array( '1', 'ΜΗΝΑΣΑΝΑΘΕΩΡΗΣΗΣ1', 'REVISIONMONTH1' ),
        'revisionyear'              => array( '1', 'ΕΤΟΣΑΛΛΑΓΗΣ', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', 'ΧΡΟΝΟΣΗΜΑΝΣΗΑΛΛΑΓΗΣ', 'REVISIONTIMESTAMP' ),
+       'revisionuser'              => array( '1', 'ΧΡΗΣΤΗΣΑΝΑΘΕΩΡΗΣΗΣ', 'REVISIONUSER' ),
        'plural'                    => array( '0', 'ΠΛΗΘΥΝΤΙΚΟΣ:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'ΠΛΗΡΕΣURL:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'ΠΛΗΡΕΣURLΚ:', 'FULLURLE:' ),
+       'canonicalurl'              => array( '0', 'ΚΑΝΟΝΙΚΟURL:', 'CANONICALURL:' ),
+       'canonicalurle'             => array( '0', 'ΚΑΝΟΝΙΚΟURLΚ:', 'CANONICALURLE:' ),
        'lcfirst'                   => array( '0', 'ΠΡΩΤΟΠΕΖΟ:', 'LCFIRST:' ),
        'ucfirst'                   => array( '0', 'ΠΡΩΤΟΚΕΦΑΛΑΙΟ:', 'UCFIRST:' ),
        'lc'                        => array( '0', 'ΠΕΖΑ:', 'LC:' ),
        'uc'                        => array( '0', 'ΚΕΦΑΛΑΙΑ:', 'UC:' ),
        'raw'                       => array( '0', 'ΓΥΜΝΑ:', 'RAW:' ),
-       'displaytitle'              => array( '1', 'ΔΕΙΞΕΤΙΤΛΟ', 'DISPLAYTITLE' ),
+       'displaytitle'              => array( '1', 'ΔΕΙΞΕΤΙΤΛΟ', 'ΠΡΟΒΟΛΗΤΙΤΛΟΥ', 'DISPLAYTITLE' ),
        'rawsuffix'                 => array( '1', 'Γ', 'R' ),
        'newsectionlink'            => array( '1', '__ΔΕΣΜΟΣΝΕΑΣΕΝΟΤΗΤΑΣ__', '__NEWSECTIONLINK__' ),
        'currentversion'            => array( '1', 'ΤΡΕΧΟΥΣΑΕΚΔΟΣΗ', 'CURRENTVERSION' ),
@@ -329,6 +336,8 @@ $magicWords = array(
        'numberingroup'             => array( '1', 'ΟΜΑΔΑΑΡΙΘΜΗΣΗΣ', 'NUMBERINGROUP', 'NUMINGROUP' ),
        'staticredirect'            => array( '1', '__ΣΤΑΤΙΚΗΑΝΑΚΑΤΕΥΘΥΝΣΗ__', '__STATICREDIRECT__' ),
        'protectionlevel'           => array( '1', 'ΕΠΙΠΕΔΟΠΡΟΣΤΑΣΙΑΣ', 'PROTECTIONLEVEL' ),
+       'url_path'                  => array( '0', 'ΔΙΑΔΡΟΜΗ', 'PATH' ),
+       'url_query'                 => array( '0', 'ΕΡΩΤΗΜΑ', 'QUERY' ),
 );
 
 $fallback8bitEncoding = 'iso-8859-7';
@@ -579,7 +588,7 @@ $messages = array(
 'articlepage' => 'Εμφάνιση σελίδας περιεχομένου',
 'talk' => 'Συζήτηση',
 'views' => 'Προβολές',
-'toolbox' => 'Î\95Ï\81γαλειοθήκη',
+'toolbox' => 'Î\95Ï\81γαλεία',
 'userpage' => 'Προβολή σελίδας χρήστη',
 'projectpage' => 'Προβολή σελίδας εγχειρήματος',
 'imagepage' => 'Προβολή σελίδας αρχείου',
@@ -635,8 +644,6 @@ $1',
 'ok' => 'Εντάξει',
 'retrievedfrom' => 'Ανακτήθηκε από «$1»',
 'youhavenewmessages' => 'Έχετε $1 ($2).',
-'newmessageslink' => 'νέα μηνύματα',
-'newmessagesdifflink' => 'τελευταία αλλαγή',
 'youhavenewmessagesfromusers' => 'Έχετε $1 από {{PLURAL:$3|έναν άλλο χρήστη|$3 χρήστες}} ($2).',
 'youhavenewmessagesmanyusers' => 'Έχετε $1 από πολλούς χρήστες ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ένα νέο μήνυμα|νέα μηνύματα}}',
@@ -811,7 +818,7 @@ $2',
 'gotaccount' => 'Έχετε ήδη λογαριασμό; $1.',
 'gotaccountlink' => 'Είσοδος',
 'userlogin-resetlink' => 'Ξεχάσατε τα στοιχεία εισόδου σας;',
-'userlogin-resetpassword-link' => 'Î\88κδοÏ\83η Î½Î­Î¿Ï\85 ÎºÏ\89δικοÏ\8d πρόσβασης',
+'userlogin-resetpassword-link' => 'Î\9eεÏ\87λαÏ\83αÏ\84ε Ï\84ον ÎºÏ\89δικÏ\8c πρόσβασης',
 'helplogin-url' => 'Help:Σύνδεση',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Βοήθεια για τη σύνδεσή σας]]',
 'createacct-join' => 'Εισάγετε τα στοιχεία σας παρακάτω.',
@@ -924,7 +931,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'Κωδικός επαναφοράς',
 'passwordreset-text-one' => 'Συμπληρώστε την παρακάτω φόρμα για να επαναφέρετε τον κωδικό πρόσβασής σας.',
-'passwordreset-text-many' => '{{PLURAL:$1|ΣÏ\85μÏ\80ληÏ\81Ï\8eÏ\83Ï\84ε Î­Î½Î± Î±Ï\80Ï\8c Ï\84α Ï\80εδία Î³Î¹Î± Î½Î± ÎµÏ\80αναÏ\86έÏ\81εÏ\84ε Ï\84ον ÎºÏ\89δικÏ\8c Ï\80Ï\81Ï\8cÏ\83βαÏ\83ήÏ\82 Ï\83αÏ\82.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|ΣÏ\85μÏ\80ληÏ\81Ï\8eÏ\83Ï\84ε Î­Î½Î± Î±Ï\80Ï\8c Ï\84α Ï\80εδία Î³Î¹Î± Î½Î± Î»Î¬Î²ÎµÏ\84ε Ï\80Ï\81οÏ\83Ï\89Ï\81ινÏ\8c ÎºÏ\89δικÏ\8c Ï\80Ï\81Ï\8cÏ\83βαÏ\83η Î¼Î­Ï\83Ï\89 Î·Î»ÎµÎºÏ\84Ï\81ονικοÏ\8d Ï\84αÏ\87Ï\85δÏ\81ομείοÏ\85.}}',
 'passwordreset-legend' => 'Επαναφορά κωδικού πρόσβασης',
 'passwordreset-disabled' => 'Η επαναφορά κωδικού πρόσβασης έχει απενεργοποιηθεί σε αυτό το wiki',
 'passwordreset-emaildisabled' => "Τα χαρακτηριστικά ηλεκτρονικού ταχυδρομείου έχουν απενεργοποιηθεί σ' αυτό το wiki.",
@@ -1308,8 +1315,8 @@ Mπορείτε να δείτε αυτή την διαφορά. Λεπτομέρ
 'revdelete-hide-user' => 'Κρύψε όνομα χρήστη/IP συντάκτη',
 'revdelete-hide-restricted' => 'Απόκρυψη δεδομένων από διαχειριστές καθώς και από άλλους',
 'revdelete-radio-same' => '(μην αλλάξετε)',
-'revdelete-radio-set' => 'Î\9dαι',
-'revdelete-radio-unset' => 'Î\8cÏ\87ι',
+'revdelete-radio-set' => 'Î\95μÏ\86ανέÏ\82',
+'revdelete-radio-unset' => 'Î\9aÏ\81Ï\85Ï\86Ï\8c',
 'revdelete-suppress' => 'Απόκρυψε δεδομένα από διαχειριστές όπως και από άλλους',
 'revdelete-unsuppress' => 'Αφαίρεσε περιορισμούς στις αποκατεστημένες αναθεωρήσεις',
 'revdelete-log' => 'Αιτία:',
@@ -1462,8 +1469,6 @@ $1",
 'preferences' => 'Προτιμήσεις',
 'mypreferences' => 'Προτιμήσεις',
 'prefs-edits' => 'Αριθμός επεξεργασιών:',
-'prefsnologin' => 'Δεν έχετε συνδεθεί.',
-'prefsnologintext' => 'Πρέπει να έχετε <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} συνδεθεί]</span> για να καθορίσετε τις προτιμήσεις χρήστη.',
 'changepassword' => 'Αλλαγή κωδικού',
 'prefs-skin' => 'Οπτική οργάνωση (skin)',
 'skin-preview' => 'Προεπισκόπηση',
@@ -1757,6 +1762,7 @@ $1",
 'recentchanges-label-minor' => 'Αυτή είναι μια μικροαλλαγή',
 'recentchanges-label-bot' => 'Αυτή η επεξεργασία έγινε από ένα ρομπότ',
 'recentchanges-label-unpatrolled' => 'Αυτή η επεξεργασία δεν έχει ελεγχθεί ακόμα',
+'recentchanges-legend-newpage' => '$1 - νέα σελίδα',
 'rcnote' => "Παρακάτω {{PLURAL:$1|υπάρχει '''1''' αλλαγή|υπάρχουν οι τελευταίες '''$1''' αλλαγές}} στο διάστημα {{PLURAL:$2|της τελευταίας ημέρας|των τελευταίων '''$2''' ημερών}}, από τις $5, $4 και εξής.",
 'rcnotefrom' => "Παρακάτω είναι οι αλλαγές από τις '''$2''' (εμφανίζονται μέχρι '''$1''').",
 'rclistfrom' => 'Εμφάνιση νέων αλλαγών αρχίζοντας από $1',
@@ -2088,7 +2094,7 @@ $1',
 'uploadnewversion-linktext' => 'Φορτώστε μια νέα έκδοση αυτού του αρχείου',
 'shared-repo-from' => 'από το $1',
 'shared-repo' => 'ένα κοινό εναποθετήριο',
-'shared-repo-name-wikimediacommons' => 'Κοινά Wikimedia',
+'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
 'upload-disallowed-here' => 'Δεν μπορείτε να αντικαταστήσετε αυτό το αρχείο.',
 
 # File reversion
@@ -2906,7 +2912,7 @@ $1',
 'movepage-moved' => '\'\'\'"$1" μεταφέρθηκε στο "$2"\'\'\'',
 'movepage-moved-redirect' => 'Δημιουργήθηκε μια ανακατεύθυνση.',
 'movepage-moved-noredirect' => 'Η δημιουργία ανακατεύθυνσης παρεμποδίστηκε.',
-'articleexists' => 'Υπάρχει ήδη σελίδα με αυτό το όνομα. Παρακαλούμε δώστε άλλο όνομα στη σελίδα.',
+'articleexists' => 'Υπάρχει ήδη σελίδα με αυτό το όνομα, ή το όνομα που επιλέξατε δεν είναι αποδεκτό. Παρακαλούμε δώστε άλλο όνομα στη σελίδα.',
 'cantmove-titleprotected' => "Δεν μπορείτε να μετακινήσετε μια σελίδα σ' αυτή τη θέση διότι έχει απαγορευθεί η δημιουργία αυτού του τίτλου",
 'talkexists' => "Η ίδια η σελίδα μετακινήθηκε επιτυχώς αλλά όχι και η σελίδα συζήτησης, λόγω του ότι υπάρχει ήδη άλλη σελίδα συζήτησης κάτω από το νέο τίτλο. Παρακαλούμε ενοποιήστε τις δύο σελίδες με 'αντιγραφή-και-επικόλληση'.",
 'movedto' => 'Μετακινήθηκε στο',
@@ -2979,7 +2985,7 @@ $1',
 'allmessagesdefault' => 'Προεπιλεγμένο κείμενο μηνύματος',
 'allmessagescurrent' => 'Παρόν κείμενο',
 'allmessagestext' => 'Αυτή είναι μια λίστα με όλα τα μηνύματα συστήματος που βρίσκονται στην περιοχή MediaWiki.
-Παρακαλούμε επισκεφθείτε τα [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] και [//translatewiki.net translatewiki.net] αν επιθυμείτε να συνεισφέρετε σε μια γενική μετάφραση του MediaWiki.',
+Παρακαλούμε επισκεφθείτε τα [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] και [//translatewiki.net translatewiki.net] αν επιθυμείτε να συνεισφέρετε σε μια γενική μετάφραση του MediaWiki.',
 'allmessagesnotsupportedDB' => "Αυτή η σελίδα δεν υποστηρίζεται επειδή το ''wgUseDatabaseMessages'' είναι απενεργοποιημένο.",
 'allmessages-filter-legend' => 'Φίλτρο',
 'allmessages-filter' => 'Ταξινόμηση βάσει της δήλωσης προσαρμογής:',
@@ -3180,6 +3186,8 @@ $2',
 'spam_reverting' => 'Επαναφορά στην τελευταία έκδοση που δεν περιέχει συνδέσμους στο $1',
 'spam_blanking' => 'Όλες οι αναθεωρήσεις περιείχαν συνδέσμους προς το $1, εξάλειψη',
 'spam_deleting' => 'Διαγραφή όλων των αναθεωρήσεων που περιείχαν συνδέσμους προς το $1',
+'simpleantispam-label' => "Έλεγχος anti-spam.
+'''ΜΗΝ''' το συμπληρώσετε αυτό!",
 
 # Info page
 'pageinfo-title' => 'Πληροφορίες για "$1"',
@@ -3743,7 +3751,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Επεξεργαστείτε αυτό το αρχείο χρησιμοποιώντας κάποια εξωτερική εφαρμογή',
-'edit-externally-help' => '(Βλ. [//www.mediawiki.org/wiki/Manual:External_editors οδηγίες εγκατάστασης] για περισσότερες πληροφορίες)',
+'edit-externally-help' => '(Βλ. [https://www.mediawiki.org/wiki/Manual:External_editors οδηγίες εγκατάστασης] για περισσότερες πληροφορίες)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'όλες',
@@ -3930,8 +3938,9 @@ $5
 'version-hook-subscribedby' => 'Υπογεγραμμένο από',
 'version-version' => '(Έκδοση $1)',
 'version-license' => 'Άδεια χρήσης',
-'version-poweredby-credits' => "Αυτό το wiki λειτουργεί με το λογισμικό '''[//www.mediawiki.org/ MediaWiki]''', πνευματική ιδιοκτησία © 2001-$1 $2.",
+'version-poweredby-credits' => "Αυτό το wiki λειτουργεί με το λογισμικό '''[https://www.mediawiki.org/ MediaWiki]''', πνευματική ιδιοκτησία © 2001-$1 $2.",
 'version-poweredby-others' => 'άλλοι',
+'version-poweredby-translators' => 'translatewiki.net μεταφραστές',
 'version-credits-summary' => 'Θα θέλαμε να αναγνωρίσουμε τη συμβολή των παρακάτω προσώπων στο [[Special:Version|MediaWiki]].',
 'version-license-info' => "Το MediaWiki είναι ελεύθερο λογισμικό. Μπορείτε να το αναδιανείμετε ή/και να το τροποποιήσετε υπό τους όρους της άδειας GNU General Public License όπως αυτή εκδόθηκε από το Free Software Foundation· είτε της δεύτερης έκδοσης της άδειας, είτε (κατ' επιλογή σας) οποιασδήποτε επόμενης έκδοσης.
 
@@ -4008,6 +4017,8 @@ $5
 'tags-display-header' => 'Εμφάνιση στις λίστες αλλαγής',
 'tags-description-header' => 'Πλήρης περιγραφή του νοήματος',
 'tags-hitcount-header' => 'Αλλαγές με ετικέτα',
+'tags-active-yes' => 'Ναι',
+'tags-active-no' => 'Όχι',
 'tags-edit' => 'επεξεργασία',
 'tags-hitcount' => '$1 {{PLURAL:$1|αλλαγή|αλλαγές}}',
 
@@ -4174,4 +4185,21 @@ $5
 'limitreport-expansiondepth' => 'Μεγαλύτερο βάθος ανάπτυξης',
 'limitreport-expensivefunctioncount' => 'Πλήθος ακριβών συναρτήσεων συντακτικού αναλυτή',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Επέκτεινε τα πρότυπα',
+'expand_templates_intro' => 'Αυτή η ειδική σελίδα παίρνει κείμενο και αναπτύσσει όλα τα πρότυπα σε αυτό αναδρομικά. 
+Επίσης αναπτύσσει συναρτήσεις συντακτικού αναλυτή όπως η
+<nowiki>{{</nowiki>#language:…}}, και μεταβλητές όπως η
+<nowiki>{{</nowiki>CURRENTDAY}}.
+Ουσιαστικά επεκτείνει οτιδήποτε βρίσκεται σε διπλές αγκύλες.',
+'expand_templates_title' => 'Τίτλων συμφραζόμενων, για την {{FULLPAGENAME}} κ.τ.λ.:',
+'expand_templates_input' => 'Κείμενο εισόδου:',
+'expand_templates_output' => 'Αποτέλεσμα',
+'expand_templates_xml_output' => 'Έξοδος XML',
+'expand_templates_ok' => 'Εντάξει',
+'expand_templates_remove_comments' => 'Αφαίρεση σχολίων',
+'expand_templates_remove_nowiki' => 'Απόκρυψη της ετικέτας <nowiki> στο αποτέλεσμα',
+'expand_templates_generate_xml' => 'Εμφάνιση δέντρου συντακτικής ανάλυσης XML',
+'expand_templates_preview' => 'Προεπισκόπηση',
+
 );
index ec8f0f2..1bd59b2 100644 (file)
@@ -406,6 +406,7 @@ $specialPageAliases = array(
        'DoubleRedirects'           => array( 'DoubleRedirects' ),
        'EditWatchlist'             => array( 'EditWatchlist' ),
        'Emailuser'                 => array( 'EmailUser' ),
+       'ExpandTemplates'           => array( 'ExpandTemplates', 'Expantemplates' ),
        'Export'                    => array( 'Export' ),
        'Fewestrevisions'           => array( 'FewestRevisions' ),
        'FileDuplicateSearch'       => array( 'FileDuplicateSearch' ),
@@ -494,6 +495,12 @@ $specialPageAliases = array(
  */
 $linkTrail = '/^([a-z]+)(.*)$/sD';
 
+/**
+ * Regular expression charset matching the "link prefix", e.g. "foo" in
+ * foo[[bar]]. UTF-8 characters may be used.
+ */
+$linkPrefixCharset = 'a-zA-Z\\x{80}-\\x{10ffff}';
+
 /**
  * List of filenames for some ui images that can be overridden per language
  * basis if needed.
@@ -550,7 +557,7 @@ $preloadedMessages = array(
        'editsectionhint',
        'help',
        'helppage',
-       'tooltip-iwiki',
+       'interlanguage-link-title',
        'jumpto',
        'jumptonavigation',
        'jumptosearch',
@@ -790,8 +797,6 @@ future releases. Also note that since each list value is wrapped in a unique
 'broken-file-category'           => 'Pages with broken file links',
 'categoryviewer-pagedlinks'      => '($1) ($2)', # only translate this message to other languages if you have to change it
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD', # only translate this message to other languages if you have to change it
-
 'about'         => 'About',
 'article'       => 'Content page',
 'newwindow'     => '(opens in new window)',
@@ -810,7 +815,6 @@ future releases. Also note that since each list value is wrapped in a unique
 'qbedit'         => 'Edit',
 'qbpageoptions'  => 'This page',
 'qbmyoptions'    => 'My pages',
-'qbspecialpages' => 'Special pages',
 'faq'            => 'FAQ',
 'faqpage'        => 'Project:FAQ',
 'sitetitle'      => '{{SITENAME}}', # do not translate or duplicate this message to other languages
@@ -911,7 +915,7 @@ $1',
 'disclaimers'          => 'Disclaimers',
 'disclaimerpage'       => 'Project:General disclaimer',
 'edithelp'             => 'Editing help',
-'edithelppage'         => '//www.mediawiki.org/wiki/Special:MyLanguage/Help:Editing_pages', # do not translate or duplicate this message to other languages
+'edithelppage'         => 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Editing_pages', # do not translate or duplicate this message to other languages
 'helppage'             => 'Help:Contents',
 'mainpage'             => 'Main Page',
 'mainpage-description' => 'Main page',
@@ -935,12 +939,10 @@ See [[Special:Version|version page]].',
 'backlinksubtitle'             => '← $1', # only translate this message to other languages if you have to change it
 'retrievedfrom'                => 'Retrieved from "$1"',
 'youhavenewmessages'           => 'You have $1 ($2).',
-'newmessageslink'              => 'new messages',
-'newmessagesdifflink'          => 'last change',
 'youhavenewmessagesfromusers'  => 'You have $1 from {{PLURAL:$3|another user|$3 users}} ($2).',
 'youhavenewmessagesmanyusers'  => 'You have $1 from many users ($2).',
-'newmessageslinkplural'        => '{{PLURAL:$1|a new message|new messages}}',
-'newmessagesdifflinkplural'    => 'last {{PLURAL:$1|change|changes}}',
+'newmessageslinkplural'        => '{{PLURAL:$1|a new message|999=new messages}}',
+'newmessagesdifflinkplural'    => 'last {{PLURAL:$1|change|999=changes}}',
 'youhavenewmessagesmulti'      => 'You have new messages on $1',
 'newtalkseparator'             => ',&#32;', # do not translate or duplicate this message to other languages
 'editsection'                  => 'edit',
@@ -972,7 +974,8 @@ See [[Special:Version|version page]].',
 'red-link-title'               => '$1 (page does not exist)',
 'sort-descending'              => 'Sort descending',
 'sort-ascending'               => 'Sort ascending',
-'tooltip-iwiki'                => '$1 – $2', # only translate this message to other languages if you have to change it
+'interlanguage-link-title'     => '$1 – $2', # only translate this message to other languages if you have to change it
+'interlanguage-link-title-langonly' => '$1', # do not translate or duplicate this message to other languages
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main'      => 'Page',
@@ -1047,9 +1050,6 @@ It may contain one or more characters that cannot be used in titles.',
 'perfcachedts'                  => 'The following data is cached, and was last updated $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.',
 'querypage-no-updates'          => 'Updates for this page are currently disabled.
 Data here will not presently be refreshed.',
-'wrong_wfQuery_params'          => 'Incorrect parameters to wfQuery()<br />
-Function: $1<br />
-Query: $2',
 'viewsource'                    => 'View source',
 'viewsource-title'              => 'View source for $1',
 'actionthrottled'               => 'Action throttled',
@@ -1081,7 +1081,8 @@ The administrator who locked it offered this explanation: "$3".',
 'invalidtitle-knownnamespace'   => 'Invalid title with namespace "$2" and text "$3"',
 'invalidtitle-unknownnamespace' => 'Invalid title with unknown namespace number $1 and text "$2"',
 'exception-nologin'             => 'Not logged in',
-'exception-nologin-text'        => 'This page or action requires you to be logged in on this wiki.',
+'exception-nologin-text'        => 'Please [[Special:Userlogin|log in]] to be able to access this page or action.',
+'exception-nologin-text-manual' => 'Please $1 to be able to access this page or action.',
 
 # Virus scanner
 'virus-badscanner'     => "Bad configuration: Unknown virus scanner: ''$1''",
@@ -1094,7 +1095,7 @@ The administrator who locked it offered this explanation: "$3".',
 Note that some pages may continue to be displayed as if you were still logged in, until you clear your browser cache.",
 'welcomeuser'                     => 'Welcome, $1!',
 'welcomecreation-msg'             => 'Your account has been created.
-Do not forget to change your [[Special:Preferences|{{SITENAME}} preferences]].',
+You can change your {{SITENAME}} [[Special:Preferences|preferences]] if you wish.',
 'yourname'                        => 'Username:',
 'userlogin-yourname'              => 'Username',
 'userlogin-yourname-ph'           => 'Enter your username',
@@ -1130,7 +1131,7 @@ Do not forget to change your [[Special:Preferences|{{SITENAME}} preferences]].',
 'gotaccount'                      => 'Already have an account? $1.',
 'gotaccountlink'                  => 'Log in',
 'userlogin-resetlink'             => 'Forgotten your login details?',
-'userlogin-resetpassword-link'    => 'Reset your password',
+'userlogin-resetpassword-link'    => 'Forgot your password?',
 'helplogin-url'                   => 'Help:Logging in',
 'userlogin-helplink'              => '[[{{MediaWiki:helplogin-url}}|Help with logging in]]',
 'userlogin-loggedin'              => 'You are already logged in as {{GENDER:$1|$1}}.
@@ -1195,7 +1196,7 @@ Please try again.',
 'passwordtooshort'                => 'Passwords must be at least {{PLURAL:$1|1 character|$1 characters}}.',
 'password-name-match'             => 'Your password must be different from your username.',
 'password-login-forbidden'        => 'The use of this username and password has been forbidden.',
-'mailmypassword'                  => 'Email new password',
+'mailmypassword'                  => 'Reset password',
 'passwordremindertitle'           => 'New temporary password for {{SITENAME}}',
 'passwordremindertext'            => 'Someone (probably you, from IP address $1) requested a new
 password for {{SITENAME}} ($4). A temporary password for user
@@ -1211,7 +1212,7 @@ continue using your old password.',
 'passwordsent'                    => 'A new password has been sent to the email address registered for "$1".
 Please log in again after you receive it.',
 'blocked-mailpassword'            => 'Your IP address is blocked from editing, and so is not allowed to use the password recovery function to prevent abuse.',
-'eauthentsent'                    => 'A confirmation email has been sent to the nominated email address.
+'eauthentsent'                    => 'A confirmation email has been sent to the specified email address.
 Before any other email is sent to the account, you will have to follow the instructions in the email, to confirm that the account is actually yours.',
 'throttled-mailpassword'          => 'A password reset email has already been sent, within the last {{PLURAL:$1|hour|$1 hours}}.
 To prevent abuse, only one password reset email will be sent per {{PLURAL:$1|hour|$1 hours}}.',
@@ -1224,8 +1225,8 @@ To prevent abuse, only one password reset email will be sent per {{PLURAL:$1|hou
 'mailerror'                       => 'Error sending mail: $1',
 'acct_creation_throttle_hit'      => 'Visitors to this wiki using your IP address have created {{PLURAL:$1|1 account|$1 accounts}} in the last day, which is the maximum allowed in this time period.
 As a result, visitors using this IP address cannot create any more accounts at the moment.',
-'emailauthenticated'              => 'Your email address was authenticated on $2 at $3.',
-'emailnotauthenticated'           => 'Your email address is not yet authenticated.
+'emailauthenticated'              => 'Your email address was confirmed on $2 at $3.',
+'emailnotauthenticated'           => 'Your email address is not yet confirmed.
 No email will be sent for any of the following features.',
 'noemailprefs'                    => 'Specify an email address in your preferences for these features to work.',
 'emailconfirmlink'                => 'Confirm your email address',
@@ -1285,8 +1286,8 @@ You may have already successfully changed your password or requested a new tempo
 
 # Special:PasswordReset
 'passwordreset'                    => 'Reset password',
-'passwordreset-text-one'           => 'Complete this form to reset your password.',
-'passwordreset-text-many'          => '{{PLURAL:$1|Fill one of the fields to reset your password.}}',
+'passwordreset-text-one'           => 'Complete this form to receive a temporary password via email.',
+'passwordreset-text-many'          => '{{PLURAL:$1|Fill in one of the fields to receive a temporary password via email.}}',
 'passwordreset-legend'             => 'Reset password',
 'passwordreset-disabled'           => 'Password resets have been disabled on this wiki.',
 'passwordreset-emaildisabled'      => 'Email features have been disabled on this wiki.',
@@ -1704,17 +1705,17 @@ Other administrators on {{SITENAME}} will still be able to access the hidden con
 'revdelete-suppress-text'     => "Suppression should '''only''' be used for the following cases:
 * Potentially libelous information
 * Inappropriate personal information
-*: ''home addresses and telephone numbers, social security numbers, etc.''",
+*: ''home addresses and telephone numbers, national identification numbers, etc.''",
 'revdelete-legend'            => 'Set visibility restrictions',
-'revdelete-hide-text'         => 'Hide revision text',
+'revdelete-hide-text'         => 'Revision text',
 'revdelete-hide-image'        => 'Hide file content',
 'revdelete-hide-name'         => 'Hide action and target',
-'revdelete-hide-comment'      => 'Hide edit summary',
-'revdelete-hide-user'         => "Hide editor's username/IP address",
+'revdelete-hide-comment'      => 'Edit summary',
+'revdelete-hide-user'         => "Editor's username/IP address",
 'revdelete-hide-restricted'   => 'Suppress data from administrators as well as others',
 'revdelete-radio-same'        => '(do not change)',
-'revdelete-radio-set'         => 'Yes',
-'revdelete-radio-unset'       => 'No',
+'revdelete-radio-set'         => 'Hidden',
+'revdelete-radio-unset'       => 'Visible',
 'revdelete-suppress'          => 'Suppress data from administrators as well as others',
 'revdelete-unsuppress'        => 'Remove restrictions on restored revisions',
 'revdelete-log'               => 'Reason:',
@@ -1857,7 +1858,7 @@ Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'showingresultsnum'                => "Showing below {{PLURAL:$3|'''1''' result|'''$3''' results}} starting with #'''$2'''.",
 'showingresultsheader'             => "{{PLURAL:$5|Result '''$1''' of '''$3'''|Results '''$1 - $2''' of '''$3'''}} for '''$4'''",
 'nonefound'                        => "'''Note:''' Only some namespaces are searched by default.
-Try prefixing your query with ''all:'' to search all content (including talk pages, templates, etc), or use the desired namespace as prefix.",
+Try prefixing your query with ''all:'' to search all content (including talk pages, templates, etc.), or use the desired namespace as prefix.",
 'search-nonefound'                 => 'There were no results matching the query.',
 'powersearch'                      => 'Advanced search',
 'powersearch-legend'               => 'Advanced search',
@@ -1894,8 +1895,7 @@ Note that their indexes of {{SITENAME}} content may be out of date.',
 'preferences-summary'           => '', # do not translate or duplicate this message to other languages
 'mypreferences'                 => 'Preferences',
 'prefs-edits'                   => 'Number of edits:',
-'prefsnologin'                  => 'Not logged in',
-'prefsnologintext'              => 'You must be <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logged in]</span> to set user preferences.',
+'prefsnologintext2'             => 'Please $1 to set user preferences.',
 'changepassword'                => 'Change password',
 'changepassword-summary'        => '', # do not translate or duplicate this message to other languages
 'prefs-skin'                    => 'Skin',
@@ -2205,6 +2205,9 @@ Your email address is not revealed when other users contact you.',
 'recentchanges-label-minor'         => 'This is a minor edit',
 'recentchanges-label-bot'           => 'This edit was performed by a bot',
 'recentchanges-label-unpatrolled'   => 'This edit has not yet been patrolled',
+'recentchanges-label-plusminus'     => 'The page size changed by this number of bytes',
+'recentchanges-legend-newpage'      => '(also see [[Special:NewPages|list of new pages]])',
+'recentchanges-legend-plusminus'    => "(''±123'')",
 'rcnote'                            => "Below {{PLURAL:$1|is '''1''' change|are the last '''$1''' changes}} in the last {{PLURAL:$2|day|'''$2''' days}}, as of $5, $4.",
 'rcnotefrom'                        => "Below are the changes since '''$2''' (up to '''$1''' shown).",
 'rclistfrom'                        => 'Show new changes starting from $1',
@@ -3013,9 +3016,9 @@ Contact the editor:
 mail: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-There will be no other notifications in case of further activity unless you visit this page. You could also reset the notification flags for all your watched pages on your watchlist.
+There will be no other notifications in case of further activity unless you visit this page while logged in. You could also reset the notification flags for all your watched pages on your watchlist.
 
-                        Your friendly {{SITENAME}} notification system
+Your friendly {{SITENAME}} notification system
 
 --
 To change your email notification settings, visit
@@ -3218,7 +3221,7 @@ It may have already been undeleted.',
 $1',
 'undelete-show-file-confirm'   => 'Are you sure you want to view the deleted revision of the file "<nowiki>$1</nowiki>" from $2 at $3?',
 'undelete-show-file-submit'    => 'Yes',
-'undelete-revisionrow'         => '$1 $2 ($3) $4 . . $5 $6 $7', # only translate this message to other languages if you have to change it
+'undelete-revision-row'         => '$1 $2 ($3) $4 . . $5 $6 $7 $8 $9', # only translate this message to other languages if you have to change it
 
 # Namespace form on various pages
 'namespace'                     => 'Namespace:',
@@ -3562,7 +3565,7 @@ In the latter case you can also use a link, for example [[{{#Special:Export}}/{{
 'allmessagesdefault'            => 'Default message text',
 'allmessagescurrent'            => 'Current message text',
 'allmessagestext'               => 'This is a list of system messages available in the MediaWiki namespace.
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB'     => "This page cannot be used because '''\$wgUseDatabaseMessages''' has been disabled.",
 'allmessages-filter-legend'     => 'Filter',
 'allmessages-filter'            => 'Filter by customization state:',
@@ -3851,6 +3854,8 @@ This is probably caused by a link to a blacklisted external site.',
 'spam_reverting'      => 'Reverting to last revision not containing links to $1',
 'spam_blanking'       => 'All revisions contained links to $1, blanking',
 'spam_deleting'       => 'All revisions contained links to $1, deleting',
+'simpleantispam-label' => "Anti-spam check.
+Do '''NOT''' fill this in!",
 
 # Info page
 'pageinfo-header'                 => '-', # do not translate or duplicate this message to other languages
@@ -3865,6 +3870,7 @@ This is probably caused by a link to a blacklisted external site.',
 'pageinfo-length'                 => 'Page length (in bytes)',
 'pageinfo-article-id'             => 'Page ID',
 'pageinfo-language'               => 'Page content language',
+'pageinfo-content-model'          => 'Page content model',
 'pageinfo-robot-policy'           => 'Indexing by robots',
 'pageinfo-robot-index'            => 'Allowed',
 'pageinfo-robot-noindex'          => 'Disallowed',
@@ -3955,7 +3961,7 @@ By executing it, your system may be compromised.",
 'svg-long-desc'               => 'SVG file, nominally $1 × $2 pixels, file size: $3',
 'svg-long-desc-animated'      => 'Animated SVG file, nominally $1 × $2 pixels, file size: $3',
 'svg-long-error'              => 'Invalid SVG file: $1',
-'show-big-image'              => 'Full resolution',
+'show-big-image'              => 'Original file',
 'show-big-image-preview'      => 'Size of this preview: $1.',
 'show-big-image-other'        => 'Other {{PLURAL:$2|resolution|resolutions}}: $1.',
 'show-big-image-size'         => '$1 × $2 pixels',
@@ -4527,10 +4533,6 @@ $8', # only translate this message to other languages if you have to change it
 'exif-urgency-high'   => 'High ($1)',
 'exif-urgency-other'  => 'User-defined priority ($1)',
 
-# External editor support
-'edit-externally'      => 'Edit this file using an external application',
-'edit-externally-help' => '(See the [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)',
-
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'all',
 'namespacesall' => 'all',
@@ -4645,6 +4647,7 @@ Please confirm that you really want to recreate this page.",
 'percent'             => '$1%', # only translate this message to other languages if you have to change it
 'parentheses'         => '($1)', # only translate this message to other languages if you have to change it
 'brackets'            => '[$1]', # only translate this message to other languages if you have to change it
+'quotation-marks'     => '"$1"',
 
 # Multipage image navigation
 'imgmultipageprev' => '← previous page',
@@ -4843,7 +4846,7 @@ You can also [[Special:EditWatchlist|use the standard editor]].',
 'version-version'                       => '(Version $1)',
 'version-svn-revision'                  => '(r$2)', # only translate this message to other languages if you have to change it
 'version-license'                       => 'License',
-'version-poweredby-credits'             => "This wiki is powered by '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits'             => "This wiki is powered by '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others'              => 'others',
 'version-poweredby-translators'         => 'translatewiki.net translators',
 'version-credits-summary'               => 'We would like to recognize the following persons for their contribution to [[Special:Version|MediaWiki]].',
@@ -4868,7 +4871,7 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'redirect'            => 'Redirect by file, user, or revision ID',
 'redirect-legend'     => 'Redirect to a file or page',
 'redirect-text'       => '', # do not translate or duplicate this message to other languages
-'redirect-summary'    => 'This special page redirects to a file (given the file name), a page (given a revision ID), or a user page (given a numeric user ID).',
+'redirect-summary'    => 'This special page redirects to a file (given the file name), a page (given a revision ID), or a user page (given a numeric user ID). Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit'     => 'Go',
 'redirect-lookup'     => 'Lookup:',
 'redirect-value'      => 'Value:',
@@ -4891,8 +4894,8 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 # Special:SpecialPages
 'specialpages'                   => 'Special pages',
 'specialpages-summary'           => '', # do not translate or duplicate this message to other languages
-'specialpages-note'              => '----
-* Normal special pages.
+'specialpages-note-top'          => 'Legend',
+'specialpages-note'              => '* Normal special pages.
 * <span class="mw-specialpagerestricted">Restricted special pages.</span>',
 'specialpages-group-maintenance' => 'Maintenance reports',
 'specialpages-group-other'       => 'Other special pages',
@@ -4954,8 +4957,7 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 
 # Database error messages
 'dberr-header'      => 'This wiki has a problem',
-'dberr-problems'    => 'Sorry!
-This site is experiencing technical difficulties.',
+'dberr-problems'    => 'Sorry! This site is experiencing technical difficulties.',
 'dberr-again'       => 'Try waiting a few minutes and reloading.',
 'dberr-info'        => '(Cannot contact the database server: $1)',
 'dberr-info-hidden' => '(Cannot contact the database server)',
@@ -5138,4 +5140,20 @@ Otherwise, you can use the easy form below. Your comment will be added to the pa
 'limitreport-expensivefunctioncount'       => 'Expensive parser function count',
 'limitreport-expensivefunctioncount-value' => '$1/$2', # only translate this message to other languages if you have to change it
 
+# ExpandTemplates
+'expandtemplates'                  => 'Expand templates',
+'expand_templates_intro'           => 'This special page takes text and expands all templates in it recursively.
+It also expands supported parser functions like
+<code><nowiki>{{</nowiki>#language:…}}</code> and variables like
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+In fact, it expands pretty much everything in double-braces.',
+'expand_templates_title'           => 'Context title, for {{FULLPAGENAME}}, etc.:',
+'expand_templates_input'           => 'Input text:',
+'expand_templates_output'          => 'Result',
+'expand_templates_xml_output'      => 'XML output',
+'expand_templates_ok'              => 'OK',
+'expand_templates_remove_comments' => 'Remove comments',
+'expand_templates_remove_nowiki'   => 'Suppress <nowiki> tags in result',
+'expand_templates_generate_xml'    => 'Show XML parse tree',
+'expand_templates_preview'         => 'Preview',
 );
index 2144c40..8f6dcfa 100644 (file)
@@ -38,6 +38,7 @@
  * @author Smeira
  * @author ThomasPusch
  * @author Tlustulimu
+ * @author Umbert'
  * @author Urhixidur
  * @author Yekrats
  * @author Александр Сигачёв
@@ -94,7 +95,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Malbona_titolo' ),
        'Blankpage'                 => array( 'Malplena_paĝo' ),
        'Block'                     => array( 'Forbari_IP-adreson' ),
-       'Blockme'                   => array( 'Forbari_min' ),
        'Booksources'               => array( 'Citoj_el_libroj' ),
        'BrokenRedirects'           => array( 'Rompitaj_alidirektiloj' ),
        'Categories'                => array( 'Kategorioj' ),
@@ -106,10 +106,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Krei_konton' ),
        'Deadendpages'              => array( 'Paĝoj_sen_interna_ligilo' ),
        'DeletedContributions'      => array( 'Forigitaj_kontribuoj' ),
-       'Disambiguations'           => array( 'Apartigiloj' ),
        'DoubleRedirects'           => array( 'Duoblaj_alidirektiloj' ),
        'EditWatchlist'             => array( 'Redakti_atentaron' ),
        'Emailuser'                 => array( 'Retpoŝti_uzanton' ),
+       'ExpandTemplates'           => array( 'Malfaldi_ŝablonon' ),
        'Export'                    => array( 'Elporti', 'Eksporti' ),
        'Fewestrevisions'           => array( 'Plej_malmultaj_revizioj' ),
        'FileDuplicateSearch'       => array( 'Serĉi_pri_duoblaj_dosieroj' ),
@@ -570,7 +570,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Pri {{SITENAME}}',
 'aboutpage' => 'Project:Enkonduko',
-'copyright' => 'La enhavo estas disponebla laŭ $1.',
+'copyright' => 'La enhavo estas disponebla laŭ $1, se ne estas alia indiko.',
 'copyrightpage' => '{{ns:project}}:Aŭtorrajto',
 'currentevents' => 'Aktualaĵoj',
 'currentevents-url' => 'Project:Aktualaĵoj',
@@ -580,7 +580,7 @@ $1',
 'helppage' => 'Help:Enhavo',
 'mainpage' => 'Ĉefpaĝo',
 'mainpage-description' => 'Ĉefpaĝo',
-'policy-url' => 'Project:Konsiletoj',
+'policy-url' => 'Project:Regularo',
 'portal' => 'Komunuma portalo',
 'portal-url' => 'Project:Komunuma portalo',
 'privacy' => 'Regularo pri respekto de la privateco',
@@ -596,8 +596,6 @@ $1',
 'ok' => 'Ek!',
 'retrievedfrom' => 'Elŝutita el  "$1"',
 'youhavenewmessages' => 'Por vi estas $1 ($2).',
-'newmessageslink' => 'novaj mesaĝoj',
-'newmessagesdifflink' => 'ŝanĝoj kompare kun antaŭlasta versio',
 'youhavenewmessagesfromusers' => 'Riceviĝis $1 de {{PLURAL:$3|alia uzanto|$3 uzantoj}} ($2).',
 'youhavenewmessagesmanyusers' => 'Riceviĝis $1 de multaj uzantoj ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|nova mesaĝo|novaj mesaĝoj}}',
@@ -653,6 +651,7 @@ Listo de validaj specialaj paĝoj estas trovebla ĉe [[Special:SpecialPages|{{in
 # General errors
 'error' => 'Eraro',
 'databaseerror' => 'Datumbaza eraro',
+'databaseerror-error' => 'Eraro: $1',
 'laggedslavemode' => 'Avertu: la paĝo eble ne enhavas lastatempajn ĝisdatigojn.',
 'readonly' => 'Datumaro ŝlosita, nurlega',
 'enterlockreason' => 'Bonvolu klarigi, kial oni ŝlosas la datumaron, kaj
@@ -778,7 +777,7 @@ Ne forgesu ŝanĝi viajn [[Special:Preferences|{{SITENAME}}-preferojn]]',
 'createacct-emailrequired' => 'Retpoŝta adreso',
 'createacct-emailoptional' => 'Retpoŝta adreso (nedeviga)',
 'createacct-email-ph' => 'Enigu vian retpoŝtan adreson',
-'createaccountmail' => 'Uzi provizoran hazardsignan pasvorton kaj sendi ĝin al la retpoŝto suben',
+'createaccountmail' => 'Uzi provizoran hazardsignan pasvorton kaj sendi ĝin al la retpoŝta adreso ĉi-suba',
 'createacct-realname' => 'Vera nomo (nedeviga)',
 'createaccountreason' => 'Kialo:',
 'createacct-reason' => 'Kialo',
@@ -795,6 +794,7 @@ Ne forgesu ŝanĝi viajn [[Special:Preferences|{{SITENAME}}-preferojn]]',
 'userexists' => 'Salutnomo enigita jam estas uzata.
 Bonvolu elekti alian nomon.',
 'loginerror' => 'Ensaluta eraro',
+'createacct-error' => 'Eraro pri kreado de konto',
 'createaccounterror' => 'Ne eblis krei konton: $1',
 'nocookiesnew' => 'La uzantokonto estis kreita sed vi ne estas ensalutinta. *** E-igo lcfirst {{SITENAME}} uzas kuketojn por akcepti uzantojn. Kuketoj esta malaktivigitaj ĉe vi. Bonvolu aktivigi ilin kaj ensalutu per viaj novaj salutnomo kaj pasvorto.',
 'nocookieslogin' => '{{SITENAME}} uzas kuketojn por akcepti uzantojn. Kuketoj esta malaktivigitaj ĉe vi. Bonvolu aktivigi ilin kaj provu denove.',
@@ -830,7 +830,7 @@ registrita por "$1".
 Bonvolu saluti denove ricevinte ĝin.',
 'blocked-mailpassword' => 'Via IP adreso estas forbarita de redaktado, kaj tial
 ne rajtas uzi la pasvorto-rekovran funkcion por malebligi misuzon.',
-'eauthentsent' => 'Konfirma retmesaĝo estas sendita al la nomita retadreso. Antaŭ ol iu ajn alia mesaĝo estos sendita al la konto, vi devos sekvi la instrukciojn en la mesaĝo por konfirmi ke la konto ja estas la via.',
+'eauthentsent' => 'Konfirma retmesaĝo estis sendita al la nomita retadreso. Antaŭ ol iu ajn alia mesaĝo estos sendita al la konto, vi devos sekvi la instrukciojn en la mesaĝo por konfirmi ke la konto ja estas via.',
 'throttled-mailpassword' => 'Retpoŝto kun reŝargita pasvorto estis jam sendita ene de la {{PLURAL:$1|lasta horo|lastaj $1 horoj}}.
 Por preventi misuzon, nur unu reŝargita pasvorto estos sendita dum {{PLURAL:$1|horo|$1 horoj}}.',
 'mailerror' => 'Okazis eraro sendante retpoŝtaĵon: $1',
@@ -852,11 +852,13 @@ Enigi bone formatita adreso aŭ malplenigi tiun kampon.',
 
 Vi povas ignori ĉi mesaĝon, se ĉi konto estis kreita erare.',
 'usernamehasherror' => 'Salutnomo ne povas enhavi kriphaketaĵajn signojn',
-'login-throttled' => 'Vi tro ofte provis ensaluti.
-Bonvolu ĝisatendi antaŭ retrovi.',
+'login-throttled' => 'Vi ĵus tro ofte provis ensaluti.
+Bonvolu ĝisatendi $1 antaŭ reprovi.',
 'login-abort-generic' => 'Via ensaluto malsukcesis - Ĉesigita',
 'loginlanguagelabel' => 'Lingvo: $1',
 'suspicious-userlogout' => 'Via peto por elsaluti estis malpermesita ĉar verŝajne ĝi estis sendita de trompita retumilo aŭ kaŝiganta proksima servilo.',
+'createacct-another-realname-tip' => 'La vera nomo estas nenecesa.
+Se vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontribuoj.',
 
 # Email sending
 'php-mail-error-unknown' => 'Nekonata eraro en la funkcio mail() de PHP',
@@ -872,7 +874,7 @@ Bonvolu ĝisatendi antaŭ retrovi.',
 'newpassword' => 'Nova pasvorto',
 'retypenew' => 'Retajpi novan pasvorton',
 'resetpass_submit' => 'Fari pasvorton kaj ensaluti',
-'changepassword-success' => 'Via pasvorto estis sukcese ŝanĝita! Nun ensalutanta vin...',
+'changepassword-success' => 'Via pasvorto estis sukcese ŝanĝita!',
 'resetpass_forbidden' => 'Pasvortoj ne estas ŝanĝeblaj',
 'resetpass-no-info' => 'Vi devas ensaluti por atingi ĉi tiun paĝon rekte.',
 'resetpass-submit-loggedin' => 'Ŝanĝi pasvorton',
@@ -884,6 +886,7 @@ Vi eble jam ŝanĝis vian pasvorton aŭ petis novan provizoran pasvorton.',
 
 # Special:PasswordReset
 'passwordreset' => 'Restarigo de pasvorto',
+'passwordreset-text-one' => 'Plenigu ĉi tiun formularon por renovigi vian pasvorton.',
 'passwordreset-legend' => 'Refari pasvorton',
 'passwordreset-disabled' => 'Pasvortaj restarigoj estis malŝaltitaj en ĉi tiu vikio.',
 'passwordreset-emaildisabled' => 'Retpoŝtaj funkcioj estas malfunkciigitaj en tiu ĉi vikio.',
@@ -915,7 +918,7 @@ aŭ se vi memoris vian originalan pasvorton, kaj vi ne plu volas ŝanĝi
 Provizora pasvorto: $2',
 'passwordreset-emailsent' => 'Renovigita pasvorto estis retpoŝte sendita.',
 'passwordreset-emailsent-capture' => 'Retpoŝto kun renovigita pasvorto estis sendita, kiu estas montrata sube.',
-'passwordreset-emailerror-capture' => 'Retpoŝto kun renovigita pasvorto estis generita, montrata sube, sed sendado al uzanto malsukcesis: $1',
+'passwordreset-emailerror-capture' => 'Retpoŝto kun renovigita pasvorto estis generita, montrata sube, sed sendado al la {{GENDER:$2|uzanto}} malsukcesis: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'Ŝanĝi retpoŝtadreson',
@@ -929,6 +932,14 @@ Provizora pasvorto: $2',
 'changeemail-submit' => 'Ŝanĝi retpoŝtadreson',
 'changeemail-cancel' => 'Nuligi',
 
+# Special:ResetTokens
+'resettokens-no-tokens' => 'Ne estas ŝlosiloj renovigeblaj.',
+'resettokens-legend' => 'Renovigi ŝlosilojn',
+'resettokens-tokens' => 'Ŝlosiloj:',
+'resettokens-token-label' => '$1 (nuna valoro: $2)',
+'resettokens-done' => 'Ŝlosiloj renovigitaj.',
+'resettokens-resetbutton' => 'Renovigi elektitajn ŝlosilojn',
+
 # Edit page toolbar
 'bold_sample' => 'Grasa teksto',
 'bold_tip' => 'Grasa teksto',
@@ -1135,7 +1146,7 @@ Verŝajne ĝi estis forigita.',
 'content-failed-to-parse' => 'Oni malsukcesis analizi $2-entenon laŭ la $1-modelo: $3',
 'invalid-content-data' => 'Enhavo estas malvalida',
 'content-not-allowed-here' => 'Enhavo de $1 ne estas permesita en paĝo [[$2]]',
-'editwarning-warning' => 'Forlasante ĉi tiun paĝon kaŭzos al vi perdi iun ajn ŝanĝojn kiujn vi faris.
+'editwarning-warning' => 'Forlaso de ĉi tiu paĝo kaŭzos al vi perdi iun ajn ŝanĝojn kiujn vi faris.
 Se vi ensalutas, vi povas malŝalti ĉi tiun averton en la sekcio "{{int:prefs-editing}}" de viaj preferoj.',
 
 # Content models
@@ -1172,6 +1183,7 @@ Bonvolu konfirmi la jenan komparaĵon por verigi ĉi tiel vi volas, kaj konservi
 'undo-failure' => 'Ne povis nuligi redakton pro konfliktaj intermezaj redaktoj.',
 'undo-norev' => 'La redakto ne eblis esti malfarita ĉar ĝi aŭ ne ekzistas aŭ estis forigita.',
 'undo-summary' => 'Nuligis version $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuto]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])',
+'undo-summary-username-hidden' => 'Malfari ŝanĝon $1 de kaŝita uzulo',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Ne povas krei konton',
@@ -1269,8 +1281,8 @@ Aliaj administrantoj ĉe {{SITENAME}} plu povos aliri la kaŝitan entenon kaj re
 'revdelete-hide-user' => 'Kaŝi nomon aŭ IP-adreson de redaktinto',
 'revdelete-hide-restricted' => 'Subpremi ĉi tiujn datenojn de administrantoj kaj ankaŭ aliaj',
 'revdelete-radio-same' => '(ne ŝanĝi)',
-'revdelete-radio-set' => 'Jes',
-'revdelete-radio-unset' => 'Ne',
+'revdelete-radio-set' => 'Videbla',
+'revdelete-radio-unset' => 'Kaŝita',
 'revdelete-suppress' => 'Subpremi datenojn de kaj administrantoj kaj aliaj',
 'revdelete-unsuppress' => 'Forigi limigojn al restarigitaj versioj',
 'revdelete-log' => 'Kialo:',
@@ -1361,7 +1373,7 @@ Detaloj troveblos en la [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}
 # Search results
 'searchresults' => 'Serĉrezultoj',
 'searchresults-title' => 'Serĉrezultoj por "$1"',
-'searchresulttext' => 'Por pliaj informoj kiel priserĉi la {{SITENAME}}n, vidu [[{{MediaWiki:Helppage}}|serĉi en {{SITENAME}}]].',
+'searchresulttext' => 'Por pliaj informoj pri serĉado en {{SITENAME}} vidu [[{{MediaWiki:Helppage}}|{{int:help}}]]..',
 'searchsubtitle' => 'Vi serĉis "\'\'\'[[$1]]\'\'\'" ([[Special:Prefixindex/$1|ĉiuj paĝoj komence de "$1"]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|ĉiuj paĝoj ligantaj al "$1"]])',
 'searchsubtitleinvalid' => 'Serĉmendo "$1"',
 'toomanymatches' => 'Tro da serĉo-trafoj estis trovitaj; bonvolu provi malsaman serĉomendon.',
@@ -1426,8 +1438,6 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'preferences' => 'Preferoj',
 'mypreferences' => 'Preferoj',
 'prefs-edits' => 'Nombro de redaktoj:',
-'prefsnologin' => 'Ne jam salutis!',
-'prefsnologintext' => 'Vi devas esti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ensalutita]</span> por fari viajn preferojn.',
 'changepassword' => 'Ŝanĝi pasvorton',
 'prefs-skin' => 'Etoso',
 'skin-preview' => 'Antaŭrigardo',
@@ -1535,6 +1545,7 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'prefs-displaywatchlist' => 'Montraj opcioj',
 'prefs-tokenwatchlist' => 'Ĵetono',
 'prefs-diffs' => 'Diferencoj',
+'prefs-help-prefershttps' => 'Ĉi tiu agordo ekefikos je via sekva ensaluto.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Ŝajnas ke la retpoŝtadreso estas valida',
@@ -1561,6 +1572,7 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'userrights-notallowed' => 'Via konto ne rajtas doni aŭ forigi uzanto-rajtojn.',
 'userrights-changeable-col' => 'Grupoj kiujn vi povas ŝanĝi',
 'userrights-unchangeable-col' => 'Grupoj kiujn vi ne povas ŝanĝi',
+'userrights-removed-self' => 'Vi sukcese nuligis viajn proprajn rajtojn. Do vi ne plu rajtas aliri ĉi tiun paĝon.',
 
 # Groups
 'group' => 'Grupo:',
@@ -1634,6 +1646,8 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'right-editmyusercss' => 'Redakti viajn proprajn CSS-dosierojn',
 'right-editmyuserjs' => 'Redakti viajn proprajn JavaScript-dosierojn',
 'right-viewmywatchlist' => 'Rigardi vian atentaron',
+'right-viewmyprivateinfo' => 'Vidi viajn proprajn privatajn informojn (ekz. retpoŝtan adreson, veran nomon)',
+'right-editmyprivateinfo' => 'Redakti viajn proprajn privatajn informojn (ekz. retpoŝtan adreson, veran nomon)',
 'right-rollback' => 'Tuj malfari la redaktojn de la lasta uzanto kiu redaktis specifan paĝon',
 'right-markbotedits' => 'Marki restarigitajn redaktojn kiel robotajn redaktojn',
 'right-noratelimit' => 'Ne influita de po-limoj',
@@ -1685,7 +1699,7 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'action-block' => 'forari ĉi tiun uzanton de redaktado',
 'action-protect' => 'ŝanĝi la protektan nivelon por ĉi tiu paĝo',
 'action-rollback' => 'tuj malfari la redaktojn de la lasta uzanto kiu redaktis specifan paĝon',
-'action-import' => 'importi ĉi tiun paĝon de alia vikio',
+'action-import' => 'enporti paĝojn de alia vikio',
 'action-importupload' => 'importi ĉi tiun paĝon de dosiera alŝuto',
 'action-patrol' => 'marki redakton de alia persono kiel patrolitan',
 'action-autopatrol' => 'fari vian redakton markitan kiel patrolitan',
@@ -1695,17 +1709,24 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'action-userrights-interwiki' => 'redakti la rajtojn de uzantoj en aliaj vikioj',
 'action-siteadmin' => 'ŝlosi aŭ malŝlosi la datumbazon',
 'action-sendemail' => 'sendi retpoŝtojn',
+'action-editmywatchlist' => 'modifi vian atento-liston',
+'action-viewmywatchlist' => 'vidi vian atento-liston',
+'action-viewmyprivateinfo' => 'vidi viajn privatajn informojn',
+'action-editmyprivateinfo' => 'redakti viajn privatajn informojn',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|ŝanĝo|ŝanĝoj}}',
+'enhancedrc-history' => 'historio',
 'recentchanges' => 'Lastaj ŝanĝoj',
 'recentchanges-legend' => 'Opcioj pri lastaj ŝanĝoj',
 'recentchanges-summary' => 'Per ĉi tiu paĝo vi povas sekvi la plej lastajn ŝanĝojn en la {{SITENAME}}.',
+'recentchanges-noresult' => 'En la donita tempo ne estis ŝanĝoj, kiuj konformas al la kriterioj.',
 'recentchanges-feed-description' => 'Sekvi la plej lastatempajn ŝanĝojn al la vikio en ĉi tiu fonto.',
 'recentchanges-label-newpage' => 'Ĉi tiu redakto kreis novan paĝon',
 'recentchanges-label-minor' => 'Ĉi tiu estas eta redakto',
 'recentchanges-label-bot' => 'Ĉi tiu redakto estis farita per roboto.',
 'recentchanges-label-unpatrolled' => 'Ĉi tiu redakto ne jam estis patrolata.',
+'recentchanges-legend-newpage' => '$1 - nova paĝo',
 'rcnote' => "Jen la {{PLURAL:$1|lasta '''1''' ŝanĝo|lastaj '''$1''' ŝanĝoj}} dum la {{PLURAL:$2|lasta tago|lastaj '''$2''' tagoj}}, ekde $5, $4.",
 'rcnotefrom' => "Jen la ŝanĝoj ekde '''$2''' (lastaj ĝis '''$1''').",
 'rclistfrom' => 'Montri novajn ŝanĝojn ekde "$1"',
@@ -2923,14 +2944,14 @@ En la lasta okazo, vi ankaŭ povas uzi ligilon, ekz-e [[{{#Special:Export}}/{{Me
 'allmessagesdefault' => 'Defaŭlta teksto',
 'allmessagescurrent' => 'Nuna teksto',
 'allmessagestext' => 'Ĉi tio estas listo de ĉiuj mesaĝoj haveblaj en la MediaWiki-nomspaco.
-Bonvolu aliri [//www.mediawiki.org/wiki/Localisation MediaWiki-Asimilado] kaj [//translatewiki.net translatewiki.net]
+Bonvolu aliri [https://www.mediawiki.org/wiki/Localisation MediaWiki-Asimilado] kaj [//translatewiki.net translatewiki.net]
 se vi volus kontribui al la komuna MediaWiki-asimilado.',
 'allmessagesnotsupportedDB' => '{{ns:special}}:Allmessages ne subtenata ĉar la variablo wgUseDatabaseMessages estas malkonektita.',
 'allmessages-filter-legend' => 'Filtri',
 'allmessages-filter' => 'Filtri laŭ ŝanĝada stato',
-'allmessages-filter-unmodified' => 'Neŝanĝitaĵoj',
+'allmessages-filter-unmodified' => 'Neŝanĝitaj',
 'allmessages-filter-all' => 'Ĉio',
-'allmessages-filter-modified' => 'Ŝanĝitaĵoj',
+'allmessages-filter-modified' => 'Ŝanĝitaj',
 'allmessages-prefix' => 'Filtri laŭ prefikso:',
 'allmessages-language' => 'Lingvo:',
 'allmessages-filter-submit' => 'Ek!',
@@ -3132,6 +3153,8 @@ Datoj de versioj kaj nomoj de redaktantoj estos preservitaj.
 'spam_reverting' => 'Restarigo de lasta versio ne entenante ligilojn al $1',
 'spam_blanking' => 'Forviŝo de ĉiuj versioj entenantaj ligilojn al $1',
 'spam_deleting' => 'Ĉiuj versioj enhavis ligilojn al $1 - forigante',
+'simpleantispam-label' => 'Kontrolo kontraŭ spamo.
+NE ENIGU ion ajn!',
 
 # Info page
 'pageinfo-title' => 'Informoj por "$1"',
@@ -3689,7 +3712,7 @@ Aliaj estos kaŝitaj defaŭlte.
 
 # External editor support
 'edit-externally' => 'Ŝanĝi ĉi tiun dosieron per ekstera programaro',
-'edit-externally-help' => "(Vidu la [//www.mediawiki.org/wiki/Manual:External_editors instalinstrukciojn] por pliaj informoj.) ''[angle]''.",
+'edit-externally-help' => "(Vidu la [https://www.mediawiki.org/wiki/Manual:External_editors instalinstrukciojn] por pliaj informoj.) ''[angle]''.",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ĉiuj',
@@ -3928,7 +3951,7 @@ Vi povas ankaŭ [[Special:EditWatchlist|redakti norme]].',
 'version-hook-subscribedby' => 'Abonita de',
 'version-version' => '(Versio $1)',
 'version-license' => 'Permesilo',
-'version-poweredby-credits' => "Ĉi tiu vikio funkcias per '''[//www.mediawiki.org/ MediaWiki]''', aŭtorrajto ©&thinsp;2001–$1 $2.",
+'version-poweredby-credits' => "Ĉi tiu vikio funkcias per '''[https://www.mediawiki.org/ MediaWiki]''', aŭtorrajto ©&thinsp;2001–$1 $2.",
 'version-poweredby-others' => 'aliaj',
 'version-credits-summary' => 'Ni ŝatus agnoski la sekvajn personojn pro siaj kontribuoj al [[Special:Version|MediaWiki]].',
 'version-license-info' => 'MediaWiki estas libera programaro. Vi povas redistribui ĝin kaj/aŭ modifi ĝin sub la kondiĉoj de la GNU General Public Licens (GNU Ĝenerala Publika Permesilo) en ties eldono de la Free Software Foundation (Libera Softvara Fondaĵo) - aŭ versio 2 de la Permesilo, aŭ (laŭ via elekto) iu ajn posta versio.
@@ -3956,8 +3979,7 @@ Oni devis doni al vi [{{SERVER}}{{SCRIPTPATH}}/COPYING ekzempleron de la GNU Gen
 
 # Special:SpecialPages
 'specialpages' => 'Specialaj paĝoj',
-'specialpages-note' => '----
-* Normaj specialaj paĝoj.
+'specialpages-note' => '* Normaj specialaj paĝoj.
 * <strong class="mw-specialpagerestricted">Limigitaj specialaj paĝoj.</strong>
 * <span class="mw-specialpagecached">Memorkaŝitaj specialaj paĝoj (eble malaktualaj).</span>',
 'specialpages-group-maintenance' => 'Raportoj pri prizorgado',
@@ -4148,4 +4170,20 @@ Aŭ vi povas uzi la facilan formularon sube. Via komento estos aldonita al la pa
 'duration-centuries' => '$1 {{PLURAL:$1|jarcento|jarcentoj}}',
 'duration-millennia' => '$1 {{PLURAL:$1|jarmilo|jarmiloj}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Ampleksigi ŝablonojn',
+'expand_templates_intro' => 'Ĉi tiu speciala paĝo traktas tekston kaj ampleksigas ĉiujn ŝablonojn en ĝi rekursie.
+Ĝi ankaŭ ampleksigas sintaksajn funkciojn kiel
+<code><nowiki>{{</nowiki>#language:…}}</code> kaj variablojn kiel
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. Fakte preskaŭ iujn ajn en duoblaj krampoj.',
+'expand_templates_title' => 'Kunteksta titolo, por {{FULLPAGENAME}}, ktp.:',
+'expand_templates_input' => 'Enigita teksto:',
+'expand_templates_output' => 'Rezulto',
+'expand_templates_xml_output' => 'XML-eligo',
+'expand_templates_ok' => 'Ek!',
+'expand_templates_remove_comments' => 'Forigi komentojn',
+'expand_templates_remove_nowiki' => 'Nuligi <nowiki> etikedojn en rezulto',
+'expand_templates_generate_xml' => 'Montri XML-sintaksarbon',
+'expand_templates_preview' => 'Antaŭrigardo',
+
 );
index 05f6804..fa6ef2d 100644 (file)
@@ -49,6 +49,7 @@
  * @author Hazard-SJ
  * @author Hercule
  * @author Icvav
+ * @author Ihojose
  * @author Imre
  * @author Invadinado
  * @author Jatrobat
@@ -138,12 +139,12 @@ $namespaceGenderAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'UsuariosActivos' ),
        'Allmessages'               => array( 'TodosLosMensajes' ),
+       'AllMyUploads'              => array( 'TodasMisSubidas', 'TodosMisArchivos' ),
        'Allpages'                  => array( 'Todas', 'Todas_las_páginas' ),
        'Ancientpages'              => array( 'PáginasAntiguas', 'Páginas_antiguas' ),
        'Badtitle'                  => array( 'Título_incorrecto' ),
-       'Blankpage'                 => array( 'BlanquearPágina', 'Blanquear_página' ),
+       'Blankpage'                 => array( 'PáginaEnBlanco', 'BlanquearPágina', 'Blanquear_página', 'Página_en_blanco' ),
        'Block'                     => array( 'Bloquear' ),
-       'Blockme'                   => array( 'Bloquearme' ),
        'Booksources'               => array( 'FuentesDeLibros', 'Fuentes_de_libros' ),
        'BrokenRedirects'           => array( 'RedireccionesRotas', 'Redirecciones_rotas' ),
        'Categories'                => array( 'Categorías' ),
@@ -155,10 +156,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crear_una_cuenta', 'CrearCuenta' ),
        'Deadendpages'              => array( 'PáginasSinSalida', 'Páginas_sin_salida' ),
        'DeletedContributions'      => array( 'ContribucionesBorradas', 'Contribuciones_Borradas' ),
-       'Disambiguations'           => array( 'Desambiguaciones', 'Desambiguación' ),
        'DoubleRedirects'           => array( 'RedireccionesDobles', 'Redirecciones_dobles' ),
        'EditWatchlist'             => array( 'EditarSeguimiento' ),
        'Emailuser'                 => array( 'Enviar_correo_electrónico', 'MandarEmailUsuario' ),
+       'ExpandTemplates'           => array( 'Sustituir_plantillas', 'Sustituidor_de_plantillas', 'Expandir_plantillas' ),
        'Export'                    => array( 'Exportar' ),
        'Fewestrevisions'           => array( 'MenosEdiciones', 'Menos_ediciones' ),
        'FileDuplicateSearch'       => array( 'BuscarArchivosDuplicados', 'Buscar_archivos_duplicados' ),
@@ -200,9 +201,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'PáginasProtegidas', 'Páginas_protegidas' ),
        'Protectedtitles'           => array( 'TítulosProtegidos', 'Títulos_protegidos' ),
        'Randompage'                => array( 'Aleatoria', 'Aleatorio', 'Página_aleatoria' ),
+       'RandomInCategory'          => array( 'Aleatorio_en_categoría' ),
        'Randomredirect'            => array( 'RedirecciónAleatoria', 'Redirección_aleatoria' ),
        'Recentchanges'             => array( 'CambiosRecientes', 'Cambios_recientes' ),
        'Recentchangeslinked'       => array( 'CambiosEnEnlazadas', 'Cambios_en_enlazadas' ),
+       'Redirect'                  => array( 'Redirigir' ),
+       'ResetTokens'               => array( 'ReestablecerClaves' ),
        'Revisiondelete'            => array( 'BorrarRevisión', 'Borrar_revisión' ),
        'Search'                    => array( 'Buscar' ),
        'Shortpages'                => array( 'PáginasCortas', 'Páginas_cortas' ),
@@ -221,6 +225,7 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'PlantillasSinUso', 'Plantillas_sin_uso' ),
        'Unwatchedpages'            => array( 'PáginasSinVigilar', 'Páginas_sin_vigilar' ),
        'Upload'                    => array( 'SubirArchivo', 'Subir_archivo' ),
+       'UploadStash'               => array( 'ArchivosEscondidos', 'FicherosEscondidos' ),
        'Userlogin'                 => array( 'Entrar', 'Entrada_del_usuario' ),
        'Userlogout'                => array( 'Salida_del_usuario', 'Salir' ),
        'Userrights'                => array( 'PermisosUsuarios', 'Permisos_de_usuarios' ),
@@ -283,6 +288,8 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'NOMBRECOMPLETODEPAGINAC', 'NOMBRECOMPLETODEPÁGINAC', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'NOMBREDESUBPAGINA', 'NOMBREDESUBPÁGINA', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'NOMBREDESUBPAGINAC', 'NOMBREDESUBPÁGINAC', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'NOMBREDEPAGINARAIZ', 'NOMBREDEPÁGINARAÍZ', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'NOMBREDEPAGINARAIZC', 'NOMBREDEPÁGINARAÍZC', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'NOMBREDEPAGINABASE', 'NOMBREDEPÁGINABASE', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'NOMBREDEPAGINABASEC', 'NOMBREDEPÁGINABASEC', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'NOMBREDEPÁGINADEDISCUSIÓN', 'NOMBREDEPAGINADEDISCUSION', 'NOMBREDEPAGINADISCUSION', 'NOMBREDEPÁGINADISCUSIÓN', 'TALKPAGENAME' ),
@@ -383,10 +390,10 @@ $messages = array(
 'tog-extendwatchlist' => 'Expandir la lista de seguimiento a todos los cambios, no sólo a los más recientes',
 'tog-usenewrc' => 'Agrupar los cambios por página en los cambios recientes y en la lista de seguimiento (requiere JavaScript)',
 'tog-numberheadings' => 'Numerar automáticamente los encabezados',
-'tog-showtoolbar' => 'Mostrar la barra de edición (requiere JavaScript)',
-'tog-editondblclick' => 'Editar las páginas con doble clic (requiere JavaScript)',
-'tog-editsection' => 'Habilitar la edición de secciones mediante el enlace [editar]',
-'tog-editsectiononrightclick' => 'Habilitar la edición de secciones pulsando el botón derecho en los títulos de secciones (requiere JavaScript)',
+'tog-showtoolbar' => 'Mostrar la barra de edición',
+'tog-editondblclick' => 'Editar las páginas al pulsar dos veces en ellos con el ratón',
+'tog-editsection' => 'Activar la edición de secciones mediante el enlace [editar]',
+'tog-editsectiononrightclick' => 'Activar la edición de secciones pulsando el botón derecho en los títulos de secciones',
 'tog-showtoc' => 'Mostrar el índice (para páginas con más de 3 encabezados)',
 'tog-rememberpassword' => 'Recordar mi nombre de usuario y contraseña entre sesiones en este navegador (por un máximo de $1 {{PLURAL:$1|día|días}})',
 'tog-watchcreations' => 'Añadir las páginas que cree y los archivos que suba a mi lista de seguimento',
@@ -404,7 +411,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Mostrar el número de usuarios que la vigilan',
 'tog-oldsig' => 'Firma actual:',
 'tog-fancysig' => 'Tratar la firma como wikitexto (sin un enlace automático)',
-'tog-uselivepreview' => 'Usar previsualización en vivo (requiere JavaScript) (experimental)',
+'tog-uselivepreview' => 'Usar previsualización dinámica (experimental)',
 'tog-forceeditsummary' => 'Avisarme cuando grabe la página sin introducir un resumen de edición',
 'tog-watchlisthideown' => 'Ocultar mis ediciones en la lista de seguimiento',
 'tog-watchlisthidebots' => 'Ocultar las ediciones de bots en la lista de seguimiento',
@@ -427,7 +434,7 @@ $messages = array(
 # Font style option in Special:Preferences
 'editfont-style' => 'Estilo de tipografía del área de edición:',
 'editfont-default' => 'Predeterminado del navegador',
-'editfont-monospace' => 'Tipografía monoespaciada',
+'editfont-monospace' => 'Tipo de letra monoespaciado',
 'editfont-sansserif' => 'Tipo de letra de palo seco',
 'editfont-serif' => 'Tipo de letra con serifas',
 
@@ -442,7 +449,7 @@ $messages = array(
 'sun' => 'dom',
 'mon' => 'lun',
 'tue' => 'mar',
-'wed' => 'mie',
+'wed' => 'mié',
 'thu' => 'jue',
 'fri' => 'vie',
 'sat' => 'sab',
@@ -474,7 +481,7 @@ $messages = array(
 'feb' => 'feb',
 'mar' => 'mar',
 'apr' => 'abr',
-'may' => 'mayo',
+'may' => 'may',
 'jun' => 'jun',
 'jul' => 'jul',
 'aug' => 'ago',
@@ -497,10 +504,10 @@ $messages = array(
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Categoría|Categorías}}',
-'category_header' => 'Artículos en la categoría «$1»',
+'category_header' => 'Páginas en la categoría «$1»',
 'subcategories' => 'Subcategorías',
 'category-media-header' => 'Archivos multimedia en la categoría «$1»',
-'category-empty' => "''La categoría no contiene actualmente ningún artículo o archivo multimedia.''",
+'category-empty' => "''La categoría no contiene ninguna página o archivo.''",
 'hidden-categories' => '{{PLURAL:$1|Categoría escondida|Categorías escondidas}}',
 'hidden-category-category' => 'Categorías ocultas',
 'category-subcat-count' => '{{PLURAL:$2|Esta categoría solo contiene la siguiente subcategoría.|Esta categoría contiene {{PLURAL:$1|la siguiente subcategoría|las siguientes $1 subcategorías}}, de un total de $2.}}',
@@ -510,8 +517,8 @@ $messages = array(
 'category-file-count' => '{{PLURAL:$2|Esta categoría contiene solamente el siguiente archivo.|{{PLURAL:$1|El siguiente archivo pertenece|Los siguientes $1 archivos pertenecen}} a esta categoría, de un total de $2.}}',
 'category-file-count-limited' => '{{PLURAL:$1|El siguiente fichero pertenece|Los siguientes $1 ficheros pertenecen}} a esta categoría.',
 'listingcontinuesabbrev' => 'cont.',
-'index-category' => 'Páginas indexadas',
-'noindex-category' => 'Páginas no indexadas',
+'index-category' => 'Páginas indizadas',
+'noindex-category' => 'Páginas no indizadas',
 'broken-file-category' => 'Páginas con enlaces rotos a archivos',
 
 'about' => 'Acerca de',
@@ -520,7 +527,7 @@ $messages = array(
 'cancel' => 'Cancelar',
 'moredotdotdot' => 'Más...',
 'morenotlisted' => 'Esta lista no está completa.',
-'mypage' => 'Mi página',
+'mypage' => 'Página',
 'mytalk' => 'Discusión',
 'anontalk' => 'Discusión para esta IP',
 'navigation' => 'Navegación',
@@ -534,7 +541,7 @@ $messages = array(
 'qbmyoptions' => 'Mis páginas',
 'qbspecialpages' => 'Páginas especiales',
 'faq' => 'Preguntas más frecuentes',
-'faqpage' => 'Project:FAQ',
+'faqpage' => 'Project:P+F',
 
 # Vector skin
 'vector-action-addsection' => 'Nueva sección',
@@ -548,7 +555,7 @@ $messages = array(
 'vector-view-edit' => 'Editar',
 'vector-view-history' => 'Ver historial',
 'vector-view-view' => 'Leer',
-'vector-view-viewsource' => 'Ver fuente',
+'vector-view-viewsource' => 'Ver código',
 'actions' => 'Acciones',
 'namespaces' => 'Espacios de nombres',
 'variants' => 'Variantes',
@@ -588,7 +595,7 @@ $messages = array(
 'talkpagelinktext' => 'Discusión',
 'specialpage' => 'Página especial',
 'personaltools' => 'Herramientas personales',
-'postcomment' => 'Nueva sección',
+'postcomment' => 'Sección nueva',
 'articlepage' => 'Ver artículo',
 'talk' => 'Discusión',
 'views' => 'Vistas',
@@ -629,7 +636,7 @@ $1',
 'disclaimers' => 'Aviso legal',
 'disclaimerpage' => 'Project:Limitación general de responsabilidad',
 'edithelp' => 'Ayuda de edición',
-'helppage' => 'Help:Contenidos',
+'helppage' => 'Help:Contenido',
 'mainpage' => 'Página principal',
 'mainpage-description' => 'Página principal',
 'policy-url' => 'Project:Políticas',
@@ -648,32 +655,30 @@ $1',
 'ok' => 'Aceptar',
 'retrievedfrom' => 'Obtenido de «$1»',
 'youhavenewmessages' => 'Tienes $1 ($2).',
-'newmessageslink' => 'mensajes nuevos',
-'newmessagesdifflink' => 'última modificación',
 'youhavenewmessagesfromusers' => 'Tienes $1 de {{PLURAL:$3|otro usuario|$3 usuarios}} ($2).',
 'youhavenewmessagesmanyusers' => 'Tienes $1 de muchos usuarios ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un nuevo mensaje|mensajes nuevos}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|última modificación|últimos cambios}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un mensaje nuevo|999=mensajes nuevos}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|último cambio|999=últimos cambios}}',
 'youhavenewmessagesmulti' => 'Tienes mensajes nuevos en $1',
 'editsection' => 'editar',
 'editold' => 'editar',
-'viewsourceold' => 'ver código fuente',
+'viewsourceold' => 'ver código',
 'editlink' => 'modificar',
-'viewsourcelink' => 'ver fuente',
+'viewsourcelink' => 'ver código',
 'editsectionhint' => 'Editar sección: $1',
 'toc' => 'Contenido',
 'showtoc' => 'mostrar',
 'hidetoc' => 'ocultar',
-'collapsible-collapse' => 'Ocultar',
-'collapsible-expand' => 'Mostrar',
+'collapsible-collapse' => 'Contraer',
+'collapsible-expand' => 'Expandir',
 'thisisdeleted' => '¿Ver o restaurar $1?',
-'viewdeleted' => '¿Deseas ver $1?',
+'viewdeleted' => '¿Quieres ver $1?',
 'restorelink' => '{{PLURAL:$1|una edición borrada|$1 ediciones borradas}}',
-'feedlinks' => 'Sindicación:',
-'feed-invalid' => 'Tipo de subscripción a sindicación de noticias inválida.',
-'feed-unavailable' => 'Las fuentes web no están disponibles',
-'site-rss-feed' => '$1 Fuente RSS',
-'site-atom-feed' => 'Feed Atom de $1',
+'feedlinks' => 'Canal:',
+'feed-invalid' => 'El tipo de canal de suscripción no es válido.',
+'feed-unavailable' => 'Los canales de sindicación no están disponibles',
+'site-rss-feed' => 'Canal RSS de $1',
+'site-atom-feed' => 'Canal Atom de $1',
 'page-rss-feed' => 'Canal RSS «$1»',
 'page-atom-feed' => 'Canal Atom «$1»',
 'red-link-title' => '$1 (la página no existe)',
@@ -683,7 +688,7 @@ $1',
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Página',
 'nstab-user' => 'Página {{GENDER:{{ROOTPAGENAME}}|del usuario|de la usuaria}}',
-'nstab-media' => 'Media',
+'nstab-media' => 'Multimedia',
 'nstab-special' => 'Página especial',
 'nstab-project' => 'Página del proyecto',
 'nstab-image' => 'Archivo',
@@ -693,8 +698,8 @@ $1',
 'nstab-category' => 'Categoría',
 
 # Main script and global functions
-'nosuchaction' => 'No existe tal acción',
-'nosuchactiontext' => 'La acción especificada en la dirección es inválida.
+'nosuchaction' => 'No existe esa acción',
+'nosuchactiontext' => 'La acción especificada en la dirección no es válida.
 Es posible que hayas escrito mal la URL o que hayas seguido un enlace incorrecto. Esto también podría indicar un error en el software utilizado en {{SITENAME}}.',
 'nosuchspecialpage' => 'No existe esa página especial',
 'nospecialpagetext' => '<strong>Ha solicitado una página especial inexistente.</strong>
@@ -753,9 +758,9 @@ Puede que contenga uno o más caracteres que no se pueden usar en los títulos.'
 'wrong_wfQuery_params' => 'Parámetros incorrectos para wfQuery()<br />
 Función: $1<br />
 Consulta: $2',
-'viewsource' => 'Ver fuente',
-'viewsource-title' => 'Ver el código fuente de «$1»',
-'actionthrottled' => 'Acción bloqueada',
+'viewsource' => 'Ver código',
+'viewsource-title' => 'Ver el código de «$1»',
+'actionthrottled' => 'Acción limitada',
 'actionthrottledtext' => "Como medida contra el ''spam'', la acción que estás realizando está limitada a un número determinado de veces en un periodo corto de tiempo, y has excedido ese límite. Por favor inténtalo de nuevo en unos minutos.",
 'protectedpagetext' => 'Esta página ha sido protegida para evitar su edición u otras acciones.',
 'viewsourcetext' => 'Puedes ver y copiar el código fuente de esta página:',
@@ -782,7 +787,8 @@ El administrador que lo ha bloqueado ofrece esta explicación: "$3".',
 'invalidtitle-knownnamespace' => 'Título no válido con el espacio de nombres "$2" y el texto "$3"',
 'invalidtitle-unknownnamespace' => 'Título no válido con número de espacio de nombres desconocido  $1  y el texto "$2"',
 'exception-nologin' => 'No has iniciado sesión',
-'exception-nologin-text' => 'Esta página o acción requiere que inicies sesión en este wiki.',
+'exception-nologin-text' => '[[Special:Userlogin|Inicia sesión]] para acceder a esta página o acción.',
+'exception-nologin-text-manual' => 'Necesitas $1 para acceder a esta página o acción.',
 
 # Virus scanner
 'virus-badscanner' => "Error de configuración: Antivirus desconocido: ''$1''",
@@ -826,9 +832,9 @@ No olvides personalizar tus [[Special:Preferences|preferencias de {{SITENAME}}]]
 'nologinlink' => 'Crear una cuenta',
 'createaccount' => 'Crear una cuenta',
 'gotaccount' => '¿Ya tienes una cuenta? $1.',
-'gotaccountlink' => 'Entrar',
+'gotaccountlink' => 'Iniciar sesión',
 'userlogin-resetlink' => '¿Olvidaste tus datos de acceso?',
-'userlogin-resetpassword-link' => 'Restablecer la contraseña',
+'userlogin-resetpassword-link' => '¿Has olvidado tu contraseña?',
 'helplogin-url' => 'Help:Inicio de sesión',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ayuda]]',
 'userlogin-loggedin' => 'Ya estás conectado como {{GENDER:$1|$1}}.
@@ -849,13 +855,13 @@ Usa el formulario de abajo para iniciar sesión como otro usuario.',
 'createacct-imgcaptcha-ph' => 'Escribe el texto de arriba',
 'createacct-submit' => 'Crea tu cuenta',
 'createacct-another-submit' => 'Crear otra cuenta',
-'createacct-benefit-heading' => '{{SITENAME}} lo construye gente como tú.',
+'createacct-benefit-heading' => '{{SITENAME}} es hecha por gente como tú.',
 'createacct-benefit-body1' => '{{PLURAL:$1|edición|ediciones}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|página|páginas}}',
 'createacct-benefit-body3' => '{{PLURAL:$1|colaborador reciente|colaboradores recientes}}',
 'badretype' => 'Las contraseñas no coinciden.',
 'userexists' => 'El nombre de usuario indicado ya está en uso.
-Por favor escoge un nombre diferente.',
+Elige un nombre diferente.',
 'loginerror' => 'Error de inicio de sesión',
 'createacct-error' => 'Error al crear la cuenta',
 'createaccounterror' => 'No se pudo crear la cuenta: $1',
@@ -901,7 +907,7 @@ Para evitar los abusos, solo se enviará un recordatorio de contraseña cada {{P
 'mailerror' => 'Error al enviar correo: $1',
 'acct_creation_throttle_hit' => 'Los visitantes a este wiki usando tu dirección IP han creado {{PLURAL:$1|una cuenta|$1 cuentas}} en el último día, lo cual es lo máximo permitido en este periodo de tiempo.
 Como resultado, los visitantes usando esta dirección IP no pueden crear más cuentas en este momento.',
-'emailauthenticated' => 'Tu dirección de correo electrónico fue autenticada el $2 a $3.',
+'emailauthenticated' => 'Tu dirección de correo electrónico fue confirmada el $2 a las $3.',
 'emailnotauthenticated' => 'Aún no has confirmado tu dirección de correo electrónico.
 Hasta que lo hagas, las siguientes funciones no estarán disponibles.',
 'noemailprefs' => 'Especifica una dirección electrónica para habilitar estas características.',
@@ -910,7 +916,7 @@ Hasta que lo hagas, las siguientes funciones no estarán disponibles.',
 Por favor, escribe una dirección en el formato adecuado o deja el campo en blanco.',
 'cannotchangeemail' => 'Las direcciones de la correo electrónico de las cuentas de usuario no puedes cambiarse en esta wiki.',
 'emaildisabled' => 'Este sitio no puede enviar mensajes de correo electrónico.',
-'accountcreated' => 'Cuenta creada',
+'accountcreated' => 'Se ha creado la cuenta',
 'accountcreatedtext' => 'La cuenta de usuario de [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) ha sido creada.',
 'createaccount-title' => 'Creación de cuenta para {{SITENAME}}',
 'createaccount-text' => 'Alguien creó en {{SITENAME}} ($4) una cuenta asociada a este correo electrónico con el nombre «$2».
@@ -1037,16 +1043,16 @@ Deberías hacerlo si accidentalmente la has compartido con alguien o si su cuent
 'subject' => 'Asunto/encabezado:',
 'minoredit' => 'Esta es una edición menor',
 'watchthis' => 'Vigilar esta página',
-'savearticle' => 'Grabar la página',
+'savearticle' => 'Guardar la página',
 'preview' => 'Previsualizar',
 'showpreview' => 'Mostrar previsualización',
-'showlivepreview' => 'Previsualización inmediata',
-'showdiff' => 'Mostrar cambios',
+'showlivepreview' => 'Previsualización dinámica',
+'showdiff' => 'Mostrar los cambios',
 'anoneditwarning' => "'''Aviso:''' No has iniciado sesión con una cuenta de usuario.
 Tu dirección IP se almacenará en el historial de ediciones de la página.",
 'anonpreviewwarning' => "''No has iniciado sesión con una cuenta de usuario. Al guardar los cambios se almacenará tu dirección IP en el historial de edición de la página.''",
 'missingsummary' => "'''Atención:''' No has escrito un resumen de edición. Si haces clic nuevamente en «{{int:savearticle}}» tu edición se grabará sin él.",
-'missingcommenttext' => 'Por favor, introduce un texto debajo.',
+'missingcommenttext' => 'Escribe un comentario a continuación.',
 'missingcommentheader' => "'''Recordatorio:''' No has escrito un título para este comentario. Si haces clic nuevamente en \"{{int:savearticle}}\" tu edición se grabará sin él.",
 'summary-preview' => 'Previsualización del resumen:',
 'subject-preview' => 'Previsualización del tema/título:',
@@ -1089,7 +1095,7 @@ Quizá ha sido movida o borrada mientras visitabas la página.',
 'loginreqtitle' => 'Es necesario iniciar sesión',
 'loginreqlink' => 'iniciar sesión',
 'loginreqpagetext' => 'Debes $1 para ver otras páginas.',
-'accmailtitle' => 'La contraseña ha sido enviada.',
+'accmailtitle' => 'Se ha enviado la contraseña',
 'accmailtext' => 'Se ha enviado a $2 una contraseña generada aleatoriamente para [[User talk:$1|$1]].
 
 La contraseña para esta nueva cuenta puede cambiarse en [[Special:ChangePassword|la página destinada para ello]] después de haber iniciado sesión.',
@@ -1146,10 +1152,10 @@ Si el problema persiste, [[Special:UserLogout|cierra la sesión]] y vuelve a ide
 Se rechazó la edición para evitar que el texto de la página se corrompa.
 Esto sucede en ocasiones cuando se usa un servicio de proxy anónimo defectuoso.'''",
 'edit_form_incomplete' => "'''Algunas partes del formulario de edición no llegaron al servidor, comprueba que tus ediciones están intactas e inténtalo de nuevo'''.",
-'editing' => 'Editando $1',
-'creating' => 'Creando la página $1',
-'editingsection' => 'Editando $1 (sección)',
-'editingcomment' => 'Editando $1 (nueva sección)',
+'editing' => 'Editar $1',
+'creating' => 'Crear la página $1',
+'editingsection' => 'Editar $1 (sección)',
+'editingcomment' => 'Editar $1 (sección nueva)',
 'editconflict' => 'Conflicto de edición: $1',
 'explainconflict' => "Alguien más ha cambiado esta página desde que empezaste a editarla.
 El área de texto superior contiene el texto de la página como existe actualmente.
@@ -1278,8 +1284,8 @@ Leyenda: '''(act)''' = diferencias con la versión actual,
 '''(ant)''' = diferencias con la versión anterior, '''m''' = edición menor",
 'history-fieldset-title' => 'Buscar en el historial',
 'history-show-deleted' => 'Solo ediciones ocultadas',
-'histfirst' => 'Primeras',
-'histlast' => 'Ã\9altimas',
+'histfirst' => 'primeras',
+'histlast' => 'últimas',
 'historysize' => '({{PLURAL:$1|1 byte|$1 bytes}})',
 'historyempty' => '(vacío)',
 
@@ -1328,10 +1334,10 @@ Aún tiene la posibilidad de verla; puede ampliar los detalles en el [{{fullurl:
 'revdelete-nooldid-text' => 'No se ha especificado una revisión o revisiones destino sobre las que realizar esta función.',
 'revdelete-nologtype-title' => 'ningún nombre dado',
 'revdelete-nologtype-text' => 'No has especificado ningún nombre para ejecutar esta acción.',
-'revdelete-nologid-title' => 'Entrada de registro inválida',
+'revdelete-nologid-title' => 'Entrada de registro no válida',
 'revdelete-nologid-text' => 'Tampoco has especificado un objetivo de eventos para ejecutar esta función o la entrada especificada no existe.',
-'revdelete-no-file' => 'El fichero especificado no existe.',
-'revdelete-show-file-confirm' => '¿Realmente deseas ver la revisión borrada del archivo "<nowiki>$1</nowiki>" del $2 a las $3?',
+'revdelete-no-file' => 'El archivo especificado no existe.',
+'revdelete-show-file-confirm' => '¿Quieres ver la revisión borrada del archivo «<nowiki>$1</nowiki>» del $2 a las $3?',
 'revdelete-show-file-submit' => 'Sí',
 'revdelete-selected' => "'''{{PLURAL:$2|Revisión seleccionada|Revisiones seleccionadas}} de [[:$1]]:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|Seleccionado un evento|Seleccionados eventos}}:'''",
@@ -1343,15 +1349,15 @@ Otros administradores de {{SITENAME}} aún podrán acceder al contenido oculto y
 * Información personal inapropiada, tal como:
 *: ''nombres, domicilios, números de teléfono, números de la seguridad social e información análoga.",
 'revdelete-legend' => 'Establecer restricciones de revisión:',
-'revdelete-hide-text' => 'Ocultar el texto de la revisión',
+'revdelete-hide-text' => 'Texto de la revisión',
 'revdelete-hide-image' => 'Ocultar el contenido del archivo',
 'revdelete-hide-name' => 'Ocultar acción y objetivo',
-'revdelete-hide-comment' => 'Ocultar el resumen de edición',
-'revdelete-hide-user' => 'Ocultar el nombre/IP del editor',
+'revdelete-hide-comment' => 'Resumen de edición',
+'revdelete-hide-user' => 'Nombre/IP del editor',
 'revdelete-hide-restricted' => 'Suprimir datos a los administradores así como al resto',
 'revdelete-radio-same' => '(no cambiar)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'No',
+'revdelete-radio-set' => 'Oculta',
+'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => 'Suprimir datos a los administradores así como al resto',
 'revdelete-unsuppress' => 'Eliminar restricciones de revisiones restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1382,9 +1388,9 @@ No tiene acceso a él.',
 ** Comentario o información personal inapropiados
 ** Nombre de usuario inapropiado
 ** Información potencialmente injuriosa o calumniante',
-'revdelete-otherreason' => 'Otra/adicional razón:',
-'revdelete-reasonotherlist' => 'Otra razón',
-'revdelete-edit-reasonlist' => 'Editar razones de borrado',
+'revdelete-otherreason' => 'Otro motivo:',
+'revdelete-reasonotherlist' => 'Otro motivo',
+'revdelete-edit-reasonlist' => 'Editar motivos de borrado',
 'revdelete-offender' => 'Autor de la revisión:',
 
 # Suppression log
@@ -1415,7 +1421,7 @@ Nota que usar los enlaces de navegación borrará las selecciones de esta column
 'mergehistory-autocomment' => 'Fusionando [[:$1]] en [[:$2]]',
 'mergehistory-comment' => 'Fusionando [[:$1]] en [[:$2]]: $3',
 'mergehistory-same-destination' => 'Las páginas de origen y destino no pueden ser la misma',
-'mergehistory-reason' => 'Razón:',
+'mergehistory-reason' => 'Motivo:',
 
 # Merge log
 'mergelog' => 'Registro de fusiones',
@@ -1508,13 +1514,12 @@ Mientras tanto puedes buscar mediante Google, pero ten en cuenta que sus índice
 'preferences' => 'Preferencias',
 'mypreferences' => 'Preferencias',
 'prefs-edits' => 'Cantidad de ediciones:',
-'prefsnologin' => 'No has iniciado sesión',
-'prefsnologintext' => 'Necesitas <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} iniciar sesión]</span> para establecer las preferencias del usuario.',
+'prefsnologintext2' => 'Necesitas $1 para definir las preferencias del usuario.',
 'changepassword' => 'Cambiar contraseña',
 'prefs-skin' => 'Apariencia',
 'skin-preview' => 'Previsualizar',
 'datedefault' => 'Sin preferencia',
-'prefs-beta' => 'Características de prueba',
+'prefs-beta' => 'Funciones en pruebas',
 'prefs-datetime' => 'Fecha y hora',
 'prefs-labs' => 'Características de los laboratorios',
 'prefs-user-pages' => 'Páginas de usuario',
@@ -1524,7 +1529,7 @@ Mientras tanto puedes buscar mediante Google, pero ten en cuenta que sus índice
 'prefs-watchlist-days' => 'Número de días a mostrar en la lista de seguimiento:',
 'prefs-watchlist-days-max' => 'Máximo $1 {{PLURAL:$1|día|días}}',
 'prefs-watchlist-edits' => 'Número de ediciones a mostrar en la lista expandida:',
-'prefs-watchlist-edits-max' => 'Máximo: 1000',
+'prefs-watchlist-edits-max' => 'Cantidad máxima: 1000',
 'prefs-watchlist-token' => 'Ficha de lista de seguimiento:',
 'prefs-misc' => 'Miscelánea',
 'prefs-resetpass' => 'Cambiar contraseña',
@@ -1549,8 +1554,8 @@ Mientras tanto puedes buscar mediante Google, pero ten en cuenta que sus índice
 'prefs-help-watchlist-token2' => 'Esta es la clave secreta para el canal de contenido web de tu lista de seguimiento.
 Cualquier persona que la conozca podría leer tu lista, así que no la compartas.
 [[Special:ResetTokens|Pulsa aquí si necesitas restablecerla]].',
-'savedprefs' => 'Tus preferencias han sido guardadas.',
-'timezonelegend' => 'Zona horaria:',
+'savedprefs' => 'Se han guardado tus preferencias.',
+'timezonelegend' => 'Huso horario:',
 'localtime' => 'Hora local:',
 'timezoneuseserverdefault' => 'Usar la hora del servidor ($1)',
 'timezoneuseoffset' => 'Otra (especifica la diferencia horaria)',
@@ -1559,7 +1564,7 @@ Cualquier persona que la conozca podría leer tu lista, así que no la compartas
 'guesstimezone' => 'Rellenar a partir de la hora del navegador',
 'timezoneregion-africa' => 'África',
 'timezoneregion-america' => 'América',
-'timezoneregion-antarctica' => 'Antártica',
+'timezoneregion-antarctica' => 'Antártida',
 'timezoneregion-arctic' => 'Ártico',
 'timezoneregion-asia' => 'Asia',
 'timezoneregion-atlantic' => 'Océano Atlántico',
@@ -1588,15 +1593,15 @@ Esto no se puede deshacer.',
 'yourlanguage' => 'Idioma:',
 'yourvariant' => 'Variante lingüística del contenido:',
 'prefs-help-variant' => 'Tu variante u ortografía preferida para mostrar las páginas de contenido de este wiki.',
-'yournick' => 'Nueva firma:',
+'yournick' => 'Firma nueva:',
 'prefs-help-signature' => 'Los comentarios en páginas de discusión deberían firmarse con «<nowiki>~~~~</nowiki>», que se convertirá en tu firma con fecha y hora.',
 'badsig' => 'El código de tu firma no es válido; comprueba las etiquetas HTML.',
 'badsiglength' => 'Tu firma es muy larga.
 Debe contener un máximo de {{PLURAL:$1|un carácter|$1 caracteres}}.',
-'yourgender' => '¿Cómo prefieres ser descrito/a?',
-'gender-unknown' => 'Prefiero no especificar',
-'gender-male' => 'Él edita páginas wiki',
-'gender-female' => 'Ella edita páginas wiki',
+'yourgender' => 'Sexo:',
+'gender-unknown' => 'Prefiero no especificarlo',
+'gender-male' => 'Masculino',
+'gender-female' => 'Femenino',
 'prefs-help-gender' => 'Opcional: empleado para que sea usado correctamente el género por parte del software. Esta información será pública.',
 'email' => 'Correo electrónico',
 'prefs-help-realname' => 'El nombre real es opcional. Si decides proporcionarlo, se usará para dar atribución a tu trabajo.',
@@ -1681,7 +1686,7 @@ Tu dirección de correo no se revela cuando otros usuarios te contactan.',
 'right-createpage' => 'Crear páginas que no sean páginas de discusión',
 'right-createtalk' => 'Crear páginas de discusión',
 'right-createaccount' => 'Crear cuentas de usuario nuevas',
-'right-minoredit' => 'Marcar ediciones como «menores»',
+'right-minoredit' => 'Marcar ediciones como menores',
 'right-move' => 'Trasladar páginas',
 'right-move-subpages' => 'Trasladar páginas con sus subpáginas',
 'right-move-rootuserpages' => 'Trasladar páginas de usuario raíz',
@@ -1807,6 +1812,7 @@ Tu dirección de correo no se revela cuando otros usuarios te contactan.',
 'recentchanges-label-minor' => 'Esta es una edición menor',
 'recentchanges-label-bot' => 'Esta edición fue realizada por un robot',
 'recentchanges-label-unpatrolled' => 'Esta edición todavía no se ha patrullado',
+'recentchanges-legend-newpage' => '$1 - página nueva',
 'rcnote' => "Debajo {{PLURAL:$1|hay '''1''' cambio efectuado|están los últimos '''$1''' cambios efectuados}} en  {{PLURAL:$2|el último día|los últimos '''$2''' días}}, hasta el $4, $5.",
 'rcnotefrom' => 'A continuación se muestran los cambios desde <b>$2</b> (hasta <b>$1</b>).',
 'rclistfrom' => 'Mostrar nuevos cambios desde $1',
@@ -3044,7 +3050,7 @@ En el último caso también puedes usar un enlace, por ejemplo [[{{#Special:Expo
 'allmessagesdefault' => 'Texto predeterminado',
 'allmessagescurrent' => 'Texto actual',
 'allmessagestext' => 'Esta es una lista de mensajes del sistema disponibles en el espacio de nombres MediaWiki:
-Por favor visita [//www.mediawiki.org/wiki/Localisation Localización MediaWiki] y [//translatewiki.net translatewiki.net] si deseas contribuir con la localización genérica MediaWiki.',
+Por favor visita [https://www.mediawiki.org/wiki/Localisation Localización MediaWiki] y [//translatewiki.net translatewiki.net] si deseas contribuir con la localización genérica MediaWiki.',
 'allmessagesnotsupportedDB' => "Esta página no está disponible porque '''\$wgUseDatabaseMessages''' está deshabilitado.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar por estado de personalización:',
@@ -3210,6 +3216,7 @@ Puedes ver su código fuente',
 Permite añadir una razón al resumen de edición.',
 'tooltip-preferences-save' => 'Guardar las preferencias',
 'tooltip-summary' => 'Introduce un breve resumen',
+'interlanguage-link-title' => '$1 ($2)',
 
 # Stylesheets
 'common.css' => '/* El CSS colocado en esta página será aplicado a todas las apariencias */',
@@ -3259,6 +3266,8 @@ Esto podría estar causado por un enlace a un sitio externo incluido en la lista
 'spam_reverting' => 'Revirtiendo a la última versión que no contenga enlaces a $1',
 'spam_blanking' => 'Todas las revisiones contienen enlaces a $1, blanqueando',
 'spam_deleting' => 'Todas las revisiones que contienen enlaces a $1, en proceso de eliminación',
+'simpleantispam-label' => 'Comprobación anti-spam
+¡NO rellenes esto!',
 
 # Info page
 'pageinfo-title' => 'Información para «$1»',
@@ -3272,6 +3281,7 @@ Esto podría estar causado por un enlace a un sitio externo incluido en la lista
 'pageinfo-length' => 'Longitud de la página (en bytes)',
 'pageinfo-article-id' => 'Identificador ID de la página',
 'pageinfo-language' => 'Idioma de la página',
+'pageinfo-content-model' => 'Modelo de contenido de la página',
 'pageinfo-robot-policy' => 'Indización por robots',
 'pageinfo-robot-index' => 'Permitido',
 'pageinfo-robot-noindex' => 'No permitido',
@@ -3360,7 +3370,7 @@ Ejecutarlo podría comprometer la seguridad de su equipo.",
 'svg-long-desc' => 'archivo SVG, nominalmente $1 × $2 píxeles, tamaño de archivo: $3',
 'svg-long-desc-animated' => 'Archivo SVG animado, nominalmente de $1 × $2 píxeles, tamaño del archivo: $3',
 'svg-long-error' => 'Archivo SVG no válido: $1',
-'show-big-image' => 'Resolución original',
+'show-big-image' => 'Archivo original',
 'show-big-image-preview' => 'Tamaño de esta previsualización: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Otra resolución|Otras resoluciones}}: $1.',
 'show-big-image-size' => '$1 × $2 píxeles',
@@ -3831,7 +3841,7 @@ Existen otros campos que se mantendrán ocultos por defecto.
 
 # External editor support
 'edit-externally' => 'Editar este archivo usando una aplicación externa',
-'edit-externally-help' => '(Lee las [//www.mediawiki.org/wiki/Manual:External_editors instrucciones de configuración] -en inglés- para más información)',
+'edit-externally-help' => '(Lee las [https://www.mediawiki.org/wiki/Manual:External_editors instrucciones de configuración] -en inglés- para más información)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todos',
@@ -3924,6 +3934,7 @@ Confirma que realmente quieres volver a crear esta página.",
 
 # Separators for various lists, etc.
 'comma-separator' => ',&#32;',
+'quotation-marks' => '«$1»',
 
 # Multipage image navigation
 'imgmultipageprev' => '← página anterior',
@@ -4012,7 +4023,7 @@ También puedes [[Special:EditWatchlist|usar el editor estándar]].',
 'version-hook-subscribedby' => 'Suscrito por',
 'version-version' => '(Versión $1)',
 'version-license' => 'Licencia',
-'version-poweredby-credits' => "Este wiki funciona gracias a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Este wiki funciona gracias a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'otros',
 'version-poweredby-translators' => 'Traductores de translatewiki.net',
 'version-credits-summary' => 'Queremos reconocer a las siguientes personas por su contribución a [[Special:Version|MediaWiki]].',
@@ -4033,7 +4044,7 @@ Has recibido [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia de la Licencia Pública
 # Special:Redirect
 'redirect' => 'Redirigir por archivo, usuario o ID de revisión',
 'redirect-legend' => 'Redirigir a un archivo o página',
-'redirect-summary' => 'Esta página especial redirige a un fichero (dado un nombre de fichero), a una página (dado un identificador de revisión) o a una página de usuario (dado en identificador numérico de usuario).',
+'redirect-summary' => 'Esta página especial redirige a un fichero (dado un nombre de fichero), a una página (dado un identificador de revisión) o a una página de usuario (dado en identificador numérico de usuario). Uso: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], o [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Ir',
 'redirect-lookup' => 'Buscar:',
 'redirect-value' => 'Valor:',
@@ -4055,8 +4066,8 @@ Has recibido [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia de la Licencia Pública
 
 # Special:SpecialPages
 'specialpages' => 'Páginas especiales',
-'specialpages-note' => '----
-* Páginas especiales normales
+'specialpages-note-top' => 'Leyenda',
+'specialpages-note' => '* Páginas especiales normales
 * <span class="mw-specialpagerestricted">Páginas especiales restringidas.</span>
 * <span class="mw-specialpagecached">Páginas especiales en caché (podrían ser obsoletas).</span>',
 'specialpages-group-maintenance' => 'Reportes de mantenimiento',
@@ -4099,6 +4110,7 @@ Has recibido [{{SERVER}}{{SCRIPTPATH}}/COPYING una copia de la Licencia Pública
 'tags-active-header' => '¿Activo?',
 'tags-hitcount-header' => 'Cambios etiquetados',
 'tags-active-yes' => 'Sí',
+'tags-active-no' => 'No',
 'tags-edit' => 'editar',
 'tags-hitcount' => '$1 {{PLURAL:$1|cambio|cambios}}',
 
@@ -4271,4 +4283,19 @@ En otro caso, puedes usar el siguiente formulario. Tu comentario será añadido
 'limitreport-expansiondepth' => 'Profundidad máxima de expansión',
 'limitreport-expensivefunctioncount' => 'Cuenta de la funcion expansiva del analizador',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandir plantillas',
+'expand_templates_intro' => 'Esta página especial toma un texto wiki y expande todas sus plantillas recursivamente.
+También expande las funciones sintácticas como <code><nowiki>{{</nowiki>#language:…}}</code>, y variables como
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. De hecho, expande casi cualquier cosa que esté entre llaves dobles.',
+'expand_templates_title' => 'Título de la página, útil para expandir <nowiki>{{PAGENAME}}</nowiki> o similares',
+'expand_templates_input' => 'Texto a expandir:',
+'expand_templates_output' => 'Resultado:',
+'expand_templates_xml_output' => 'Salida XML',
+'expand_templates_ok' => 'Aceptar',
+'expand_templates_remove_comments' => 'Eliminar comentarios (<!-- ... -->)',
+'expand_templates_remove_nowiki' => 'Suprimir <nowiki> etiquetas en resultado',
+'expand_templates_generate_xml' => 'Mostrar el árbol XML.',
+'expand_templates_preview' => 'Previsualización',
+
 );
index 505d090..880ab63 100644 (file)
@@ -7,6 +7,7 @@
  * @ingroup Language
  * @file
  *
+ * @author AivoK
  * @author Avjoska
  * @author Cylly1512
  * @author Geitost
@@ -54,6 +55,7 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Teguskasutajad' ),
        'Allmessages'               => array( 'Kõik_sõnumid' ),
+       'AllMyUploads'              => array( 'Kõik_minu_failid' ),
        'Allpages'                  => array( 'Kõik_leheküljed' ),
        'Ancientpages'              => array( 'Vanimad_leheküljed' ),
        'Blankpage'                 => array( 'Tühi_leht' ),
@@ -69,10 +71,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Konto_loomine' ),
        'Deadendpages'              => array( 'Edasipääsuta_leheküljed' ),
        'DeletedContributions'      => array( 'Kustutatud_kaastöö' ),
-       'Disambiguations'           => array( 'Täpsustusleheküljed' ),
        'DoubleRedirects'           => array( 'Kahekordsed_ümbersuunamised' ),
        'EditWatchlist'             => array( 'Jälgimisloendi_redigeerimine' ),
        'Emailuser'                 => array( 'E-kirja_saatmine' ),
+       'ExpandTemplates'           => array( 'Mallide_hõrendamine' ),
        'Export'                    => array( 'Lehekülgede_eksport' ),
        'Fewestrevisions'           => array( 'Vähim_muudatusi' ),
        'FileDuplicateSearch'       => array( 'Faili_duplikaatide_otsimine', 'Otsi_faili_duplikaate' ),
@@ -96,6 +98,7 @@ $specialPageAliases = array(
        'MIMEsearch'                => array( 'MIME_otsing' ),
        'Mostcategories'            => array( 'Enim_kategoriseeritud' ),
        'Mostimages'                => array( 'Kõige_kasutatumad_failid' ),
+       'Mostinterwikis'            => array( 'Enim_keelelinke' ),
        'Mostlinked'                => array( 'Kõige_viidatumad_leheküljed' ),
        'Mostlinkedcategories'      => array( 'Kõige_viidatumad_kategooriad' ),
        'Mostlinkedtemplates'       => array( 'Kõige_viidatumad_mallid' ),
@@ -116,9 +119,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Kaitstud_leheküljed' ),
        'Protectedtitles'           => array( 'Kaitstud_pealkirjad' ),
        'Randompage'                => array( 'Juhuslik_artikkel' ),
+       'RandomInCategory'          => array( 'Juhuslik_kategoorias' ),
        'Randomredirect'            => array( 'Juhuslik_ümbersuunamine' ),
        'Recentchanges'             => array( 'Viimased_muudatused' ),
        'Recentchangeslinked'       => array( 'Seotud_muudatused' ),
+       'Redirect'                  => array( 'Ümbersuunamine' ),
+       'ResetTokens'               => array( 'Lubade_lähtestamine' ),
        'Revisiondelete'            => array( 'Muudatuse_kustutamine', 'Kustuta_muudatus' ),
        'Search'                    => array( 'Otsimine', 'Otsi' ),
        'Shortpages'                => array( 'Lühikesed_leheküljed' ),
@@ -198,6 +204,7 @@ $magicWords = array(
        'pagenamee'                 => array( '1', 'LEHEKÜLJENIMI1', 'PAGENAMEE' ),
        'namespace'                 => array( '1', 'NIMERUUM', 'NAMESPACE' ),
        'namespacee'                => array( '1', 'NIMERUUM1', 'NAMESPACEE' ),
+       'namespacenumber'           => array( '1', 'NIMERUUMINUMBER', 'NAMESPACENUMBER' ),
        'talkspace'                 => array( '1', 'ARUTELUNIMERUUM', 'TALKSPACE' ),
        'talkspacee'                => array( '1', 'ARUTELUNIMERUUM1', 'TALKSPACEE' ),
        'subjectspace'              => array( '1', 'SISUNIMERUUM', 'SUBJECTSPACE', 'ARTICLESPACE' ),
@@ -206,6 +213,8 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'KOGULEHEKÜLJENIMI1', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'ALAMLEHEKÜLJENIMI', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'ALAMLEHEKÜLJENIMI1', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'JUURLEHEKÜLJENIMI', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'JUURLEHEKÜLJENIMI1', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'NIMERUUMITANIMI', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'NIMERUUMITANIMI1', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'ARUTELUNIMI', 'TALKPAGENAME' ),
@@ -248,7 +257,10 @@ $magicWords = array(
        'pagesinnamespace'          => array( '1', 'LEHEKÜLGINIMERUUMIS', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
        'numberofadmins'            => array( '1', 'ÜLEMAMÄÄR', 'NUMBEROFADMINS' ),
        'formatnum'                 => array( '0', 'ARVUVORMINDUS', 'FORMATNUM' ),
+       'special'                   => array( '0', 'eri', 'special' ),
+       'speciale'                  => array( '0', 'eri1', 'speciale' ),
        'defaultsort'               => array( '1', 'JÄRJESTA:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
+       'filepath'                  => array( '0', 'FAILITEE:', 'FILEPATH:' ),
        'hiddencat'                 => array( '1', '__PEIDETUDKAT__', '__HIDDENCAT__' ),
        'pagesincategory'           => array( '1', 'LEHEKÜLGIKATEGOORIAS', 'PAGESINCATEGORY', 'PAGESINCAT' ),
        'index'                     => array( '1', 'INDEKSIGA', '__INDEX__' ),
@@ -476,7 +488,7 @@ $messages = array(
 'returnto' => 'Naase lehele $1',
 'tagline' => 'Allikas: {{SITENAME}}',
 'help' => 'Juhend',
-'search' => 'Otsimine',
+'search' => 'Otsing',
 'searchbutton' => 'Otsi',
 'go' => 'Mine',
 'searcharticle' => 'Mine',
@@ -566,19 +578,17 @@ Vaata [[Special:Version|versiooni lehekülge]].',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Pärit leheküljelt "$1"',
 'youhavenewmessages' => 'Sulle on $1 ($2).',
-'newmessageslink' => 'uusi sõnumeid',
-'newmessagesdifflink' => 'viimane muudatus',
 'youhavenewmessagesfromusers' => 'Sulle on $1 {{PLURAL:$3|ühelt|$3}} kasutajalt ($2).',
 'youhavenewmessagesmanyusers' => 'Sulle on $1 paljudelt kasutajatelt ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|uus sõnum|uusi sõnumeid}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|viimane muudatus|viimased muudatused}}',
+'newmessageslinkplural' => '{{PLURAL:$1|uus sõnum|999=uusi sõnumeid}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|viimane muudatus|999=viimased muudatused}}',
 'youhavenewmessagesmulti' => 'Sulle on uusi sõnumeid $1',
 'editsection' => 'muuda',
 'editold' => 'redigeeri',
 'viewsourceold' => 'vaata lähteteksti',
-'editlink' => 'redigeeri',
+'editlink' => 'muuda',
 'viewsourcelink' => 'vaata lähteteksti',
-'editsectionhint' => 'Redigeeri alaosa "$1"',
+'editsectionhint' => 'Muuda alaosa "$1"',
 'toc' => 'Sisukord',
 'showtoc' => 'näita',
 'hidetoc' => 'peida',
@@ -590,10 +600,10 @@ Vaata [[Special:Version|versiooni lehekülge]].',
 'feedlinks' => 'Sööde:',
 'feed-invalid' => 'Vigane vootüüp.',
 'feed-unavailable' => 'Uudisvood ei ole saadaval.',
-'site-rss-feed' => '$1 RSS-toide',
-'site-atom-feed' => '$1 Atom-toide',
-'page-rss-feed' => '"$1" RSS-toide',
-'page-atom-feed' => '"$1" Atom-toide',
+'site-rss-feed' => '$1 (RSS-voog)',
+'site-atom-feed' => '$1 Atom-voog',
+'page-rss-feed' => '$1 (RSS-voog)',
+'page-atom-feed' => '$1 (Atom-voog)',
 'red-link-title' => '$1 (pole veel kirjutatud)',
 'sort-descending' => 'Järjesta laskuvalt',
 'sort-ascending' => 'Järjesta tõusvalt',
@@ -699,7 +709,8 @@ Administraator lukustas selle järgmisel põhjusel: "$3".',
 'invalidtitle-knownnamespace' => 'Vigane pealkiri nimeruumis "$2" tekstiga "$3"',
 'invalidtitle-unknownnamespace' => 'Vigane pealkiri nimeruuminumbriga $1 ja tekstiga "$2"',
 'exception-nologin' => 'Sisse logimata',
-'exception-nologin-text' => 'Selle lehekülje või toimingu jaoks pead selles vikis olema sisse loginud.',
+'exception-nologin-text' => 'Selle lehekülje või toimingu jaoks [[Special:Userlogin|logi]] palun sisse.',
+'exception-nologin-text-manual' => 'Pead $1, et sellele leheküljele või toimingule ligi pääseda.',
 
 # Virus scanner
 'virus-badscanner' => "Viga konfiguratsioonis: tundmatu viirusetõrje: ''$1''",
@@ -746,7 +757,7 @@ Pane tähele, et seni kuni sa pole oma võrgulehitseja puhvrit tühjendanud, võ
 'gotaccount' => "Kui sul on juba konto, '''$1'''.",
 'gotaccountlink' => 'logi sisse',
 'userlogin-resetlink' => 'Kas oled unustanud oma sisselogimisandmed?',
-'userlogin-resetpassword-link' => 'Lähtesta oma parool',
+'userlogin-resetpassword-link' => 'Unustasid parooli?',
 'helplogin-url' => 'Help:Sisselogimine',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Sisselogimisabi]]',
 'userlogin-loggedin' => 'Oled juba sisse logitud nimega {{GENDER:$1|$1}}.
@@ -805,15 +816,16 @@ Kui uut parooli palus keegi teine või sulle meenus vana parool ja sa ei soovi s
 'passwordsent' => 'Uus parool on saadetud kasutaja $1 registreeritud e-postiaadressil.
 Pärast parooli saamist logige palun sisse.',
 'blocked-mailpassword' => 'Sinu IP-aadressi jaoks on toimetamine blokeeritud, seetõttu ei saa sa kasutada ka parooli meeldetuletamise funktsiooni.',
-'eauthentsent' => 'Sisestatud e-posti aadressile on saadetud kinnituse e-kiri.
-Enne kui su kontole ükskõik milline muu e-kiri saadetakse, pead sa e-kirjas olevat juhist järgides kinnitama, et konto on tõepoolest sinu.',
+'eauthentsent' => 'Määratud e-posti aadressile on saadetud kinnituse e-kiri.
+Enne kui su kontole ükskõik milline muu e-kiri saadetakse, pead e-kirjas olevat juhist järgides kinnitama, et konto on tõepoolest sinu.',
 'throttled-mailpassword' => 'Parooli lähtestamise e-kiri saadetud viimase {{PLURAL:$1|tunni|$1 tunni}} jooksul.
 Väärtarvitamise vältimiseks saadetakse {{PLURAL:$1|tunni|$1 tunni}} jooksul ainult üks lähtestamise e-kiri.',
 'mailerror' => 'Viga kirja saatmisel: $1',
 'acct_creation_throttle_hit' => 'Selle viki külastajad, kes kasutavad sinu IP-aadressi, on viimase ööpäeva jooksul loonud {{PLURAL:$1|ühe konto|$1 kontot}}, mis on selles ajavahemikus ülemmääraks.
 Seetõttu ei saa seda IP-aadressi kasutades hetkel rohkem kontosid luua.',
 'emailauthenticated' => 'Sinu e-posti aadressi kinnitamisaeg: $2 kell $3.',
-'emailnotauthenticated' => 'Sinu e-posti aadress <strong>pole veel kinnitatud</strong>. Järgnevate funktsioonidega seotud e-kirju kinnitamata aadressile ei saadeta.',
+'emailnotauthenticated' => 'Sinu e-posti aadress pole veel kinnitatud.
+Järgnevate funktsioonidega seotud e-kirju ei saadeta.',
 'noemailprefs' => 'Järgnevate võimaluste toimimiseks on vaja sisestada e-posti aadress.',
 'emailconfirmlink' => 'Kinnita oma e-posti aadress',
 'invalidemailaddress' => 'E-posti aadress ei ole aktsepteeritav, sest see on vigaselt kirjutatud.
@@ -913,7 +925,7 @@ Peaksid load lähtestama, kui jagasid neid kogemata või kui su konto on kellegi
 'resettokens-legend' => 'Lubade lähtestamine',
 'resettokens-tokens' => 'Load:',
 'resettokens-token-label' => '$1 (praegune väärtus: $2)',
-'resettokens-watchlist-token' => '[[Special:Watchlist|Jälgimisloendis olevatel lehekülgedel tehtud muudatuste]] võrgutoite (Atom/RSS) luba',
+'resettokens-watchlist-token' => '[[Special:Watchlist|Jälgimisloendis olevatel lehekülgedel tehtud muudatuste]] veebivoo (Atom/RSS) luba',
 'resettokens-done' => 'Load lähtestatud.',
 'resettokens-resetbutton' => 'Lähtesta valitud load',
 
@@ -929,7 +941,7 @@ Peaksid load lähtestama, kui jagasid neid kogemata või kui su konto on kellegi
 'headline_sample' => 'Pealkiri',
 'headline_tip' => '2. taseme pealkiri',
 'nowiki_sample' => 'Sisesta vormindamata tekst',
-'nowiki_tip' => 'Ignoreeri viki vormindust',
+'nowiki_tip' => 'Ignoreeri vikivormindust',
 'image_sample' => 'Näidis.jpg',
 'image_tip' => 'Pilt',
 'media_sample' => 'Näidis.ogg',
@@ -1118,23 +1130,23 @@ Tundub, et see on kustutatud.',
 'edit-already-exists' => 'Ei saanud alustada uut lehekülge.
 See on juba olemas.',
 'defaultmessagetext' => 'Sõnumi vaiketekst',
+'content-failed-to-parse' => 'Ebaõnnestus $1i mudeli $2-tüüpi sisu liigendamine: $3',
 'invalid-content-data' => 'Vigased sisuandmed',
-'content-not-allowed-here' => 'Lehekülg [[$2]] ei või sisaldada $1.',
+'content-not-allowed-here' => 'Lehekülg [[$2]] ei või sisaldada $1i.',
 'editwarning-warning' => 'Sellelt leheküljelt lahkumise tõttu võivad tehtud muudatused kaotsi minna.
 Kui oled sisse loginud, saad selle hoiatuse eelistuste alaosas "Toimetamine" keelata.',
 
 # Content models
-'content-model-wikitext' => 'vikiteksti',
-'content-model-text' => 'lihtteksti',
-'content-model-javascript' => 'JavaScripti',
-'content-model-css' => 'CSSi',
+'content-model-wikitext' => 'vikitekst',
+'content-model-text' => 'lihttekst',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''Hoiatus:''' See lehekülg kasutab liialt palju aeglustavaid laiendusfunktsioone. Neid võiks kasutada vähem kui {{PLURAL:$2|ühel|$2}} korral, praegu on kasutatud {{PLURAL:$1|ühel|$1}} korral.",
 'expensive-parserfunction-category' => 'Liiga palju aeglasi laiendusfunktsioone kasutavad leheküljed',
-'post-expand-template-inclusion-warning' => "'''Hoiatus:''' Väljakutsutavate mallide hulk on liiga suur.
-Mistõttu osasid malle ei näidata.",
-'post-expand-template-inclusion-category' => 'Leheküljed, milledel on mallide väljakutsumise limiit ületatud',
+'post-expand-template-inclusion-warning' => "'''Hoiatus:''' Väljakutsutavate mallide hulk on liiga suur, mõningaid malle ei näidata.",
+'post-expand-template-inclusion-category' => 'Leheküljed, kus mallide väljakutsumise limiit on ületatud',
 'post-expand-template-argument-warning' => "'''Hoiatus:''' See lehekülg sisaldab argumendina vähemalt üht malli, mille määratud maht on liiga suur.
 Need argumendid on välja jäetud.",
 'post-expand-template-argument-category' => 'Malli vahele jäetud argumente sisaldavad leheküljed',
@@ -1239,18 +1251,19 @@ Saad seda muudatust vaadata. [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAG
 {{GRAMMAR:genitive|{{SITENAME}}}} administraatorid saavad peidetud sisu siiski vaadata ning seda vajadusel selle liidese kaudu taastada, kui see pole just täiendavalt keelatud.",
 'revdelete-confirm' => 'Kinnita, et soovid tõesti seda teha ning et saad aru tagajärgedest ja tegevus on kooskõlas [[{{MediaWiki:Policy-url}}|siinsete kokkulepetega]].',
 'revdelete-suppress-text' => "Andmed tuleks varjata '''ainult''' järgnevatel juhtudel:
+* Võimalik laim
 * Sobimatu isiklik teave
-*: ''kodune aadress ja telefoninumber, sotsiaalhoolekandenumber jne''",
+*: ''kodune aadress ja telefoninumber, isikukood jne''",
 'revdelete-legend' => 'Nähtavuse piirangute seadmine',
-'revdelete-hide-text' => 'Peida redaktsiooni tekst',
+'revdelete-hide-text' => 'Redaktsiooni tekst',
 'revdelete-hide-image' => 'Peida faili sisu',
 'revdelete-hide-name' => 'Peida toiming ja sihtmärk',
-'revdelete-hide-comment' => 'Peida resümee',
-'revdelete-hide-user' => 'Peida toimetaja kasutajanimi või IP-aadress',
+'revdelete-hide-comment' => 'Resümee',
+'revdelete-hide-user' => 'Toimetaja kasutajanimi või IP-aadress',
 'revdelete-hide-restricted' => 'Varja andmeid nii administraatorite kui ka teiste eest.',
 'revdelete-radio-same' => '(ära muuda)',
-'revdelete-radio-set' => 'Jah',
-'revdelete-radio-unset' => 'Ei',
+'revdelete-radio-set' => 'Peidetud',
+'revdelete-radio-unset' => 'Nähtav',
 'revdelete-suppress' => 'Varja andmed nii administraatorite kui ka teiste eest',
 'revdelete-unsuppress' => 'Eemalda taastatud redaktsioonidelt piirangud',
 'revdelete-log' => 'Põhjus:',
@@ -1410,8 +1423,7 @@ Pane tähele, et Google'is talletatud {{GRAMMAR:genitive|{{SITENAME}}}} sisu võ
 'preferences' => 'Eelistused',
 'mypreferences' => 'Eelistused',
 'prefs-edits' => 'Redigeerimiste arv:',
-'prefsnologin' => 'Sisse logimata',
-'prefsnologintext' => 'Oma eelistuste määramiseks pead olema <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} sisse logitud]</span>.',
+'prefsnologintext2' => 'Pead $1, et oma eelistusi muuta.',
 'changepassword' => 'Muuda parool',
 'prefs-skin' => 'Kujundus',
 'skin-preview' => 'eelvaade',
@@ -1448,7 +1460,7 @@ Pane tähele, et Google'is talletatud {{GRAMMAR:genitive|{{SITENAME}}}} sisu võ
 'recentchangesdays-max' => 'Ülemmäär $1 {{PLURAL:$1|päev|päeva}}',
 'recentchangescount' => 'Mitut redaktsiooni vaikimisi näidata:',
 'prefs-help-recentchangescount' => 'See käib viimaste muudatuste, lehekülgede ajalugude ja logide kohta.',
-'prefs-help-watchlist-token2' => 'See on sinu jälgimisloendi võrgutoite salavõti.
+'prefs-help-watchlist-token2' => 'See on sinu jälgimisloendi veebivoo salavõti.
 Igaüks, kes seda teab, saab lugeda sinu jälgimisloendit. Seega ära jaga seda.
 [[Special:ResetTokens|Klõpsa siia, kui sul on vaja see lähtestada]].',
 'savedprefs' => 'Sinu eelistused on salvestatud.',
@@ -1707,10 +1719,12 @@ See teave on avalik.',
 'recentchanges-summary' => 'Jälgi sellel leheküljel viimaseid muudatusi.',
 'recentchanges-noresult' => 'Selles ajavahemikus pole tehtud neile kriteeriumitele vastavaid muudatusi.',
 'recentchanges-feed-description' => 'Jälgi vikisse tehtud viimaseid muudatusi.',
-'recentchanges-label-newpage' => 'See muudatus lõi uue lehekülje',
-'recentchanges-label-minor' => 'See on pisiparandus',
-'recentchanges-label-bot' => 'Selle muudatuse sooritas robot',
+'recentchanges-label-newpage' => 'Uus lehekülg',
+'recentchanges-label-minor' => 'Pisiparandus',
+'recentchanges-label-bot' => 'Roboti tehtud muudatus',
 'recentchanges-label-unpatrolled' => 'Seda muudatust ei ole veel kontrollitud',
+'recentchanges-label-plusminus' => 'Lehekülje suuruse muutus baitides',
+'recentchanges-legend-newpage' => '(vaata ka [[Special:NewPages|uute lehekülgede loendit]])',
 'rcnote' => "Allpool on esitatud {{PLURAL:$1|'''1''' muudatus|viimased '''$1''' muudatust}} viimase {{PLURAL:$2|päeva|'''$2''' päeva}} jooksul seisuga $4, kell $5.",
 'rcnotefrom' => "Allpool on toodud muudatused alates: '''$2''' (näidatakse kuni '''$1''' muudatust)",
 'rclistfrom' => 'Näita muudatusi alates: $1',
@@ -2414,7 +2428,7 @@ Redigeerijaga ühenduse võtmine:
 e-post: $PAGEEDITOR_EMAIL
 viki: $PAGEEDITOR_WIKI
 
-Seni kuni sa seda lehte ei külasta, selle lehega seotud toimingute kohta sulle uusi teavitus-e-kirju ei saadeta. Jälgimisloendis saaksid kõigi jälgitavate lehekülgedega seotud teavitussätted ka lähtestada.
+Seni kuni sa sisselogituna seda lehekülge ei külasta, selle leheküljega seotud toimingute kohta sulle uusi teavituse e-kirju ei saadeta. Jälgimisloendis saaksid kõigi jälgitavate lehekülgedega seotud teavitussätted ka lähtestada.
 
 Abivalmilt
 {{GRAMMAR:genitive|{{SITENAME}}}} teavitussüsteem
@@ -2889,7 +2903,8 @@ Kas kustutad selle, et luua võimalus teisaldamiseks?',
 'immobile-target-namespace-iw' => 'Keelelink ei ole sobiv koht lehekülje teisaldamiseks.',
 'immobile-source-page' => 'Lehekülg ei ole teisaldatav.',
 'immobile-target-page' => 'Soovitud pealkirja alla ei saa teisaldada.',
-'imagenocrossnamespace' => 'Faili ei saa teisaldada mõnda muusse nimeruumi',
+'bad-target-model' => 'Soovitud sihtlehekülje sisumudel on erinev. {{ucfirst:$1}}i ei saa teisendada $2iks.',
+'imagenocrossnamespace' => 'Faili ei saa teisaldada mõnda muusse nimeruumi.',
 'nonfile-cannot-move-to-file' => 'Failinimeruumi saab ainult faile teisaldada.',
 'imagetypemismatch' => 'Uus faililaiend ei sobi selle tüübiga',
 'imageinvalidfilename' => 'Sihtmärgi nimi on vigane',
@@ -2932,7 +2947,7 @@ Viimasel juhul saab kasutada ka linki, näiteks lehekülje "[[{{MediaWiki:Mainpa
 'allmessagesdefault' => 'Vaiketekst',
 'allmessagescurrent' => 'Praegune tekst',
 'allmessagestext' => 'See on loend kõikidest olemasolevatest süsteemisõnumitest MediaWiki nimeruumis.
-Kui soovid MediaWiki tarkvara tõlkimises osaleda, siis vaata lehti [//www.mediawiki.org/wiki/Localisation MediaWiki lokaliseerimine] ja [//translatewiki.net translatewiki.net].',
+Kui soovid MediaWiki tarkvara tõlkimises osaleda, siis vaata lehti [https://www.mediawiki.org/wiki/Localisation MediaWiki lokaliseerimine] ja [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => "Seda lehekülge ei saa kasutada, sest '''\$wgUseDatabaseMessages''' ei tööta.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Muutmisoleku filter:',
@@ -3035,13 +3050,13 @@ Palun ürita uuesti.',
 'tooltip-pt-mytalk' => 'Sinu arutelulehekülg',
 'tooltip-pt-anontalk' => 'Arutelu sellelt IP-aadressilt tehtud muudatuste kohta',
 'tooltip-pt-preferences' => 'Sinu eelistused',
-'tooltip-pt-watchlist' => 'Lehekülgede loend, mida jälgid muudatuste osas',
+'tooltip-pt-watchlist' => 'Lehekülgede loend, mille muudatusi jälgid',
 'tooltip-pt-mycontris' => 'Sinu kaastööde loend',
 'tooltip-pt-login' => 'Me julgustame teid sisse logima, kuid see pole kohustuslik.',
 'tooltip-pt-anonlogin' => 'Me julgustame teid sisse logima, kuid see pole kohustuslik.',
 'tooltip-pt-logout' => 'Logi välja',
 'tooltip-ca-talk' => 'Selle artikli arutelu',
-'tooltip-ca-edit' => 'Saad seda lehekülge redigeerida. Palun kasuta enne salvestamist eelvaadet.',
+'tooltip-ca-edit' => 'Sa saad seda lehekülge muuta. Palun kasuta enne salvestamist eelvaadet.',
 'tooltip-ca-addsection' => 'Lisa uus alaosa',
 'tooltip-ca-viewsource' => 'See lehekülg on kaitstud.
 Saad vaadata selle lähteteksti.',
@@ -3065,9 +3080,9 @@ Saad vaadata selle lähteteksti.',
 'tooltip-n-randompage' => 'Mine juhuslikule leheküljele',
 'tooltip-n-help' => 'Kuidas redigeerida',
 'tooltip-t-whatlinkshere' => 'Kõik viki leheküljed, mis siia viitavad',
-'tooltip-t-recentchangeslinked' => 'Viimased muudatused lehekülgedel, milledele on siit viidatud',
-'tooltip-feed-rss' => 'Selle lehekülje RSS-toide',
-'tooltip-feed-atom' => 'Selle lehekülje Atom-toide',
+'tooltip-t-recentchangeslinked' => 'Viimased muudatused lehekülgedel, millele on siit viidatud',
+'tooltip-feed-rss' => 'Selle lehekülje RSS-voog',
+'tooltip-feed-atom' => 'Selle lehekülje Atom-voog',
 'tooltip-t-contributions' => 'Kuva selle kasutaja kaastöö',
 'tooltip-t-emailuser' => 'Saada sellele kasutajale e-kiri',
 'tooltip-t-upload' => 'Laadi faile üles',
@@ -3088,7 +3103,7 @@ Saad vaadata selle lähteteksti.',
 'tooltip-save' => 'Salvesta muudatused',
 'tooltip-preview' => 'Näita tehtavaid muudatusi. Palun kasutage seda enne salvestamist!',
 'tooltip-diff' => 'Näita tehtavaid muudatusi.',
-'tooltip-compareselectedversions' => 'Näita erinevusi kahe selle lehe valitud versiooni vahel.',
+'tooltip-compareselectedversions' => 'Näita erinevusi selle lehe kahe valitud versiooni vahel.',
 'tooltip-watch' => 'Lisa see lehekülg oma jälgimisloendisse',
 'tooltip-watchlistedit-normal-submit' => 'Eemalda leheküljed',
 'tooltip-watchlistedit-raw-submit' => 'Uuenda jälgimisloendit',
@@ -3130,6 +3145,8 @@ See on ilmselt põhjustatud linkimisest mustas nimekirjas olevasse välisvõrguk
 'spam_reverting' => 'Taastan viimase versiooni, mis ei sisalda linke aadressile $1.',
 'spam_blanking' => 'Kõik versioonid sisaldasid linke veebilehele $1. Lehekülg tühjendatud.',
 'spam_deleting' => 'Kustutatud kõik redaktsioonid, mis viitasid aadressile $1.',
+'simpleantispam-label' => "Rämpspostikontroll.
+'''ÄRA''' täida seda välja!",
 
 # Info page
 'pageinfo-title' => 'Teave lehekülje "$1" kohta',
@@ -3143,6 +3160,7 @@ See on ilmselt põhjustatud linkimisest mustas nimekirjas olevasse välisvõrguk
 'pageinfo-length' => 'Lehekülje pikkus (baitides)',
 'pageinfo-article-id' => 'Lehekülje identifikaator',
 'pageinfo-language' => 'Lehekülje sisu keel',
+'pageinfo-content-model' => 'Lehekülje sisumudel',
 'pageinfo-robot-policy' => 'Robotindekseering',
 'pageinfo-robot-index' => 'Lubatud',
 'pageinfo-robot-noindex' => 'Keelatud',
@@ -3229,7 +3247,7 @@ Selle avamine võib su arvutit kahjustada.",
 'svg-long-desc' => 'SVG-fail, algsuurus $1 × $2 pikslit, faili suurus: $3',
 'svg-long-desc-animated' => 'Animeeritud SVG-fail,  algsuurus $1 × $2 pikslit, faili suurus: $3',
 'svg-long-error' => 'Vigane SVG-fail: $1',
-'show-big-image' => 'Originaalsuurus',
+'show-big-image' => 'Algfail',
 'show-big-image-preview' => 'Selle eelvaate suurus: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Teine eraldusvõime|Teised eraldusvõimed}}: $1.',
 'show-big-image-size' => '$1 × $2 pikslit',
@@ -3320,6 +3338,7 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-orientation' => 'Orientatsioon',
 'exif-samplesperpixel' => 'Komponentide arv',
 'exif-planarconfiguration' => 'Andmejärjestus',
+'exif-ycbcrsubsampling' => 'Y-i ja C diskreetimissuhe',
 'exif-ycbcrpositioning' => 'Y- ja C-positsioonimine',
 'exif-xresolution' => 'Horisontaalne eraldus',
 'exif-yresolution' => 'Vertikaalne eraldus',
@@ -3363,13 +3382,18 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-aperturevalue' => 'APEX-avaarv',
 'exif-brightnessvalue' => 'APEX-heledus',
 'exif-exposurebiasvalue' => 'Särituse mõju',
-'exif-subjectdistance' => 'Subjekti kaugus',
+'exif-maxaperturevalue' => 'Vähim ava',
+'exif-subjectdistance' => 'Põhimotiivi kaugus',
 'exif-meteringmode' => 'Mõõtmisviis',
 'exif-lightsource' => 'Valgusallikas',
 'exif-flash' => 'Välk',
 'exif-focallength' => 'Fookuskaugus',
+'exif-subjectarea' => 'Põhimotiivi ala',
 'exif-flashenergy' => 'Välgu võimsus',
-'exif-subjectlocation' => 'Subjekti asukoht',
+'exif-focalplanexresolution' => 'Fokaaltasandi laius',
+'exif-focalplaneyresolution' => 'Fokaaltasandi kõrgus',
+'exif-focalplaneresolutionunit' => 'Fokaaltasandi eraldusühik',
+'exif-subjectlocation' => 'Põhimotiivi asukoht',
 'exif-exposureindex' => 'Särituse number',
 'exif-sensingmethod' => 'Tundlikustamismeetod',
 'exif-filesource' => 'Faili päritolu',
@@ -3385,6 +3409,7 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-saturation' => 'Küllastus',
 'exif-sharpness' => 'Teravus',
 'exif-devicesettingdescription' => 'Seadme seadistuste kirjeldus',
+'exif-subjectdistancerange' => 'Põhimotiivi kaugusvahemik',
 'exif-imageuniqueid' => 'Pildi ainuline identifikaator',
 'exif-gpsversionid' => 'GPS-tähise versioon',
 'exif-gpslatituderef' => 'Põhja- või lõunalaius',
@@ -3400,12 +3425,19 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-gpsdop' => 'Mõõtmise täpsus',
 'exif-gpsspeedref' => 'Kiirusühik',
 'exif-gpsspeed' => 'GPS-vastuvõtja kiirus',
-'exif-gpstrack' => 'Liikumise suund',
+'exif-gpstrackref' => 'Liikumissuuna tüüp',
+'exif-gpstrack' => 'Liikumissuund',
+'exif-gpsimgdirectionref' => 'Pildi suuna tüüp',
 'exif-gpsimgdirection' => 'Pildi suund',
 'exif-gpsmapdatum' => 'Geodeetiline alus',
+'exif-gpsdestlatituderef' => 'Poolkera (laius)',
 'exif-gpsdestlatitude' => 'Kujutatud koha laius',
+'exif-gpsdestlongituderef' => 'Poolkera (pikkus)',
 'exif-gpsdestlongitude' => 'Kujutatud koha pikkus',
-'exif-gpsdestdistance' => 'Sihtmärgi kaugus',
+'exif-gpsdestbearingref' => 'Sihtpunkti suuna tüüp',
+'exif-gpsdestbearing' => 'Sihtpunkti suund',
+'exif-gpsdestdistanceref' => 'Sihtpunkti kauguse ühik',
+'exif-gpsdestdistance' => 'Sihtpunkti kaugus',
 'exif-gpsprocessingmethod' => 'GPS-töötlusmeetodi nimi',
 'exif-gpsareainformation' => 'GPS-ala nimi',
 'exif-gpsdatestamp' => 'GPS kuupäev',
@@ -3427,8 +3459,11 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-objectname' => 'Lühipealkiri',
 'exif-specialinstructions' => 'Erijuhised',
 'exif-headline' => 'Pealkiri',
+'exif-credit' => 'Päritolu/Annetaja',
 'exif-source' => 'Allikas',
+'exif-editstatus' => 'Pildi toimetusolek',
 'exif-urgency' => 'Pakilisus',
+'exif-fixtureidentifier' => 'Tugiandmete nimi',
 'exif-locationdest' => 'Kujutatud asukoht',
 'exif-locationdestcode' => 'Kujutatud asukoha kood',
 'exif-objectcycle' => 'Päeva osa, milleks meediafail on ette nähtud',
@@ -3440,6 +3475,7 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-iimsupplementalcategory' => 'Lisakategooriad',
 'exif-datetimeexpires' => 'Mitte kasutada hiljem kui',
 'exif-datetimereleased' => 'Avaldamiskuupäev',
+'exif-originaltransmissionref' => 'Algse edastuskoha kood',
 'exif-identifier' => 'Identifikaator',
 'exif-lens' => 'Kasutatud objektiiv',
 'exif-serialnumber' => 'Kaamera seerianumber',
@@ -3473,6 +3509,9 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 
 # Exif attributes
 'exif-compression-1' => 'Pakkimata',
+'exif-compression-2' => 'CCITT G3 ühemõõtmeline muudetud Hoffmani sarikodeerimine',
+'exif-compression-3' => 'CCITT G3 faksikodeerimine',
+'exif-compression-4' => 'CCITT G4 faksikodeerimine',
 
 'exif-copyrighted-true' => 'Kaitstud',
 'exif-copyrighted-false' => 'Autoriõiguslik seisund määramata',
@@ -3488,7 +3527,8 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-orientation-7' => 'Pööratud 90° päripäeva ja püstselt ümberpööratud',
 'exif-orientation-8' => 'Pööratud 90° päripäeva',
 
-'exif-planarconfiguration-2' => 'tasapinnaline vorm',
+'exif-planarconfiguration-1' => 'järjestikvorming',
+'exif-planarconfiguration-2' => 'kihiline vorming',
 
 'exif-colorspace-65535' => 'Kalibreerimata',
 
@@ -3499,6 +3539,8 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-exposureprogram-2' => 'Tavaprogramm',
 'exif-exposureprogram-3' => 'Ava prioriteet',
 'exif-exposureprogram-4' => 'Katiku prioriteet',
+'exif-exposureprogram-5' => 'Loovprogramm (ülekaalus väljasügavus)',
+'exif-exposureprogram-6' => 'Aktiivprogramm (ülekaalus lühike säriaeg)',
 'exif-exposureprogram-7' => 'Portree töörežiim (lähifotode jaoks, taust fookusest väljas)',
 'exif-exposureprogram-8' => 'Maastiku töörežiim (maastikupiltide jaoks, taust on teravdatud)',
 
@@ -3546,13 +3588,17 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-focalplaneresolutionunit-2' => 'toll',
 
 'exif-sensingmethod-1' => 'Määramata',
-'exif-sensingmethod-2' => 'Ühe-kiibiga värvisensor',
-'exif-sensingmethod-3' => 'Kahe-kiibiga värvisensor',
-'exif-sensingmethod-4' => 'Kolme-kiibiga värvisensor',
-'exif-sensingmethod-7' => 'Kolmerealine sensor',
+'exif-sensingmethod-2' => 'Ühe kiibiga värviandur',
+'exif-sensingmethod-3' => 'Kahe kiibiga värviandur',
+'exif-sensingmethod-4' => 'Kolme kiibiga värviandur',
+'exif-sensingmethod-5' => 'Jadavärviandur',
+'exif-sensingmethod-7' => 'Trilineaarne andur',
+'exif-sensingmethod-8' => 'Lineaarne jadavärviandur',
 
 'exif-filesource-3' => 'Digitaalne fotokaamera',
 
+'exif-scenetype-1' => 'Pildistatud otse',
+
 'exif-customrendered-0' => 'Tavatöötlus',
 'exif-customrendered-1' => 'Kohandatud töötlus',
 
@@ -3604,6 +3650,7 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 'exif-gpsaltitude-below-sealevel' => '$1 {{PLURAL:$1|meeter|meetrit}} allpool merepinda',
 
 'exif-gpsstatus-a' => 'Mõõtmine pooleli',
+'exif-gpsstatus-v' => 'Koostalitlevus',
 
 'exif-gpsmeasuremode-2' => '2-mõõtmeline ulatus',
 'exif-gpsmeasuremode-3' => '3-mõõtmeline ulatus',
@@ -3673,7 +3720,7 @@ Kui faili on rakendustarkvaraga töödeldud, võib osa andmeid olla muudetud võ
 
 # External editor support
 'edit-externally' => 'Töötle faili välise programmiga',
-'edit-externally-help' => '(Vaata väliste redaktorite [//www.mediawiki.org/wiki/Manual:External_editors kasutusjuhendit])',
+'edit-externally-help' => '(Vaata väliste redaktorite [https://www.mediawiki.org/wiki/Manual:External_editors kasutusjuhendit])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Näita kõiki',
@@ -3846,7 +3893,7 @@ Sa võid [[Special:EditWatchlist|kasutada ka harilikku tekstiredaktorit]].',
 'version-hook-subscribedby' => 'Tellijad',
 'version-version' => '(Versioon $1)',
 'version-license' => 'Litsents',
-'version-poweredby-credits' => "See viki kasutab '''[//www.mediawiki.org/ MediaWiki]''' tarkvara. Autoriõigus © 2001–$1 $2.",
+'version-poweredby-credits' => "See viki kasutab '''[https://www.mediawiki.org/ MediaWiki]''' tarkvara. Autoriõigus © 2001–$1 $2.",
 'version-poweredby-others' => 'teised',
 'version-poweredby-translators' => 'translatewiki.net-i tõlkijad',
 'version-credits-summary' => 'Tahame tunnustada järgmisi inimesi [[Special:Version|MediaWikile]] tehtud kaastöö eest.',
@@ -3865,7 +3912,7 @@ GNU Üldise Avaliku Litsentsi [{{SERVER}}{{SCRIPTPATH}}/COPYING eksemplar] peaks
 # Special:Redirect
 'redirect' => 'Ümbersuunamine faili, kasutaja või redaktsiooni identifikaatori järgi',
 'redirect-legend' => 'Ümbersuunamine faili juurde või leheküljele',
-'redirect-summary' => 'See erilehekülg suunab ümber faili (toodud failinimi), lehekülje (toodud redaktsiooni identifikaator) või kasutajalehekülje (toodud numbriline kasutaja identfikaator) juurde.',
+'redirect-summary' => 'See erilehekülg suunab ümber faili (toodud failinimi), lehekülje (toodud redaktsiooni identifikaator) või kasutajalehekülje (toodud numbriline kasutaja identfikaator) juurde. Kasutamine: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] või [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Mine',
 'redirect-lookup' => 'Leia:',
 'redirect-value' => 'Väärtus:',
@@ -3887,10 +3934,8 @@ GNU Üldise Avaliku Litsentsi [{{SERVER}}{{SCRIPTPATH}}/COPYING eksemplar] peaks
 
 # Special:SpecialPages
 'specialpages' => 'Erileheküljed',
-'specialpages-note' => '----
-* Harilikud erileheküljed
-* <span class="mw-specialpagerestricted">Piiranguga erileheküljed</span>
-* <span class="mw-specialpagecached">Uuendamata sisuga erileheküljed (ei pruugi enam kasutuses olla)</span>',
+'specialpages-note' => '* Harilikud erileheküljed.
+* <span class="mw-specialpagerestricted">Piiranguga erileheküljed.</span>',
 'specialpages-group-maintenance' => 'Hooldusaruanded',
 'specialpages-group-other' => 'Teised erileheküljed',
 'specialpages-group-login' => 'Sisselogimine ja konto loomine',
@@ -4103,4 +4148,21 @@ Kui ei, kasuta allolevat lihtsat vormi. Sinu kommentaar lisatakse koos kasutajan
 'limitreport-expansiondepth' => 'Suurim hõrendussügavus',
 'limitreport-expensivefunctioncount' => 'Kulukate parserifunktsioonide arv',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Mallide hõrendamine',
+'expand_templates_intro' => 'See erilehekülg hõrendab siia sisestatud tekstis kõik mallid rekursiivselt.
+Samuti hõrendab see parserifunktsioonid nagu
+<code><nowiki>{{</nowiki>#language:…}}</code> ja muutujad nagu
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Õigupoolest hõrendab see kahekordsete looksulgude vahel pea kõike.',
+'expand_templates_title' => 'Sisu pealkiri, näiteks {{FULLPAGENAME}} jaoks:',
+'expand_templates_input' => 'Sisendtekst:',
+'expand_templates_output' => 'Tulemus',
+'expand_templates_xml_output' => 'XML-väljund',
+'expand_templates_ok' => 'Hõrenda',
+'expand_templates_remove_comments' => 'Eemalda selgitavad märkused',
+'expand_templates_remove_nowiki' => 'Ära näita tulemuses <nowiki>-silte',
+'expand_templates_generate_xml' => 'Näita XML sõelumispuud',
+'expand_templates_preview' => 'Eelvaade',
+
 );
index 7749d0d..0aae185 100644 (file)
@@ -55,14 +55,12 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'OrrialdeZaharrak' ),
        'Blankpage'                 => array( 'OrrialdeZuria' ),
        'Block'                     => array( 'Blokeatu' ),
-       'Blockme'                   => array( 'BlokeaNazazu' ),
        'BrokenRedirects'           => array( 'HautsitakoBirzuzenketak' ),
        'Categories'                => array( 'Kategoriak' ),
        'ChangePassword'            => array( 'PasahitzaAldatu' ),
        'Confirmemail'              => array( 'EmailaBaieztatu' ),
        'Contributions'             => array( 'Ekarpenak' ),
        'CreateAccount'             => array( 'KontuaSortu' ),
-       'Disambiguations'           => array( 'Argipenak' ),
        'DoubleRedirects'           => array( 'BirzuzenketaBikoitzak' ),
        'Emailuser'                 => array( 'LankideEmaila' ),
        'Export'                    => array( 'Esportatu' ),
@@ -133,12 +131,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Ezkutatu patruilatutako aldaketa azken aldaketetan',
 'tog-newpageshidepatrolled' => 'Ezkutatu patruilatutako orriak, orri-zerrenda berritik',
 'tog-extendwatchlist' => 'Jarraipen-zerrenda zabaldu aldaketa guztiak ikusteko, ez bakarrik azken aldaketak',
-'tog-usenewrc' => 'Azken aldaketetan eta jarraipen-zerrendan aldaketak orrialdearen arabera taldekatu (JavaScript behar da)',
+'tog-usenewrc' => 'Azken aldaketetan eta jarraipen-zerrendan aldaketak orrialdearen arabera taldekatu',
 'tog-numberheadings' => 'Goiburukoak automatikoki zenbakitu',
-'tog-showtoolbar' => 'Aldaketen tresna-barra erakutsi (JavaScript)',
-'tog-editondblclick' => 'Klik bikoitzaren bitartez orrialdeak aldatu (JavaScript)',
+'tog-showtoolbar' => 'Aldaketen tresna-barra erakutsi',
+'tog-editondblclick' => 'Klik bikoitzaren bitartez orrialdeak aldatu',
 'tog-editsection' => 'Atalak [aldatu] loturen bitartez aldatzeko aukera gaitu',
-'tog-editsectiononrightclick' => 'Atalen izenburuetan klik eginez atala<br />aldatzea gaitu (JavaScript)',
+'tog-editsectiononrightclick' => 'Atalen izenburuetan eskuin klik eginez aldatzea gaitu',
 'tog-showtoc' => 'Edukien taula erakutsi (3 goiburukotik gorako orrialdeentzako)',
 'tog-rememberpassword' => 'Nire saioa ordenagailu honetan gorde ({{PLURAL:$1|egun baterako| $1 egunerako}} gehienez)',
 'tog-watchcreations' => 'Sortzen ditudan orrialdeak eta fitxategiak nire jarraipen-zerrendara gehitu',
@@ -156,7 +154,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Jarraitzen duen erabiltzaile kopurua erakutsi',
 'tog-oldsig' => 'Egungo sinadura:',
 'tog-fancysig' => 'Sinadura wikitestu gisa tratatu (lotura automatikorik gabe)',
-'tog-uselivepreview' => 'Zuzeneko aurrebista erakutsi (JavaScript) (Proba fasean)',
+'tog-uselivepreview' => 'Zuzeneko aurrebista erakutsi (Proba fasean)',
 'tog-forceeditsummary' => 'Aldaketaren laburpena zuri uzterakoan ohartarazi',
 'tog-watchlisthideown' => 'Segimendu zerrendan nire aldaketak ezkutatu',
 'tog-watchlisthidebots' => 'Segimendu zerrendan bot-en aldaketak ezkutatu',
@@ -269,7 +267,7 @@ $messages = array(
 'newwindow' => '(leiho berrian irekitzen da)',
 'cancel' => 'Utzi',
 'moredotdotdot' => 'Gehiago...',
-'morenotlisted' => 'Zerrendatu gabeko gehiago...',
+'morenotlisted' => 'Zerrenda hau ez dago osorik.',
 'mypage' => 'Orrialdea',
 'mytalk' => 'Eztabaida',
 'anontalk' => 'IP honen eztabaida',
@@ -351,7 +349,7 @@ $messages = array(
 'viewhelppage' => 'Laguntza orrialdea ikusi',
 'categorypage' => 'Kategoria orrialdea ikusi',
 'viewtalkpage' => 'Eztabaida ikusi',
-'otherlanguages' => 'Beste hizkuntzetan',
+'otherlanguages' => 'Erdaretan',
 'redirectedfrom' => '($1(e)tik birzuzenduta)',
 'redirectpagesub' => 'Birzuzenketa orrialdea',
 'lastmodifiedat' => 'Orrialdearen azken aldaketa: $2, $1.',
@@ -372,7 +370,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}}(e)ri buruz',
 'aboutpage' => 'Project:Honi_buruz',
-'copyright' => 'Eduki guztia $1(r)en babespean dago.',
+'copyright' => 'Eduki guztia $1(r)en babespean dago, ez bada kontrakoa esaten.',
 'copyrightpage' => '{{ns:project}}:Eskubideak',
 'currentevents' => 'Albisteak',
 'currentevents-url' => 'Project:Albisteak',
@@ -398,8 +396,6 @@ $1',
 'ok' => 'Ados',
 'retrievedfrom' => '"$1"(e)tik jasota',
 'youhavenewmessages' => '$1 dauzkazu ($2).',
-'newmessageslink' => 'Mezu berriak',
-'newmessagesdifflink' => 'azken aldaketa ikusi',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Beste erabiltzaile baten|$3 erabiltzaileren}} $1 ($2).',
 'youhavenewmessagesmanyusers' => 'Hainbat erabiltzaileren $1 ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|Mezu berri bat duzu|Mezu berriak dituzu}}',
@@ -455,6 +451,10 @@ Existitzen direnen zerrenda ikus dezakezu  [[Special:SpecialPages|{{int:specialp
 # General errors
 'error' => 'Errorea',
 'databaseerror' => 'Datu-base errorea',
+'databaseerror-textcl' => 'Datubasearen eskera akats bat gertatu da.',
+'databaseerror-query' => 'Eskaera: $1',
+'databaseerror-function' => 'Funtzioa: $1',
+'databaseerror-error' => 'Akatsa: $1',
 'laggedslavemode' => 'Oharra: Baliteke orrialde honetan azken aldaketak ez erakustea.',
 'readonly' => 'Datu-basea blokeatuta dago',
 'enterlockreason' => 'Zehaztu blokeatzeko arrazoia, noiz kenduko den jakinaraziz',
@@ -488,6 +488,7 @@ Baliteke beste norbaitek ezabatu izana.',
 'cannotdelete-title' => 'Ezin da "$1" orrialdea ezabatu',
 'delete-hook-aborted' => 'Ezabatzea hook batek gelditu du.
 Ez du arrazoirik eman.',
+'no-null-revision' => 'Ezin izan da "$1" orrialdearen berrikuspen huts bat sortu',
 'badtitle' => 'Izenburu ezegokia',
 'badtitletext' => 'Eskatutako orrialde izenburua ez da baliozkoa, hutsik dago, edo gaizki lotutako hizkuntzen arteko lotura da. Baliteke izenburuetan erabili ezin den karaktereren bat izatea.',
 'perfcached' => 'Hurrengo datuak katxean gordeta daude eta litekeena da guztiz eguneratuta ez egotea. Gehienez {{PLURAL:$1|emaitza 1 dago|$1 emaitza daude}} eskuragarri katxean.',
@@ -516,6 +517,8 @@ $2",
 'customjsprotected' => 'Ez duzu baimenik JavaScript orrialde hau aldatzeko beste erabiltzaile baten hobespen pertsonalak dituelako.',
 'mycustomcssprotected' => 'Ez duzu baimenik CSS orrialde hau aldatzeko.',
 'mycustomjsprotected' => 'Ez duzu baimentik JavaScript orrialdea aldatzeko.',
+'myprivateinfoprotected' => 'Ez duzu eskumenik zure informazio pribatua aldatzeko.',
+'mypreferencesprotected' => 'Ez daukazu eskumenik zure hobespenak aldatzeko.',
 'ns-specialprotected' => 'Ezin dira {{ns:special}} izen-tarteko orrialdeak editatu.',
 'titleprotected' => "[[User:$1|$1]]ek izenburu hau sortzea ekidin zuen.
 Emandako arrazoia ''$2'' izan zen.",
@@ -535,8 +538,7 @@ Blokeoa ezarri zuen administratzaileak honako arrazoia eman zuen: "$3".',
 # Login and logout pages
 'logouttext' => "'''Saioa itxi egin duzu.'''
 
-Erabiltzaile anonimo bezala jarrai dezakezu {{SITENAME}} erabiltzen, edo <span class='plainlinks'>[$1 saioa has dezakezu berriz]</span> erabiltzaile berdinarekin edo ezberdin batekin.
-Kontuan izan orrialde batzuk saioa hasita bazenu bezala ikus ditzakezula nabigatzailearen katxea garbitu arte.",
+Jakin ezazu hainbat orrialdetan ager daitekela oraindik saioa ez duzula itxi, zure nabigatzailearen katxea garbitzen ez duzun arte.",
 'welcomeuser' => 'Ongi etorri, $1!',
 'welcomecreation-msg' => 'Zure kontua sortua izan da.
 Ez ezazu ahaztu zure [[Special:Preferences|{{SITENAME}} hobespenak]] aldatzea.',
@@ -573,15 +575,19 @@ Ez ezazu ahaztu zure [[Special:Preferences|{{SITENAME}} hobespenak]] aldatzea.',
 'gotaccount' => "Baduzu erabiltzaile kontua? '''$1'''.",
 'gotaccountlink' => 'Saioa hasi',
 'userlogin-resetlink' => 'Saioa hasteko datuak ahaztu dituzu?',
-'userlogin-resetpassword-link' => 'Zure pasahitza berrezarri',
+'userlogin-resetpassword-link' => 'Zure pasahitza ahaztu duzu?',
 'helplogin-url' => 'Help:Sarrera',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Barrura sartzeko laguntza]]',
+'userlogin-loggedin' => 'Dagoeneko izena emana zaude {{GENDER:$1|$1}}.
+Beheko formularioa erabil ezazu beste erabiltzaile baten izenean sartzeko.',
+'userlogin-createanother' => 'Beste kontu bat sortu',
 'createacct-join' => 'Sartu zure informazioa azpian.',
+'createacct-another-join' => 'Sartu kontu berriaren informazioa azpian.',
 'createacct-emailrequired' => 'E-posta helbidea',
 'createacct-emailoptional' => 'E-posta helbidea (hautazkoa)',
 'createacct-email-ph' => 'Sartu zure e-posta helbidea',
 'createacct-another-email-ph' => 'Posta elektronikoaren helbidea sartu',
-'createaccountmail' => 'Erabili behin-behineko pasahitz ausazko bat eta bidali behean agertzeko den e-posta helbidera',
+'createaccountmail' => 'Erabili behin-behineko pasahitz ausazko bat eta bidali agertzen den e-posta helbidera',
 'createacct-realname' => 'Benetako izena (hautazkoa)',
 'createaccountreason' => 'Arrazoia:',
 'createacct-reason' => 'Arrazoia',
@@ -634,14 +640,15 @@ eta aurretik zenuen pasahitza erabiltzen jarrai ezazu.',
 Mesedez, saioa hasi jasotakoan.',
 'blocked-mailpassword' => 'Zure IP helbidea aldaketak egiteko blokeatuta dago, eta beraz ezin da pasahitza berreskuratzeko aukera erabili.',
 'eauthentsent' => 'Egiaztapen mezu bat bidali da zehaztutako e-posta helbidera.
-Helbide horretara beste edozein mezu bidali aurretik, bertan azaltzen diren argibideak jarraitu behar dituzu, e-posta hori zurea dela egiaztatzeko.',
+Helbide horretara beste edozein mezu bidali aurretik, bertan azaltzen diren argibideak jarraitu behar dituzu, kontua zurea dela egiaztatzeko.',
 'throttled-mailpassword' => 'Pasahitz gogorarazle bat bidali da jada azken {{PLURAL:$1|orduan|$1 orduetan}}.
 Bandalismoa sahiesteko pasahitz eskaera bat baino ezin da egin {{PLURAL:$1|orduan|$1 orduan}} behin.',
 'mailerror' => 'Errorea mezua bidaltzerakoan: $1',
 'acct_creation_throttle_hit' => 'Sentitzen dugu, {{PLURAL:$1|erabiltzaile kontu bat sortu duzu|$1 erabiltzaile kontu sortu dituzu}} dagoeneko.
 Ondorioz, ezin duzu kontu gehiago sortu.',
 'emailauthenticated' => 'Zure e-posta helbidea autentifikatu da $2an $3(e)tan.',
-'emailnotauthenticated' => 'Zure posta helbidea egiaztatu gabe dago. Ez da mezurik bidaliko hurrengo ezaugarrientzako.',
+'emailnotauthenticated' => 'Zure posta helbidea egiaztatu gabe dago. 
+Ez da mezurik bidaliko hurrengo ezaugarrientzako.',
 'noemailprefs' => 'Zehaztu e-posta helbide bat ezaugarri hauek erabili ahal izateko.',
 'emailconfirmlink' => 'Egiaztatu zure e-posta helbidea',
 'invalidemailaddress' => 'Ezin da e-posta helbide hori ontzat eman baliogabeko formatua duela dirudielako.
@@ -658,10 +665,12 @@ Orain bertan sar zaitezke eta zure pasahitza aldatu.
 Kontu honen sorrera akats bat dela uste baduzu mezu honi ez diozu zertan jaramonik egin.',
 'usernamehasherror' => 'Erabiltzaile-izenak ezin du kuxin-karaktererik eduki',
 'login-throttled' => 'Saioa hasteko saiakera gehiegi egin berri dituzu.
-Berriro saiatu aurretik itxaron ezazu, mesedez.',
+Berriro saiatu aurretik $1 itxoin, mesedez.',
 'login-abort-generic' => 'Zure sarrera ez da arrakastatsua izan - Abortatua',
 'loginlanguagelabel' => 'Hizkuntza: $1',
 'suspicious-userlogout' => 'Saioa amaitzeko egin duzun eskaria ukatu da. Izan ere, ematen du eskari hori gaizki dabilen nabigatzaile edo cache proxy batek bidali duela.',
+'createacct-another-realname-tip' => 'Benetako izena hautazkoa da.
+Ematea erabakitzen baduzu hori erabiliko da lanaren atribuzioa egiterako garaian.',
 
 # Email sending
 'php-mail-error-unknown' => 'PHPren mail() funtzioan arazo ezezagun bat egon da.',
@@ -677,7 +686,7 @@ Berriro saiatu aurretik itxaron ezazu, mesedez.',
 'newpassword' => 'Pasahitz berria:',
 'retypenew' => 'Pasahitz berria berriz idatzi:',
 'resetpass_submit' => 'Pasahitza definitu eta saioa hasi',
-'changepassword-success' => 'Zure pasahitza aldatu egin da! Saioa hasten...',
+'changepassword-success' => 'Zure pasahitza ondo aldatu da!',
 'resetpass_forbidden' => 'Ezin dira pasahitzak aldatu',
 'resetpass-no-info' => 'Orrialde honetara zuzenean sartzeko izena eman behar duzu.',
 'resetpass-submit-loggedin' => 'Pasahitza aldatu',
@@ -703,6 +712,7 @@ Agian dagoeneko ondo aldatu duzu zure pasahitza edo behin-behineko pasahitza bat
 'passwordreset-emailelement' => 'Erabiltzaile izena: $1
 Behin-behineko pasahitza: $2',
 'passwordreset-emailsent' => 'Pasahitza berrezartzeko e-posta bidali da.',
+'passwordreset-emailsent-capture' => 'Pasahitza berrezartzeko e-posta bat bidali dizugu, behean erakusten dena.',
 
 # Special:ChangeEmail
 'changeemail' => 'Aldatu e-mail helbidea',
@@ -716,6 +726,16 @@ Behin-behineko pasahitza: $2',
 'changeemail-submit' => 'E-posta aldatu',
 'changeemail-cancel' => 'Utzi',
 
+# Special:ResetTokens
+'resettokens' => 'Tokenak berrezarri',
+'resettokens-no-tokens' => 'Ez dago tokenik berrezartzeko.',
+'resettokens-legend' => 'Tokenak berrezarri',
+'resettokens-tokens' => 'Tokenak:',
+'resettokens-token-label' => '$1 (oraingo balioa: $2)',
+'resettokens-watchlist-token' => '(Atom/RSS) jarioarentzako tokenak [[Special:Watchlist|jarraitzen dituzun orrialdeen aldaketetarako]]',
+'resettokens-done' => 'Tokenak berrezarrita.',
+'resettokens-resetbutton' => 'Hautatutako tokenak berrezarri',
+
 # Edit page toolbar
 'bold_sample' => 'Letra lodiko testua',
 'bold_tip' => 'Letra lodiko testua',
@@ -741,7 +761,7 @@ Behin-behineko pasahitza: $2',
 'subject' => 'Izenburua:',
 'minoredit' => 'Hau aldaketa txikia da',
 'watchthis' => 'Orrialde hau jarraitu',
-'savearticle' => 'Gorde orrialdea',
+'savearticle' => 'Gorde orria',
 'preview' => 'Aurrebista erakutsi',
 'showpreview' => 'Aurrebista erakutsi',
 'showlivepreview' => 'Zuzeneko aurrebista',
@@ -794,7 +814,7 @@ Baliteke orrialdea begiratzen zenuen bitartean norbaitek ezabatu edo izenburua a
 'accmailtitle' => 'Pasahitza bidali da.',
 'accmailtext' => "[[User talk:$1|$1]]-entzako ausaz sortutako pasahitza $2-(r)a bidali da.
 
-Kontu berri honentzako pasahitza edozein unetan alda daiteke ''[[Special:ChangePassword|pasahitz aldaketa]]'' orrian, saioa hasi ondoren.",
+''[[Special:ChangePassword|pasahitz aldaketa]]'' orrialdean alda daiteke, behin barruan sartuta.",
 'newarticle' => '(Berria)',
 'newarticletext' => "Orrialde hau ez da existitzen oraindik. Orrialde sortu nahi baduzu, beheko koadroan idazten hasi zaitezke (ikus [[{{MediaWiki:Helppage}}|laguntza orrialdea]] informazio gehiagorako). Hona nahi gabe etorri bazara, nabigatzaileko '''atzera''' botoian klik egin.",
 'anontalkpagetext' => "----''Orrialde hau konturik sortu ez edo erabiltzen ez duen erabiltzaile anonimo baten eztabaida orria da.
@@ -842,6 +862,7 @@ Zure aldaketak ez dira oraindik gorde!",
 'token_suffix_mismatch' => "'''Zure aldaketa ezeztatua izan da zure bezeroak puntuazio-karaktereak itxuragabetu dituelako.
 Aldaketa ezeztatua izan da testuaren galtzea galarazteko.
 Hau batzuetan gertatzen da buggyan oinarritutako web proxy zerbitzua erabiltzean.'''",
+'edit_form_incomplete' => "'''Aldaketa formularioaren atal batzuk ez dira iritsi zerbitzarira; bi aldiz ziurtatu zure aldaketak osorik daudela eta berriro saiatu.'''",
 'editing' => '$1 aldatzen',
 'creating' => '$1 sortzen',
 'editingsection' => '$1 aldatzen (atala)',
@@ -1069,6 +1090,7 @@ Ezin duzu atzitu.',
 'revdelete-no-change' => "'''Abisua:''' $1 $2 data duen elementuak jadanik bazituen eskatutako ikusgaitasun ezarpenak.",
 'revdelete-concurrent-change' => 'Errorea, $1 $2 data duen elementua aldatzean: badirudi haren egoera aldatu duela nor edo nork, zu aldatzen saiatzen ari zinela.
 Begira itzazu erregistroak.',
+'revdelete-only-restricted' => '$2 data duen $1 elementua ezkutatzen arazoa: ezin dira kendu adminstratzaileen ikuskaritzatik elementuak ez badago beste ikusgarritasun aukerarik hautatua.',
 'revdelete-reason-dropdown' => '*Ezabatzeko ohiko arrazoiak
 ** Egile eskubideak urratzea
 ** Informazio pertsonal edo iruzkin desegokia
@@ -1117,13 +1139,14 @@ Kontura zaitez nabigazio loturek, zutabea ezabatu dezakela.',
 
 # Diffs
 'history-title' => '"$1" orrialdearen historia berrikuspena',
-'difference-title' => '"$1"-en berrikuspenen arteko aldaketa',
+'difference-title' => '«$1»: berrikuspenen arteko aldeak',
 'difference-title-multipage' => '"$1" eta "$2" orrialdeen arteko ezberditasunak',
 'difference-multipage' => '(Orrialdeen arteko ezberdintasunak)',
 'lineno' => '$1. lerroa:',
 'compareselectedversions' => 'Hautatutako bertsioak alderatu',
 'showhideselectedversions' => 'Erakutsi/ezkutatu aukeratutako berrikuspenak',
 'editundo' => 'desegin',
+'diff-empty' => '(Ez dago alderik)',
 'diff-multi' => '({{PLURAL:$1|Ez da tarteko berrikuspen bat|Ez dira tarteko $1 berrikuspen}} erakusten {{PLURAL:$2|lankide batena|$2 lankiderena}}.)',
 
 # Search results
@@ -1192,8 +1215,6 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 'preferences' => 'Hobespenak',
 'mypreferences' => 'Hobespenak',
 'prefs-edits' => 'Aldaketa kopurua:',
-'prefsnologin' => 'Saioa hasi gabe',
-'prefsnologintext' => '<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Izena eman]</span> behar duzu zure hobespenak ezartzeko.',
 'changepassword' => 'Pasahitza aldatu',
 'prefs-skin' => 'Itxura',
 'skin-preview' => 'Aurrebista',
@@ -1218,7 +1239,7 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 'prefs-rendering' => 'Itxura',
 'saveprefs' => 'Gorde',
 'resetprefs' => 'Hasieratu',
-'restoreprefs' => 'Konfigurazio lehenetsi guztiak berrezarri',
+'restoreprefs' => 'Konfigurazio lehenetsi guztiak berrezarri (sekzio guztietan)',
 'prefs-editing' => 'Aldatzen',
 'rows' => 'Lerroak:',
 'columns' => 'Zutabeak:',
@@ -1271,11 +1292,13 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 'badsig' => 'Baliogabeko sinadura; egiaztatu HTML etiketak.',
 'badsiglength' => 'Zure sinadura luzeegia da.
 $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
-'yourgender' => 'Generoa:',
-'gender-unknown' => 'Zehaztugabea',
-'gender-male' => 'Gizona',
-'gender-female' => 'Emakumea',
-'prefs-help-gender' => 'Hautazkoa: softwareak generoa zehazteko erabilia. Informazio hau publikoa da.',
+'yourgender' => 'Nola nahiagu duzu deskribatua izatea?',
+'gender-unknown' => 'Nahiago dut ez esatea',
+'gender-male' => 'Wiki orrialdeak editatzen dituen gizona',
+'gender-female' => 'Wiki orrialdeak editatzen dituen emakumea',
+'prefs-help-gender' => 'Hobespen hau jartzea aukerazkoa da.
+Softwareak bere balioak erabiltzen ditu zu aipatzeko eta beste batzuek genero gramatikala erabiltzeko aukera izan dezaten.
+Informazio hau publikoa da.',
 'email' => 'E-posta',
 'prefs-help-realname' => '* Benetako izena (aukerakoa): zehaztea erabakiz gero, zure lanarentzako atribuzio bezala balioko du.',
 'prefs-help-email' => 'E-posta helbidea aukerakoa da, baina zure pasahitza ahaztekotan berriro zure e-postara bidaltzeko aukera ematen dizu.',
@@ -1286,7 +1309,9 @@ $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
 'prefs-signature' => 'Sinadura',
 'prefs-dateformat' => 'Data-formatua',
 'prefs-timeoffset' => 'Denbora ezberdintasuna',
-'prefs-advancedediting' => 'Aukera aurreratuak',
+'prefs-advancedediting' => 'Genero aukerak',
+'prefs-editor' => 'Editorea',
+'prefs-preview' => 'Aurreikusi',
 'prefs-advancedrc' => 'Aukera aurreratuak',
 'prefs-advancedrendering' => 'Aukera aurreratuak',
 'prefs-advancedsearchoptions' => 'Aukera aurreratuak',
@@ -1295,6 +1320,7 @@ $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
 'prefs-displaysearchoptions' => 'Aukerak erakutsi',
 'prefs-displaywatchlist' => 'Aukerak erakutsi',
 'prefs-diffs' => 'Ezberdintasunak',
+'prefs-help-prefershttps' => 'Hobespen hauek eragina izango dute sartzen zaren hurrengoan.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'E-posta helbidea zuzena dela dirudi',
@@ -1453,9 +1479,15 @@ $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
 'action-userrights-interwiki' => 'beste wikietako lankideen lankide-eskumenak aldatu',
 'action-siteadmin' => 'datubasea babestu edo babesa kendu',
 'action-sendemail' => 'E-mailak bidali',
+'action-editmywatchlist' => 'zure jarraipn zerrenda aldatu',
+'action-viewmywatchlist' => 'zure jarraipen zerrenda ikusi',
+'action-viewmyprivateinfo' => 'zure informazio pribatua ikusi',
+'action-editmyprivateinfo' => 'zure informazio pribatua aldatu',
 
 # Recent changes
 'nchanges' => '{{PLURAL:$1|aldaketa 1|$1 aldaketa}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|azkeneko bisitatik}}',
+'enhancedrc-history' => 'historia',
 'recentchanges' => 'Aldaketa berriak',
 'recentchanges-legend' => 'Azken aldaketen aukerak',
 'recentchanges-summary' => 'Orri honetan ikuska ditzakezu wiki honetan egindako azken aldaketak.',
@@ -1464,6 +1496,7 @@ $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
 'recentchanges-label-minor' => 'Hau aldaketa txikia da',
 'recentchanges-label-bot' => 'Aldaketa hau bot batek egin du',
 'recentchanges-label-unpatrolled' => 'Aldaketa hau ez da oraindik patruilatua izan',
+'recentchanges-legend-newpage' => '$1 - orrialde berria',
 'rcnote' => "Beheko azken {{PLURAL:$2|eguneko|'''$2''' egunetako}} azken {{PLURAL:$1|aldaketa|'''$1''' aldaketak}} hurrengo datan egin ziren: $5, $4.",
 'rcnotefrom' => 'Jarraian azaltzen diren aldaketak data honetatik aurrerakoak dira: <b>$2</b> (gehienez <b>$1</b> erakusten dira).',
 'rclistfrom' => 'Erakutsi $1 ondorengo aldaketa berriak',
@@ -1486,7 +1519,7 @@ $1 {{PLURAL:$1|karakteretik|karakteretik}} behera izan behar ditu.',
 'rc_categories_any' => 'Edozein',
 'rc-change-size-new' => '{{PLURAL:$1|Byte 1|$1 byte}} aldaketaren ostean',
 'newsectionsummary' => '/* $1 */ atal berria',
-'rc-enhanced-expand' => 'Erakutsi xehetasunak (JavaScript beharrezkoa da)',
+'rc-enhanced-expand' => 'Erakutsi xehetasunak',
 'rc-enhanced-hide' => 'Xehetasunak ezkutatu',
 'rc-old-title' => 'hasiera batean "$1" gisa sortua',
 
@@ -1616,6 +1649,7 @@ $1',
 'upload-too-many-redirects' => 'URLak birzuzenketa gehiegi zituen',
 'upload-unknown-size' => 'Tamaina ezezaguna',
 'upload-http-error' => 'HTTP errorea gertatu da: $1',
+'upload-copy-upload-invalid-domain' => 'Domeinu honetan ezin dira igoerak kopiatu.',
 
 # File backend
 'backend-fail-stream' => 'Ezin izan da "$1" fitxategiaren stream egin.',
@@ -1625,6 +1659,7 @@ $1',
 'backend-fail-notsame' => 'Berdina ez den beste fitxategi bat dago "$1"n',
 'backend-fail-invalidpath' => '"$1" ez da gordetzeko helbide baliagarria.',
 'backend-fail-delete' => 'Ezin izan da ezabatu "$1" fitxategia.',
+'backend-fail-describe' => 'Ezin dira "$1" fitxategiaren metadatuak aldatu.',
 'backend-fail-alreadyexists' => '"$1" fitxategia jadanik badago.',
 'backend-fail-store' => 'Ezin izan da gorde "$1" fitxategia "$2" helbidean.',
 'backend-fail-copy' => 'Ezin izan da kopiatu "$1" fitxategia "$2" helbidean.',
@@ -1635,15 +1670,27 @@ $1',
 'backend-fail-read' => 'Ezin izan da "$1" fitxategia irakurri.',
 'backend-fail-create' => 'Ezin izan da "$1" fitxategia idatzi.',
 'backend-fail-maxsize' => 'Ezin izan da idatzi "$1" fitxategia {{PLURAL:$2|byte bat|$2 byte}} baino handiagoa delako.',
+'backend-fail-connect' => 'Ezin izan da "$1" gordailuaren atzeko aldearekin konektatu.',
+'backend-fail-internal' => 'Akats ezezaguna gertatu da "$1" gordailuaren atzeko aldean.',
 
 # Lock manager
 'lockmanager-notlocked' => 'Ezin izan da "$1" askatu; ez dago itxita.',
 'lockmanager-fail-closelock' => 'Ezin izan da "$1" fitxategiaren giltza itxi.',
+'lockmanager-fail-deletelock' => 'Ezin izan da "$1" fitxategia desblokeatu.',
+'lockmanager-fail-acquirelock' => 'Ezin izan da "$1" blokeoa eskuratu.',
+'lockmanager-fail-openlock' => 'Ezin izan da "$1" blokeo fitxategia ireki.',
+'lockmanager-fail-releaselock' => 'Ezin izan da "$1" blokeoa askatu.',
+'lockmanager-fail-db-bucket' => 'Ezin izan dut $1 buketean datubase nahikoa ziurtatu.',
+'lockmanager-fail-db-release' => 'Ezin izan da $1 datubasean giltzaraporik askatu.',
 
 # ZipDirectoryReader
 'zip-wrong-format' => 'Zehaztutako fitxategia ez zen ZIP motakoa.',
 
 # Special:UploadStash
+'uploadstash' => 'Gordailu bat igo',
+'uploadstash-clear' => 'Kodetutako fitxategiak izkutatu',
+'uploadstash-nofiles' => 'Ez duzu kodetutako fitxategirik.',
+'uploadstash-errclear' => 'Fitxategiak ezabatzeak ez du arrakastarik izan.',
 'uploadstash-refresh' => 'Fitxategien zerrenda eguneratu',
 
 # img_auth script messages
@@ -1783,6 +1830,9 @@ Bere [$2 fitxategiaren deskribapen orrialdea] behean dago.',
 'randompage' => 'Ausazko orria',
 'randompage-nopages' => 'Ez dago orrialderik honako {{PLURAL:$2|kategorian|kategoriatan}}: $1',
 
+# Random page in category
+'randomincategory-selectcategory-submit' => 'Joan',
+
 # Random redirect
 'randomredirect' => 'Ausazko birzuzenketa',
 'randomredirect-nopages' => 'Ez dago birzuzenketarik "$1" izen-tartean.',
@@ -2010,6 +2060,7 @@ Badago [[{{MediaWiki:Listgrouprights-helppage}}|informazio osagarria]] banakako
 'noemailtext' => 'Erabiltzaile honek ez du baliozko e-posta helbiderik zehaztu.',
 'nowikiemailtitle' => 'Ezin da e-postarik bidali',
 'nowikiemailtext' => 'Erabiltzaile honek beste erabiltzaileengandik e-postak ez jasotzea hautatu du.',
+'emailnotarget' => 'Jasotzailearentzat lankide izen ez-egokia edo ezezaguna.',
 'emailtarget' => 'Sartu jasolearen erabiltzaile izena',
 'emailusername' => 'Lankide izena:',
 'emailusernamesubmit' => 'Bidali',
@@ -2237,11 +2288,8 @@ Aukeratutako leheneratze bat burutzeko, leheneratu nahi dituzun berrikuspenen ko
 'undeleterevisions' => '$1 {{PLURAL:$1|berrikuspen|berrikuspen}} artxibatuta',
 'undeletehistory' => 'Orrialdea leheneratzen baduzu, berrikuspena guztiak leheneratuko dira historian.
 Ezabatu ondoren izen berdina duen orrialde berri bat sortzen bada leheneratutako berrikuspenak azalduko dira historian.',
-'undeleterevdel' => 'Berrezarpena ez da egingo goreneko orrialde edo fitxategia partzialki ezabatua suertatzen bada.
-Kasu horietan ezabatutako azken aldaketen aukeraketa kendu edo agertarazi beharko dituzu.
-
-Undeletion will not be performed if it will result in the top page or file revision being partially deleted.
-In such cases, you must uncheck or unhide the newest deleted revision.',
+'undeleterevdel' => 'Desezabatzea ez da egingo, baldin horren ondorioz goreneko orria edo fitxategia partzialki ezabatuko bada.
+Halakoetan, ezabatutako azken aldaketak desaukeratu edo atzera agerrarazi beharko dituzu.',
 'undeletehistorynoadmin' => 'Artikulua ezabatu egin da. Ezabatzeko azalpena beheko laburpenean erakusten da, ezabatu aurretik parte hartu zuten erabiltzaileen xehetasunekin batera. Ezabatutako berrikuspenen oraingo testua administratzaileek bakarrik ikus dezakete.',
 'undelete-revision' => '$1(e)n berrikuspen $3(e)k ezabatu du ($4(e)ko $5(e)tan):',
 'undeleterevision-missing' => 'Baliogabeko berrikuspena. Baliteke lotura ezegokia izatea, edo berriskupena leheneratu edo kendu izana.',
@@ -2250,7 +2298,7 @@ In such cases, you must uncheck or unhide the newest deleted revision.',
 'undeletelink' => 'ikusi/leheneratu',
 'undeleteviewlink' => 'ikusi',
 'undeletereset' => 'Hasieratu',
-'undeleteinvert' => 'Aukeraketa alderanztu',
+'undeleteinvert' => 'Alderanztu aukera',
 'undeletecomment' => 'Arrazoia:',
 'undeletedrevisions' => '{{PLURAL:$1|Berrikuspen 1 leheneratu da|$1 berrikuspen leheneratu dira}}',
 'undeletedrevisions-files' => '{{PLURAL:$1|berrikuspen|berrikuspen}} eta {{PLURAL:$2|fitxategi|fitxategi}} leheneratu dira',
@@ -2288,7 +2336,7 @@ $1',
 'contributions' => '{{GENDER:$1|Lankidearen}} ekarpenak',
 'contributions-title' => '$1(r)entzat lankidearen ekarpenak',
 'mycontris' => 'Ekarpenak',
-'contribsub2' => '$1 ($2)',
+'contribsub2' => '{{GENDER:$3|$1(r)entzat}} ($2)',
 'nocontribs' => 'Ez da ezaugarri horiekin bat datorren aldaketarik aurkitu.',
 'uctop' => '(azken aldaketa)',
 'month' => 'Hilabetea (eta lehenagokoak):',
@@ -2551,6 +2599,7 @@ Horrez gain, lotura zuzena ere erabil dezakezu; adibidez, [[{{#Special:Export}}/
 'exportcuronly' => 'Oraingo berrikuspena bakarrik hartu, ez historia guztia',
 'exportnohistory' => "----
 '''Oharra:''' Formulario honen bitartez orrialdeen historia osoak esportatzeko aukera ezgaitu egin da, errendimendua dela-eta.",
+'exportlistauthors' => 'Orrialde bakoitzaren lankideen zerrenda osoa sartu',
 'export-submit' => 'Esportatu',
 'export-addcattext' => 'Orrialdeak gehitu kategoria honetatik:',
 'export-addcat' => 'Gehitu',
@@ -2566,7 +2615,7 @@ Horrez gain, lotura zuzena ere erabil dezakezu; adibidez, [[{{#Special:Export}}/
 'allmessagesdefault' => 'Testu lehenetsia',
 'allmessagescurrent' => 'Oraingo testua',
 'allmessagestext' => 'MediaWikin erabiltzen diren mezu guztien zerrenda.
-Mesedez bisitatu [//www.mediawiki.org/wiki/Localisation MediaWiki] eta [//translatewiki.net translatewiki.net] orrialdeak MediaWikira ekarpenak egin badituzu.',
+Mesedez bisitatu [https://www.mediawiki.org/wiki/Localisation MediaWiki] eta [//translatewiki.net translatewiki.net] orrialdeak MediaWikira ekarpenak egin badituzu.',
 'allmessagesnotsupportedDB' => "Ezin da '''{{ns:special}}:Allmessages''' erabili '''\$wgUseDatabaseMessages''' ezgaituta dagoelako.",
 'allmessages-filter-legend' => 'Iragazi',
 'allmessages-filter' => 'Aldaketa-egoeraren arabera iragazi:',
@@ -2583,6 +2632,7 @@ Mesedez bisitatu [//www.mediawiki.org/wiki/Localisation MediaWiki] eta [//transl
 'thumbnail_error' => 'Errorea irudi txikia sortzerakoan: $1',
 'djvu_page_error' => 'DjVu orrialdea eremuz kanpo',
 'djvu_no_xml' => 'Ezinezkoa izan da DjVu fitxategiaren XML lortzea',
+'thumbnail-temp-create' => 'Ezin izan da behin-behineko iruditxoa sortu',
 'thumbnail-dest-create' => 'Ezin izan da iruditxoa gorde helburuan',
 'thumbnail_invalid_params' => 'Irudi txikiaren ezarpenak ez dira baliagarriak',
 'thumbnail_dest_directory' => 'Ezinezkoa izan da helburu direktorioa sortu',
@@ -2628,6 +2678,8 @@ Fitxategiaren atal bat baino ez zen igo.',
 'import-upload' => 'Igo XML datuak',
 'import-token-mismatch' => 'Sesio data galdu da. Saia saitez berriro ere, mesedez.',
 'import-invalid-interwiki' => 'Ezin da esandako wikitik inportatu.',
+'import-rootpage-invalid' => 'Emandako jatorri orrialdea izenburu ez-baliagarria da.',
+'import-rootpage-nosubpage' => 'Jatorri orrialdearen "$1" izen-tarteak ez du baimentzen azpi-orrialderik.',
 
 # Import log
 'importlogpage' => 'Inportazio erregistroa',
@@ -2640,6 +2692,12 @@ Fitxategiaren atal bat baino ez zen igo.',
 # JavaScriptTest
 'javascripttest' => 'JavaScript frogatzen',
 'javascripttest-title' => '$1 frogak egiten',
+'javascripttest-pagetext-noframework' => 'Orrialde hau JavaScript frogak egiteko gordeta dago.',
+'javascripttest-pagetext-unknownframework' => 'Froga eremu ez-ezaguna "$1".',
+'javascripttest-pagetext-frameworks' => 'Mesedez, aukera ezazu froga eremu hauetako bat: $1',
+'javascripttest-pagetext-skins' => 'Aukeratu frogak egiteko itxura bat:',
+'javascripttest-qunit-intro' => 'Ikusi [$1 frogen dokumentazioa] mediawiki.org orrialdean.',
+'javascripttest-qunit-heading' => 'MediWiki JavaScript QUnit froga taldea',
 
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'Nire lankide orria',
@@ -2741,6 +2799,9 @@ Baliteke zerrenda beltzean dagoen kanpo lotura batek sortzea arazo hori.',
 'spambot_username' => 'MediaWikiren spam garbiketa',
 'spam_reverting' => '$1(e)rako loturarik ez daukan azken bertsiora itzultzen',
 'spam_blanking' => 'Berrikuspen guztiek $1(e)rako lotura zeukaten, husten',
+'spam_deleting' => '$1(e)ra loturak dituzten errebisio guztiak ezabatzen',
+'simpleantispam-label' => "Anti-spam egiaztapena.
+Atal hau '''EZ''' bete!",
 
 # Info page
 'pageinfo-title' => '"$1"(r)entzako informazioa',
@@ -2754,14 +2815,15 @@ Baliteke zerrenda beltzean dagoen kanpo lotura batek sortzea arazo hori.',
 'pageinfo-length' => 'Orriaren neurria (byteak)',
 'pageinfo-article-id' => 'Orriaren identifikazio zenbakia',
 'pageinfo-language' => 'Orriaren edukiaren hizkuntza',
-'pageinfo-robot-policy' => 'Bilaketa motorraren egoera',
-'pageinfo-robot-index' => 'Indexagarria',
-'pageinfo-robot-noindex' => 'Indexaezina',
+'pageinfo-robot-policy' => 'Errobotak indexatzea egiten',
+'pageinfo-robot-index' => 'Baimendua',
+'pageinfo-robot-noindex' => 'Debekatua',
 'pageinfo-views' => 'Bistaratze-kopurua',
 'pageinfo-watchers' => 'Orriaren jarraitzaileen kopurua',
 'pageinfo-few-watchers' => '{{PLURAL:$1|Ikusle bat|$1 ikusle}} baino gutxiago',
 'pageinfo-redirects-name' => 'Orri honetara dakarten birzuzenketak',
 'pageinfo-subpages-name' => 'Orri honen azpiorriak',
+'pageinfo-subpages-value' => '$1 ({{PLURAL:$2|birzuzenketa $2|$2 birzuzenketa}}; {{PLURAL:$3|ez-birzuzenketa $3|$3 ez-birzuzenketa}}',
 'pageinfo-firstuser' => 'Orriaren sortzailea',
 'pageinfo-firsttime' => 'Orriaren sortze data',
 'pageinfo-lastuser' => 'Azken editorea',
@@ -2770,6 +2832,7 @@ Baliteke zerrenda beltzean dagoen kanpo lotura batek sortzea arazo hori.',
 'pageinfo-authors' => 'Egile kopurua, guztira',
 'pageinfo-recent-edits' => 'Oraintsuko edizioen kopurua (azken $1)',
 'pageinfo-recent-authors' => 'Oraintsuko egileen kopurua',
+'pageinfo-magic-words' => 'Hitz {{PLURAL:$1|magikoa|magikoak}} ($1)',
 'pageinfo-hidden-categories' => 'Ezkutuko {{PLURAL:$1|kategoria|kategoriak}} ($1)',
 'pageinfo-templates' => 'Txertatutako {{PLURAL:$1|txantiloia|txantiloiak}} ($1)',
 'pageinfo-toolboxlink' => 'Orri honen datuak',
@@ -3045,6 +3108,7 @@ Zerrenda elementuak (hasieran * duten lerroak) baino ez dira kontuan hartzen. Le
 'exif-source' => 'Jatorria',
 'exif-editstatus' => 'Irudiaren egoera editoriala',
 'exif-urgency' => 'Larrialdia',
+'exif-fixtureidentifier' => 'Konpontzearen izena',
 'exif-locationdest' => 'Agertzen den lekua',
 'exif-locationdestcode' => 'Agertzen den lekuaren kodea',
 'exif-objectcycle' => 'Media hau baliagarria den egunaren ordua',
@@ -3056,11 +3120,14 @@ Zerrenda elementuak (hasieran * duten lerroak) baino ez dira kontuan hartzen. Le
 'exif-iimsupplementalcategory' => 'Kategoria gehigarriak',
 'exif-datetimeexpires' => 'Ez erabili data hau pasata:',
 'exif-datetimereleased' => 'Ekoizpen data:',
+'exif-originaltransmissionref' => 'Trasmisio originalaren kokapen kodea',
 'exif-identifier' => 'Identifikatzailea',
 'exif-lens' => 'Erabilitako lentea',
 'exif-serialnumber' => 'Kameraren serie-zenbakia',
 'exif-cameraownername' => 'Kameraren jabea',
 'exif-label' => 'Etiketa',
+'exif-datetimemetadata' => 'Datuaren metadata azken aldiz aldatu da',
+'exif-nickname' => 'Irudiaren izen ez-formala',
 'exif-rating' => 'Balorazioa (5 arte)',
 'exif-rightscertificate' => 'Eskubideen kudeaketa ziurtagiria',
 'exif-copyrighted' => 'Copyright egoera',
@@ -3087,10 +3154,13 @@ Zerrenda elementuak (hasieran * duten lerroak) baino ez dira kontuan hartzen. Le
 
 # Exif attributes
 'exif-compression-1' => 'Konprimatu gabe',
+'exif-compression-2' => 'CCITT Group 3 1-Dimensional Modified Huffman kodetzea abiatu da',
+'exif-compression-3' => 'CCITT Group 3 fax kodetzea',
+'exif-compression-4' => 'CCITT Group 4 fax kodetzea',
 'exif-compression-6' => 'JPEG',
 
 'exif-copyrighted-true' => 'Copyrightduna',
-'exif-copyrighted-false' => 'Domeinu askea',
+'exif-copyrighted-false' => 'Copyright egoera ez da ezarri',
 
 'exif-photometricinterpretation-2' => 'GBU (RGB)',
 'exif-photometricinterpretation-6' => 'YCbCr',
@@ -3273,8 +3343,10 @@ Zerrenda elementuak (hasieran * duten lerroak) baino ez dira kontuan hartzen. Le
 'exif-gpsdirection-m' => 'Norabide magnetikoa',
 
 'exif-ycbcrpositioning-1' => 'Zentratua',
+'exif-ycbcrpositioning-2' => 'Gune partekatua',
 
 'exif-dc-contributor' => 'Egileak',
+'exif-dc-coverage' => 'Media honen denbora- edo leku-esparrua',
 'exif-dc-date' => 'Data(k)',
 'exif-dc-publisher' => 'Argitaratzailea',
 'exif-dc-relation' => 'Harremana duen media',
@@ -3311,7 +3383,7 @@ Zerrenda elementuak (hasieran * duten lerroak) baino ez dira kontuan hartzen. Le
 
 # External editor support
 'edit-externally' => 'Fitxategi hau editatu kanpo-aplikazio bat erabiliz',
-'edit-externally-help' => '(Ikus [//www.mediawiki.org/wiki/Manual:External_editors konfiguraziorako argibideak] informazio gehiagorako)',
+'edit-externally-help' => '(Ikus [https://www.mediawiki.org/wiki/Manual:External_editors konfiguraziorako argibideak] informazio gehiagorako)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'guztiak',
@@ -3455,7 +3527,7 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 'version-hook-subscribedby' => 'Hauen harpidetzarekin',
 'version-version' => '(Bertsioa $1)',
 'version-license' => 'Lizentzia',
-'version-poweredby-credits' => "Wiki hau '''[//www.mediawiki.org/ MediaWiki]'''k sustatzen du (copyright © 2001-$1 $2).",
+'version-poweredby-credits' => "Wiki hau '''[https://www.mediawiki.org/ MediaWiki]'''k sustatzen du (copyright © 2001-$1 $2).",
 'version-poweredby-others' => 'beste batzuk',
 'version-software' => 'Instalatutako softwarea',
 'version-software-product' => 'Produktua',
@@ -3484,11 +3556,11 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 'fileduplicatesearch-info' => '$1 × $2 pixel<br />Fitxategiaren tamaina: $3<br />MIME mota: $4',
 'fileduplicatesearch-result-1' => '"$1" fitxategiak ez du duplikazio zehazki berdinik.',
 'fileduplicatesearch-result-n' => '"$1" fitxategiak {{PLURAL:$2|kopia zehatz bakarra du|$2 kopia zehatz ditu}}.',
+'fileduplicatesearch-noresults' => 'Ez da aurkitu "$1" izeneko fitxategirik.',
 
 # Special:SpecialPages
 'specialpages' => 'Orri bereziak',
-'specialpages-note' => '----
-* Orri berezi arruntak.
+'specialpages-note' => '* Orri berezi arruntak.
 * <strong class="mw-specialpagerestricted">Mugatutako orri bereziak.</strong>',
 'specialpages-group-maintenance' => 'Mantentze-oharrak',
 'specialpages-group-other' => 'Beste orri berezi batzuk',
@@ -3538,6 +3610,9 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 'compare-rev1' => '1. berrikuspena',
 'compare-rev2' => '2. berrikuspena',
 'compare-submit' => 'Alderatu',
+'compare-invalid-title' => 'Zehaztutako izenburua ez dago zuzen.',
+'compare-title-not-exists' => 'Zehazturiko izenburua ez da existitzen.',
+'compare-revision-not-exists' => 'Zehazturiko berrikuspena ez da existitzen.',
 
 # Database error messages
 'dberr-header' => 'Wiki honek arazo bat du',
@@ -3565,6 +3640,7 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 
 # SQLite database support
 'sqlite-has-fts' => '$1 testu osoan bilatzeko laguntzarekin',
+'sqlite-no-fts' => '$1 testu osoan bilatzeko laguntzarik gabe',
 
 # New logging system
 'logentry-delete-delete' => '$1 wikilariak $3 orria {{GENDER:$2|ezabatu}} du',
@@ -3596,7 +3672,9 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 'feedback-message' => 'Mezua:',
 'feedback-cancel' => 'Utzi',
 'feedback-submit' => 'Feedbacka bidali',
+'feedback-error1' => 'Akatsa: APIaren emaitza ez ezagunak',
 'feedback-error2' => 'Akatsa: Aldaketa ez da egin',
+'feedback-error3' => 'Akatsa: APIaren erantzunik gabe',
 'feedback-close' => 'Egina',
 'feedback-bugnew' => 'Txekeatu dut. Bug berria bidaliko',
 
@@ -3607,11 +3685,25 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 # API errors
 'api-error-badaccess-groups' => 'Ez duzu baimendik fitxategi hauek wiki honetara igotzeko.',
 'api-error-badtoken' => 'Barne akatsa: token okerra.',
+'api-error-empty-file' => 'Bidali duzun fitxategia hutsik dago.',
+'api-error-emptypage' => 'Berria sortzerako garaian orrialde hutsak ezin dira erabili.',
+'api-error-fetchfileerror' => 'Barne akatsa: zerbait gaizki joan da fitxategia eskuratzerakoan.',
+'api-error-file-too-large' => 'Bidali duzun fitxategia handiegia zen.',
 'api-error-filename-tooshort' => 'Fitxategiaren izena laburregia da.',
 'api-error-filetype-banned' => 'Mota horretako fitxategiak debekatuta daude.',
+'api-error-filetype-missing' => 'Fitxategiak ez zuen luzapenik.',
 'api-error-illegal-filename' => 'Fitxategiaren izena ez da onartzen.',
+'api-error-mustbeloggedin' => 'Fitxategiak igotzeko izena emanda eduki behar duzu.',
+'api-error-mustbeposted' => 'Barne arazoa: HTTP POST beharrezkoa da.',
+'api-error-noimageinfo' => 'Igoera ondo egin da, baina zerbitzariak ez digu informaziorik eman zerbitzariaren inguruan.',
+'api-error-nomodule' => 'Barne arazoa: igoera modulurik ez dago.',
+'api-error-ok-but-empty' => 'Barne arazoa: zerbitzariaren erantzunik ez.',
+'api-error-overwrite' => 'Existitzen den fitxategi bat gain-idaztea ez da posible.',
+'api-error-stashfailed' => 'Barne arazoa: Zerbitzariak ezin izan du behin-behineko fitxategia gorde',
+'api-error-timeout' => 'Zerbitzariak ez du erantzun espero zitekeen denboran.',
 'api-error-unclassified' => 'Ezezaguna den errorea gertatu da.',
 'api-error-unknown-code' => 'Akats ezezaguna: "$1".',
+'api-error-unknown-error' => 'Barne arazoa: fitxategia igotzen saiatzerakoan zerbait gaizki egon da.',
 'api-error-unknown-warning' => 'Ohartarazpen ezezaguna: "$1".',
 'api-error-unknownerror' => 'Akats ezezaguna: "$1".',
 'api-error-uploaddisabled' => 'Wiki honetan ezin dira igoerak egin.',
@@ -3631,4 +3723,20 @@ Halaber [[Special:EditWatchlist|aldatzaile estandarra]] erabil dezakezu.',
 # Image rotation
 'rotate-comment' => 'Irudia erlojuaren norantzan {{PLURAL:$1|gradu 1|$1 gradu}} biratua izan da',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Txantiloi ordezkatzailea',
+'expand_templates_intro' => 'Aparteko orrialde honek modu errekurtsiboan txantiloiak ordezkatu egiten ditu.
+Funtzioak ere ordezkatu egiten ditu, hala nola
+<code><nowiki>{{</nowiki>#language:…}}</code>, eta
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code> bezalako aldagaiak ere.
+Kortxete bikoitzarekin hobeto egiten da lan.',
+'expand_templates_title' => 'Izenburua ({{FULLPAGENAME}} ordezkatzeko, eta abar):',
+'expand_templates_input' => 'Sarrerako testua:',
+'expand_templates_output' => 'Emaitza',
+'expand_templates_xml_output' => 'XML irteera',
+'expand_templates_ok' => 'Ados',
+'expand_templates_remove_comments' => 'Iruzkinak kendu',
+'expand_templates_generate_xml' => 'Erakutsi XML parse zuhaitza',
+'expand_templates_preview' => 'Aurreikusi',
+
 );
index cf6a54d..c793efe 100644 (file)
@@ -254,8 +254,6 @@ $messages = array(
 'ok' => 'Dalcuerdu',
 'retrievedfrom' => 'Arrecuperau dendi "$1"',
 'youhavenewmessages' => 'Tiinis $1 ($2).',
-'newmessageslink' => 'nuevus mensahis',
-'newmessagesdifflink' => 'úrtimu chambu',
 'youhavenewmessagesmulti' => 'Tiinis nuevus mensahis en $1',
 'editsection' => 'eital',
 'editold' => 'eital',
@@ -784,8 +782,6 @@ Asigurati e qu'esti chambu mantenga la continuiá el estorial la páhina.",
 'preferences' => 'Preferéncias',
 'mypreferences' => 'Las mis preferéncias',
 'prefs-edits' => "Númiru d'eicionis:",
-'prefsnologin' => "Nu t'alcuentras rustriu",
-'prefsnologintext' => 'Ebis estal [[Special:UserLogin|rustriu]] pa chambal las tus preferéncias.',
 'changepassword' => 'Chambal consínia',
 'prefs-skin' => 'Aparéncia',
 'skin-preview' => 'Previsoreal',
@@ -1758,7 +1754,7 @@ Ya desisti la páhina "[[:$1]]". Te petaria esborrala pa premitil el treslau?',
 'allmessagesdefault' => 'Testu pol defeutu',
 'allmessagescurrent' => 'Testu atual',
 'allmessagestext' => 'Esta es una lista e mensahis del sistema disponibris nel espaciu e nombris MediaWiki:
-Pol favol, vesita [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net] si quieis colabutal.',
+Pol favol, vesita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] i [//translatewiki.net translatewiki.net] si quieis colabutal.',
 'allmessagesnotsupportedDB' => "Nu se puei gastal esta páhina polque '''\$wgUseDatabaseMessages''' está desativau.",
 
 # Thumbnails
@@ -2180,7 +2176,7 @@ Cualisquiel otru atihu ena mesma línia se consierará ececión, p.s. páhinas o
 
 # External editor support
 'edit-externally' => 'Eital esti archivu gastandu una apricación esterna',
-'edit-externally-help' => 'Pa mas enholmación, lei las [//www.mediawiki.org/wiki/Manual:External_editors istrucionis de configuración] (en ingrés).',
+'edit-externally-help' => 'Pa mas enholmación, lei las [https://www.mediawiki.org/wiki/Manual:External_editors istrucionis de configuración] (en ingrés).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tó',
@@ -2363,4 +2359,7 @@ Pol favol, confirma si rialmenti quieis gorvel a crial la páhina.",
 'revdelete-unrestricted' => 'las restricionis a los çahorilis án siu esborrás',
 'rightsnone' => '(dengunu)',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'Previsoreal',
+
 );
index 91af22c..25bb697 100644 (file)
@@ -81,34 +81,34 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'کاربران_فعال' ),
        'Allmessages'               => array( 'تمام_پیغام‌ها' ),
+       'AllMyUploads'              => array( 'همهٔ_بارگذاری‌های_من', 'همه_بارگذاری‌های_من' ),
        'Allpages'                  => array( 'تمام_صفحه‌ها' ),
        'Ancientpages'              => array( 'صفحه‌های_قدیمی' ),
        'Badtitle'                  => array( 'عنوان_بد' ),
        'Blankpage'                 => array( 'صفحه_خالی' ),
        'Block'                     => array( 'بستن_نشانی_آی‌پی' ),
-       'Blockme'                   => array( 'بستن_من' ),
        'Booksources'               => array( 'منابع_کتاب' ),
        'BrokenRedirects'           => array( 'تغییرمسیرهای_خراب' ),
        'Categories'                => array( 'رده‌ها' ),
        'ChangeEmail'               => array( 'تغییر_رایانامه' ),
        'ChangePassword'            => array( 'از_نو_کردن_گذرواژه' ),
        'ComparePages'              => array( 'مقایسه_صفحات' ),
-       'Confirmemail'              => array( 'تایید_رایانامه' ),
+       'Confirmemail'              => array( 'تأیید_رایانامه' ),
        'Contributions'             => array( 'مشارکت‌ها' ),
        'CreateAccount'             => array( 'ایجاد_حساب_کاربری' ),
        'Deadendpages'              => array( 'صفحه‌های_بن‌بست' ),
        'DeletedContributions'      => array( 'مشارکت‌های_حذف_شده' ),
-       'Disambiguations'           => array( 'ابهام‌زدایی' ),
        'DoubleRedirects'           => array( 'تغییرمسیرهای_دوتایی' ),
        'EditWatchlist'             => array( 'ویرایش_فهرست_پی‌گیری‌ها' ),
        'Emailuser'                 => array( 'نامه_به_کاربر' ),
+       'ExpandTemplates'           => array( 'گسترش_الگوها' ),
        'Export'                    => array( 'برون_بری_صفحه' ),
        'Fewestrevisions'           => array( 'کمترین_نسخه' ),
        'FileDuplicateSearch'       => array( 'جستجوی_پرونده_تکراری' ),
        'Filepath'                  => array( 'مسیر_پرونده' ),
-       'Import'                    => array( 'درون_ریزی_صفحه' ),
-       'Invalidateemail'           => array( 'باطل_کردن_رایانامه' ),
-       'JavaScriptTest'            => array( 'تست_جاوا_اسکریپت' ),
+       'Import'                    => array( 'درونریزی_صفحه' ),
+       'Invalidateemail'           => array( 'باطلکردن_رایانامه' ),
+       'JavaScriptTest'            => array( 'تست_جاوااسکریپت' ),
        'BlockList'                 => array( 'فهرست_بستن_نشانی_آی‌پی' ),
        'LinkSearch'                => array( 'جستجوی_پیوند' ),
        'Listadmins'                => array( 'فهرست_مدیران' ),
@@ -137,6 +137,7 @@ $specialPageAliases = array(
        'Myuploads'                 => array( 'بارگذاری‌های_من' ),
        'Newimages'                 => array( 'تصاویر_جدید' ),
        'Newpages'                  => array( 'صفحه‌های_تازه' ),
+       'PagesWithProp'             => array( 'صفحه‌های_با_خاصیت' ),
        'PasswordReset'             => array( 'بازنشاندن_گذرواژه' ),
        'PermanentLink'             => array( 'پیوند_دائمی' ),
        'Popularpages'              => array( 'صفحه‌های_محبوب' ),
@@ -144,11 +145,13 @@ $specialPageAliases = array(
        'Prefixindex'               => array( 'نمایه_پیشوندی' ),
        'Protectedpages'            => array( 'صفحه‌های_محافظت_شده' ),
        'Protectedtitles'           => array( 'عنوان‌های_محافظت_شده' ),
-       'Randompage'                => array( 'صفحه_تصادفی' ),
+       'Randompage'                => array( 'صفحهٔ_تصادفی' ),
+       'RandomInCategory'          => array( 'تصادفی_در_رده' ),
        'Randomredirect'            => array( 'تغییرمسیر_تصادفی' ),
        'Recentchanges'             => array( 'تغییرات_اخیر' ),
        'Recentchangeslinked'       => array( 'تغییرات_مرتبط' ),
        'Redirect'                  => array( 'تغییرمسیر' ),
+       'ResetTokens'               => array( 'بازنشانی_نشانه‌ها' ),
        'Revisiondelete'            => array( 'حذف_نسخه' ),
        'Search'                    => array( 'جستجو' ),
        'Shortpages'                => array( 'صفحه‌های_کوتاه' ),
@@ -230,6 +233,8 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'نام‌کامل‌صفحه‌کد', 'نام_کامل_صفحه_کد', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'نام‌زیرصفحه', 'نام_زیرصفحه', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'نام‌زیرصفحه‌کد', 'نام_زیرصفحه_کد', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'نام_صفحه_ریشه', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'نام_صفحه_ریشه_ای', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'نام‌صفحه‌مبنا', 'نام_صفحه_مبنا', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'نام‌صفحه‌مبناکد', 'نام_صفحه_مبنا_کد', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'نام‌صفحه‌بحث', 'نام_صفحه_بحث', 'TALKPAGENAME' ),
@@ -249,6 +254,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'وسط', 'center', 'centre' ),
        'img_framed'                => array( '1', 'قاب', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'بی‌قاب', 'بیقاب', 'بی_قاب', 'frameless' ),
+       'img_lang'                  => array( '1', 'زبان=$1', 'lang=$1' ),
        'img_page'                  => array( '1', 'صفحه=$1', 'صفحه_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'ایستاده', 'ایستاده=$1', 'ایستاده_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'حاشیه', 'border' ),
@@ -262,6 +268,7 @@ $magicWords = array(
        'img_text_bottom'           => array( '1', 'متن-پایین', 'text-bottom' ),
        'img_link'                  => array( '1', 'پیوند=$1', 'link=$1' ),
        'img_alt'                   => array( '1', 'جایگزین=$1', 'alt=$1' ),
+       'img_class'                 => array( '1', 'کلاس=$1', 'class=$1' ),
        'int'                       => array( '0', 'ترجمه:', 'INT:' ),
        'sitename'                  => array( '1', 'نام‌وبگاه', 'نام_وبگاه', 'SITENAME' ),
        'ns'                        => array( '0', 'فن:', 'NS:' ),
@@ -269,6 +276,7 @@ $magicWords = array(
        'localurl'                  => array( '0', 'نشانی:', 'LOCALURL:' ),
        'localurle'                 => array( '0', 'نشانی‌کد:', 'نشانی_کد:', 'LOCALURLE:' ),
        'articlepath'               => array( '0', 'مسیرمقاله', 'مسیر_مقاله', 'ARTICLEPATH' ),
+       'pageid'                    => array( '0', 'شناسه_صفحه', 'PAGEID' ),
        'server'                    => array( '0', 'سرور', 'کارساز', 'SERVER' ),
        'servername'                => array( '0', 'نام‌کارساز', 'نام_کارساز', 'نام‌سرور', 'نام_سرور', 'SERVERNAME' ),
        'scriptpath'                => array( '0', 'مسیرسند', 'مسیر_سند', 'SCRIPTPATH' ),
@@ -316,6 +324,7 @@ $magicWords = array(
        'padleft'                   => array( '0', 'لبه‌چپ', 'لبه_چپ', 'PADLEFT' ),
        'padright'                  => array( '0', 'لبه‌راست', 'لبه_راست', 'PADRIGHT' ),
        'special'                   => array( '0', 'ویژه', 'special' ),
+       'speciale'                  => array( '0', 'ویژه_ای', 'speciale' ),
        'defaultsort'               => array( '1', 'ترتیب:', 'ترتیب‌پیش‌فرض:', 'ترتیب_پیش_فرض:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
        'filepath'                  => array( '0', 'مسیرپرونده:', 'مسیر_پرونده:', 'FILEPATH:' ),
        'tag'                       => array( '0', 'برچسب', 'tag' ),
@@ -333,6 +342,10 @@ $magicWords = array(
        'url_query'                 => array( '0', 'دستور', 'QUERY' ),
        'defaultsort_noerror'       => array( '0', 'بدون‌خطا', 'بدون_خطا', 'noerror' ),
        'defaultsort_noreplace'     => array( '0', 'جایگزین‌نکن', 'جایگزین_نکن', 'noreplace' ),
+       'pagesincategory_all'       => array( '0', 'همه', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'صفحات', 'pages' ),
+       'pagesincategory_subcats'   => array( '0', 'زیررده‌ها', 'subcats' ),
+       'pagesincategory_files'     => array( '0', 'پرونده‌ها', 'files' ),
 );
 
 $digitTransformTable = array(
@@ -481,7 +494,7 @@ $messages = array(
 'tog-noconvertlink' => 'تبدیل عنوان پیوند غیرفعال شود',
 'tog-norollbackdiff' => 'بعد از واگردانی تفاوت نشان داده نشود',
 'tog-useeditwarning' => 'زمان خروج از صفحهٔ ویرایش در صورت داشتن ویرایش‌های‌ ذخیره‌نشده به من هشدار داده شود',
-'tog-prefershttps' => 'هنگامی که ثبت ورود انجام گرفته همواره از اتصال امن استفاده شود',
+'tog-prefershttps' => 'در حالت ورود به سامانه همواره از اتصال امن استفاده شود',
 
 'underline-always' => 'همیشه',
 'underline-never' => 'هرگز',
@@ -713,12 +726,10 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'برگرفته از «$1»',
 'youhavenewmessages' => '$1 دارید ($2).',
-'newmessageslink' => 'پیام‌های جدید',
-'newmessagesdifflink' => 'آخرین تغییر',
 'youhavenewmessagesfromusers' => 'شما از {{PLURAL:$3|یک کاربر دیگر|$3  کاربر}} $1 دارید ($2).',
 'youhavenewmessagesmanyusers' => 'شما از تعدادی کاربر $1 دارید ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|پیام جدید}}',
-'newmessagesdifflinkplural' => '{{formatnum:$1}} {{PLURAL:$1|تغییر|تغییر}} اخیر',
+'newmessageslinkplural' => '{{PLURAL:$1|پیام جدید|999=پیام‌های جدید}}',
+'newmessagesdifflinkplural' => '{{formatnum:$1}} {{PLURAL:$1|تغییر|999=تغییر}} اخیر',
 'youhavenewmessagesmulti' => 'پیام‌های جدیدی در $1 دارید.',
 'editsection' => 'ویرایش',
 'editold' => 'ویرایش',
@@ -853,7 +864,8 @@ $2',
 'invalidtitle-knownnamespace' => 'عنوان نامعتبر با فضای نام «$2» و متن «$3»',
 'invalidtitle-unknownnamespace' => 'عنوان نامعتبر با فضای نام ناشناختهٔ شمارهٔ $1 و متن «$2»',
 'exception-nologin' => 'به سامانه وارد نشده‌اید',
-'exception-nologin-text' => 'دسترسی به این صفحه یا انجام این عمل در این ویکی نیازمند وارد شدن به سیستم  است.',
+'exception-nologin-text' => 'لطفاً به سامانه [[Special:Userlogin|وارد شوید]] تا بتوانید به این صفحه دسترسی داشته باشید.',
+'exception-nologin-text-manual' => 'لطفاً  $1  تا بتوانید به این صفحه یا عمل دسترسی داشته باشید.',
 
 # Virus scanner
 'virus-badscanner' => "پیکربندی بد: پویشگر ویروس ناشناخته: ''$1''",
@@ -863,7 +875,7 @@ $2',
 # Login and logout pages
 'logouttext' => "'''اکنون شما ثبت خروج کرده‌اید.'''
 توجه داشته باشید که تا حافظهٔ نهان مرورگرتان را پاک نکنید، بعضی از صفحات ممکن است همچنان به گونه‌ای نمایش یابند که انگار وارد شده‌اید.",
-'welcomeuser' => 'خوشامدید، $1!',
+'welcomeuser' => 'خوشامدید $1!',
 'welcomecreation-msg' => 'حساب کاربری شما ایجاد شده است.
 فراموش نکنید که [[Special:Preferences|ترجیحات {{SITENAME}}]] خود را تغییر دهید.',
 'yourname' => 'نام کاربری:',
@@ -923,7 +935,7 @@ $2',
 'createacct-benefit-heading' => '{{SITENAME}} توسط افرادی مانند شما ساخته شده‌است',
 'createacct-benefit-body1' => '{{PLURAL:$1|ویرایش}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|صفحه}}',
-'createacct-benefit-body3' => '{{PLURAL:$1|مشارکت‌کنندهٔ|مشارکت‌کنندگان}} اخیر',
+'createacct-benefit-body3' => '{{PLURAL:$1|مشارکت‌کنندهٔ}} اخیر',
 'badretype' => 'گذرواژه‌هایی که وارد کرده‌اید یکسان نیستند.',
 'userexists' => 'نام کاربری‌ای که وارد کردید قبلاً استفاده شده‌است.
 لطفاً یک نام دیگر انتخاب کنید.',
@@ -976,8 +988,8 @@ $2',
 'mailerror' => 'خطا در فرستادن رایانامه: $1',
 'acct_creation_throttle_hit' => 'بازدیدکنندگان این ویکی که از نشانی آی‌پی شما استفاده می‌کنند در روز گذشته {{PLURAL:$1|یک حساب کاربری|$1 حساب کاربری}} ساخته‌اند، که بیشترین تعداد مجاز در آن بازهٔ زمانی است.
 به همین خاطر، بازدیدکنندگانی که از این نشانی آی‌پی استفاده می‌کنند نمی‌توانند در حال حاضر حساب جدیدی بسازند.',
-'emailauthenticated' => 'نشانی رایانامه شما در $2 ساعت $3 تصدیق شد.',
-'emailnotauthenticated' => 'نشانی رایانامه شما هنوز تصدیق نشده‌است.
+'emailauthenticated' => 'نشانی رایانامهٔ شما در $2 ساعت $3 تصدیق شد.',
+'emailnotauthenticated' => 'نشانی رایانامهٔ شما هنوز تصدیق نشده‌است.
 برای هیچ‌یک از ویژگی‌های زیر رایانامه ارسال نخواهد شد.',
 'noemailprefs' => 'برای راه‌اندازی این قابلیت‌ها یک نشانی رایانامه مشخص کنید.',
 'emailconfirmlink' => 'تأیید نشانی رایانامه',
@@ -1029,7 +1041,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'بازنشانی گذرواژه',
 'passwordreset-text-one' => 'برای بازنشانی گذرواژه‌تان این فرم را کامل کنید.',
-'passwordreset-text-many' => '{{PLURAL:$1|یکی از موارد را برای بازنشانی گذرواژه‌تان پر کنید.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|برای دریافت یک گذرواژهٔ موقت از راه رایانامه، یکی از زمینه‌ها را پر کنید.}}',
 'passwordreset-legend' => 'بازنشانی گذرواژه',
 'passwordreset-disabled' => 'بازنشانی گذرواژه در این ویکی غیرفعال شده است.',
 'passwordreset-emaildisabled' => 'ویژگی‌های رایانامه در این ویکی نافعال شده‌اند.',
@@ -1053,7 +1065,7 @@ $2
 شما باید هم‌اکنون وارد شده و یک گذرواژهٔ جدید برگزینید. اگر شخص دیگری این درخواست را داده است، یا اگر گذرواژهٔ اصلی‌تان را به خاطر آوردید و دیگر نمی‌خواهید آن را تغییر دهید، می‌توانید این پیغام را نادیده بگیرید و به استفاده از گذرواژهٔ قبلی‌تان ادامه دهید.',
 'passwordreset-emailelement' => 'نام کاربری: $1
 گذرواژهٔ موقت: $2',
-'passwordreset-emailsent' => 'یک نامهٔ بازنشانی گذرواژه فرستاده شده است.',
+'passwordreset-emailsent' => 'یک نامهٔ بازنشانی گذرواژه فرستاده شدهاست.',
 'passwordreset-emailsent-capture' => 'یک رایانامهٔ بازنشانی که در پایین نمایش داده شده، فرستاده شده است.',
 'passwordreset-emailerror-capture' => 'رایانامهٔ بازنشانی، که در زیر نمایش داده شده، ایجاد شد، ولی ارسال آن به {{GENDER:$2|کاربر}} موفقیت‌آمیز نبود: $1',
 
@@ -1077,7 +1089,7 @@ $2
 'resettokens-legend' => 'بازنشانی شناساننده‌ها',
 'resettokens-tokens' => 'شناساننده‌ها:',
 'resettokens-token-label' => '$1 (مقدار کنونی: $2)',
-'resettokens-watchlist-token' => 'شناساننده Ø¨Ø±Ø§Û\8c Ø®Ù\88راک Ù\88بÙ\90 [[Special:Watchlist|تغÛ\8cÛ\8cرات ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù¾Û\8cÚ¯Û\8cرÛ\8c Ù\85Û\8câ\80\8cÚ©Ù\86Û\8cد]] (اتÙ\85/آراسâ\80\8cاس)',
+'resettokens-watchlist-token' => 'شناسانندهÙ\94 Ø®Ù\88راک Ù\88بÙ\90Û\8c [[Special:Watchlist|تغÛ\8cÛ\8cرات ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8cÛ\8c Ú©Ù\87 Ù¾Û\8câ\80\8cÚ¯Û\8cرÛ\8c Ù\85Û\8câ\80\8cÚ©Ù\86Û\8cد]] (اتÙ\85/آراسâ\80\8cاس)',
 'resettokens-done' => 'بازنشانی شناساننده‌ها.',
 'resettokens-resetbutton' => 'بازشناسی شناساننده‌های گزیده‌شده.',
 
@@ -1250,8 +1262,8 @@ $2
 اگر می‌خواهید متن را در یک پروندهٔ متنی کپی کنید و برای آینده ذخیره‌اش کنید.
 
 مدیری که آن را قفل کرده این توضیح را ارائه کرده‌است: $1",
-'protectedpagewarning' => "'''هشدار: این صفحه قفل شده است تا فقط کاربران با امتیاز مدیر بتوانند ویرایشش کنند.'''
-آخرین موارد سیاهه در زیر آمده است:",
+'protectedpagewarning' => "'''هشدار: این صفحه قفل شده‌است تا فقط کاربران با دسترسی مدیریت بتوانند ویرایشش کنند.'''
+آخرین موارد سیاهه در زیر آمدهاست:",
 'semiprotectedpagewarning' => "'''توجه:''' این صفحه قفل شده‌است تا تنها کاربران ثبت‌نام‌کرده قادر به ویرایش آن باشند.
 آخرین موارد سیاهه در زیر آمده‌است:",
 'cascadeprotectedwarning' => "'''هشدار:''' این صفحه به علت قرارگرفتن در {{PLURAL:$1|صفحهٔ|صفحه‌های}} آبشاری-محافظت‌شدهٔ زیر قفل شده‌است تا فقط مدیران بتوانند ویرایشش کنند.",
@@ -1419,17 +1431,17 @@ $2
 'revdelete-suppress-text' => "فرونشانی باید '''تنها''' برای موارد زیر استفاده شود:
 * اطلاعات به طور بالقوه افتراآمیز
 * اطلاعات نامناسب شخصی
-*: ''نشانی منزل، شماره تلفن، شماره تامین اجتماعی و غیره.''",
+*: ''نشانی منزل، شماره تلفن، کد ملی و غیره.''",
 'revdelete-legend' => 'تنظیم محدودیت‌های پیدایی',
-'revdelete-hide-text' => 'Ù\86Ù\87Ù\81تÙ\86 Ù\85تÙ\86 Ù\86سخÙ\87',
+'revdelete-hide-text' => 'متن نسخه',
 'revdelete-hide-image' => 'نهفتن محتویات پرونده',
 'revdelete-hide-name' => 'نهفتن عمل و هدف',
-'revdelete-hide-comment' => 'نهفتن توضیح ویرایش',
-'revdelete-hide-user' => 'نام کاربری/نشانی آی‌پی ویراستار پنهان شود',
+'revdelete-hide-comment' => 'خلاصهٔ ویرایش',
+'revdelete-hide-user' => 'نام کاربری/نشانی آی‌پی',
 'revdelete-hide-restricted' => 'فرونشانی اطلاعات برای مدیران به همراه دیگران',
 'revdelete-radio-same' => '(بدون تغییر)',
-'revdelete-radio-set' => 'بله',
-'revdelete-radio-unset' => 'خیر',
+'revdelete-radio-set' => 'پنهان',
+'revdelete-radio-unset' => 'نمایان',
 'revdelete-suppress' => 'از دسترسی مدیران به داده نیز مانند سایر کاربران جلوگیری به عمل آید.',
 'revdelete-unsuppress' => 'خاتمهٔ محدودیت‌ها در مورد نسخه‌های انتخاب شده',
 'revdelete-log' => 'دلیل:',
@@ -1534,7 +1546,7 @@ $1",
 'shown-title' => 'نمایش $1 {{PLURAL:$1|نتیجه|نتیجه}} در هر صفحه',
 'viewprevnext' => 'نمایش ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-legend' => 'گزینه‌های جستجو',
-'searchmenu-exists' => "'''صفحه‌ای با عنوان \"[[:\$1]]\" در این ویکی وجود دارد.'''",
+'searchmenu-exists' => "'''صفحه‌ای با عنوان «[[:$1]]» در این ویکی وجود دارد.'''",
 'searchmenu-new' => "'''صفحهٔ «[[:$1]]» را در این ویکی بسازید!'''",
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|مرور صفحه‌های با این پیشوند]]',
 'searchprofile-articles' => 'صفحه‌های محتوایی',
@@ -1585,8 +1597,7 @@ $1",
 'preferences' => 'ترجیحات',
 'mypreferences' => 'ترجیحات',
 'prefs-edits' => 'تعداد ویرایش‌ها:',
-'prefsnologin' => 'به سامانه وارد نشده‌اید',
-'prefsnologintext' => 'برای تنظیم ترجیحات کاربر باید <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} به سامانه وارد شوید]</span>.',
+'prefsnologintext2' => 'لطفاً  $1  برای تنظیم ترجیحات کاربر.',
 'changepassword' => 'تغییر گذرواژه',
 'prefs-skin' => 'پوسته',
 'skin-preview' => 'پیش‌نمایش',
@@ -1761,7 +1772,7 @@ $1",
 'right-createpage' => 'ایجاد صفحه (در مورد صفحه‌های غیر بحث)',
 'right-createtalk' => 'ایجاد صفحه‌های بحث',
 'right-createaccount' => 'ایجاد حساب‌های کاربری',
-'right-minoredit' => 'علامت‌زدن ویرایش‌ها به عنوان جزئی',
+'right-minoredit' => 'علامت‌زدن ویرایش‌ها بهعنوان جزئی',
 'right-move' => 'انتقال صفحه',
 'right-move-subpages' => 'انتقال صفحه‌ها به همراه زیر‌صفحه‌هایشان',
 'right-move-rootuserpages' => 'انتقال صفحه‌های کاربری سرشاخه',
@@ -1794,7 +1805,7 @@ $1",
 'right-ipblock-exempt' => 'تاثیر نپذیرفتن از قطع دسترسی‌های آی‌پی، خودکار یا فاصله‌ای',
 'right-proxyunbannable' => 'تاثیر نپذیرفتن از قطع دسترسی خودکار پروکسی‌ها',
 'right-unblockself' => 'بازکردن دسترسی خود',
-'right-protect' => 'تغییر میزان محافظت صفحه‌ها و ویرایش صفحه‌های محافظت شده آبشاری',
+'right-protect' => 'تغییر میزان محافظت صفحه‌ها و ویرایش صفحه‌های محافظتشده آبشاری',
 'right-editprotected' => 'ویرایش صفحه‌های محافظت شده به عنوان "{{int:protect-level-sysop}}"',
 'right-editsemiprotected' => 'ویرایش صفحه حفاظت‌شده به عنوان "{{int:protect-level-autoconfirmed}}"',
 'right-editinterface' => 'ویرایش واسط کاربری',
@@ -1811,12 +1822,12 @@ $1",
 'right-rollback' => 'واگردانی سریع ویرایش‌های آخرین کاربری که یک صفحه را ویرایش کرده‌است',
 'right-markbotedits' => 'علامت‌زدن ویرایش‌های واگردانی‌شده به‌عنوان ویرایش ربات',
 'right-noratelimit' => 'تاثیر نپذیرفتن از محدودیت سرعت',
-'right-import' => 'وارد کردن صفحه از ویکی‌های دیگر',
-'right-importupload' => 'وارد کردن صفحه از طریق بارگذاری پرونده',
+'right-import' => 'واردکردن صفحه از ویکی‌های دیگر',
+'right-importupload' => 'واردکردن صفحه از طریق بارگذاری پرونده',
 'right-patrol' => 'گشت زدن به ویرایش‌های دیگران',
 'right-autopatrol' => 'گشن زدن خودکار به ویرایش‌های خودش',
 'right-patrolmarks' => 'مشاهدهٔ برچسب گشت تغییرات اخیر',
-'right-unwatchedpages' => 'مشاهدهٔ فهرست صفحه‌هایی که پیگیری نمی‌شوند',
+'right-unwatchedpages' => 'مشاهدهٔ فهرست صفحه‌هایی که پیگیری نمی‌شوند',
 'right-mergehistory' => 'ادغام تاریخچهٔ صفحه‌ها',
 'right-userrights' => 'ویرایش تمام اختیارات کاربرها',
 'right-userrights-interwiki' => 'ویرایش اختیارات کاربرهای ویکی‌های دیگر',
@@ -1852,14 +1863,14 @@ $1",
 'action-delete' => 'حذف این صفحه',
 'action-deleterevision' => 'حذف این نسخه',
 'action-deletedhistory' => 'مشاهدهٔ تاریخچهٔ حذف شدهٔ این صفحه',
-'action-browsearchive' => 'جستجوی صفحه‌های حذف شده',
+'action-browsearchive' => 'جستجوی صفحه‌های حذفشده',
 'action-undelete' => 'احیای این صفحه',
 'action-suppressrevision' => 'مشاهده و احیای ویرایش‌های حذف شده',
 'action-suppressionlog' => 'مشاهدهٔ این سیاههٔ خصوصی',
 'action-block' => 'قطع دسترسی این کاربر از ویرایش‌کردن',
 'action-protect' => 'تغییر سطح محافظت این صفحه',
 'action-rollback' => 'واگردانی سریع ویرایش‌های آخرین کاربری که یک صفحه را ویرایش کرده‌است',
-'action-import' => 'وارد کردن صفحه از ویکی های دیگر',
+'action-import' => 'واردکردن صفحه از ویکی های دیگر',
 'action-importupload' => 'واردکردن صفحه از طریق بارگذاری پرونده',
 'action-patrol' => 'گشت زدن ویرایش دیگران',
 'action-autopatrol' => 'گشت زدن ویرایش خودتان',
@@ -1887,6 +1898,9 @@ $1",
 'recentchanges-label-minor' => 'این ویرایش جزئی‌است',
 'recentchanges-label-bot' => 'این ویرایش را یک ربات انجام داده‌است',
 'recentchanges-label-unpatrolled' => 'این ویرایش هنوز گشت‌زنی نشده‌است',
+'recentchanges-label-plusminus' => 'حجم صفحه به اندازه این بایت‌ها تغییر یافته‌است',
+'recentchanges-legend-newpage' => '(همچنین به [[Special:NewPages|فهرست صفحات جدید]] نگاه کنید)',
+'recentchanges-legend-plusminus' => "('' ±۱۲۳'')",
 'rcnote' => "در زیر {{PLURAL:$1|'''۱''' تغییر|آخرین '''$1''' تغییر}} در آخرین {{PLURAL:$2|روز|'''$2''' روز}} را، تا $4 ساعت $5 می‌بینید.",
 'rcnotefrom' => 'در زیر تغییرات از تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشان داده می‌شود).',
 'rclistfrom' => 'نمایش تغییرات جدید با شروع از $1',
@@ -2121,11 +2135,11 @@ $1',
 # Special:UploadStash
 'uploadstash' => 'انبار بارگذاری',
 'uploadstash-summary' => 'این صفحه دسترسی به پرونده‌هایی که بارگذاری شده‌اند (یا در حال بارگذاری هستند) اما هنوز در ویکی منتشر نشده‌اند را فراهم می‌کند. این پرونده‌ها توسط هیچ کاربری به جز کسی که آن‌ها را بارگذاری کرده قابل دیدن نیستند.',
-'uploadstash-clear' => 'پاک کردن پرونده‌های انبارشده',
+'uploadstash-clear' => 'پاککردن پرونده‌های انبارشده',
 'uploadstash-nofiles' => 'شما هیچ پروندهٔ انبارشده‌ای ندارید.',
 'uploadstash-badtoken' => 'انجام این اقدام ناموفق بود، احتمالاً به این دلیل که اعتبار ویرایش شما به اتمام رسیده است. دوباره امتحان کنید.',
-'uploadstash-errclear' => 'پاک کردن پرونده‌ها ناموفق بود.',
-'uploadstash-refresh' => 'تازه کردن فهرست پرونده‌ها',
+'uploadstash-errclear' => 'پاککردن پرونده‌ها ناموفق بود.',
+'uploadstash-refresh' => 'تازهکردن فهرست پرونده‌ها',
 'invalid-chunk-offset' => 'جابجایی نامعتبر قطعه',
 
 # img_auth script messages
@@ -2267,7 +2281,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization را ببینید.',
 'mimesearch-summary' => 'با کمک این صفحه شما می‌توانید پرونده‌هایی که یک نوع MIME به خصوص دارند را پیدا کنید.
 ورودی: به صورت contenttype/subtype ، نظیر <code>image/jpeg</code>.',
 'mimetype' => 'نوع MIME:',
-'download' => 'بارگÛ\8cرÛ\8c',
+'download' => 'درÛ\8cاÙ\81ت',
 
 # Unwatched pages
 'unwatchedpages' => 'صفحه‌های پی‌گیری‌نشده',
@@ -2306,7 +2320,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization را ببینید.',
 'statistics-articles' => 'صفحه‌های محتوایی',
 'statistics-pages' => 'صفحه‌ها',
 'statistics-pages-desc' => 'تمام صفحه‌های این ویکی، از جمله صفحه‌های بحث، تغییرمسیر و غیره',
-'statistics-files' => 'پرونده‌های بارگذاری شده',
+'statistics-files' => 'پرونده‌های بارگذاریشده',
 'statistics-edits' => 'ویرایش صفحه‌ها از هنگامی که {{SITENAME}} راه‌اندازی شده',
 'statistics-edits-average' => 'متوسط ویرایش‌ها به ازای هر صفحه',
 'statistics-views-total' => 'مجموع بازدیدها',
@@ -2370,7 +2384,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization را ببینید.',
 'wantedpages-badtitle' => 'عنوان نامجاز در مجموعهٔ نتایج: $1',
 'wantedfiles' => 'پرونده‌های مورد نیاز',
 'wantedfiletext-cat' => 'پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبه مثبت کاذب <del>خط خواهد خورد.</del> علاوه بر این، صفحاتی که پرونده‌هایی ناموجود را در خود جای داده‌اند در [[:$1]] فهرست شده‌اند.',
-'wantedfiletext-nocat' => 'پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبه مثبت کاذب <del>خط خواهد خورد.</del>',
+'wantedfiletext-nocat' => 'پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبهٔ مثبت کاذب <del>خط خواهد خورد.</del>',
 'wantedtemplates' => 'الگوهای مورد نیاز',
 'mostlinked' => 'صفحه‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است',
 'mostlinkedcategories' => 'رده‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است',
@@ -2583,7 +2597,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization را ببینید.',
 'iteminvalidname' => 'مشکل با مورد «$1»، نام نامعتبر است...',
 'wlnote' => 'در زیر {{PLURAL:$1|تغییری|$1 تغییری}} که در {{PLURAL:$2|ساعت|$2 ساعت}} گذشته انجام شده موجود است، تاریخ آخرین بازیابی: $3، $4',
 'wlshowlast' => 'نمایش آخرین $1 ساعت $2 روز $3',
-'watchlist-options' => 'گزینه‌های پیگیری',
+'watchlist-options' => 'گزینه‌های پیگیری',
 
 # Displayed when you click the "watch" button and it is in the process of watching
 'watching' => 'پی‌گیری...',
@@ -2617,7 +2631,7 @@ $PAGEINTRO $NEWPAGE
 نامه: $PAGEEDITOR_EMAIL
 ویکی: $PAGEEDITOR_WIKI
 
-تا هنگامی که به صفحه سر نزده‌اید، در صورت رخ‌دادنِ احتمالیِ تغییراتِ بیشتر، اعلانیه‌ای برای شما فرستاده نخواهد شد.
+تا هنگامی که به صفحه سر نزده‌اید، در صورت رخ‌دادنِ احتمالیِ فعالیت بیشتر، تا زمانی که در با کاربریتان در سیستم هستید، اعلانیه‌ای برای شما فرستاده نخواهد شد.
 شما همچنین می‌توانید در صفحهٔ پی‌گیری‌های خود پرچم‌های مربوط به آگاهی‌رسانی را صفر کنید همچنین می‌توانید پرچم‌های آگاهی‌سازی را بازنشانی کنید.
 
 دوستدار شما، سامانهٔ آگاهی‌رسانی {{SITENAME}}
@@ -2802,7 +2816,7 @@ $1',
 
 برای دیدن سیاههٔ حذف‌ها و احیاهای اخیر به  [[Special:Log/delete|سیاههٔ حذف]] رجوع کنید.",
 'undelete-header' => 'برای دیدن صفحه‌های حذف‌شدهٔ اخیر [[Special:Log/delete|سیاههٔ حذف]] را ببینید.',
-'undelete-search-title' => 'جستجوی صفحه‌های حذف شده',
+'undelete-search-title' => 'جستجوی صفحه‌های حذفشده',
 'undelete-search-box' => 'جستجوی صفحه‌های حذف‌شده.',
 'undelete-search-prefix' => 'نمایش صفحه‌ها با شروع از:',
 'undelete-search-submit' => 'برو',
@@ -2890,8 +2904,8 @@ $1',
 'ipbreason' => 'دلیل:',
 'ipbreasonotherlist' => 'دلیل دیگر',
 'ipbreason-dropdown' => '*دلایل متداول قطع دسترسی
-**وارد کردن اطلاعات نادرست
-**پاک کردن اطلاعات مفید از صفحه‌ها
+**واردکردن اطلاعات نادرست
+**پاککردن اطلاعات مفید از صفحه‌ها
 **هرزنگاری از طریق درج مکرر پیوند به وب‌گاه‌ها
 **درج چرندیات یا نوشته‌های بی‌معنا در صفحه‌ها
 **تهدید یا ارعاب دیگر کاربران
@@ -2907,7 +2921,7 @@ $1',
 'ipbotheroption' => 'دیگر',
 'ipbotherreason' => 'دلیل دیگر/اضافی:',
 'ipbhidename' => 'نهفتن نام کاربری از ویرایش‌ها و فهرست‌ها',
-'ipbwatchuser' => 'پیگیری صفحهٔ کاربری و بحث این کاربر',
+'ipbwatchuser' => 'پیگیری صفحهٔ کاربری و بحث این کاربر',
 'ipb-disableusertalk' => 'جلوگیری از ویرایشی صفحهً بحث توسط خود کاربر در زمانی که بسته است',
 'ipb-change-block' => 'بستن دوبارهٔ کاربر با این تنظیم‌ها',
 'ipb-confirm' => 'تأیید بستن',
@@ -3149,8 +3163,8 @@ $1',
 'allmessagesdefault' => 'متن پیش‌فرض پیغام',
 'allmessagescurrent' => 'متن کنونی پیغام',
 'allmessagestext' => 'این فهرستی از پیغام‌های سامانه‌ای موجود در فضای نام مدیاویکی است.
-چنانچه مایل به مشارکت در محلی‌سازی مدیاویکی هستید لطفاً [//www.mediawiki.org/wiki/Localisation محلی‌سازی مدیاویکی] و [//translatewiki.net translatewiki.net] را ببینید.',
-'allmessagesnotsupportedDB' => "نمی‌توان از '''{{ns:special}}:همهٔ پیغام‌ها''' استفاده کرد چود '''&lrm;\$wgUseDatabaseMessages''' خاموش شده است.",
+چنانچه مایل به مشارکت در محلی‌سازی مدیاویکی هستید لطفاً [https://www.mediawiki.org/wiki/Localisation محلی‌سازی مدیاویکی] و [//translatewiki.net translatewiki.net] را ببینید.',
+'allmessagesnotsupportedDB' => "این صفحه نمی‌تواند استفاده شود به این دلیل که <bdi>'''\$wgUseDatabaseMessages'''</bdi> غیرفعال شده‌است.",
 'allmessages-filter-legend' => 'پالایه',
 'allmessages-filter' => 'پالودن بر اساس وضعیت شخصی‌سازی:',
 'allmessages-filter-unmodified' => 'تغییر نیافته',
@@ -3240,7 +3254,7 @@ $2',
 'javascripttest-title' => 'در حال اجرای آزمایش‌های $1',
 'javascripttest-pagetext-noframework' => 'این صفحه برای اجرای آزمایش‌های جاوا اسکریپت کنار گذاشته شده‌است.',
 'javascripttest-pagetext-unknownframework' => 'چارچوب آزمایشی ناشناخته «$1».',
-'javascripttest-pagetext-frameworks' => 'لطفاً یکی از فریم‌ورک‌های آزمایشی زیر را انتخاب کنید: $1',
+'javascripttest-pagetext-frameworks' => 'لطفاً یکی از چارچوب‌های آزمایش زیر را انتخاب کنید: $1',
 'javascripttest-pagetext-skins' => 'پوسته‌ای را برای اجرای آزمایش‌ها انتخاب کنید:',
 'javascripttest-qunit-intro' => '[$1 مستندات آزمایش] را در mediawiki.org ببینید.',
 'javascripttest-qunit-heading' => 'مجموعه آزمایش QUnit جاوااسکریپت برای مدیاویکی',
@@ -3314,6 +3328,7 @@ $2',
 'tooltip-undo' => '«خنثی‌سازی» این ویرایش را خنثی می‌کند و جعبهٔ ویرایش را در حالت پیش‌نمایش باز می‌کند تا افزودن دلیل در خلاصهٔ ویرایش ممکن شود.',
 'tooltip-preferences-save' => 'ذخیره کردن ترجیحات',
 'tooltip-summary' => 'خلاصه‌ای وارد کنید',
+'interlanguage-link-title' => '$1–$2',
 
 # Stylesheets
 'common.css' => '/* دستورات این بخش همهٔ کاربران را تحت تاثیر قرار می‌دهند. */',
@@ -3343,6 +3358,8 @@ $2',
 'spam_reverting' => 'واگردانی به آخرین نسخه‌ای که پیوندی به $1 ندارد.',
 'spam_blanking' => 'تمام نسخه‌ها حاوی پیوند به $1 بود، در حال خالی کردن',
 'spam_deleting' => 'تمام نسخه‌ها حاوی پیوند به $1 بود، در حال حذف',
+'simpleantispam-label' => "بررسی ضدهرزنگاری.
+این قسمت را پر '''نکنید'''!",
 
 # Info page
 'pageinfo-title' => 'اطلاعات در مورد «$1»',
@@ -3356,6 +3373,7 @@ $2',
 'pageinfo-length' => 'حجم صفحه  (بایت)',
 'pageinfo-article-id' => 'شناسهٔ صفحه',
 'pageinfo-language' => 'زبان محتوای صفحه',
+'pageinfo-content-model' => 'ساختار محتوای صفحه',
 'pageinfo-robot-policy' => '‌فهرست‌کردن توسط ربات‌ها',
 'pageinfo-robot-index' => 'مجاز',
 'pageinfo-robot-noindex' => 'نامجاز',
@@ -3443,7 +3461,7 @@ $1',
 'svg-long-desc' => 'پروندهٔ اس‌وی‌جی، با ابعاد <span dir="ltr">$1 × $2</span> پیکسل، اندازهٔ پرونده: $3',
 'svg-long-desc-animated' => 'پروندهٔ اس‌وی‌جی متحرک، با ابعاد <span dir="ltr">$1 × $2</span> پیکسل، اندازهٔ پرونده: $3',
 'svg-long-error' => 'پرونده SVG نامجاز: $1',
-'show-big-image' => 'تصویر با تفکیک‌پذیری بالاتر',
+'show-big-image' => 'پروندهٔ اصلی',
 'show-big-image-preview' => 'اندازهٔ این پیش‌نمایش: $1.',
 'show-big-image-other' => '{{PLURAL:$2|کیفیت|کیفیت‌های}} دیگر: $1.',
 'show-big-image-size' => '<span dir="ltr">$1 × $2</span> پیکسل',
@@ -3468,6 +3486,10 @@ $1',
 'sp-newimages-showfrom' => 'نشان‌دادن تصویرهای جدید از $2، $1 به بعد',
 
 # Video information, used by Language::formatTimePeriod() to format lengths in the above messages
+'seconds-abbrev' => '$1 ثانیه',
+'minutes-abbrev' => '$1 دقیقه',
+'hours-abbrev' => '$1 ساعت',
+'days-abbrev' => '$1 روز',
 'seconds' => '{{PLURAL:$1|$1ثانیه| $1  ثانیه}}',
 'minutes' => '{{PLURAL: $1|دقیقه|دقیقه}}',
 'hours' => '{{PLURAL: $1|ساعت|ساعت}}',
@@ -3877,7 +3899,7 @@ $1',
 
 'exif-dc-contributor' => 'مشارکت‌کنندگان',
 'exif-dc-coverage' => 'محدوده مکانی و یا زمانی رسانه',
-'exif-dc-date' => 'تاریخ (ها)',
+'exif-dc-date' => 'تاریخ(ها)',
 'exif-dc-publisher' => 'ناشر',
 'exif-dc-relation' => 'رسانه‌های مرتبط',
 'exif-dc-rights' => 'حقوق',
@@ -3913,7 +3935,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ویرایش این پرونده با یک ویرایشگر بیرونی',
-'edit-externally-help' => '(برای اطلاعات بیشتر [//www.mediawiki.org/wiki/Manual:External_editors دستورالعمل تنظیم] را ببینید)',
+'edit-externally-help' => '(برای اطلاعات بیشتر [https://www.mediawiki.org/wiki/Manual:External_editors دستورالعمل تنظیم] را ببینید)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'همه',
@@ -3997,7 +4019,7 @@ $5
 
 # action=purge
 'confirm_purge_button' => 'تأیید',
-'confirm-purge-top' => 'پاک کردن نسخهٔ حافظهٔ نهانی (Cache) این صفحه را تأیید می‌کنید؟',
+'confirm-purge-top' => 'پاککردن نسخهٔ حافظهٔ نهانی (Cache) این صفحه را تأیید می‌کنید؟',
 'confirm-purge-bottom' => 'خالی کردن میانگیر یک صفحه باعث می‌شود که آخرین نسخهٔ آن نمایش یابد.',
 
 # action=watch/unwatch
@@ -4010,6 +4032,7 @@ $5
 'semicolon-separator' => '؛&#32;',
 'comma-separator' => '،&#32;',
 'percent' => '$1٪',
+'quotation-marks' => '$1',
 
 # Multipage image navigation
 'imgmultipageprev' => '&rarr; صفحهٔ پیشین',
@@ -4056,7 +4079,7 @@ $5
 'watchlistedit-noitems' => 'فهرست پی‌گیری‌های شما خالی است.',
 'watchlistedit-normal-title' => 'ویرایش فهرست پی‌گیری‌ها',
 'watchlistedit-normal-legend' => 'حذف عنوان‌ها از فهرست پی‌گیری‌ها',
-'watchlistedit-normal-explain' => 'عنوان‌های موجود در فهرست پیگیری شما در زیر نشان داده شده‌اند.
+'watchlistedit-normal-explain' => 'عنوان‌های موجود در فهرست پیگیری شما در زیر نشان داده شده‌اند.
 برای حذف هر عنوان جعبهٔ کنار آن را علامت بزنید و دکمهٔ «{{int:Watchlistedit-normal-submit}}» را بفشارید.
 شما همچنین می‌توانید [[Special:EditWatchlist/raw|فهرست خام را ویرایش کنید]].',
 'watchlistedit-normal-submit' => 'حذف عنوان‌ها',
@@ -4160,7 +4183,7 @@ $5
 'version-version' => '(نسخه $1)',
 'version-svn-revision' => '(&رلم;r$2)',
 'version-license' => 'اجازه‌نامه',
-'version-poweredby-credits' => "این ویکی توسط '''[//www.mediawiki.org/ مدیاویکی]''' پشتیبانی می‌شود، کلیهٔ حقوق محفوظ است © 2001-$1 $2.",
+'version-poweredby-credits' => "این ویکی توسط '''[https://www.mediawiki.org/ مدیاویکی]''' پشتیبانی می‌شود، کلیهٔ حقوق محفوظ است © 2001-$1 $2.",
 'version-poweredby-others' => 'دیگران',
 'version-poweredby-translators' => 'مترجمان translatewiki.net',
 'version-credits-summary' => 'افراد زیر را به خاطر ویرایش‌هایش در [[Special:Version|مدیاویکی]] معرفی می‌نمائیم.',
@@ -4181,7 +4204,7 @@ $5
 # Special:Redirect
 'redirect' => 'تغییرمسیر توسط پرونده، کاربر یا شناسهٔ نسخه',
 'redirect-legend' => 'تغییرمسیر به یک پرونده یا صفحه',
-'redirect-summary' => 'این صفحهٔ ویژه به پرونده (نام پرونده داده‌شده)، صفحه (شماره شناسهٔ صفحه داده‌شده) یا صفحهٔ کاربری (شناسهٔ عددی کاربری داده‌شده) تغییرمسیر می‌یابد',
+'redirect-summary' => 'این صفحهٔ ویژه به پرونده (نام پرونده داده‌شده)، صفحه (شماره شناسهٔ صفحه داده‌شده) یا صفحهٔ کاربری (شناسهٔ عددی کاربری داده‌شده) تغییرمسیر می‌یابد. طرز استفاده: [[{{#Special:Redirect}}/file/Example.jpg]]، [[{{#Special:Redirect}}/revision/328429]] یا [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'برو',
 'redirect-lookup' => 'جستجو:',
 'redirect-value' => 'مقدار:',
@@ -4203,11 +4226,11 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'صفحه‌های ویژه',
-'specialpages-note' => '----
-* صفحه‌های ویژهٔ عادی.
-* <strong class="mw-specialpagerestricted">صفحه‌های ویژهٔ محدودشده.</strong>',
+'specialpages-note-top' => 'شرح علائم',
+'specialpages-note' => '* صفحه‌های ویژهٔ عادی.
+* <span class="mw-specialpagerestricted">صفحه‌های ویژهٔ محدودشده.</span>',
 'specialpages-group-maintenance' => 'گزارش‌های نگهداری',
-'specialpages-group-other' => 'صÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ù\88Û\8cÚ\98Ù\87Ù\94 Ø¯Û\8cگر',
+'specialpages-group-other' => 'ساÛ\8cر ØµÙ\81Ø­Ù\87â\80\8cÙ\87اÛ\8c Ù\88Û\8cÚ\98Ù\87',
 'specialpages-group-login' => 'ورود / ثبت نام',
 'specialpages-group-changes' => 'تغییرات اخیر و سیاهه‌ها',
 'specialpages-group-media' => 'گزارش بارگذاری رسانه‌ها',
@@ -4294,7 +4317,7 @@ $5
 # New logging system
 'logentry-delete-delete' => '$1 صفحهٔ $3 را {{GENDER:$2|حذف کرد}}',
 'logentry-delete-restore' => '$1 صفحهٔ $3 را {{GENDER:$2|احیا کرد}}',
-'logentry-delete-event' => '$1 پیدایی {{PLURAL:$5|یک مورد سیاهه|$5 مورد سیاهه}} را در $3 {{GENDER:$2|تغییر داد}} : $4',
+'logentry-delete-event' => '$1 پیدایی {{PLURAL:$5|یک مورد سیاهه|$5 مورد سیاهه}} را در $3 {{GENDER:$2|تغییر داد}}: $4',
 'logentry-delete-revision' => '$1 پیدایی {{PLURAL:$5|یک نسخه|$5 نسخه}} صفحه $3 را {{GENDER:$2|تغییر داد}}: $4',
 'logentry-delete-event-legacy' => '$1 پیدایی موارد سیاهه را در $3 {{GENDER:$2|تغییر داد}}',
 'logentry-delete-revision-legacy' => '$1 پیدایی نسخه‌های $3 را {{GENDER:$2|تغییر داد}}',
@@ -4316,7 +4339,7 @@ $5
 'logentry-move-move_redir' => '$1 صفحهٔ $3 را به $4 که تغییرمسیر بود {{GENDER:$2|منتقل کرد}}',
 'logentry-move-move_redir-noredirect' => '$1 صفحهٔ $3 را بدون برجای‌گذاشتن تغییرمسیر به $4 که تغییرمسیر بود {{GENDER:$2|منتقل کرد}}',
 'logentry-patrol-patrol' => '$1 نسخه $4 صفحه $3 را به عنوان گشت خورده {{GENDER:$2|علامت زد}}',
-'logentry-patrol-patrol-auto' => '$1 نسخه $4 صفحه $3 را به طور خودکار به عنوان گشت خورده {{GENDER:$2|علامت زد}}',
+'logentry-patrol-patrol-auto' => '$1 نسخهٔ $4 صفحهٔ $3 را به‌طور خودکار به‌عنوان گشت‌خورده {{GENDER:$2|علامت زد}}',
 'logentry-newusers-newusers' => 'حساب کاربری $1 {{GENDER:$2|ایجاد شد}}',
 'logentry-newusers-create' => 'حساب کاربری $1 {{GENDER:$2|ایجاد شد}}',
 'logentry-newusers-create2' => 'حساب کاربری $3 توسط $1 {{GENDER:$2|ایجاد شد}}',
@@ -4417,4 +4440,17 @@ $5
 'limitreport-expansiondepth' => 'بیشترین عمق گسترش',
 'limitreport-expensivefunctioncount' => 'تعداد تابع تجزیه‌گر پرمصرف',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'بسط‌دادن الگوها',
+'expand_templates_intro' => 'این صفحهٔ ویژه متنی را دریافت کرده و تمام الگوهای به‌کاررفته در آن را به طور بازگشتی بسط می‌دهد. همچنین تابع‌های تجزیه چون <code><nowiki>{{</nowiki>#language:…}}</code> و متغیرهایی چون  <code><nowiki>{{</nowiki>CURRENTDAY}}</code> را هم بسط می‌دهد — در واقع تقریباً هرچه را که داخل دوآکولاد باشد. این کار با صدازدن مرحلهٔ تجزیهٔ مربوط در خود مدیاویکی صورت می‌گیرد.',
+'expand_templates_title' => 'عنوان موضوع، برای {{FULLPAGENAME}} و غیره:',
+'expand_templates_input' => 'متن ورودی:',
+'expand_templates_output' => 'نتیجه',
+'expand_templates_xml_output' => 'خروجی XML',
+'expand_templates_ok' => 'تأیید',
+'expand_templates_remove_comments' => 'حذف ملاحظات',
+'expand_templates_remove_nowiki' => 'خنثی کردن تگ‌های <nowiki> در نتیجه',
+'expand_templates_generate_xml' => 'نمایش درخت تجزیهٔ XML',
+'expand_templates_preview' => 'پیش‌نمایش',
+
 );
index 1fd5da9..c4434b7 100644 (file)
@@ -22,6 +22,7 @@
  * @author Kaganer
  * @author Kulmalukko
  * @author Linnea
+ * @author Mies
  * @author Mobe
  * @author Nedergard
  * @author Nike
@@ -75,7 +76,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Kelpaamaton_otsikko' ),
        'Blankpage'                 => array( 'Tyhjä_sivu' ),
        'Block'                     => array( 'Estä' ),
-       'Blockme'                   => array( 'Estä_minut' ),
        'Booksources'               => array( 'Kirjalähteet' ),
        'BrokenRedirects'           => array( 'Virheelliset_ohjaukset', 'Virheelliset_uudelleenohjaukset' ),
        'Categories'                => array( 'Luokat' ),
@@ -87,10 +87,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Luo_tunnus' ),
        'Deadendpages'              => array( 'Linkittömät_sivut' ),
        'DeletedContributions'      => array( 'Poistetut_muokkaukset' ),
-       'Disambiguations'           => array( 'Täsmennyssivut' ),
        'DoubleRedirects'           => array( 'Kaksinkertaiset_ohjaukset', 'Kaksinkertaiset_uudelleenohjaukset' ),
        'EditWatchlist'             => array( 'Muokkaa_tarkkailulistaa' ),
        'Emailuser'                 => array( 'Lähetä_sähköpostia' ),
+       'ExpandTemplates'           => array( 'Mallineiden_laajennus' ),
        'Export'                    => array( 'Vie_sivuja' ),
        'Fewestrevisions'           => array( 'Vähiten_muokatut_sivut' ),
        'FileDuplicateSearch'       => array( 'Kaksoiskappaleiden_haku' ),
@@ -133,6 +133,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Suojatut_sivut' ),
        'Protectedtitles'           => array( 'Suojatut_sivunimet' ),
        'Randompage'                => array( 'Satunnainen_sivu' ),
+       'RandomInCategory'          => array( 'Satunnainen_sivu_luokasta' ),
        'Randomredirect'            => array( 'Satunnainen_ohjaus', 'Satunnainen_uudelleenohjaus' ),
        'Recentchanges'             => array( 'Tuoreet_muutokset' ),
        'Recentchangeslinked'       => array( 'Linkitetyt_muutokset' ),
@@ -226,8 +227,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'keskitetty', 'keski', 'center', 'centre' ),
        'img_framed'                => array( '1', 'kehys', 'kehystetty', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'kehyksetön', 'frameless' ),
-       'img_page'                  => array( '1', 'sivu=$1', 'sivu $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'yläoikea', 'yläoikea=$1', 'yläoikea $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'sivu=$1', 'sivu_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'yläoikea', 'yläoikea=$1', 'yläoikea_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'reunus', 'border' ),
        'img_baseline'              => array( '1', 'perustaso', 'baseline' ),
        'img_sub'                   => array( '1', 'alaindeksi', 'sub' ),
@@ -591,12 +592,10 @@ $1',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Haettu osoitteesta $1',
 'youhavenewmessages' => 'Sinulle on $1 ($2).',
-'newmessageslink' => 'uusia viestejä',
-'newmessagesdifflink' => 'viimeisin muutos',
 'youhavenewmessagesfromusers' => 'Sinulle on $1 {{PLURAL:$3|toiselta käyttäjältä|$3 käyttäjältä}} ($2).',
 'youhavenewmessagesmanyusers' => 'Sinulle on $1 uusia viestejä useilta käyttäjiltä ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|uusi viesti|uusia viestejä}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|viimeinen muutos|viimeiset muutokset}}',
+'newmessageslinkplural' => '{{PLURAL:$1|uusi viesti|999=uusia viestejä}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|viimeinen muutos|999=viimeiset muutokset}}',
 'youhavenewmessagesmulti' => 'Sinulla on uusia viestejä sivuilla $1',
 'editsection' => 'muokkaa',
 'editold' => 'muokkaa',
@@ -724,7 +723,8 @@ Lukituksen asettanut ylläpitäjä on antanut seuraavan syyn toimenpiteelle: $3.
 'invalidtitle-knownnamespace' => 'Virheellinen sivunimi, nimiavaruus "$2" ja teksti "$3"',
 'invalidtitle-unknownnamespace' => 'Virheellinen sivunimi, tuntematon nimiavaruus numero $1 ja teksti "$2"',
 'exception-nologin' => 'Et ole kirjautunut sisään',
-'exception-nologin-text' => 'Tämä sivu tai toiminto edellyttää sisäänkirjautumista tähän wikiin.',
+'exception-nologin-text' => 'Ole hyvä ja [[Special:Userlogin|kirjaudu sisään]], niin pääset tälle sivulle tai tähän toimintoon.',
+'exception-nologin-text-manual' => 'Sinun pitää $1 jotta pääset tälle sivulle tai toimintoon.',
 
 # Virus scanner
 'virus-badscanner' => "Virheellinen asetus: Tuntematon virustutka: ''$1''",
@@ -771,7 +771,7 @@ Huomaa, että jotkut sivut saattavat näkyä edelleen kuin olisit kirjautunut si
 'gotaccount' => "Jos sinulla on jo tunnus, voit '''$1'''.",
 'gotaccountlink' => 'kirjautua sisään',
 'userlogin-resetlink' => 'Unohditko salasanasi?',
-'userlogin-resetpassword-link' => 'Vaihda salasanaasi',
+'userlogin-resetpassword-link' => 'Unohditko salasanasi?',
 'helplogin-url' => 'Help:Sisäänkirjautuminen',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Auta sisäänkirjautumisessa]]',
 'userlogin-loggedin' => 'Olet jo kirjautunut sisään tunnuksella {{GENDER:$1|$1}}.
@@ -824,18 +824,20 @@ Salli evästeiden käyttö, ja sen jälkeen kirjaudu sisään juuri luomallasi k
 'passwordremindertext' => 'Joku IP-osoitteesta $1 pyysi {{GRAMMAR:partitive|{{SITENAME}}}} ($4) lähettämään uuden salasanan. Väliaikainen salasana käyttäjälle $2 on nyt $3. Kirjaudu sisään ja vaihda salasana. Väliaikainen salasana vanhenee {{PLURAL:$5|yhden päivän|$5 päivän}} kuluttua.
 
 Jos joku muu on tehnyt tämän pyynnön, tai jos olet muistanut salasanasi ja et halua vaihtaa sitä, voit jättää tämän viestin huomiotta ja jatkaa vanhan salasanan käyttöä.',
-'noemail' => 'Käyttäjälle "$1" ei ole määritelty sähköpostiosoitetta.',
+'noemail' => 'Käyttäjälle $1 ei ole määritelty sähköpostiosoitetta.',
 'noemailcreate' => 'Sinun on annettava voimassa oleva sähköpostiosoite',
 'passwordsent' => 'Uusi salasana on lähetetty käyttäjän <b>$1</b> sähköpostiosoitteeseen.
 Ole hyvä ja kirjaudu sisään kun olet saanut sen.',
 'blocked-mailpassword' => 'Osoitteellesi on asetettu muokkausesto, joka estää käyttämästä salasanamuistutustoimintoa.',
-'eauthentsent' => 'Varmennussähköposti on lähetetty annettuun sähköpostiosoitteeseen. Muita viestejä ei lähetetä, ennen kuin olet toiminut viestin ohjeiden mukaan ja varmistanut, että sähköpostiosoite kuuluu sinulle.',
+'eauthentsent' => 'Varmennussähköposti on lähetetty annettuun sähköpostiosoitteeseen.
+Muita viestejä ei lähetetä, ennen kuin olet toiminut viestin ohjeiden mukaan ja varmistanut, että sähköpostiosoite kuuluu sinulle.',
 'throttled-mailpassword' => 'Salasananpalautusviesti on lähetetty {{PLURAL:$1|kuluvan|kuluvien $1}} tunnin aikana. Salasananpalautusviestejä lähetetään enintään {{PLURAL:$1|tunnin|$1 tunnin}} välein.',
 'mailerror' => 'Virhe lähetettäessä sähköpostia: $1',
 'acct_creation_throttle_hit' => 'IP-osoitteestasi on luotu tähän wikiin jo {{PLURAL:$1|yksi tunnus|$1 tunnusta}} päivän aikana, joka suurin sallittu määrä tälle ajalle.
 Tästä johtuen tästä IP-osoitteesta ei voi tällä hetkellä luoda uusia tunnuksia.',
 'emailauthenticated' => 'Sähköpostiosoitteesi varmennettiin $2 kello $3.',
-'emailnotauthenticated' => 'Sähköpostiosoitettasi ei ole vielä varmennettu. Sähköpostia ei lähetetä liittyen alla oleviin toimintoihin.',
+'emailnotauthenticated' => 'Sähköpostiosoitettasi ei ole vielä varmennettu.
+Sähköpostia ei lähetetä liittyen alla oleviin toimintoihin.',
 'noemailprefs' => 'Sähköpostiosoitetta ei ole määritelty.',
 'emailconfirmlink' => 'Varmenna sähköpostiosoite',
 'invalidemailaddress' => 'Sähköpostiosoitetta ei voida hyväksyä, koska se ei ole oikeassa muodossa. Ole hyvä ja anna oikea sähköpostiosoite tai jätä kenttä tyhjäksi.',
@@ -879,14 +881,14 @@ Nimesi näytetään käyttäjätunnuksesi sijasta sivun tekijäluettelossa.',
 'resetpass-wrong-oldpass' => 'Virheellinen väliaikainen tai nykyinen salasana.
 Olet saattanut jo onnistuneesti vaihtaa salasanasi tai pyytää uutta väliaikaista salasanaa.',
 'resetpass-temp-password' => 'Väliaikainen salasana:',
-'resetpass-abort-generic' => 'Lisäosa hylkäsi salasanan vaihdon.',
+'resetpass-abort-generic' => 'Laajennus keskeytti salasanan vaihdon.',
 
 # Special:PasswordReset
-'passwordreset' => 'Salasanan vaihto',
-'passwordreset-text-one' => 'Täytä tämä lomake vaihtaaksesi salasanasi.',
-'passwordreset-text-many' => '{{PLURAL:$1|Täytä yksi kentistä alustaaksesi salasanasi.}}',
-'passwordreset-legend' => 'Salasanan vaihto',
-'passwordreset-disabled' => 'Salasanojen vaihtaminen ei ole mahdollista tässä wikissä.',
+'passwordreset' => 'Salasanan uudistus',
+'passwordreset-text-one' => 'Täytä tämä lomake uudistaaksesi salasanasi.',
+'passwordreset-text-many' => '{{PLURAL:$1|Täytä yksi kentistä uudistaaksesi salasanasi.}}',
+'passwordreset-legend' => 'Salasanan uudistus',
+'passwordreset-disabled' => 'Salasanojen uudistaminen ei ole mahdollista tässä wikissä.',
 'passwordreset-emaildisabled' => 'Sähköpostitoiminnot on poistettu käytöstä tässä wikissä.',
 'passwordreset-username' => 'Käyttäjätunnus:',
 'passwordreset-domain' => 'Verkkotunnus:',
@@ -915,8 +917,8 @@ pyynnön, tai muistat sittenkin vanhan salasanasi, etkä halua muuttaa sitä,
 voit jättää tämän viestin huomiotta ja jatkaa vanhan salasanan käyttöä.',
 'passwordreset-emailelement' => 'Käyttäjätunnus: $1
 Väliaikainen salasana: $2',
-'passwordreset-emailsent' => 'Salasanan palautuksesta kertova viesti on lähetetty sähköpostitse.',
-'passwordreset-emailsent-capture' => 'Salasanan palautuksesta kertova sähköpostiviesti on lähetetty, ja se näkyy myös alla.',
+'passwordreset-emailsent' => 'Salasanan uudistamisesta kertova viesti on lähetetty sähköpostitse.',
+'passwordreset-emailsent-capture' => 'Salasanan uudistamisesta kertova sähköpostiviesti on lähetetty, ja se näkyy myös alla.',
 'passwordreset-emailerror-capture' => 'Allaoleva sähköpostiviesti luotiin, mutta sen lähettäminen {{GENDER:$2|käyttäjälle}} epäonnistui: $1',
 
 # Special:ChangeEmail
@@ -933,9 +935,9 @@ Väliaikainen salasana: $2',
 
 # Special:ResetTokens
 'resettokens' => 'Uudista avaimet',
-'resettokens-text' => 'Tällä sivulla voit uudistaa avaimesi, jotka mahdollistavat pääsyn käyttäjätunnukseesi liittyviin tiettyihin yksityisiin tietoihin.
+'resettokens-text' => "Tällä sivulla voit uudistaa avaimesi (''eng.'' reset tokens), jotka mahdollistavat pääsyn käyttäjätunnukseesi liittyviin tiettyihin yksityisiin tietoihin.
 
-Sinun pitäisi tehdä tämä, jos olet vahingossa jakanut avaimet jonkun kanssa tai jos käyttäjätunnuksesi on vaarannettu.',
+Sinun pitäisi tehdä tämä, jos olet vahingossa jakanut avaimet jonkun kanssa tai jos käyttäjätunnuksesi on vaarannettu.",
 'resettokens-no-tokens' => 'Avaimia ei ole uudistettavaksi.',
 'resettokens-legend' => 'Uudista avaimet',
 'resettokens-tokens' => 'Avaimet:',
@@ -1136,7 +1138,7 @@ Jos olet kirjautuneena sisään, voit poistaa tämän varoituksen käytöstä as
 
 # Content models
 'content-model-wikitext' => 'wikiteksti',
-'content-model-text' => 'teksti',
+'content-model-text' => 'pelkkä teksti',
 'content-model-javascript' => 'JavaScript',
 'content-model-css' => 'CSS',
 
@@ -1254,8 +1256,9 @@ Voit silti nähdä tämän muutoksen. Lisätietoja löytyy [{{fullurl:{{#Special
 Muut ylläpitäjät {{GRAMMAR:inessive|{{SITENAME}}}} voivat silti tarkastella piilotettua sisältöä, ja he voivat palauttaa sen näkyviin tämän käyttöliittymän kautta, ellei tätä ole erikseen rajoitettu.",
 'revdelete-confirm' => 'Varmista, että haluat tehdä tämän – ymmärrät seuraukset ja teet tämän [[{{MediaWiki:Policy-url}}|käytäntöjen]] mukaisesti.',
 'revdelete-suppress-text' => "Häivytystä pitäisi käyttää '''vain''' seuraavissa tapauksissa:
+* Mahdollisesti henkilön kunniaa loukkaavia tietoja
 * Sopimattomat henkilötiedot
-*: ''kotiosoitteet, puhelinnumerot, sosiaaliturvatunnukset ja muut.''",
+*: ''kotiosoitteet, puhelinnumerot, henkilötunnukset ja muut.''",
 'revdelete-legend' => 'Aseta version näkyvyyden rajoitukset',
 'revdelete-hide-text' => 'Piilota version tekstisisältö',
 'revdelete-hide-image' => 'Piilota tiedoston sisältö',
@@ -1264,8 +1267,8 @@ Muut ylläpitäjät {{GRAMMAR:inessive|{{SITENAME}}}} voivat silti tarkastella p
 'revdelete-hide-user' => 'Piilota tekijän tunnus tai IP-osoite',
 'revdelete-hide-restricted' => 'Häivytä tiedot sekä ylläpitäjien että muiden käyttäjien näkyviltä',
 'revdelete-radio-same' => '(älä muuta)',
-'revdelete-radio-set' => 'Kyllä',
-'revdelete-radio-unset' => 'Ei',
+'revdelete-radio-set' => 'Piilossa',
+'revdelete-radio-unset' => 'Näkyvissä',
 'revdelete-suppress' => 'Häivytä tiedot myös ylläpitäjien näkyviltä samalla kun piilotat ne muilta käyttäjiltä',
 'revdelete-unsuppress' => 'Poista rajoitukset palautetuilta versioilta',
 'revdelete-log' => 'Syy:',
@@ -1281,14 +1284,17 @@ $1",
 'revdel-restore-visible' => 'näkyvät versiot',
 'pagehist' => 'Sivun muutoshistoria',
 'deletedhist' => 'Poistettujen versioiden historia',
-'revdelete-hide-current' => 'Virhe tapahtui $2, $1 päivätyn kohteen piilottamisessa: tämä on nykyinen versio. Sitä ei voi piilottaa.',
+'revdelete-hide-current' => 'Virhe piilotettaessa kohdetta päivämäärällä $1 kello $2: Tämä on uusin versio.
+Sitä ei voi piilottaa.',
 'revdelete-show-no-access' => 'Virhe näyttäessä kohtaa $2 kello $1: kohta on merkitty ”rajoitetuksi”.
 Sinulla ei ole oikeutta siihen.',
-'revdelete-modify-no-access' => 'Virhe tapahtui $2, $1 kohteen muokkauksessa: tämä kohde on merkitty "rajoitetuksi". Sinulla ei ole oikeuksia sen muokkaukseen.',
-'revdelete-modify-missing' => 'Virhe muuttaessa kohdetta, jonka tunnus on $1: Se puuttuu tietokannasta.',
-'revdelete-no-change' => "'''Varoitus:''' kohteessa $2 kello $1 on jo valmiiksi haluamasi näkyvyysasetukset.",
-'revdelete-concurrent-change' => 'Virhe $2, $1 päivätyn kohteen muokkauksessa: sen tilan on näköjään muuttanut joku sillä aikaa kun yritit muokata sitä. Ole hyvä ja tarkista lokit.',
-'revdelete-only-restricted' => 'Virhe piilotettaessa $1 kello $2 päivättyä kohdetta: Et voi poistaa kohteita ylläpitäjien näkyviltä valitsematta myös jotain muuta näkyvyysasetusta.',
+'revdelete-modify-no-access' => 'Virhe kohteen päivämäärällä $1 kello $2 muutoksessa: tämä kohde on merkitty "rajoitetuksi". 
+Sinulla ei ole oikeutta muuttaa kohdetta.',
+'revdelete-modify-missing' => 'Virhe muuttaessa kohdetta, jonka tunniste on $1: Se puuttuu tietokannasta.',
+'revdelete-no-change' => "'''Varoitus.''' Kohteessa päivämäärällä $1 kello $2 on jo valmiiksi haluamasi näkyvyysasetukset.",
+'revdelete-concurrent-change' => 'Virhe kohteen päivämäärällä $1 kello $2 muutoksessa: sen näkyvyysasetuksia on ilmeisesti joku muuttanut sillä aikaa kun yritit muuttaa sitä.
+Ole hyvä ja tarkista lokit.',
+'revdelete-only-restricted' => 'Virhe piilotettaessa kohdetta päivämäärällä $1 kello $2: Et voi häivyttää kohteita ylläpitäjien näkyviltä valitsematta sen lisäksi jotain muuta näkyvyysasetusta.',
 'revdelete-reason-dropdown' => '*Yleiset poistosyyt
 ** Tekijänoikeusrikkomus
 ** Sopimattomat henkilötiedot
@@ -1399,7 +1405,7 @@ $1 {{int:pipe-separator}} $2',
 'searchall' => 'kaikki',
 'showingresults' => "{{PLURAL:$1|'''Yksi''' tulos|'''$1''' tulosta}} tuloksesta '''$2''' alkaen.",
 'showingresultsnum' => "Alla on {{PLURAL:$3|'''Yksi''' hakutulos|'''$3''' hakutulosta}} alkaen '''$2.''' tuloksesta.",
-'showingresultsheader' => "{{PLURAL:$5|Tulokset '''$1'''–'''$3'''|Tulokset '''$1'''–'''$2''' kaikkiaan '''$3''' osuman joukosto}} haulle '''$4'''",
+'showingresultsheader' => "{{PLURAL:$5|Tulokset '''$1'''–'''$3'''|Tulokset '''$1'''–'''$2''' kaikkiaan '''$3''' osuman joukosta}} haulle '''$4'''",
 'nonefound' => "'''Huomautus''': Haku kohdistuu oletuksena vain tiettyihin nimiavaruuksiin.
 Kokeile lisätä haun alkuun ''all:'', niin haku kohdistuu kaikkeen sisältöön (mukaan lukien keskustelut, mallineet jne.) tai kohdista haku haluttuun nimiavaruuteen.",
 'search-nonefound' => 'Hakusi ei tuottanut tulosta.',
@@ -1410,7 +1416,7 @@ Kokeile lisätä haun alkuun ''all:'', niin haku kohdistuu kaikkeen sisältöön
 'powersearch-field' => 'Etsi',
 'powersearch-togglelabel' => 'Muuta valintaa',
 'powersearch-toggleall' => 'Valitse kaikki',
-'powersearch-togglenone' => 'Poista valinnat',
+'powersearch-togglenone' => 'Ei mitään',
 'search-external' => 'Ulkoinen haku',
 'searchdisabled' => 'Tekstihaku on poistettu toistaiseksi käytöstä suuren kuorman vuoksi. Voit käyttää alla olevaa Googlen hakukenttää sivujen etsimiseen, kunnes haku tulee taas käyttöön. <small>Huomaa, että ulkopuoliset kopiot {{GRAMMAR:genitive|{{SITENAME}}}} sisällöstä eivät välttämättä ole ajan tasalla.</small>',
 'search-error' => 'Virhe ilmaantui haettaessa: $1',
@@ -1419,8 +1425,7 @@ Kokeile lisätä haun alkuun ''all:'', niin haku kohdistuu kaikkeen sisältöön
 'preferences' => 'Asetukset',
 'mypreferences' => 'Asetukset',
 'prefs-edits' => 'Muokkauksia',
-'prefsnologin' => 'Et ole kirjautunut sisään.',
-'prefsnologintext' => 'Sinun täytyy <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kirjautua sisään]</span>, jotta voisit muuttaa asetuksiasi.',
+'prefsnologintext2' => 'Sinun pitää $1 ennen kuin voit muuttaa käyttäjän asetuksia.',
 'changepassword' => 'Salasanan vaihto',
 'prefs-skin' => 'Ulkoasu',
 'skin-preview' => 'esikatselu',
@@ -1602,7 +1607,7 @@ Tämä tieto on julkinen.',
 'right-reupload-own' => 'Korvata itsetallennettu tiedosto uudella tiedostolla',
 'right-reupload-shared' => 'Korvata jaettuun mediavarastoon tallennettuja tiedostoja paikallisesti',
 'right-upload_by_url' => 'Tallentaa tiedostoja verkko-osoitteella',
-'right-purge' => 'Päivittää tiedoston välimuistitetun version ilman varmennussivua',
+'right-purge' => 'Tyhjentää sivuston välimuisti ilman varmennussivua',
 'right-autoconfirmed' => 'IP-pohjaiset nopeusrajoitukset eivät ole voimassa',
 'right-bot' => 'Kohdellaan automaattisena prosessina',
 'right-nominornewtalk' => 'Tehdä pieniä muokkauksia käyttäjien keskustelusivuille siten, että käyttäjälle ei ilmoiteta siitä uutena viestinä',
@@ -1612,9 +1617,9 @@ Tämä tieto on julkinen.',
 'right-bigdelete' => 'Poistaa sivuja, joilla on pitkä historia',
 'right-deletelogentry' => 'Poistaa ja palauttaa tiettyjä lokimerkintöjä',
 'right-deleterevision' => 'Poistaa ja palauttaa sivujen versioita',
-'right-deletedhistory' => 'Tarkastella poistettuja versiotietoja ilman niihin liittyvää sisältöä',
+'right-deletedhistory' => 'Tarkastella poistettujen versioiden tietoja ilman niihin liittyvää tekstisisältöä',
 'right-deletedtext' => 'Tarkastella poistettujen sivujen tekstiä ja muutoksia poistettujen versioiden välillä',
-'right-browsearchive' => 'Tarkastella poistettuja sivuja',
+'right-browsearchive' => 'Hakea poistettuja sivuja',
 'right-undelete' => 'Palauttaa poistettuja sivuja',
 'right-suppressrevision' => 'Tarkastella ja palauttaa ylläpitäjiltä piilotettuja versioita',
 'right-suppressionlog' => 'Tarkastella yksityisiä lokeja',
@@ -1631,22 +1636,22 @@ Tämä tieto on julkinen.',
 'right-editusercssjs' => 'Muokata toisten käyttäjien CSS- ja JavaScript-tiedostoja',
 'right-editusercss' => 'Muokata toisten käyttäjien CSS-tiedostoja',
 'right-edituserjs' => 'Muokata toisten käyttäjien JavaScript-tiedostoja',
-'right-editmyusercss' => 'Muokata omia CSS-tiedostojaan',
-'right-editmyuserjs' => 'Muokata omia JavaScript-tiedostojaan',
-'right-viewmywatchlist' => 'Tarkastella tarkkailulistaasi',
+'right-editmyusercss' => 'Muokata omia CSS-tiedostoja',
+'right-editmyuserjs' => 'Muokata omia JavaScript-tiedostoja',
+'right-viewmywatchlist' => 'Nähdä oma tarkkailulista',
 'right-editmywatchlist' => 'Muokata tarkkailulistaasi. Huomaa, että jotkin toiminnot lisäävät yhä sivuja listallesi riippumatta tästä oikeudesta.',
 'right-viewmyprivateinfo' => 'Nähdä omat yksityiset tietosi (esim. sähköpostiosoite, oikea nimi)',
 'right-editmyprivateinfo' => 'Muokata omia yksityisiä tietojasi (esim. sähköpostiosoite, oikea nimi)',
 'right-editmyoptions' => 'Muokata omia asetuksiasi',
 'right-rollback' => 'Palauttaa nopeasti käyttäjän viimeisimmät muokkaukset sivuun',
-'right-markbotedits' => 'Kumota muokkauksia bottimerkinnällä',
+'right-markbotedits' => 'Merkitä muokkausten palauttaminen botilla tehdyksi',
 'right-noratelimit' => 'Ohittaa nopeusrajoitukset',
 'right-import' => 'Tuoda sivuja muista wikeistä',
 'right-importupload' => 'Tuoda sivuja tiedostosta',
-'right-patrol' => 'Merkitä muokkaukset tarkastetuiksi',
-'right-autopatrol' => 'Muokkaukset aina valmiiksi tarkastetuksi merkittyjä',
+'right-patrol' => 'Merkitä muiden tekemät muokkaukset tarkastetuiksi',
+'right-autopatrol' => 'Omat muokkaukset on automaattisesti merkitty tarkastetuksi',
 'right-patrolmarks' => 'Nähdä tarkastusmerkit tuoreissa muutoksissa',
-'right-unwatchedpages' => 'Tarkastella listaa tarkkailemattomista sivuista',
+'right-unwatchedpages' => 'Nähdä luetteloa tarkkailemattomista sivuista',
 'right-mergehistory' => 'Yhdistää sivujen historioita',
 'right-userrights' => 'Muuttaa kaikkia käyttäjäoikeuksia',
 'right-userrights-interwiki' => 'Muokata käyttäjien oikeuksia muissa wikeissä',
@@ -1671,7 +1676,7 @@ Tämä tieto on julkinen.',
 'action-createaccount' => 'luoda tätä käyttäjätunnusta',
 'action-minoredit' => 'merkitä tätä muokkausta pieneksi',
 'action-move' => 'siirtää tätä sivua',
-'action-move-subpages' => 'siirtää tätä sivua, ja sen alasivuja',
+'action-move-subpages' => 'siirtää tätä sivua eikä sen alasivuja',
 'action-move-rootuserpages' => 'siirtää käyttäjäsivuja',
 'action-movefile' => 'siirtää tätä tiedostoa',
 'action-upload' => 'tallentaa tätä tiedostoa',
@@ -1683,7 +1688,7 @@ Tämä tieto on julkinen.',
 'action-deleterevision' => 'poistaa tätä versiota',
 'action-deletedhistory' => 'tarkastella tämän sivun poistettua historiaa',
 'action-browsearchive' => 'etsiä poistettuja sivuja',
-'action-undelete' => 'palauttaa tätä sivua',
+'action-undelete' => 'palauttaa tätä poistettua sivua',
 'action-suppressrevision' => 'tarkastella ja palauttaa tätä piilotettua versiota',
 'action-suppressionlog' => 'tarkastella tätä yksityislokia',
 'action-block' => 'estää tätä käyttäjää muokkaamasta',
@@ -1691,9 +1696,9 @@ Tämä tieto on julkinen.',
 'action-rollback' => 'käyttää nopeaa palautusta kumoamaan viimeisen käyttäjän viimeiset muutokset sivuun',
 'action-import' => 'tuoda sivuja toisesta wikistä',
 'action-importupload' => 'tuoda sivuja tiedostosta',
-'action-patrol' => 'merkitä muiden muokkauksia tarkastetuiksi',
-'action-autopatrol' => 'saada muokkaukset automaattisesti tarkastetuiksi',
-'action-unwatchedpages' => 'tarkastella tarkkailemattomien sivujen listaa',
+'action-patrol' => 'merkitä muiden tekemiä muokkauksia tarkastetuiksi',
+'action-autopatrol' => 'merkitä omia muokkauksiasi tarkastetuiksi',
+'action-unwatchedpages' => 'nähdä luetteloa tarkkailemattomista sivuista',
 'action-mergehistory' => 'yhdistää tämän sivun historiaa',
 'action-userrights' => 'muokata kaikkia käyttöoikeuksia',
 'action-userrights-interwiki' => 'muokata muiden wikien käyttäjien käyttöoikeuksia',
@@ -1717,6 +1722,8 @@ Tämä tieto on julkinen.',
 'recentchanges-label-minor' => 'Tämä on pieni muutos',
 'recentchanges-label-bot' => 'Tämän muutoksen suoritti botti',
 'recentchanges-label-unpatrolled' => 'Tätä muutosta ei ole vielä tarkastettu',
+'recentchanges-label-plusminus' => 'Sivun koon muutos tavuina',
+'recentchanges-legend-newpage' => '(katso myös [[Special:NewPages|lista uusista sivuista]])',
 'rcnote' => 'Alla on {{PLURAL:$1|yksi muutos|$1 tuoreinta muutosta}} {{PLURAL:$2|yhden päivän|$2 viime päivän}} ajalta $4 kello $5 asti.',
 'rcnotefrom' => 'Alla on muutokset <b>$2</b> lähtien. Enintään <b>$1</b> merkintää näytetään.',
 'rclistfrom' => 'Näytä uudet muutokset $1 alkaen',
@@ -1758,7 +1765,7 @@ Tämä tieto on julkinen.',
 'reuploaddesc' => 'Peruuta tallennus ja palaa tallennuslomakkeelle.',
 'upload-tryagain' => 'Lähetä muutettu tiedostokuvaus',
 'uploadnologin' => 'Et ole kirjautunut sisään',
-'uploadnologintext' => 'Sinun pitää $1 tallentaaksesi tiedostoja.',
+'uploadnologintext' => 'Sinun pitää $1, jotta voit tallentaa tiedostoja.',
 'upload_directory_missing' => 'Tallennushakemisto $1 puuttuu, eikä palvelin pysty luomaan sitä.',
 'upload_directory_read_only' => 'Palvelimella ei ole kirjoitusoikeuksia tallennushakemistoon $1.',
 'uploaderror' => 'Tallennusvirhe',
@@ -2044,30 +2051,30 @@ Voit tarvittaessa muokata [$2 tiedoston kuvaussivua] kohteessa.',
 'uploadnewversion-linktext' => 'Tallenna uusi versio tästä tiedostosta',
 'shared-repo-from' => 'kohteesta $1',
 'shared-repo' => 'jaettu mediavarasto',
-'upload-disallowed-here' => 'Et voi korvata tätä tiedostoa.',
+'upload-disallowed-here' => 'Et voi korvata tätä tiedostoa uudella tiedostolla.',
 
 # File reversion
 'filerevert' => 'Tiedoston $1 palautus',
 'filerevert-legend' => 'Tiedoston palautus',
-'filerevert-intro' => '<span class="plainlinks">Olet palauttamassa tiedostoa \'\'\'[[Media:$1|$1]]\'\'\' [$4 versioon, joka luotiin $2 kello $3].</span>',
-'filerevert-comment' => 'Syy',
-'filerevert-defaultcomment' => 'Palautettiin versioon, joka luotiin $1 kello $2 (UTC)',
-'filerevert-submit' => 'Palauta',
-'filerevert-success' => '<span class="plainlinks">\'\'\'[[Media:$1|$1]]\'\'\' on palautettu [$4 versioon, joka luotiin $2 kello $3].</span>',
+'filerevert-intro' => "Olet palauttamassa takaisin tiedostoa '''[[Media:$1|$1]]''' [$4 versioon, joka luotiin $2 kello $3].",
+'filerevert-comment' => 'Syy:',
+'filerevert-defaultcomment' => 'Palautettiin takaisin versioon, joka luotiin $1 kello $2 (UTC)',
+'filerevert-submit' => 'Suorita palauttaminen',
+'filerevert-success' => "'''[[Media:$1|$1]]''' on palautettu takaisin [$4 versioon, joka luotiin $2 kello $3].",
 'filerevert-badversion' => 'Tiedostosta ei ole luotu versiota kyseisellä ajan hetkellä.',
 
 # File deletion
 'filedelete' => 'Tiedoston $1 poisto',
 'filedelete-legend' => 'Tiedoston poisto',
-'filedelete-intro' => "Olet poistamassa tiedostoa '''[[Media:$1|$1]]''' ja kaiken sen historian.",
-'filedelete-intro-old' => '<span class="plainlinks">Olet poistamassa tiedoston \'\'\'[[Media:$1|$1]]\'\'\' [$4 $3 kello $2 luotua versiota].</span>',
-'filedelete-comment' => 'Syy',
+'filedelete-intro' => "Olet poistamassa tiedoston '''[[Media:$1|$1]]''' ja kaiken sen historian.",
+'filedelete-intro-old' => '<span class="plainlinks">Olet poistamassa tiedoston \'\'\'[[Media:$1|$1]]\'\'\' [$4 päivämäärällä $2 kello $3 luotua versiota].</span>',
+'filedelete-comment' => 'Syy:',
 'filedelete-submit' => 'Poista',
 'filedelete-success' => "Tiedosto '''$1''' on poistettu.",
-'filedelete-success-old' => "Tiedoston '''[[Media:$1|$1]]''' $3 kello $2 luotu versio on poistettu.",
+'filedelete-success-old' => "Tiedoston '''[[Media:$1|$1]]''' $2 kello $3 luotu versio on poistettu.",
 'filedelete-nofile' => "Tiedostoa '''$1''' ei ole.",
-'filedelete-nofile-old' => "Tiedostosta '''$1''' ei ole olemassa pyydettyä versiota.",
-'filedelete-otherreason' => 'Muu syy tai tarkennus',
+'filedelete-nofile-old' => "Tiedostosta '''$1''' ei ole olemassa arkistossa olevaa versiota, jolla on annetut ominaisuudet.",
+'filedelete-otherreason' => 'Muu syy tai tarkennus:',
 'filedelete-reason-otherlist' => 'Muu syy',
 'filedelete-reason-dropdown' => '*Yleiset poistosyyt
 ** Kaksoiskappale
@@ -2457,7 +2464,7 @@ Palaute ja lisäapu osoitteessa:
 'exblank' => 'oli tyhjä',
 'delete-confirm' => 'Sivun ”$1” poistaminen',
 'delete-legend' => 'Sivun poisto',
-'historywarning' => "'''Varoitus:''' Sivua, jota olet poistamassa on muokattu noin $1 {{PLURAL:$1|kerta|kertaa}}:",
+'historywarning' => "'''Varoitus:''' Sivua, jota olet poistamassa, on muokattu noin $1 {{PLURAL:$1|kerta|kertaa}}:",
 'confirmdeletetext' => 'Olet poistamassa sivun tai tiedoston ja kaiken sen historian. Ymmärrä teon seuraukset ja tee poisto {{GRAMMAR:genitive|{{SITENAME}}}} [[{{MediaWiki:Policy-url}}|käytäntöjen]] mukaisesti.',
 'actioncomplete' => 'Toiminto suoritettu',
 'actionfailed' => 'Toiminto epäonnistui',
@@ -2484,7 +2491,7 @@ Sivulla $2 on lista viimeaikaisista poistoista.',
 'rollback' => 'palauta aiempaan versioon',
 'rollback_short' => 'Palautus',
 'rollbacklink' => 'palauta',
-'rollbacklinkcount' => 'palauta {{PLURAL:$1|muutos|$1 muutosta}}',
+'rollbacklinkcount' => 'palauta $1 {{PLURAL:$1|muutos|muutosta}}',
 'rollbacklinkcount-morethan' => 'palauta yli $1 {{PLURAL:$1|muutos|muutosta}}',
 'rollbackfailed' => 'Palautus epäonnistui',
 'cantrollback' => 'Aiempaan versioon ei voi palauttaa, koska viimeisin kirjoittaja on sivun ainoa tekijä.',
@@ -2565,31 +2572,31 @@ Viimeisimmän muokkauksen on tehnyt käyttäjä [[User:$3|$3]] ([[User talk:$3|k
 'restriction-level-all' => 'mikä tahansa suojaus',
 
 # Undelete
-'undelete' => 'Palauta poistettuja sivuja',
+'undelete' => 'Tarkastele poistettuja sivuja',
 'undeletepage' => 'Tarkastele ja palauta poistettuja sivuja',
 'undeletepagetitle' => "'''Poistetut versiot sivusta [[:$1]]'''.",
 'viewdeletedpage' => 'Poistettujen sivujen selaus',
-'undeletepagetext' => '{{PLURAL:$1|Seuraava sivu|Seuraavat sivut}} on poistettu, mutta {{PLURAL:$1|se löytyy|ne löytyvät}} vielä arkistosta, joten {{PLURAL:$1|se on|ne ovat}} palautettavissa. Arkisto saatetaan tyhjentää aika ajoin.',
-'undelete-fieldset-title' => 'Palauta versiot',
+'undeletepagetext' => '{{PLURAL:$1|Seuraava sivu|Seuraavat sivut}} on poistettu, mutta {{PLURAL:$1|se löytyy|ne löytyvät}} vielä arkistosta, joten {{PLURAL:$1|se|ne}} voidaan palauttaa takaisin. Arkisto saatetaan tyhjentää aika ajoin.',
+'undelete-fieldset-title' => 'Palauta versioita',
 'undeleteextrahelp' => "Palauttaaksesi sivun koko muutoshistorian jätä kaikki valintalaatikot tyhjiksi ja napsauta '''''{{int:undeletebtn}}'''''.
 Voit palauttaa versioita valikoivasti valitsemalla vain niiden versioiden valintalaatikot, jotka haluat palauttaa.",
-'undeleterevisions' => '{{PLURAL:$1|Versio|$1 versiota}} arkistoitu.',
+'undeleterevisions' => '$1 {{PLURAL:$1|versio|versiota}} on arkistoitu.',
 'undeletehistory' => 'Jos palautat sivun, kaikki versiot lisätään sivun historiaan. Jos uusi sivu samalla nimellä on luotu poistamisen jälkeen, palautetut versiot lisätään sen historiaan.',
 'undeleterevdel' => 'Palautusta ei tehdä, jos sen seurauksena sivun uusin versio olisi osittain piilotettu. 
 Tässä tilanteessa älä valitse palautettavaksi näkyviin viimeisintä poistettua versiota tai poista version piilotus.',
 'undeletehistorynoadmin' => 'Tämä sivu on poistettu. 
 Syy sivun poistamiseen näkyy alla olevassa yhteenvedossa, jossa on myös tiedot, ketkä olivat muokanneet tätä sivua ennen poistamista. 
 Näiden poistettujen versioiden varsinainen tekstisisältö on vain ylläpitäjien luettavissa.',
-'undelete-revision' => 'Poistettu sivu $1 hetkellä $4 kello $5. Tekijä: $3.',
+'undelete-revision' => 'Poistettu versio sivusta $1 (aikaleima $4 kello $5). Version tekijä: $3.',
 'undeleterevision-missing' => 'Virheellinen tai puuttuva versio. 
-Sinulla on kenties käytössä väärä linkki, tai sitten versio on saatettu palauttaa tai poistaa arkistosta.',
+Sinulla on kenties käytössä väärä linkki, tai sitten versio on saatettu palauttaa takaisin tai poistaa arkistosta.',
 'undelete-nodiff' => 'Aikaisempaa versiota ei löytynyt.',
 'undeletebtn' => 'Palauta',
 'undeletelink' => 'näytä tai palauta',
 'undeleteviewlink' => 'näytä',
 'undeletereset' => 'Tyhjennä',
 'undeleteinvert' => 'Käänteinen valinta',
-'undeletecomment' => 'Syy',
+'undeletecomment' => 'Syy:',
 'undeletedrevisions' => '{{PLURAL:$1|Yksi versio|$1 versiota}} palautettiin',
 'undeletedrevisions-files' => '{{PLURAL:$1|Yksi versio|$1 versiota}} ja {{PLURAL:$2|yksi tiedosto|$2 tiedostoa}} palautettiin',
 'undeletedfiles' => '{{PLURAL:$1|1 tiedosto|$1 tiedostoa}} palautettiin',
@@ -2637,7 +2644,7 @@ $1',
 'sp-contributions-newbies' => 'Näytä uusien tulokkaiden muutokset',
 'sp-contributions-newbies-sub' => 'Uusien käyttäjien muokkaukset',
 'sp-contributions-newbies-title' => 'Uusien käyttäjien muokkaukset',
-'sp-contributions-blocklog' => 'estot',
+'sp-contributions-blocklog' => 'estoloki',
 'sp-contributions-deleted' => 'poistetut muokkaukset',
 'sp-contributions-uploads' => 'tallennukset',
 'sp-contributions-logs' => 'lokit',
@@ -2713,11 +2720,11 @@ Voimassa olevat estot näkyvät [[Special:BlockList|estolistasta]].',
 'ipb-edit-dropdown' => 'Muokkaa estosyitä',
 'ipb-unblock-addr' => 'Poista käyttäjän $1 esto',
 'ipb-unblock' => 'Poista käyttäjän tai IP-osoitteen muokkausesto',
-'ipb-blocklist' => 'Näytä estot',
+'ipb-blocklist' => 'Näytä voimassa olevat estot',
 'ipb-blocklist-contribs' => 'Käyttäjän $1 muokkaukset',
-'unblockip' => 'Muokkauseston poisto',
+'unblockip' => 'Muokkauseston poisto käyttäjältä',
 'unblockiptext' => 'Tällä lomakkeella voit poistaa käyttäjän tai IP-osoitteen muokkauseston.',
-'ipusubmit' => 'Poista esto',
+'ipusubmit' => 'Poista tämä esto',
 'unblocked' => 'Käyttäjän [[User:$1|$1]] esto on poistettu',
 'unblocked-range' => '$1 ei ole enää estettynä',
 'unblocked-id' => 'Esto $1 on poistettu',
@@ -2769,7 +2776,7 @@ Alla on ote häivytyslokista.',
 'block-log-flags-nousertalk' => 'oman keskustelusivun muokkaaminen estetty',
 'block-log-flags-angry-autoblock' => 'kehittynyt automaattiesto käytössä',
 'block-log-flags-hiddenname' => 'käyttäjänimi piilotettu',
-'range_block_disabled' => 'Ylläpitäjän oikeus luoda alue-estoja ei ole käytössä.',
+'range_block_disabled' => 'Ylläpitäjien mahdollisuus asettaa avaruusestoja on poistettu käytöstä.',
 'ipb_expiry_invalid' => 'Virheellinen päättymisaika.',
 'ipb_expiry_temp' => 'Piilotettujen käyttäjätunnusten estojen tulee olla pysyviä.',
 'ipb_hide_invalid' => 'Tämän tunnuksen piilottaminen ei onnistu. Sillä saattaa olla liikaa muokkauksia.',
@@ -2901,27 +2908,26 @@ Alla on viimeisin lokitapahtuma:',
 Valitse toinen nimi.',
 
 # Export
-'export' => 'Sivujen vienti',
-'exporttext' => 'Voit viedä sivun tai sivujen tekstiä ja muokkaushistoriaa XML-muodossa.
-Tämä tieto voidaan tuoda toiseen käyttämällä MediaWikiä [[Special:Import|tuontisivun]] kautta.
+'export' => 'Vie sivuja',
+'exporttext' => "Voit viedä (''export'') sivun tai usean sivun tekstin ja muokkaushistorian XML-muodossa.
+Tämä tieto voidaan tuoda (''import'') toiseen wikiin käyttämällä MediaWikiä [[Special:Import|tuontisivun]] kautta.
 
-Syötä sivujen otsikoita jokainen omalle rivilleen alla olevaan laatikkoon.
-Valitse myös, haluatko kaikki versiot sivuista, vai ainoastaan nykyisen version.
+Kirjoita sivujen nimet, jokainen nimike omalle rivilleen, alla olevaan tietolaatikkoon. Valitse, haluatko viedä sivun uusimman version sekä samalla kaikki vanhat versiot ja sivun historian tietorivit, vai haluatko viedä sivun uusimman version, jossa on tieto viimeisimmästä muokkauksesta.
 
-Jälkimmäisessä tapauksessa voit myös käyttää linkkiä. Esimerkiksi sivun [[{{MediaWiki:Mainpage}}]] saa vietyä linkistä [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].',
+Jälkimmäisessä tapauksessa voit myös käyttää linkkiä. Esimerkiksi sivun [[{{MediaWiki:Mainpage}}]] saa vietyä linkistä [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].",
 'exportall' => 'Vie kaikki sivut',
-'exportcuronly' => 'Liitä mukaan ainoastaan uusin versio – ei koko historiaa.',
-'exportnohistory' => '----
-Sivujen koko historian vienti on estetty suorituskykysyistä.',
+'exportcuronly' => 'Ota vientiin ainoastaan uusin versio – ei koko historiaa',
+'exportnohistory' => "----
+'''Huomautus:''' Sivujen koko muokkaushistorian vienti tämän lomakkeen kautta on poistettu käytöstä suorituskykysyistä.",
 'exportlistauthors' => 'Lisää lista jokaisen sivun muokkaajista',
 'export-submit' => 'Vie',
-'export-addcattext' => 'Lisää sivut luokasta',
+'export-addcattext' => 'Lisää sivut luokasta:',
 'export-addcat' => 'Lisää',
-'export-addnstext' => 'Lisää sivut nimiavaruudesta',
+'export-addnstext' => 'Lisää sivut nimiavaruudesta:',
 'export-addns' => 'Lisää',
 'export-download' => 'Tallenna tiedostona',
-'export-templates' => 'Liitä mallineet',
-'export-pagelinks' => 'Sisällytä linkkien kohteina olevat sivut syvyydelle',
+'export-templates' => 'Ota mukaan mallineet',
+'export-pagelinks' => 'Sisällytä linkkien kohteina olevat sivut syvyydelle:',
 
 # Namespace 8 related
 'allmessages' => 'Järjestelmäviestit',
@@ -2929,7 +2935,7 @@ Sivujen koko historian vienti on estetty suorituskykysyistä.',
 'allmessagesdefault' => 'Oletusarvo',
 'allmessagescurrent' => 'Nykyinen arvo',
 'allmessagestext' => 'Tämä on luettelo järjestelmäviesteistä, jotka ovat saatavilla MediaWiki-nimiavaruudessa.
-Jos haluat muokata MediaWikin yleistä kotoistusta, käy [//www.mediawiki.org/wiki/Localisation MediaWikin kotoistussivuilla] ja sivustolla [//translatewiki.net translatewiki.net].',
+Jos haluat muokata MediaWikin yleistä kotoistusta, käy [https://www.mediawiki.org/wiki/Localisation MediaWikin kotoistussivuilla] ja sivustolla [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => 'Tämä sivu ei ole käytössä, koska <tt>$wgUseDatabaseMessages</tt>-asetus on pois päältä.',
 'allmessages-filter-legend' => 'Suodata',
 'allmessages-filter' => 'Suodata muutosten perusteella',
@@ -2958,16 +2964,18 @@ $2',
 
 # Special:Import
 'import' => 'Tuo sivuja',
-'importinterwiki' => 'Tuo sivuja lähiwikeistä',
-'import-interwiki-text' => 'Valitse wiki ja sivun nimi. Versioiden päivämäärät ja muokkaajat säilytetään. Kaikki wikienväliset tuonnit kirjataan [[Special:Log/import|tuontilokiin]].',
+'importinterwiki' => 'Tuo sivuja muista wikeistä (transwiki import)',
+'import-interwiki-text' => 'Valitse wiki ja sivun nimi tuontia varten.
+Versioiden päivämäärät ja muokkaajien nimet säilyvät ennallaan. 
+Kaikki wikienväliset tuontitapahtumat kirjataan [[Special:Log/import|tuontilokiin]].',
 'import-interwiki-source' => 'Lähdewiki/sivu:',
-'import-interwiki-history' => 'Kopioi sivun koko historia',
-'import-interwiki-templates' => 'Liitä kaikki mallineet',
+'import-interwiki-history' => 'Kopioi sivun koko historia ja kaikki versiot',
+'import-interwiki-templates' => 'Ota mukaan kaikki mallineet',
 'import-interwiki-submit' => 'Tuo',
 'import-interwiki-namespace' => 'Kohdenimiavaruus:',
-'import-interwiki-rootpage' => 'Tuo annetun sivun alasivuiksi (valinnainen):',
+'import-interwiki-rootpage' => 'Kohteessa oleva perussivu (valinnainen):',
 'import-upload-filename' => 'Tiedostonimi:',
-'import-comment' => 'Syy',
+'import-comment' => 'Kommentti:',
 'importtext' => 'Vie sivuja lähdewikistä käyttäen [[Special:Export|vientityökalua]].
 Tallenna tiedot koneellesi ja tuo ne tällä sivulla.',
 'importstart' => 'Tuodaan sivuja...',
@@ -2987,7 +2995,7 @@ Tallenna tiedot koneellesi ja tuo ne tällä sivulla.',
 'importuploaderrorpartial' => 'Tuontitiedoston tallennus epäonnistui. Tiedostosta oli lähetetty vain osa.',
 'importuploaderrortemp' => 'Tuontitiedoston tallennus epäonnistui. Väliaikaistiedostojen kansio puuttuu.',
 'import-parse-failure' => 'XML-tuonti epäonnistui jäsennysvirheen takia.',
-'import-noarticle' => 'Ei tuotavaa sivua.',
+'import-noarticle' => 'Ei sivua tuotavaksi!',
 'import-nonewrevisions' => 'Kaikki versiot on tuotu aiemmin.',
 'xml-error-string' => '$1 rivillä $2, sarakkeessa $3 (tavu $4): $5',
 'import-upload' => 'Tallenna XML-tiedosto',
@@ -2995,21 +3003,21 @@ Tallenna tiedot koneellesi ja tuo ne tällä sivulla.',
 'import-invalid-interwiki' => 'Määritellystä wikistä ei voi tuoda.',
 'import-error-edit' => 'Sivua $1 ei tuotu, koska sinulla ei ole oikeutta muokata sitä.',
 'import-error-create' => 'Sivua $1 ei tuotu, koska sinulla ei ole oikeutta luoda sitä.',
-'import-error-interwiki' => 'Sivua $1 ei voitu tuoda, koska sen nimi on varattu ulkoisen linkittämisen (interwiki).',
-'import-error-special' => 'Sivua $1 ei tuoda, koska se kuuluu nimitilaan, joka ei salli sivuja.',
-'import-error-invalid' => 'Sivua $1 ei tuoda, koska sen nimi ei kelpaa.',
+'import-error-interwiki' => 'Sivua $1 ei tuotu, koska sen nimi on varattu ulkoiseen linkittämiseen (interwiki).',
+'import-error-special' => 'Sivua $1 ei tuotu, koska se kuuluu erityiseen nimiavaruuteen, joka ei salli sivuja.',
+'import-error-invalid' => 'Sivua $1 ei tuotu, koska sen nimi ei kelpaa.',
 'import-error-unserialize' => 'Versiota $2 sivusta $1 ei voida jakaa osiin. Version ilmoitettiin käyttävän sisältömallia $3 ja sarjoitusmuotoilua $4.',
 'import-options-wrong' => '{{PLURAL:$2|Väärä asetus|Väärät asetukset}}: <nowiki>$1</nowiki>',
-'import-rootpage-invalid' => 'Annettu sivun nimi ei kelpaa.',
-'import-rootpage-nosubpage' => 'Annetun sivun nimiavaruus $1 ei salli alasivuja.',
+'import-rootpage-invalid' => 'Annettu perussivun nimi ei kelpaa.',
+'import-rootpage-nosubpage' => 'Annetun perussivun nimiavaruus "$1" ei salli alasivuja.',
 
 # Import log
 'importlogpage' => 'Tuontiloki',
-'importlogpagetext' => 'Loki toisista wikeistä tuoduista sivuista.',
-'import-logentry-upload' => 'toi sivun [[$1]] lähettämällä tiedoston',
+'importlogpagetext' => 'Loki ylläpitäjien toisista wikeistä tuomista sivuista, joissa on muokkaushistoriaa.',
+'import-logentry-upload' => 'toi sivun [[$1]] tiedostomuodossa',
 'import-logentry-upload-detail' => '{{PLURAL:$1|yksi versio|$1 versiota}}',
 'import-logentry-interwiki' => 'toi toisesta wikistä sivun $1',
-'import-logentry-interwiki-detail' => '{{PLURAL:$1|yksi versio|$1 versiota}} wikistä $2',
+'import-logentry-interwiki-detail' => '$1 {{PLURAL:$1|versio|versiota}} tuotiin wikistä $2',
 
 # JavaScriptTest
 'javascripttest' => 'JavaScriptin testaus',
@@ -3039,21 +3047,21 @@ Tallenna tiedot koneellesi ja tuo ne tällä sivulla.',
 Voit katsella sivun lähteenä olevaa wikitekstiä.',
 'tooltip-ca-history' => 'Sivun aikaisemmat versiot',
 'tooltip-ca-protect' => 'Suojaa tämä sivu',
-'tooltip-ca-unprotect' => 'Muuta tämän sivun suojauksia',
+'tooltip-ca-unprotect' => 'Muuta tämän sivun suojauksen asetuksia',
 'tooltip-ca-delete' => 'Poista tämä sivu',
-'tooltip-ca-undelete' => 'Palauta tämä sivu',
+'tooltip-ca-undelete' => 'Palauta ne muokkaukset, jotka tehtiin tälle sivulle ennen kuin se poistettiin',
 'tooltip-ca-move' => 'Siirrä tämä sivu',
 'tooltip-ca-watch' => 'Lisää tämä sivu tarkkailulistallesi',
 'tooltip-ca-unwatch' => 'Poista tämä sivu tarkkailulistaltasi',
-'tooltip-search' => 'Etsi {{GRAMMAR:elative|{{SITENAME}}}}',
+'tooltip-search' => 'Hae {{GRAMMAR:elative|{{SITENAME}}}}',
 'tooltip-search-go' => 'Siirry sivulle, joka on tarkalleen tällä nimellä',
-'tooltip-search-fulltext' => 'Etsi sivuilta tätä tekstiä',
+'tooltip-search-fulltext' => 'Hae sivuilta tätä tekstiä',
 'tooltip-p-logo' => 'Etusivu',
 'tooltip-n-mainpage' => 'Siirry etusivulle',
 'tooltip-n-mainpage-description' => 'Siirry etusivulle',
 'tooltip-n-portal' => 'Keskustelua projektista',
 'tooltip-n-currentevents' => 'Taustatietoa tämänhetkisistä tapahtumista',
-'tooltip-n-recentchanges' => 'Lista tuoreista muutoksista',
+'tooltip-n-recentchanges' => 'Luettelo tuoreista muutoksista',
 'tooltip-n-randompage' => 'Avaa satunnainen sivu',
 'tooltip-n-help' => 'Ohjeita',
 'tooltip-t-whatlinkshere' => 'Lista sivuista, jotka viittaavat tänne',
@@ -3086,10 +3094,11 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 'tooltip-watchlistedit-raw-submit' => 'Päivitä tarkkailulista',
 'tooltip-recreate' => 'Luo sivu uudelleen',
 'tooltip-upload' => 'Aloita tallennus',
-'tooltip-rollback' => 'Palauttaminen kumoaa viimeisimmän muokkaajan yhden tai useamman muutoksen yhdellä kertaa.',
+'tooltip-rollback' => 'Palautustyökalu kumoaa sivun viimeisen muokkaajan yhden tai useamman muutoksen yhdellä kertaa.',
 'tooltip-undo' => 'Kumoaminen palauttaa tämän muutoksen ja avaa artikkelin esikatselussa. Yhteenvetokenttään voi kirjoittaa palautuksen syyn.',
 'tooltip-preferences-save' => 'Tallenna asetukset',
 'tooltip-summary' => 'Kirjoita lyhyt yhteenveto',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Tämä sivu sisältää koko sivustoa muuttavia tyylejä. */',
@@ -3138,10 +3147,12 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 'spam_reverting' => 'Palautettu viimeisimpään versioon, joka ei sisällä linkkejä kohteeseen $1.',
 'spam_blanking' => 'Kaikki versiot sisälsivät linkkejä kohteeseen $1. Sivu tyhjennetty.',
 'spam_deleting' => 'Kaikki versiot sisälsivät linkkejä kohteeseen $1, poistetaan',
+'simpleantispam-label' => "Mainostenvastainen varmistus.
+'''ÄLÄ''' täytä tätä!",
 
 # Info page
 'pageinfo-title' => 'Tietoja sivusta $1',
-'pageinfo-not-current' => 'Tätä tietoa on mahdoton näyttää vanhoille versiolle.',
+'pageinfo-not-current' => 'Valitettavasti ei ole mahdollista antaa tätä tietoa, joka liittyy vanhoihin versioihin.',
 'pageinfo-header-basic' => 'Perustiedot',
 'pageinfo-header-edits' => 'Muutoshistoria',
 'pageinfo-header-restrictions' => 'Sivun suojaus',
@@ -3151,6 +3162,7 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 'pageinfo-length' => 'Sivun pituus (tavuina)',
 'pageinfo-article-id' => 'Sivun tunniste',
 'pageinfo-language' => 'Sivun sisällön kieli',
+'pageinfo-content-model' => 'Sivun sisällön muoto',
 'pageinfo-robot-policy' => 'Hakukonemerkinnät',
 'pageinfo-robot-index' => 'Indeksoitava',
 'pageinfo-robot-noindex' => 'Ei indeksoitava',
@@ -3215,8 +3227,8 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 
 $1',
 'filedelete-missing' => 'Tiedostoa $1 ei voi poistaa, koska sitä ei ole olemassa.',
-'filedelete-old-unregistered' => 'Tiedoston version $1 ei ole tietokannassa.',
-'filedelete-current-unregistered' => 'Tiedosto $1 ei ole tietokannassa.',
+'filedelete-old-unregistered' => 'Tiedoston määritettyä versiota $1 ei ole tietokannassa.',
+'filedelete-current-unregistered' => 'Tiedostoa $1 ei ole tietokannassa.',
 'filedelete-archive-read-only' => 'Arkistohakemistoon ”$1” kirjoittaminen epäonnistui.',
 
 # Browsing diffs
@@ -3236,7 +3248,7 @@ Suorittamalla sen järjestelmäsi voi muuttua epäluotettavaksi.",
 'svg-long-desc' => 'SVG-tiedosto; oletustarkkuus $1 × $2 kuvapistettä; tiedostokoko $3',
 'svg-long-desc-animated' => 'Animoitu SVG-tiedosto; oletustarkkuus $1 × $2 kuvapistettä; tiedostokoko $3',
 'svg-long-error' => 'Kelvoton SVG-tiedosto: $1',
-'show-big-image' => 'Korkeatarkkuuksinen versio',
+'show-big-image' => 'Alkuperäinen tiedosto',
 'show-big-image-preview' => 'Tämän esikatselun koko: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Muu resoluutio|Muut resoluutiot}}: $1.',
 'show-big-image-size' => '$1 × $2 kuvapistettä',
@@ -3471,7 +3483,7 @@ Kaikki muut linkit ovat poikkeuksia eli toisin sanoen sivuja, joissa tiedostoa s
 'exif-copyrightowner' => 'Tekijänoikeuden haltija',
 'exif-usageterms' => 'Käyttöehdot',
 'exif-webstatement' => 'Verkossa oleva tekijänoikeustieto',
-'exif-originaldocumentid' => 'Alkuperäisen asiakirjan tunnusnumero',
+'exif-originaldocumentid' => 'Alkuperäisen asiakirjan tunniste',
 'exif-licenseurl' => 'Tekijänoikeuslisenssin URL',
 'exif-morepermissionsurl' => 'Vaihtoehtoiset lisenssitiedot',
 'exif-attributionurl' => 'Kun kuvaa käytetään, linkitä tähän osoitteeseen',
@@ -3703,7 +3715,7 @@ Kaikki muut linkit ovat poikkeuksia eli toisin sanoen sivuja, joissa tiedostoa s
 
 # External editor support
 'edit-externally' => 'Muokkaa tätä tiedostoa ulkoisessa sovelluksessa',
-'edit-externally-help' => '(Katso [//www.mediawiki.org/wiki/Manual:External_editors ohjeet], jos haluat lisätietoja.)',
+'edit-externally-help' => '(Katso [https://www.mediawiki.org/wiki/Manual:External_editors ohjeet], jos haluat lisätietoja.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'koko historia',
@@ -3885,7 +3897,7 @@ Voit myös muokata listaa [[Special:EditWatchlist|tavalliseen tapaan]].',
 'version-hook-subscribedby' => 'Kytkökset',
 'version-version' => '(Versio $1)',
 'version-license' => 'Lisenssi',
-'version-poweredby-credits' => "Tämä wiki käyttää '''[//www.mediawiki.org/ MediaWikiä]'''. Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Tämä wiki käyttää '''[https://www.mediawiki.org/ MediaWikiä]'''. Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'muut',
 'version-poweredby-translators' => 'translatewiki.net-kääntäjät',
 'version-credits-summary' => 'Haluaisimme kiittää seuraavia henkilöitä heidän panoksestaan [[Special:Version|MediaWiki-ohjelmistoon]].',
@@ -3904,7 +3916,7 @@ Sinun olisi pitänyt saada [{{SERVER}}{{SCRIPTPATH}}/COPYING kopio GNU General P
 # Special:Redirect
 'redirect' => 'Ohjaus tiedostonimen, käyttäjätunnisteen tai versiotunnisteen mukaan',
 'redirect-legend' => 'Ohjaus tiedostoon tai sivulle',
-'redirect-summary' => 'Tämä toimintosivu ohjaa tiedostoon (tiedostonimen mukaan), sivulle (versiotunnisteen mukaan) tai käyttäjäsivulle (käyttäjätunnisteen numeron mukaan).',
+'redirect-summary' => 'Tämä toimintosivu ohjaa tiedostoon (tiedostonimen mukaan), sivulle (versiotunnisteen mukaan) tai käyttäjäsivulle (käyttäjätunnisteen mukaan). Käyttö: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] tai [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Siirry',
 'redirect-lookup' => 'Hae:',
 'redirect-value' => 'Arvo:',
@@ -3926,8 +3938,8 @@ Sinun olisi pitänyt saada [{{SERVER}}{{SCRIPTPATH}}/COPYING kopio GNU General P
 
 # Special:SpecialPages
 'specialpages' => 'Toimintosivut',
-'specialpages-note' => '----
-* Normaalit toimintosivut.
+'specialpages-note-top' => 'Merkkien selitys',
+'specialpages-note' => '* Normaalit toimintosivut.
 * <span class="mw-specialpagerestricted">Rajoitetut toimintosivut.</span>',
 'specialpages-group-maintenance' => 'Sivujen huoltaminen',
 'specialpages-group-other' => 'Muut',
@@ -3962,7 +3974,7 @@ Sinun olisi pitänyt saada [{{SERVER}}{{SCRIPTPATH}}/COPYING kopio GNU General P
 'tag-filter-submit' => 'Suodata',
 'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Merkintä|Merkinnät}}]]: $2)',
 'tags-title' => 'Merkinnät',
-'tags-intro' => 'Tämä sivu luetteloi merkinnät, joilla ohjelmisto voi merkitä muokkauksia, ja niiden tarkoitukset.',
+'tags-intro' => "Tämä sivu luetteloi ne merkinnät (''eng.'' tags), joilla ohjelmisto voi merkitä muokkauksia, ja niiden tarkoitukset.",
 'tags-tag' => 'Merkintänimi',
 'tags-display-header' => 'Näkyvyys muutosluetteloissa',
 'tags-description-header' => 'Täysi kuvaus tarkoituksesta',
@@ -4105,9 +4117,9 @@ Muussa tapauksessa voit käyttää alla olevaa helpompaa lomaketta. Kommenttisi
 'api-error-publishfailed' => 'Sisäinen virhe: Väliaikaisen tiedoston julkaiseminen epäonnistui.',
 'api-error-timeout' => 'Palvelin ei vastannut odotetun ajan kuluessa.',
 'api-error-unclassified' => 'Tapahtui tuntematon virhe.',
-'api-error-unknown-code' => 'Tuntematon virhe: $1',
+'api-error-unknown-code' => 'Tuntematon virhe: $1.',
 'api-error-unknown-error' => 'Sisäinen virhe: Jotain meni vikaan kun tiedostosi yritettiin tallentaa.',
-'api-error-unknown-warning' => 'Tuntematon varoitus: $1',
+'api-error-unknown-warning' => 'Tuntematon varoitus: $1.',
 'api-error-unknownerror' => 'Tuntematon virhe: $1.',
 'api-error-uploaddisabled' => 'Tiedostojen tallentaminen ei ole käytössä.',
 'api-error-verification-error' => 'Tiedosto voi olla vioittunut, tai sillä saattaa olla väärä tiedostopääte.',
@@ -4135,6 +4147,22 @@ Muussa tapauksessa voit käyttää alla olevaa helpompaa lomaketta. Kommenttisi
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|tavu|tavua}}',
 'limitreport-templateargumentsize' => 'Mallineen argumenttien koko',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|tavu|tavua}}',
-'limitreport-expansiondepth' => 'Suurin laajennussyvyys',
+'limitreport-expansiondepth' => 'Highest expansion depth',
+
+# Special:ExpandTemplates
+'expandtemplates' => 'Mallineiden laajennus',
+'expand_templates_intro' => 'Tämä toimintosivu ottaa syötteekseen tekstiä ja laajentaa kaikki mallineet rekursiivisesti sekä jäsenninfunktiot, kuten
+<code><nowiki>{{</nowiki>#language:...}}</code>, ja -muuttujat, kuten
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Toisin sanoen melkein kaiken, joka on kaksoisaaltosulkeiden sisällä.',
+'expand_templates_title' => 'Otsikko (esimerkiksi muuttujaa {{FULLPAGENAME}} varten)',
+'expand_templates_input' => 'Teksti',
+'expand_templates_output' => 'Tulos',
+'expand_templates_xml_output' => 'XML-tuloste',
+'expand_templates_ok' => 'Laajenna',
+'expand_templates_remove_comments' => 'Poista kommentit',
+'expand_templates_remove_nowiki' => 'Poista <nowiki>-tagit tulosteesta',
+'expand_templates_generate_xml' => 'Näytä XML-jäsennyspuu',
+'expand_templates_preview' => 'Esikatselu',
 
 );
index 556170a..b779082 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'Categories'                => array( 'Bólkar' ),
        'Contributions'             => array( 'Brúkaraíkast' ),
        'Deadendpages'              => array( 'Gøtubotns síður' ),
-       'Disambiguations'           => array( 'Síður við fleirfaldum týdningi' ),
        'DoubleRedirects'           => array( 'Tvífaldað ávísing' ),
        'Emailuser'                 => array( 'Send t-post til brúkara' ),
        'Export'                    => array( 'Útflutningssíður' ),
@@ -329,7 +328,7 @@ $messages = array(
 'articlepage' => 'Vís síðu við innihaldi',
 'talk' => 'Kjak',
 'views' => 'Skoðanir',
-'toolbox' => 'Amboðskassi',
+'toolbox' => 'Tól',
 'userpage' => 'Vís brúkarasíðu',
 'projectpage' => 'Vís verkætlanarsíðu',
 'imagepage' => 'Vís fílusíðuna',
@@ -386,12 +385,10 @@ Sí [[Special:Version|versjón síða]].',
 'ok' => 'Í lagi',
 'retrievedfrom' => 'Heintað frá "$1"',
 'youhavenewmessages' => 'Tú hevur $1 ($2).',
-'newmessageslink' => 'nýggj boð',
-'newmessagesdifflink' => 'seinasta broyting',
 'youhavenewmessagesfromusers' => 'Tú hevur $1 frá {{PLURAL:$3|øðrum brúkara|$3 brúkarum}} ($2).',
 'youhavenewmessagesmanyusers' => 'Tú hevur $1 frá fleiri brúkarum ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|eini nýggj boð|nýggj boð}}',
-'newmessagesdifflinkplural' => 'seinasta {{PLURAL:$1|broyting|broytingar}}',
+'newmessageslinkplural' => '{{PLURAL:$1|eini nýggj boð|999=nýggj boð}}',
+'newmessagesdifflinkplural' => 'seinasta {{PLURAL:$1|broyting|999=broytingar}}',
 'youhavenewmessagesmulti' => 'Tú hevur nýggj boð á $1',
 'editsection' => 'rætta',
 'editold' => 'rætta',
@@ -443,6 +440,8 @@ Hetta kann eisini benda á ein feil í software'ini sum {{SITENAME}} brúkar.",
 # General errors
 'error' => 'Villa',
 'databaseerror' => 'Villa í dátagrunni',
+'databaseerror-query' => 'Fyrispurningur: $1',
+'databaseerror-function' => 'Funksjón: $1',
 'databaseerror-error' => 'Feilur: $1',
 'laggedslavemode' => "'''Ávaring:''' Síðan inniheldur møguliga ikki nýggjar dagføringar.",
 'readonly' => 'Dátubasan er stongd fyri skriving',
@@ -519,7 +518,8 @@ Umboðsstjórin sum stongdi hana, gav hesa frágreiðing: "$3".',
 'invalidtitle-knownnamespace' => 'Ógyldugt heiti við navnaøki "$2" og teksti "$3"',
 'invalidtitle-unknownnamespace' => 'Ógyldigt heiti við ókendum navnaøkis tali $1 og teksti "$2"',
 'exception-nologin' => 'Tú ert ikki loggað/ur inn',
-'exception-nologin-text' => 'Henda síða ella tað tú ætlar at gera kremvur at tú ert innritað/ur á hesa wiki.',
+'exception-nologin-text' => 'Vinarliga [[Special:Userlogin|rita inn]] fyri at fáa atgongd til hesa síðu ella handling.',
+'exception-nologin-text-manual' => 'Vinarliga $1 fyri at fáa atgongd til hesa síðu ella handling.',
 
 # Virus scanner
 'virus-badscanner' => "Konfiguratións villa: Ókendur virus skannari: ''$1''",
@@ -566,9 +566,12 @@ Gloym ikki at broyta tínar [[Special:Preferences|{{SITENAME}}-innstillingar]].'
 'gotaccount' => "Hevur tú longu eina kontu? '''$1'''.",
 'gotaccountlink' => 'Rita inn',
 'userlogin-resetlink' => 'Hevur tú gloymt tínar logg inn upplýsingar',
-'userlogin-resetpassword-link' => 'Nullstilla títt loyniorð',
+'userlogin-resetpassword-link' => 'Hevur tú gloymt títt loyniorð?',
 'helplogin-url' => 'Help:Innritan',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hjálp til innritan]]',
+'userlogin-loggedin' => 'Tú ert longu innritað/ur sum {{GENDER:$1|$1}}.
+Nýt formularin niðanfyri fyri at rita inn sum ein annar brúkari.',
+'userlogin-createanother' => 'Stovna eina aðra kontu',
 'createacct-join' => 'Skrivað tínar upplýsingar niðanfyri.',
 'createacct-another-join' => 'Skriva upplýsingarnar fyri tað nýggju kontuna niðanfyri.',
 'createacct-emailrequired' => 'Teldupost adressa',
@@ -631,16 +634,16 @@ og tú ikki longur ynskir at broyta tað, so skal tú síggja burtur frá hesum
 sum er skrásett fyri "$1".
 Vinarliga rita inn eftir at tú hevur fingið hana.',
 'blocked-mailpassword' => 'Tín IP adressa er stongd fyri at gera rættingar á síðum, og tí er tað ikki loyvt at brúka funkuna fyri endurskapan av loyniorði, hetta fyri at forða fyri misnýtslu.',
-'eauthentsent' => '↓ Ein váttanar t-postur er sendur til givna t-post bústaðin.
-Áðrenn aðrir teldupostar verða sendir til kontuna, mást tú fylgja leiðbeiningunum í t-postinum, fyri at vátta at kontoin veruliga er tín.',
+'eauthentsent' => 'Ein váttanar teldupostur er sendur til givna teldupost bústaðin.
+Áðrenn nakað annað teldubræv verður sent til kontuna, mást tú fylgja leiðbeiningunum í teldupostinum, fyri at vátta at kontoin veruliga er tín.',
 'throttled-mailpassword' => 'Ein teldupostur har loyniorðið verður nullstillað er longu sendur fyri bert {{PLURAL:$1|tíma|$1 tímum}} síðan.
 Fyri at fyribyrja misnýtslu, verður bert ein teldupostur við nullstillaðum loyniorði sendur fyri pr. {{PLURAL:$1|tíma|$1 tímar}}.',
 'mailerror' => 'Villa tá t-postur var sendur: $1',
 'acct_creation_throttle_hit' => 'Vitjandi á hesi wiki, sum nýta tína IP addressu, hava stovnað {{PLURAL:$1|1 kontu|$1 kontur}} seinastu dagarnar, sum er mest loyvda hetta tíðarskeið.
 Sum eitt úrslit av hesum, kunnu vitjandi sum brúka hesa IP adressuna ikki stovna fleiri kontur í løtuni.',
-'emailauthenticated' => 'Tín t-post adressa varð váttað hin $2 kl. $3.',
-'emailnotauthenticated' => 'Tín t-post adressa er enn ikki komin í gildi. Ongin t-postur
-verður sendur fyri nak av fylgjandi hentleikum.',
+'emailauthenticated' => 'Tín teldupost adressa varð váttað hin $2 kl. $3.',
+'emailnotauthenticated' => 'Tín teldupost adressa er enn ikki váttað. Ongin teldupostur
+verður sendur fyri nakran av fylgjandi hentleikum.',
 'noemailprefs' => 'Skriva eina t-post adressu, so hesar funktiónir fara at virka.',
 'emailconfirmlink' => 'Vátta tína t-post adressu',
 'invalidemailaddress' => 'T-post bústaðurin kann ikki verða góðtikin, tí hann sær út til at hava ógyldugt format.
@@ -1066,15 +1069,15 @@ Tú kanst síggja munin; smálutir eru at finna í [{{fullurl:{{#Special:Log}}/s
 'logdelete-selected' => "'''{{PLURAL:$1|Útvald logghending|Útvaldar logghendingar}}:'''",
 'revdelete-confirm' => 'Vinarliga vátta, at tú ætlar at gera hetta, at tú skilir avleiðingarnar, og at tú ger hetta í samsvari við [[{{MediaWiki:Policy-url}}|mannagongdirnar]].',
 'revdelete-legend' => 'Set avmarkinga fyri sjónligheit',
-'revdelete-hide-text' => 'Goym burtur tekstin á hesi versjónini',
+'revdelete-hide-text' => 'Versjónstekstur',
 'revdelete-hide-image' => 'Fjal fílu innihald',
 'revdelete-hide-name' => 'Fjal handling og mál',
-'revdelete-hide-comment' => 'Fjal rættingar frágreiðing',
-'revdelete-hide-user' => 'Fjal brúkaranavn/IP adressu hjá tí sum rættar',
+'revdelete-hide-comment' => 'Samandráttur um rættingar',
+'revdelete-hide-user' => 'Brúkaranavn/IP adressa hjá tí sum rættar',
 'revdelete-hide-restricted' => 'Síggj burtur frá data frá administratorum líka væl sum frá øðrum',
 'revdelete-radio-same' => '(ikki broyta)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nei',
+'revdelete-radio-set' => 'Fjalt',
+'revdelete-radio-unset' => 'Sjónligt',
 'revdelete-suppress' => 'Síggj burtur frá data frá administratorum líka væl sum frá øðrum',
 'revdelete-unsuppress' => 'Tak burtur avmarkingar á endurskaptum versjónum',
 'revdelete-log' => 'Orsøk:',
@@ -1223,8 +1226,6 @@ Legg til merkis, at teirra innihaldsyvirlit av {{SITENAME}} kann vera gamalt og
 'preferences' => 'Innstillingar',
 'mypreferences' => 'Innstillingar',
 'prefs-edits' => 'Tal av rættingum:',
-'prefsnologin' => 'Tú hevur ikki ritað inn',
-'prefsnologintext' => 'Tú mást vera <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} innritað/ur]</span> fyri at broyta brúkarainnstillingar.',
 'changepassword' => 'Broyt loyniorð',
 'prefs-skin' => 'Hamur',
 'skin-preview' => 'Forskoðan',
@@ -1486,8 +1487,8 @@ Tín t-post adressa verður ikki avdúkað, tá aðrir brúkarir seta seg í sam
 'action-block' => 'noktað hesum brúkara at rætta',
 'action-protect' => 'broyt verjustøðuna hjá hesi síðu',
 'action-rollback' => 'rulla skjótt aftur rættingarnar hjá tí seinasta brúkaranum, sum rættaði eina ávísa síðu',
-'action-import' => 'innflyt hesa síðu frá aðrari wiki',
-'action-importupload' => 'innflyt hesa síðuna frá einari fílu sum er løgd út',
+'action-import' => 'innflyt síður frá aðrari wiki',
+'action-importupload' => 'innflyt síður frá einari fílu sum er løgd út',
 'action-patrol' => 'markað rætting hjá øðrum sum eftirhugda',
 'action-autopatrol' => 'fá tina rætting merkta sum eftirhugda',
 'action-unwatchedpages' => 'Síggj listan yvir síður sum ikki eru eftiransaðar',
@@ -1503,6 +1504,8 @@ Tín t-post adressa verður ikki avdúkað, tá aðrir brúkarir seta seg í sam
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|broyting|broytingar}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|síðan seinastu vitjan}}',
+'enhancedrc-history' => 'søga',
 'recentchanges' => 'Seinastu broytingar',
 'recentchanges-legend' => 'Nýligar broytingar møguleikar',
 'recentchanges-summary' => 'Á hesi síðu kanst tú fylgja teimum nýggjastu broytingunum á hesi wiki.',
@@ -1512,6 +1515,7 @@ Tín t-post adressa verður ikki avdúkað, tá aðrir brúkarir seta seg í sam
 'recentchanges-label-minor' => 'Hetta er ein lítil rætting',
 'recentchanges-label-bot' => 'Henda rætting varð gjørd av einum botti',
 'recentchanges-label-unpatrolled' => 'Henda rætting er ikki blivin eftirkannað enn',
+'recentchanges-legend-newpage' => '(sí eisini [[Special:NewPages|yvirlit yvir nýggjar síður]])',
 'rcnote' => "Niðanfyri {{PLURAL:$1|stendur '''1''' tann seinasta broytingin|standa '''$1''' tær seinastu broytingarnar}} {{PLURAL:$2|seinasta dagin|seinastu '''$2''' dagarnar}}, frá $5, $4.",
 'rcnotefrom' => "Niðanfyri standa broytingarnar síðani '''$2''', (upp til '''$1''' er sýndar).",
 'rclistfrom' => 'Sýn nýggjar broytingar byrjandi við $1',
@@ -1770,6 +1774,7 @@ Tú kanst eisini royna aftur, tá tað ikki eru so nógv í gongd her í senn.',
 'listfiles_size' => 'Stødd',
 'listfiles_description' => 'Frágreiðing',
 'listfiles_count' => 'Versjónir',
+'listfiles-latestversion' => 'Galdandi versjón',
 'listfiles-latestversion-yes' => 'Ja',
 'listfiles-latestversion-no' => 'Nei',
 
@@ -1975,6 +1980,7 @@ Víðaristilling verður nú gjørd til [[$2]].',
 'listusers' => 'Brúkaralisti',
 'listusers-editsonly' => 'Vís bara brúkarar sum hava gjørt rættingar',
 'listusers-creationsort' => 'Bólkað eftir stovningardegnum',
+'listusers-desc' => 'Sortera í minkandi raðfylgju',
 'usereditcount' => '$1 {{PLURAL:$1|rætting|rættingar}}',
 'usercreated' => '{{GENDER:$3|Upprættað}} hin $1 kl. $2',
 'newpages' => 'Nýggjar síður',
@@ -2205,10 +2211,12 @@ Sí $2 fyri fulla skráseting av strikingum.',
 'deletecomment' => 'Orsøk:',
 'deleteotherreason' => 'Onnur orsøk:',
 'deletereasonotherlist' => 'Onnur orsøk',
-'deletereason-dropdown' => '*Vanligar orsøkir til striking
-** Umbøn frá høvunda
+'deletereason-dropdown' => '* Vanligar orsøkir til striking
+** Spamm
+** Herverk (Vandalisma)
 ** Brot á upphavsrættin
-** Herverk (Vandalisma)',
+** Umbøn frá høvunda
+** Brotin víðaristilling',
 'delete-edit-reasonlist' => 'Rætta orsøkir til striking',
 'delete-toobig' => 'Henda síðan hevur eina langa rættingar søgu, meira enn $1 {{PLURAL:$1|versjón|versjónir}}. 
 Striking av slíkum síðum er avmarkað fyri at forða fyri at onkur av óvart kemur til at forstýra {{SITENAME}}.',
@@ -2228,7 +2236,7 @@ onkur annar hevur longu rættað ella rullað síðuna aftur.
 Seinasta broytingin á síðuni var av [[User:$3|$3]] ([[User talk:$3|kjak]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Rættingarfrágreiðingin var: \"''\$1''\".",
 'revertpage' => 'Tók burtur rættingar hjá [[Special:Contributions/$2|$2]] ([[User talk:$2|kjak]]) til seinastu versjón hjá [[User:$1|$1]]',
-'revertpage-nouser' => 'Tók burtur rættingar hjá einum fjaldum brúkara til seinastu versjón hjá [[User:$1|$1]]',
+'revertpage-nouser' => 'Tók burtur rættingar hjá einum fjaldum brúkara til seinastu versjón hjá  {{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'Tók burtur rættingar hjá $1;
 broytti tað aftur til seinastu versjón hjá $2.',
 
@@ -2328,6 +2336,7 @@ Sí [[Special:Log/delete|slettingarloggin]] fyri at síggja seinastu strikingar
 'undelete-search-prefix' => 'Vís síður sum byrja við:',
 'undelete-search-submit' => 'Leita',
 'undelete-no-results' => 'Ongar síður sum passaðu til vóru funnar í arkivinum yvir slettaðar síður.',
+'undelete-error' => 'Feilur hendi meðan síðan skuldi endurstovnast',
 'undelete-show-file-submit' => 'Ja',
 
 # Namespace form on various pages
@@ -2341,7 +2350,7 @@ Sí [[Special:Log/delete|slettingarloggin]] fyri at síggja seinastu strikingar
 'contributions' => '{{GENDER:$1|Brúkaraíkøst}}',
 'contributions-title' => 'Brúkaraíkøst fyri $1',
 'mycontris' => 'Íkøst',
-'contribsub2' => 'Eftir $1 ($2)',
+'contribsub2' => 'Fyri {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Ongar broytingar vóru funnar, sum samsvaraðu hesar treytirnar.',
 'uctop' => '(verandi)',
 'month' => 'Frá mánaði (og áðrenn):',
@@ -2622,7 +2631,7 @@ Vinarliga vel eitt annað navn.',
 'allmessagesdefault' => 'Enskur tekstur',
 'allmessagescurrent' => 'Verandi tekstur',
 'allmessagestext' => 'Hetta er eitt yvirlit av tøkum kervisboðum í MediaWiki-navnarúmi.
-Vinarliga vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] um tú ynskir at geva títt íkast til ta generisku MediaWiki lokalisatiónina.',
+Vinarliga vitja [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] um tú ynskir at geva títt íkast til ta generisku MediaWiki lokalisatiónina.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:AllMessages''' er ikki stuðlað orsakað av at '''\$wgUseDatabaseMessages''' er sløkt.",
 'allmessages-filter-legend' => 'Filtur',
 'allmessages-filter-unmodified' => 'Óbroytt',
@@ -2733,7 +2742,7 @@ Vinarliga royn aftur.',
 'tooltip-n-randompage' => 'Far til tilvildarliga síðu',
 'tooltip-n-help' => 'Staðið har tú fært hjálp',
 'tooltip-t-whatlinkshere' => 'Yvirlit yvir allar wikisíður, ið slóða higar',
-'tooltip-t-recentchangeslinked' => 'Broytingar á síðum, ið slóða higar, í seinastuni',
+'tooltip-t-recentchangeslinked' => 'Seinastu broytingar á síðum, ið slóða higar',
 'tooltip-feed-rss' => 'RSS-fóðurið til hesa síðuna',
 'tooltip-feed-atom' => 'Atom-fóðurið til hesa síðuna',
 'tooltip-t-contributions' => 'Skoða yvirlit yvir íkast hjá hesum brúkara',
@@ -2876,7 +2885,7 @@ Vinarliga royn aftur.',
 'svg-long-desc' => 'SVG fíle, nominelt $1 × $2 pixel, fíle stødd: $3',
 'svg-long-desc-animated' => 'Animerað SVG fíla, nominelt $1 × $2 pixels, fílustødd: $3',
 'svg-long-error' => 'Ógyldug SVG fíla: $1',
-'show-big-image' => 'Full upploysn',
+'show-big-image' => 'Upprunafíla',
 'show-big-image-preview' => 'Stødd av hesi forskoðan: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Onnur upploysn|Aðrar upploysnir}}: $1.',
 'file-info-gif-frames' => '$1 {{PLURAL:$1|ramma|rammur}}',
@@ -3052,7 +3061,7 @@ Onnur metadáta verða fjald sum standard.
 
 # External editor support
 'edit-externally' => 'Rætta hesa fílu við eksternari applikatión',
-'edit-externally-help' => '(Sí [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] fyri meira kunning)',
+'edit-externally-help' => '(Sí [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] fyri meira kunning)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alt',
@@ -3142,7 +3151,7 @@ Hendan váttanarkoda fer úr gildi tann $4.',
 'version-hook-name' => 'Krókurnavn',
 'version-version' => '(Útgáva $1)',
 'version-license' => 'Lisensur',
-'version-poweredby-credits' => "Henda wiki verður rikin av '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Henda wiki verður rikin av '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'onnur',
 'version-poweredby-translators' => 'translatewiki.net týðarar',
 'version-credits-summary' => 'Vit ynskja at takka fylgjandi persónum fyri teirra íkast til [[Special:Version|MediaWiki]].',
@@ -3227,4 +3236,9 @@ Hendan váttanarkoda fer úr gildi tann $4.',
 'duration-decades' => '$1 {{PLURAL:$1|áratíggju}}',
 'duration-centuries' => '$1 {{PLURAL:$1|øld|øldir}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Úrslit',
+'expand_templates_ok' => 'Í lagi',
+'expand_templates_preview' => 'Forskoðan',
+
 );
index bb9395f..d724e54 100644 (file)
@@ -60,6 +60,7 @@
  * @author Louperivois
  * @author Ltrlg
  * @author Lucyin
+ * @author Mattho69
  * @author McDutchie
  * @author Meithal
  * @author Metroitendo
@@ -71,6 +72,7 @@
  * @author Omnipaedista
  * @author Peter17
  * @author PieRRoMaN
+ * @author ProgVal
  * @author Quentinv57
  * @author Rastus Vernon
  * @author Remember the dot
@@ -135,20 +137,20 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'MauvaisTitre', 'Mauvais_titre' ),
        'Blankpage'                 => array( 'Page_blanche', 'PageBlanche' ),
        'Block'                     => array( 'Bloquer', 'Blocage' ),
-       'Blockme'                   => array( 'Bloquez-moi', 'Bloquezmoi' ),
        'Booksources'               => array( 'Ouvrages_de_référence', 'Ouvrages_de_reference', 'Ouvragesderéférence', 'Ouvragesdereference', 'Recherche_ISBN', 'Recherche_isbn', 'RechercheISBN', 'Rechercheisbn' ),
        'BrokenRedirects'           => array( 'Redirections_cassées', 'RedirectionCassées', 'Redirections_cassees', 'RedirectionsCassees' ),
        'Categories'                => array( 'Catégories' ),
        'ChangeEmail'               => array( 'ChangerCouriel', 'Changer_courrielw' ),
        'ChangePassword'            => array( 'Changement_du_mot_de_passe', 'ChangementDuMotDePasse' ),
+       'ComparePages'              => array( 'Comparer_des_pages' ),
        'Confirmemail'              => array( 'Confirmer_l\'adresse_de_contact', 'Confirmer_le_courriel', 'ConfirmerLeCourriel' ),
        'CreateAccount'             => array( 'Créer_un_compte', 'CréerUnCompte', 'CréerCompte' ),
        'Deadendpages'              => array( 'Pages_en_impasse', 'PagesEnImpasse' ),
        'DeletedContributions'      => array( 'Contributions_supprimées', 'ContributionsSupprimées', 'ContributionSupprimees' ),
-       'Disambiguations'           => array( 'Homonymies', 'Homonymie', 'Pages_d\'homonymie' ),
        'DoubleRedirects'           => array( 'Doubles_redirections', 'DoublesRedirections', 'Redirections_doubles', 'RedirectionsDoubles' ),
        'EditWatchlist'             => array( 'Éditer_Liste_de_suivi', 'ÉditerListeDeSuivi' ),
        'Emailuser'                 => array( 'Envoyer_un_courriel', 'EnvoyerUnCourriel', 'Courriel', 'Envoyer_un_e-mail', 'EnvoyerUnEMail', 'E-mail', 'EMail' ),
+       'ExpandTemplates'           => array( 'ExpansionDesModèles' ),
        'Export'                    => array( 'Exporter', 'Exportation' ),
        'Fewestrevisions'           => array( 'Pages_les_moins_modifiées', 'PagesLesMoinsModifiées', 'Pages_les_moins_modifiees', 'PagesLesMoinsModifiees', 'Les_moins_modifiés', 'LesMoinsModifiés', 'Les_moins_modifies', 'LesMoinsModifies' ),
        'FileDuplicateSearch'       => array( 'Recherche_fichier_en_double', 'RechercheFichierEnDouble' ),
@@ -181,6 +183,7 @@ $specialPageAliases = array(
        'Mytalk'                    => array( 'Mes_discussions', 'Mesdiscussions' ),
        'Newimages'                 => array( 'Nouveaux_fichiers', 'NouveauxFichiers', 'Nouvelles_images', 'NouvellesImages' ),
        'Newpages'                  => array( 'Nouvelles_pages', 'NouvellesPages', 'Pages_récentes', 'PagesRécentes', 'Pages_recentes', 'PagesRecentes' ),
+       'PagesWithProp'             => array( 'Pages_avec_la_propriété' ),
        'PasswordReset'             => array( 'Réinitialisation_du_mot_de_passe', 'RéinitialisationDuMotDePasse' ),
        'PermanentLink'             => array( 'LienPermanent', 'Lien_permanent' ),
        'Popularpages'              => array( 'Pages_les_plus_visitées', 'Pages_les_plus_visitees', 'Pageslesplusvisitées', 'Pageslesplusvisitees' ),
@@ -189,9 +192,11 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Pages_protégées', 'PagesProtégées', 'Pages_protegees', 'PagesProtegees' ),
        'Protectedtitles'           => array( 'Titres_protégés', 'TitresProtégés', 'Titres_proteges', 'TitresProteges' ),
        'Randompage'                => array( 'Page_au_hasard', 'PageAuHasard', 'Au_hasard', 'AuHasard', 'Aléatoire', 'Aleatoire' ),
+       'RandomInCategory'          => array( 'Page_au_hasard_dans_une_catégorie' ),
        'Randomredirect'            => array( 'Redirection_au_hasard', 'Redirect_au_hasard', 'Redirectionauhasard', 'Redirectauhasard', 'Redirection_aléatoire', 'Redirect_aléatoire', 'Redirectionaléatoire', 'Redirectaléatoire', 'Redirection_aleatoire', 'Redirect_aleatoire', 'Redirectionaleatoire', 'Redirectaleatoire' ),
        'Recentchanges'             => array( 'Modifications_récentes', 'Modifications_recentes', 'ModificationsRécentes', 'ModificationsRecentes' ),
        'Recentchangeslinked'       => array( 'Suivi_des_liens', 'SuiviDesLiens' ),
+       'Redirect'                  => array( 'Redirection' ),
        'Revisiondelete'            => array( 'Versions_supprimées', 'Versions_supprimees', 'Versionsupprimées', 'Versionsupprimees' ),
        'Search'                    => array( 'Recherche', 'Rechercher', 'Chercher' ),
        'Shortpages'                => array( 'Pages_courtes', 'PagesCourtes' ),
@@ -271,6 +276,8 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'NOMPAGECOMPLETX', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'NOMSOUSPAGE', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'NOMSOUSPAGEX', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'NOMPAGERACINE', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'NOMPAGERACINEX', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'NOMBASEDEPAGE', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'NOMBASEDEPAGEX', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'NOMPAGEDISCUSSION', 'TALKPAGENAME' ),
@@ -285,9 +292,10 @@ $magicWords = array(
        'img_center'                => array( '1', 'centré', 'center', 'centre' ),
        'img_framed'                => array( '1', 'cadre', 'encadré', 'encadre', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'sans_cadre', 'non_encadré', 'non_encadre', 'frameless' ),
-       'img_upright'               => array( '1', 'redresse', 'redresse=$1', 'redresse $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_lang'                  => array( '1', 'langue=$1', 'lang=$1' ),
+       'img_upright'               => array( '1', 'redresse', 'redresse=$1', 'redresse_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'bordure', 'border' ),
-       'img_baseline'              => array( '1', 'ligne_de_base', 'base', 'baseline' ),
+       'img_baseline'              => array( '1', 'ligne-de-base', 'base', 'baseline' ),
        'img_sub'                   => array( '1', 'indice', 'ind', 'sub' ),
        'img_super'                 => array( '1', 'exposant', 'exp', 'super', 'sup' ),
        'img_top'                   => array( '1', 'haut', 'top' ),
@@ -296,12 +304,14 @@ $magicWords = array(
        'img_bottom'                => array( '1', 'bas', 'bottom' ),
        'img_text_bottom'           => array( '1', 'bas-texte', 'bas-txt', 'text-bottom' ),
        'img_link'                  => array( '1', 'lien=$1', 'link=$1' ),
+       'img_class'                 => array( '1', 'classe=$1', 'class=$1' ),
        'sitename'                  => array( '1', 'NOMSITE', 'SITENAME' ),
        'ns'                        => array( '0', 'ESPACEN:', 'NS:' ),
        'nse'                       => array( '0', 'ESPACENX:', 'NSE:' ),
        'localurl'                  => array( '0', 'URLLOCALE:', 'LOCALURL:' ),
        'localurle'                 => array( '0', 'URLLOCALEX:', 'LOCALURLE:' ),
        'articlepath'               => array( '0', 'CHEMINARTICLE', 'ARTICLEPATH' ),
+       'pageid'                    => array( '0', 'IDPAGE', 'PAGEID' ),
        'server'                    => array( '0', 'SERVEUR', 'SERVER' ),
        'servername'                => array( '0', 'NOMSERVEUR', 'SERVERNAME' ),
        'scriptpath'                => array( '0', 'CHEMINSCRIPT', 'SCRIPTPATH' ),
@@ -325,6 +335,8 @@ $magicWords = array(
        'plural'                    => array( '0', 'PLURIEL:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'URLCOMPLETE:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'URLCOMPLETEX:', 'FULLURLE:' ),
+       'canonicalurl'              => array( '0', 'URLCANONIQUE:', 'CANONICALURL:' ),
+       'canonicalurle'             => array( '0', 'URLCANONIQUEX:', 'CANONICALURLE:' ),
        'lcfirst'                   => array( '0', 'INITMINUS:', 'LCFIRST:' ),
        'ucfirst'                   => array( '0', 'INITMAJUS:', 'INITCAPIT:', 'UCFIRST:' ),
        'lc'                        => array( '0', 'MINUS:', 'LC:' ),
@@ -332,6 +344,7 @@ $magicWords = array(
        'raw'                       => array( '0', 'BRUT:', 'RAW:' ),
        'displaytitle'              => array( '1', 'AFFICHERTITRE', 'DISPLAYTITLE' ),
        'rawsuffix'                 => array( '1', 'BRUT', 'B', 'R' ),
+       'nocommafysuffix'           => array( '0', 'SANSSEP', 'NOSEP' ),
        'newsectionlink'            => array( '1', '__LIENNOUVELLESECTION__', '__NEWSECTIONLINK__' ),
        'nonewsectionlink'          => array( '1', '__AUCUNLIENNOUVELLESECTION__', '__NONEWSECTIONLINK__' ),
        'currentversion'            => array( '1', 'VERSIONACTUELLE', 'CURRENTVERSION' ),
@@ -348,6 +361,7 @@ $magicWords = array(
        'padleft'                   => array( '0', 'BOURRAGEGAUCHE', 'BOURREGAUCHE', 'PADLEFT' ),
        'padright'                  => array( '0', 'BOURRAGEDROITE', 'BOURREDROITE', 'PADRIGHT' ),
        'special'                   => array( '0', 'spécial', 'special' ),
+       'speciale'                  => array( '0', 'spéciale', 'speciale' ),
        'defaultsort'               => array( '1', 'CLEFDETRI:', 'CLEDETRI:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
        'filepath'                  => array( '0', 'CHEMIN:', 'FILEPATH:' ),
        'tag'                       => array( '0', 'balise', 'tag' ),
@@ -360,8 +374,11 @@ $magicWords = array(
        'protectionlevel'           => array( '1', 'NIVEAUDEPROTECTION', 'PROTECTIONLEVEL' ),
        'url_path'                  => array( '0', 'CHEMIN', 'PATH' ),
        'url_query'                 => array( '0', 'QUESTION', 'QUERY' ),
+       'defaultsort_noerror'       => array( '0', 'sanserreur', 'noerror' ),
+       'defaultsort_noreplace'     => array( '0', 'sansremplacer', 'noreplace' ),
        'pagesincategory_all'       => array( '0', 'tous', 'all' ),
-       'pagesincategory_files'     => array( '0', 'fichier', 'files' ),
+       'pagesincategory_subcats'   => array( '0', 'souscats', 'subcats' ),
+       'pagesincategory_files'     => array( '0', 'fichiers', 'files' ),
 );
 
 $bookstoreList = array(
@@ -434,7 +451,7 @@ $messages = array(
 'tog-noconvertlink' => 'Désactiver la conversion des titres',
 'tog-norollbackdiff' => "Ne pas afficher le diff lors d'une révocation",
 'tog-useeditwarning' => "M'avertir quand je quitte une page de modification sans publier les changements",
-'tog-prefershttps' => 'Toujours utiliser une connexion sécurisée en étant connecté',
+'tog-prefershttps' => 'Toujours utiliser une connexion sécurisée en étant connecté(e)',
 
 'underline-always' => 'Toujours',
 'underline-never' => 'Jamais',
@@ -664,11 +681,9 @@ $1",
 'ok' => 'Valider',
 'retrievedfrom' => 'Récupérée de « $1 »',
 'youhavenewmessages' => 'Vous avez $1 ($2).',
-'newmessageslink' => 'de nouveaux messages',
-'newmessagesdifflink' => 'dernière modification',
 'youhavenewmessagesfromusers' => "Vous avez $1 {{PLURAL:$3|d'un autre utilisateur|de $3 autres utilisateurs}} ($2).",
 'youhavenewmessagesmanyusers' => 'Vous avez $1 de nombreux utilisateurs ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un message|de nouveaux messages}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un nouveau message|de nouveaux messages}}',
 'newmessagesdifflinkplural' => '{{PLURAL:$1|dernière modification|dernières modifications}}',
 'youhavenewmessagesmulti' => 'Vous avez de nouveaux messages sur $1.',
 'editsection' => 'modifier',
@@ -763,7 +778,7 @@ Aucune explication n'a été fournie.",
 'badtitle' => 'Mauvais titre',
 'badtitletext' => 'Le titre de la page demandée est invalide, vide, ou il s’agit d’un titre inter-langue ou inter-projet mal formé. Il contient peut-être un ou plusieurs caractères qui ne peuvent pas être utilisés dans les titres.',
 'perfcached' => 'Les données suivantes sont en cache et peuvent ne pas être à jour. Un maximum de {{PLURAL:$1|un résultat|$1 résultats}} est disponible dans le cache.',
-'perfcachedts' => 'Les données suivantes sont en cache et ont été mises à jour pour la dernière fois à $1. Un maximum de {{PLURAL:$4|un résultat|$4 résultats}} est disponible dans le cache.',
+'perfcachedts' => 'Les données suivantes sont en cache et ont été mises à jour pour la dernière fois le $1. Un maximum de {{PLURAL:$4|un résultat est disponible|$4 résultats sont disponibles}} dans le cache.',
 'querypage-no-updates' => 'Les mises à jour pour cette page sont actuellement désactivées. Les données ci-dessous ne sont pas mises à jour.',
 'wrong_wfQuery_params' => 'Paramètres incorrects sur wfQuery()<br />
 Fonction : $1<br />
@@ -797,8 +812,9 @@ Le motif avancé est « ''$2'' ».",
 L'administrateur qui l'a verrouillé a fourni ce motif : « $3 ».",
 'invalidtitle-knownnamespace' => "Titre invalide avec l'espace de noms « $2 » et l'intitulé « $3 »",
 'invalidtitle-unknownnamespace' => "Titre invalide avec le numéro d'espace de noms $1 et l'intitulé « $2 » inconnus",
-'exception-nologin' => 'Non connecté',
-'exception-nologin-text' => "Cette page ou cette action nécessite d'être connecté sur ce wiki.",
+'exception-nologin' => 'Non connecté(e)',
+'exception-nologin-text' => 'Veuillez [[Special:Userlogin|vous connecter]] pour pouvoir accéder à cette page ou cette action.',
+'exception-nologin-text-manual' => 'Veuillez $1 pour pouvoir accéder à cette page ou cette action.',
 
 # Virus scanner
 'virus-badscanner' => "Mauvaise configuration : scanneur de virus inconnu : ''$1''",
@@ -839,17 +855,17 @@ N'oubliez pas de modifier [[Special:Preferences|vos préférences pour {{SITENAM
 'notloggedin' => 'Non connecté',
 'userlogin-noaccount' => "Vous n'avez pas de compte ?",
 'userlogin-joinproject' => 'Rejoignez {{SITENAME}}',
-'nologin' => "Vous n'êtes pas encore inscrit ? $1.",
+'nologin' => "Vous n'avez pas de compte ? $1.",
 'nologinlink' => 'Créer un compte',
 'createaccount' => 'Créer un compte',
 'gotaccount' => "Vous avez déjà un compte ? '''$1'''.",
 'gotaccountlink' => 'Connectez-vous',
 'userlogin-resetlink' => 'Vous avez oublié vos détails de connexion ?',
-'userlogin-resetpassword-link' => 'Réinitialiser le mot de passe',
+'userlogin-resetpassword-link' => 'Mot de passe oublié ?',
 'helplogin-url' => 'Help:Connexion',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Aide à la connexion]]',
-'userlogin-loggedin' => 'Vous êtes déjà connecté en tant que {{GENDER:$1|$1}}.
-Utilisez le formulaire ci-dessous pour vous connecter avec un autre utilisateur.',
+'userlogin-loggedin' => 'Vous êtes déjà connecté{{GENDER:$1||e|(e)}} en tant que {{GENDER:$1|$1}}.
+Utilisez le formulaire ci-dessous pour vous connecter avec un autre compte utilisateur.',
 'userlogin-createanother' => 'Créer un autre compte',
 'createacct-join' => 'Entrez vos informations ci-dessous.',
 'createacct-another-join' => 'Saisir les informations du nouveau compte ci-dessous.',
@@ -894,7 +910,7 @@ Vérifiez l'orthographe, ou [[Special:UserLogin/signup|créez un nouveau compte]
 'passwordtooshort' => 'Votre mot de passe doit contenir au moins $1 caractère{{PLURAL:$1||s}}.',
 'password-name-match' => "Votre mot de passe doit être différent de votre nom d'utilisateur.",
 'password-login-forbidden' => "L'utilisation de ce nom d'utilisateur et de ce mot de passe a été interdite.",
-'mailmypassword' => 'Recevoir un nouveau mot de passe par courriel',
+'mailmypassword' => 'Réinitialiser le mot de passe',
 'passwordremindertitle' => 'Nouveau mot de passe temporaire pour {{SITENAME}}',
 'passwordremindertext' => "Quelqu'un (probablement vous, ayant l'adresse IP $1) a demandé un nouveau mot de
 passe pour {{SITENAME}} ($4 ). Un mot de passe temporaire a été créé pour
@@ -909,14 +925,14 @@ pouvez ignorer ce message et continuer à utiliser votre ancien mot de passe.",
 'noemailcreate' => 'Vous devez fournir une adresse de courriel valide',
 'passwordsent' => "Un nouveau mot de passe a été envoyé à l'adresse de courriel de l'utilisateur « $1 ». Veuillez vous reconnecter après l'avoir reçu.",
 'blocked-mailpassword' => 'Votre adresse IP est bloquée en écriture, la fonction de rappel du mot de passe est donc désactivée pour éviter les abus.',
-'eauthentsent' => "Un courriel de confirmation a été envoyé à l'adresse indiquée.
-Avant qu'un autre courriel ne soit envoyé à ce compte, vous devrez suivre les instructions du courriel et confirmer que le compte est bien le vôtre.",
+'eauthentsent' => 'Un courriel de confirmation a été envoyé à l’adresse indiquée.
+Avant qu’un autre courriel ne soit envoyé à ce compte, vous devrez suivre les instructions du courriel et confirmer que le compte est bien le vôtre.',
 'throttled-mailpassword' => "Un courriel de réinitialisation de votre mot de passe a déjà été envoyé durant {{PLURAL:$1|la dernière heure|les $1 dernières heures}}. Afin d'éviter les abus, un seul courriel de réinitialisation de votre mot de passe sera envoyé par {{PLURAL:$1|heure|intervalle de $1 heures}}.",
 'mailerror' => "Erreur lors de l'envoi du courriel : $1",
 'acct_creation_throttle_hit' => "Quelqu'un utilisant votre adresse IP a créé {{PLURAL:$1|un compte|$1 comptes}} au cours des dernières 24 heures, ce qui constitue la limite autorisée dans cet intervalle de temps.
 Par conséquent, la création de compte a été temporairement désactivée pour cette adresse IP.",
-'emailauthenticated' => 'Votre adresse de courriel a été authentifiée le $2 à $3.',
-'emailnotauthenticated' => "Votre adresse de courriel n'est <strong>pas encore authentifiée</strong>. Aucun courriel ne sera envoyé pour chacune des fonctions suivantes.",
+'emailauthenticated' => 'Votre adresse de courriel a été confirmée le $2 à $3.',
+'emailnotauthenticated' => "Votre adresse de courriel n'est pas encore confirmée. Aucun courriel ne sera envoyé pour chacune des fonctions suivantes.",
 'noemailprefs' => 'Indiquez une adresse de courriel dans vos préférences pour utiliser ces fonctions.',
 'emailconfirmlink' => 'Confirmez votre adresse de courriel',
 'invalidemailaddress' => 'Cette adresse courriel ne peut pas être acceptée car elle semble avoir un format incorrect.
@@ -955,7 +971,7 @@ Si vous décidez de le fournir, il sera utilisé pour attribuer à l’utilisate
 'resetpass_submit' => 'Changer le mot de passe et se connecter',
 'changepassword-success' => 'Votre mot de passe a été changé avec succès !',
 'resetpass_forbidden' => 'Les mots de passe ne peuvent pas être changés',
-'resetpass-no-info' => 'Vous devez être connecté pour avoir accès à cette page.',
+'resetpass-no-info' => 'Vous devez être connecté(e) pour avoir accès à cette page.',
 'resetpass-submit-loggedin' => 'Changer de mot de passe',
 'resetpass-submit-cancel' => 'Annuler',
 'resetpass-wrong-oldpass' => 'Mot de passe actuel ou temporaire invalide.
@@ -966,7 +982,7 @@ Vous avez peut-être déjà changé votre mot de passe ou demandé un nouveau mo
 # Special:PasswordReset
 'passwordreset' => 'Remise à zéro 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 réinitialiser votre mot de passe.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Remplissez un des champs pour recevoir un mot de passe temporaire par courriel.}}',
 'passwordreset-legend' => 'Remise à zéro du mot de passe',
 'passwordreset-disabled' => 'La réinitialisation des mots de passe a été désactivée sur ce wiki.',
 'passwordreset-emaildisabled' => 'Les fonctionnalités e-mail ont été désactivées sur ce wiki.',
@@ -996,7 +1012,7 @@ Mot de passe temporaire : $2",
 'changeemail' => 'Changer l’adresse de courriel',
 'changeemail-header' => 'Changer l’adresse de courriel du compte',
 'changeemail-text' => 'Remplissez ce formulaire pour changer votre adresse de courriel. Vous devrez entrer votre mot de passe pour confirmer ce changement.',
-'changeemail-no-info' => 'Vous devez être connecté pour pouvoir accéder directement à cette page.',
+'changeemail-no-info' => 'Vous devez être connecté(e) pour pouvoir accéder directement à cette page.',
 'changeemail-oldemail' => 'Adresse de courriel actuelle :',
 'changeemail-newemail' => 'Nouvelle adresse de courriel :',
 'changeemail-none' => '(aucune)',
@@ -1048,7 +1064,7 @@ Vous devriez le faire si vous les avez partagés accidentellement avec quelqu'un
 'showlivepreview' => 'Aperçu rapide',
 'showdiff' => 'Voir les modifications',
 'anoneditwarning' => "'''Attention :''' vous n'êtes pas identifié(e). Votre adresse IP sera enregistrée dans l'historique de cette page.",
-'anonpreviewwarning' => "''Vous n'êtes pas identifié. Sauvegarder enregistrera votre adresse IP dans l'historique des modifications de la page.''",
+'anonpreviewwarning' => "''Vous n'êtes pas identifié(e). Sauvegarder enregistrera votre adresse IP dans l'historique des modifications de la page.''",
 'missingsummary' => "'''Rappel :''' vous n'avez pas encore fourni le résumé de votre modification.
 Si vous cliquez de nouveau sur le bouton « {{int:savearticle}} », la publication sera faite sans nouvel avertissement.",
 'missingcommenttext' => 'Veuillez entrer un commentaire ci-dessous.',
@@ -1097,7 +1113,7 @@ Elle a peut-être été déplacée ou supprimée depuis que vous avez lu cette p
 'loginreqpagetext' => 'Vous devez vous $1 pour voir les autres pages.',
 'accmailtitle' => 'Mot de passe envoyé.',
 'accmailtext' => "Un mot de passe généré aléatoirement pour [[User talk:$1|$1]] a été envoyé à $2.
-Il peut être modifié sur la page ''[[Special:ChangePassword|Changement de mot de passe]]'' après s’être connecté.",
+Il peut être modifié sur la page ''[[Special:ChangePassword|Changement de mot de passe]]'' après s’être connecté{{GENDER:$1||e|(e)}}.",
 'newarticle' => '(Nouveau)',
 'newarticletext' => "Vous avez suivi un lien vers une page qui n'existe pas encore ou qui a été [{{fullurl:Special:Log|type=delete&page={{FULLPAGENAMEE}}}} effacée].
 Pour créer cette page, entrez votre texte dans la boîte ci-dessous (vous pouvez consulter [[{{MediaWiki:Helppage}}|la page d'aide]] pour plus d'informations).
@@ -1169,8 +1185,8 @@ Une solution de rechange a été trouvée pour vous permettre de modifier en tou
 'editingold' => "'''Attention : vous êtes en train de modifier une ancienne version de cette page.
 Si vous la publiez, toutes les modifications effectuées depuis cette version seront perdues.'''",
 '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). Si vous ne désirez pas que vos écrits soient modifiés et distribués à volonté, merci de ne pas les soumettre ici.<br 
-/>Vous 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. '''N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !'''",
+'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). Si vous ne désirez pas que vos écrits soient modifiés et distribués à volonté, merci de ne pas les soumettre ici.<br />
+Vous 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. '''N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !'''",
 'copyrightwarning2' => "Toutes les contributions à {{SITENAME}} peuvent être modifiées ou supprimées par d’autres utilisateurs. Si vous ne désirez pas que vos écrits soient modifiés et distribués à volonté, merci de ne pas les soumettre ici.<br 
 />Vous 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’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !'''",
@@ -1339,18 +1355,19 @@ Vous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#S
 Les autres administrateurs de {{SITENAME}} pourront toujours accéder au contenu caché et le restaurer à travers cette même interface, à moins que des restrictions supplémentaires ne soient mises en place.",
 '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 '''que''' dans les cas suivants :
+* Informations potentiellement diffamatoires
 * Informations personnelles inappropriées
 *: ''adresse, numéro de téléphone, numéro de sécurité sociale, …''",
 'revdelete-legend' => 'Mettre en place des restrictions de visibilité :',
-'revdelete-hide-text' => 'Masquer le texte de la version',
+'revdelete-hide-text' => 'Texte de la révision',
 'revdelete-hide-image' => 'Masquer le contenu du fichier',
 'revdelete-hide-name' => "Masquer l'action et la cible",
-'revdelete-hide-comment' => 'Masquer le commentaire de modification',
-'revdelete-hide-user' => "Masquer le pseudo ou l'adresse IP du contributeur.",
+'revdelete-hide-comment' => 'Modifier le résumé',
+'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-radio-same' => '(ne pas changer)',
-'revdelete-radio-set' => 'Oui',
-'revdelete-radio-unset' => 'Non',
+'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 :',
@@ -1477,10 +1494,10 @@ Vous pouvez trouver des détails dans le [{{fullurl:{{#Special:Log}}/delete|page
 'search-interwiki-caption' => 'Projets frères',
 'search-interwiki-default' => 'Résultats sur $1 :',
 'search-interwiki-more' => '(plus)',
-'search-relatedarticle' => 'Relaté',
+'search-relatedarticle' => 'Reliés',
 'mwsuggest-disable' => 'Désactiver les suggestions de recherche',
 'searcheverything-enable' => 'Rechercher dans tous les espaces de noms',
-'searchrelated' => 'relaté',
+'searchrelated' => 'reliés',
 'searchall' => 'tout',
 'showingresults' => 'Affichage de <b>$1</b> résultat{{PLURAL:$1||s}} à partir du n°<b>$2</b>.',
 'showingresultsnum' => 'Affichage de <b>$3</b> résultat{{PLURAL:$3||s}} à partir du n°<b>$2</b>.',
@@ -1504,8 +1521,7 @@ Essayez en utilisant le préfixe ''all:'' pour rechercher dans tout le contenu (
 'preferences' => 'Préférences',
 'mypreferences' => 'Préférences',
 'prefs-edits' => 'Nombre de modifications :',
-'prefsnologin' => 'Non connecté',
-'prefsnologintext' => 'Vous devez être <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} connecté]</span> pour modifier vos préférences d\'utilisateur.',
+'prefsnologintext2' => 'Veuillez $1 pour définir les préférences utilisateur.',
 'changepassword' => 'Changer de mot de passe',
 'prefs-skin' => 'Habillage',
 'skin-preview' => 'Prévisualiser',
@@ -1713,7 +1729,7 @@ Cette information sera publique.',
 'right-unblockself' => 'Se débloquer soi-même',
 'right-protect' => 'Modifier les niveaux de protection et modifier les pages protégées en cascade',
 'right-editprotected' => 'Modifier les pages protégées avec « {{int:protect-level-sysop}} »',
-'right-editsemiprotected' => 'Modifier les pages protégées avec « {{int:protect-level-autoconfirmed}} »',
+'right-editsemiprotected' => 'Modifier les pages protégées avec « {{int:protect-level-autoconfirmed}} »',
 'right-editinterface' => "Modifier l'interface utilisateur",
 'right-editusercssjs' => "Modifier les fichiers CSS et JavaScript d'autres utilisateurs",
 'right-editusercss' => "Modifier les fichiers CSS d'autres utilisateurs",
@@ -1804,6 +1820,9 @@ Cette information sera publique.',
 'recentchanges-label-minor' => 'Cette modification est mineure',
 'recentchanges-label-bot' => 'Cette modification a été effectuée par un robot.',
 'recentchanges-label-unpatrolled' => "Cette modification n'a pas encore été patrouillée.",
+'recentchanges-label-plusminus' => 'La taille de la page a changé de ce nombre d’octets',
+'recentchanges-legend-newpage' => '(voir aussi la [[Special:NewPages|liste des nouvelles pages]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Voici {{PLURAL:$1|la dernière modification effectuée|les $1 dernières modifications effectuées}} durant {{PLURAL:$2|la dernière journée|les <b>$2</b> derniers jours}} jusqu'à $5 le $4.",
 'rcnotefrom' => "Voici les modifications effectuées depuis le '''$2''' ('''$1''' au maximum).",
 'rclistfrom' => 'Afficher les nouvelles modifications depuis le $1.',
@@ -1844,7 +1863,7 @@ Cette information sera publique.',
 'uploadbtn' => 'Importer le fichier',
 'reuploaddesc' => "Annuler et retourner au formulaire d'import",
 'upload-tryagain' => 'Envoyer la description du fichier modifiée',
-'uploadnologin' => 'Non connecté(e)',
+'uploadnologin' => 'Non connecté{{GENDER:||e|(e)}}',
 'uploadnologintext' => 'Vous devez $1 pour importer des fichiers.',
 'upload_directory_missing' => "Le répertoire d'import de fichier ($1) est introuvable et n'a pas pu être créé par le serveur web.",
 'upload_directory_read_only' => "Le répertoire d'import de fichier ($1) n'est pas accessible en écriture depuis le serveur web.",
@@ -2058,7 +2077,7 @@ Voyez https://www.mediawiki.org/wiki/Manual:Image_Authorization.",
 'img-auth-notindir' => "Le chemin demandé n'est pas le répertoire d'import configuré.",
 'img-auth-badtitle' => 'Impossible de construire un titre valide à partir de « $1 ».',
 'img-auth-nologinnWL' => "Vous n'êtes pas connecté et « $1 » n'est pas dans la liste blanche.",
-'img-auth-nofile' => "Le fichier « $1 » n'existe pas.",
+'img-auth-nofile' => "Le fichier « $1 » n'existe pas.",
 'img-auth-isdir' => "Vous essayez d'accéder au répertoire « $1 ».
 Seul l'accès aux fichiers est permis.",
 'img-auth-streaming' => 'Lecture en continu de « $1 ».',
@@ -2239,7 +2258,7 @@ N'oubliez pas de vérifier s'il n'y a pas d'autres liens vers les modèles avant
 'pageswithprop' => 'Pages avec une propriété de page',
 'pageswithprop-legend' => 'Pages avec une propriété de page',
 'pageswithprop-text' => 'Cette page liste les pages qui utilisent une propriété de page particulière.',
-'pageswithprop-prop' => 'Nom de la propriété:',
+'pageswithprop-prop' => 'Nom de la propriété :',
 'pageswithprop-submit' => 'Aller',
 'pageswithprop-prophidden-long' => 'valeur de propriété de texte long masquée ($1)',
 'pageswithprop-prophidden-binary' => 'valeur de propriété binaire masquée ($1)',
@@ -2481,8 +2500,8 @@ L'adresse électronique que vous avez indiquée dans [[Special:Preferences|vos p
 'watchlistfor2' => 'Pour $1 $2',
 'nowatchlist' => 'Votre liste de suivi ne référence aucune page.',
 'watchlistanontext' => 'Veuillez vous $1 pour visualiser ou modifier les éléments de votre liste de suivi.',
-'watchnologin' => 'Non connecté',
-'watchnologintext' => 'Vous devez être [[Special:UserLogin|identifié]] pour modifier votre liste de suivi.',
+'watchnologin' => 'Non connecté(e)',
+'watchnologintext' => 'Vous devez être [[Special:UserLogin|identifié(e)]] pour modifier votre liste de suivi.',
 'addwatch' => 'Ajouter à la liste de suivi',
 'addedwatchtext' => 'La page « [[:$1]] » a été ajoutée à votre [[Special:Watchlist|liste de suivi]].
 Les prochaines modifications de cette page et de la page de discussion associée y seront répertoriées.',
@@ -2536,9 +2555,9 @@ Contactez ce contributeur :
 courriel : $PAGEEDITOR_EMAIL
 wiki : $PAGEEDITOR_WIKI
 
-Il n\'y aura pas d\'autres notifications en cas de changements ultérieurs, à moins que vous ne visitiez cette page. Vous pouvez aussi réinitialiser les drapeaux de notification pour toutes les pages de votre liste de suivi.
+Il n’y aura pas d’autres notifications en cas de changements ultérieurs, à moins que vous ne visitiez cette page une fois connecté. Vous pouvez aussi réinitialiser les drapeaux de notification pour toutes les pages de votre liste de suivi.
 
-             Votre système de notification de {{SITENAME}}
+Votre système de notification de {{SITENAME}}
 
 --
 Pour modifier les paramètres de notification par courriel, visitez
@@ -2832,7 +2851,7 @@ Donnez ci-dessous un motif précis (par exemple en citant les pages qui ont ét
 'blockipsuccesssub' => 'Blocage réussi',
 'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] a été bloqué{{GENDER:$1||e|}}.<br />
 Consultez la [[Special:BlockList|liste des blocages]] pour revoir les blocages.',
-'ipb-blockingself' => 'Vous êtes sur le point de bloquer votre propre compte ! Êtes-vous certain de vouloir faire cela ?',
+'ipb-blockingself' => 'Vous êtes sur le point de bloquer votre propre compte ! Êtes-vous certain{{GENDER:||e|(e)}} de vouloir faire cela ?',
 'ipb-confirmhideuser' => "Vous êtes sur le point de bloquer un utilisateur avec « cacher l'utilisateur » activé. Cela supprime le nom de l'utilisateur dans toutes les listes et les entrées du journal. Êtes-vous sûr de vouloir le faire ?",
 'ipb-edit-dropdown' => 'Modifier les motifs de blocage par défaut',
 'ipb-unblock-addr' => 'Débloquer $1',
@@ -2842,8 +2861,8 @@ Consultez la [[Special:BlockList|liste des blocages]] pour revoir les blocages.'
 'unblockip' => 'Débloquer un utilisateur ou une adresse IP',
 'unblockiptext' => "Utilisez le formulaire ci-dessous pour rétablir l'accès aux modifications depuis une adresse IP ou un nom d'utilisateur.",
 'ipusubmit' => 'Supprimer ce blocage',
-'unblocked' => '[[User:$1|$1]] a été débloqué',
-'unblocked-range' => '$1 a été débloqué',
+'unblocked' => '[[User:$1|$1]] a été débloqué{{GENDER:$1||e|(e)}}',
+'unblocked-range' => '$1 a été débloqué{{GENDER:$1||e|(e)}}',
 'unblocked-id' => 'Le blocage $1 a été enlevé',
 'blocklist' => 'Utilisateurs bloqués',
 'ipblocklist' => 'Utilisateurs bloqués',
@@ -2917,7 +2936,7 @@ Vous ne pouvez pas créer un compte.',
 'cant-block-while-blocked' => 'Vous ne pouvez pas bloquer d’autres utilisateurs tant que vous êtes bloqué{{GENDER:||e|(e)}}.',
 'cant-see-hidden-user' => "L’utilisateur que vous tentez de bloquer a déjà été bloqué et masqué. N’ayant pas le droit ''hideuser'', vous ne pouvez pas voir ou modifier le blocage de cet utilisateur.",
 'ipbblocked' => "Vous ne pouvez pas bloquer ou débloquer d'autres utilisateurs, parce que vous êtes vous-même bloqué",
-'ipbnounblockself' => "Vous n'êtes pas autorisé à vous débloquer vous-même",
+'ipbnounblockself' => "Vous n'êtes pas autorisé{{GENDER:||e|(e)}} à vous débloquer vous-même",
 
 # Developer tools
 'lockdb' => 'Verrouiller la base de données',
@@ -3054,7 +3073,7 @@ Dans ce dernier cas vous pouvez aussi utiliser un lien, tel que [[{{#Special:Exp
 'allmessagesdefault' => 'Message par défaut',
 'allmessagescurrent' => 'Message actuel',
 'allmessagestext' => "Ceci est la liste des messages disponibles dans l'espace MediaWiki.
-Veuillez visiter la [//www.mediawiki.org/wiki/Localisation Localisation de MediaWiki] et [//translatewiki.net/ translatewiki.net] si vous désirez contribuer à la localisation générique de MediaWiki.",
+Veuillez visiter la [https://www.mediawiki.org/wiki/Localisation Localisation de MediaWiki] et [//translatewiki.net/ translatewiki.net] si vous désirez contribuer à la localisation générique de MediaWiki.",
 'allmessagesnotsupportedDB' => "Cette page '''{{ns:special}}:Allmessages''' n'est pas utilisable car '''\$wgUseDatabaseMessages''' a été désactivé.",
 'allmessages-filter-legend' => 'Filtrer',
 'allmessages-filter' => 'Filtrer par état de modification :',
@@ -3221,7 +3240,7 @@ Vous pouvez toutefois en visualiser la source.',
 'tooltip-undo' => '« Annuler » rétablit la modification précédente et ouvre la fenêtre de modification en mode prévisualisation. Il est possible d’ajouter une raison dans le résumé.',
 'tooltip-preferences-save' => 'Sauvegarder les préférences',
 'tooltip-summary' => 'Entrez un bref résumé',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Le CSS placé ici sera appliqué à tous les habillages. */',
@@ -3270,6 +3289,8 @@ Vous pouvez toutefois en visualiser la source.',
 'spam_reverting' => 'Rétablissement de la dernière version ne contenant pas de lien vers $1',
 'spam_blanking' => 'Toutes les versions contenant des liens vers $1 sont blanchies',
 'spam_deleting' => 'Toutes les versions contenaient des liens vers $1, suppression',
+'simpleantispam-label' => "Vérification anti-pourriel.
+Ne '''RIEN''' inscrire ici !",
 
 # Info page
 'pageinfo-title' => 'Informations pour « $1 »',
@@ -3283,6 +3304,7 @@ Vous pouvez toutefois en visualiser la source.',
 'pageinfo-length' => 'Taille de la page (en octets)',
 'pageinfo-article-id' => 'Numéro de la page',
 'pageinfo-language' => 'Langue du contenu de la page',
+'pageinfo-content-model' => 'Modèle de contenu de la page',
 'pageinfo-robot-policy' => 'Indexation par robots',
 'pageinfo-robot-index' => 'Autorisée',
 'pageinfo-robot-noindex' => 'Interdite',
@@ -3369,7 +3391,7 @@ Si vous l'exécutez, votre système peut être compromis.",
 'svg-long-desc' => 'Fichier SVG, résolution de $1 × $2 pixels, taille : $3',
 'svg-long-desc-animated' => 'Fichier SVG animé, taille $1 x $2 pixels, taille du fichier: $3',
 'svg-long-error' => 'Fichier SVG non valide: $1',
-'show-big-image' => 'Image en plus haute résolution',
+'show-big-image' => "Fichier d'origine",
 'show-big-image-preview' => 'Taille de cet aperçu : $1.',
 'show-big-image-other' => '{{PLURAL:$2|Autre résolution|Autres résolutions}} : $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3841,7 +3863,7 @@ Les autres liens sur la même ligne sont considérés comme des exceptions, par
 
 # External editor support
 'edit-externally' => 'Modifier ce fichier en utilisant une application externe',
-'edit-externally-help' => "(Consulter [//www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d'installation] pour plus d'informations)",
+'edit-externally-help' => "(Consulter [https://www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d'installation] pour plus d'informations)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tout',
@@ -3929,7 +3951,7 @@ $5',
 'scarytranscludetoolong' => "[L'URL est trop longue]",
 
 # Delete conflict
-'deletedwhileediting' => "'''Attention''' : cette page a été supprimée après que vous avez commencé à la modifier !",
+'deletedwhileediting' => "'''Attention''' : cette page a été supprimée après que vous ayez commencé à la modifier !",
 'confirmrecreate' => "L’utilisateur [[User:$1|$1]] ([[User talk:$1|Discussion]]) a supprimé cette page, alors que vous aviez commencé à la modifier, pour le motif suivant :
 : ''$2''
 Veuillez confirmer que vous désirez réellement recréer cette page.",
@@ -3951,6 +3973,7 @@ Veuillez confirmer que vous désirez réellement recréer cette page.",
 'semicolon-separator' => '&nbsp;;&#32;',
 'colon-separator' => '&nbsp;:&#32;',
 'percent' => '$1&#160;%',
+'quotation-marks' => '« $1 »',
 
 # Multipage image navigation
 'imgmultipageprev' => '← page précédente',
@@ -4103,7 +4126,7 @@ Vous pouvez aussi [[Special:EditWatchlist|utiliser l'éditeur normal]].",
 'version-hook-subscribedby' => 'Abonnés :',
 'version-version' => '(version $1)',
 'version-license' => 'Licence',
-'version-poweredby-credits' => "Ce wiki fonctionne grâce à '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ce wiki fonctionne grâce à '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'autres',
 'version-poweredby-translators' => 'traducteurs de translatewiki.net',
 'version-credits-summary' => 'Nous tenons à remercier les personnes suivantes pour leur contribution à  [[Special:Version|MediaWiki]].',
@@ -4124,7 +4147,7 @@ Vous devriez avoir reçu [{{SERVER}}{{SCRIPTPATH}}/COPYING une copie de la Licen
 # Special:Redirect
 'redirect' => 'Redirigé par fichier, utilisateur, ou ID de révision',
 'redirect-legend' => 'Rediriger vers une page ou un fichier',
-'redirect-summary' => "Cette page spéciale redirige vers un fichier (nom donné au fichier), une page (ID attribuée à la révision) ou une page d'utilisateur (identifiant numérique attribué à l'utilisateur).",
+'redirect-summary' => 'Cette page spéciale redirige vers un fichier (nom de fichier fourni), une page (ID de révision fourni) ou une page d’utilisateur (identifiant numérique de l’utilisateur fourni). Utilisation : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], ou [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Valider',
 'redirect-lookup' => 'Recherche :',
 'redirect-value' => 'Valeur :',
@@ -4146,10 +4169,9 @@ Vous devriez avoir reçu [{{SERVER}}{{SCRIPTPATH}}/COPYING une copie de la Licen
 
 # Special:SpecialPages
 'specialpages' => 'Pages spéciales',
-'specialpages-note' => '----
-* Pages spéciales normales.
-* <span class="mw-specialpagerestricted">Pages spéciales restreintes.</span>
-* <span class="mw-specialpagecached">Pages spéciales seulement en cache (pourraient être désuètes).</span>',
+'specialpages-note-top' => 'Légende',
+'specialpages-note' => '* Pages spéciales normales.
+* <span class="mw-specialpagerestricted">Pages spéciales restreintes.</span>',
 'specialpages-group-maintenance' => 'Rapports de maintenance',
 'specialpages-group-other' => 'Autres pages spéciales',
 'specialpages-group-login' => "S'identifier / s'inscrire",
@@ -4362,4 +4384,21 @@ Sinon, vous pouvez utiliser le formulaire simplifié ci-dessous. Votre commentai
 'limitreport-expansiondepth' => 'Plus grande profondeur d’expansion',
 'limitreport-expensivefunctioncount' => 'Nombre de fonctions d’analyse coûteuses',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expansion des modèles',
+'expand_templates_intro' => "Cette page spéciale accepte un texte wiki source et permet de réaliser récursivement l’expansion des modèles qu’il contient.
+Elle réalise aussi l’expansion des fonctions du parseur telles que
+<code><nowiki>{{</nowiki>#language:...}}</code> et des variables telles que
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+En fait, elle réalise l'expansion de pratiquement tout ce qui est encadré par des doubles accolades.",
+'expand_templates_title' => 'Titre de la page, si le code utilise {{FULLPAGENAME}}, etc. :',
+'expand_templates_input' => 'Texte wiki source :',
+'expand_templates_output' => 'Texte wiki obtenu après expansion',
+'expand_templates_xml_output' => 'Résultat intermédiaire de l’analyse, au format XML',
+'expand_templates_ok' => 'Valider',
+'expand_templates_remove_comments' => 'Supprimer les commentaires',
+'expand_templates_remove_nowiki' => 'Supprime les marqueurs <nowiki> dans le résultat',
+'expand_templates_generate_xml' => 'Voir l’arborescence d’analyse XML',
+'expand_templates_preview' => 'Aperçu du rendu',
+
 );
index 7c5a5cb..bce0091 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Pâges_les_muens_dèrriérement_changiês', 'PâgesLesMuensDèrriérementChangiês' ),
        'Blankpage'                 => array( 'Pâge_voueda', 'PâgeVoueda' ),
        'Block'                     => array( 'Blocar', 'Blocâjo' ),
-       'Blockme'                   => array( 'Blocâd-mè', 'BlocâdMè' ),
        'Booksources'               => array( 'Ôvres_de_refèrence', 'ÔvresDeRefèrence' ),
        'BrokenRedirects'           => array( 'Redirèccions_câsses', 'RedirèccionsCâsses' ),
        'Categories'                => array( 'Catègories' ),
@@ -69,9 +68,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Fâre_un_compto', 'FâreUnCompto' ),
        'Deadendpages'              => array( 'Pâges_en_cul-de-sac', 'PâgesEnCulDeSac' ),
        'DeletedContributions'      => array( 'Contribucions_suprimâs', 'ContribucionsSuprimâs' ),
-       'Disambiguations'           => array( 'Homonimia', 'Homonimies', 'Pâges_d\'homonimia', 'PâgesDHomonimia' ),
        'DoubleRedirects'           => array( 'Redirèccions_dobles', 'RedirèccionsDobles' ),
        'Emailuser'                 => array( 'Mandar_un_mèssâjo', 'MandarUnMèssâjo', 'Mèssâjo' ),
+       'ExpandTemplates'           => array( 'Èxpension_des_modèlos', 'ÈxpensionDesModèlos' ),
        'Export'                    => array( 'Èxportar', 'Èxportacion' ),
        'Fewestrevisions'           => array( 'Pâges_les_muens_changiês', 'PâgesLesMuensChangiês' ),
        'FileDuplicateSearch'       => array( 'Rechèrche_des_fichiérs_en_doblo', 'RechèrcheDesFichiérsEnDoblo' ),
@@ -111,6 +110,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Pâges_protègiês', 'PâgesProtègiês' ),
        'Protectedtitles'           => array( 'Titros_protègiês', 'TitrosProtègiês' ),
        'Randompage'                => array( 'Pâge_a_l\'hasârd', 'PâgeALHasârd' ),
+       'RandomInCategory'          => array( 'Pâge_a_l\'hasârd_dens_una_catègorie', 'PâgeALHasârdDensUnaCatègorie' ),
        'Randomredirect'            => array( 'Redirèccion_a_l\'hasârd', 'RedirèccionALHasârd' ),
        'Recentchanges'             => array( 'Dèrriérs_changements', 'DèrriérsChangements' ),
        'Recentchangeslinked'       => array( 'Survelyence_des_lims', 'SurvelyenceDesLims' ),
@@ -582,8 +582,6 @@ Vêde la [[Special:Version|pâge de les vèrsions]].',
 'ok' => 'D’acôrd',
 'retrievedfrom' => 'Rècupèrâye de « $1 »',
 'youhavenewmessages' => 'Vos éd de $1 ($2).',
-'newmessageslink' => 'mèssâjos novéls',
-'newmessagesdifflink' => 'dèrriér changement',
 'youhavenewmessagesfromusers' => 'Vos éd $1 {{PLURAL:$3|d’un ôtr’utilisator|de $3 ôtros utilisators}} ($2).',
 'youhavenewmessagesmanyusers' => 'Vos éd $1 d’un mouél d’utilisators ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|un mèssâjo novél|de mèssâjos novéls}}',
@@ -1448,8 +1446,6 @@ Notâd que lor endèxacion du contegnu de {{SITENAME}} pôt pas étre a jorn.',
 'preferences' => 'Prèferences',
 'mypreferences' => 'Prèferences',
 'prefs-edits' => 'Nombro de changements :',
-'prefsnologin' => 'Pas branchiê',
-'prefsnologintext' => 'Vos dête étre <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} branchiê]</span> por dèfenir les prèferences utilisator.',
 'changepassword' => 'Changiér lo contresegno',
 'prefs-skin' => 'Habelyâjo',
 'skin-preview' => 'Prèvêre',
@@ -1725,6 +1721,7 @@ Se vos chouèsésséd de lo balyér, serat empleyê por vos atribuar voutres ôv
 'recentchanges-label-minor' => 'O est un petiôt changement',
 'recentchanges-label-bot' => 'Ceti changement est étâ fêt per un robot',
 'recentchanges-label-unpatrolled' => 'Ceti changement est p’oncor étâ gouardâ',
+'recentchanges-legend-newpage' => '$1 - pâge novèla',
 'rcnote' => "Vê-que {{PLURAL:$1|lo dèrriér changement fêt|los '''$1''' dèrriérs changements fêts}} pendent {{PLURAL:$2|lo jorn passâ|los '''$2''' jorns passâs}} tant qu’a $5 lo $4.",
 'rcnotefrom' => "Vê-que los changements fêts dês lo '''$2''' (tant qu’a '''$1''' montrâs).",
 'rclistfrom' => 'Montrar los novéls changements dês lo $1',
@@ -2988,7 +2985,7 @@ Dens cél dèrriér câs, vos pouede asse-ben utilisar un lim, coment [[{{#Speci
 'allmessagesdefault' => 'Mèssâjo per dèfôt',
 'allmessagescurrent' => 'Tèxto d’ora',
 'allmessagestext' => 'O est la lista des mèssâjos sistèmo disponiblos dens l’èspâço MediaWiki.
-Volyéd visitar la [//www.mediawiki.org/wiki/Localisation localisacion de MediaWiki] et pués [//translatewiki.net translatewiki.net] se vos voléd contribuar a la localisacion g·ènèrica de MediaWiki.',
+Volyéd visitar la [https://www.mediawiki.org/wiki/Localisation localisacion de MediaWiki] et pués [//translatewiki.net translatewiki.net] se vos voléd contribuar a la localisacion g·ènèrica de MediaWiki.',
 'allmessagesnotsupportedDB' => "Ceta pâge '''{{ns:special}}:Allmessages''' est inutilisâbla perce que '''\$wgUseDatabaseMessages''' at étâ dèsactivâ.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar per ètat de changement :',
@@ -3194,6 +3191,8 @@ O est probâblament diu a un lim de vers un seto de defôr qu’aparêt sur la l
 'spam_reverting' => 'Rètablissement de la dèrriére vèrsion que contint gins de lim de vers $1',
 'spam_blanking' => 'Totes les vèrsions que contegnont des lims de vers $1 sont blanchies',
 'spam_deleting' => 'Totes les vèrsions que contegnont des lims de vers $1 sont suprimâs',
+'simpleantispam-label' => "Contrôlo anti-spame.
+Enscrîde '''REN''' ique !",
 
 # Info page
 'pageinfo-title' => 'Enformacions por « $1 »',
@@ -3735,7 +3734,7 @@ Los ôtros champs seront cachiês per dèfôt.
 
 # External editor support
 'edit-externally' => 'Changiér ceti fichiér en utilisent una aplicacion de defôr',
-'edit-externally-help' => '(Vêde les [//www.mediawiki.org/wiki/Manual:External_editors enstruccions d’enstalacion] por més d’enformacions)',
+'edit-externally-help' => '(Vêde les [https://www.mediawiki.org/wiki/Manual:External_editors enstruccions d’enstalacion] por més d’enformacions)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tot',
@@ -3997,7 +3996,7 @@ Vos pouede asse-ben utilisar l’[[Special:EditWatchlist|èditor normal]].',
 'version-version' => '(Vèrsion $1)',
 'version-svn-revision' => '(v$2)',
 'version-license' => 'Licence',
-'version-poweredby-credits' => "Ceti vouiqui fonccione grâce a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ceti vouiqui fonccione grâce a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'ôtros',
 'version-license-info' => 'MediaWiki est una programeria libra ; vos la pouede tornar distribuar et / ou changiér d’aprés los tèrmos de la Licence publica g·ènèrala GNU coment publeyê per la Free Software Foundation ; seye la vèrsion 2 de la Licence, ou ben (a voutron chouèx) tota novèla vèrsion.
 
@@ -4024,8 +4023,7 @@ Vos devriâd avêr reçu un [{{SERVER}}{{SCRIPTPATH}}/COPYING ègzemplèro de la
 
 # Special:SpecialPages
 'specialpages' => 'Pâges spèciâles',
-'specialpages-note' => '----
-* Pâges spèciâles normales.
+'specialpages-note' => '* Pâges spèciâles normales.
 * <span class="mw-specialpagerestricted">Pâges spèciâles rètrentes.</span>
 * <span class="mw-specialpagecached">Pâges spèciâles solament en cache (porriant étre dèpassâs).</span>',
 'specialpages-group-maintenance' => 'Rapôrts de mantegnence',
@@ -4210,4 +4208,21 @@ Vos devriâd avêr reçu un [{{SERVER}}{{SCRIPTPATH}}/COPYING ègzemplèro de la
 'duration-centuries' => '$1 sièclo{{PLURAL:$1||s}}',
 'duration-millennia' => '$1 milènèro{{PLURAL:$1||s}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Èxpension des modèlos',
+'expand_templates_intro' => 'Ceta pâge spèciâla accèpte un vouiquitèxto sôrsa et pèrmèt de rèalisar rècursivament l’èxpension des modèlos que contint.
+Rèalise asse-ben l’èxpension de les fonccions du parsor coment
+<code><nowiki>{{</nowiki>#language:...<nowiki>}}</nowiki></code> et de les variâbles prèdèfenies coment
+<code><nowiki>{{</nowiki>CURRENTDAY<nowiki>}}</nowiki></code> — en veré praticament tot cen qu’est encâdrâ per des dobles colâdes.
+Rèalise cen en apelent los étâjos succèssifs que vont avouéc du parsor de MediaWiki lui-mémo.',
+'expand_templates_title' => 'Titro de la pâge, se lo code utilise {{FULLPAGENAME}}, etc. :',
+'expand_templates_input' => 'Vouiquitèxto sôrsa :',
+'expand_templates_output' => 'Rèsultat',
+'expand_templates_xml_output' => 'Rèsultat u format XML',
+'expand_templates_ok' => 'D’acôrd',
+'expand_templates_remove_comments' => 'Suprimar los comentèros',
+'expand_templates_remove_nowiki' => 'Suprime les balises <nowiki> dens lo rèsultat',
+'expand_templates_generate_xml' => 'Fâre vêre l’âbro du parsor u format XML',
+'expand_templates_preview' => 'Prèvisualisacion du rendu',
+
 );
index 4c740a7..7e25267 100644 (file)
@@ -267,7 +267,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Auer {{SITENAME}}',
 'aboutpage' => 'Project:Auer',
-'copyright' => 'Det stäänt oner det lisens $1.',
+'copyright' => 'Det sidj as tu fun oner $1 , wan diar niks ööders stäänt.',
 'copyrightpage' => '{{ns:project}}:Copyrights',
 'currentevents' => 'Aktuels',
 'currentevents-url' => 'Project:Aktuels',
@@ -297,12 +297,10 @@ Luke efter bi't [[Special:Version|werjuunssidj]]",
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Faan „$1“',
 'youhavenewmessages' => 'Dü heest $1 ($2).',
-'newmessageslink' => 'nei bööd',
-'newmessagesdifflink' => 'Leest änring',
 'youhavenewmessagesfromusers' => 'Dü heest $1 faan {{PLURAL:$3|en öödern brüker|$3 ööder brükern}} ($2).',
 'youhavenewmessagesmanyusers' => 'Dü heest $1 faan flook ööder brükern ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|ian nei nooracht|nei noorachten}}',
-'newmessagesdifflinkplural' => 'leetst {{PLURAL:$1|feranrang|feranrangen}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ian nei bööd|999=nei bööd}}',
+'newmessagesdifflinkplural' => 'leetst {{PLURAL:$1|feranrang|999=feranrangen}}',
 'youhavenewmessagesmulti' => 'Dü heest nei bööd üüb $1',
 'editsection' => 'Bewerke',
 'editold' => 'Bewerke',
@@ -432,7 +430,8 @@ Di grünj faan di administraator as: „$3“.',
 'invalidtitle-knownnamespace' => 'Ferkiard auerskraft uun di nöömrüm „$2“ an tekst „$3“',
 'invalidtitle-unknownnamespace' => 'Ferkiard auerskraft uun di ünbekäänd nöömrüm „$1“ an tekst „$2“',
 'exception-nologin' => 'Ei uunmeldet',
-'exception-nologin-text' => 'Det könst dü bluas bewerke, wan dü uunmeldet beest.',
+'exception-nologin-text' => 'Wees so gud an [[Special:Userlogin|melde di uun]], am detdiar sidj of aktjuun ütjtufeeren.',
+'exception-nologin-text-manual' => 'Wees so gud an $1 , am detdiar sidj of aktjuun ütjtufeeren.',
 
 # Virus scanner
 'virus-badscanner' => "Ferkiard iinstelang: Ünbekäänd wiirenscanner: ''$1''",
@@ -479,9 +478,12 @@ Ferjid det ei, an aachte üüb din [[Special:Preferences|{{SITENAME}} iinstelang
 'gotaccount' => "Dü hääst ål en brükerkonto? '''$1'''.",
 'gotaccountlink' => 'Uunmelde',
 'userlogin-resetlink' => 'Heest dü din login dooten ferjiden?',
-'userlogin-resetpassword-link' => 'Paaswurd turagsaat',
+'userlogin-resetpassword-link' => 'Paaswurd ferjiden?',
 'helplogin-url' => 'Help:Uunmelde',
 'userlogin-helplink' => "[[{{MediaWiki:helplogin-url}}|Halep bi't uunmeldin]]",
+'userlogin-loggedin' => 'Du beest al üs {{GENDER:$1|$1}} uunmeldet.
+Brük det formulaar diar oner, am di mä en öödern nööm uuntumeldin.',
+'userlogin-createanother' => 'En ööder brükerkonto iinracht',
 'createacct-join' => 'Du oner din dooten iin.',
 'createacct-another-join' => "Skriiw oner a dooten för't nei brükerkonto hen",
 'createacct-emailrequired' => 'E-mail adres',
@@ -502,8 +504,8 @@ Ferjid det ei, an aachte üüb din [[Special:Preferences|{{SITENAME}} iinstelang
 'createacct-benefit-body2' => '{{PLURAL:$1|sidj|sidjen}}',
 'createacct-benefit-body3' => 'aktiif {{PLURAL:$1|skriiwer|skriiwern}}',
 'badretype' => 'Jo tau paaswurden san ei likedenang.',
-'userexists' => 'Dideer brükernoome as ål ferjääwen.
-Wees sü gödj en kiis en ouderen.',
+'userexists' => 'Didiar brükernööm as al wech.
+Wees so gud an schük di en öödern.',
 'loginerror' => "Bi't uunmeldin as wat skiaf gingen",
 'createacct-error' => "Bi't iinrachten faan det brükerkonto as wat skiaf gingen",
 'createaccounterror' => 'Brükerkonto küd ei iinracht wurd: $1',
@@ -529,7 +531,7 @@ Wees so gud an ferschük det noch ans.',
 Ferschük det man noch ans.',
 'passwordtooshort' => 'Paaswurden skel tumanst {{PLURAL:$1|1 tiaken|$1 tiakens}} lung wees.',
 'password-name-match' => 'Dü könst dan brükernööm ei üs paaswurd nem.',
-'password-login-forbidden' => 'Jüdeer brükernoome än paasuurd as ferbin.',
+'password-login-forbidden' => 'Didiar brükernööm mä detdiar paaswurd as ei tuläät.',
 'mailmypassword' => 'Schüür mi en nei paaswurd.',
 'passwordremindertitle' => 'Nei tidjwiis paaswurd för {{SITENAME}}',
 'passwordremindertext' => 'En brüker (woorskiinelk dü, faan IP adres $1) hää am en nei paaswurd för {{SITENAME}} ($4) fraaget.
@@ -575,7 +577,7 @@ Wees so gud an teew $1, iar dü det noch ans ferschükst.',
 'createacct-another-realname-tip' => 'Stäänt tu wool. Wan dü dan rochten nööm uundääst, koon hi mä din feranrangen ferbünjen wurd.',
 
 # Email sending
-'php-mail-error-unknown' => 'Ünbekäänd feeler mä det funktsjuun mail() faan PHP.',
+'php-mail-error-unknown' => 'Ünbekäänd feeler mä det funktjuun mail() faan PHP.',
 'user-mail-no-addy' => 'Küd nian e-mail schüür saner e-mail-adres.',
 'user-mail-no-body' => 'Dü wulst en e-mail saner tekst wechsjüür.',
 
@@ -606,10 +608,10 @@ of am en nei paaswurd uunfraaget.',
 'passwordreset-legend' => 'Paaswurd turagsaat',
 'passwordreset-disabled' => 'Dü könst din paaswurd uun detdiar wiki ei turagsaat.',
 'passwordreset-emaildisabled' => 'E-mail as üüb detheer Wiki ufknipset wurden.',
-'passwordreset-username' => 'Brükernoome:',
+'passwordreset-username' => 'Brükernööm:',
 'passwordreset-domain' => 'Domain:',
 'passwordreset-capture' => 'Wel dü det e-mail nooracht uunluke?',
-'passwordreset-capture-help' => 'Wan dü detheer kasje uunkrüsagst, woort det e-mail nooracht mä det nei paaswurd uunwiset an tu di brüker sjüürd.',
+'passwordreset-capture-help' => 'Wan dü detheer kasche uunkrüsagst, woort det e-mail nooracht mä det nei paaswurd uunwiset an tu di brüker schüürd.',
 'passwordreset-email' => 'E-mail adres:',
 'passwordreset-emailtitle' => 'Brükerkonto aw {{SITENAME}}',
 'passwordreset-emailtext-ip' => 'Hoker mä det IP-Adres $1, woorskiinelk dü salew, wul hal brükerinformatsjuunen för {{SITENAME}} tusjüürd fu ($4). {{PLURAL:$3|Detdiar brükerkonto as|Jodiar brükerkontos san}} mä detdiar E-Mail-adres ferbünjen:
@@ -623,8 +625,8 @@ Dü skulst di uunmelde an en nei paaswurd iinracht. Wan hoker ööders detheer u
 $2
 
 {{PLURAL:$3|Detheer tidjwiis paaswurd lääpt|Joheer tidjwiis paaswurden luup}} efter {{PLURAL:$5|ään dai|$5 daar}} uf. Dü skulst di uunmelde an en nei paaswurd iinracht. Wan hoker ööders detheer uunfraag steld hää of dü din ual paaswurd käänst, säärst dü niks widjer onernem. Melde di ianfach mä din ual paaswurd uun.',
-'passwordreset-emailelement' => 'Brükernoome: $1
-Tidwis paasuurd: $2',
+'passwordreset-emailelement' => 'Brükernööm: $1
+Tidjwiis paaswurd: $2',
 'passwordreset-emailsent' => 'Diar as en E-Mail tu di onerwais.',
 'passwordreset-emailsent-capture' => 'Detdiar E-Mail, wat oner uunwiset woort, as tu di onerwais.',
 'passwordreset-emailerror-capture' => 'Detdiar E-Mail, wat oner uunwiset woort, wiar tu di onerwais, oober küd ei tu di {{GENDER:$2|brüker}} ufsjüürd wurd: $1',
@@ -690,7 +692,7 @@ Wan dü det sidj seekerst, woort det saner auerskraft auernimen.",
 'summary-preview' => 'Föörskau faan det tuupfaadang:',
 'subject-preview' => 'Föörskau faan det auerskraft:',
 'blockedtitle' => 'Brüker as speret',
-'blockedtext' => "'''Dan brükernööm of IP adres as speret wurden.'''
+'blockedtext' => "'''Dan brükernööm of din IP-adres as speret wurden.'''
 
 Det as maaget wurden faan $1.
 Di grünj as ''$2''.
@@ -701,11 +703,11 @@ Di grünj as ''$2''.
 
 Dü könst $1 kontaktiare of uk en [[{{MediaWiki:Grouppage-sysop}}|administraator]] am det tu diskutiarin.
 
-Dü könst ei det E-Mail-funktsjuun 'E-mail tu dideere brüker' brük, so loong dü nian E-Mail-adres uun din [[Special:Preferences|brükerkonto iinstelangen]] uunden heest of wan det E-Mail-funktsjuun för di speret wurden as.
+Dü könst ei det e-mail-funktjuun 'E-mail tu didiar brüker' brük, so loong dü nian e-mail-adres uun din [[Special:Preferences|brükerkonto-iinstelangen]] uunden heest of wan det e-mail-funktjuun för di speret wurden as.
 
-Uugenblakelk as din IP addres $3, an det sper ID as #$5.
-För arke uunfraag wurd aal jo informatsjuunen boowen brükt.",
-'autoblockedtext' => "'''Din IP adres as speret wurden, auer det faan en öödern spereten brüker brükt wurden as.'''
+Uugenblakelk as din IP-addres $3, an det sper-ID as #$5.
+För arke uunfraag wurd aal jo informatjuunen boowen brükt.",
+'autoblockedtext' => "'''Din IP-adres as speret wurden, auer det faan en öödern spereten brüker brükt wurden as.'''
 
 Di grünj as:
 : ''$2''.
@@ -716,10 +718,10 @@ Di grünj as:
 
 Dü könst $1 kontaktiare of uk en [[{{MediaWiki:Grouppage-sysop}}|administraator]] am det tu diskutiarin.
 
-Dü könst ei det E-Mail-funktsjuun 'E-mail tu dideere brüker' brük, so loong dü nian E-Mail-adres uun din [[Special:Preferences|brükerkonto iinstelangen]] uunden heest of wan det E-Mail-funktsjuun för di speret wurden as.
+Dü könst ei det e-mail-funktjuun 'E-mail tu didiar brüker' brük, so loong dü nian e-mail-adres uun din [[Special:Preferences|brükerkonto-iinstelangen]] uunden heest of wan det e-mail-funktjuun för di speret wurden as.
 
-Uugenblakelk as din IP addres $3, an det sper ID as #$5.
-För arke uunfraag wurd aal jo informatsjuunen boowen brükt.",
+Uugenblakelk as din IP-addres $3, an det sper-ID as #$5.
+För arke uunfraag wurd aal jo informatjuunen boowen brükt.",
 'blockednoreason' => 'nään grünj uunden',
 'whitelistedittext' => 'Dü skel di $1, am sidjen tu bewerkin.',
 'confirmedittext' => 'Dü skel iarst din e-mail-adres gudkään, iar dü began könst tu werkin. Maage det üüb det sidj mä din persöönelk [[Special:Preferences|iinstelangen]].',
@@ -973,17 +975,17 @@ Dü könst di ferskeel uunluke. Wan dü muar wed wel, luke iin uun't [{{fullurl:
 'revdelete-confirm' => 'Ferseekre noch ans, dat dü det würelk du wel, dat dü witjst, wat dü dääst, an dat det mä a [[{{MediaWiki:Policy-url}}|bestemangen]] auerian stemet.',
 'revdelete-suppress-text' => "Det skul '''bluas''' onertrakt wurd bi:
 * Persöönelk informatsjuunen, diar näämen wat uungung
-*: ''Adresen, Tilefoonnumern, Ferseekerangsnumern an sowat''",
+*: ''Adresen, tilefoonnumern, ferseekerangsnumern an sowat''",
 'revdelete-legend' => 'Iinstelangen, hüföl tu sen wees skal',
-'revdelete-hide-text' => 'Tekst faan det werjuun fersteeg',
+'revdelete-hide-text' => 'Tekst faan det werjuun',
 'revdelete-hide-image' => 'Fersteeg, wat uun det datei stäänt',
 'revdelete-hide-name' => 'Logbuk-aktjuun fersteeg',
-'revdelete-hide-comment' => 'Tuupfaadet beskriiwang fersteeg',
-'revdelete-hide-user' => 'Brükernööm/IP-adres faan di brüker fersteeg',
+'revdelete-hide-comment' => 'Tuupfaadet beskriiwang',
+'revdelete-hide-user' => 'Brükernööm/IP-adres faan di brüker',
 'revdelete-hide-restricted' => 'Dooten uk för administratooren an öödern fersteeg',
 'revdelete-radio-same' => '(ei feranre)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Naan',
+'revdelete-radio-set' => 'Ferbürgen',
+'revdelete-radio-unset' => 'Tu sen',
 'revdelete-suppress' => "Grünj för't striken uk för administratooren an öödern fersteeg",
 'revdelete-unsuppress' => 'Weder iinsteld werjuunen luasmaage',
 'revdelete-log' => 'Grünj:',
@@ -1031,8 +1033,8 @@ Aachte diarüüb, dat di ferluup faan det sidj uk rocht as.',
 'mergehistory-into' => 'Ööder sidj:',
 'mergehistory-list' => 'Werjuunen, diar tuupfeerd wurd kön.',
 'mergehistory-merge' => 'Jodiar werjuunen faan „[[:$1]]“ kön efter „[[:$2]]“ auerdraanj wurd.
-Kääntiakne det wersjuun, wat üs leetst mä auerdraanj wurd skal.
-A nawigatjuun links saat ales weder turag üüb di ual stant.',
+Kääntiakne det werjuun, wat üs leetst mä auerdraanj wurd skal.
+A nawigatjuun-links saat ales weder turag üüb di ual stant.',
 'mergehistory-go' => 'Wise werjuunen, diar tuupfeerd wurd kön.',
 'mergehistory-submit' => 'Werjuunen tuupfeer',
 'mergehistory-empty' => 'Nian werjuunen kön tuupfeerd wurd.',
@@ -1136,8 +1138,7 @@ Dü könst det uun't [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}
 'preferences' => 'Iinstelangen',
 'mypreferences' => 'Iinstelangen',
 'prefs-edits' => 'Taal faan feranrangen:',
-'prefsnologin' => 'Ei uunmeldet',
-'prefsnologintext' => 'Dü skel <span class="plainlinks">[{{fullurl:{{#special:UserLogin}}|returnto=$1}} uunmeldet]</span> wees, am din iinstelangen tu feranrin.',
+'prefsnologintext2' => 'Wees so gud an $1 , am din brüker-iinstelangen fäästtuleien.',
 'changepassword' => 'Paaswurd feranre',
 'prefs-skin' => 'Skak',
 'skin-preview' => 'Föörskau',
@@ -1408,7 +1409,7 @@ Arken koon det lees.',
 'action-protect' => 'det seekerhaid faan sidjen tu feranrin',
 'action-rollback' => 'feranrangen faan di leetst brüker gau turagtusaaten',
 'action-import' => 'sidjen faan en ööder Wiki tu importiarin',
-'action-importupload' => 'sidjen auer det huuchschüüren faan datein tu importiarin',
+'action-importupload' => 'sidjen auer det huuchschüüren faan en datei tu importiarin',
 'action-patrol' => 'det werk faan ööder brükern üs kontroliaret tu kääntiaknin',
 'action-autopatrol' => 'aanj feranrangen üs kontroliaret tu kääntiaknin',
 'action-unwatchedpages' => 'det list faan sidjen uuntulukin, diar näämen üüb aachtet',
@@ -1435,6 +1436,9 @@ Arken koon det lees.',
 'recentchanges-label-minor' => 'Letj feranrang',
 'recentchanges-label-bot' => 'Feranrang faan en bot',
 'recentchanges-label-unpatrolled' => 'Detdiar feranrang as noch ei efterluket wurden',
+'recentchanges-label-plusminus' => 'Feranert sidjengrate (am soföl bytes)',
+'recentchanges-legend-newpage' => "(luke uk bi't [[Special:NewPages|list mä nei sidjen]])",
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Diar {{PLURAL:$1|stäänt det leetst feranrang|stun a leetst '''$1''' feranrangen}} faan a leetst {{PLURAL:$2|dai|'''$2''' daar}}. Stant: $4, am a klook $5.",
 'rcnotefrom' => "Diar wurd a feranrangen sant '''$2'''uunwiset (ei muar üs '''$1''' feranrangen).",
 'rclistfrom' => 'Bluas feranrangen sant $1 wise.',
@@ -1472,7 +1476,7 @@ Arken koon det lees.',
 
 # Upload
 'upload' => 'Datei huuchschüür',
-'uploadbtn' => 'Datei huuchsjüür',
+'uploadbtn' => 'Datei huuchschüür',
 'reuploaddesc' => "Ufbreeg an turag tu't sidj för't huuchschüüren",
 'upload-tryagain' => 'Feranert dateibeskriiwang ufsjüür',
 'uploadnologin' => 'Ei uunmeldet',
@@ -1512,13 +1516,13 @@ Am en '''bil''' uun en artiikel tu brüken, brük en link faan det furem:
 'badfilename' => 'Det datei hää en neien nööm füngen an het nü „$1“.',
 'filetype-mime-mismatch' => 'Det dateiaanj „.$1“ paaset ei tu di MIME-Typ ($2).',
 'filetype-badmime' => 'Datein faan di MIME-Typ „$1“ mut ei huuchschüürd wurd.',
-'filetype-bad-ie-mime' => 'Detdiar datei koon ei huuchsjüürd wurd, auer di Internet Explorer det för en „$1“ häält, an di slach as ei tuläät, auer hi gefeerelk wees küd.',
+'filetype-bad-ie-mime' => 'Detdiar datei koon ei huuchschüürd wurd, auer di Internet Explorer det för en „$1“ häält, an di slach as ei tuläät, auer hi gefeerelk wees küd.',
 'filetype-unwanted-type' => "'''„.$1“''' as üs dateiformaat ei tuläät. Tuläät {{PLURAL:$3|as detdiar formaat|san jodiar formaaten}}: $2.",
 'filetype-banned-type' => "'''„.$1“''' {{PLURAL:$4|as nään tuläät slach faan datein|san nian tuläät slacher faan datein}}.
 {{PLURAL:$3|En tuläät slach as|Tuläät slacher san}} $2.",
-'filetype-missing' => 'Det datei, wat dü huuchsjüür wel, hää nian aanj (t.b. „.jpg“).',
-'empty-file' => 'Det datei, wat dü huuchsjüürd heest, as leesag.',
-'file-too-large' => 'Det datei, wat dü huuchsjüürd heest, as tu grat.',
+'filetype-missing' => 'Det datei, wat dü huuchschüür wel, hää nian aanj (t.b. „.jpg“).',
+'empty-file' => 'Det datei, wat dü huuchschüürd heest, as leesag.',
+'file-too-large' => 'Det datei, wat dü huuchschüürd heest, as tu grat.',
 'filename-tooshort' => 'Di dateinööm as tu kurt.',
 'filetype-banned' => 'Son slach faan datei as ei tuläät.',
 'verification-error' => 'Det datei hää det seekerhaidspreew ei bestenen.',
@@ -1530,8 +1534,8 @@ Am en '''bil''' uun en artiikel tu brüken, brük en link faan det furem:
 'tmp-write-error' => "Bi't skriiwen faan det tidjwiis datei as wat skiaf gingen.",
 'large-file' => 'Datein skul ei grater wees üs $1, wan mögelk. Detdiar datei as $2 grat.',
 'largefileserver' => 'Detdiar datei as grater, üs di server üüb iinsteld as.',
-'emptyfile' => 'Det datei, wat dü huuchsjüürd heest, as leesag. Ferlicht heest dü di ferskrewen. Luke noch ans, of dü würelk detdiar datei huuchsjüür wel.',
-'windows-nonascii-filename' => 'Detheer Wiki läät nian dateinöömer mä sondertiaken tu.',
+'emptyfile' => 'Det datei, wat dü huuchschüürd heest, as leesag. Ferlicht heest dü di ferskrewen. Luke noch ans, of dü würelk detdiar datei huuchschüür wel.',
+'windows-nonascii-filename' => 'Detheer wiki läät nian dateinöömer mä aparte tiakens tu.',
 'fileexists' => 'En datei mä didiar nööm jaft at al. Luke noch ans efter <strong>[[:$1]]</strong>, wan dü ei gans seeker beest, of dü det anre wel.
 [[$1|thumb]]',
 'filepageexists' => "En beskriiwangssidj för <strong>[[:$1]]</strong> as al diar, oober nian datei. Din beskriiwang woort ei apnimen. Det beskriiwangssidj mut do man efter't huuchschüüren noch ans efterluket wurd.
@@ -1540,26 +1544,26 @@ Am en '''bil''' uun en artiikel tu brüken, brük en link faan det furem:
 * Nööm faan det nei datei: <strong>[[:$1]]</strong>
 * Nööm faan det ual datei: <strong>[[:$2]]</strong>
 Wees so gud an nem en öödern nööm.',
-'fileexists-thumbnail-yes' => "Detdiar datei as was en letjer maaget bil ''(thumbnail)''. [[$1|thumb]]
+'fileexists-thumbnail-yes' => "Detdiar datei as was en sümnaielbil ''(thumbnail)''. [[$1|thumb]]
 Luke di det datei <strong>[[:$1]]</strong> noch ans uun.
-Wan det det originaal bil as, säärst dü nään letjer maaget bil huuchsjüür.",
-'file-thumbnail-no' => "Di dateinööm begant mä <strong>$1</strong>. Det as was en letjer maaget bil ''(thumbnail)''.
+Wan det det originaal bil as, säärst dü nian sümnaielbil huuchschüür.",
+'file-thumbnail-no' => "Di dateinööm begant mä <strong>$1</strong>. Det as was en sümnaielbil ''(thumbnail)''.
 Luke noch ans efter, of dü det bil uun fol grate diar heest, an do schüür det huuch.",
 'fileexists-forbidden' => 'En datei mä didiar nööm jaft at al an koon ei auerskrewen wurd.
 Gung noch ans turag an schüür det datei mä en öödern nööm huuch.
 [[File:$1|thumb|center|$1]]',
-'fileexists-shared-forbidden' => "En datei mä didiar nööm stäänt al uun't gemiansoom archiif. Wan dü det bil likes huuchsjüür wel, gung turag nem en öödern nööm.
+'fileexists-shared-forbidden' => "En datei mä didiar nööm stäänt al uun't gemiansoom archiif. Wan dü det bil likes huuchschüür wel, gung turag an nem en öödern nööm.
 [[File:$1|thumb|center|$1]]",
 'file-exists-duplicate' => 'Detdiar datei as en duplikaat faan {{PLURAL:$1|detdiar datei|$1 datein}}:',
 'file-deleted-duplicate' => "En duplikaat faan detdiar datei ([[:$1]]) as al ans stregen wurden. Luke iin uun logbuk för't striken, iar dü det noch ans huuchsjüürst.",
 'uploadwarning' => 'Wäärnang',
-'uploadwarning-text' => 'Feranre det datei-beskriiwang an fersjük det noch ans nei.',
+'uploadwarning-text' => 'Feranre det datei-beskriiwang an ferschük det noch ans nei.',
 'savefile' => 'Datei seekre',
 'uploadedimage' => 'hää "[[$1]]" huuchschüürd',
-'overwroteimage' => 'hää en nei werjuun faan „[[$1]]“ huuchsjüürd',
+'overwroteimage' => 'hää en nei werjuun faan „[[$1]]“ huuchschüürd',
 'uploaddisabled' => 'Huuchschüüren as ei aktiwiaret',
 'copyuploaddisabled' => 'Huuchschüüren faan URLs as ei aktiwiaret.',
-'uploadfromurl-queued' => 'Din huuchsjüürd datei teewt.',
+'uploadfromurl-queued' => 'Din huuchschüürd datei teewt.',
 'uploaddisabledtext' => 'Det huuchschüüren faan datein as ei aktiwiaret.',
 'php-uploaddisabledtext' => 'Det huuchschüüren faan datein as uun PHP ei aktiwiaret.
 Luke di det iinstelang faan <code>file_uploads</code> uun.',
@@ -1575,7 +1579,7 @@ Java-datein kön ei tuläät wurd, auer jo det seekerhaid uun fraag stel küd.',
 'upload-description' => 'Dateibeskriiwang',
 'upload-options' => "Iinstelangen för't huuchschüüren",
 'watchthisupload' => 'Luke efter detdiar datei',
-'filewasdeleted' => 'En datei mä didiar nööm as al ans huuchsjüürd an leederhen weder stregen wurden. Luke iarst ans iin uun $1, iar dü det datei würelk seekerst.',
+'filewasdeleted' => 'En datei mä didiar nööm as al ans huuchschüürd an leederhen weder stregen wurden. Luke iarst ans iin uun $1, iar dü det datei würelk seekerst.',
 'filename-bad-prefix' => "Di dateinööm begant mä '''„$1“'''. Sok nöömer kem miast faan digitaalkameras an sai ei föl ütj.
 Nem en beedern nööm för det datei.",
 'upload-success-subj' => 'Det huuchschüüren hää loket.',
@@ -1689,7 +1693,7 @@ För a seekerhaid as img_auth.php ei aktiwiaret.',
 'upload-curl-error6' => 'URL küd ei fünjen wurd',
 'upload-curl-error6-text' => 'Det URL küd ei fünjen wurd. Luke di det URL noch ans uun, an of det sidj uk würelk diar as.',
 'upload-curl-error28' => 'Det huuchschüüren hää tu loong düüret (time-out).',
-'upload-curl-error28-text' => 'Det sidj hää tu loong ei swaaret (time-out). Luke noch ans efter, of det sidj uk würelk diar as. Fersjük det beeder leeder noch ans weder.',
+'upload-curl-error28-text' => 'Det sidj hää tu loong ei swaaret (time-out). Luke noch ans efter, of det sidj uk würelk diar as. Ferschük det beeder leeder noch ans weder.',
 
 'license' => 'Lisens:',
 'license-header' => 'Lisens',
@@ -1712,6 +1716,7 @@ För a seekerhaid as img_auth.php ei aktiwiaret.',
 'listfiles_count' => 'Werjuunen',
 'listfiles-show-all' => 'Ual bilwerjuunen mä iinslütj',
 'listfiles-latestversion' => 'Aktuel werjuun',
+'listfiles-latestversion-yes' => 'Ja',
 'listfiles-latestversion-no' => 'Naan',
 
 # File description page
@@ -1750,7 +1755,7 @@ Ferlicht wel dü det [$2 beskriiwangssidj] feranre.',
 'sharedupload-desc-create' => 'Detdiar datei as faan $1 an koon faan ööder projekten brükt wurd.
 Ferlicht wel dü det [$2 beskriiwangssidj] feranre.',
 'filepage-nofile' => 'En datei mä didiar nööm jaft at ei.',
-'filepage-nofile-link' => 'En datei mä didiar nööm jaft at ei, man dü könst det [$1 huuchsjüür].',
+'filepage-nofile-link' => 'En datei mä didiar nööm jaft at ei, man dü könst det [$1 huuchschüür].',
 'uploadnewversion-linktext' => 'En nei werjuun faan detdiar datei huuchschüür',
 'shared-repo-from' => 'foon $1',
 'shared-repo' => 'en gemiansoom archiif',
@@ -1920,10 +1925,11 @@ Uun arke rä stun ferwisangen tu't iarst an ööder widjerfeerang an uk tu det s
 'listusers' => 'Brükerfertiaknis',
 'listusers-editsonly' => 'Wise bluas aktiif brükern',
 'listusers-creationsort' => 'Sortiare efter dootem',
+'listusers-desc' => 'Sortiare amdeel',
 'usereditcount' => '{{PLURAL:$1|feranrang|$1 feranrangen}}',
 'usercreated' => '{{GENDER:$3|Maaget}} di $1 am a klook $2',
 'newpages' => 'Nei sidjen',
-'newpages-username' => 'Brükernoome:',
+'newpages-username' => 'Brükernööm:',
 'ancientpages' => 'Al loong ei muar bewerket sidjen',
 'move' => 'Fersküüw',
 'movethispage' => 'Detdiar sidj fersküüw',
@@ -2052,7 +2058,7 @@ Din aanj e-mail adres faan din [[Special:Preferences|iinstelangen]] woort uunwis
 'usermaildisabledtext' => 'Dü könst nian e-mail tu ööder brükern schüür.',
 'noemailtitle' => 'Nian e-mail adres',
 'noemailtext' => 'Didiar brüker hää nian gudkäänd e-mail adres uunden.',
-'nowikiemailtitle' => 'E-mail koon ei sjüürd wurd',
+'nowikiemailtitle' => 'E-mail koon ei wechschüürd wurd',
 'nowikiemailtext' => 'Didiar brüker maad nian e-mails faan ööder brükern fu.',
 'emailnotarget' => 'Didiar brükernööm as ei bekäänd of ei gudkäänd, am ham en e-mail tu schüüren',
 'emailtarget' => 'Brükernööm faan di ööder brüker iindu',
@@ -2135,7 +2141,7 @@ Kontakt tu di bewerker:
 E-mail: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
-Di wurd iarst ans nian e-mails muar tu detdiar sidj schüürd, bit dü det sidj weder beschükst. Üüb din list faan sidjen, diar dü uun\'t uug behual wel, könst dü a noorachtenkääntiaken weder turagsaat.
+Di wurd iarst ans nian e-mails muar tu detdiar sidj schüürd, bit dü det sidj weder uunmeldet beschükst. Üüb din list faan sidjen, diar dü uun\'t uug behual wel, könst dü a noorachtenkääntiaken weder turagsaat.
 
 Dan frinjelk {{SITENAME}}-noorachten siinst
 
@@ -2172,9 +2178,11 @@ Halep an muar diartu: {{canonicalurl:{{MediaWiki:Helppage}}}}',
 'deleteotherreason' => 'Ööder/noch en grünj:',
 'deletereasonotherlist' => 'Ööder grünj',
 'deletereason-dropdown' => "*Algemian grünjer för't striken
-** Di skriiwer wul det so
+** Spam / dom tjüch
+** Wandaalen onerwais
 ** Copyright as ei beaachtet
-** Wandaalen onerwais",
+** Di skriiwer wul det so
+** Widjerfeerang uunstaken",
 'delete-edit-reasonlist' => "Grünjer för't striken bewerke",
 'delete-toobig' => 'Detdiar sidj hää muar üs $1 {{PLURAL:$1|werjuun|werjuunen}} . Sok sidjen kön ei so gau stregen wurd, ööders san a servers plaat.',
 'delete-warning-toobig' => "Detdiar sidj hää muar üs $1 {{PLURAL:$1|werjuun|werjuunen}} . Det striken koon komer maage bi't dootenbeenk.",
@@ -2192,7 +2200,7 @@ Halep an muar diartu: {{canonicalurl:{{MediaWiki:Helppage}}}}',
 Det leetst feranrang as faan [[User:$3|$3]] ([[User talk:$3|Diskusjuun]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Tuupfaadet feranrang: ''„$1“''.",
 'revertpage' => 'Feranrangen faan [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusjuun]]) san üüb di leetst stant faan [[User:$1|$1]] turagsaat wurden.',
-'revertpage-nouser' => 'Feranrangen faan en ferbürgenen brüker turagsaat an det leetst werjuun faan [[User:$1|$1]] weder iinsteld.',
+'revertpage-nouser' => 'Feranrangen faan en ferbürgenen brüker turagsaat an det leetst werjuun faan {{GENDER:$1|[[User:$1|$1]]}} weder iinsteld.',
 'rollback-success' => 'Feranrangen faan $1 turagsaat an det leetst werjuun faan $2 weder iinsteld.',
 
 # Edit tokens
@@ -2262,7 +2270,7 @@ Dü könst det seekerhaid feranre, det feranert oober ei det seekerhaid faan jo
 'restriction-edit' => 'Bewerke',
 'restriction-move' => 'Fersküüw',
 'restriction-create' => 'Maage',
-'restriction-upload' => 'Huuchsjüür',
+'restriction-upload' => 'Huuchschüür',
 
 # Restriction levels
 'restriction-level-sysop' => 'seekert (bluas för administratooren)',
@@ -2332,7 +2340,7 @@ $1",
 'contributions' => '{{GENDER:$1|Brüker}} bidracher',
 'contributions-title' => 'Brükerbidracher för "$1"',
 'mycontris' => 'Bidracher',
-'contribsub2' => 'För $1 ($2)',
+'contribsub2' => 'För {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Diar wiar nian paasin brükerbidracher',
 'uctop' => '(aktuel)',
 'month' => 'faan muun (of iarer):',
@@ -2633,7 +2641,7 @@ Di eksport as uk mä [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] mögelk, tun
 'allmessagesdefault' => 'Standard tekst',
 'allmessagescurrent' => 'Aktuel tekst',
 'allmessagestext' => "Det as en list mä MediaWiki-süsteemteksten.
-Wees so gud an beschük a sidjen [//www.mediawiki.org/wiki/Localisation MediaWiki-auersaatang] an [//translatewiki.net translatewiki.net], wan dü bi't auersaaten mähalep meest.",
+Wees so gud an beschük a sidjen [https://www.mediawiki.org/wiki/Localisation MediaWiki-auersaatang] an [//translatewiki.net translatewiki.net], wan dü bi't auersaaten mähalep meest.",
 'allmessagesnotsupportedDB' => 'Detdiar spezial-sidj koon ei brükt wurd, auer <tt>$wgUseDatabaseMessages</tt> ei aktiif as.',
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter för di uunpaaset stant:',
@@ -2794,6 +2802,7 @@ Dü könst di kweltekst uunluke.',
 'tooltip-undo' => 'Saat bluas det leetst feranrang turag an wiset det resultoot uun en föörskau uun. Uun det tuupfaadet beskriiwang skul en grünj för det turagsaaten uunden wurd.',
 'tooltip-preferences-save' => 'Iinstelangen seekre',
 'tooltip-summary' => 'Faade det kurt tuup',
+'interlanguage-link-title' => '$1 - $2',
 
 # Metadata
 'notacceptable' => 'Di Wiki-server koon a dooten ei för dan aperoot apwerke.',
@@ -2818,6 +2827,8 @@ Dü könst di kweltekst uunluke.',
 'spam_reverting' => 'Leetst werjuun saner ferwisangen tu $1 weder iinsteld.',
 'spam_blanking' => 'Aal a werjuunen mä en ferwisang tu $1 san apklaaret wurden.',
 'spam_deleting' => 'Aal a werjuunen mä en ferwisung tu $1 san stregen wurden.',
+'simpleantispam-label' => "Anti-spam preew.
+Heer '''NIKS''' iindreeg!",
 
 # Info page
 'pageinfo-title' => 'Informatjuun tu „$1“',
@@ -2831,6 +2842,7 @@ Dü könst di kweltekst uunluke.',
 'pageinfo-length' => 'Sidjenlengde (uun bytes)',
 'pageinfo-article-id' => 'Sidjenkäännumer (ID)',
 'pageinfo-language' => 'Sidjenspriak',
+'pageinfo-content-model' => 'Muude för sidjenteksten',
 'pageinfo-robot-policy' => 'Faan bots indisiaret',
 'pageinfo-robot-index' => 'Tuläät',
 'pageinfo-robot-noindex' => 'Ei tuläät',
@@ -2910,7 +2922,7 @@ $1",
 'svg-long-desc' => 'SVG-datei, grate: $1 × $2 pixel, dateigrate: $3',
 'svg-long-desc-animated' => 'Animiaret SVG-datei, grate $1 × $2 pixel, dateigrate: $3',
 'svg-long-error' => 'Ferkiard SVG-datei: $1',
-'show-big-image' => 'Huuger apliasang',
+'show-big-image' => 'Originaal datei',
 'show-big-image-preview' => 'Grate faan detdiar föörskaubil: $1.',
 'show-big-image-other' => 'Ööder {{PLURAL:$2|apliasang|apliasangen}}: $1.',
 'show-big-image-size' => '$1 × $2 pixel',
@@ -2925,7 +2937,7 @@ $1",
 # Special:NewFiles
 'newimages' => 'Nei datein',
 'imagelisttext' => "Diar as en list faan '''$1''' {{PLURAL:$1|datei|datein}}, sortiaret $2.",
-'newimages-summary' => 'Detdiar spezial-sidj wiset a tuleetst huuchsjüürd datein uun.',
+'newimages-summary' => 'Detdiar spezial-sidj wiset a tuleetst huuchschüürd datein uun.',
 'newimages-legend' => 'Filter',
 'newimages-label' => 'Dateinööm (of en dial diarfaan):',
 'showhidebots' => '(Bots $1)',
@@ -3376,7 +3388,7 @@ Ferwisangen uun det salew rä wurd üs ütjnoomen uunsen, huar det datei dach uu
 
 # External editor support
 'edit-externally' => 'Detdiar datei mä en ekstern program bewerke',
-'edit-externally-help' => "(Luk efter uun't [//www.mediawiki.org/wiki/Manual:External_editors hoonbuk] am muar diartu)",
+'edit-externally-help' => "(Luk efter uun't [https://www.mediawiki.org/wiki/Manual:External_editors hoonbuk] am muar diartu)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'aaltumaal',
@@ -3468,6 +3480,9 @@ Ferseekre, dat dü det sidj würelk nei maage wel.",
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => "Wel dü detdiar sidj ei muar uun't uug behual?",
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1“',
+
 # Multipage image navigation
 'imgmultipageprev' => '← leetst sidj (turag)',
 'imgmultipagenext' => 'naist sidj →',
@@ -3552,7 +3567,7 @@ Dü könst uk det [[Special:EditWatchlist|normool sidj]] tu bewerkin nem.",
 'version-hook-subscribedby' => 'Aprepen faan',
 'version-version' => '(Werjuun $1)',
 'version-license' => 'Lisens',
-'version-poweredby-credits' => "Detheer wääbsteed werket mä '''[//www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Detheer wääbsteed werket mä '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'öödern',
 'version-poweredby-translators' => 'Auersaatern faan translatewiki.net',
 'version-credits-summary' => 'Wi besoonke üs bi jodiar persuunen för hör bidracher tu [[Special:Version|MediaWiki]].',
@@ -3571,7 +3586,8 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 # Special:Redirect
 'redirect' => 'Widjerfeerang üüb en brükersidj, sidjenwerjuun of datei.',
 'redirect-legend' => 'Widjerfeerang üüb en sidjenwerjuun of datei.',
-'redirect-summary' => 'Det spezial-sidj feert widjer üüb en brükersidj, sidjenwerjuun of datei.',
+'redirect-summary' => 'Detdiar spezial-sidj feert widjer üüb en brükersidj, sidjenwerjuun of datei.
+An det woort so brükt: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], of [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Widjer',
 'redirect-lookup' => 'Schük:',
 'redirect-value' => 'Käänang of dateinööm:',
@@ -3593,10 +3609,9 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 
 # Special:SpecialPages
 'specialpages' => 'Spezial-sidjen',
-'specialpages-note' => '----
-* Normool spezial-sidjen
-* <span class="mw-specialpagerestricted">Spezial-sidjen mä tugripsrochten</span>
-* <span class="mw-specialpagecached">Spezial-sidjen uun a cache (As ferlicht ei muar aktuel.)</span>',
+'specialpages-note-top' => 'Legend',
+'specialpages-note' => '* Normool spezial-sidjen
+* <span class="mw-specialpagerestricted">Spezial-sidjen mä tugripsrochten</span>',
 'specialpages-group-maintenance' => 'Werksteedsidjen',
 'specialpages-group-other' => 'Ööder spezial-sidjen',
 'specialpages-group-login' => 'Melde di uun of skriiw di iin',
@@ -3634,7 +3649,10 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'tags-tag' => 'Kääntiaken-nööm',
 'tags-display-header' => 'Nööm üüb feranrangslisten',
 'tags-description-header' => 'Widjloftag beskriiwang',
+'tags-active-header' => 'Aktiif?',
 'tags-hitcount-header' => 'Kääntiakent feranrangen',
+'tags-active-yes' => 'Ja',
+'tags-active-no' => 'Naan',
 'tags-edit' => 'bewerke',
 'tags-hitcount' => '$1 {{PLURAL:$1|feranrang|feranrangen}}',
 
@@ -3693,10 +3711,10 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'logentry-suppress-revision-legacy' => '$1 {{GENDER:$2}} hää stalswigin det uunlukin feranert faan werjuunen faan det sidj $3',
 'revdelete-content-hid' => 'Ferbürgen',
 'revdelete-summary-hid' => 'Ferbürgen tuupfaadang',
-'revdelete-uname-hid' => 'brükernoome ferstäägen',
+'revdelete-uname-hid' => 'brükernööm ferbürgen',
 'revdelete-content-unhid' => 'Ei muar ferberag',
 'revdelete-summary-unhid' => 'Tuupfaadang ei muar ferberag',
-'revdelete-uname-unhid' => 'brükernoome frijääwen',
+'revdelete-uname-unhid' => 'brükernööm weder tu sen',
 'revdelete-restricted' => 'mögelkhaiden för administratooren wechnimen',
 'revdelete-unrestricted' => 'mögelkhaiden för administratooren ütjwidjet',
 'logentry-move-move' => '$1 {{GENDER:$2}} hää det sidj $3 efter $4 fersköwen.',
@@ -3743,12 +3761,12 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'api-error-duplicate-archive' => 'Diar wiar al {{PLURAL:$1|[$2 ööder datei]|[$2 ööder datein]}} mä detsalew banen. {{PLURAL:$1|Hat as |Jo san}} oober stregen wurden.',
 'api-error-duplicate-archive-popup-title' => 'Dobelt {{PLURAL:$1|datei, diar al stregen wurden as|datein, diar al stregen wurden san}}.',
 'api-error-duplicate-popup-title' => 'Dobelt {{PLURAL:$1|datei|datein}}',
-'api-error-empty-file' => 'Det datei, wat dü huuchsjüürd heest, as leesag.',
+'api-error-empty-file' => 'Det datei, wat dü huuchschüürd heest, as leesag.',
 'api-error-emptypage' => 'Dü mutst nian leesag sidjen nei iinstel.',
 'api-error-fetchfileerror' => "Intern feeler: Bi't ufrepen faan det datei as wat skiaf gingen.",
 'api-error-fileexists-forbidden' => 'En datei mä di nööm „$1“ as al diar. Hat koon ei auerskrewen wurd.',
 'api-error-fileexists-shared-forbidden' => "En date mä di nööm „$1“ as al uun't gemiansoom archiif an koon ei auerskrewen wurd.",
-'api-error-file-too-large' => 'Det datei, wat dü huuchsjüürd heest, as tu grat.',
+'api-error-file-too-large' => 'Det datei, wat dü huuchschüürd heest, as tu grat.',
 'api-error-filename-tooshort' => 'Di dateinööm as tu kurt.',
 'api-error-filetype-banned' => 'Son slach faan datei as ei tuläät.',
 'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|as nään tuläät slach faan datein|san nian tuläät slacher faan datein}}.
@@ -3801,10 +3819,24 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'limitreport-ppvisitednodes' => 'Taal faan ferbinjangsknooter för di föörproseser',
 'limitreport-ppgeneratednodes' => 'Faan di föörproseser bereegent ferbinjangsknooter',
 'limitreport-postexpandincludesize' => "Grate faan iinbinjangen efter't ütjwidjin",
-'limitreport-postexpandincludesize-value' => '$1/$2 bytes',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|byte|bytes}}',
 'limitreport-templateargumentsize' => "Grate faan't föörlaagenargument",
-'limitreport-templateargumentsize-value' => '$1/$2 bytes',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|byte|bytes}}',
 'limitreport-expansiondepth' => 'Maksimaal ütjwidjangsjipde',
 'limitreport-expensivefunctioncount' => 'Taal faan apwendag parser-funktjuunen',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Föörlaagen ütjwidje',
+'expand_templates_intro' => 'Üüb detdiar spezial-sidj wurd a föörlaagen faan di tekst rekursiif ütjwidjet.
+Uk parser-funktjuunen liküs <code><nowiki>{{</nowiki>#language:…}}</code> an wariaabeln liküs <code><nowiki>{{</nowiki>CURRENTDAY}}</code> wurd ferwerket - det ment ales, wat tesken dobelt sleufen stäänt.',
+'expand_templates_title' => 'Kontekst-tiitel, för {{FULLPAGENAME}} asw.:',
+'expand_templates_input' => 'Skriiwfial:',
+'expand_templates_output' => 'Resultaat',
+'expand_templates_xml_output' => 'XML-resultaat',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Komentaaren wechnem',
+'expand_templates_remove_nowiki' => "<nowiki>-tags uun't resultaat ei uunwise",
+'expand_templates_generate_xml' => 'XML-parser-buum uunwise',
+'expand_templates_preview' => 'Föörskau',
+
 );
index e5c1211..2fab5cf 100644 (file)
@@ -51,7 +51,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Contribûts', 'ContribûtsUtent' ),
        'CreateAccount'             => array( 'CreeIdentitât' ),
        'Deadendpages'              => array( 'PagjinisCenceJessude' ),
-       'Disambiguations'           => array( 'Omonimiis' ),
        'DoubleRedirects'           => array( 'ReIndreçamentsDoplis' ),
        'Emailuser'                 => array( 'MandeEmail' ),
        'Export'                    => array( 'Espuarte' ),
@@ -98,8 +97,8 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'ModeiNoDoprâts' ),
        'Unwatchedpages'            => array( 'PagjinisNoTignudisDiVoli' ),
        'Upload'                    => array( 'Cjame' ),
-       'Userlogin'                 => array( 'Jentre', 'Login' ),
-       'Userlogout'                => array( 'Jes', 'Logout' ),
+       'Userlogin'                 => array( 'Jentre' ),
+       'Userlogout'                => array( 'Jes' ),
        'Userrights'                => array( 'PermèsUtents' ),
        'Wantedcategories'          => array( 'CategoriisDesideradis' ),
        'Watchlist'                 => array( 'TignudisDiVoli' ),
@@ -340,8 +339,6 @@ $messages = array(
 'ok' => 'Va ben',
 'retrievedfrom' => 'Cjapât fûr di $1',
 'youhavenewmessages' => 'Tu âs $1 ($2).',
-'newmessageslink' => 'gnûfs messaçs',
-'newmessagesdifflink' => 'difarencis cu la penultime revision',
 'youhavenewmessagesmulti' => 'Tu âs gnûfs messaçs su $1',
 'editsection' => 'cambie',
 'editold' => 'cambie',
@@ -705,7 +702,6 @@ Leiende: (cur) = difarencis cun la version atuâl, (prec) = difarencis cun la ve
 'preferences' => 'Preferencis',
 'mypreferences' => 'Preferencis',
 'prefs-edits' => 'Numar di cambiaments fats:',
-'prefsnologin' => 'No tu sês jentrât',
 'changepassword' => 'Gambie peraule clâf',
 'prefs-skin' => 'Mascare',
 'skin-preview' => 'Anteprime',
@@ -1358,7 +1354,7 @@ Sielç par plasê un altri non.',
 'allmessagesdefault' => 'Test predeterminât',
 'allmessagescurrent' => 'Test curint',
 'allmessagestext' => 'Cheste e je une liste dai messaçs di sisteme disponibii tal non dal spazi MediaWiki.
-Par plasê va su [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se tu vuelis contribuî ae traduzion gjeneriche di MediaWiki.',
+Par plasê va su [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se tu vuelis contribuî ae traduzion gjeneriche di MediaWiki.',
 'allmessages-filter-all' => 'Ducj',
 'allmessages-language' => 'Lenghe:',
 'allmessages-filter-submit' => 'Va',
@@ -1543,7 +1539,7 @@ Se il file al è stât cambiât rispiet al so stât origjinâl, cualchi informaz
 
 # External editor support
 'edit-externally' => 'Modifiche chest file cuntune aplicazion esterne',
-'edit-externally-help' => '(Cjale lis [//www.mediawiki.org/wiki/Manual:External_editors istruzions] par vê altris informazions)',
+'edit-externally-help' => '(Cjale lis [https://www.mediawiki.org/wiki/Manual:External_editors istruzions] par vê altris informazions)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'dutis',
@@ -1625,8 +1621,7 @@ Se il file al è stât cambiât rispiet al so stât origjinâl, cualchi informaz
 
 # Special:SpecialPages
 'specialpages' => 'Pagjinis speciâls',
-'specialpages-note' => '----
-* Pagjinis speciâls no riservadis.
+'specialpages-note' => '* Pagjinis speciâls no riservadis.
 * <strong class="mw-specialpagerestricted">Pagjinis speciâls a ciertis categoriis di utents.</strong>',
 'specialpages-group-maintenance' => 'Rapuarts di manutenzion',
 'specialpages-group-other' => 'Altris pagjinis speciâls',
@@ -1677,4 +1672,11 @@ Se il file al è stât cambiât rispiet al so stât origjinâl, cualchi informaz
 # API errors
 'api-error-unclassified' => 'Al è capitât un erôr no cognossût',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espant i modei',
+'expand_templates_output' => 'Risultât',
+'expand_templates_ok' => 'Va ben',
+'expand_templates_remove_comments' => 'Gjave i coments',
+'expand_templates_preview' => 'Anteprime',
+
 );
index db3b20d..c3ddfec 100644 (file)
@@ -12,6 +12,7 @@
  * @author Purodha
  * @author Pyt
  * @author SK-luuut
+ * @author Shirayuki
  * @author Snakesteuben
  * @author Urhixidur
  * @author לערי ריינהארט
@@ -74,7 +75,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Meidogger-bydragen', 'Meidogger bydragen', 'Bydragen', 'Brûker bydragen' ),
        'CreateAccount'             => array( 'Nije ynstellings oanmeitsje', 'Nijeynstellingsoanmeitsje' ),
        'Deadendpages'              => array( 'Siden sûnder keppelings', 'Siden sûnder ferwizings', 'Siden sûnder links' ),
-       'Disambiguations'           => array( 'Betsjuttingssiden', 'Trochferwizings' ),
        'DoubleRedirects'           => array( 'Dûbele trochferwizings', 'Dûbeletrochferwizings' ),
        'Emailuser'                 => array( 'Skriuw meidogger', 'Skriuw dizze brûker', 'Skriuw dizze meidogger' ),
        'Export'                    => array( 'Eksportearje' ),
@@ -386,8 +386,6 @@ $1",
 'ok' => 'Goed',
 'retrievedfrom' => 'Untfongen fan "$1"',
 'youhavenewmessages' => 'Jo hawwe $1 ($2).',
-'newmessageslink' => 'nije berjochten',
-'newmessagesdifflink' => 'ferskil mei foarlêste ferzje',
 'youhavenewmessagesmulti' => 'Jo hawwe nije berjochten op $1',
 'editsection' => 'bewurkje',
 'editold' => 'bewurkje',
@@ -949,8 +947,6 @@ Jo kinne ek in nammerûmte as foarheaksel brûke.",
 'preferences' => 'Ynstellings',
 'mypreferences' => 'Myn foarkarynstellings',
 'prefs-edits' => 'Tal bewurkings:',
-'prefsnologin' => 'Net oanmeld',
-'prefsnologintext' => 'Jo moatte <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} oanmeld]</span> wêze om jo foarkar-ynstellings te feroarje te kinnen.',
 'changepassword' => 'Wachtwurd feroarje',
 'prefs-skin' => 'Side-oansjen',
 'skin-preview' => 'Proefbyld',
@@ -1182,6 +1178,7 @@ Jo kinne ek oaren de mûglikheid jaan kontakt mei jo op te nimmen troch in ferwi
 'recentchanges-label-minor' => 'Dit is in tekstwiziging',
 'recentchanges-label-bot' => 'Dizze wiziging is troch in robot makke',
 'recentchanges-label-unpatrolled' => 'Dizze wiziging is noch net neisjûn',
+'recentchanges-legend-newpage' => '$1 - nije side',
 'rcnote' => "Dit {{PLURAL:$1|is de lêste feroaring|binne de lêste '''$1''' feroarings}} yn de lêste {{PLURAL:$2|dei|'''$2''' dagen}}, fan $4 $5.",
 'rcnotefrom' => 'Dit binne de feroarings sûnt <b>$2</b> (maksimaal <b>$1</b>).',
 'rclistfrom' => 'Jou nije feroarings, begjinnende mei $1',
@@ -1987,7 +1984,7 @@ De doelside "[[:$1]]" is der al. Moat dy wiske wurde om plak te meitsjen foar it
 'allmessagesdefault' => 'Standerttekst',
 'allmessagescurrent' => 'Tekst yn de nijste ferzje',
 'allmessagestext' => 'Dit is in list fan alle systeemberjochten beskikber yn de MediaWiki-nammeromte.
-Sjoch: [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net].',
+Sjoch: [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net].',
 
 # Thumbnails
 'thumbnail-more' => 'Fergrutsje',
@@ -2193,7 +2190,7 @@ Alle folgjende links dy't op deselde rigel steane, wurde behannele as útsûnder
 
 # External editor support
 'edit-externally' => 'Wizigje dizze triem mei in ekstern programma',
-'edit-externally-help' => 'Sjoch de [//www.mediawiki.org/wiki/Manual:External_editors ynstel-hantlieding] foar mear ynformaasje.',
+'edit-externally-help' => 'Sjoch de [https://www.mediawiki.org/wiki/Manual:External_editors ynstel-hantlieding] foar mear ynformaasje.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alles',
@@ -2290,8 +2287,7 @@ Wolle jo de side wier op 'e nij skriuwe?",
 
 # Special:SpecialPages
 'specialpages' => 'Bysûndere siden',
-'specialpages-note' => '----
-* Normale bysûndere siden.
+'specialpages-note' => '* Normale bysûndere siden.
 * <strong class="mw-specialpagerestricted">Beheinde bysûndere siden.</strong>',
 'specialpages-group-maintenance' => 'Underhâld siden',
 'specialpages-group-other' => 'Oare bysûndere siden',
index d7b37f5..a72fa86 100644 (file)
@@ -218,8 +218,6 @@ $messages = array(
 'listingcontinuesabbrev' => 'ar lean.',
 'index-category' => 'Leathanaigh innéacsaithe',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Maidir leis',
 'article' => 'Leathanach ábhair',
 'newwindow' => '(a osclófar i bhfuinneog nua)',
@@ -346,8 +344,6 @@ $messages = array(
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Aisghabháil ó "$1"',
 'youhavenewmessages' => 'Tá $1 agat ($2).',
-'newmessageslink' => 'teachtaireachtaí nua',
-'newmessagesdifflink' => 'difear ón leasú leathdhéanach',
 'youhavenewmessagesmulti' => 'Tá teachtaireachtaí nua agat ar $1',
 'editsection' => 'athraigh',
 'editold' => 'athraigh',
@@ -823,8 +819,6 @@ Bain triail as ''all:'' a chur roimh d'iarratas chun an t-inneachar ar fad (leat
 # Preferences page
 'preferences' => 'Sainroghanna',
 'mypreferences' => 'Sainroghanna',
-'prefsnologin' => 'Níl tú logáilte isteach',
-'prefsnologintext' => 'Ní mór duit <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logáil isteach]</span> chun do chuid sainroghanna phearsanta a shocrú.',
 'changepassword' => "Athraigh d'fhocal faire",
 'prefs-skin' => 'Craiceann',
 'skin-preview' => 'Réamhamharc',
@@ -962,6 +956,7 @@ do chuid dreachtaí a chur i leith tusa.',
 'recentchanges-feed-description' => 'Rianaigh na n-athruite vicí is déanaí sa fotha seo.',
 'recentchanges-label-minor' => 'Mionathrú é seo',
 'recentchanges-label-bot' => 'Chomhlíon róbó an t-athrú seo',
+'recentchanges-legend-newpage' => '$1 - leathanach nua',
 'rcnote' => "Is {{PLURAL:$1|é seo a leanas <strong>an t-athrú amháin</strong>|iad seo a leanas na <strong>$1</strong> athruithe is déanaí}} {{PLURAL:$2|ar feadh an lae dheireanaigh|ar feadh na '''$2''' lá deireanacha}}, as $5, $4.",
 'rcnotefrom' => 'Is iad seo a leanas na hathruithe ó <b>$2</b> (go dti <b>$1</b> taispeánaithe).',
 'rclistfrom' => 'Taispeáin athruithe nua ó $1 anuas.',
@@ -1467,8 +1462,8 @@ Is an téacs as na leagan scriosta seo ar fáil do riarthóirí amháin.',
 'sp-contributions-submit' => 'Cuardaigh',
 
 # What links here
-'whatlinkshere' => 'Naisc go dtí an lch seo',
-'whatlinkshere-title' => 'Naisc chuig $1',
+'whatlinkshere' => 'Naisc leis an lch seo',
+'whatlinkshere-title' => 'Naisc le $1',
 'whatlinkshere-page' => 'Leathanach:',
 'linkshere' => "Tá nasc chuig '''[[:$1]]''' ar na leathanaigh seo a leanas:",
 'nolinkshere' => "Níl leathanach ar bith ann a bhfuil nasc chuig '''[[:$1]]''' air.",
@@ -1641,7 +1636,7 @@ Sa dara cás, is féidir leat nasc a úsáid, mar shampla [[{{#Special:Export}}/
 'allmessagesdefault' => 'Téacs réamhshocraithe',
 'allmessagescurrent' => 'Téacs reatha',
 'allmessagestext' => 'Is liosta é seo de theachtaireachtaí córais atá le fáil san ainmspás MediaWiki.
-Tabhair cuairt ar [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] agus [//translatewiki.net translatewiki.net] le do thoil más mian leat cur leis an logánú ginearálta MediaWiki.',
+Tabhair cuairt ar [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] agus [//translatewiki.net translatewiki.net] le do thoil más mian leat cur leis an logánú ginearálta MediaWiki.',
 'allmessagesnotsupportedDB' => "Ní féidir an leathanach seo a úsáid dá bharr gur díchumasaíodh '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-all' => 'Uile',
 'allmessages-language' => 'Teanga:',
@@ -1761,6 +1756,9 @@ iarradh sábháil. Is dócha gur nasc chuig suíomh seachtrach ba chúis leis.',
 'spamprotectionmatch' => 'Truicear ár scagaire dramhála ag an téacs seo a leanas: $1',
 'spambot_username' => 'MediaWiki turscar glanadh',
 
+# Info page
+'pageinfo-toolboxlink' => 'Faoin leathanach seo',
+
 # Skin names
 'skinname-cologneblue' => 'Gorm Köln',
 'skinname-monobook' => 'MonoBook',
@@ -2089,7 +2087,7 @@ cúlra i bhfócas)',
 
 # External editor support
 'edit-externally' => 'Athraigh an comhad seo le feidhmchlár seachtrach',
-'edit-externally-help' => '(Féach ar na [//www.mediawiki.org/wiki/Manual:External_editors treoracha cumraíochta] as Béarla le tuilleadh eolais)',
+'edit-externally-help' => '(Féach ar na [https://www.mediawiki.org/wiki/Manual:External_editors treoracha cumraíochta] as Béarla le tuilleadh eolais)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'an t-iomlán',
@@ -2215,4 +2213,8 @@ Rachaidh an cód deimhnithe seo as feidhm ag $4.',
 # Search suggestions
 'searchsuggest-search' => 'Cuardaigh',
 
+# Special:ExpandTemplates
+'expand_templates_remove_comments' => 'Scrios nótaí tráchta',
+'expand_templates_preview' => 'Réamhamharc',
+
 );
index 636e841..89a37be 100644 (file)
@@ -61,7 +61,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Katılmaklar' ),
        'CreateAccount'             => array( 'EsapYarat', 'EsapAç' ),
        'Deadendpages'              => array( 'BaalantısızYazılar', 'BaalantısızSayfalar', 'BaalantısızYapraklar' ),
-       'Disambiguations'           => array( 'MaanaAydınnatmak', 'MaanaAydınnatma' ),
        'DoubleRedirects'           => array( 'İkiKeräYönnendirmäler', 'İkiKeräYönnendirmeler' ),
        'Listadmins'                => array( 'İzmetliListası' ),
        'Listbots'                  => array( 'BotListası' ),
@@ -306,8 +305,6 @@ $messages = array(
 'ok' => 'TAMAN',
 'retrievedfrom' => 'Alındı "$1"dän',
 'youhavenewmessages' => 'Var eni $1 ($2).',
-'newmessageslink' => 'eni mesajlar',
-'newmessagesdifflink' => 'Bitki diişmäk',
 'youhavenewmessagesmulti' => "$1'de eni mesajınız var.",
 'editsection' => 'diiştir',
 'editold' => 'diiştir',
@@ -1061,7 +1058,7 @@ Herliim fayl diiştirildi yaratılıştan sora, bir takım parametrlär var nic
 
 # External editor support
 'edit-externally' => 'Kompyuterinizdäki uygulamaklarlan faylı düz',
-'edit-externally-help' => 'Taa çok bilgi için var nicä bakmaa metadaki [//www.mediawiki.org/wiki/Manual:External_editors dış uygulama instrumentläri] (angliyça) sayfasına.',
+'edit-externally-help' => 'Taa çok bilgi için var nicä bakmaa metadaki [https://www.mediawiki.org/wiki/Manual:External_editors dış uygulama instrumentläri] (angliyça) sayfasına.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Hepsini göster',
index eeca569..6d90acc 100644 (file)
@@ -284,8 +284,6 @@ $1',
 'ok' => '做得',
 'retrievedfrom' => '版本页 "$1"',
 'youhavenewmessages' => '倷有 $1 ($2).',
-'newmessageslink' => '新消息',
-'newmessagesdifflink' => '最晏𠮶改动',
 'youhavenewmessagesmulti' => '$1 上有倷𠮶新消息',
 'editsection' => '编写',
 'editold' => '编写',
@@ -763,8 +761,6 @@ $2',
 'preferences' => '参数设置',
 'mypreferences' => '偶𠮶参数设置',
 'prefs-edits' => '编辑数:',
-'prefsnologin' => '哈冇登入',
-'prefsnologintext' => '汝要<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登入]</span>后才设得正个人参数。',
 'changepassword' => '改过密码',
 'prefs-skin' => '皮',
 'skin-preview' => '(预览)',
@@ -1051,7 +1047,7 @@ $2',
 'unwatchedpages' => '冇眏到𠮶页面',
 
 # List redirects
-'listredirects' => '重定向页面列表',
+'listredirects' => '重定向列表',
 
 # Unused templates
 'unusedtemplates' => '冇使用𠮶模板',
@@ -1063,7 +1059,7 @@ $2',
 'randompage-nopages' => '个只名字空间冇𠮶页面。',
 
 # Random redirect
-'randomredirect' => '随机重定向页面',
+'randomredirect' => '随机重定向',
 'randomredirect-nopages' => '个只名字空间冇重定向页面。',
 
 # Statistics
@@ -1086,7 +1082,7 @@ $2',
 'statistics-users-active-desc' => '头$1日操作过𠮶用户',
 'statistics-mostpopular' => '眵𠮶人最多𠮶页面',
 
-'doubleredirects' => '双重重定向页面',
+'doubleredirects' => '双重重定向',
 'doubleredirectstext' => '底下𠮶重定向链接到别只重定向页面:',
 'double-redirect-fixed-move' => '[[$1]]拕移动正,佢个下拕重定向到[[$2]]。',
 'double-redirect-fixer' => '重定向𠮶修正器',
@@ -1438,7 +1434,7 @@ $1',
 'linkshere' => '下底𠮶页面链接到[[:$1]]:',
 'nolinkshere' => '冇页面链接到[[:$1]]。',
 'nolinkshere-ns' => '选正𠮶空间名内冇页面链接到[[:$1]]。',
-'isredirect' => '重定向页',
+'isredirect' => '重定向页',
 'istemplate' => '含到',
 'isimage' => '档案连结',
 'whatlinkshere-prev' => '先$1只',
@@ -1601,7 +1597,7 @@ $1',
 'allmessagesdefault' => '默认文字',
 'allmessagescurrent' => '眼前𠮶文字',
 'allmessagestext' => '个首列到全部制定得正𠮶系统界面。
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:系统界面功能'''关卟嘞('''\$wgUseDatabaseMessages''')。",
 
 # Thumbnails
@@ -2070,7 +2066,7 @@ $1',
 
 # External editor support
 'edit-externally' => '用外部程式来编辑个只档案',
-'edit-externally-help' => '请参看[//www.mediawiki.org/wiki/Manual:External_editors 设置步骤]了解别𠮶内容。',
+'edit-externally-help' => '请参看[https://www.mediawiki.org/wiki/Manual:External_editors 设置步骤]了解别𠮶内容。',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
@@ -2194,7 +2190,7 @@ $3
 'version-hook-subscribedby' => '订阅人',
 'version-version' => '(版本 $1)',
 'version-license' => '许可证',
-'version-poweredby-credits' => "个只 Wiki 由 '''[//www.mediawiki.org/ MediaWiki]''' 驱动,版权所有 © 2001-$1 $2。",
+'version-poweredby-credits' => "个只 Wiki 由 '''[https://www.mediawiki.org/ MediaWiki]''' 驱动,版权所有 © 2001-$1 $2。",
 'version-software' => '装正𠮶软件',
 'version-software-version' => '版本',
 
index 4628ab3..1aa9cb9 100644 (file)
@@ -32,7 +32,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( '老早嗰頁面' ),
        'BrokenRedirects'           => array( '壞吥嗰重定向頁' ),
        'CreateAccount'             => array( '新建隻帳戶' ),
-       'Disambiguations'           => array( '多義項' ),
        'Fewestrevisions'           => array( '最少改動嗰頁面' ),
        'Longpages'                 => array( '莽文章' ),
        'Mostcategories'            => array( '最多分類嗰頁面' ),
@@ -306,8 +305,6 @@ $1',
 'ok' => '做得',
 'retrievedfrom' => '版本頁「$1」',
 'youhavenewmessages' => '汝有 $1 ($2).',
-'newmessageslink' => '新消息',
-'newmessagesdifflink' => '頂晏嗰改動',
 'youhavenewmessagesmulti' => '$1 上有倷嗰新消息',
 'editsection' => '編寫',
 'editold' => '編寫',
@@ -785,8 +782,6 @@ $2',
 'preferences' => '參數設置',
 'mypreferences' => '我嗰參數設置',
 'prefs-edits' => '編輯數:',
-'prefsnologin' => '哈冇登入',
-'prefsnologintext' => '汝要<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登入]</span>後才設得正個人參數。',
 'changepassword' => '改過密碼',
 'prefs-skin' => '皮',
 'skin-preview' => '(預覽)',
@@ -1623,7 +1618,7 @@ $1',
 'allmessagesdefault' => '默認文字',
 'allmessagescurrent' => '眼前嗰文字',
 'allmessagestext' => '箇首列到全部制定得正嗰系統界面。
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:系統界面功能'''關卟嘞('''\$wgUseDatabaseMessages''')。",
 
 # Thumbnails
@@ -2092,7 +2087,7 @@ $1',
 
 # External editor support
 'edit-externally' => '用外部程式來編輯箇隻檔案',
-'edit-externally-help' => '請參看[//www.mediawiki.org/wiki/Manual:External_editors 設置步驟]瞭解別嗰內容。',
+'edit-externally-help' => '請參看[https://www.mediawiki.org/wiki/Manual:External_editors 設置步驟]瞭解別嗰內容。',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
@@ -2216,7 +2211,7 @@ $3
 'version-hook-subscribedby' => '訂閱人',
 'version-version' => '(版本 $1)',
 'version-license' => '許可證',
-'version-poweredby-credits' => "箇隻 Wiki 由 '''[//www.mediawiki.org/ MediaWiki]''' 驅動,版權所有 © 2001-$1 $2。",
+'version-poweredby-credits' => "箇隻 Wiki 由 '''[https://www.mediawiki.org/ MediaWiki]''' 驅動,版權所有 © 2001-$1 $2。",
 'version-software' => '裝正嗰軟件',
 'version-software-version' => '版本',
 
index a65a09d..6e255c7 100644 (file)
@@ -42,12 +42,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Falaich mùthaidhean fo fhaire ann an liosta nam mùthaidhean ùra',
 'tog-newpageshidepatrolled' => 'Falaich duilleagan fo fhaire ann an liosta nan duilleagan ùra',
 'tog-extendwatchlist' => "Leudaich an clàr-faire gus an seall e gach mùthadh 's chan ann an fheadhainn as ùire a-mhàin",
-'tog-usenewrc' => "Buidhnich na h-atharraichean a-rèir duilleige sna mùthaidhean ùra agus air a' chlàr-fhaire (feumaidh seo JavaScript)",
+'tog-usenewrc' => "Buidhnich na h-atharraichean a-rèir duilleige sna mùthaidhean ùra agus air a' chlàr-fhaire",
 'tog-numberheadings' => 'Cuir àireamhan ri ceann-sgrìobhaidhean leis fhèin',
-'tog-showtoolbar' => 'Seall am bàr-inneil deasachaidh (feumaidh seo JavaScript)',
-'tog-editondblclick' => 'Tòisich air deasachadh duilleige le briogadh dùbailt (feumaidh seo JavaScript)',
+'tog-showtoolbar' => 'Seall am bàr-inneal deasachaidh',
+'tog-editondblclick' => 'Tòisich air deasachadh duilleige le briogadh dùbailte',
 'tog-editsection' => 'Cuir am comas deasachadh earainn le ceanglaichean [deasaich]',
-'tog-editsectiononrightclick' => "Cuir an comas deasachadh earainn le briogadh deas air tiotal de dh'earrainn (feumaidh seo JavaScript)",
+'tog-editsectiononrightclick' => "Cuir an comas deasachadh earrainn le briogadh deas air tiotal de dh'earrainn",
 'tog-showtoc' => 'Seall an clàr-innse (air duilleagan air a bheil barrachd air 3 ceann-sgrìobhaidhean)',
 'tog-rememberpassword' => "Cuimhnich gu bheil mi air logadh a-steach air a' choimpiutair seo (suas gu $1 {{PLURAL:$1|latha|latha|làithean|latha}})",
 'tog-watchcreations' => "Cuir duilleagan a chruthaicheas mi air a' chlàr-fhaire agam",
@@ -65,7 +65,7 @@ $messages = array(
 'tog-shownumberswatching' => "Nochd àireamh nan cleachdaichean a tha a' cumail sùil air",
 'tog-oldsig' => 'An t-earr-sgrìobhadh làithreach:',
 'tog-fancysig' => 'Làimhsich an t-earr-sgrìobhadh mar wikitext (gun cheangal leis fhèin)',
-'tog-uselivepreview' => 'Cleachd an ro-shealladh beò (feumaidh seo JavaScript) (deuchainneach)',
+'tog-uselivepreview' => 'Cleachd an ro-shealladh beò (deuchainneach)',
 'tog-forceeditsummary' => "Cuir ceist nuair a dh'fhàgas mi gearr-chunntas an deasachaidh bàn",
 'tog-watchlisthideown' => 'Falaich mo mhùthaidhean fhèin air mo chlàr-faire',
 'tog-watchlisthidebots' => 'Falaich mùthaidhean nam bot air mo chlàr-faire',
@@ -78,6 +78,7 @@ $messages = array(
 'tog-showhiddencats' => 'Seall na roinnean falaichte',
 'tog-norollbackdiff' => 'Na dèan diof às dèidh roiligeadh air ais',
 'tog-useeditwarning' => 'Thoir rabhadh dhomh ma bhios mi an impis duilleag deasachaidh fhàgail mus do shàbhail mi na mùthaidhean agam',
+'tog-prefershttps' => 'Cleachd ceangal tèarainte an-còmhnaidh nuair a bhios mi clàraichte a-staigh',
 
 'underline-always' => 'An-còmhnaidh',
 'underline-never' => 'Na dèan seo idir',
@@ -141,6 +142,18 @@ $messages = array(
 'oct' => 'Dàmh',
 'nov' => 'Samh',
 'dec' => 'Dùbh',
+'january-date' => '$1 dhen Fhaoilleach',
+'february-date' => '$1 dhen Ghearran',
+'march-date' => '$1 dhen Mhàrt',
+'april-date' => '$1 dhen Ghiblean',
+'may-date' => '$1 dhen Chèitean',
+'june-date' => '$1 dhen Ògmhios',
+'july-date' => '$1 dhen Iuchar',
+'august-date' => '$1 dhen Lùnastal',
+'september-date' => '$1 dhen t-Sultain',
+'october-date' => '$1 dhen Dàmhair',
+'november-date' => '$1 dhen t-Samhain',
+'december-date' => '$1 dhen Dùbhlachd',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Roinn-seòrsa|Roinn-seòrsa|Roinnean-seòrsa|Roinn-seòrsa}}',
@@ -166,7 +179,7 @@ $messages = array(
 'newwindow' => "(a' fosgladh ann an uinneag ùr)",
 'cancel' => 'Sguir dheth',
 'moredotdotdot' => 'Barrachd...',
-'morenotlisted' => 'Barrachd nach eil air an liosta...',
+'morenotlisted' => 'Chan eil an liosta seo iomlan.',
 'mypage' => 'Duilleag',
 'mytalk' => 'Deasbaireachd',
 'anontalk' => 'Conaltradh airson an IP seo',
@@ -222,6 +235,7 @@ $messages = array(
 'create-this-page' => 'Cruthaich an duilleag seo',
 'delete' => 'Sguab às',
 'deletethispage' => 'Sguab às an duilleag seo',
+'undeletethispage' => 'Neo-dhèan sguabadh às na duilleige seo',
 'undelete_short' => "Neo-dhèan sguabadh às de {{PLURAL:$1|dh'aon deasachadh|$1 dheasachadh|$1 deasachaidhean|$1 deasachadh}}",
 'viewdeleted_short' => 'Seall {{PLURAL:$1|aon deasachadh|$1 dheasachadh|$1 deasachaidhean|$1 deasachadh}} a chaidh a sguabadh às',
 'protect' => 'Dìon',
@@ -238,7 +252,7 @@ $messages = array(
 'articlepage' => 'Seall duilleag na susbainte',
 'talk' => 'Deasbaireachd',
 'views' => 'Tadhalan',
-'toolbox' => 'Bogsa-innealan',
+'toolbox' => 'Innealan',
 'userpage' => "Seall duilleag a' chleachdaiche",
 'projectpage' => "Seall duilleag a' phròiseict",
 'imagepage' => 'Seall duilleag an fhaidhle',
@@ -268,7 +282,7 @@ $1",
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Mu dhèidhinn {{SITENAME}}',
 'aboutpage' => 'Project:Mu dhèidhinn',
-'copyright' => 'Tha susbaint ri làimh fo $1.',
+'copyright' => "Tha susbaint ri làimh fo $1 mur eil an caochladh 'ga innse.",
 'copyrightpage' => '{{ns:project}}:Còraichean lethbhric',
 'currentevents' => 'Cùisean an latha',
 'currentevents-url' => 'Project:Cùisean an latha',
@@ -295,8 +309,6 @@ Seall air [[Special:Version|duilleag an tionndaidh]].',
 'ok' => 'Ceart ma-thà',
 'retrievedfrom' => 'Air a tharraing à "$1"',
 'youhavenewmessages' => 'Tha $1 ($2) agad.',
-'newmessageslink' => 'teachdaireachdan ùra',
-'newmessagesdifflink' => 'mùthadh mu dheireadh',
 'youhavenewmessagesfromusers' => 'Tha $1 o {{PLURAL:$3|aon chleachdaiche|$3 chleachdaiche|$3 cleachdaichean|$3 cleachdaiche}} agad ($2).',
 'youhavenewmessagesmanyusers' => 'Tha $1 agad o iomadh cleachdaiche ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|aon teachdaireachd ùr|$1 theachdaireachd ùr|$1 teachdaireachdan ùra|$1 teachdaireachd ùr}}',
@@ -352,6 +364,12 @@ Gheibh thu liosta nan duilleagan sònraichte 's dligheach aig [[Special:SpecialP
 # General errors
 'error' => 'Mearachd',
 'databaseerror' => 'Mearachd an stòir-dhàta',
+'databaseerror-text' => "Thachair mearachd leis a' cheist a chuireadh dhan stòr-dàta.
+Dh'fhaoidte gu bheil buga sa bhathar-bhog.",
+'databaseerror-textcl' => "Thachair mearachd leis a' cheist a chuireadh dhan stòr-dàta.",
+'databaseerror-query' => 'Ceist: $1',
+'databaseerror-function' => 'Foincsean: $1',
+'databaseerror-error' => 'Mearachd: $1',
 'laggedslavemode' => "'''Rabhadh:''' Faodaidh nach eil ùrachaidhean a rinneadh o chionn ghoirid a' nochdadh san duilleag.",
 'readonly' => 'Stòr-dàta glaiste',
 'enterlockreason' => "Cuir a-steach adhbhar a' ghlais, a' gabhail a-steach tuairmeas air fuasgladh a' ghlais.",
@@ -385,6 +403,7 @@ Faodaidh gun deach a sguabadh às le cuideigin eile mu thràth.',
 'cannotdelete-title' => 'Cha ghabh an duilleag "$1" a sguabadh às',
 'delete-hook-aborted' => 'Sguireadh dhen sguabadh às ri linn dubhain.
 Cha deach adhbhar a thoirt seachad.',
+'no-null-revision' => 'Cha b\' urrainn dhuinn lèirmheas neoinitheach ùr a chruthachadh dhan duilleag "$1"',
 'badtitle' => 'Droch thiotal',
 'badtitletext' => "Bha an duilleag a dh'iarr thu mì-dhligheach, falamh no le tiotal eadar-chànanach no eadar-uici air a dhroch cheangal.
 Faodaidh gu bheil aon no barrachd charactairean ann nach urrainn dhut a chleachdadh ann an tiotalan.",
@@ -412,6 +431,10 @@ $2',
 'namespaceprotected' => "Chan eil cead agad duilleagan san namespace '''$1''' a dheasachadh.",
 'customcssprotected' => "Chan eil cead agad an duilleag CSS seo a dheasachadh a chionn 's gu bheil na roghainnean pearsanta aig cleachdaiche eile innte.",
 'customjsprotected' => "Chan eil cead agad an duilleag JavaScript seo a dheasachadh a chionn 's gu bheil na roghainnean pearsanta aig cleachdaiche eile innte.",
+'mycustomcssprotected' => 'Chan eil cead agad an duilleag CSS seo a dheasachadh.',
+'mycustomjsprotected' => 'Chan eil cead agad an duilleag JavaScript seo a dheasachadh.',
+'myprivateinfoprotected' => 'Chan eil cead agad am fiosrachadh prìobhaideach agad a dheasachadh.',
+'mypreferencesprotected' => 'Chan eil cead agad na roghainnean agad a dheasachadh.',
 'ns-specialprotected' => 'Chan ghabh duilleagan sònraichte a dheasachadh.',
 'titleprotected' => 'Chaidh an duilleag seo a dhìon o chruthachadh le [[User:$1|$1]].
 Seo am mìneachadh: "\'\'$2\'\'".',
@@ -428,16 +451,26 @@ Thug an rianaire a ghlais e seachad an t-adhbhar a leanas: "$3".',
 'virus-unknownscanner' => 'sganair bhìorasan neo-aithnichte:',
 
 # Login and logout pages
-'logouttext' => "'''Chaidh do logadh a-mach.'''
-'S urrainn dhut leantainn air adhart a' cleachdadh {{SITENAME}} a chleachdadh gun urra no 's urrainn dhut <span class='plainlinks'>[$1 logadh a-steach a-rithist]</span> mar an dearbh-chleachdaiche no mar chleachdaiche eile.
-Thoir an aire gum bi coltas air cuide dhe na duilleagan mar gum biodh tu air logadh a-steach gus am falamhaich thu tasgadan a' bhrabhsair agad.",
+'logouttext' => "'''Chaidh do chlàradh a-mach.'''
+
+Thoir an aire gum bi coltas air cuid dhe na duilleagan mar gum biodh tu air clàradh a-steach gus am falamhaich thu tasgadan a' bhrabhsair agad.",
 'welcomeuser' => 'Fàilte ort, $1',
 'welcomecreation-msg' => 'Chaidh an cunntas agad a chruthachadh.
 Na dìochuimhnich na [[Special:Preferences|roghainnean agad air {{SITENAME}}]] a ghleusadh dhut fhèin.',
 'yourname' => 'Ainm-cleachdaiche:',
+'userlogin-yourname' => 'Ainm-cleachdaiche',
+'userlogin-yourname-ph' => 'Cuir a-steach an t-ainm-cleachdaiche agad',
+'createacct-another-username-ph' => 'Cuir a-steach an t-ainm-cleachdaiche',
 'yourpassword' => 'Am facal-faire agad',
+'userlogin-yourpassword' => 'Facal-faire',
+'userlogin-yourpassword-ph' => 'Cuir a-steach am facal-faire agad',
+'createacct-yourpassword-ph' => 'Cuir a-steach facal-faire',
 'yourpasswordagain' => 'Ath-sgrìobh facal-faire',
+'createacct-yourpasswordagain' => 'Dearbh am facal-faire',
+'createacct-yourpasswordagain-ph' => 'Cuir a-steach am facal-faire a-rithist',
 'remembermypassword' => "Cuimhnich gu bheil mi air logadh a-steach air a' choimpiutair seo (suas gu $1 {{PLURAL:$1|latha|latha|làithean|latha}})",
+'userlogin-remembermypassword' => 'Cum clàraichte a-staigh mi',
+'userlogin-signwithsecure' => 'Cleachd ceangal tèarainte',
 'yourdomainname' => 'An àrainn-lìn agad:',
 'password-change-forbidden' => 'Chan urrainn dhut faclan-faire atharrachadh air an uicipeid seo.',
 'externaldberror' => 'Thachair mearachd le dearbhadh an stòir-dhàta air neo chan eil cead agad an cunntas agad air an taobh a-muigh ùrachadh.',
@@ -449,18 +482,44 @@ Na dìochuimhnich na [[Special:Preferences|roghainnean agad air {{SITENAME}}]] a
 'logout' => 'Log a-mach',
 'userlogout' => 'Log a-mach',
 'notloggedin' => 'Chan eil thu air logadh a-steach',
+'userlogin-noaccount' => 'Nach eil cunntas agad?',
+'userlogin-joinproject' => 'Gabh pàirt ann an {{SITENAME}}',
 'nologin' => 'Nach eil cunntas agad fhathast? $1.',
 'nologinlink' => 'Cruthaich cunntas',
 'createaccount' => 'Cruthaich cunntas ùr',
 'gotaccount' => 'A bheil cunntas agad mu thràth? $1.',
 'gotaccountlink' => 'Log a-steach',
 'userlogin-resetlink' => "Na dhìochuimhnich thu d' ainm is facal-faire?",
+'userlogin-resetpassword-link' => 'Na dhìochuimhnich thu am facal-faire agad?',
+'helplogin-url' => "Help:A' clàradh a-steach",
+'userlogin-helplink' => "[[{{MediaWiki:helplogin-url}}|Cobhair leis a' chlàradh a-steach]]",
+'userlogin-loggedin' => 'Chaidh do chlàradh mar {{GENDER:$1|$1}} mu thràth.
+Cleachd am foirm gu h-ìosal airson clàradh a-steach mar chleachdaiche eile.',
+'userlogin-createanother' => 'Cruthaich cunntas eile',
+'createacct-join' => 'Cuir a-steach am fiosrachadh agad gu h-ìosal.',
+'createacct-another-join' => "Cuir a-steach fiosrachadh a' chunntais ùir gu h-ìosal.",
+'createacct-emailrequired' => 'Seòladh puist-d',
+'createacct-emailoptional' => 'Seòladh puist-d (roghainneil)',
+'createacct-email-ph' => 'Cuir a-steach an seòladh puist-d agad',
+'createacct-another-email-ph' => 'Cuir a-steach seòladh puist-d',
 'createaccountmail' => "Cleachd facal-faire sealach air thuaiream agus cuir e dhan phost-d a tha 'ga shònrachadh gu h-ìosal",
+'createacct-realname' => 'Fìor-ainm (roghainneil)',
 'createaccountreason' => 'Adhbhar:',
+'createacct-reason' => 'Adhbhar',
+'createacct-reason-ph' => "Carson a tha thu a' cruthachadh cunntas eile?",
+'createacct-captcha' => 'Sgrùdadh tèarainteachd',
+'createacct-imgcaptcha-ph' => 'Cuir a-steach an teacsa a chì thu gu h-àrd',
+'createacct-submit' => 'Cruthaich an cunntas agad',
+'createacct-another-submit' => 'Cruthaich cunntas eile',
+'createacct-benefit-heading' => "Tha {{SITENAME}} 'ga chruthachadh le daoine mar thu fhèin.",
+'createacct-benefit-body1' => '{{PLURAL:$1|deasachadh|dheasachadh|deasachaidhean|deasachadh}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|duilleag|dhuilleag|duilleagan|duilleag}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|chom-pàirtiche|chom-pàirtiche|com-pàirtichean|com-pàirtiche}} o chionn goirid',
 'badretype' => "Chan eil an dà fhacal-faire a chuir thu a-steach a' freagairt ri chèile.",
 'userexists' => "Tha an t-ainm-cleachdaiche a chuir thu a-steach 'ga chleachdadh mu thràth.
 Nach tagh thu ainm eile?",
 'loginerror' => 'Mearachd log a-steach',
+'createacct-error' => "Mearachd le cruthachadh a' chunntais",
 'createaccounterror' => 'Cha do ghabh an cunntas a leanas a chruthachadh: $1',
 'nocookiesnew' => "Chaidh an cunntas a chruthachadh ach cha do rinn thu logadh a-steach.
 Tha {{SITENAME}} a' cleachdadh briosgaidean gus daoine a logadh a-steach.
@@ -503,12 +562,12 @@ agus leantainn ort leis an t-seann fhacal-faire.',
 Clàraich a-steach a-rithist nuair a gheibh thu e.',
 'blocked-mailpassword' => "Chaidh bacadh a chur air an t-seòladh IP agad 's chan eil cead deasachaidh agad agus chan urrainn dhut an gleus a chum aiseag an fhacail-fhaire a chleachdadh gus casg a chur air mì-ghnàthachadh.",
 'eauthentsent' => 'Chaidh post-d dearbhaidh a chur dhan phost-d a chaidh ainmeachadh.
-Mus dèid post-d sam bith eile a chur dhan chunntas, feumaidh tu leantainn ris an treòrachadh sa phost-d mar dhearbhadh gur ann agadsa a tha an cunntas.',
+Mus dèid post-d sam bith eile a chur dhan chunntas, feumaidh tu leantainn ris an stiùireadh sa phost-d mar dhearbhadh gur ann agadsa a tha an cunntas.',
 'throttled-mailpassword' => 'Chaidh post-d a chur airson ath-shuidheachadh facail-fhaire mu thràth {{PLURAL:$1|uair|$1 uair|$1 uairean|$1 uair}} a thìde air ais.
 Gus casg a chur air mì-ghnàthachadh, cha chuir sinn ach aon chuimhneachan facail-fhaire gach {{PLURAL:$1|uair|$1 uair|$1 uairean|$1 uair}} a thìde.',
 'mailerror' => "Mearachd a' cur post: $1",
 'acct_creation_throttle_hit' => "Chruthaich na h-aoighean air an Uici seo {{PLURAL:$1|1 chunntas|$1 chunntas|$1 cunntasan|$1 cunntas}} fon IP agad an-dè agus sin an àireamh as motha a tha ceadaichte. Chan urrainn do dh'aoighean eile on IP seo barrachd chunntasan a chruthachadh air sgàth sin.",
-'emailauthenticated' => 'Chaidh an seòladh puist-dhealain agad a dhearbhadh $2 aig $3.',
+'emailauthenticated' => 'Chaidh an seòladh puist-d agad a dhearbhadh $2 aig $3.',
 'emailnotauthenticated' => 'Cha deach am post-d agad a dhearbhadh fhathast.
 Cha dèid post-d a chur airson gin dhe na feartan a leanas.',
 'noemailprefs' => 'Sònraich post-d sna roghainnean agad gus na feartan seo a chur an comas.',
@@ -518,7 +577,7 @@ Cuir a-steach seòladh san fhòrmat cheart no falamhaich an raon sin.",
 'cannotchangeemail' => 'Cha ghabh na puist-d a tha co-cheangailte ri cunntas atharrachadh air an uicipeid seo.',
 'emaildisabled' => 'Chan urrainn dhut puist-d a chur air an làrach seo.',
 'accountcreated' => 'Cunntas cruthaichte',
-'accountcreatedtext' => 'Chaidh an cunntas cleachdaiche airson $1 a chruthachadh.',
+'accountcreatedtext' => 'Chaidh an cunntas cleachdaiche airson [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) a chruthachadh.',
 'createaccount-title' => 'Cruthachadh cunntais airson {{SITENAME}}',
 'createaccount-text' => 'Chruthaich cuideigin cunntas airson a\' phost-d agad air {{SITENAME}} ($4) air a bheil "$2", leis an fhacal-fhaire "$3".
 Bu chòir dhut clàradh a-steach agus am facal-faire agad atharrachadh gu h-ìosal an-dràsta.
@@ -526,10 +585,12 @@ Bu chòir dhut clàradh a-steach agus am facal-faire agad atharrachadh gu h-ìos
 \'S urrainn dhut an teachdaireachd seo a leigeil seachad ma chaidh an cunntas a chruthachadh air mhearachd.',
 'usernamehasherror' => 'Chan fhaod hais a bhith ann an ainm cleachdaiche',
 'login-throttled' => "Dh'fheuch thu ri clàradh a-steach ro thric o chionn ghoirid.
-Fuirich ort mus feuch thu ris a-rithist.",
+Fuirich ort $1 mus feuch thu ris a-rithist.",
 'login-abort-generic' => "Cha do shoirbhich leat leis a' chlàradh a-steach - Chaidh sgur dheth",
 'loginlanguagelabel' => 'Cànan: $1',
 'suspicious-userlogout' => "Chaidh d' iarrtas airson clàradh a-mach a dhiùltadh a chionn 's gu bheil coltas gun deach a chur le brabhsair briste no le progsaidh tasglannaidh.",
+'createacct-another-realname-tip' => 'Cha leig thu leas innse dè am fìor-ainm a tha ort.
+Ma bheir thu seachad e, thèid seo a chleachdadh gus urram a thoirt dha na h-ùghdaran airson an cuid obrach.',
 
 # Email sending
 'php-mail-error-unknown' => 'Mearachd neo-aithichte san fheart mail() aig PHP.',
@@ -545,8 +606,7 @@ Gus an clàradh a-steach a choileadh, tha agad ri facal-faire ùr a shuidheachad
 'newpassword' => 'Facal-faire ùr',
 'retypenew' => 'Ath-sgrìobh am facal-faire ùr',
 'resetpass_submit' => "Suidhich am facal-faire 's clàraich a-steach",
-'changepassword-success' => "Chaidh am facal-faire agad atharrachadh!
-'Gad chlàradh a-steach an-dràsta...",
+'changepassword-success' => 'Chaidh am facal-faire agad atharrachadh!',
 'resetpass_forbidden' => 'Cha ghabh na faclan-faire atharrachadh',
 'resetpass-no-info' => 'Feumaidh tu clàradh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.',
 'resetpass-submit-loggedin' => 'Atharraich am facal-faire',
@@ -554,11 +614,15 @@ Gus an clàradh a-steach a choileadh, tha agad ri facal-faire ùr a shuidheachad
 'resetpass-wrong-oldpass' => "Tha am facal-faire sealach no làithreach mì-dhligheach.
 Saoil an do dh'atharraich thu am facal-faire agad mu thràth no an do dh'iarr thu facal-faire sealach ùr?",
 'resetpass-temp-password' => 'Facal-faire sealach:',
+'resetpass-abort-generic' => 'Chuir leudachan crìoch air atharrachadh an fhacail-fhaire.',
 
 # Special:PasswordReset
 'passwordreset' => 'Ath-shuidhich am facal-faire',
+'passwordreset-text-one' => 'Lìon am foirm seo gus am facal-faire agad ath-shuidheachadh.',
+'passwordreset-text-many' => '{{PLURAL:$1|Lìon aon dhe na raointean gus am facal-faire agad ath-shuidheachadh.}}',
 'passwordreset-legend' => 'Ath-shuidhich am facal-faire',
 'passwordreset-disabled' => 'Chaidh ath-shuidheachadh nam faclan-faire a chur à comas air an uicipeid seo.',
+'passwordreset-emaildisabled' => "Chaidh feartan a' phuist-d a chur à comas san uicipeid seo.",
 'passwordreset-username' => 'Ainm-cleachdaiche:',
 'passwordreset-domain' => 'Àrainn-lìn:',
 'passwordreset-capture' => "A bheil thu airson coimhead air a' phost-d?",
@@ -581,7 +645,7 @@ Bu chòir dhut clàradh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma
 Facal-faire sealach: $2',
 'passwordreset-emailsent' => 'Chaidh post-d airson ath-shuidheachadh an fhacail-fhaire a chur.',
 'passwordreset-emailsent-capture' => 'Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a chur agus chì thu sin gu h-ìosal.',
-'passwordreset-emailerror-capture' => "Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a ghintinn agus chì thu sin gu h-ìosal ach cha b' urrainn dhuinn a chur dhan chleachdaiche: $1",
+'passwordreset-emailerror-capture' => "Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a ghintinn agus chì thu sin gu h-ìosal ach cha b' urrainn dhuinn a chur dhan chleachdaiche {{GENDER:$2|user}}: $1",
 
 # Special:ChangeEmail
 'changeemail' => 'Atharraich am post-d',
@@ -595,6 +659,19 @@ Facal-faire sealach: $2',
 'changeemail-submit' => 'Atharraich am post-d',
 'changeemail-cancel' => 'Sguir dheth',
 
+# Special:ResetTokens
+'resettokens' => 'Ath-shuidhich na tòcanan',
+'resettokens-text' => "'S urrainn dhut tòcanan ath-shuidheachadh a bheir cothrom dhut air cuid a dhàta prìobhaideach a tha co-cheangailte ris a' chunntas agad.
+
+Bu chòir dhut seo a dhèanamh ma thug thu do chuideigin e air mhearachd no ma bhris cuideigin a-steach air a' chunntas agad.",
+'resettokens-no-tokens' => 'Chan eil tòcan ann a ghabhas ath-shuidheachadh.',
+'resettokens-legend' => 'Ath-shuidhich na tòcanan',
+'resettokens-tokens' => 'Tòcanan:',
+'resettokens-token-label' => "$1 ('s e $2 an luach làithreach)",
+'resettokens-watchlist-token' => "Tòcan airson an inbhir-lìn (Atom/RSS) a sheallas dhut [[Special:Watchlist|atharraichean air duilleagan a tha air a' chlàr-fhaire agad]]",
+'resettokens-done' => 'Chaidh na tòcanan ath-shuidheachadh.',
+'resettokens-resetbutton' => 'Ath-shuidhich na tòcanan a chaidh a thaghadh',
+
 # Edit page toolbar
 'bold_sample' => 'Teacs trom',
 'bold_tip' => 'Teacs trom',
@@ -677,7 +754,7 @@ Dh'fhaoidte gun deach a ghluasad no a sguabadh às fhad 's a bha thu a' coimhead
 'accmailtitle' => 'Facal-faire air a chur.',
 'accmailtext' => "Chaidh facal-faire a chruthachadh air thuaiream airson [[User talk:$1|$1]] 's a chur gu $2.
 
-Gabhaidh am facal-faire airson a' chunntais ùir seo atharrachadh air an fo ''[[Special:ChangePassword|atharraich facal-faire]]'' as dèidh do chleachdaiche logadh a-steach.",
+Gabhaidh am facal-faire airson a' chunntais ùir seo atharrachadh air an fo ''[[Special:ChangePassword|atharraich facal-faire]]'' as dèidh dhan chleachdaiche clàradh a-steach.",
 'newarticle' => '(Ùr)',
 'newarticletext' => "Lean thu ri ceangal gu duilleag nach eil ann fhathast.
 Cuir teacs sa bhogsa gu h-ìosal gus an duilleag seo a chruthachadh (seall air [[{{MediaWiki:Helppage}}|duilleag na cobharach]] airson barrachd fiosrachaidh).
@@ -786,7 +863,7 @@ Seo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
 'nocreate-loggedin' => 'Chan eil cead agad duilleagan ùra a chruthachadh.',
 'sectioneditnotsupported-title' => 'Chan eil taic ri deasachadh earrannan',
 'sectioneditnotsupported-text' => 'Chan eil taic ri deasachadh earrannan air an duilleag seo.',
-'permissionserrors' => "Meareachd leis a' chead",
+'permissionserrors' => "Mearachd leis a' chead",
 'permissionserrorstext' => 'Chan eil cead agad sin a dhèanamh air sgàth {{PLURAL:$1|an adhbhair|an $1 adhbhar|nan $1 adhbharan|nan $1 adhbhar}} a leanas:',
 'permissionserrorstext-withaction' => 'Chan eil cead agad airson "$2" air sgàth {{PLURAL:$1|an $1 adhbhair|an $1 adhbhar|nan $1 adhbharan|nan $1 adhbhar}} a leanas:',
 'recreate-moveddeleted-warn' => "'''Rabhadh: Tha thu gu bhith ath-chruthachadh duilleag a chaidh a sguabadh às roimhe.'''
@@ -802,6 +879,7 @@ Cha deach adhbhar a thoirt seachad.',
 Tha coltas gun deach a sguabadh às.",
 'edit-conflict' => 'Còmhstri deasachaidh.',
 'edit-no-change' => "Chaidh an obair-dheasachaidh agad a leigeil seachad a chionn 's nach do dh'atharraich thu dad.",
+'postedit-confirmation' => 'Chaidh na dheasaich thu a shàbhaladh.',
 'edit-already-exists' => "Cha b' urrainn dhuinn an duilleag ùr a chruthachadh.
 Tha e ann mu thràth.",
 'defaultmessagetext' => 'Teacsa bunaiteach na teachdaireachd',
@@ -829,10 +907,29 @@ Cha dèid cuid dhith a ghabhail a-steach.",
 Chaidh na h-argamaidean sinn a leigeil seachad.",
 'post-expand-template-argument-category' => 'Duilleagan air an deach argamaidean teamplaidean fhàgail às',
 'parser-template-loop-warning' => 'Mhothaicheadh do lùb teamplaid: [[$1]]',
+'parser-template-recursion-depth-warning' => 'Chaidh thu thairis air crìoch doimhne nan ath-chùrsaidhean teamplaid ($1)',
+'language-converter-depth-warning' => 'Chaidh thu thairis air crìoch doimhne an iompachair chànain ($1)',
+'node-count-exceeded-category' => 'Duilleagan far an deachas thairis air cunntas nan nòdan',
+'node-count-exceeded-warning' => 'Chaidh an duilleag thairis air cunntas nan nòdan',
+'expansion-depth-exceeded-category' => "Duilleagan far an deachas thairis air a' chrìoch leudachaidh",
+'expansion-depth-exceeded-warning' => 'Chaidh an duilleag thairis air an doimhne leudachaidh',
 'parser-unstrip-loop-warning' => 'Mhothaich sinn do lùb unstrip',
+'parser-unstrip-recursion-limit' => 'Chaidheas thairis air crìoch unstrip recursion ($1)',
+'converter-manual-rule-error' => 'Mhothaich sinn do mhearachd san riaghailt iompachadh làimhe airson cànan',
+
+# "Undo" feature
+'undo-success' => "Gabhaidh an deasachadh seo a neo-dhèanamh.
+Thoir sùil air a' choimeas gu h-ìosal is dearbh gur e sin a tha fa-near dhut agus sàbhail na h-atharraichean gu h-ìosal gus neo-dhèanamh an deasachaidh a choileanadh.",
+'undo-failure' => "Cha b' urrainn dhuinn an deasachadh a neo-dhèanamh air sgàth 's gun robh deasachaidhean eile sa mheadhan.",
+'undo-norev' => "Cha b' urrainn dhuinn an deasachadh a neo-dhèanamh a chionn 's nach robh e ann no gun deach a sguabadh às.",
+'undo-summary' => 'Neo-dhèan mùthadh $1 le [[Special:Contributions/$2|$2]] ([[User talk:$2|Deasbaireachd]])',
+'undo-summary-username-hidden' => 'Neo-dhèan am mùthadh $1 le cleachdaiche falaichte',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Cha ghabh an cunntas a chruthachadh',
+'cantcreateaccount-text' => "Chuir [[User:$3|$3]] bacadh air cruthachadh chunntasan on t-seòladh IP seo ('''$1''').
+
+Dh'innise $3 gun do rinn iad seo air sgàth: ''$2''",
 
 # History pages
 'viewpagelogs' => 'Seall logaichean na duilleige seo',
@@ -870,30 +967,130 @@ Feuch is [[Special:Search|lorg duilleagan ùra iomachaidh air an uici]]",
 'rev-deleted-comment' => '(chaidh gearr-chunntas an deasachaidh a thoirt air falbh)',
 'rev-deleted-user' => '(chaidh an t-ainm-cleachdaiche a thoirt air falbh)',
 'rev-deleted-event' => '(chaidh gnìomh an loga a thoirt air falbh)',
+'rev-deleted-user-contribs' => '[chaidh an t-ainm-cleachdaiche no an seòladh IP a thoirt air falbh - chan fhaic na com-pàirtichean an deasachadh]',
+'rev-deleted-text-permission' => "Chaidh mùthadh na duilleige seo '''a sguabadh às'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].",
+'rev-deleted-text-unhide' => "Chaidh mùthadh na duilleige seo '''a sguabadh às'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].
+'S urrainn dhut [$1 am mùthadh seo fhaicinn fhathast] ma tha thu airson leantainn air adhart.",
+'rev-suppressed-text-unhide' => "Chaidh mùthadh na duilleige seo '''a mhùchadh'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a mhùchadh].
+'S urrainn dhut [$1 am mùthadh seo fhaicinn fhathast] ma tha thu airson leantainn air adhart.",
+'rev-deleted-text-view' => "Chaidh mùthadh na duilleige seo '''a sguabadh às'''.
+'S urrainn dhut coimhead air, gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].",
+'rev-suppressed-text-view' => "Chaidh mùthadh na duilleige seo '''a mhùchadh'''.
+'S urrainn dhut coimhead air, gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a mhùchadh].",
+'rev-deleted-no-diff' => "Chan fhaic thu an diff seo a chionn 's gun deach aon dhe na mùthaidhean '''a sguabadh às'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].",
+'rev-suppressed-no-diff' => "Chan fhaic thu an diff seo a chionn 's gun deach aon dhe na mùthaidhean '''a sguabadh às'''.",
+'rev-deleted-unhide-diff' => "Chaidh mùthadh dhen diff seo '''a sguabadh às'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].
+'S urrainn dhut [$1 coimhead air an diff seo fhathast] ma tha thu airson leantainn air adhart.",
+'rev-suppressed-unhide-diff' => "Chaidh mùthadh an diff seo '''a mhùchadh'''.
+Gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a mhùchadh].
+'S urrainn dhut [$1 coimhead air an diff seo fhathast] ma tha thu airson leantainn air adhart.",
+'rev-deleted-diff-view' => "Chaidh mùthadh an diff seo '''a sguabadh às'''.
+'S urrainn dhut coimhead air an diff seo, gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a sguabadh às].",
+'rev-suppressed-diff-view' => "Chaidh mùthadh an diff seo '''a mhùchadh'''.
+'S urrainn dhut coimhead air an diff seo, gheibh thu mion-fhiosrachadh air [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} ann an loga nan rudan a chaidh a mhùchadh].",
 'rev-delundel' => 'seall/falaich',
 'rev-showdeleted' => 'seall',
+'revisiondelete' => 'Sguab às/neo-dhèan sguabadh às mhùthaidhean',
+'revdelete-nooldid-title' => 'Tha am mùthadh seo mì-dhligheach',
+'revdelete-nooldid-text' => "Cha do shònraich thu mùthadh airson seo a dhèanamh, chan eil e ann no tha thu a' feuchainn ris am mùthadh làithreach a chur am falach.",
+'revdelete-nologtype-title' => 'Cha deach seòrsa an loga a shònrachadh',
+'revdelete-nologtype-text' => 'Cha do shònraich thu seòrsa an loga air an dèanar seo.',
+'revdelete-nologid-title' => 'Innteart mì-dhligheach an loga',
+'revdelete-nologid-text' => 'Cha do shònraich thu tachartas loga targaide gus seo a dhèanamh no chan eil an t-innteart seo ann.',
+'revdelete-no-file' => 'Chan eil am faidhle a shònraich thu ann.',
+'revdelete-show-file-confirm' => 'A bheil thu cinnteach gu bheil thu airson coimhead air mùthadh an fhaidhle "<nowiki>$1</nowiki>" a chaidh a sguabadh às $2 aig $3?',
+'revdelete-show-file-submit' => 'Tha',
 'revdelete-selected' => "'''{{PLURAL:$2|Lèirmheas|Lèirmheasan}} de [[:$1]] a thagh thu:'''",
 'logdelete-selected' => "'''{{PLURAL:$1|An tachartas loga|Na tachartasan loga}} a thagh thu:'''",
-'revdelete-hide-user' => 'Falaich ainm-cleachdaiche/seòladh IP an deasaiche',
+'revdelete-text' => "'''Nochdaidh lèirmheasan is tachartasan fhathast ann an eachdraidh 's logaichean na duilleige ach bidh cuid a shusbaint ann nach fhaic am poball.'''
+Gheibh rianairean eile air {{SITENAME}} greim fhathast air an t-susbaint fhalaichte agus gabhaidh an sguabadh às a neo-dhèanamh a-rithist san aon eadar-aghaidh mur an deach cuingeachaidhean eile a shuidheachadh.",
+'revdelete-confirm' => "Dearbh gu bheil thu airson seo a dhèanamh, gu bheil thu a' tuigsinn na thachras ri linn agus gu bheil thu a' dèanamh seo a-rèir [[{{MediaWiki:Policy-url}}|a' phoileasaidh]].",
+'revdelete-suppress-text' => "Cha bu chòir dhut mùchadh a chleachdadh '''ach''' ann an suidheachaidhean mar seo:
+* Fiosrachadh a dh'fhaodadh a bhith dìteachail
+* Fiosrachadh pearsanta a tha cearr
+*: ''seòladh taige, àireamhan fòn, àireamhan NI is msaa.''",
+'revdelete-legend' => 'Suidhich cuingeachaidhean na faicsinneachd',
+'revdelete-hide-text' => "Teacsa a' mhùthaidh",
+'revdelete-hide-image' => 'Falaich susbaint an fhaidhle',
+'revdelete-hide-name' => 'Falaich an gnìomh agus an targaid',
+'revdelete-hide-comment' => 'Gearr-chunntas an deasachaidh',
+'revdelete-hide-user' => 'Ainm-cleachdaiche/seòladh IP an deasaiche',
+'revdelete-hide-restricted' => 'Mùch dàta o rianairean agus càch',
 'revdelete-radio-same' => '(na atharraich)',
-'revdelete-radio-set' => 'Dèan seo',
-'revdelete-radio-unset' => 'Na dèan seo',
+'revdelete-radio-set' => 'Ri fhaicinn',
+'revdelete-radio-unset' => 'Falaichte',
+'revdelete-suppress' => 'Mùch dàta o rianairean agus càch',
+'revdelete-unsuppress' => 'Thoir air falbh na bacaidhean air mùthaidhean a chaidh aiseag',
 'revdelete-log' => 'Adhbhar:',
 'revdelete-submit' => 'Cuir air {{PLURAL:$1|an lèirmheas|na lèirmheasan}} a thagh thu',
+'revdelete-success' => "'''Chaidh so-fhaicsinneachd a' mhùthaidh ùrachadh.'''",
+'revdelete-failure' => "'''Cha b' urrainn dhuinn so-fhaicsinneachd a' mhùthaidh ùrachadh:'''
+$1",
+'logdelete-success' => "'''Chaidh faicsinneachd an loga a shuidheachadh.'''",
+'logdelete-failure' => "'''Cha b' urrainn dhuinn faicsinneachd an loga a shuidheachadh:'''
+$1",
 'revdel-restore' => 'mùth follaiseachd',
 'revdel-restore-deleted' => 'mùthaidhean a chaidh a sguabadh às',
 'revdel-restore-visible' => 'mùthaidhean faicsinneach',
 'pagehist' => 'Eachdraidh na duilleige',
+'deletedhist' => 'Eachdraidh a chaidh a sguabadh às',
+'revdelete-hide-current' => "Mearachd a' cur am falach an nì dhen $2, $1: Seo an lèirmheas làithreach. Cha ghabh a chur am falach.",
+'revdelete-show-no-access' => 'Mearachd a\' sealltainn an nì on $2, $1: Tha comharra ann a dh\'innseas gu bheil e "cuingichte".
+Chan eil cothrom agad air.',
+'revdelete-modify-no-access' => 'Mearachd ag atharrachadh an nì on $2, $1: Tha comharra ann a dh\'innseas gu bheil e "cuingichte".
+Chan eil cothrom agad air.',
+'revdelete-modify-missing' => 'Mearachd ag atharrachadh an nì leis an ID $1: Chan eil e san stòr-dàta!',
+'revdelete-no-change' => "'''Rabhadh:''' Bha na roghainnean faicsinneachd a dh'iarr thu aig an nì dhen $2, $1 mu thràth.",
+'revdelete-concurrent-change' => "Mearachd ag atharrachadh an nì on $2, $1: Tha coltas gun deach a staid atharrachadh le cuideigin dìreach nuair a dh'fheuch thusa ri atharrachadh.
+Thoir sùil air na logaichean.",
+'revdelete-only-restricted' => "Mearachd a' cur an nì on $2, $1 am falach: Chan urrainn dhut nithean le rianairean a mhùchadh gun a bhith a' taghadh aon dhe na roghainnean faicsinneachd eile cuideachd.",
+'revdelete-reason-dropdown' => "*Adhbharan cumanta airson sguabadh às rudan
+** Briseadh còrach-lethbhreac
+** Beachd no fiosrachadh pearsanta mì-iomchaidh
+** Ainm-cleachdaiche mì-iomchaidh
+** Fiosrachadh a dh'fhaodadh a bhith dìteachail",
 'revdelete-otherreason' => 'Adhbhar eile/a bharrachd:',
 'revdelete-reasonotherlist' => 'Adhbhar eile',
 'revdelete-edit-reasonlist' => 'Deasaich adhbharan an sguabaidh às',
 'revdelete-offender' => "Ùghdar a' mhùthaidh:",
 
+# Suppression log
+'suppressionlog' => 'Loga nam mùchaidhean',
+'suppressionlogtext' => "Chì thu liosta nan rudan a chaidh a sguabadh às agus a bhacadh gu h-ìosal, a' gabhail a-steach stuth a chaidh fhalach o rianairean. Faic [[Special:BlockList|liosta nam bacaidhean]] airson liosta nan toirmeasgan is bacaidhean beò.",
+
 # History merging
+'mergehistory' => 'Co-aonaich eachdraidhean na duilleige',
+'mergehistory-header' => 'Leigidh an duilleag seo leat na lèirmheasan aig aon duilleag a cho-aonadh le duilleag nas ùire.
+Dèan cinnteach gun glèidh an t-atharrachadh seo leantainneachd eachdraidh na duilleige.',
+'mergehistory-box' => 'Co-aonaich na lèirmheasan aig dà dhuilleag:',
 'mergehistory-from' => 'An duilleag thùsail:',
+'mergehistory-into' => 'An duilleag targaide:',
+'mergehistory-list' => 'Eachdraidh nan deasachaidhean a ghabhas a cho-aonadh',
+'mergehistory-merge' => 'Gabhaidh na lèirmheasan a leanas aig [[:$1]] a cho-aonadh le [[:$2]].
+Cleachd colbh nam putanan-rèidio gus dìreach na lèirmheasan a cho-aonadh a chaidh a chruthachadh aig an àm a chaidh a shònrachadh no roimhe sin.
+Thoir an aire gun dèid an colbh seo ath-shuidheachadh ma chleachdas tu ceanglaichean na seòladaireachd.',
+'mergehistory-go' => 'Seall na deasachaidhean a ghabhas a cho-aonadh',
+'mergehistory-submit' => 'Co-aonaich na lèirmheasan',
+'mergehistory-empty' => 'Chan eil lèirmheas sam bith ann a ghabhas a cho-aonadh.',
+'mergehistory-success' => 'Chaidh $3 {{PLURAL:$3|lèirmheas|lèirmheas|lèirmheasan|lèirmheas}} de [[:$1]] a cho-aonadh dha [[:$2]].',
+'mergehistory-fail' => "Cha ghabh an eachdraidh a cho-aonadh, thoir sùil air paramadairean na duilleige 's an ama.",
+'mergehistory-no-source' => 'Chan eil an tùs-duilleag $1 ann.',
+'mergehistory-no-destination' => 'Chan eil an an duilleag targaide $1 ann.',
+'mergehistory-invalid-source' => "Feumaidh an tùs-duilleag a bhith 'na thiotal dligheach.",
+'mergehistory-invalid-destination' => "Feumaidh an duilleag targaide a bhith 'na thiotal dligheach.",
+'mergehistory-autocomment' => 'Chaidh [[:$1]] a cho-aonadh dha [[:$2]]',
+'mergehistory-comment' => 'Chaidh [[:$1]] a cho-aonadh dha [[:$2]]: $3',
+'mergehistory-same-destination' => 'Chan fhaod an tùs-duilleag is an duilleag targaide a bhith co-ionnann',
 'mergehistory-reason' => 'Adhbhar:',
 
 # Merge log
+'mergelog' => "Loga a' cho-aonaidh",
+'pagemerge-logentry' => 'chaidh [[$1]] a cho-aonadh dha [[$2]] (lèirmheasan suas ri $3)',
 'revertmerge' => 'Dì-aontaich',
 
 # Diffs
@@ -903,6 +1100,7 @@ Feuch is [[Special:Search|lorg duilleagan ùra iomachaidh air an uici]]",
 'compareselectedversions' => 'Dèan coimeas eadar na mùthaidhean a thagh thu',
 'showhideselectedversions' => 'Seall/Falaich na lèirmheasan a thagh thu',
 'editundo' => 'neo-dhèan',
+'diff-empty' => '(Gun diofar eatarra)',
 'diff-multi' => '({{PLURAL:$1|Aon lèirmheas eadar-mheadhanach||$1 lèirmheasan eadar-mheadhanach|$1 lèirmheas eadar-mheadhanach}} le {{PLURAL:$2|aon chleachdaiche|$2 chleachdaiche|$2 cleachdaichean|$2 cleachdaiche}} gun sealltainn)',
 'diff-multi-manyusers' => '({{PLURAL:$1|Aon lèirmheas eadar-mheadhanach||$1 lèirmheasan eadar-mheadhanach|$1 lèirmheas eadar-mheadhanach}} le {{PLURAL:$2|aon chleachdaiche|$2 chleachdaiche|$2 cleachdaichean|$2 cleachdaiche}} gun sealltainn)',
 
@@ -973,8 +1171,6 @@ Faodaidh gum bi inneacsan susbaint {{SITENAME}} tuilleadh 's sean ge-tà.",
 'preferences' => 'Roghainnean',
 'mypreferences' => 'Na roghainnean agam',
 'prefs-edits' => 'Co mheud deasachadh:',
-'prefsnologin' => 'Chan eil thu air clàradh a-steach',
-'prefsnologintext' => 'Feumaidh tu <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} clàradh a-steach]</span> mus urrainn dhut roghainnean cleachdaiche a chur air gleus.',
 'changepassword' => 'Atharraich facal-faire',
 'prefs-skin' => 'Bian',
 'skin-preview' => 'Ro-shealladh',
@@ -988,6 +1184,9 @@ Faodaidh gum bi inneacsan susbaint {{SITENAME}} tuilleadh 's sean ge-tà.",
 'prefs-watchlist' => 'An clàr-faire',
 'prefs-watchlist-days' => "Co mheud latha a sheallar air a' chlàr-fhaire:",
 'prefs-watchlist-days-max' => "{{PLURAL:$1|latha|latha|làithean|latha}} air a' char as motha",
+'prefs-watchlist-edits-max' => 'Àireamh as motha: 1000',
+'prefs-watchlist-token' => "Tòcan a' chlàir-fhaire:",
+'prefs-misc' => 'Measgachadh',
 'prefs-resetpass' => 'Atharraich am facal-faire',
 'prefs-changeemail' => 'Atharraich am post-d',
 'prefs-setemail' => 'Suidhich seòladh puist-d',
@@ -995,16 +1194,20 @@ Faodaidh gum bi inneacsan susbaint {{SITENAME}} tuilleadh 's sean ge-tà.",
 'prefs-rendering' => 'Coltas',
 'saveprefs' => 'Sàbhail',
 'resetprefs' => 'Falamhaich atharrachaidhean nach deach a shàbhaladh fhathast',
-'restoreprefs' => 'Aisig na roghainnean bunaiteach uile',
+'restoreprefs' => 'Aisig na roghainnean bunaiteach uile (anns gach earrann)',
 'prefs-editing' => "A' deasachadh",
 'rows' => 'Sreathan',
 'columns' => 'Colbhan',
 'searchresultshead' => 'Lorg',
 'stub-threshold-disabled' => 'À comas',
+'recentchangesdays-max' => "{{PLURAL:$1|latha|latha|làithean|latha}} air a' char as motha",
+'recentchangescount' => 'Uiread a dheasachaidhean a thèid a shealltainn a ghnàth:',
 'savedprefs' => 'Tha na roghainnean agad air an sàbhaladh.',
 'timezonelegend' => 'Roinn-tìde:',
 'localtime' => 'An t-àm ionadail:',
+'timezoneuseserverdefault' => 'Cleachd bun-roghainn na h-Uicipeid ($1)',
 'servertime' => 'Àm an fhrithealaichte:',
+'guesstimezone' => 'Lìon on bhrabhsair',
 'timezoneregion-africa' => 'Afraga',
 'timezoneregion-america' => 'Aimeireaga',
 'timezoneregion-antarctica' => 'An Antartaig',
@@ -1015,6 +1218,8 @@ Faodaidh gum bi inneacsan susbaint {{SITENAME}} tuilleadh 's sean ge-tà.",
 'timezoneregion-europe' => 'An Roinn-Eòrpa',
 'timezoneregion-indian' => 'An Cuan Innseanach',
 'timezoneregion-pacific' => 'An Cuan Sèimh',
+'allowemail' => 'Ceadaich post-d o chleachdaichean eile',
+'prefs-searchoptions' => 'Lorg',
 'prefs-namespaces' => 'Namespaces',
 'default' => 'an roghainn bhunaiteach',
 'prefs-files' => 'Faidhlichean',
@@ -1038,10 +1243,10 @@ Faodaidh gum bi inneacsan susbaint {{SITENAME}} tuilleadh 's sean ge-tà.",
 Thoir sùil air na tagaichean HTML.',
 'badsiglength' => 'Tha an t-earr-sgrìobhadh agad ro fhada.
 Chan fhaod e a bhith nas fhaide na $1 {{PLURAL:$1|charactar|charactar|caractaran|caractar}}.',
-'yourgender' => 'Gnè:',
-'gender-unknown' => 'Gun innse',
-'gender-male' => 'Fireann',
-'gender-female' => 'Boireann',
+'yourgender' => "Dè a' ghnè a tha annad:",
+'gender-unknown' => "B' fhearr leam gun a bhith 'ga leigeil ris",
+'gender-male' => 'Deasaichidh e duilleagan na h-Uicipeid',
+'gender-female' => 'Deasaichidh i duilleagan na h-Uicipeid',
 'email' => 'Post-d:',
 'prefs-help-email' => "Chan leig thu leas post-dealain a chur ann ach bidh feum air ma dhìochuimhnicheas tu am facal-faire agad 's ma dh'iarras tu fear ùr.",
 'prefs-help-email-others' => "'S urrainn dhut leigeil le daoine eile post-dealain a chur thugad tro cheangal air an duilleag agad.
@@ -1052,7 +1257,9 @@ Chan fhaicear an seòladh fhèin nuair a chuireas cuideigin post-dealain thugad.
 'prefs-signature' => 'Earr-sgrìobhadh',
 'prefs-dateformat' => "Fòrmat a' chinn-là",
 'prefs-timeoffset' => 'Diofar ama',
-'prefs-advancedediting' => 'Roghainnean adhartach',
+'prefs-advancedediting' => 'Roghainnean coitcheann',
+'prefs-editor' => 'Deasaiche',
+'prefs-preview' => 'Ro-shealladh',
 'prefs-advancedrc' => 'Roghainnean adhartach',
 'prefs-advancedrendering' => 'Roghainnean adhartach',
 'prefs-advancedsearchoptions' => 'Roghainnean adhartach',
@@ -1060,6 +1267,7 @@ Chan fhaicear an seòladh fhèin nuair a chuireas cuideigin post-dealain thugad.
 'prefs-displayrc' => 'Roghainnean taisbeanaidh',
 'prefs-displaysearchoptions' => 'Roghainnean taisbeanaidh',
 'prefs-displaywatchlist' => 'Roghainnean taisbeanaidh',
+'prefs-tokenwatchlist' => 'Tòcan',
 'prefs-diffs' => 'Diffs',
 
 # User preference: email validation using jQuery
@@ -1151,7 +1359,7 @@ Chan fhaicear an seòladh fhèin nuair a chuireas cuideigin post-dealain thugad.
 'minoreditletter' => 'b',
 'newpageletter' => 'Ù',
 'boteditletter' => 'bt',
-'rc-enhanced-expand' => 'Seall am mion-fhiosrachadh (feumaidh seo JavaScript)',
+'rc-enhanced-expand' => 'Seall am mion-fhiosrachadh',
 'rc-enhanced-hide' => 'Cuir am mion-fhiosrachadh am falach',
 
 # Recent changes linked
@@ -1335,9 +1543,11 @@ Seall air $2 airson clàr de dhuilleagan a chaidh a sguabadh às o chionn ghoiri
 'deleteotherreason' => 'Adhbhar eile/a bharrachd:',
 'deletereasonotherlist' => 'Adhbhar eile',
 'deletereason-dropdown' => "*Adhbharan cumanta airson sguabadh às
-** Dh'iarr an t-ùghdar e
+** Spama
+** Milleadh
 ** Tha e a' briseadh na còrach-lethbhreac
-** Milleadh",
+** Dh'iarr an t-ùghdar e
+** Ath-threòrachadh briste",
 'delete-edit-reasonlist' => 'Deasaich adhbharan sguabadh às',
 
 # Rollback
@@ -1395,7 +1605,7 @@ Seo roghainnean làithreach na duilleige '''$1''':",
 'contributions' => "Mùthaidhean a' {{GENDER:$1|chleachdaiche}}",
 'contributions-title' => 'Mùthaidhean a rinn $1',
 'mycontris' => 'Mùthaidhean',
-'contribsub2' => 'Do $1 ($2)',
+'contribsub2' => 'Airson {{GENDER:$3|$1}} ($2)',
 'uctop' => '(làithreach)',
 'month' => 'On mhìos (agus na bu tràithe):',
 'year' => 'On bhliadhna (agus na bu tràithe):',
@@ -1502,7 +1712,7 @@ Bidh agad ris an co-aontachadh a làimh.'''",
 'allmessagesname' => 'Ainm',
 'allmessagesdefault' => 'Teacsa bunaiteach na teachdaireachd',
 'allmessagestext' => 'Seo liosta de theachdaireachdan an t-siostaim a tha ri làimh ann an namespace MediaWiki.
-Tadhail air [//www.mediawiki.org/wiki/Localisation Ionadaileadh MediaWiki] is [//translatewiki.net translatewiki.net] ma tha thu airson pàirt a ghabhail ann an ionadaileadh MediaWiki.',
+Tadhail air [https://www.mediawiki.org/wiki/Localisation Ionadaileadh MediaWiki] is [//translatewiki.net translatewiki.net] ma tha thu airson pàirt a ghabhail ann an ionadaileadh MediaWiki.',
 
 # Thumbnails
 'thumbnail-more' => 'Meudaich',
@@ -1621,7 +1831,7 @@ Bidh an fheadhainn eile falaichte a ghnàth.
 
 # External editor support
 'edit-externally' => 'Deasaich am faidhle le prògram on taobh a-muigh',
-'edit-externally-help' => '(Seall air [//www.mediawiki.org/wiki/Manual:External_editors mìneachadh an t-suidheachaidh] airson barrachd fiosrachaidh)',
+'edit-externally-help' => '(Seall air [https://www.mediawiki.org/wiki/Manual:External_editors mìneachadh an t-suidheachaidh] airson barrachd fiosrachaidh)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'a h-uile',
index a170f92..cd9bc27 100644 (file)
@@ -68,12 +68,12 @@ $dateFormats = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Usuarios_activos' ),
        'Allmessages'               => array( 'Todas_as_mensaxes' ),
+       'AllMyUploads'              => array( 'Todas_as_miñas_cargas', 'Todos_os_meus_ficheiros' ),
        'Allpages'                  => array( 'Todas_as_páxinas' ),
        'Ancientpages'              => array( 'Páxinas_máis_antigas' ),
        'Badtitle'                  => array( 'Título_incorrecto' ),
        'Blankpage'                 => array( 'Baleirar_a_páxina' ),
        'Block'                     => array( 'Bloquear', 'Bloquear_o_enderezo_IP', 'Bloquear_o_usuario' ),
-       'Blockme'                   => array( 'Bloquearme' ),
        'Booksources'               => array( 'Fontes_bibliográficas' ),
        'BrokenRedirects'           => array( 'Redireccións_rotas' ),
        'Categories'                => array( 'Categorías' ),
@@ -85,10 +85,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crear_unha_conta' ),
        'Deadendpages'              => array( 'Páxinas_mortas' ),
        'DeletedContributions'      => array( 'Contribucións_borradas' ),
-       'Disambiguations'           => array( 'Homónimos' ),
        'DoubleRedirects'           => array( 'Redireccións_dobres' ),
        'EditWatchlist'             => array( 'Editar_a_lista_de_vixilancia' ),
        'Emailuser'                 => array( 'Correo_electrónico' ),
+       'ExpandTemplates'           => array( 'Expandir_os_modelos' ),
        'Export'                    => array( 'Exportar' ),
        'Fewestrevisions'           => array( 'Páxinas_con_menos_revisións' ),
        'FileDuplicateSearch'       => array( 'Procura_de_ficheiros_duplicados' ),
@@ -137,6 +137,7 @@ $specialPageAliases = array(
        'Recentchanges'             => array( 'Cambios_recentes' ),
        'Recentchangeslinked'       => array( 'Cambios_relacionados' ),
        'Redirect'                  => array( 'Redirección' ),
+       'ResetTokens'               => array( 'Restablecer_os_pases' ),
        'Revisiondelete'            => array( 'Revisións_borradas' ),
        'Search'                    => array( 'Procurar' ),
        'Shortpages'                => array( 'Páxinas_curtas' ),
@@ -175,7 +176,7 @@ $magicWords = array(
        'forcetoc'                  => array( '0', '__FORZAROÍNDICE__', '__FORCARTDC__', '__FORCARSUMARIO__', '__FORÇARTDC__', '__FORÇARSUMÁRIO__', '__FORCETOC__' ),
        'toc'                       => array( '0', '__ÍNDICE__', '__TDC__', '__SUMÁRIO__', '__SUMARIO__', '__TOC__' ),
        'noeditsection'             => array( '0', '__SECCIÓNSNONEDITABLES__', '__NÃOEDITARSEÇÃO__', '__SEMEDITARSEÇÃO__', '__NAOEDITARSECAO__', '__SEMEDITARSECAO__', '__NOEDITSECTION__' ),
-       'currentmonth'              => array( '1', 'MESACTUAL', 'MESATUAL', 'MESATUAL2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'currentmonth'              => array( '1', 'MESACTUAL', 'MESACTUAL2', 'MESATUAL', 'MESATUAL2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
        'currentmonth1'             => array( '1', 'MESACTUAL1', 'MESATUAL1', 'CURRENTMONTH1' ),
        'currentmonthname'          => array( '1', 'NOMEDOMESACTUAL', 'NOMEDOMESATUAL', 'CURRENTMONTHNAME' ),
        'currentmonthabbrev'        => array( '1', 'ABREVIATURADOMESACTUAL', 'MESATUALABREV', 'MESATUALABREVIADO', 'ABREVIATURADOMESATUAL', 'CURRENTMONTHABBREV' ),
@@ -185,7 +186,7 @@ $magicWords = array(
        'currentyear'               => array( '1', 'ANOACTUAL', 'ANOATUAL', 'CURRENTYEAR' ),
        'currenttime'               => array( '1', 'DATAEHORAACTUAIS', 'HORARIOATUAL', 'CURRENTTIME' ),
        'currenthour'               => array( '1', 'HORAACTUAL', 'HORAATUAL', 'CURRENTHOUR' ),
-       'localmonth'                => array( '1', 'MESLOCAL', 'LOCALMONTH', 'LOCALMONTH2' ),
+       'localmonth'                => array( '1', 'MESLOCAL', 'MESLOCAL2', 'LOCALMONTH', 'LOCALMONTH2' ),
        'localmonth1'               => array( '1', 'MESLOCAL1', 'LOCALMONTH1' ),
        'localmonthname'            => array( '1', 'NOMEDOMESLOCAL', 'LOCALMONTHNAME' ),
        'localmonthabbrev'          => array( '1', 'ABREVIATURADOMESLOCAL', 'MESLOCALABREV', 'MESLOCALABREVIADO', 'LOCALMONTHABBREV' ),
@@ -204,10 +205,15 @@ $magicWords = array(
        'numberofviews'             => array( '1', 'NÚMERODEVISITAS', 'NUMERODEEXIBICOES', 'NÚMERODEEXIBIÇÕES', 'NUMBEROFVIEWS' ),
        'pagename'                  => array( '1', 'NOMEDAPÁXINA', 'NOMEDAPAGINA', 'NOMEDAPÁGINA', 'PAGENAME' ),
        'namespace'                 => array( '1', 'ESPAZODENOMES', 'DOMINIO', 'DOMÍNIO', 'ESPACONOMINAL', 'ESPAÇONOMINAL', 'NAMESPACE' ),
+       'namespacenumber'           => array( '1', 'NÚMERODOESPAZODENOMES', 'NAMESPACENUMBER' ),
+       'talkspace'                 => array( '1', 'ESPAZODECONVERSA', 'PAGINADEDISCUSSAO', 'PÁGINADEDISCUSSÃO', 'TALKSPACE' ),
+       'subjectspace'              => array( '1', 'ESPAZODECONTIDO', 'PAGINADECONTEUDO', 'PAGINADECONTEÚDO', 'SUBJECTSPACE', 'ARTICLESPACE' ),
        'fullpagename'              => array( '1', 'NOMECOMPLETODAPÁXINA', 'NOMECOMPLETODAPAGINA', 'NOMECOMPLETODAPÁGINA', 'FULLPAGENAME' ),
        'subpagename'               => array( '1', 'NOMEDASUBPÁXINA', 'NOMEDASUBPAGINA', 'NOMEDASUBPÁGINA', 'SUBPAGENAME' ),
+       'rootpagename'              => array( '1', 'NOMEDAPÁXINARAÍZ', 'ROOTPAGENAME' ),
        'basepagename'              => array( '1', 'NOMEDAPÁXINABASE', 'NOMEDAPAGINABASE', 'NOMEDAPÁGINABASE', 'BASEPAGENAME' ),
        'talkpagename'              => array( '1', 'NOMEDAPÁXINADECONVERSA', 'NOMEDAPAGINADEDISCUSSAO', 'NOMEDAPÁGINADEDISCUSSÃO', 'TALKPAGENAME' ),
+       'subjectpagename'           => array( '1', 'NOMEDAPÁXINADECONTIDO', 'NOMEDAPAGINADECONTEUDO', 'NOMEDAPÁGINADECONTEÚDO', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
        'img_thumbnail'             => array( '1', 'miniatura', 'miniaturadaimaxe', 'miniaturadaimagem', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'miniatura=$1', 'miniaturadaimaxe=$1', 'miniaturadaimagem=$1', 'thumbnail=$1', 'thumb=$1' ),
        'img_right'                 => array( '1', 'dereita', 'direita', 'right' ),
@@ -216,8 +222,10 @@ $magicWords = array(
        'img_center'                => array( '1', 'centro', 'center', 'centre' ),
        'img_framed'                => array( '1', 'conmarco', 'conbordo', 'marco', 'commoldura', 'comborda', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'senmarco', 'senbordo', 'semmoldura', 'semborda', 'frameless' ),
-       'img_page'                  => array( '1', 'páxina=$1', 'páxina $1', 'página=$1', 'página $1', 'page=$1', 'page $1' ),
+       'img_page'                  => array( '1', 'páxina=$1', 'páxina_$1', 'página=$1', 'página $1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'arribaádereita', 'arribaádereita=$1', 'arribaádereita_$1', 'superiordireito', 'superiordireito=$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'bordo', 'borda', 'border' ),
+       'img_baseline'              => array( '1', 'liñadebase', 'linhadebase', 'baseline' ),
        'img_top'                   => array( '1', 'arriba', 'acima', 'top' ),
        'img_text_top'              => array( '1', 'texto-arriba', 'text-top' ),
        'img_middle'                => array( '1', 'medio', 'meio', 'middle' ),
@@ -226,16 +234,38 @@ $magicWords = array(
        'img_link'                  => array( '1', 'ligazón=$1', 'ligação=$1', 'link=$1' ),
        'img_class'                 => array( '1', 'clase=$1', 'class=$1' ),
        'sitename'                  => array( '1', 'NOMEDOSITIO', 'NOMEDOSITE', 'NOMEDOSÍTIO', 'SITENAME' ),
-       'localurl'                  => array( '0', 'URLLOCAL', 'LOCALURL:' ),
+       'localurl'                  => array( '0', 'URLLOCAL:', 'LOCALURL:' ),
        'articlepath'               => array( '0', 'RUTADOARTIGO', 'ARTICLEPATH' ),
        'pageid'                    => array( '0', 'IDDAPÁXINA', 'PAGEID' ),
        'server'                    => array( '0', 'SERVIDOR', 'SERVER' ),
        'servername'                => array( '0', 'NOMEDOSERVIDOR', 'SERVERNAME' ),
+       'scriptpath'                => array( '0', 'RUTADAESCRITURA', 'CAMINHODOSCRIPT', 'SCRIPTPATH' ),
+       'stylepath'                 => array( '0', 'RUTADOESTILO', 'STYLEPATH' ),
        'grammar'                   => array( '0', 'GRAMÁTICA:', 'GRAMMAR:' ),
        'gender'                    => array( '0', 'SEXO:', 'GENERO', 'GÊNERO', 'GENDER:' ),
-       'displaytitle'              => array( '1', 'AMOSAROTÍTULO', 'EXIBETITULO', 'EXIBETÍTULO', 'DISPLAYTITLE' ),
+       'currentweek'               => array( '1', 'SEMANAACTUAL', 'SEMANAATUAL', 'CURRENTWEEK' ),
+       'localweek'                 => array( '1', 'SEMANALOCAL', 'LOCALWEEK' ),
+       'revisionid'                => array( '1', 'IDDAREVISIÓN', 'IDDAREVISAO', 'IDDAREVISÃO', 'REVISIONID' ),
+       'revisionday'               => array( '1', 'DÍADAREVISIÓN', 'DIADAREVISAO', 'DIADAREVISÃO', 'REVISIONDAY' ),
+       'revisionday2'              => array( '1', 'DÍADAREVISIÓN2', 'DIADAREVISAO2', 'DIADAREVISÃO2', 'REVISIONDAY2' ),
+       'revisionmonth'             => array( '1', 'MESDAREVISIÓN', 'MESDAREVISAO', 'MÊSDAREVISÃO', 'REVISIONMONTH' ),
+       'revisionmonth1'            => array( '1', 'MESDAREVISIÓN1', 'REVISIONMONTH1' ),
+       'revisionyear'              => array( '1', 'ANODAREVISIÓN', 'ANODAREVISAO', 'ANODAREVISÃO', 'REVISIONYEAR' ),
+       'revisiontimestamp'         => array( '1', 'DATAEHORADAREVISIÓN', 'REVISIONTIMESTAMP' ),
+       'revisionuser'              => array( '1', 'USUARIODAREVISIÓN', 'USUARIODAREVISAO', 'USUÁRIODAREVISÃO', 'REVISIONUSER' ),
+       'fullurl'                   => array( '0', 'URLCOMPLETO:', 'FULLURL:' ),
+       'canonicalurl'              => array( '0', 'URLCANÓNICO:', 'CANONICALURL:' ),
+       'lcfirst'                   => array( '0', 'PRIMEIRAMINÚSCULA:', 'PRIMEIRAMINUSCULA:', 'LCFIRST:' ),
+       'ucfirst'                   => array( '0', 'PRIMEIRAMAIÚSCULA:', 'PRIMEIRAMAIUSCULA:', 'UCFIRST:' ),
+       'lc'                        => array( '0', 'MINÚSCULA:', 'MINUSCULA', 'MINÚSCULA', 'MINUSCULAS', 'MINÚSCULAS', 'LC:' ),
+       'uc'                        => array( '0', 'MAIÚSCULA:', 'MAIUSCULA', 'MAIÚSCULA', 'MAIUSCULAS', 'MAIÚSCULAS', 'UC:' ),
+       'raw'                       => array( '0', 'ENBRUTO:', 'RAW:' ),
+       'displaytitle'              => array( '1', 'AMOSAROTÍTULO', 'MOSTRAROTÍTULO', 'EXIBETITULO', 'EXIBETÍTULO', 'DISPLAYTITLE' ),
        'newsectionlink'            => array( '1', '__LIGAZÓNDANOVASECCIÓN__', '__LINKDENOVASECAO__', '__LINKDENOVASEÇÃO__', '__LIGACAODENOVASECAO__', '__LIGAÇÃODENOVASEÇÃO__', '__NEWSECTIONLINK__' ),
+       'currentversion'            => array( '1', 'VERSIÓNACTUAL', 'REVISAOATUAL', 'REVISÃOATUAL', 'CURRENTVERSION' ),
        'language'                  => array( '0', '#LINGUA:', '#IDIOMA:', '#LANGUAGE:' ),
+       'contentlanguage'           => array( '1', 'LINGUADOCONTIDO', 'IDIOMADOCONTIDO', 'IDIOMADOCONTEUDO', 'IDIOMADOCONTEÚDO', 'CONTENTLANGUAGE', 'CONTENTLANG' ),
+       'pagesinnamespace'          => array( '1', 'PÁXINASNOESPAZODENOMES:', 'PAGINASNOESPACONOMINAL', 'PÁGINASNOESPAÇONOMINAL', 'PAGINASNODOMINIO', 'PÁGINASNODOMÍNIO', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
        'numberofadmins'            => array( '1', 'NÚMERODEADMINISTRADORES', 'NUMERODEADMINISTRADORES', 'NUMBEROFADMINS' ),
        'special'                   => array( '0', 'especial', 'special' ),
        'defaultsort'               => array( '1', 'ORDENAR:', 'ORDENACAOPADRAO', 'ORDENAÇÃOPADRÃO', 'ORDEMPADRAO', 'ORDEMPADRÃO', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
@@ -244,6 +274,7 @@ $magicWords = array(
        'pagesincategory'           => array( '1', 'PÁXINASNACATEGORÍA', 'PAGINASNACATEGORIA', 'PÁGINASNACATEGORIA', 'PAGINASNACAT', 'PÁGINASNACAT', 'PAGESINCATEGORY', 'PAGESINCAT' ),
        'pagesize'                  => array( '1', 'TAMAÑODAPÁXINA', 'TAMANHODAPAGINA', 'TAMANHODAPÁGINA', 'PAGESIZE' ),
        'url_path'                  => array( '0', 'RUTA', 'PATH' ),
+       'url_query'                 => array( '0', 'PESCUDA', 'QUERY' ),
        'pagesincategory_all'       => array( '0', 'todos', 'all' ),
        'pagesincategory_pages'     => array( '0', 'páxinas', 'pages' ),
        'pagesincategory_subcats'   => array( '0', 'subcategorías', 'subcats' ),
@@ -527,12 +558,10 @@ $1',
 'ok' => 'Aceptar',
 'retrievedfrom' => 'Traído desde "$1"',
 'youhavenewmessages' => 'Ten $1 ($2).',
-'newmessageslink' => 'mensaxes novas',
-'newmessagesdifflink' => 'diferenzas coa revisión anterior',
 'youhavenewmessagesfromusers' => 'Ten $1 {{PLURAL:$3|doutro usuario|de $3 usuarios}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ten $1 de moitos usuarios ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|unha mensaxe nova|mensaxes novas}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|última modificación|últimas modificacións}}',
+'newmessageslinkplural' => '{{PLURAL:$1|unha mensaxe nova|999=mensaxes novas}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|última modificación|999=últimas modificacións}}',
 'youhavenewmessagesmulti' => 'Ten mensaxes novas en $1',
 'editsection' => 'editar',
 'editold' => 'editar',
@@ -561,7 +590,7 @@ $1',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Páxina',
-'nstab-user' => 'Páxina de {{GENDER:{{#titleparts:{{BASEPAGENAME}}|1}}|usuario|usuaria}}',
+'nstab-user' => 'Páxina de {{GENDER:{{ROOTPAGENAME}}|usuario|usuaria}}',
 'nstab-media' => 'Páxina multimedia',
 'nstab-special' => 'Páxina especial',
 'nstab-project' => 'Páxina do proxecto',
@@ -664,7 +693,8 @@ O administrador que bloqueou o repositorio achegou este motivo: "$3".',
 'invalidtitle-knownnamespace' => 'Título inválido co espazo de nomes "$2" e o texto "$3"',
 'invalidtitle-unknownnamespace' => 'Título inválido cun número de espazo de nomes, $1, descoñecido e o texto "$2"',
 'exception-nologin' => 'Non accedeu ao sistema',
-'exception-nologin-text' => 'Esta páxina ou acción necesita que vostede acceda ao sistema neste wiki.',
+'exception-nologin-text' => '[[Special:Userlogin|Acceda ao sistema]] para poder realizar esa acción ou acceder a esa páxina.',
+'exception-nologin-text-manual' => 'Debe $1 para poder realizar esa acción ou acceder a esa páxina.',
 
 # Virus scanner
 'virus-badscanner' => "Configuración errónea: escáner de virus descoñecido: ''$1''",
@@ -711,7 +741,7 @@ Non esqueza personalizar as súas [[Special:Preferences|preferencias de {{SITENA
 'gotaccount' => 'Xa ten unha conta? $1.',
 'gotaccountlink' => 'Acceda ao sistema',
 'userlogin-resetlink' => 'Esqueceu os seus datos de rexistro?',
-'userlogin-resetpassword-link' => 'Restablecer o seu contrasinal',
+'userlogin-resetpassword-link' => 'Esqueceu o contrasinal?',
 'helplogin-url' => 'Help:Rexistro',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Axuda co rexistro]]',
 'userlogin-loggedin' => 'Xa accedeu ao sistema como {{GENDER:$1|$1}}.
@@ -768,7 +798,7 @@ Por favor, inténteo de novo.',
 'passwordtooshort' => 'Os contrasinais deben conter, como mínimo, {{PLURAL:$1|1 carácter|$1 caracteres}}.',
 'password-name-match' => 'O seu contrasinal debe ser diferente do seu nome de usuario.',
 'password-login-forbidden' => 'O uso deste nome de usuario e contrasinal foi prohibido.',
-'mailmypassword' => 'Enviádeme un contrasinal novo por correo',
+'mailmypassword' => 'Restablecer o contrasinal',
 'passwordremindertitle' => 'Novo contrasinal temporal para {{SITENAME}}',
 'passwordremindertext' => 'Alguén (probablemente vostede, desde o enderezo IP $1) solicitou un novo
 contrasinal para acceder a {{SITENAME}} ($4). Un contrasinal temporal para o usuario
@@ -784,15 +814,16 @@ continuar a utilizar o seu contrasinal vello.',
 'passwordsent' => 'Enviouse un contrasinal novo ao enderezo de correo electrónico rexistrado de "$1".
 Por favor, acceda ao sistema de novo tras recibilo.',
 'blocked-mailpassword' => 'O seu enderezo IP está bloqueado e ten restrinxida a edición de artigos. Tampouco se lle permite usar a función de recuperación do contrasinal para evitar abusos do sistema.',
-'eauthentsent' => 'Envióuselle un correo electrónico de confirmación ao enderezo mencionado.
+'eauthentsent' => 'Envióuselle un correo electrónico de confirmación ao enderezo especificado.
 Antes de que se lle envíe calquera outro correo a esta conta terá que seguir as instrucións que aparecen nesa mensaxe para confirmar que a conta é realmente súa.',
 'throttled-mailpassword' => 'Enviouse un correo electrónico de restablecemento do contrasinal {{PLURAL:$1|na última hora|nas últimas $1 horas}}.
 Para evitar o abuso do sistema só se enviará unha mensaxe de restablecemento cada {{PLURAL:$1|hora|$1 horas}}.',
 'mailerror' => 'Produciuse un erro ao enviar o correo electrónico: $1',
 'acct_creation_throttle_hit' => 'Alguén que visitou este wiki co seu enderezo IP creou, no último día, {{PLURAL:$1|unha conta|$1 contas}}, que é o máximo permitido neste período de tempo.
 Como resultado, os visitantes que usen este enderezo IP non poden crear máis contas nestes intres.',
-'emailauthenticated' => 'O seu enderezo de correo electrónico foi autenticado o $2 ás $3.',
-'emailnotauthenticated' => 'O seu enderezo de correo electrónico aínda <strong>non foi autenticado</strong>. Non se enviou ningunha mensaxe por algunha das seguintes razóns.',
+'emailauthenticated' => 'O seu enderezo de correo electrónico foi confirmado o $2 ás $3.',
+'emailnotauthenticated' => 'O seu enderezo de correo electrónico aínda non foi confirmado.
+Non se enviará ningunha mensaxe por ningunha das seguintes características.',
 'noemailprefs' => 'Especifique un enderezo de correo electrónico se quere que funcione esta opción.',
 'emailconfirmlink' => 'Confirmar o enderezo de correo electrónico',
 'invalidemailaddress' => 'Non se pode aceptar o enderezo de correo electrónico porque semella ter un formato incorrecto.
@@ -842,7 +873,7 @@ Pode ser que xa cambiase o seu contrasinal ou que solicitase un novo contrasinal
 # Special:PasswordReset
 'passwordreset' => 'Restablecer o contrasinal',
 'passwordreset-text-one' => 'Encha este formulario para restablecer o seu contrasinal.',
-'passwordreset-text-many' => '{{PLURAL:$1|Encha un dos campos para restablecer o seu contrasinal.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Encha un dos campos para recibir por correo electrónico un contrasinal temporal.}}',
 'passwordreset-legend' => 'Restablecer o contrasinal',
 'passwordreset-disabled' => 'O restablecemento de contrasinais está desactivado neste wiki.',
 'passwordreset-emaildisabled' => 'As funcións do correo electrónico están desactivadas neste wiki.',
@@ -1233,19 +1264,20 @@ función, a revisión especificada non existe ou está intentando agochar a revi
 'revdelete-text' => "'''As revisións borradas seguirán aparecendo no historial da páxina e nos rexistros, pero partes do seu contido serán inaccesibles de cara ao público.'''
 Os demais administradores de {{SITENAME}} poderán acceder ao contido agochado e poderán restaurar a páxina de novo a través desta mesma interface, a non ser que se estableza algunha restrición adicional.",
 'revdelete-confirm' => 'Por favor, confirme que quere levar a cabo esta acción, que comprende as consecuencias e que o fai de acordo [[{{MediaWiki:Policy-url}}|coas políticas]].',
-'revdelete-suppress-text' => "A eliminación '''só''' debería ser usada nos seguintes casos:
+'revdelete-suppress-text' => "A eliminación '''unicamente''' debería utilizarse nos seguintes casos:
+* Información potencialmente difamatoria
 * Información persoal inapropiada
-*: ''domicilios e números de teléfono, números da seguridade social, etc.''",
+*: ''domicilios e números de teléfono, números da seguridade social etc.''",
 'revdelete-legend' => 'Aplicar restricións de visibilidade',
-'revdelete-hide-text' => 'Agochar o texto da revisión',
+'revdelete-hide-text' => 'Texto da revisión',
 'revdelete-hide-image' => 'Agochar o contido do ficheiro',
 'revdelete-hide-name' => 'Agochar a acción e o destino',
-'revdelete-hide-comment' => 'Agochar o resumo de edición',
-'revdelete-hide-user' => 'Agochar o nome de usuario ou o enderezo IP do editor',
+'revdelete-hide-comment' => 'Resumo de edición',
+'revdelete-hide-user' => 'Nome de usuario ou enderezo IP do editor',
 'revdelete-hide-restricted' => 'Eliminar os datos da vista dos administradores así coma da doutros',
 'revdelete-radio-same' => '(non cambiar)',
-'revdelete-radio-set' => 'Si',
-'revdelete-radio-unset' => 'Non',
+'revdelete-radio-set' => 'Agochado',
+'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => 'Eliminar os datos da vista dos administradores así coma da doutros',
 'revdelete-unsuppress' => 'Retirar as restricións sobre as revisións restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1402,9 +1434,8 @@ Note que os seus índices do contido de {{SITENAME}} poden estar desactualizados
 'preferences' => 'Preferencias',
 'mypreferences' => 'Preferencias',
 'prefs-edits' => 'Número de edicións:',
-'prefsnologin' => 'Non accedeu ao sistema',
-'prefsnologintext' => 'Debe <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} acceder ao sistema]</span> para modificar as preferencias de usuario.',
-'changepassword' => 'Cambiar o meu contrasinal',
+'prefsnologintext2' => 'Debe $1 para definir as preferencias de usuario.',
+'changepassword' => 'Cambiar o contrasinal',
 'prefs-skin' => 'Aparencia',
 'skin-preview' => 'Vista previa',
 'datedefault' => 'Ningunha preferencia',
@@ -1444,10 +1475,10 @@ Note que os seus índices do contido de {{SITENAME}} poden estar desactualizados
 Calquera persoa que a saiba poderá ler a súa lista de vixilancia; non comparta esta clave.
 [[Special:ResetTokens|Prema aquí se necesita restablecela]].',
 'savedprefs' => 'Gardáronse as súas preferencias.',
-'timezonelegend' => 'Zona horaria:',
+'timezonelegend' => 'Fuso horario:',
 'localtime' => 'Hora local:',
 'timezoneuseserverdefault' => 'Usar a hora do servidor por defecto ($1)',
-'timezoneuseoffset' => 'Outra (especifique o desprazamento)',
+'timezoneuseoffset' => 'Outro (especifique o desprazamento)',
 'timezoneoffset' => 'Desprazamento¹:',
 'servertime' => 'Hora do servidor:',
 'guesstimezone' => 'Encher desde o navegador',
@@ -1583,7 +1614,7 @@ Se escolle dalo utilizarase para atribuírlle o seu traballo.',
 'right-move-rootuserpages' => 'Mover páxinas de usuario raíz',
 'right-movefile' => 'Mover ficheiros',
 'right-suppressredirect' => 'Non crear unha redirección dende o nome vello ao mover unha páxina',
-'right-upload' => 'Cargar ficheiros',
+'right-upload' => 'Subir ficheiros',
 'right-reupload' => 'Sobrescribir ficheiros existentes',
 'right-reupload-own' => 'Sobrescribir un ficheiro existente cargado polo mesmo usuario',
 'right-reupload-shared' => 'Sobrescribir localmente ficheiros do repositorio multimedia',
@@ -1703,6 +1734,9 @@ Se escolle dalo utilizarase para atribuírlle o seu traballo.',
 'recentchanges-label-minor' => 'Esta é unha edición pequena',
 'recentchanges-label-bot' => 'Esta edición foi realizada por un bot',
 'recentchanges-label-unpatrolled' => 'Esta edición aínda non foi comprobada',
+'recentchanges-label-plusminus' => 'O tamaño da páxina variou este número de bytes',
+'recentchanges-legend-newpage' => '(véxase tamén a [[Special:NewPages|lista de páxinas novas]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "A continuación {{PLURAL:$1|móstrase '''1''' cambio|móstranse os últimos '''$1''' cambios}} {{PLURAL:$2|no último día|nos últimos '''$2''' días}} ata o $4 ás $5.",
 'rcnotefrom' => "A continuación móstranse os cambios feitos desde o '''$3''' ás '''$4''' (móstranse '''$1''' como máximo).",
 'rclistfrom' => 'Mostrar os cambios novos desde o $1',
@@ -1740,8 +1774,8 @@ As páxinas da súa [[Special:Watchlist|lista de vixilancia]] aparecen en '''neg
 'recentchangeslinked-to' => 'Mostrar os cambios relacionados das páxinas que ligan coa dada',
 
 # Upload
-'upload' => 'Cargar un ficheiro',
-'uploadbtn' => 'Cargar o ficheiro',
+'upload' => 'Subir un ficheiro',
+'uploadbtn' => 'Subir o ficheiro',
 'reuploaddesc' => 'Cancelar a carga e volver ao formulario de carga',
 'upload-tryagain' => 'Enviar a descrición do ficheiro modificada',
 'uploadnologin' => 'Non accedeu ao sistema',
@@ -2034,7 +2068,7 @@ Tamén pode reintentalo cando haxa menos actividade.',
 'imagelinks' => 'Uso do ficheiro',
 'linkstoimage' => '{{PLURAL:$1|A seguinte páxina liga|As seguintes $1 páxinas ligan}} con esta imaxe:',
 'linkstoimage-more' => 'Máis {{PLURAL:$1|dunha páxina liga|de $1 páxinas ligan}} con este ficheiro.
-A seguinte lista só amosa {{PLURAL:$1|a primeira páxina que liga|as primeiras $1 páxina que ligan}} con el.
+A seguinte lista só mostra {{PLURAL:$1|a primeira páxina que liga|as primeiras $1 páxina que ligan}} con el.
 Hai dispoñible [[Special:WhatLinksHere/$2|unha lista completa]].',
 'nolinkstoimage' => 'Ningunha páxina liga con este ficheiro.',
 'morelinkstoimage' => 'Ver [[Special:WhatLinksHere/$1|máis ligazóns]] cara a este ficheiro.',
@@ -2386,7 +2420,7 @@ O enderezo de correo electrónico que inseriu [[Special:Preferences|nas súas pr
 'mywatchlist' => 'Lista de vixilancia',
 'watchlistfor2' => 'De $1 $2',
 'nowatchlist' => 'Non ten elementos na súa lista de vixilancia.',
-'watchlistanontext' => 'Faga o favor de $1 ao sistema para ver ou editar os elementos da súa lista de vixilancia.',
+'watchlistanontext' => 'Debe $1 para ver ou editar os elementos da súa lista de vixilancia.',
 'watchnologin' => 'Non accedeu ao sistema',
 'watchnologintext' => 'Debe [[Special:UserLogin|acceder ao sistema]] para modificar a súa lista de vixilancia.',
 'addwatch' => 'Engadir á lista vixilancia',
@@ -2442,9 +2476,9 @@ Pode contactar co editor:
 por correo electrónico: $PAGEEDITOR_EMAIL
 no wiki: $PAGEEDITOR_WIKI
 
-Non se producirán novas notificacións cando haxa novos cambios ata que vostede visite a páxina. Pode borrar os indicadores de aviso de notificación para o conxunto das páxinas marcadas na súa lista de vixilancia.
+Non se producirán máis notificacións en caso de que haxa actividade nova ata que acceda ao sistema e visite a páxina. Pode restablecer os indicadores de aviso de notificación para o conxunto das páxinas marcadas na súa lista de vixilancia.
 
-       O sistema de avisos de {{SITENAME}}
+O sistema de avisos de {{SITENAME}}
 
 --
 Para cambiar as notificacións por correo electrónico, visite
@@ -2560,8 +2594,8 @@ Pode mudar o nivel de protección da páxina pero iso non afectará á protecci
 'protect-expiry-indefinite' => 'indefinido',
 'protect-cascade' => 'Protexer as páxinas incluídas nesta (protección en serie)',
 'protect-cantedit' => 'Non pode modificar os niveis de protección desta páxina porque non ten os permisos necesarios para editala.',
-'protect-othertime' => 'Outro período:',
-'protect-othertime-op' => 'outro período',
+'protect-othertime' => 'Outra duración:',
+'protect-othertime-op' => 'outra duración',
 'protect-existing-expiry' => 'Período de caducidade actual: $2 ás $3',
 'protect-otherreason' => 'Outro motivo:',
 'protect-otherreason-op' => 'Outro motivo',
@@ -2724,7 +2758,7 @@ Explique a razón específica do bloqueo (por exemplo, citando as páxinas concr
 'ipbemailban' => 'Impedir que o usuario envíe correos electrónicos',
 'ipbenableautoblock' => 'Bloquear automaticamente o último enderezo IP utilizado por este usuario, e calquera outro enderezo desde o que intente editar',
 'ipbsubmit' => 'Bloquear este usuario',
-'ipbother' => 'Outro período de tempo:',
+'ipbother' => 'Outra duración:',
 'ipboptions' => '2 horas:2 hours,1 día:1 day,3 días:3 days,1 semana:1 week,2 semanas:2 weeks,1 mes:1 month,3 meses:3 months,6 meses:6 months,1 ano:1 year,para sempre:infinite',
 'ipbotheroption' => 'outra',
 'ipbotherreason' => 'Outro motivo:',
@@ -2964,7 +2998,7 @@ No último caso, pode usar tamén unha ligazón, por exemplo [[{{#Special:Export
 'allmessagesdefault' => 'Texto predeterminado',
 'allmessagescurrent' => 'Texto actual',
 'allmessagestext' => 'Esta é unha lista de todas as mensaxes dispoñibles no espazo de nomes MediaWiki.
-Por favor, visite a [//www.mediawiki.org/wiki/Localisation localización MediaWiki] e [//translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.',
+Por favor, visite a páxina de [https://www.mediawiki.org/wiki/Localisation localización de MediaWiki] e [//translatewiki.net translatewiki.net] se quere contribuír á localización xenérica de MediaWiki.',
 'allmessagesnotsupportedDB' => "Esta páxina non está dispoñible porque '''\$wgUseDatabaseMessages''' está desactivado.",
 'allmessages-filter-legend' => 'Filtrar',
 'allmessages-filter' => 'Filtrar por estado de personalización:',
@@ -3099,7 +3133,7 @@ Pode ver o código fonte.',
 'tooltip-feed-atom' => 'Fonte de novas Atom desta páxina',
 'tooltip-t-contributions' => 'Ver a lista de contribucións {{GENDER:{{BASEPAGENAME}}|deste usuario|desta usuaria}}',
 'tooltip-t-emailuser' => 'Enviarlle unha mensaxe a {{GENDER:{{BASEPAGENAME}}|este usuario|esta usuaria}} por correo electrónico',
-'tooltip-t-upload' => 'Cargar ficheiros',
+'tooltip-t-upload' => 'Subir ficheiros',
 'tooltip-t-specialpages' => 'Lista de todas as páxinas especiais',
 'tooltip-t-print' => 'Versión para imprimir da páxina',
 'tooltip-t-permalink' => 'Ligazón permanente a esta versión da páxina',
@@ -3127,6 +3161,7 @@ Pode ver o código fonte.',
 'tooltip-undo' => '"Desfacer" reverte esta edición e abre o formulario de edición nun modo previo. Permite engadir un motivo no resumo de edición.',
 'tooltip-preferences-save' => 'Gardar as preferencias',
 'tooltip-summary' => 'Escriba un breve resumo',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/** O CSS que se coloque aquí será aplicado a todas as aparencias */',
@@ -3176,6 +3211,8 @@ Isto, probabelmente, se debe a unha ligazón cara a un sitio externo que está n
 'spam_reverting' => 'Revertida á última edición sen ligazóns a "$1"',
 'spam_blanking' => 'Limpáronse todas as revisións con ligazóns a "$1"',
 'spam_deleting' => 'Borráronse todas as revisións con ligazóns a "$1"',
+'simpleantispam-label' => "Comprobación antispam.
+'''NON''' encha isto!",
 
 # Info page
 'pageinfo-title' => 'Información sobre "$1"',
@@ -3189,6 +3226,7 @@ Isto, probabelmente, se debe a unha ligazón cara a un sitio externo que está n
 'pageinfo-length' => 'Lonxitude da páxina (en bytes)',
 'pageinfo-article-id' => 'ID da páxina',
 'pageinfo-language' => 'Lingua do contido da páxina',
+'pageinfo-content-model' => 'Modelo do contido da páxina',
 'pageinfo-robot-policy' => 'Indexación por robots',
 'pageinfo-robot-index' => 'Permitida',
 'pageinfo-robot-noindex' => 'Non permitida',
@@ -3274,7 +3312,7 @@ O seu sistema pode quedar comprometido se o executa.",
 'svg-long-desc' => 'ficheiro SVG; resolución de $1 × $2 píxeles; tamaño do ficheiro: $3',
 'svg-long-desc-animated' => 'ficheiro SVG animado; resolución de $1 × $2 píxeles; tamaño do ficheiro: $3',
 'svg-long-error' => 'Ficheiro SVG non válido: $1',
-'show-big-image' => 'Imaxe na máxima resolución',
+'show-big-image' => 'Ficheiro orixinal',
 'show-big-image-preview' => 'Tamaño desta vista previa: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Outra resolución|Outras resolucións}}: $1.',
 'show-big-image-size' => '$1 × $2 píxeles',
@@ -3743,7 +3781,7 @@ Os demais agocharanse por omisión.
 
 # External editor support
 'edit-externally' => 'Editar este ficheiro cunha aplicación externa',
-'edit-externally-help' => '(Vexa as seguintes [//www.mediawiki.org/wiki/Manual:External_editors instrucións] <small>(en inglés)</small> para obter máis información)',
+'edit-externally-help' => '(Consulte as seguintes [https://www.mediawiki.org/wiki/Manual:External_editors instrucións] para obter máis información)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todo',
@@ -3769,7 +3807,7 @@ Por favor, comprobe que no enderezo de correo electrónico non haxa caracteres i
 O programa de correo informa do seguinte: $1',
 'confirmemail_invalid' => 'O código de confirmación non é válido.
 Pode ser que caducase.',
-'confirmemail_needlogin' => 'Necesita $1 para confirmar o seu enderezo de correo electrónico.',
+'confirmemail_needlogin' => 'Debe $1 para confirmar o seu enderezo de correo electrónico.',
 'confirmemail_success' => 'Confirmouse o seu enderezo de correo electrónico. Agora xa pode [[Special:UserLogin|acceder ao sistema]] e facer uso do wiki.',
 'confirmemail_loggedin' => 'Xa se confirmou o seu enderezo de correo electrónico.',
 'confirmemail_error' => 'Houbo un problema ao gardar a súa confirmación.',
@@ -3846,6 +3884,7 @@ Por favor, confirme que realmente quere recrear esta páxina.",
 
 # Separators for various lists, etc.
 'colon-separator' => ':&#32;',
+'quotation-marks' => '"$1"',
 
 # Multipage image navigation
 'imgmultipageprev' => '← páxina anterior',
@@ -3935,7 +3974,7 @@ Tamén pode [[Special:EditWatchlist|empregar o editor normal]].',
 'version-hook-subscribedby' => 'Subscrito por',
 'version-version' => '(Versión $1)',
 'version-license' => 'Licenza',
-'version-poweredby-credits' => "Este wiki está desenvolvido por '''[//www.mediawiki.org/wiki/MediaWiki/gl MediaWiki]''', dereitos de autor © 2001-$1 $2.",
+'version-poweredby-credits' => "Este wiki está desenvolvido por '''[https://www.mediawiki.org/wiki/MediaWiki/gl MediaWiki]''', dereitos de autoría © 2001-$1 $2.",
 'version-poweredby-others' => 'outros',
 'version-poweredby-translators' => 'os tradutores de translatewiki.net',
 'version-credits-summary' => 'Queremos recoñecer as seguintes persoas polas súas achegas a [[Special:Version|MediaWiki]].',
@@ -3956,7 +3995,7 @@ Debería recibir [{{SERVER}}{{SCRIPTPATH}}/COPYING unha copia da licenza públic
 # Special:Redirect
 'redirect' => 'Redirixir por nome de ficheiro, ID de usuario ou ID de revisión',
 'redirect-legend' => 'Redirixir a un ficheiro ou unha páxina',
-'redirect-summary' => 'Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID dunha revisión) ou unha páxina de usuario (dado o ID dun usuario).',
+'redirect-summary' => 'Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID dunha revisión) ou unha páxina de usuario (dado o ID dun usuario). Utilización: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Continuar',
 'redirect-lookup' => 'Procurar:',
 'redirect-value' => 'Valor:',
@@ -3978,8 +4017,8 @@ Debería recibir [{{SERVER}}{{SCRIPTPATH}}/COPYING unha copia da licenza públic
 
 # Special:SpecialPages
 'specialpages' => 'Páxinas especiais',
-'specialpages-note' => '----
-* Páxinas especiais normais.
+'specialpages-note-top' => 'Lenda',
+'specialpages-note' => '* Páxinas especiais normais.
 * <span class="mw-specialpagerestricted">Páxinas especiais restrinxidas.</span>',
 'specialpages-group-maintenance' => 'Informes de mantemento',
 'specialpages-group-other' => 'Outras páxinas especiais',
@@ -4002,7 +4041,7 @@ Debería recibir [{{SERVER}}{{SCRIPTPATH}}/COPYING unha copia da licenza públic
 'external_image_whitelist' => ' #Deixe esta liña tal e como está<pre>
 #Poña embaixo fragmentos de expresións regulares (tan só a parte que vai entre //)
 #Isto coincidirá cos enderezos URL das imaxes externas (hotlinked)
-#Aquelas que coincidan serán amosadas como imaxes, senón, só será amosada unha ligazón cara a esta
+#Aquelas que coincidan mostraranse como imaxes, senón, só se mostrará unha ligazón cara a esta
 #As liñas que comecen por "#" son comentarios
 #Non diferencia entre maiúsculas e minúsculas
 
@@ -4193,4 +4232,21 @@ En caso contrario, pode empregar o formulario sinxelo inferior. O seu comentario
 'limitreport-expansiondepth' => 'Máxima profundidade de expansión',
 'limitreport-expensivefunctioncount' => 'Número de funcións de análise custosas',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandir os modelos',
+'expand_templates_intro' => 'Esta páxina especial toma texto e expande todos os modelos dentro del recursivamente.
+Tamén expande as funcións de análise como
+<code><nowiki>{{</nowiki>#language:…}}</code> e variables como
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+De feito, expande case calquera cousa entre dúas chaves.',
+'expand_templates_title' => 'Título do contexto, para {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Texto de entrada:',
+'expand_templates_output' => 'Resultado',
+'expand_templates_xml_output' => 'Saída XML',
+'expand_templates_ok' => 'Aceptar',
+'expand_templates_remove_comments' => 'Eliminar os comentarios',
+'expand_templates_remove_nowiki' => 'Suprimir as etiquetas <nowiki> no resultado',
+'expand_templates_generate_xml' => 'Mostrar as árbores de análise XML',
+'expand_templates_preview' => 'Vista previa',
+
 );
diff --git a/languages/messages/MessagesGom_latn.php b/languages/messages/MessagesGom_latn.php
new file mode 100644 (file)
index 0000000..4acdb41
--- /dev/null
@@ -0,0 +1,757 @@
+<?php
+/** Goan Konkani (Latin script) (Konknni)
+ *
+ * See MessagesQqq.php for message documentation incl. usage of parameters
+ * To improve a translation please visit http://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ * @author Deepak D'Souza
+ * @author Isidore Dantas
+ * @author The Discoverer
+ */
+
+$messages = array(
+'underline-always' => 'Soddankal',
+'underline-never' => 'Kednach na',
+
+# Dates
+'sunday' => 'Aitar',
+'monday' => 'Somar',
+'tuesday' => 'Munglar',
+'wednesday' => 'Budhwar',
+'thursday' => 'Birestar',
+'friday' => 'Sukrar',
+'saturday' => 'Sonvar',
+'sun' => 'Ait',
+'mon' => 'Som',
+'tue' => 'Mung',
+'wed' => 'Budh',
+'thu' => 'Bres',
+'fri' => 'Sukr',
+'sat' => 'Son',
+'january' => 'Janer',
+'february' => 'Febrer',
+'march' => 'Mars',
+'april' => 'Abril',
+'may_long' => 'Mai',
+'june' => 'Jun',
+'july' => 'Julai',
+'august' => 'Agost',
+'september' => 'Setembr',
+'october' => 'Otubr',
+'november' => 'Novembr',
+'december' => 'Dezembr',
+'january-gen' => 'Janer',
+'february-gen' => 'Febrer',
+'march-gen' => 'Mars',
+'april-gen' => 'Abril',
+'may-gen' => 'Mai',
+'june-gen' => 'Jun',
+'july-gen' => 'Julai',
+'august-gen' => 'Agost',
+'september-gen' => 'Setembr',
+'october-gen' => 'Otubr',
+'november-gen' => 'Novembr',
+'december-gen' => 'Dezembr',
+'jan' => 'Jan',
+'feb' => 'Feb',
+'mar' => 'Mar',
+'apr' => 'Abr',
+'may' => 'Mai',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Ago',
+'sep' => 'Set',
+'oct' => 'Otu',
+'nov' => 'Nov',
+'dec' => 'Dez',
+'january-date' => '$1 Janer',
+'february-date' => '$1 Febrer',
+'march-date' => '$1 Mars',
+'april-date' => '$1 Abril',
+'may-date' => '$1 Mai',
+'june-date' => '$1 Jun',
+'july-date' => '$1 Julai',
+'august-date' => '$1 Agost',
+'september-date' => '$1 Setembr',
+'october-date' => '$1 Otubr',
+'november-date' => '$1 Novembr',
+'december-date' => '$1 Dezembr',
+
+# Categories related messages
+'pagecategories' => '{{PLURAL:$1|Vorg|Vorgam}}',
+'category_header' => '"$1" vorgantlim panam',
+'subcategories' => 'Upvorg',
+'category-media-header' => '"$1" hea vorgan madheom\'ma',
+'category-empty' => "''Hea vorgan sodhea ekui pan vo madheom na''",
+'hidden-categories' => '{{PLURAL:$1|Lipoilolo vorg|Lipoilole vorg}}',
+'category-subcat-count' => '{{PLURAL:$2|Hea vorgan fokot hi ek upvorg asa.|Hea vorgan {{PLURAL:$1|hi upvorg asa|heo $1 upvorg asat}}, beriz $2 upvorga modem.}}',
+'category-article-count' => '{{PLURAL:$2|Hea vorgan fokot hi ek pan asa.|Hea vorgan {{PLURAL:$1|hi pan asa|him $1 panam asat}} beriz $2 panam modem.}}',
+'category-file-count' => '{{PLURAL:$2|Hea vorgan fokot hi ek fail asa.|Hea vorgan {{PLURAL:$1|hi fail asa|heo $1 faili asat}}, beriz $2 faili modem.}}',
+'listingcontinuesabbrev' => 'chalu',
+'noindex-category' => 'Suchi-potran zoddunk-naslelim panam',
+
+'about' => 'Hea vixoiavoir',
+'article' => 'Vixoi sombondhi pan',
+'newwindow' => '(novea zonelant uktem zata)',
+'cancel' => "Rod'd kor",
+'mytalk' => 'Bhasabhas',
+'navigation' => 'Dixa-niontronn',
+
+# Cologne Blue skin
+'qbfind' => 'Sod',
+'qbedit' => 'Bodol',
+'qbspecialpages' => 'Khaxelim panam',
+'faq' => 'Choddxe vicharlole prosn',
+
+# Vector skin
+'vector-action-addsection' => 'Vixoi zodd',
+'vector-action-delete' => 'Kadd',
+'vector-action-move' => 'Fuddem voch',
+'vector-action-protect' => 'Rakh',
+'vector-view-create' => 'Roch',
+'vector-view-edit' => 'Sudar',
+'vector-view-history' => 'Itihas polloi',
+'vector-view-view' => 'Vach',
+'vector-view-viewsource' => 'Mull polloi',
+'actions' => 'Karvaio',
+'namespaces' => 'Nanv-thollam',
+'variants' => 'Dusre',
+
+'errorpagetitle' => 'Chuk',
+'returnto' => '$1 hanga porot voch.',
+'tagline' => '{{SITENAME}} savn',
+'help' => 'Adar',
+'search' => 'Sod',
+'searchbutton' => 'Sod',
+'go' => 'Pavl mar',
+'searcharticle' => 'Fuddem voch',
+'history' => 'Panacho itihas',
+'history_short' => 'Itihas',
+'printableversion' => "Chapp'pachi avruti",
+'permalink' => 'Togpi zodd',
+'view' => 'Poloi',
+'edit' => 'Sudar',
+'create' => 'Roch',
+'editthispage' => 'Hem pan bodol',
+'create-this-page' => 'Ho pan roch',
+'delete' => 'Vogllai',
+'deletethispage' => 'Hem pan kad',
+'protect' => 'Rakh',
+'protect_change' => 'bodol',
+'protectthispage' => 'Hem pan rakh',
+'newpage' => 'Novem pan',
+'talkpage' => 'Hea panachem bhasabhas kor',
+'talkpagelinktext' => 'Bhasabhas',
+'specialpage' => 'Khaxhel pan',
+'personaltools' => 'Khasgi avtam',
+'articlepage' => 'Vixoi sombondhi pan poloi',
+'talk' => 'Bhasabhas',
+'views' => 'Niall',
+'toolbox' => 'Avtam',
+'userpage' => 'Vangddiacho pan poloi',
+'imagepage' => 'Imazichem pan poloi',
+'viewhelppage' => 'Adar pan poloi',
+'categorypage' => 'Vorgachem pan poloi',
+'otherlanguages' => 'Dusrea bhasanim',
+'redirectedfrom' => '($1 savn porot dixent)',
+'redirectpagesub' => 'Punornirdexan pan',
+'lastmodifiedat' => 'Hem pan xevtim $1 disa, $2 vazta bodolelem.',
+'jumpto' => 'Hangachean voch',
+'jumptonavigation' => 'Dixa-niontronn',
+'jumptosearch' => 'sod',
+
+# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
+'aboutsite' => '{{SITENAME}} babtint',
+'aboutpage' => 'Project:Vixoiavixim',
+'copyrightpage' => '{{ns:project}}:Prat-hokk',
+'currentevents' => 'Chalu ghoddnneo',
+'currentevents-url' => 'Project:Chalu ghoddneo',
+'disclaimers' => 'Chotraio',
+'disclaimerpage' => 'Project:Sadeo chotraio',
+'edithelp' => 'Sudarunk palov',
+'helppage' => 'Help:Mozkur',
+'mainpage' => 'Mukhel Pan',
+'mainpage-description' => 'Mukhel Pan',
+'portal' => 'Somudaik proves-dar',
+'portal-url' => 'Project:Somudaik proves-dar',
+'privacy' => 'Gupitaiechem dhoronn',
+'privacypage' => 'Project:Gupitachem dhoronn',
+
+'badaccess-group0' => "Tumi tillson kel'lem kary korunk tumkam permissanv na.",
+'badaccess-groups' => "Tumi tillson kel'lem kary mat {{PLURAL:$2|the group|one of the groups}}: $1 -ak permissanv asa.",
+
+'versionrequired' => 'MediaWikichem $1 version zai',
+'versionrequiredtext' => 'Hem pan vaprunk MediaWikichem $1 version zai.
+[[Special:Version|version page]] pan poloea.',
+
+'ok' => 'Zait',
+'retrievedfrom' => '"$1" savn prapt kelam',
+'youhavenewmessages' => 'Tumkam $1 ($2) asat.',
+'editsection' => 'sudar',
+'editold' => 'sudar',
+'viewsourceold' => 'mull poloi',
+'editlink' => 'sudar',
+'viewsourcelink' => 'mull polloi',
+'editsectionhint' => 'khondd sudar: $1',
+'toc' => 'Suchi potr',
+'showtoc' => 'dakhoi',
+'hidetoc' => 'lipoi',
+'site-atom-feed' => '$1 Atom purvoi',
+'page-atom-feed' => '"$1" Atom purvonn',
+'red-link-title' => '$1 (hea nanvachem pan na)',
+
+# Short words for each namespace, by default used in the namespace tab in monobook
+'nstab-main' => 'Pan',
+'nstab-user' => 'Vapuddpeachem pan',
+'nstab-special' => 'Kherit pan',
+'nstab-project' => 'Project-ache pan',
+'nstab-image' => 'Fail',
+'nstab-mediawiki' => 'Sondex',
+'nstab-template' => 'Saacho',
+'nstab-category' => 'Vorg',
+
+# General errors
+'error' => 'Chuk',
+'missing-article' => 'Totv-kox (Database) hantun mellunk zai aslem tem mozkur "$1" $2 mellunk-nam.
+
+Horxim, oxem ek pornem frk vo eka panachem itihasachem zodd vogllailem, tedna zata.
+
+Oxem nhoi zalear, tuka softwer-an chuk sampodlam zait.
+Upkar korun eka [[Special:ListUsers/sysop|karbhari]]chea nodrek hadd, Internet Zago Sodpi (URL) hachi nond gheun.',
+'missingarticle-rev' => '(uzollnni#: $1)',
+'missingarticle-diff' => '(Frk: $1, $2)',
+'badtitle' => 'Chukichem nanv',
+'badtitletext' => 'Tuven maglelem panache nanv chukichem, rintem, vo ek sarkem zodunk-naslelem bhase-modlem vo wiki-modlem nanv.
+
+Tantun ek vo sabaar okxor asot jenka nanvanim uzar korunk zainan.',
+'viewsource' => 'Mull polloi',
+
+# Login and logout pages
+'welcomeuser' => 'Ievkar, $1!',
+'yourname' => 'Vapuddpeachem nanv:',
+'yourpassword' => 'Gupitutor:',
+'userlogin-yourpassword' => 'Gupitutor',
+'yourpasswordagain' => 'Gupit utor porot boroi:',
+'remembermypassword' => 'Hea internet browseran mhojem sotrachem ugdas dovor (chodan chod $1 {{PLURAL:$1|disak|disank}})',
+'login' => 'Sotrromb kor',
+'nav-login-createaccount' => 'Sotrrombh kor / khato roch',
+'loginprompt' => "{{SITENAME}}, hea siticher sotrorombh korunktujea internet browseran ''cookies'' suru asunk zai.",
+'userlogin' => 'Sotrrombh kor / khatem roch',
+'logout' => 'Bhair podd',
+'userlogout' => 'Sotracho xevott',
+'nologin' => 'Tuje kodde khatem na? $1.',
+'nologinlink' => 'Novem khatem ughodd',
+'createaccount' => 'Khatem roch',
+'gotaccount' => 'Tuje kodem khatem asa? $1.',
+'gotaccountlink' => 'Sotrorombh kor',
+'userlogin-resetlink' => 'Sotrorombh korpacheo bariksai visorlai?',
+'mailmypassword' => 'Novem gupitutor email kor',
+'loginlanguagelabel' => 'Bhas: $1',
+
+# Edit page toolbar
+'bold_sample' => 'Datt mozkur',
+'bold_tip' => 'Datt mozkur',
+'italic_sample' => 'Palso mozkur',
+'italic_tip' => 'Palso mozkur',
+'link_sample' => 'Zoddachem nanv',
+'link_tip' => 'Bhitorlem zoddop',
+'extlink_sample' => 'http://www.udaronn.in zoddachem nanv',
+'extlink_tip' => 'Bhailem site (survatek http:// visronakai)',
+'headline_sample' => 'Mathalleacho mozkur',
+'headline_tip' => 'Dusrea patllicho mathallo',
+'nowiki_sample' => 'Sworup diunk naslelem mozkur hanga ghal',
+'nowiki_tip' => 'Wiki sworup durlokx kor',
+'image_tip' => 'Bosoileli fail',
+'media_tip' => 'Failichem zodd',
+'sig_tip' => 'Tuji soi, vell-chaap soit',
+'hr_tip' => 'Adhvem rang (Komi uzar kor)',
+
+# Edit pages
+'summary' => 'Sar:',
+'subject' => 'Vishoy:',
+'minoredit' => 'Hem ek dhaktem sudarop',
+'watchthis' => 'Hea panar nodor dovor',
+'savearticle' => 'Pan samball',
+'preview' => 'Zholok',
+'showpreview' => 'Zholok dakhoi',
+'showdiff' => 'Bodolpam dakhoi',
+'anoneditwarning' => "'''Chotrai:''' Tuven sotrorombh korunk nai.
+Tuzo internet potteachi nond panachem itihasan zatelem.",
+'newarticle' => '(Novem)',
+'newarticletext' => "Tuven ek zoddache patlav kelai, zachem pan azun rochunk na.
+Pan rochunk, khallchea chovkottan boroi (anik mahitik [[{{MediaWiki:Helppage}}|adar pan]] polloi).
+Tu hangasor chukin pavlai zalear tujea internet browser-achi '''Fatim'' vo '''Back''' butao dab.",
+'noarticletext' => 'Sodheak hem pan rinte asa.
+Tujean 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 sudharunk zata]</span>.',
+'noarticletext-nopermission' => 'Sodheak hem pan rinte asa.
+Tujean 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.',
+'previewnote' => "'''Hi fokot ek zholok mhonn ugddas dhor.'''
+Tujim bodolpam azun sambhallun dovrunk nant!",
+'editing' => '$1 sudarop',
+'editingsection' => '(Vibhag) $1 sudar',
+'templatesused' => "Hea panant uzar {{PLURAL:$1|kel'lo sancho|kel'le sanche}}:",
+'template-protected' => '(rakhlelem)',
+'template-semiprotected' => '(ordhem rakhun dovorlelem)',
+'hiddencategories' => 'Hem pan {{PLURAL:$1|1 lipoilelea vorgacho vangddi|$1 lipoileleam vorgancho vangddi}}:',
+'permissionserrorstext-withaction' => '$2, hem korpak tuka porvangi na, {{PLURAL:$1|hea karnnak lagon|hea karnnank lagun}}:',
+'recreate-moveddeleted-warn' => "'''Xittkavnni: Tum ek pan porot rochtai jem fattim vogllailelem .'''
+
+Panacho sudar korop sarkem zalear dhean di.
+Pan vogllavpachem ani sotr halovpachem, sovloti khatir hangasor dilelem asa:",
+'moveddeleted-notice' => 'Hem pan vogllailem asa.
+Panachea vogllaonechi ani hallonechi sotr mahiti khatir sokoil sondorba khatir dilea.',
+
+# Parser/template warnings
+'post-expand-template-inclusion-warning' => "'''Chotrai:''' Sacho zoddpacho akar chod vhodlem asa.
+Thodde sache zoddchenant",
+'post-expand-template-inclusion-category' => 'Zea panani sache zoddpachem akarachem merakin chod zala',
+'post-expand-template-argument-warning' => "'''Chotrai:''' Hea panan ek tori oslo sacheacho parametro asa zacho patlloylea uprant akar chod vhoddlo zata.
+Heo parametrank durlokx keleat.",
+'post-expand-template-argument-category' => 'Sacheache parametro zoddunknan osle panam',
+
+# History pages
+'viewpagelogs' => 'Hea panachim sotram polloi',
+'currentrev-asof' => '$1, hachi halinchi uzollnni',
+'revisionasof' => '$1 hachi uzollnni',
+'revision-info' => '$2 hannem $1, hachi uzollnni',
+'previousrevision' => '← Adli uzollnni',
+'nextrevision' => 'Novi uzolnni →',
+'currentrevisionlink' => 'Sogleanvon novi uzollnni',
+'cur' => 'chal',
+'last' => 'adl',
+'page_first' => 'poilem',
+'page_last' => 'akhirchem',
+'histlegend' => "Frk nivoddni: Jeo uzollneo tuka comparar korunk zai, tenche fudle ''radio'' butao petoi
+Vivron: '''({{int:cur}})''' = halinchi uzollnie borobor forok, '''({{int:last}})''' = adli uzollnie borobor forok, '''{{int:minoreditletter}}''' = dhaktem sudharop.",
+'history-fieldset-title' => 'Itihas chall',
+'history-show-deleted' => 'Fokot vogllailelem',
+'histfirst' => 'sogleavon adhlem',
+'histlast' => 'sogleavon novem',
+
+# Revision feed
+'history-feed-item-nocomment' => '$1 hannem $4, $3 hea vellar',
+
+# Revision deletion
+'rev-delundel' => 'dakhoi/lipoi',
+'revdel-restore' => 'Disnnem bodol',
+'revdel-restore-deleted' => "rod'd kelelo uzollnneo",
+'revdel-restore-visible' => 'Dispi uzollnneo',
+
+# Merge log
+'revertmerge' => 'Doxim kor',
+
+# Diffs
+'history-title' => '"$1" hachea uzollnnecho itihas',
+'lineno' => 'Line ank $1:',
+'compareselectedversions' => 'Nivodloleo uzollneo comparar kor',
+'editundo' => "rod'd kor",
+'diff-multi' => "({{PLURAL:$2|Eka vapuddpean|$2 vapuddpeamni}} {{PLURAL:$1|kel'li ek modli uzollnni|kel'leo $1 modleo uzollnneo}} dakhonk nant)",
+
+# Search results
+'searchresults' => 'Sodacho nikal',
+'searchresults-title' => '"$1" -khatir sodacho nikal',
+'prevn' => 'adlem {{PLURAL:$1|$1}}',
+'nextn' => 'fuddlem {{PLURAL:$1|$1}}',
+'prevn-title' => '{{PLURAL:$1|Fattlem $1 porinnam|Fattlem $1 porinam}}',
+'nextn-title' => '{{PLURAL:$1|Fuddlem $1 porinnam|Fudnlim $1 porinnam}}',
+'shown-title' => 'Dor panar {{PLURAL:$1|porinam|porinam}} dakhoi',
+'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3) poloi',
+'searchmenu-exists' => "'''Hea Wikicher \"[[:\$1]]\" nanvanche pan asa.'''",
+'searchmenu-new' => "'''\"[[:\$1]]\" hem pan hea vikint roch!'''",
+'searchprofile-articles' => 'Mozkurachim panam',
+'searchprofile-project' => 'Adar ani Project panam',
+'searchprofile-images' => 'Bhovmadhiom',
+'searchprofile-everything' => 'Sogllem',
+'searchprofile-advanced' => 'Sodpache poryay',
+'searchprofile-articles-tooltip' => '$1 hantunt sod',
+'searchprofile-project-tooltip' => '$1 hantunt sod',
+'searchprofile-images-tooltip' => 'Faili sod',
+'searchprofile-everything-tooltip' => "Akhea sitin sod (Bhasabhas panant'ui)",
+'searchprofile-advanced-tooltip' => 'chalu nanvthollancher sod',
+'search-result-size' => '$1 {{PLURAL:$2|1 utor|$2 utram}}',
+'search-result-category-size' => '{{PLURAL:$1|1 vangddi|$1 vangddi}} ({{PLURAL:$2|1 upvorg|$2 upvorg}}, {{PLURAL:$3|1 fichier|$3 fichieri}})',
+'search-redirect' => '($1 porot dixen dhaddop)',
+'search-section' => '(vibhag $1)',
+'search-suggest' => 'mhonnunk sodi: $1',
+'searchrelated' => 'sombondit',
+'searchall' => 'soglle',
+'showingresultsheader' => "{{PLURAL:$5|'''$3''' hantlem '''$1''' porinam|'''$3''' hantlim '''$1 - $2''' porinam}}, '''$4''' haka",
+'search-nonefound' => 'Tujea sodak mell khata toslem kai porinam nan.',
+'powersearch-field' => 'Hachea khatir sodha',
+
+# Preferences page
+'preferences' => 'Posondeo',
+'mypreferences' => 'Posonti',
+'youremail' => 'Tuzo email potto',
+'yourrealname' => 'Khorem nanv:',
+'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 zodde vorvim tuje xim sompork korunk diunk zata.
+Dusre tuje xim sompork kortat tednam tuzo email potto tankam kollchenam.',
+
+# Groups
+'group-all' => '(soglle)',
+
+# Special:Log/newusers
+'newuserlogpage' => 'Vapurpi rochnnechem sotr',
+
+# Associated actions - in the sentence "You do not have permission to X"
+'action-edit' => 'hem pan sudar',
+
+# Recent changes
+'nchanges' => '$1 {{PLURAL:$1|bodlop|bodlopam}}',
+'recentchanges' => 'Halincho bodol',
+'recentchanges-legend' => 'Hallinch zalleo bodlopancheo poryay',
+'recentchanges-feed-description' => "Wiki'k kel'le halinche bodlopancher hea vhawa vorvim nodor dovor.",
+'recentchanges-label-newpage' => 'Hea sudaran ek novem pan rochlam',
+'recentchanges-label-minor' => 'Ho ek dhaktto sudar',
+'recentchanges-label-bot' => "Hem bodlop eka robotan kel'lem",
+'recentchanges-label-unpatrolled' => 'Hem sudharop azun topasunk nam',
+'rcnote' => "Sokoil {{PLURAL:$1|dilelim nimannim '''1''' bodlopam| '''$1''' bodlopam}} {{PLURAL:$2|xevotchea disan|xevottchim '''$2''' disanim}}, $5, $4 porian.",
+'rcnotefrom' => "Sokoil '''$2''' savn zalelim bodolpam dileant ( '''$1'''meren dakhoileant).",
+'rclistfrom' => '$1 savn suru zatelim novim bodolpam dakhoi',
+'rcshowhideminor' => '$1 dhaktteo sudarnneo',
+'rcshowhidebots' => '$1 robot',
+'rcshowhideliu' => '$1 sotrromb kelele vapuddpi',
+'rcshowhideanons' => '$1 nanv-naslelim vapurpi',
+'rcshowhidepatr' => '$1 topaslele sudharop',
+'rcshowhidemine' => 'Mhojem sudarop $1',
+'rclinks' => "Xevtiche $2 disanim zal'le $1 bodlopam dakhoi<br />$3",
+'diff' => 'frk',
+'hist' => 'iti',
+'hide' => 'Lipoi',
+'show' => 'Dakhoi',
+'minoreditletter' => 'd',
+'newpageletter' => 'N',
+'boteditletter' => 'r',
+'rc-enhanced-expand' => 'Bariksann dakhoi',
+'rc-enhanced-hide' => 'Bariksann lipoi',
+
+# Recent changes linked
+'recentchangeslinked' => 'Sombondit bodolpam',
+'recentchangeslinked-toolbox' => 'Sombondit bodolpam',
+'recentchangeslinked-title' => '"$1" sombondit zalelim bodolpam',
+'recentchangeslinked-summary' => "Hem zaun asa eke panaksun vo eka voraksun, halinch kel'lim bodlopanchi suchi.
+
+[[Special:Watchlist|Tujea sadurvollerint]] aslelim panam 'datt' asat.",
+'recentchangeslinked-page' => 'Panache nanv:',
+'recentchangeslinked-to' => "Dil'em panache bodlek haka zodlelem panank kel'lim bodlopam dakhoi",
+
+# Upload
+'upload' => 'Fail upload kor',
+'uploadlogpage' => 'Uploadachem sotr',
+'filedesc' => 'Sar',
+'uploadedimage' => ' "[[$1]]" upload zalem',
+'watchthisupload' => 'Hea faylar dixtt dovor',
+
+'license' => 'Porvangi',
+'license-header' => 'Porvangi',
+
+# File description page
+'file-anchor-link' => 'Fail',
+'filehist' => 'Failicho itihas',
+'filehist-help' => ' Tea vellar aslelea rupan pollonvk tarikh/vellar koll mar',
+'filehist-revert' => 'Nimanea avruttik porot vor',
+'filehist-current' => 'chalont',
+'filehist-datetime' => 'Tarikh/Vell',
+'filehist-thumb' => 'Lhan-imaz',
+'filehist-thumbtext' => '$1 avrute khatir lhan-imaz',
+'filehist-user' => 'Vaporpi',
+'filehist-dimensions' => 'Akar',
+'filehist-comment' => 'vivek',
+'imagelinks' => 'Failicho vapor',
+'linkstoimage' => '{{PLURAL:$1|Hem pan|$1 Him panam}} hea failik {{PLURAL:$1|zoddtta|zoddttat}}',
+'nolinkstoimage' => 'Hea failik zoddpi panam nant',
+'sharedupload-desc-here' => 'Hi fail $1, hachi ani dusreo projectanim haka uzar korunk zata.
+Hachem [$2 failichem vivron panan] asleli vivron khala dilea:',
+
+# File deletion
+'filedelete-otherreason' => 'Dusrem/aniki karon:',
+
+# Random page
+'randompage' => 'Khoincheim pan',
+
+# Statistics
+'statistics' => 'Ankddevari',
+
+# Miscellaneous special pages
+'nbytes' => '$1 {{PLURAL:$1|byte|bytesi}}',
+'nmembers' => '$1 {{PLURAL:$1|vangddi}}',
+'prefixindex' => 'Panam jenche nanvache survatek asa...',
+'shortpages' => 'Dhaktim panam',
+'longpages' => 'Lamb panam',
+'usercreated' => '$3 hannem $1 disa $2 vaztam rochlelem',
+'newpages' => 'Novim panam',
+'move' => 'Zago bodol',
+'pager-newer-n' => '{{PLURAL:$1|novem 1|novim $1}}',
+'pager-older-n' => '{{PLURAL:$1|adlem 1|adlim $1}}',
+
+# Book sources
+'booksources' => 'Pustokachem mull',
+'booksources-search-legend' => 'Pustokachim mullam sod',
+'booksources-go' => 'Fuddem voch',
+
+# Special:Log
+'speciallogtitlelabel' => 'Vishoi vo vapurpi:',
+'log' => 'Sotram',
+
+# Special:AllPages
+'allpages' => 'Sogllim panam',
+'alphaindexline' => '$1 savn $2',
+'nextpage' => 'Mukklem pan ($1)',
+'prevpage' => "Ad'dlem pan ($1)",
+'allpagesfrom' => 'Hanga thavn suru zatelea panank dakhoi:',
+'allarticles' => 'Sogllim panam',
+'allpagessubmit' => 'Fuddem voch',
+
+# Special:Categories
+'categories' => 'Vorg',
+
+# Special:LinkSearch
+'linksearch-line' => '$1 $2 savn zoddlelem asa',
+
+# Special:ListGroupRights
+'listgrouprights-members' => '(vapuddpeanchi suchi)',
+
+# Email user
+'emailuser' => 'Email dhadd',
+
+# Watchlist
+'watchlist' => 'Sadurachi volleri',
+'mywatchlist' => 'Sadurachi volleri',
+'watchlistfor2' => '$1 hache khatir $2',
+'watch' => 'Sadur rav',
+'watchthispage' => 'Hea panar dixtt dovor',
+'unwatch' => 'Nodor kadd',
+'watchlist-details' => 'Tujea sadurvollerint {{PLURAL:$1|$1 pan asa|$1 panam asat}}, ulovpachim panam mezonastanam.',
+'wlheader-showupdated' => "Tujea fatle bhette san bodol'lean tim panam '''datt''' dakhoileant.",
+'wlshowlast' => 'Xevottchim $1 voram $2 dis $3 dakhoi',
+'watchlist-options' => 'Sadurvollericheo poryay',
+
+# Displayed when you click the "watch" button and it is in the process of watching
+'watching' => 'Disht dovortanv...',
+'unwatching' => 'Disht kaddthanv...',
+
+# Delete
+'actioncomplete' => 'Karvai sompurnn',
+'actionfailed' => 'Karvai oiesiesvi',
+'dellogpage' => 'Vogllaoneche sotr',
+'deleteotherreason' => 'Dusrem/aniki karon:',
+
+# Rollback
+'rollbacklink' => 'kovoll',
+
+# Protect
+'protectlogpage' => 'Surokxitechem sotr',
+'protectedarticle' => 'rakhlelem "[[$1]]"',
+'protect-otherreason' => 'Dusrem/aniki karon:',
+'protect-otherreason-op' => 'Dusrem karon',
+
+# Undelete
+'undeletelink' => 'polloi/adlea zagear hadd',
+'undeleteviewlink' => 'polloi',
+
+# Namespace form on various pages
+'namespace' => 'Nanv-tholl',
+'invert' => 'Nonddni urfattoi',
+'blanknamespace' => '(Mukhel)',
+
+# Contributions
+'contributions' => '{{GENDER:$1|Vapuddpi}} borovpam',
+'contributions-title' => '$1 hea vapuddpean kelelim borovpam',
+'mycontris' => 'Borovpam',
+'contribsub2' => '{{GENDER:$3|$1}} hacheo ($2)',
+'uctop' => '(atachem)',
+'month' => 'Mhoinea savn (ani adichem):',
+'year' => 'Hea vorsa savn (ani adichem):',
+
+'sp-contributions-newbies' => 'Fokot novea khateachim borovpam dakhoi',
+'sp-contributions-blocklog' => 'addavnniache sotr',
+'sp-contributions-uploads' => 'upload',
+'sp-contributions-logs' => 'sotr',
+'sp-contributions-talk' => 'bhasabhas',
+'sp-contributions-search' => 'Borovpam sod',
+'sp-contributions-username' => 'Antorzall namo vo vapuddpeachem nanv:',
+'sp-contributions-toponly' => 'Fokot halincheo uzollnneo dakhoi',
+'sp-contributions-submit' => 'Sod',
+
+# What links here
+'whatlinkshere' => 'Hanga kitem zoddta',
+'whatlinkshere-title' => '"$1" haka zoddlelim panam',
+'whatlinkshere-page' => 'Pan:',
+'linkshere' => "Sokoilim panam '''[[:$1]]''' ak zoddtat:",
+'nolinkshere' => "Khoincheim pan '''[[:$1]]''' ak zoddna.",
+'isredirect' => 'Porot dixen pan dhadd',
+'istemplate' => 'Durasth-somaves',
+'isimage' => 'failichem zoddop',
+'whatlinkshere-prev' => '{{PLURAL:$1|adlem|adlem $1}}',
+'whatlinkshere-next' => '{{PLURAL:$1|fuddlem|fuddlim $1}}',
+'whatlinkshere-links' => '← zoddpam',
+'whatlinkshere-hideredirs' => '$1 porot dixen',
+'whatlinkshere-hidetrans' => '$1 durasth-somaves',
+'whatlinkshere-hidelinks' => '$1 zoddpam',
+'whatlinkshere-hideimages' => 'Failinchim zoddpam $1',
+'whatlinkshere-filters' => 'Challnio',
+
+# Block/unblock
+'ipboptions' => '2 voram:2 hours,1 dis:1 day,3 dis:3 days,1 satollo:1 week,2 satolle:2 weeks,1 mhoino:1 month,3 mhoine:3 months,6 mhoine:6 months,1 voros:1 year,sasnnank:infinite',
+'ipbotherreason' => 'Dusrem/aniki karon:',
+'ipblocklist' => 'Addhailele vapuddpi',
+'blocklink' => 'addavnnni',
+'unblocklink' => 'Addavnni kadd',
+'change-blocklink' => 'Addavnnni bodol',
+'contribslink' => 'borovp',
+'blocklogpage' => 'addavnnechem sotr',
+'blocklogentry' => '[[$1]] addailelem $2 asun vellacho ont: $3',
+'block-log-flags-nocreate' => 'Khatem rochop opatr kelam',
+
+# Move page
+'move-watch' => 'Hea panar disht dovor',
+'movelogpage' => 'Sotr bodol',
+'movereason' => 'Karonn:',
+'revertmove' => 'porti',
+
+# Export
+'export' => 'Panank niryat kor',
+
+# Namespace 8 related
+'allmessagesname' => 'Nanv',
+'allmessagesdefault' => 'Falta sondex mozkur',
+
+# Thumbnails
+'thumbnail-more' => 'vaddoi',
+'thumbnail_error' => 'Lhan-imaz toiar kortana chuk zali. Karonn: $1',
+
+# Tooltip help for the actions
+'tooltip-pt-userpage' => 'Tujem vapuddpachem pan',
+'tooltip-pt-mytalk' => 'Tumchem ulovpachem pan',
+'tooltip-pt-preferences' => 'Tumcheo avddi',
+'tooltip-pt-watchlist' => 'Bodlachea dekhrekh korpachea panachi volleri',
+'tooltip-pt-mycontris' => 'Tujea borovpanchi suchi',
+'tooltip-pt-login' => 'Tumkam sotrrombh korunk protsavan asa; em soktichem nhoi',
+'tooltip-pt-logout' => 'Sotracho xevott',
+'tooltip-ca-talk' => 'Mozkurachea vixoiavoir bhasabhas',
+'tooltip-ca-edit' => 'Tumchean hem pan sudarunk zata. Upkar korun sambhallche adim zholok butanv vapor',
+'tooltip-ca-addsection' => 'Novo vibhag suru kor',
+'tooltip-ca-viewsource' => 'Hem pan rakhun dovorlam.
+Tujean tachem mull pollonv ieta',
+'tooltip-ca-history' => 'Hea panacheo adleo uzollnneo',
+'tooltip-ca-protect' => 'Hem pan rakh',
+'tooltip-ca-delete' => 'Hem pan vogllai',
+'tooltip-ca-move' => 'Hem pan fuddem vhor',
+'tooltip-ca-watch' => 'Hem pan tujea sadurvollerint zodd',
+'tooltip-ca-unwatch' => 'Hem pan tumchea sadurtaievelean kadd',
+'tooltip-search' => '{{SITENAME}}  sod',
+'tooltip-search-go' => 'Hea just nanvachem pan asa zalear tea panar voch',
+'tooltip-search-fulltext' => 'Hea utarea khatir pana sod',
+'tooltip-p-logo' => 'Mukhel panak bhett di',
+'tooltip-n-mainpage' => 'Mukhel panak bhett di',
+'tooltip-n-mainpage-description' => 'Mukhel Panak bhett di',
+'tooltip-n-portal' => 'Hea prokolpa vixim, tumchean kitem korum ieta, khoim kitem sodchem',
+'tooltip-n-currentevents' => 'Chalu ghoddneachea fattbhuichi mahiti sod',
+'tooltip-n-recentchanges' => 'Wikint halinch bodol keleleachi volleri',
+'tooltip-n-randompage' => 'Khoincheim ek pan uktem kor',
+'tooltip-n-help' => 'sodpachem tholl',
+'tooltip-t-whatlinkshere' => 'Hanga zoddlelea sogllea wiki pananchi volleri',
+'tooltip-t-recentchangeslinked' => 'Hea panak zoddlelea panachim halinchim bodolpam',
+'tooltip-feed-atom' => 'Hea panak Atom purovnni',
+'tooltip-t-contributions' => 'Hea vapuddpeachea borovpanchi suchi',
+'tooltip-t-emailuser' => 'Hea vapuddpeak email patthoi',
+'tooltip-t-upload' => 'Faili upload kor',
+'tooltip-t-specialpages' => 'Kherit pananchi volleri',
+'tooltip-t-print' => 'Hea panachem chhapunk ietelem rupantor',
+'tooltip-t-permalink' => 'Hea panache uzollnnek togpi zodd',
+'tooltip-ca-nstab-main' => 'Suchi pan polloi',
+'tooltip-ca-nstab-user' => 'Vapuddpeachem pan polloi',
+'tooltip-ca-nstab-special' => 'Hem ek kherit pan, tujeam hem pan sudarunk zaina',
+'tooltip-ca-nstab-project' => 'Project-achem pan polloi',
+'tooltip-ca-nstab-image' => 'Failichem pan polloi',
+'tooltip-ca-nstab-template' => 'Saacho polloi',
+'tooltip-ca-nstab-category' => 'Vorgachem pan polloi',
+'tooltip-minoredit' => 'Haka ek kirkoll sudharop mhunn khunnay',
+'tooltip-save' => 'Tujim bodolpam sambhall',
+'tooltip-preview' => 'Bodlopanchi zholok polloi, upkar hem samballche adim vapor!',
+'tooltip-diff' => 'Tumi hea mozkurant kelelo bodol dakhoiat',
+'tooltip-compareselectedversions' => 'Hea panacheo don nivoddleleo uzollneo modem forok polloi',
+'tooltip-watch' => 'Hem pan tujea xadurvollerint zodd',
+'tooltip-rollback' => '"Kovllop" hea panachea xevttachea borovpa kodde kea kollant portota.',
+'tooltip-undo' => '"Rodd\' kor" sudharop portita ani sudharopak Zholok ritin ukodta. Tem saran karon zoddunk dita.',
+'tooltip-summary' => 'Mottvo sar ghal',
+
+# Info page
+'pageinfo-toolboxlink' => 'Panachi mahiti',
+
+# Browsing diffs
+'previousdiff' => '←  Adlo sudar',
+'nextdiff' => 'Fuddlem bodlop →',
+
+# Media information
+'file-info-size' => '$1 × $2 pixelam, failicho akar: $3, MIME prokar: $4',
+'file-nohires' => 'Odhik bariksai na.',
+'svg-long-desc' => 'SVG fail, nanvak $1 × $2 pixeli, failcho akar: $3',
+'show-big-image' => 'Mull fail',
+
+# Bad image list
+'bad_image_list' => 'Akar oso asa:
+
+Fokot suchicheo vostu (*-chean suru zateleo) dheanant ghevcheo
+Tech vollir, uprantli zoddnni opvad dhorpant ieta,mhonnche zoim pana failichea ek vollint asunk xoktat.',
+
+# Metadata
+'metadata' => 'Metadata',
+'metadata-help' => "Hea failin anikui mahiti asa, hi fail korunk uzar kel'le digital camera vo scanner sun tem aila zait.
+Zori tor hi failik bodol'lam zalear kai mahiti bodololem failik sarkem mell khaina zait.",
+'metadata-fields' => 'Metadata chovkott konsollttoch, hea sondexant metadata molleantlea murtipanachea dakhovnnent aspav astolo.
+* make
+* model
+* datetimeoriginal
+* exposuretime
+* fnumber
+* isospeedratings
+* focallength
+* artist
+* copyright
+* imagedescription
+* gpslatitude
+* gpslongitude
+* gpsaltitude',
+
+# External editor support
+'edit-externally' => 'Hea failik bhaili program uzar korun bodol.',
+'edit-externally-help' => '(Odhik mahite khatir [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] polloi)',
+
+# 'all' in various places, this might be different for inflected languages
+'watchlistall2' => 'soglle',
+'namespacesall' => 'sogllem',
+'monthsall' => 'sogllem',
+
+# Watchlist editing tools
+'watchlisttools-view' => 'Sombondhi bodlopam polloi',
+'watchlisttools-edit' => 'Sadurvolleri polloi ani sudar',
+'watchlisttools-raw' => 'Sadurvollerichi mull-an bodol kor',
+
+# Core parser functions
+'duplicate-defaultsort' => "'''Chotrai:''' Falta anukraman mukhel ''$2'' rodd korta adhlem falta anukraman mukhel ''$1'', haka.",
+
+# Special:SpecialPages
+'specialpages' => 'Khaxelim Panam',
+
+# External image whitelist
+'external_image_whitelist' => " #Hi voll asa toxich dovor<pre>
+#Khala sodpache sache (''regular expressions'') ghal (fokot // modem voita poi tem bhag)
+#Hanche borobor bhaile zodlele murt comparar kel'le zatele
+#Mell khatat tim murt koxeo distele, na zalear fokot mortek ek zodd distele
+#Jeo voll #-an suru zatele tem vivek mhunn manlele zatele
+#Hanga vhodle and dhakte okxora modem forok podona
+
+#Soglle sodpache sache hea volla voir ghal. Hi voll asa toxich dovor</pre>",
+
+# Special:Tags
+'tag-filter' => '[[Special:Tags|Dospi]] challni:',
+
+# Search suggestions
+'searchsuggest-search' => 'Sod',
+
+);
index f1161fd..9a4a2c1 100644 (file)
@@ -290,8 +290,6 @@ $1',
 'ok' => 'εἶεν',
 'retrievedfrom' => 'Ἀνακτηθεῖσα ὑπὸ "$1"',
 'youhavenewmessages' => 'Ἔχεις $1 ($2).',
-'newmessageslink' => 'νέας ἀγγελίας',
-'newmessagesdifflink' => 'ἐσχάτη μεταβολή',
 'youhavenewmessagesmulti' => 'Νέας εἰσί σοι ἀγγελίας ἐν $1',
 'editsection' => 'μεταγράφειν',
 'editold' => 'μεταγράφειν',
@@ -826,8 +824,6 @@ $1",
 'preferences' => 'Προαιρέσεις',
 'mypreferences' => 'Αἱ προαιρέσεις μου',
 'prefs-edits' => 'Τοσοῦται αἱ μεταβολαί:',
-'prefsnologin' => 'Μὴ συνδεδεμένος',
-'prefsnologintext' => 'Δεῖ σε <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} συνδεδεμένος εἶναι]</span> πρὸ τοῦ καθορίσειν τὰς ἐσοῦ προαιρέσεις χρωμένου.',
 'changepassword' => 'Ἀλλάττειν σύνθημα',
 'prefs-skin' => 'Ἐμφάνισις',
 'skin-preview' => 'Προεπισκοπεῖν',
@@ -1071,6 +1067,7 @@ $1",
 'recentchanges-label-minor' => 'Ἥδε μικρὰ μεταγραφή ἐστιν',
 'recentchanges-label-bot' => 'Ἥδε ἡ μεταγραφὴ ἐτελέσθη ὑπὸ αὐτομάτου τινός',
 'recentchanges-label-unpatrolled' => 'Ἥδε ἡ μεταγραφὴ μὴ ἐλεγμένη ἐστίν',
+'recentchanges-legend-newpage' => '$1 - νέα δέλτος',
 'rcnote' => "Κατωτέρω {{PLURAL:$1|ἐστὶ '''1''' ἀλλαγὴ|εἰσὶν αἱ τελευταῖαι '''$1''' ἀλλαγαὶ}} ἐν {{PLURAL:$2|τῇ τελευταίᾳ ἡμέρᾳ|ταῖς τελευταίαις '''$2''' ἡμέραις}}, ἕως καὶ $5, $4.",
 'rcnotefrom' => "Ἰδοῦ αἱ ἀλλαγαὶ ἐκ τοῦ '''$2''' (ἕως τὸ '''$1''').",
 'rclistfrom' => 'Δεικνύναι νέας ἀλλαγάς. Ἐκκίνησις ἐκ τοῦ $1',
@@ -2443,7 +2440,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Μεταγράφειν τόδε τὸ ἀρχεῖον χρώμενος ἐξώτερήν τινα ἐφαρμογήν.',
-'edit-externally-help' => 'Εἰ πλείοντα βούλει μαθεῖν, [//www.mediawiki.org/wiki/Manual:External_editors τὰς περὶ τοῦ σχῆματος διδασκαλίας] ἴδε.',
+'edit-externally-help' => 'Εἰ πλείοντα βούλει μαθεῖν, [https://www.mediawiki.org/wiki/Manual:External_editors τὰς περὶ τοῦ σχῆματος διδασκαλίας] ἴδε.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ἅπασαι',
@@ -2590,8 +2587,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Εἰδικαὶ δέλτοι',
-'specialpages-note' => '----
-* Κανονικαὶ εἰδικαὶ δέλτοι.
+'specialpages-note' => '* Κανονικαὶ εἰδικαὶ δέλτοι.
 * <strong class="mw-specialpagerestricted">Περιωρισμέναι εἰδικαὶ δἐλτοι.</strong>
 * <span class="mw-specialpagecached">Μόναι δέλτοι ἀποτεταμιευμέναι.</span>',
 'specialpages-group-maintenance' => 'Ἀναφοραὶ συντηρήσεως',
@@ -2669,4 +2665,10 @@ $5
 'searchsuggest-search' => 'Ζητεῖν',
 'searchsuggest-containing' => 'περιέχον...',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Ἐπεκτείνειν τὰ πρότυπα',
+'expand_templates_output' => 'Ἀποτέλεσμα',
+'expand_templates_ok' => 'εἶεν',
+'expand_templates_preview' => 'Προθεώρησις',
+
 );
index 46e3e29..aa24766 100644 (file)
@@ -36,7 +36,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Nit-gültige_Sytename' ),
        'Blankpage'                 => array( 'Läärsyte' ),
        'Block'                     => array( 'Sperre' ),
-       'Blockme'                   => array( 'Proxy-Sperre' ),
        'Booksources'               => array( 'ISBN-Suech' ),
        'BrokenRedirects'           => array( 'Kaputti_Wyterlaitige' ),
        'Categories'                => array( 'Kategorie' ),
@@ -48,10 +47,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Benutzerchonto_aaleege' ),
        'Deadendpages'              => array( 'Sackgassesyte' ),
        'DeletedContributions'      => array( 'Gleschti_Byytreeg' ),
-       'Disambiguations'           => array( 'Begriffschlärigsverwyys' ),
        'DoubleRedirects'           => array( 'Doppleti_Wyterlaitige' ),
        'EditWatchlist'             => array( 'Bearbeitigslischt_bearbeite' ),
        'Emailuser'                 => array( 'E-Mail' ),
+       'ExpandTemplates'           => array( 'Vorlage_expandiere' ),
        'Export'                    => array( 'Exportiere' ),
        'Fewestrevisions'           => array( 'Syte_wo_am_wenigschte_bearbeitet_sin' ),
        'FileDuplicateSearch'       => array( 'Datei-Duplikat-Suech' ),
@@ -93,6 +92,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Gschitzti_Syte' ),
        'Protectedtitles'           => array( 'Gsperrti_Titel' ),
        'Randompage'                => array( 'Zuefelligi_Syte' ),
+       'RandomInCategory'          => array( 'Zuefelligi_Kategori' ),
        'Randomredirect'            => array( 'Zuefelligi_Wyterleitig' ),
        'Recentchanges'             => array( 'Letschti_Änderige' ),
        'Recentchangeslinked'       => array( 'Änderige_an_verlinkte_Syte' ),
@@ -140,12 +140,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Vum Fäldhieter aagluegti Änderige in dr „Letschte Änderige“ usblände',
 'tog-newpageshidepatrolled' => 'Aagluegti Syten uf dr Lischt „Neiji Syte“ verstecke',
 'tog-extendwatchlist' => 'Beobachtungslischte erwytere go alli Änderige aazeige, nit numme di letschte',
-'tog-usenewrc' => 'Sytebezogeni Gruppierig bi dr «letschte Änderige» un uf dr Beobachtigslischte  (brucht JavaScript)',
+'tog-usenewrc' => 'Änderigen uf „Letschte Änderige“ un dr Beobachtigslischt no Syte gruppiere',
 'tog-numberheadings' => 'Überschrifte outomatisch numeriere',
-'tog-showtoolbar' => 'Editier-Wärchzüüg aazeige',
-'tog-editondblclick' => 'Syte ändere mit Doppelklick i d Syte (JavaScript)',
+'tog-showtoolbar' => 'Wärchzyyglyscht zum Bearbeite aazeige',
+'tog-editondblclick' => 'Syte ändere mit Doppelklick',
 'tog-editsection' => 'Links aazeige für ds Bearbeite vo einzelnen Absätz',
-'tog-editsectiononrightclick' => 'Einzelni Absätz ändere mit Rächtsclick (Javascript)',
+'tog-editsectiononrightclick' => 'Einzelni Absätz ändere mit Rächtsclick uf d Iberschrifte',
 'tog-showtoc' => 'Inhaltsverzeichnis aazeige bi Artikle mit meh als drei Überschrifte',
 'tog-rememberpassword' => 'Mit däm Browser duurhaft aamälde (Maximal fir $1 {{PLURAL:$1|Tag|Täg}})',
 'tog-watchcreations' => 'Sälber gmachti Sytene un uffegladeni Dateie automatisch  beobachte',
@@ -163,7 +163,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Aazahl Benutzer aazeige, wo ne Syten am Aaluege sy (i den Artikelsyte, i de «letschten Änderigen» und i der Beobachtigslischte)',
 'tog-oldsig' => 'Vorschau vu dr Unterschrift:',
 'tog-fancysig' => 'Signatur as Wikitext behandle (ohni automatischi Vergleichig)',
-'tog-uselivepreview' => 'Live-Vorschau bruche (JavaScript) (experimentell)',
+'tog-uselivepreview' => 'Live-Vorschau bruche (experimentell)',
 'tog-forceeditsummary' => 'Sag mer s, wänn i s Zämmefassigsfeld läär loss',
 'tog-watchlisthideown' => 'Eigeni Änderige uf d Beobachtigslischt usblände',
 'tog-watchlisthidebots' => 'Bot-Änderige in d Beobachtigslischt usblende',
@@ -177,6 +177,7 @@ $messages = array(
 'tog-noconvertlink' => 'Konvertierig vum Titel deaktiviere',
 'tog-norollbackdiff' => 'Unterschid noch em Zrucksetze unterdrucke',
 'tog-useeditwarning' => 'Warn mi, wänn I ne Syte verloss mit Bearbeitige, wu nonig gspycheret sin',
+'tog-prefershttps' => 'Wänn aagmäldet, alliwyl e sicheri Verbindig bruuche',
 
 'underline-always' => 'immer',
 'underline-never' => 'nie',
@@ -240,6 +241,18 @@ $messages = array(
 'oct' => 'Okt.',
 'nov' => 'Nov.',
 'dec' => 'Dez.',
+'january-date' => '$1. Jänner',
+'february-date' => '$1. Februar',
+'march-date' => '$1. Merz',
+'april-date' => '$1. April',
+'may-date' => '$1. Mai',
+'june-date' => '$1. Juni',
+'july-date' => '$1. Juli',
+'august-date' => '$1. Augschte',
+'september-date' => '$1. Septämber',
+'october-date' => '$1. Oktober',
+'november-date' => '$1. Novämber',
+'december-date' => '$1. Dezämber',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Kategori|Kategorie}}',
@@ -265,6 +278,7 @@ $messages = array(
 'newwindow' => '(imene nöie Fänschter)',
 'cancel' => 'Abbräche',
 'moredotdotdot' => 'Meh …',
+'morenotlisted' => 'Die Lischt isch nit vollständig.',
 'mypage' => 'Syte',
 'mytalk' => 'Diskussionsyte',
 'anontalk' => 'Diskussionssyste vo sellere IP',
@@ -298,6 +312,7 @@ $messages = array(
 'namespaces' => 'Namensryym',
 'variants' => 'Variante',
 
+'navigation-heading' => 'Navigationsmenü',
 'errorpagetitle' => 'Fähler',
 'returnto' => 'Zruck zur Syte $1.',
 'tagline' => 'Us {{SITENAME}}',
@@ -319,6 +334,7 @@ $messages = array(
 'create-this-page' => 'Die Syte afange',
 'delete' => 'Lesche',
 'deletethispage' => 'Syte lösche',
+'undeletethispage' => 'Die Syte widerhärstelle',
 'undelete_short' => '{{PLURAL:$1|1 Version|$1 Versione}} widerherstelle',
 'viewdeleted_short' => '{{PLURAL:$1|ei gleschti Änderig|$1 gleschti Ändrige}} aaluege',
 'protect' => 'Schütze',
@@ -335,7 +351,7 @@ $messages = array(
 'articlepage' => 'Syte',
 'talk' => 'Diskussion',
 'views' => 'Wievylmol agluegt',
-'toolbox' => 'Wärkzügkäschtli',
+'toolbox' => 'Wärchzyyg',
 'userpage' => 'Benutzersyte',
 'projectpage' => 'Projektsyte azeige',
 'imagepage' => 'Dateisyte',
@@ -366,7 +382,7 @@ Di maximal Wartezyt fir e Lock isch umme',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Über {{GRAMMAR:akkusativ|{{SITENAME}}}}',
 'aboutpage' => 'Project:Über {{UCFIRST:{{GRAMMAR:akkusativ|{{SITENAME}}}}}}',
-'copyright' => 'Der Inhalt vo dere Syte stoht unter der $1.',
+'copyright' => 'Dr Inhalt vu dere Syte stoht unter dr Lizänz $1, wänn s nit andersch aagee isch.',
 'copyrightpage' => '{{ns:project}}:Copyright',
 'currentevents' => 'Aktuelli Mäldige',
 'currentevents-url' => 'Project:Aktuelli Termin',
@@ -392,12 +408,10 @@ Di maximal Wartezyt fir e Lock isch umme',
 'ok' => 'OK',
 'retrievedfrom' => 'Vun "$1"',
 'youhavenewmessages' => 'Du hesch $1 ($2).',
-'newmessageslink' => 'nöji Nachrichte',
-'newmessagesdifflink' => 'Unterschid',
 'youhavenewmessagesfromusers' => 'Du hesch $1 vu {{PLURAL:$3|eme andere Benutzer|$3 Benutzer}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du hesch $1 vu vil Benutzer ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|e neji Nochricht|neji Nochrichte}}',
-'newmessagesdifflinkplural' => 'letschti {{PLURAL:$1|Änderig|Änderige}}',
+'newmessageslinkplural' => '{{PLURAL:$1|e neji Nochricht|999=neji Nochrichte}}',
+'newmessagesdifflinkplural' => 'letschti {{PLURAL:$1|Änderig|999=Änderige}}',
 'youhavenewmessagesmulti' => 'Si hen neui Nochrichte: $1',
 'editsection' => 'ändere',
 'editold' => 'Ändre',
@@ -449,6 +463,12 @@ Alli verfiegbare Spezialsyte sin in dr [[Special:SpecialPages|Lischt vu Spezials
 # General errors
 'error' => 'Fähler',
 'databaseerror' => 'Fähler in dr Datebank',
+'databaseerror-text' => 'S het e Datebankabfrogfähler gee.
+Des chennt e Fähler in dr Software aazeige.',
+'databaseerror-textcl' => 'S het e Datebankabfrogfähler gee.',
+'databaseerror-query' => 'Abfrog: $1',
+'databaseerror-function' => 'Funktion: $1',
+'databaseerror-error' => 'Fähler: $1',
 'laggedslavemode' => 'Warnig: di letschte Änderige wäre u. U. nonig aazeigt!',
 'readonly' => 'Datebank isch gsperrt',
 'enterlockreason' => 'Bitte gib e Grund y, worum d Datebank soll gsperrt wäre un e Yschätzig wie lang si soll gsperrt blybe',
@@ -479,6 +499,7 @@ Wänn s des nit isch, hesch villicht e Fähler in dr Software gfunde. Bitte mäl
 'cannotdelete' => 'D Syte oder d Datei „$1“ cha nit glescht wäre. Si isch villicht scho vu eber anderem glescht wore.',
 'cannotdelete-title' => 'Syte „$1“ cha nit glescht wäre',
 'delete-hook-aborted' => 'D Leschig isch ohni Erchlärung dur e Schnittstell abbroche wore.',
+'no-null-revision' => 'Di nej Nullversion fir d Syte „$1“ het nit chennen aagleit wäre',
 'badtitle' => 'Ugültiger Titel',
 'badtitletext' => 'Dr Titel vu dr agforderte Syte isch nit giltig gsi, leer, oder e nit giltig Sprochgleich vun eme andre Wiki.',
 'perfcached' => 'Die Informatione chemme us em Zwischespycher un sin derwyl villicht nit aktuäll. Maximal {{PLURAL:$1|ei Ergebnis isch|$1 Ergebnis sin}} im Cache verfiegbar.',
@@ -501,6 +522,10 @@ $2',
 'namespaceprotected' => "Du hesch kei Berächtigung, die Syte im '''$1'''-Namensruum z bearbeite.",
 'customcssprotected' => 'Du bisch nid berächtigt, die Syte mit CSS z bearbeite, wel si zue dr persenlige Yystellige vun eme andere Benutzer ghert.',
 'customjsprotected' => 'Du bisch nid berächtigt, die Javaskript-Syte z bearbeite, wel si zue dr persenlige Yystellige vun eme andere Benutzer ghert.',
+'mycustomcssprotected' => 'Du derfsch die CSS-Syte nit bearbeite.',
+'mycustomjsprotected' => 'Du derfsch die JavaScript-Syte nit bearbeite.',
+'myprivateinfoprotected' => 'Du derfsch Dyni privaten Informatione nit bearbeite.',
+'mypreferencesprotected' => 'Du derfsch Dyni Yystellige nit bearbeite.',
 'ns-specialprotected' => 'Spezialsyte chenne nid bearbeitet wäre.',
 'titleprotected' => "E Syte mit däm Name cha nid aaglait wäre.
 Die Sperri isch dur [[User:$1|$1]] yygrichtet wore mit dr Begrindig ''„$2“''.",
@@ -510,7 +535,8 @@ Dr Administrator, wu dr Schrybzuegriff gsperrt het, het dää Grund aagee: „$3
 'invalidtitle-knownnamespace' => 'Nit-gültige Titel mit Namensruum „$2“ un Text „$3“',
 'invalidtitle-unknownnamespace' => 'Ungültige Titel mit unbekannte Namensruumnummer $1 un Text „$2“',
 'exception-nologin' => 'Nit aagmäldet',
-'exception-nologin-text' => 'Fir die Syte oder Aktion muesch aagmäldet syy.',
+'exception-nologin-text' => 'Du muesch Di [[Special:Userlogin|aamälde]] go die Syte oder Aktion ufruefe chenne.',
+'exception-nologin-text-manual' => 'Du muesch Di $1 go die Syte oder Aktion ufruefe chenne.',
 
 # Virus scanner
 'virus-badscanner' => "Fählerhafti Konfiguration: Virescanner, wu nid bekannt isch: ''$1''",
@@ -520,13 +546,24 @@ Dr Administrator, wu dr Schrybzuegriff gsperrt het, het dää Grund aagee: „$3
 # Login and logout pages
 'logouttext' => "'''Du bisch jetz abgmäldet.'''
 
-Du chasch {{SITENAME}} wyter anonym bruche, oder Du chasch di <span class='plainlinks'>[$1 wider aamälde]</span> mit em glyche oder eme andere Benutzername.
-
-Ochat: s cha syy, ass bstimmti Syte eso aazeigt wäre, wie wänn Du allno aagmäldet wärsch, bis Du dr Zwischespycher vu Dyym Browser glescht hesch.",
+Obacht: s cha syy, ass bstimmti Syte eso aazeigt wäre, wie wänn Du allno aagmäldet wärsch, bis Du dr Zwischespycher vu Dyym Browser glescht hesch.",
+'welcomeuser' => 'Willchuu, $1!',
+'welcomecreation-msg' => 'Dyy Benutzerkonto isch aagleit wore.
+Vergiss nit, Dyni [[Special:Preferences|{{SITENAME}}-Yystellige]] z ändere.',
 'yourname' => 'Dyy Benutzername',
+'userlogin-yourname' => 'Benutzername',
+'userlogin-yourname-ph' => 'Gib Dyy Benutzernamen yy',
+'createacct-another-username-ph' => 'Gib Dyy Benutzernamen yy',
 'yourpassword' => 'Passwort:',
+'userlogin-yourpassword' => 'Passwort',
+'userlogin-yourpassword-ph' => 'Gib Dyy Passwort yy',
+'createacct-yourpassword-ph' => 'Passwort yygee',
 'yourpasswordagain' => 'Passwort no mol yygee:',
+'createacct-yourpasswordagain' => 'Passwort bstetige',
+'createacct-yourpasswordagain-ph' => 'Gib s Passwort nomol yy',
 'remembermypassword' => 'Uf däm Computer duurhaft aamälde (Maximal fir $1 {{PLURAL:$1|Tag|Täg}})',
+'userlogin-remembermypassword' => 'Aagmäldet blyybe',
+'userlogin-signwithsecure' => 'Sicheri Verbindig bruuche',
 'yourdomainname' => 'Dyyni Domäne',
 'password-change-forbidden' => 'Du chasch uf däm Wiki kei Passwerter ändere.',
 'externaldberror' => 'Entwäder s lit e Fähler bi dr externe Authentifizierung vor, oder Du derfsch Dyy extern Benutzerkonto nid aktualisiere.',
@@ -538,18 +575,44 @@ Ochat: s cha syy, ass bstimmti Syte eso aazeigt wäre, wie wänn Du allno aagmä
 'logout' => 'Abmälde',
 'userlogout' => 'Abmälde',
 'notloggedin' => 'Nit aagmäldet',
+'userlogin-noaccount' => 'No kei Benutzerkonto?',
+'userlogin-joinproject' => 'Bi {{SITENAME}} aamälde',
 'nologin' => 'No kei Benutzerkonto? $1.',
 'nologinlink' => '»Konto aaleege«',
 'createaccount' => 'Nöis Benutzerkonto aalege',
 'gotaccount' => "Du häsch scho a Konto? '''$1'''",
 'gotaccountlink' => '»Login fir Benutzer, wu scho aagmäldet sin«',
 'userlogin-resetlink' => 'Hesch Dyy Aamäldedate vergässe?',
-'createaccountmail' => 'iber E-Mail',
+'userlogin-resetpassword-link' => 'Passwort vergässe?',
+'helplogin-url' => 'Help:Aamälde',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hilf bim Aamälde]]',
+'userlogin-loggedin' => 'Du bisch scho as {{GENDER:$1|$1}} aagmäldet.
+Bruuch s Formular unte go Di unter eme andere Benutzername aamälde.',
+'userlogin-createanother' => 'En ander Benutzerkonto aalege',
+'createacct-join' => 'Gib unte Dyni Informationen yy.',
+'createacct-another-join' => 'Gib unte d Informatione vum neie Benutzerkonto yy.',
+'createacct-emailrequired' => 'E-Mail-Adräss',
+'createacct-emailoptional' => 'E-Mail-Adräss (optional)',
+'createacct-email-ph' => 'Gib Dyy E-Mail-Adräss yy',
+'createacct-another-email-ph' => 'Gib Dyy E-Mail-Adräss yy',
+'createaccountmail' => 'E temporär Zuefallspasswort bruuchen un an di aagee E-Mail-Adräss schicke',
+'createacct-realname' => 'Richtige Name (optional)',
 'createaccountreason' => 'Grund:',
+'createacct-reason' => 'Grund',
+'createacct-reason-ph' => 'Wurum Du ne ander Benutzerkonto aaleisch',
+'createacct-captcha' => 'Sicherheitspriefig',
+'createacct-imgcaptcha-ph' => 'Gib dr Tekscht yy, wu Du obe siisch',
+'createacct-submit' => 'Dyy Benutzerkonto aalege',
+'createacct-another-submit' => 'En ander Benutzerkonto aalege',
+'createacct-benefit-heading' => '{{SITENAME}} wird vu Mänsche wie Dir gschaffe.',
+'createacct-benefit-body1' => '{{PLURAL:$1|Bearbeitig|Bearbeitige}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|Syte|Syte}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|aktive Autor|aktivi Autore}}',
 'badretype' => 'Di beidi Passwörter stimme nid zämme.',
 'userexists' => 'Dä Benutzername git s scho.
 Bitte nimm e andere.',
 'loginerror' => 'Fähler bir Aamäldig',
+'createacct-error' => 'Fähler bim Aalege vum Benutzerkonto',
 'createaccounterror' => 'Het s Benutzerkonto nit chenne aalege: $1',
 'nocookiesnew' => 'Dr Benutzerzuegang isch aaglait wore, aber Du bisch nid yygloggt. {{SITENAME}} brucht fir die Funktion Cookies, bitte tue die aktiviere un logg Di derno mit Dyynem neje Benutzername un em Passwort, wu drzue ghert, yy.',
 'nocookieslogin' => '{{SITENAME}} brucht Cookies fir e Aamäldig. Du hesch d Cookies deaktiviert. Aktivier si bitte un versuech s no mol.',
@@ -594,7 +657,7 @@ Voreb ass no mee Mails iber d {{SITENAME}}-Mailfunktion an die Adräss gschickt
 'acct_creation_throttle_hit' => 'Bsuecher vu däm Wiki, wu Dyyni IP-Adräss bruuche, hän innerhalb vum letschte Tag {{PLURAL:$1|1 Benutzerkonto|$1 Benutzerkonte}} aagleit. Des isch di maximal Aazahl, wu in däm Zytruum erlaubt isch.
 
 Bsuecher, wu die IP-Adräss bruuche, chenne im Momänt kei Benutzerkonte meh aalege.',
-'emailauthenticated' => 'Di E-Mail-Adräss isch am $2 um $3 Uhr bschtätigt worde.',
+'emailauthenticated' => 'Dyy E-Mail-Adräss isch am $2 am $3 Uhr bstetigt wore.',
 'emailnotauthenticated' => 'Dyni E-Mail-Adräss isch nonig bstätigt. Wäg däm gehn di erwyterete E-Mail-Funktione nonig.
 Fir d Bstätigung muesch em Link nogoh, wu Dir gschickt woren isch. Du chasch au e neie sonig Link aafordere:',
 'noemailprefs' => 'Du hesch kei E-Mail-Adrässen aaggä, drum sy di folgende Funktione nid müglech.',
@@ -604,20 +667,23 @@ Bitte gib ä neiji Adress in nem gültige Format ii, odr tue s Feld leere.',
 'cannotchangeemail' => 'E-Mail-Adrässe chönne in däm Wiki nit gänderet werde.',
 'emaildisabled' => 'Iber die Websyte chenne kei E-Mail verschickt wäre.',
 'accountcreated' => 'S Benutzerkonto isch aagleit wore.',
-'accountcreatedtext' => 'S Benutzerkonto $1 isch aagleit wore.',
+'accountcreatedtext' => 'S Benutzerkonto fir [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|Diskussion]]) isch aagleit wore.',
 'createaccount-title' => 'Aalege vum e Benutzerkonto fir {{SITENAME}}',
 'createaccount-text' => 'Fir Dii isch e Benutzerkonto "$2" uf {{SITENAME}} ($4) aaglait wore. S Passwort fir "$2" , wu automatisch generiert woren isch, isch "$3". Du sottsch Di jetz aamälde un s Passwort ändere.
 
 Wänn s Benutzerkonto us Versäh aaglait woren isch, chasch die Nochricht ignoriere.',
 'usernamehasherror' => 'In Benutzernäme derf s kei Rautezeiche din haa',
-'login-throttled' => 'Du hesch z vilmol vergebli versuecht, Di aazmälde. Bitte wart, voreb Du s non emol versuechsch.',
+'login-throttled' => 'Du hesch z vilmol umesuscht versuecht, Di aazmälde. Bitte wart $1, voreb Du s non emol versuechsch.',
 'login-abort-generic' => 'Dyy Aamäldig isch nit erfolgryych gsii – Abbroche',
 'loginlanguagelabel' => 'Sproch: $1',
 'suspicious-userlogout' => 'Dyy Versuech di abzmälde isch abbroche wore, wel s uusgsäh het, wie wänn s vun eme bschedigte Browser oder eme Cacheproxy uus gsändet woren isch.',
+'createacct-another-realname-tip' => 'Dr richtig Name isch optional.
+Wänn Du ne aagiisch, wird er bruucht fir d Zueornig vu dr Byytreg.',
 
 # Email sending
 'php-mail-error-unknown' => 'Nit bekannte Fähler mit dr Funktion mail() vu PHP',
 'user-mail-no-addy' => 'Es isch versuecht worde e E-Mail ohni Angab vunere E-Mail-Adräss z verschigge.',
+'user-mail-no-body' => 'S isch versuecht wore, ne E-Mail mit eme lääre oder z churze Tekscht z verschicke.',
 
 # Change password dialog
 'resetpass' => 'Passwort fir s Benutzerkonto ändere oder zrucksetze',
@@ -628,7 +694,7 @@ Wänn s Benutzerkonto us Versäh aaglait woren isch, chasch die Nochricht ignori
 'newpassword' => 'Nöis Passwort',
 'retypenew' => 'Nöis Passwort (es zwöits Mal)',
 'resetpass_submit' => 'Passwort ibermittle un aamälde',
-'changepassword-success' => 'Dyy Passwort isch erfolgryych gänderet wore. Jetz chunnt d Aamäldig …',
+'changepassword-success' => 'Dyy Passwort isch erfolgryych gänderet wore.',
 'resetpass_forbidden' => 'S Passwort cha nid gänderet wäre.',
 'resetpass-no-info' => 'Du muesch Di aamälde zum uf die Syte diräkt zuegryfe z chenne.',
 'resetpass-submit-loggedin' => 'Passwort ändere',
@@ -636,34 +702,42 @@ Wänn s Benutzerkonto us Versäh aaglait woren isch, chasch die Nochricht ignori
 'resetpass-wrong-oldpass' => 'S temporär oder aktuäll Passwort isch nimi giltig.
 Villicht hesch Dyy Passwort scho gänderet oder e nej temporär Passwort aagforderet.',
 'resetpass-temp-password' => 'Temporär Passwort:',
+'resetpass-abort-generic' => 'D Passwortänderig isch dur e Erwyterig abbroche wore.',
 
 # Special:PasswordReset
 'passwordreset' => 'Passwort zruggsetze',
+'passwordreset-text-one' => 'Fill des Formular uus go Dy Passwort zrucksetze.',
+'passwordreset-text-many' => '{{PLURAL:$1|Fill eis vu dr Fälder uus go Dy Passwort zrucksetze.}}',
 'passwordreset-legend' => 'Passwort zrucksetze',
 'passwordreset-disabled' => 'S Zrucksetze vu Passwerter isch in däm Wiki deaktiviert wore.',
+'passwordreset-emaildisabled' => 'D E-Mail-Funktione sin uf däm Wiki deaktiviert wore.',
 'passwordreset-username' => 'Benutzername:',
 'passwordreset-domain' => 'Domain:',
 'passwordreset-capture' => 'Die E-Mail aaluege?',
 'passwordreset-capture-help' => 'Wänn du des Chäschtli aachrüüzesch, no wird die E-Mail (mit em temporäre Passwort) dir aazeigt, un au em Benutzer zuegschiggt.',
 'passwordreset-email' => 'E-Mail-Adräss:',
 'passwordreset-emailtitle' => 'Benutzerkontoinformationen uf {{SITENAME}}',
-'passwordreset-emailtext-ip' => 'Eber mit dr IP-Adresse $1, wahrschyns Du sälber, het e Erinnerig an Dyyni Benutzerkonteninformatione fir {{SITENAME}} aagforderet ($4). {{PLURAL:$3|Des Benutzerkonto isch|Die Benutzerkonte sin}} mit däre E-Mail-Adräss verchnipft:
+'passwordreset-emailtext-ip' => 'Eber mit dr IP-Adresse $1, wahrschyns Du sälber, het e Erinnerig an Dyyni Benutzerkonteninformatione fir {{SITENAME}} aagforderet ($4). 
+
+{{PLURAL:$3|Des Benutzerkonto isch|Die Benutzerkonte sin}} mit däre E-Mail-Adräss verchnipft: 
 
-$2
+$2 
 
 {{PLURAL:$3|Des temporär Passwort lauft|Die temporäre Passwerter laufe}} in {{PLURAL:$5|eim Tag|$5 Täg}} ab.
 Du sottsch di aamälden un e nej Passwort vergee. Wänn eber ander die Aafrog gstellt het oder Du di wider an Dyy alt Passwort chasch erinnere un s nimi wettsch ändere, chasch die Nochricht ignorieren un alsfurt Dyy alt Passwort bruche.',
-'passwordreset-emailtext-user' => 'Benutzer $1 uf {{SITENAME}} het e Erinnerig an Dyyni Benutzerkonteninformatione fir {{SITENAME}} aagforderet ($4). {{PLURAL:$3|Des Benutzerkonto isch|Die Benutzerkonte sin}} mit däre E-Mail-Adräss verchnipft:
+'passwordreset-emailtext-user' => 'Dr Benutzer $1 bi {{SITENAME}} het e Zrucksetzig vu Dym Passwort bi {{SITENAME}} aagforderet ($4). 
+
+{{PLURAL:$3|Des Benutzerkonto isch|Die Benutzerkonte sin}} mit däre E-Mail-Adräss verchnipft: 
 
-$2
+$2 
 
 {{PLURAL:$3|Des temporär Passwort lauft|Die temporäre Passwerter laufe}} in {{PLURAL:$5|eim Tag|$5 Täg}} ab.
 Du sottsch di aamälden un e nej Passwort vergee. Wänn eber ander die Aafrog gstellt het oder Du di wider an Dyy alt Passwort chasch erinnere un s nimi wettsch ändere, chasch die Nochricht ignorieren un alsfurt Dyy alt Passwort bruche.',
 'passwordreset-emailelement' => 'Benutzername: $1
 Temporär Passwort: $2',
-'passwordreset-emailsent' => 'E Erinnerig isch per E-Mail verschickt wore.',
-'passwordreset-emailsent-capture' => 'E Erinnerigsmail isch abgschiggt worde, un isch unte aazeigt.',
-'passwordreset-emailerror-capture' => 'Die Erinnerigsmail, wo unte aazeigt isch, isch generiert worde, aber de Versand aa de Benutzer isch gschyyteret: $1',
+'passwordreset-emailsent' => 'E Passwort-Zrucksetzig isch per E-Mail verschickt wore.',
+'passwordreset-emailsent-capture' => 'E Passwort-Zrucksetzigs-Mail isch vergschickt worde, un isch unte aazeigt.',
+'passwordreset-emailerror-capture' => 'Die unten angezeigte Passwortzrucksetzigsmail, wu unten aazeigt wird, isch generiert wore, aber dr Versand an {{GENDER:$2|dr Benutzer|d Benutzeri}} het nit funktioniert: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'E-Mail-Adräss ändre',
@@ -673,9 +747,23 @@ Temporär Passwort: $2',
 'changeemail-oldemail' => 'Aktuelli E-Mail-Adräss',
 'changeemail-newemail' => 'Nöii E-Mail-Adräss:',
 'changeemail-none' => '(nyt)',
+'changeemail-password' => 'Dy {{SITENAME}}-Passwort:',
 'changeemail-submit' => 'E-Mail Adräss ändre',
 'changeemail-cancel' => 'Abbräche',
 
+# Special:ResetTokens
+'resettokens' => 'Token zrucksetze',
+'resettokens-text' => 'Du chasch Token zrucksetze, wu Dir dr Zuegriff uf bstimmti privati Date megli mache, wu mit Dym Benutzerkonto do verchnipft sin.
+
+Des sottsch nume mache, wänn Du d Token us Versää mit eberem teilt hesch oder Dy Konto gfehrdet isch.',
+'resettokens-no-tokens' => 'S git kei Token zum Zrucksetze.',
+'resettokens-legend' => 'Token zrucksetze',
+'resettokens-tokens' => 'Token:',
+'resettokens-token-label' => '$1 (aktuälle Wärt: $2)',
+'resettokens-watchlist-token' => 'Token fir dr Webfeed (Atom/RSS) vu dr [[Special:Watchlist|Änderigen an Syten uf Dyre Beobachtuislischt]]',
+'resettokens-done' => 'Token zruckgsetzt.',
+'resettokens-resetbutton' => 'Uusgwehlti Token zrucksetze',
+
 # Edit page toolbar
 'bold_sample' => 'fetti Schrift',
 'bold_tip' => 'Fetti Schrift',
@@ -833,7 +921,7 @@ Hiemit gisch du zue, das du dä Tekscht '''sälber gschribe''' hesch, das der Te
 Si verspräche uns usserdäm, dass Si des alles selber gschribe oder vo nere Quälle kopiert hen, wo Public Domain odr sunscht frei isch (lueg $1 für Details).
 '''SETZE SI DO OHNI ERLAUBNIS KEINI URHEBERRÄCHTLICH GSCHÜTZTI WÄRK INE!'''",
 'longpageerror' => "'''Fähler: Dä Täxt, wu Du spychere wit, isch {{PLURAL:$1|ei Kilobyte|$1 Kilobyte}} groß. Des isch greßer wie s erlaubt Maximum vu {{PLURAL:$2|eim Kilobyte|$2 Kilobyte}}.''' S Spychere isch nit megli.",
-'readonlywarning' => "'''Achtung: Die Datebank isch fir Wartigsarbete gesperrt. Wäge däm chenne Dyyni Änderige im Momänt nid gspicheret wäre.
+'readonlywarning' => "'''Achtig: D Datebank isch fir Wartigsarbete gesperrt. Wäge däm chenne Dyyni Änderige im Momänt nit gspycheret wäre.
 Sichere de Täxt bitte lokal uf Dyynem Computer un versuech speter nomol, d Änderige z ibertrage.'''
 
 Grund fir d Sperri: $1",
@@ -871,13 +959,14 @@ Zue Dyyre Information sihsch do s Lesch-Logbuech vo däre Syte:",
 Si isch schyns glescht wore.',
 'edit-conflict' => 'Bearbeitigskonflikt.',
 'edit-no-change' => 'Dyyni Bearbeitig isch ignoriert wore, wel kei Änderig am Täxt gmacht woren isch.',
+'postedit-confirmation' => 'Dyy Bearbeitig isch gspycheret wore.',
 'edit-already-exists' => 'Di nej Syte het nid chenne aaglait wäre, wel s si scho git.',
 'defaultmessagetext' => 'Standardtext',
 'content-failed-to-parse' => 'Parse vum Inhalt $2 fir Modell $1 fählgschlaa: $3',
 'invalid-content-data' => 'Uugiltigi Inhaltsdate',
 'content-not-allowed-here' => 'Dr Inhalt „$1“ isch uf dr Syte [[$2]] nit erlaubt',
 'editwarning-warning' => 'Wänn Du die Syte verlosch, cha s syy, ass Du alli Bearbeitige verliersch, wu Du do dra gmacht hesch.
-Wänn Du aagmäldet bisch, chasch s Anzeige vu däre Warnig im „{{int:prefs-editing}}“-Beryych vu Dyyne Yystelligen abstelle.',
+Wänn Du aagmäldet bisch, chasch s Anzeige vu däre Warnig im „Bearbeite“-Beryych vu Dyyne Yystelligen abstelle.',
 
 # Content models
 'content-model-wikitext' => 'Wikitext',
@@ -910,6 +999,7 @@ S {{PLURAL:$2|derf nid meh wie ein Ufruef|derfe nid meh wie $1 Ufruef}} gee.',
 'undo-failure' => 'D Änderig het nid chenne ruckgängig gmacht wäre, wel dää Abschnitt mittlerwyli gänderet woren isch.',
 'undo-norev' => 'D Bearbeitig het nid chenne ruckgängig gmacht wäre, wel si nid vorhande oder glescht isch.',
 'undo-summary' => 'D Änderig $1 vu [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) isch ruckgängig gmacht wore.',
+'undo-summary-username-hidden' => 'Änderig $1 vun eme versteckte Benutzer ruckgängig gmacht.',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Benutzerkonto cha nid aagleit wäre.',
@@ -937,8 +1027,8 @@ Erklärig: (aktuell) = Underschid zu jetz,
 (vorane) = Underschid zur alte Version, <strong>K</strong> = chlyni Änderig',
 'history-fieldset-title' => 'Suech in dr Versionsgschicht',
 'history-show-deleted' => 'nume gleschti Versione',
-'histfirst' => 'Eltischti',
-'histlast' => 'ischti',
+'histfirst' => 'eltischti',
+'histlast' => 'neischti',
 'historysize' => '({{PLURAL:$1|1 Byte|$1 Bytes}})',
 'historyempty' => '(läär)',
 
@@ -1158,8 +1248,6 @@ Einzelheite chasch im [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'preferences' => 'Yystellige',
 'mypreferences' => 'Yystellige',
 'prefs-edits' => 'Aazahl vu dr Bearbeitige:',
-'prefsnologin' => 'Nid aagmäldet',
-'prefsnologintext' => 'Du muesch <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aagmäldet]</span> sy, für Benutzerystellige chönne z ändere',
 'changepassword' => 'Passwort ändere',
 'prefs-skin' => 'Benutzeroberflechi',
 'skin-preview' => 'Vorschou',
@@ -1430,6 +1518,7 @@ Des cha nimmi ruckgängig gmacht wäre.',
 'recentchanges-label-minor' => 'Des isch e chleini Änderig',
 'recentchanges-label-bot' => 'Die Bearbeitig isch dur e Bott uusgfiert wore',
 'recentchanges-label-unpatrolled' => 'Die Bearbeitig isch nonig vun eme Fäldhieter aagluegt wore',
+'recentchanges-legend-newpage' => '$1 - neji Syte',
 'rcnote' => "Azeigt {{PLURAL:$1|wird '''1''' Änderig|wärde di letschte '''$1''' Änderige}} {{PLURAL:$2|vom letschte Tag|i de letschte '''$2''' Täg}} (Stand: $4, $5)",
 'rcnotefrom' => 'Des sin d Ändrige syter <b>$2</b> (bis zem <b>$1</b> zeigt).',
 'rclistfrom' => '<small>Nöji Änderige ab $1 aazeige (UTC)</small>',
@@ -1452,7 +1541,7 @@ Des cha nimmi ruckgängig gmacht wäre.',
 'rc_categories_any' => 'Alli',
 'rc-change-size-new' => '$1 {{PLURAL:$1|Byte|Byte}} no dr Änderig',
 'newsectionsummary' => 'Neje Abschnitt /* $1 */',
-'rc-enhanced-expand' => 'Detail aazeige (brucht JavaScript)',
+'rc-enhanced-expand' => 'Detail aazeige',
 'rc-enhanced-hide' => 'Detail verstecke',
 'rc-old-title' => 'urspringlig aaglait as „$1“',
 
@@ -2309,7 +2398,7 @@ $1',
 'contributions' => '{{GENDER:$1|Benutzer-Byträg}}',
 'contributions-title' => 'Benutzerbyytreg vu „$1“',
 'mycontris' => 'Myyni Byyträg',
-'contribsub2' => 'Für $1 ($2)',
+'contribsub2' => 'Vu {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'S sin keini Benutzerbyytreg mit däne Kriterie gfunde wore.',
 'uctop' => '(aktuell)',
 'month' => 'u Monet:',
@@ -2595,7 +2684,7 @@ Zum Exportiere trag dr Sytetitel in dr Täxtchaschte unter yy, ei Titel pro Zyyl
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'jetzige Tekscht',
 'allmessagestext' => 'Des isch e Lischt vu allene meglige Syschtemnochrichte us em MediaWiki Namensruum.
-Lueg au uf [//www.mediawiki.org/wiki/Localisation MediaWiki Lokalisierig] un [//translatewiki.net translatewiki.net], wänn Du zue dr MediaWiki-Lokalisierig wit byytrage.',
+Lueg au uf [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokalisierig] un [//translatewiki.net translatewiki.net], wänn Du zue dr MediaWiki-Lokalisierig wit byytrage.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' cha nit bruucht wärde will '''\$wgUseDatabaseMessages''' abgschalte isch.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter fir dr aapasst Zuestand:',
@@ -2778,6 +2867,7 @@ Die uf em lokale Rächner spychere un derno do uffelade.',
 'spam_reverting' => 'Letschti Version ohni Links zue $1 widerhärgstellt.',
 'spam_blanking' => 'In allene Versione het s Links zue $1 gha, sufer gmacht.',
 'spam_deleting' => 'Alli Versione mit eme Link zue $1 sin glescht woret.',
+'simpleantispam-label' => "Spamschutz-Priefig. Do '''nyt''' yytrage!",
 
 # Info page
 'pageinfo-title' => 'Informatione zue „$1“',
@@ -2862,7 +2952,7 @@ $1',
 'file-nohires' => 'Kei höcheri Uflösig verfüegbar.',
 'svg-long-desc' => 'SVG-Datei, Basisgrößi: $1 × $2 Pixel, Dateigrößi: $3',
 'svg-long-desc-animated' => 'Animierti SVG-Datei, Basisgreßi $1 × $2 Pixel, Dateigreßi: $3',
-'show-big-image' => 'Originalgrößi',
+'show-big-image' => 'Originaldatei',
 'show-big-image-preview' => 'Greßi vu däre Vorschau: $1.',
 'show-big-image-other' => 'Wyteri {{PLURAL:$2|Ufflösig|Ufflösige}}: $1.',
 'show-big-image-size' => '$1 × $2 Pixel',
@@ -3313,7 +3403,7 @@ Andri wäre standardmäßig nit aazeigt.
 
 # External editor support
 'edit-externally' => 'Die Datei mit emnen externe Programm bearbeite',
-'edit-externally-help' => '(Lueg d [//www.mediawiki.org/wiki/Manual:External_editors Installationsaawisige] fir witeri Informatione)',
+'edit-externally-help' => '(Lueg d [https://www.mediawiki.org/wiki/Manual:External_editors Installationsaawisige] fir witeri Informatione)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alli',
@@ -3493,7 +3583,7 @@ Du chasch au d [[Special:EditWatchlist|Standard-Bearbeitigssyte]] bruuche.',
 'version-hook-subscribedby' => 'Ufruef vu',
 'version-version' => '(Version $1)',
 'version-license' => 'Lizänz',
-'version-poweredby-credits' => "Die Websyte nutzt '''[//www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Die Websyte nutzt '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'anderi',
 'version-credits-summary' => 'Mir danke däne Lyt fir ihri Bytreg zue [[Special:Version|MediaWiki]].',
 'version-license-info' => 'MediaWiki isch e freji Software, d. h. s cha, no dr Bedingige vu dr GNU General Public-Lizänz, wu vu dr Free Software Foundation vereffentligt woren isch, wyterverteilt un/oder modifiziert wäre. Doderbyy cha d Version 2, oder no eigenem Ermässe, jedi nejeri Version vu dr Lizänz brucht wäre.
@@ -3708,4 +3798,17 @@ Sunscht chasch au s eifach Formular unte nutze. Dyy Kommentar wird, zämme mit D
 'duration-centuries' => '$1 {{PLURAL:$1|Johrhundert|Johrhundert}}',
 'duration-millennia' => '$1 {{PLURAL:$1|Jahrtöusert|Jahrtöusert}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Vorlage expandiere',
+'expand_templates_intro' => 'In däre Spezialsyte cha Täxt yygee wäre und alli Vorlage in ere wäre rekursiv expandiert. Au Parserfunkione wie <nowiki>{{</nowiki>#language:…}} un Variable wie <nowiki>{{</nowiki>CURRENTDAY}} wäre usgwärtet - faktisch alles was in dopplete gschweifte Chlammere din isch. Des gschiht dur dr Ufruef vu dr jewyylige Parser-Phase in MediaWiki.',
+'expand_templates_title' => 'Kontexttitel, fir {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Yygabfäld:',
+'expand_templates_output' => 'Ergebnis',
+'expand_templates_xml_output' => 'XML-Usgab',
+'expand_templates_ok' => 'Uusfiere',
+'expand_templates_remove_comments' => 'Kommentar useneh',
+'expand_templates_remove_nowiki' => '<nowiki>-Befähl im Ergebnis unterdrucke',
+'expand_templates_generate_xml' => 'Zeig XML-Parser-Baum',
+'expand_templates_preview' => 'Vorschou',
+
 );
index b29ebcd..a8dfd2d 100644 (file)
@@ -63,9 +63,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ખાતું_ખોલો' ),
        'Deadendpages'              => array( 'મૃતાંતપાનાં' ),
        'DeletedContributions'      => array( 'હટાવેલાં_યોગદાન' ),
-       'Disambiguations'           => array( 'અસંદિગ્ધતા' ),
        'DoubleRedirects'           => array( 'દ્વિ_પુનઃમાર્ગદર્શન' ),
        'Emailuser'                 => array( 'સભ્યનેઇમેલ' ),
+       'ExpandTemplates'           => array( 'શ્રેણીવિસ્તારો' ),
        'Export'                    => array( 'નિકાસ' ),
        'Fewestrevisions'           => array( 'લઘુત્તમ_પુનરાવર્તન' ),
        'FileDuplicateSearch'       => array( 'ફાઇલપ્રતિકૃતિ_શોધ' ),
@@ -153,7 +153,7 @@ $linkTrail = "/^([\x{0A80}-\x{0AFF}]+)(.*)$/sDu";
 $messages = array(
 # User preference toggles
 'tog-underline' => 'કડીઓની નીચે લીટી (અંડરલાઇન):',
-'tog-justify' => 'ફàª\95રà«\8b લાઇનસર કરો',
+'tog-justify' => 'ફàª\95રાàª\93 લાઇનસર કરો',
 'tog-hideminor' => 'હાલમાં થયેલા ફેરફારમાં નાના ફેરફારો છુપાવો',
 'tog-hidepatrolled' => 'હાલના સલામતી માટે કરવામાં આવેલાં થયેલા ફેરફારો છુપાવો.',
 'tog-newpageshidepatrolled' => 'નવાં પાનાંની યાદીમાંથી દેખરેખ હેઠળનાં પાનાં છુપાવો',
@@ -175,9 +175,9 @@ $messages = array(
 'tog-previewonfirst' => 'પ્રથમ ફેરફાર વખતે પૂર્વાલોકન બતાવો',
 'tog-nocache' => 'બ્રાઉઝરનું પેજ કેશિંગ અસક્રિય કરો',
 'tog-enotifwatchlistpages' => 'મારી ધ્યાનસૂચિમાંનું પાનુ અને ફાઇલમાં ફેરફાર થાય ત્યારે મને ઇ-મેલ મોકલો',
-'tog-enotifusertalkpages' => 'મારી ચર્ચાનાં પાનામાં ફેરફાર થાય ત્યારે મને ઇ-મેલ મોકલો',
-'tog-enotifminoredits' => 'પાનાં અને ફાઇલ્સમાં નાનાં ફેરફાર થાય તો પણ મને ઇ-મેલ મોકલો',
-'tog-enotifrevealaddr' => 'નà«\8bàª\9fà«\80ફà«\80àª\95à«\87શનના àª\87મà«\87લમાàª\82 àª®àª¾àª°à«\82 àª\87મà«\87લ àª\8fડà«\8dરà«\87સ બતાવો',
+'tog-enotifusertalkpages' => 'મારી ચર્ચાનાં પાનામાં ફેરફાર થાય ત્યારે મને ઇમેલ મોકલો',
+'tog-enotifminoredits' => 'પાનાં અને ફાઇલ્સમાં નાનાં ફેરફાર થાય તો પણ મને ઇમેલ મોકલો',
+'tog-enotifrevealaddr' => 'નà«\8bàª\9fà«\80ફà«\80àª\95à«\87શનના àª\87મà«\87લમાàª\82 àª®àª¾àª°à«\82 àª\87મà«\87લ àª¸àª°àª¨àª¾àª®à«\81àª\82 બતાવો',
 'tog-shownumberswatching' => 'ધ્યાન રાખતા સભ્યોની સંખ્યા બતાવો',
 'tog-oldsig' => 'હાલના હસ્તાક્ષર:',
 'tog-fancysig' => 'હસ્તાક્ષરનો વિકિલખાણ તરીકે ઉપયોગ કરો (સ્વચાલિત કડી વગર)',
@@ -187,10 +187,10 @@ $messages = array(
 'tog-watchlisthidebots' => 'ધ્યાનસુચીમાં બોટ દ્વારા થયેલા ફેરફાર સંતાડો.',
 'tog-watchlisthideminor' => "'મારી ધ્યાનસુચી'માં નાનાં ફેરફારો છુપાવો",
 'tog-watchlisthideliu' => 'લોગ થયેલા સભ્ય દ્વારા કરવામાં આવેલ ફેરફાર ધ્યાનસુચીમાં છુપાવો.',
-'tog-watchlisthideanons' => 'અજાણ્યાસભ્ય દ્વારા થયેલ ફેરફાર મારી ધ્યાનસુચીમાં છુપાવો.',
-'tog-watchlisthidepatrolled' => 'સુરક્ષા કાજે કરવામાં આવેલ ફેરફાર મારી ધ્યાનસુચીમાં છુપાવો.',
-'tog-ccmeonemails' => 'મે અન્યોને મોકલેલા ઇ-મà«\87àª\87લનà«\80 àª¨àª\95લ àª®àª¨à«\87 àª®à«\8bàª\95લà«\8b',
-'tog-diffonly' => 'તફાવતની નીચે લેખ ન બતાવશો.',
+'tog-watchlisthideanons' => 'અજાણ્યા સભ્ય દ્વારા થયેલ ફેરફાર મારી ધ્યાનસુચીમાં છુપાવો',
+'tog-watchlisthidepatrolled' => 'સુરક્ષા કાજે કરવામાં આવેલ ફેરફાર મારી ધ્યાનસુચીમાં છુપાવો',
+'tog-ccmeonemails' => 'મે અન્યોને મોકલેલા ઇમà«\87લનà«\80 àª¨àª\95લ àª®àª¨à«\87 àª®à«\8bàª\95લà«\8b',
+'tog-diffonly' => 'તફાવતની નીચે લેખ ન બતાવશો',
 'tog-showhiddencats' => 'છુપી શ્રેણીઓ દર્શાવો',
 'tog-noconvertlink' => 'Disable link title conversion',
 'tog-norollbackdiff' => 'રોલબેક કર્યા પછીના તફાવતો છુપાવો',
@@ -291,8 +291,6 @@ $messages = array(
 'noindex-category' => 'અનુક્રમણિકા નહી બનાવેલા પાનાં',
 'broken-file-category' => 'ફાઇલોની ત્રૂટક કડીઓવાળાં પાનાં',
 
-'linkprefix' => '/^(.*?)((?:[a-zA-Z\\x80-\\xff]|ક્|ખ્|ગ્|ઘ્|ચ્|છ્|જ્|ઝ્|ટ્|ઠ્|ડ્|ઢ્|ણ્|ત્|થ્|દ્|ધ્|ન્|પ્|ફ્|બ્|ભ્|મ્|ય્|ર્|લ્|વ્|સ્|શ્|ષ્|હ્|ળ્|ક્ષ્|જ્ઞ્|અ|આ|ઇ|ઈ|ઉ|ઊ|એ|ઐ|ઓ|ઔ|અં|અઃ|અઁ|ઍ|ઑ|ઋ|ઁ|઼|।|્|ા|િ|ી|ુ|ૂ|ે|ૈ|ો|ૌ|ં|ઃ|ૅ|ૉ|ૃ)+)$/sD',
-
 'about' => 'વિષે',
 'article' => 'લેખનું પાનું',
 'newwindow' => '(નવા પાનામાં ખુલશે)',
@@ -341,7 +339,7 @@ $messages = array(
 'search' => 'શોધો',
 'searchbutton' => 'શોધો',
 'go' => 'જાઓ',
-'searcharticle' => 'àª\9cાવ',
+'searcharticle' => 'àª\9cાàª\93',
 'history' => 'પાનાનો ઇતિહાસ',
 'history_short' => 'ઇતિહાસ',
 'updatedmarker' => 'મારી ગઇ મુલાકાત પછીના બદલાવ',
@@ -352,7 +350,7 @@ $messages = array(
 'edit' => 'ફેરફાર કરો',
 'create' => 'બનાવો',
 'editthispage' => 'આ પાનામાં ફેરફાર કરો',
-'create-this-page' => 'આ પાનું બનાવો.',
+'create-this-page' => 'આ પાનું બનાવો',
 'delete' => 'રદ કરો',
 'deletethispage' => 'આ પાનું હટાવો',
 'undeletethispage' => 'આ પાનું પુનર્જીવીત કરો',
@@ -360,7 +358,7 @@ $messages = array(
 'viewdeleted_short' => '{{PLURAL:$1|ભૂંસી નાખેલો એક|ભૂંસી નાખેલા $1}} ફેરફાર જુઓ',
 'protect' => 'સુરક્ષિત કરો',
 'protect_change' => 'બદલો',
-'protectthispage' => 'આ પાનું સુરક્ષિત કરો.',
+'protectthispage' => 'આ પાનું સુરક્ષિત કરો',
 'unprotect' => 'સુરક્ષા બદલો',
 'unprotectthispage' => 'આ પાનાનું સુરક્ષા  બદલો',
 'newpage' => 'નવું પાનું',
@@ -372,7 +370,7 @@ $messages = array(
 'articlepage' => 'લેખનું પાનું જુઓ',
 'talk' => 'ચર્ચા',
 'views' => 'દેખાવ',
-'toolbox' => 'સાધન પેટી',
+'toolbox' => 'સાધન',
 'userpage' => 'સભ્યનું પાનું જુઓ',
 'projectpage' => 'પ્રકલ્પનું પાનું જુઓ',
 'imagepage' => 'ફાઇલનું પાનું જુઓ',
@@ -387,7 +385,7 @@ $messages = array(
 'lastmodifiedat' => 'આ પાનામાં છેલ્લો ફેરફાર $1ના રોજ $2 વાગ્યે થયો.',
 'viewcount' => 'આ પાનું {{PLURAL:$1|એક|$1}} વખત જોવામાં આવ્યું છે.',
 'protectedpage' => 'સંરક્ષિત પાનું',
-'jumpto' => 'સà«\80ધા àª\86ના àªªàª° àª\9cાવ:',
+'jumpto' => 'આના પર જાવ:',
 'jumptonavigation' => 'ભ્રમણ',
 'jumptosearch' => 'શોધો',
 'view-pool-error' => 'માફ કરશો, આ સમયે સર્વર અતિબોજા હેઠળ છે.
@@ -398,7 +396,7 @@ $messages = array(
 
 $1',
 'pool-timeout' => 'સમય સમાપ્ત -  સ્થગિતતા પ્રતિક્ષીત',
-'pool-queuefull' => '(Pool) કતાર પૂરી ભરેલી',
+'pool-queuefull' => '(Pool) કતાર પૂરી ભરેલી છે',
 'pool-errorunknown' => 'અજ્ઞાત ત્રુટિ',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
@@ -432,18 +430,16 @@ $1',
 'ok' => 'મંજૂર',
 'retrievedfrom' => '"$1"થી લીધેલું',
 'youhavenewmessages' => 'તમારા માટે $1 ($2).',
-'newmessageslink' => 'નવીન સંદેશ',
-'newmessagesdifflink' => 'છેલ્લો ફેરફાર',
 'youhavenewmessagesfromusers' => 'આપને માટે {{PLURAL:$3|અન્ય સભ્ય|$3 અન્ય સભ્યો}} તરફથી $1 છે. ($2).',
-'youhavenewmessagesmanyusers' => 'આપને માટે $1 છે. ($2)',
-'newmessageslinkplural' => '{{PLURAL:$1|નવો સંદેશો|નવા સંદેશા}}',
-'newmessagesdifflinkplural' => 'છેલ્લા {{PLURAL:$1|ફેરફાર|ફેરફારો}}',
-'youhavenewmessagesmulti' => '$1 ઉપર તમારા માટે નવો સંદેશ છે.',
+'youhavenewmessagesmanyusers' => 'આપને માટે ઘણાં સભ્યો તરફથી $1 છે ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|નવà«\8b àª¸àª\82દà«\87શà«\8b«¯à«¯à«¯=નવા àª¸àª\82દà«\87શા}}',
+'newmessagesdifflinkplural' => 'àª\9bà«\87લà«\8dલા {{PLURAL:$1|ફà«\87રફાર|૯૯૯=ફà«\87રફારà«\8b}}',
+'youhavenewmessagesmulti' => 'તમારા માટે $1 ઉપર નવા સંદેશાઓ છે',
 'editsection' => 'ફેરફાર કરો',
 'editold' => 'ફેરફાર કરો',
 'viewsourceold' => 'સ્રોત જુઓ',
 'editlink' => 'ફેરફાર',
-'viewsourcelink' => 'સ્રોત જુઓ.',
+'viewsourcelink' => 'સ્રોત જુઓ',
 'editsectionhint' => 'ફેરફાર કરો - પરિચ્છેદ: $1',
 'toc' => 'અનુક્રમણિકા',
 'showtoc' => 'બતાવો',
@@ -456,10 +452,10 @@ $1',
 'feedlinks' => 'ફીડ:',
 'feed-invalid' => 'અયોગ્ય સબસ્ક્રીપ્સન ફીડ પ્રકાર.',
 'feed-unavailable' => ' સંલગ્ન માહિતીની અપૂરાતિ મોજૂદ નથી',
-'site-rss-feed' => '$1 RSS Feed',
-'site-atom-feed' => '$1 Atom Feed',
-'page-rss-feed' => '"$1" RSS Feed',
-'page-atom-feed' => '"$1" àª\8fàª\9fà«\8bમ àª«à«\80ડ',
+'site-rss-feed' => '$1 RSS ફીડ',
+'site-atom-feed' => '$1 એટમ ફીડ',
+'page-rss-feed' => '"$1" RSS ફીડ',
+'page-atom-feed' => '"$1" એટમ ફીડ',
 'red-link-title' => '$1 (પાનું અસ્તિત્વમાં નથી)',
 'sort-descending' => 'ઉતરતા ક્રમમાં ગોઠવો',
 'sort-ascending' => 'ચડતા ક્રમમાં ગોઠવો',
@@ -477,7 +473,7 @@ $1',
 'nstab-category' => 'શ્રેણી',
 
 # Main script and global functions
-'nosuchaction' => 'આવી કોઇ ક્રિયા નથી.',
+'nosuchaction' => 'આવી કોઇ ક્રિયા નથી',
 'nosuchactiontext' => 'આ URL દ્વારા દર્શાવેલી ક્રિયા અયોગ્ય છે.
 તમે કદાચ ખોટો URL છાપ્યો હશે અથવા ખોટી કડીથી અહીં આવ્યા હશો.
 તમે સોફ્ટવેરની આ ખામી {{SITENAME}} પર દર્શાવી શકો છો.',
@@ -495,7 +491,7 @@ $1',
 'databaseerror-query' => 'પ્રશ્ન: $1',
 'databaseerror-function' => 'વિધેય: $1',
 'databaseerror-error' => 'ક્ષતિ: $1',
-'laggedslavemode' => 'ચેતવણી: પાનું તાજેતરના ફેરફાર ધરાવતું નથી.',
+'laggedslavemode' => '"ચેતવણી:" પાનું તાજેતરના ફેરફાર ધરાવતું નથી.',
 'readonly' => 'ડેટાબેઝ સ્થગિત',
 'enterlockreason' => 'સ્થગિતતા ક્યારે દુર કરાશે તેના અંદાજ શાથે,સ્થગિત કરવાનું કારણ આપો',
 'readonlytext' => 'નવી નોંધો અને ફેરફારો માટે ડેટાબેઝ હાલમાં સ્થગિત કરાયેલ છે,કદાચ નિયમિત ડેટાબેઝ સારસંભાળ માટે,તે પછી આ ફરી સામાન્ય થશે.
@@ -517,7 +513,7 @@ $1',
 'filecopyerror' => '"$1" થી "$2"માં નકલ નિષ્ફળ.',
 'filerenameerror' => '"$1" નું નામ બદલીને "$2" કરવામાં નિષ્ફળ.',
 'filedeleteerror' => '"$1" ફાઇલ હટાવી ન શકાઇ.',
-'directorycreateerror' => 'ડà«\80રેક્ટરી "$1" ન બનાવી શકાઇ.',
+'directorycreateerror' => 'ડિરેક્ટરી "$1" ન બનાવી શકાઇ.',
 'filenotfound' => 'ફાઇલ "$1" ન મળી.',
 'fileexistserror' => 'ફાઇલ "$1"માં ન લખી શકાયું : ફાઇલ અસ્તિત્વ ધરાવે છે.',
 'unexpected' => 'અણધારી કિંમત: "$1"="$2".',
@@ -528,7 +524,7 @@ $1',
 'cannotdelete-title' => '"$1" પાનું કાઢી શકતા નથી',
 'delete-hook-aborted' => 'દૂર કરવાનું હૂક વડે રોકી રાખવામાં આવ્યું.
 તે કોઇ કારણ આપતું નથી.',
-'badtitle' => 'àª\96રાબ àª¨àª¾àª®',
+'badtitle' => 'àª\96રાબ àª¶àª¿àª°à«\8dષàª\95',
 'badtitletext' => 'આપનું ઈચ્છિત શીર્ષક અમાન્ય છે, ખાલી છે, અથવાતો અયોગ્ય રીતે આંતર-ભાષિય કે આંતર-વિકિ સાથે જોડાયેલું શીર્ષક છે.
 શક્ય છે કે તેમાં એક કે વધુ એવા અક્ષર કે ચિહ્નો છે કે જે પાનાનાં શીર્ષક માટે અવૈધ છે.',
 'perfcached' => 'નીચે દર્શાવેલી માહિતી જૂના સંગ્રહમાંથી લીધેલી છે અને શક્ય છે કે તે હાલની પરિસ્થિતિમાં સચોટ ના હોય. વધુમાં વધુ {{PLURAL:$1|એક પરિણામ|$1 પરિણામો}} આ સંગ્રહમાં ઉપલબ્ધ છે.',
@@ -565,7 +561,8 @@ $2',
 'invalidtitle-knownnamespace' => 'નામસ્થળ "$2" અને લખાણ "$3" સાથે અમાન્ય મથાળું',
 'invalidtitle-unknownnamespace' => 'અજ્ઞાત નામસ્થળ ક્રમાંક $1 અને નામ "$2" વાળું અમાન્ય મથાળું',
 'exception-nologin' => 'પ્રવેશ કરેલ નથી',
-'exception-nologin-text' => 'આ પાનું કે ક્રિયા માટે આ વિકિ પર લોગઈન થવું જરૂરી છે.',
+'exception-nologin-text' => 'આ પાનું કે પ્રક્રિયા પ્રાપ્તી માટે કૃપયા [[Special:Userlogin|લોગઈન]] કરો.',
+'exception-nologin-text-manual' => 'આ પાનું કે પ્રક્રિયા મેળવવા માટે કૃપયા $1.',
 
 # Virus scanner
 'virus-badscanner' => "ખરાબ રૂપરેખા: અજાણ્યું વાઇરસ સ્કેનર: ''$1''",
@@ -582,12 +579,12 @@ $2',
 'yourname' => 'સભ્ય નામ:',
 'userlogin-yourname' => 'સભ્ય નામ',
 'userlogin-yourname-ph' => 'તમારૂં સભ્ય નામ દાખલ કરો',
-'createacct-another-username-ph' => 'તમારà«\82àª\82 àª¸àª­à«\8dયનામ àª¦àª¾àª\96લ àª\95રà«\8b',
+'createacct-another-username-ph' => 'સભ્યનામ દાખલ કરો',
 'yourpassword' => 'ગુપ્ત સંજ્ઞા:',
 'userlogin-yourpassword' => 'ગુપ્ત સંજ્ઞા',
-'userlogin-yourpassword-ph' => 'àª\97à«\81પà«\8dત àª¸àª\82àª\9cà«\8dàª\9eા લખો',
+'userlogin-yourpassword-ph' => 'તમારà«\80 àª\97à«\81પà«\8dત àª¸àª\82àª\9cà«\8dàª\9eા (પાસવરà«\8dડ) લખો',
 'createacct-yourpassword-ph' => 'પાસવર્ડ દાખલ કરો',
-'yourpasswordagain' => 'ગુપ્ત સંજ્ઞા (પાસવર્ડ) ફરી લખો',
+'yourpasswordagain' => 'ગુપ્ત સંજ્ઞા (પાસવર્ડ) ફરી લખો:',
 'createacct-yourpasswordagain' => 'પાસવર્ડની ખાતરી કરો',
 'createacct-yourpasswordagain-ph' => 'પાસવર્ડ ફરીથી દાખલ કરો',
 'remembermypassword' => 'આ કોમ્યૂટર પર મારી લૉગ ઇન વિગતો ધ્યાનમાં રાખો (વધુમાં વધુ $1 {{PLURAL:$1|દિવસ|દિવસ}} માટે)',
@@ -604,7 +601,7 @@ $2',
 'logout' => 'બહાર નીકળો',
 'userlogout' => 'બહાર નીકળો/લૉગ આઉટ',
 'notloggedin' => 'પ્રવેશ કરેલ નથી',
-'userlogin-noaccount' => 'શું તમારૂં ખાતું નથી ?',
+'userlogin-noaccount' => 'શું તમારૂં ખાતું નથી?',
 'userlogin-joinproject' => '{{SITENAME}} સાથે જોડાવ',
 'nologin' => "શું તમારૂં ખાતું નથી? તો નવું '''$1'''.",
 'nologinlink' => 'ખાતું ખોલો',
@@ -612,9 +609,11 @@ $2',
 'gotaccount' => "પહેલેથી ખાતું ખોલેલું છે? '''$1'''.",
 'gotaccountlink' => 'પ્રવેશ કરો',
 'userlogin-resetlink' => 'પોતાની પ્રવેશ માહિતી ભૂલી ગયા છો?',
-'userlogin-resetpassword-link' => 'તમારà«\80 àª\97à«\81પà«\8dતસàª\82àª\9cà«\8dàª\9eા àª¬àª¦àª²à«\8b',
+'userlogin-resetpassword-link' => 'તમારà«\8b àªªàª¾àª¸àªµàª°à«\8dડ àª­à«\82લà«\80 àª\97યા àª\9bà«\8b?',
 'helplogin-url' => 'Help:પ્રવેશ માટે',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|પ્રવેશવા માટેની મદદ]]',
+'userlogin-loggedin' => 'તમે પહેલેથી {{GENDER:$1|$1}} તરીકે પ્રવેશ કરેલો જ છે.
+બીજા સભ્ય તરીકે પ્રવેશ કરવા માટે નીચેનું ફોર્મ વાપરો.',
 'userlogin-createanother' => 'બીજું ખાતું બનાવો',
 'createacct-join' => 'તમારી માહિતી નીચે દાખલ કરો.',
 'createacct-another-join' => 'નવા ખાતાંની માહિતી નીચે દાખલ કરો.',
@@ -669,20 +668,19 @@ $2',
 'passwordtooshort' => 'ગુપ્ત સંજ્ઞામાં ઓછામાં {{PLURAL:$1|ઓછો એક અક્ષર હોવો |ઓછા $1 અક્ષર હોવા}} જોઇએ.',
 'password-name-match' => 'તમારી ગુપ્તસંજ્ઞા તમારા સભ્યનામ કરતાં અલગ જ હોવી જોઇએ.',
 'password-login-forbidden' => 'આ સભ્યનામ અને ગુપ્તસંજ્ઞા વાપરવા પર પ્રતિબંધ છે.',
-'mailmypassword' => 'પાસવરà«\8dડ àª\87-મેલમાં મોકલો',
+'mailmypassword' => 'નવà«\8b àªªàª¾àª¸àªµàª°à«\8dડ àª\87મેલમાં મોકલો',
 'passwordremindertitle' => '{{SITENAME}} માટેની નવી કામચલાઉ ગુપ્ત સંજ્ઞા',
 'passwordremindertext' => 'કોઇકે (કદાચ તમે IP એડ્રેસ $1 પરથી) {{SITENAME}} ($4) માટે નવી ગુપ્ત સજ્ઞા (પાસવર્ડ) માટે વિનંતી કરેલ છે.
 હંગામી ધોરણે સભ્ય "$2" માટે ગુપ્ત સંજ્ઞા બની છે અને તે "$3". જો તમે જ આ વિનંતી કરી હોય અને તમે ગુપ્ત સંજ્ઞા બદલવા માંગતા હો તો તમારે પ્રવેશ કરવો પડશે અને નવી ગુપ્ત સંજ્ઞા પસંદ કરવી પડશે. હંગામી ગુપ્ત સંજ્ઞાની અવધિ {{PLURAL:$5|એક દિવસ|$5 દિવસો}} છે ત્યાર બાદ તે કામ નહીં કરે.
 
 જો બીજા કોઇએ આ વિનંતી કરી હોય અથવા તમને તમારી જુની ગુપ્ત સંજ્ઞા યાદ આવી ગઇ હોય અને તમે તે બદલવા ન માંગતા હો તો આ સંદેશ અવગણીને તમારી જુની ગુપ્ત સંજ્ઞા વાપરવાનું ચાલુ રાખો.',
 'noemail' => 'સભ્ય "$1"નું કોઇ ઇ-મેલ સરનામું નોંધાયેલું નથી.',
-'noemailcreate' => 'વà«\88ધ àª\87-મà«\87લ àª\86પશà«\8b',
+'noemailcreate' => 'તમારà«\87 àªµà«\88ધ àª\87મà«\87લ àª\86પવાનà«\80 àª\9cરà«\82ર àª\9bà«\87.',
 'passwordsent' => '"$1" ની નવી ગુપ્તસંજ્ઞા (પાસવર્ડ) આપના ઇમેઇલ પર મોકલવામાં આવ્યો છે.
 કૃપા કરી તે મળ્યા બાદ ફરી લોગ ઇન કરો.',
-'blocked-mailpassword' => 'Your IP address is blocked from editing, and so is not allowed to use the password recovery function to prevent abuse.
-ફેરફાર કરવા માટે તમારું IP એડ્રેસ  સ્થગિત કરી દેવાયું છે તેથી દૂરુપયોગ ટાળવા માટે તમને ગુપ્તસંજ્ઞા રીકવરી કરવાની છૂટ નથી.',
-'eauthentsent' => 'પુષ્ટિ કરવા માટે તમે આપેલા સરનામાં પર ઇમેઇલ મોકલવામાં આવ્યો છે.
-એ જ સરનામે બીજો ઇમેઇલ થતાં પહેલાં તમારે ઇમેઇલમાં લખેલી સૂચનાઓ પ્રમાણે કરવું પડશે જેથી એ પુષ્ટિ થઇ શકે કે આપેલું સરનામું તમારું છે.',
+'blocked-mailpassword' => 'ફેરફાર કરવા માટે તમારું IP એડ્રેસ સ્થગિત કરી દેવાયું છે, તેથી દૂરુપયોગ ટાળવા માટે તમને ગુપ્તસંજ્ઞા ફરી મેળવવાની છૂટ નથી.',
+'eauthentsent' => 'પુષ્ટિ કરવા માટે નિશ્ચિત થયેલા સરનામાં પર ઇમેલ મોકલવામાં આવ્યો છે.
+એ જ સરનામે બીજો ઇમેલ થતાં પહેલાં તમારે ઇમેલમાં લખેલી સૂચનાઓ પ્રમાણે કરવું પડશે જેથી એ પુષ્ટિ થઇ શકે કે આપેલું સરનામું તમારું છે.',
 'throttled-mailpassword' => 'ગુપ્ત સંજ્ઞા યાદ અપાવતી ઇમેઇલ છેલ્લા {{PLURAL:$1|કલાકમાં|$1 કલાકોમાં}} મોકલેલી છે.
 દૂરુપયોગ રોકવા માટે, {{PLURAL:$1|કલાકમાં|$1 કલાકોમાં}} ફક્ત એક જ આવી મેઇલ કરવામાં આવે છે.',
 'mailerror' => 'મેઇલ મોકલવામાં ત્રુટિ: $1',
@@ -717,6 +715,7 @@ $2',
 # Email sending
 'php-mail-error-unknown' => 'PHPની મેલ() કામગીરીમાં અજ્ઞાત ત્રુટિ',
 'user-mail-no-addy' => 'ઈ મેલ એડ્રસ વગર ઈ મેલ મોકલવા પ્રયત્ન કરેલ.',
+'user-mail-no-body' => 'કોરો કે નાનકડો ઈમેઇલ મોકલવાનો પ્રયાસ કરાયો.',
 
 # Change password dialog
 'resetpass' => 'ગુપ્તસંજ્ઞા બદલો',
@@ -733,23 +732,24 @@ $2',
 'resetpass-no-info' => 'બારોબાર આ પાનું જોવા માટે પ્રવેશ કરવો આવશ્યક છે.',
 'resetpass-submit-loggedin' => 'ગુપ્તસંજ્ઞા બદલો',
 'resetpass-submit-cancel' => 'રદ કરો',
-'resetpass-wrong-oldpass' => 'àª\85વà«\88ધ àª¹àª\82àª\97ામà«\87 àª\95à«\87 àª\95ાયમી ગુપ્તસંજ્ઞા.
-કદાચ તમે પહેલેથી સફળતા પૂર્વક તમારી ગુપ્ત સંજ્ઞા બદલી દીધી હોય કે નવી ગુપ્ત સંંજ્ઞામાટે વિનંતિ કરી હોય',
+'resetpass-wrong-oldpass' => 'àª\85યà«\8bàª\97à«\8dય àª¹àª\82àª\97ામà«\80 àª\95à«\87 àª¹àª¾àª²àª¨ી ગુપ્તસંજ્ઞા.
+કદાચ તમે પહેલેથી સફળતાપૂર્વક તમારી ગુપ્ત સંજ્ઞા બદલી દીધી હશે કે નવી ગુપ્ત સંજ્ઞા માટે વિનંતિ કરી હશે.',
 'resetpass-temp-password' => 'કામચલાઉ ગુપ્તસંજ્ઞા:',
 'resetpass-abort-generic' => 'વિસ્તારક વડે પાસવર્ડ બદલવાનું રોકી રખાયું છે.',
 
 # Special:PasswordReset
-'passwordreset' => 'પાસવરà«\8dડ àª°à«\80સà«\87àª\9f àª\95રો',
+'passwordreset' => 'àª\97à«\81પà«\8dત àª¸àª\82àª\9cà«\8dàª\9eા àª«àª°à«\80 àª\97à«\8bઠવો',
 'passwordreset-text-one' => 'તમારો પાસવર્ડ બદલવા માટે આ ફોર્મ પૂરુ કરો.',
-'passwordreset-legend' => 'પાસવર્ડ રીસેટ કરો',
-'passwordreset-disabled' => 'આ વિકી પર પાસવર્ડ રીસેટ કરવા પર પ્રતિબંધ છે.',
+'passwordreset-text-many' => '{{PLURAL:$1|તમારો પાસવર્ડ બદલવા માટે કોઈ એક ખાનું ભરો.}}',
+'passwordreset-legend' => 'ગુપ્ત સંજ્ઞા ફરી ગોઠવો',
+'passwordreset-disabled' => 'આ વિકી પર ગુપ્ત સંજ્ઞા ફરી ગોઠવવા પર પ્રતિબંધ છે.',
 'passwordreset-emaildisabled' => 'આ વિકિ પર ઇમેઇલ સગવડ બંધ છે.',
 'passwordreset-username' => 'સભ્ય નામ:',
 'passwordreset-domain' => 'ડોમેઈન:',
-'passwordreset-capture' => 'પરિણામી ઈ મેલ જોવો છે ?',
+'passwordreset-capture' => 'પરિણામી ઈમેલ જોવો છે?',
 'passwordreset-capture-help' => 'જો તમે આ ઓપ્શન સિલેક્ટ કરશો, તો તમને અને યુઝર ને ઈ મેલ (કામચલાઉ પાસવર્ડ સાથે) દેખાડવામાં આવશે.',
-'passwordreset-email' => 'ઇ મેલ સરનામું:',
-'passwordreset-emailtitle' => '{{SITENAME}} àª®àª¾àª\9fà«\87 àª\96ાતà«\81 àª¬àª¨àª¾àªµà«\8dયà«\81àª\82',
+'passwordreset-email' => 'ઇમેલ સરનામું:',
+'passwordreset-emailtitle' => '{{SITENAME}} àªªàª° àª\96ાતાનà«\80 àª®àª¾àª¹àª¿àª¤à«\80',
 'passwordreset-emailtext-ip' => 'કોઈકે (કદાચ તમોએ , $1 IP એડ્રેસ થી) તમારી વેબસાઈટ {{SITENAME}}  ($4) નો પાસવર્ડ રિસેટ કરવાની રજૂઆત કરી છે. આ ઈમેઈલ એડ્રેસ સાથે {{PLURAL:$3|નું ખાતું|ના ખાતા}} જોડાયેલા છે.
 .
 .
@@ -769,15 +769,15 @@ $2
 'passwordreset-emailerror-capture' => 'પાસવર્ડ ફરી ગોઠવવા માટેનો ઇમેલ બનાવવામાં આવ્યો છે, જે નીચે પ્રમાણે છે, પરંતુ તે {{GENDER:$2|સભ્ય}}ને મોકલવામાં નિષ્ફળ થયો છે: $1',
 
 # Special:ChangeEmail
-'changeemail' => 'àª\88 àª®à«\87લ àª\96ાતà«\81 àª¬àª¦àª²àªµàª¾ àª®àª¾àª\9fà«\87',
-'changeemail-header' => 'તમારા àª\96ાતાનà«\81àª\82 àª\88-મà«\87àª\88લ સરનામું બદલો',
+'changeemail' => 'àª\87મà«\87લ àª¸àª°àª¨àª¾àª®à«\81àª\82 àª¬àª¦àª²à«\8b',
+'changeemail-header' => 'તમારા àª\96ાતાનà«\81àª\82 àª\87મà«\87લ સરનામું બદલો',
 'changeemail-text' => 'તમારું ઈ-મેઈલ સરનામું બદલવા માટે આ ફોર્મ ભરો. આ ફેરફાર કાયમ કરવા માટે તમારે પાસવર્ડ ભરવાની જરૂર પડશે.',
 'changeemail-no-info' => 'બારોબાર આ પાનું જોવા માટે પ્રવેશ કરવો આવશ્યક છે.',
-'changeemail-oldemail' => 'હાલ નું ઈ મેલ ખાતુ:',
-'changeemail-newemail' => 'નવું ઈ-મેલ સરનામું',
+'changeemail-oldemail' => 'હાલનું ઈમેલ સરનામું:',
+'changeemail-newemail' => 'નવું ઈમેલ સરનામું:',
 'changeemail-none' => '(કંઈ નહી)',
 'changeemail-password' => 'તમારો {{SITENAME}} પાસવર્ડ:',
-'changeemail-submit' => 'ઈ મેલ બદલો',
+'changeemail-submit' => 'ઈમેલ બદલો',
 'changeemail-cancel' => 'રદ કરો',
 
 # Special:ResetTokens
@@ -811,13 +811,13 @@ $2
 # Edit pages
 'summary' => 'સારાંશ:',
 'subject' => 'વિષય/શીર્ષક:',
-'minoredit' => 'આ એક નાનો સુધારો છે.',
+'minoredit' => 'આ એક નાનો સુધારો છે',
 'watchthis' => 'આ પાનાને ધ્યાનમાં રાખો',
-'savearticle' => 'સાચવો',
+'savearticle' => 'પાનà«\81àª\82 àª¸àª¾àª\9aવà«\8b',
 'preview' => 'પૂર્વાવલોકન',
-'showpreview' => 'ઝલક',
+'showpreview' => 'ઝલક દર્શાવો',
 'showlivepreview' => 'જીવંત પૂર્વાવલોકન',
-'showdiff' => 'ફેરફારો',
+'showdiff' => 'ફેરફારો દર્શાવો',
 'anoneditwarning' => "'''ચેતવણી:''' તમે તમારા સભ્ય નામથી પ્રવેશ કર્યો નથી.
 આ પાનાનાં ઇતિહાસમાં તમારૂં આઇ.પી. (IP) એડ્રેસ નોંધવામાં આવશે.",
 'anonpreviewwarning' => 'તમે સભ્યનામથી પ્રવેશ કર્યો નથી,આ પાનું ઈતિહાસમાંતમારા IP સરનામાના નામે  સાચવવામાં આવશે',
@@ -934,7 +934,7 @@ $2
 તમારે તમારા ફેરફારો વિહરમાન હયાત લેખમાં વિલિન કરવો પડશે. 
  જો તમે  \"{{int:savearticle}}\" આ બાન દબાવશો તો '''ફક્ત''' ઉપરનો લેખ સચવાશે.",
 'yourtext' => 'તમારું લખાણ',
-'storedversion' => 'રàª\95à«\8dષિત પુનરાવર્તન',
+'storedversion' => 'સàª\82àª\97à«\8dરહà«\87લ પુનરાવર્તન',
 'nonunicodebrowser' => "'''ચેતવણી: તમારું બ્રાઉઝર યુનિકોડ ઉકેલવા સક્ષમ નથી.'''
 અહીં તમે સુરક્ષિત રીતે ફેરફારો નહીં કરી શકો: ASCII સિવાયના અક્ષરો સંપાદન ચોકઠામાં હેક્સાડેસિમલ સ્વરૂપે દેખાશે.",
 'editingold' => "'''ચેતવણી: તમે આ પાનાની ખૂબ જૂની આવૃત્તિમાં ફેરફાર કરી રહ્યાં છો.'''
@@ -954,10 +954,10 @@ $2
 તમે તમારું લખાણ કોઇ ટેક્સ્ટ ફાઇલ માં સેવ કરી મૂકી દો અને માહિતીસંચ ખુલતા વિકિ પર સાચવી શકશો. 
 
 જે પ્રબંધકે માહિતીસંચ બંધ કર્યો છે તેણે આ કારણ આપ્યું છે: $1",
-'protectedpagewarning' => "'''ચેતવણી : આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર પ્રબંધકો જ આમાં ફેરફાર કરી શકે.'''
-તમારા àª¸àª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦àª¿ આપી છે:",
-'semiprotectedpagewarning' => "'''નોંધ : આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર પ્રબંધકો જ આમાં ફેરફાર કરી શકે.'''
-તમારા àª¸àª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦àª¿ આપી છે:",
+'protectedpagewarning' => "'''ચેતવણી:''' આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર પ્રબંધકો જ આમાં ફેરફાર કરી શકે છે.
+સàª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦à«\80 àª¨à«\80àª\9aà«\87 આપી છે:",
+'semiprotectedpagewarning' => "'''નોંધ :''' આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર નોંધાયેલાં સભ્યો જ આમાં ફેરફાર કરી શકે છે.
+સàª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦à«\80 àª¨à«\80àª\9aà«\87 આપી છે:",
 'cascadeprotectedwarning' => "'''ચેતવણી:''' આ પાનું સંરક્ષિત છે. પ્રબંધન અધિકાર ધરાવતા સભ્યો જ આમાં ફેરફાર કરી શકે છે. આ પાનું નીચેના પગથિયામય સંરક્ષણ{{PLURAL:$1|પાના|પાનાઓ}} દ્વારા સુરક્ષિત છે.",
 'titleprotectedwarning' => "'''ચેતવણી: આ પાનું સંરક્ષિત છે આથી આની રચના માટે [[Special:ListGroupRights|વિશેષ અધિકારો]]ની જરૂર છે.'''
 તે સંબંધી તાજેતરની ફેરફાર યાદી તમારા સંદર્ભ માટે આપેલી છે:",
@@ -1039,7 +1039,7 @@ $3 દ્વારા અપાયેલ કારણ છે ''$2''",
 'currentrev-asof' => '$1એ જોઈ શકાતી હાલની આવૃત્તિ',
 'revisionasof' => '$1 સુધીનાં પુનરાવર્તન',
 'revision-info' => '$2 દ્વારા $1 સુધીમાં કરવામાં આવેલાં ફેરફારો',
-'previousrevision' => '←જુના ફેરફારો',
+'previousrevision' => '← જુના ફેરફારો',
 'nextrevision' => 'આ પછીનું પુનરાવર્તન→',
 'currentrevisionlink' => 'વર્તમાન આવૃત્તિ',
 'cur' => 'વર્તમાન',
@@ -1111,20 +1111,20 @@ $3 દ્વારા અપાયેલ કારણ છે ''$2''",
 'revdelete-text' => "''' રદ્દ કરાયેલ ફેરફારો અને ઘટનાઓ પાનાના ઈતિહાસ અને લોગમાં દેખાશે , પણ તેની અંદરની માહિતી જન સમુદાયથી અદ્રશ્ય રહેશે. '''
 {{SITENAME}} પરના અન્ય પ્રબંધકો આ અદ્રશ્ય માહિતે જોઇ શકશે અને તેને પુનઃ જીવિત કરી શકશે સિવાય કે તેના પર વધારાની પાબંદી ન મુકાઇ હોય.",
 'revdelete-confirm' => 'કૃપયા પુષ્ટિ કરો કે તમે શું કરી રહ્યા છો તેની અને તેના પરિણામોની તમને જાણ છે અને તમે આ બધું  [[{{MediaWiki:Policy-url}}|the policy]] અ6તર્ગત કરી રહ્યાં છો.',
-'revdelete-suppress-text' => "બળ પૂર્વક છુપાવવું માત્ર આજ સંજોગોમાં કરી શકાશે:
+'revdelete-suppress-text' => "બળ પૂર્વક છુપાવવું \"માત્ર\" આજ સંજોગોમાં કરી શકાશે:
 * સંભવતઃ ભયાજનક માહિતી 
 * અયોગ્ય નિજી માહિતી 
-*: ''àª\98રનà«\81àª\82 àª¸àª°àª¨àª¾àª®à«\81àª\82 àª\85નà«\87 àª\9fà«\87લિફà«\8bન àª¨àª\82બર, àª¸àª¾àª®àª¾àª\9cિàª\95 àª¸à«\81રàª\95à«\8dષા àª\95à«\8dરà«\8dમ àª\88.''",
+*: ''àª\98રનà«\81àª\82 àª¸àª°àª¨àª¾àª®à«\81àª\82 àª\85નà«\87 àª\9fà«\87લિફà«\8bન àª¨àª\82બર, àª°àª¾àª·à«\8dàª\9fà«\8dરà«\80ય àª\93ળàª\96 àª\95à«\8dરમાàª\82àª\95à«\8b àªµàª\97à«\87રà«\87.''",
 'revdelete-legend' => 'દ્રશ્યતા સંબંધી પ્રતિબંધોને ગોઠવો',
-'revdelete-hide-text' => 'પà«\81નરાવરà«\8dતન àª\9bà«\81પાવà«\8b',
+'revdelete-hide-text' => 'પà«\81નરાવરà«\8dતન àª²àª\96ાણ',
 'revdelete-hide-image' => 'ફાઇલની માહિતી છુપાવો',
 'revdelete-hide-name' => 'ક્રિયા અને લક્ષ્ય સંતાડો',
-'revdelete-hide-comment' => 'ફેરફાર સારાંશ છુપાવો',
-'revdelete-hide-user' => 'સંપાદકનું નામ /આઈ પી એડ્રેસ સંતાડો',
+'revdelete-hide-comment' => 'ફેરફાર સારાંશ',
+'revdelete-hide-user' => 'સંપાદકનું નામ /આઈ પી એડ્રેસ',
 'revdelete-hide-restricted' => 'પ્રબંધક કે અન્યો સૌની માહિતી છુપાવો',
 'revdelete-radio-same' => '(બદલશો નહીઁ)',
-'revdelete-radio-set' => 'હા',
-'revdelete-radio-unset' => 'ના',
+'revdelete-radio-set' => 'àª\9bà«\81પાયà«\87લ',
+'revdelete-radio-unset' => 'દà«\8dશà«\8dયમાન',
 'revdelete-suppress' => 'પ્રબંધક કે અન્યો સૌની માહિતી છુપાવો',
 'revdelete-unsuppress' => 'સમા કરાયેલા પુનરાવર્તનો પરના પ્રતિબંધ હટાવો',
 'revdelete-log' => 'કારણ:',
@@ -1194,7 +1194,7 @@ $1",
 # Merge log
 'mergelog' => 'લોગ વિલિન કરો',
 'pagemerge-logentry' => '[[$1]] ને  [[$2]]માં વિલિન કરાયું ( $3 સુધી ના પુનરાવર્તનો)',
-'revertmerge' => 'છુટુ પાડો',
+'revertmerge' => 'છુટુ પાડો',
 'mergelogpagetext' => 'તાજેતરમાં એક બીજા સાથે વિલિન થયેલ ઇતિહાસ પાનાની યાદી',
 
 # Diffs
@@ -1277,10 +1277,9 @@ $1",
 
 # Preferences page
 'preferences' => 'પસંદ',
-'mypreferences' => 'પસંદ',
+'mypreferences' => 'પસંદગીઓ',
 'prefs-edits' => 'સંપાદનોની સંખ્યા',
-'prefsnologin' => 'પ્રવેશ કરેલ નથી',
-'prefsnologintext' => 'સભ્યના અધિકારો બદલવા તમે <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logged in]</span> પ્રવેશ કરેલો હોવો જોઈએ',
+'prefsnologintext2' => 'તમારી પસંદગીઓ પસંદ કરવા માટે કૃપયા $1.',
 'changepassword' => 'ગુપ્તસંજ્ઞા બદલો',
 'prefs-skin' => 'ફલક',
 'skin-preview' => 'ફેરફાર બતાવો',
@@ -1873,10 +1872,10 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 'filehist-current' => 'વર્તમાન',
 'filehist-datetime' => 'તારીખ/સમય',
 'filehist-thumb' => 'લઘુચિત્ર',
-'filehist-thumbtext' => '$1àª\8d હતું તે સંસ્કરણનું લઘુચિત્ર',
-'filehist-nothumb' => 'થમà«\8dબનà«\87àª\87લ નથી',
+'filehist-thumbtext' => '$1àª\8f હતું તે સંસ્કરણનું લઘુચિત્ર',
+'filehist-nothumb' => 'લàª\98à«\81àª\9aિતà«\8dર નથી',
 'filehist-user' => 'સભ્ય',
-'filehist-dimensions' => 'પરિમાણ',
+'filehist-dimensions' => 'પરિમાણ',
 'filehist-filesize' => 'ફાઇલનું કદ',
 'filehist-comment' => 'ટિપ્પણી',
 'filehist-missing' => 'ફાઇલ ગાયબ',
@@ -1917,8 +1916,8 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 'filedelete-intro' => "તમે '''[[Media:$1|$1]]'' ફાઇલ અને તેની સાથે સંલગ્ન ઇતિહાસ ભુંસી રહ્યા છો.",
 'filedelete-intro-old' => "તમે '''[[Media:$1|$1]]'''નું આ [$4 $3, $2] વર્ઝન ભુસી રહ્યા છો.",
 'filedelete-comment' => 'કારણ:',
-'filedelete-submit' => 'ભà«\81àª\82સો',
-'filedelete-success' => "'''$1'''નà«\87 àª­à«\82àª\82સà«\80 àª¨àª¾àª\82àª\96વામાં આવ્યું છે.",
+'filedelete-submit' => 'દà«\82ર àª\95રો',
+'filedelete-success' => "'''$1'''નà«\87 àª¦à«\82ર àª\95રવામાં આવ્યું છે.",
 'filedelete-success-old' => "'''[[Media:$1|$1]]'''નું $3, $2ના રોજનું  સંસ્કરણ ભુંસી નાખ્યું છે.",
 'filedelete-nofile' => "'''$1'''નું અસ્તિત્વ નથી.",
 'filedelete-nofile-old' => "'''$1'''નું  આપે જણાવેલ ખાસિયતવાળું સંગ્રહિત સંસ્કરણ અસ્તિત્વમાં નથી.",
@@ -1955,6 +1954,10 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 'randompage-nopages' => 'આ {{PLURAL:$2|નામસ્થળ|નામસ્થળો}}માં કોઇ પાના નથી: $1.',
 
 # Random page in category
+'randomincategory' => 'શ્રેણીમાં ગમે તે પાનું',
+'randomincategory-invalidcategory' => '"$1" એ યોગ્ય શ્રેણી નામ નથી.',
+'randomincategory-nopages' => '[[:Category:$1|$1]] વર્ગમાં કોઇ પાનું નથી.',
+'randomincategory-selectcategory' => 'વર્ગમાંથી ગમે તે પાનું મેળવો: $1 $2.',
 'randomincategory-selectcategory-submit' => 'જાઓ',
 
 # Random redirect
@@ -2010,6 +2013,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|બાઇટ|બાઇટ્સ}}',
 'ncategories' => '$1 {{PLURAL:$1|શ્રેણી|શ્રેણીઓ}}',
+'ninterwikis' => '$1 {{PLURAL:$1|આંતરવિકિ|આંતરવિકિઓ}}',
 'nlinks' => '$1 {{PLURAL:$1|કડી|કડીઓ}}',
 'nmembers' => '$1 {{PLURAL:$1|સદસ્ય|સદસ્યો}}',
 'nrevisions' => '$1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}',
@@ -2057,6 +2061,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 'listusers' => 'સભ્યોની યાદી',
 'listusers-editsonly' => 'માત્ર સંપાદન કરનારા સભ્યો બતાવો',
 'listusers-creationsort' => 'તારીખ અનુસાર ગોઠવો',
+'listusers-desc' => 'ઉતરતા ક્રમમાં ગોઠવો',
 'usereditcount' => '$1 {{PLURAL:$1|ફેરફાર|ફેરફારો}}',
 'usercreated' => '$1 તારીખે $2 વાગ્યે {{GENDER:$3|બનાવ્યું}}',
 'newpages' => 'નવાં પાનાં',
@@ -2102,7 +2107,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization. જુઓ',
 'prevpage' => 'પાછળનું પાનું ($1)',
 'allpagesfrom' => 'આનાથી શરૂ થતા પાના દર્શાવો:',
 'allpagesto' => 'આનાથી અંત થતા પાના દર્શાવો:',
-'allarticles' => 'બધા àª²à«\87àª\96',
+'allarticles' => 'બધા àªªàª¾àª¨àª¾àª\82àª\93',
 'allinnamespace' => 'બધા પાના  ($1 નમાવકાશ)',
 'allnotinnamespace' => 'બધા પાના  ($1 નમાવકાશમાંના હોય)',
 'allpagesprev' => 'પહેલાનું',
@@ -2274,13 +2279,14 @@ $PAGEINTRO $NEWPAGE
 ઇ-મેલ: $PAGEEDITOR_EMAIL
 વિકિ: $PAGEEDITOR_WIKI
 
-જ્યાં સુધી તમે આ પાનાની મુલાકાત નહી લો ત્યાં સુધી તેમાં ભવિષ્યમાં થનાર કોઇ પણ ફેરફારની સૂચના તમને મળશે નહિ.
+àª\9cà«\8dયાàª\82 àª¸à«\81ધà«\80 àª¤àª®à«\87 àª²à«\8bàª\97àª\88ન àª¥àª\88 àª\86 àªªàª¾àª¨àª¾àª¨à«\80 àª®à«\81લાàª\95ાત àª¨àª¹à«\80 àª²à«\8b àª¤à«\8dયાàª\82 àª¸à«\81ધà«\80 àª¤à«\87માàª\82 àª­àªµàª¿àª·à«\8dયમાàª\82 àª¥àª¨àª¾àª° àª\95à«\8bàª\87 àªªàª£ àª«à«\87રફારનà«\80 àª¸à«\82àª\9aના àª¤àª®àª¨à«\87 àª®àª³àª¶à«\87 àª¨àª¹àª¿.
 તમે તમારી ધ્યાન સૂચિમાં તમે જોયેલા પાના સંબંધી સૂચનાને લાગતા વિલપોમાં ફેરફાર કરી શકો છો.
 
+
 આપની વિશ્વાસુ {{SITENAME}} સૂચના પ્રણાલી   
  
 --
-e-mail notification settings બદલવા માટે મુલાકાત લો
+email notification settings બદલવા માટે મુલાકાત લો
 {{canonicalurl:{{#special:Preferences}}}}
 
 તમારી ધ્યાનસૂચિના  વિક્લ્પ ગોઠવણ માટે મુલાકાત લો
@@ -2317,10 +2323,12 @@ $UNWATCHURL
 'deletecomment' => 'કારણ:',
 'deleteotherreason' => 'અન્ય/વધારાનું કારણ:',
 'deletereasonotherlist' => 'અન્ય કારણ',
-'deletereason-dropdown' => '* હટાવવાનાં સામાન્ય કારણો 
-** લેખકની વિનંતી
+'deletereason-dropdown' => '* દૂર કરવાના સામાન્ય કારણો
+** સ્પામ
+** ભાંગફોડીયા પ્રવૃત્તિ
 ** પ્રકાશનાધિકાર ભંગ 
-** ભાંગફોડીયા પ્રવૃત્તિ',
+** લેખકની વિનંતી
+** ભાંગેલ વળાંક',
 'delete-edit-reasonlist' => 'ભુંસવાનું કારણ બદલો.',
 'delete-toobig' => 'આ પાનાના ફેરફારોનો ઇતિહાસ ખૂબ લાંબો છે , $1 {{PLURAL:$1|ફેરફાર|ફેરફારો}}થી પણ વધારે.
 {{SITENAME}}ને અક્સ્માતે ખોરવાતું અટકાવવા આવા પાનાને હટાવવા પર પ્રતિબંધ છે.',
@@ -2531,7 +2539,7 @@ $1',
 'whatlinkshere-hidetrans' => '$1 આરપાર સમાવેશનો',
 'whatlinkshere-hidelinks' => 'કડીઓ $1',
 'whatlinkshere-hideimages' => '$1 ફાઇલની કડીઓ',
-'whatlinkshere-filters' => 'ચાળણી',
+'whatlinkshere-filters' => 'ચાળણી',
 
 # Block/unblock
 'autoblockid' => 'ઓટોબ્લોક #$1',
@@ -2588,7 +2596,7 @@ $1',
 'unblocked-range' => '$1  અનાવરોધિત કરવામાં આવ્યું છે',
 'unblocked-id' => ' $1 નો પ્રતિબંધ હટાવાયો',
 'blocklist' => 'પ્રતિબંધિત સભ્યો',
-'ipblocklist' => 'àª\85વરà«\8bધિત વપરાશકર્તાઓ',
+'ipblocklist' => 'પà«\8dરતિબàª\82ધિત વપરાશકર્તાઓ',
 'ipblocklist-legend' => 'પ્રતિબંધિત સભ્ય શોધો',
 'blocklist-userblocks' => 'એકાઉન્ટ બ્લોકો છુપાવો',
 'blocklist-tempblocks' => 'કામચલાઉ બ્લોકો છુપાવો',
@@ -2771,10 +2779,10 @@ $1',
 'imageinvalidfilename' => 'લક્ષ્ય ફાઈલ અવૈધ છે',
 'fix-double-redirects' => 'મૂળ શીર્ષક તરફ  નિર્દેશન કરતા  દિશા નિર્દેશકો અધ્યતન કરો',
 'move-leave-redirect' => 'પાછળ દિશા સૂચન છોડો',
-'protectedpagemovewarning' => "'''નà«\8bàª\82ધ : àª\86 àªªàª¾àª¨àª¾ àªªàª° àª¸àª\82રàª\95à«\8dષણ àªµàª¿àª\95લà«\8dપ àª¸àª\95à«\8dરà«\80ય àª\9bà«\87 àª\85નà«\87 àª®àª¾àª¤à«\8dર àªªà«\8dરબàª\82ધàª\95à«\8b àª\9c àª\86માàª\82 àª«à«\87રફાર àª\95રà«\80 àª¶àª\95à«\87.'''
-તમારા àª¸àª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦àª¿ આપી છે:",
-'semiprotectedpagemovewarning' => "'''નોંધ : આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર પ્રબંધકો જ આમાં ફેરફાર કરી શકે.'''
-તમારા àª¸àª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦àª¿ આપી છે:",
+'protectedpagemovewarning' => "'''àª\9aà«\87તવણà«\80:''' àª\86 àªªàª¾àª¨àª¾ àªªàª° àª¸àª\82રàª\95à«\8dષણ àªµàª¿àª\95લà«\8dપ àª¸àª\95à«\8dરà«\80ય àª\9bà«\87 àª\85નà«\87 àª®àª¾àª¤à«\8dર àªªà«\8dરબàª\82ધàª\95à«\8b àª\9c àª\86નà«\87 àª\96સà«\87ડà«\80 àª¶àª\95à«\87 àª\9bà«\87.
+સàª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦à«\80 àª¨à«\80àª\9aà«\87 આપી છે:",
+'semiprotectedpagemovewarning' => "'''નોંધ :''' આ પાના પર સંરક્ષણ વિકલ્પ સક્રીય છે અને માત્ર નોંધાયેલાં સભ્યો જ આને ખસેડી શકે છે.
+સàª\82દરà«\8dભ àª®àª¾àª\9fà«\87 àª¤àª¾àª\9cà«\87તરનà«\80 àª²à«\8bàª\97 àª¯àª¾àª¦à«\80 àª¨à«\80àª\9aà«\87 આપી છે:",
 'move-over-sharedrepo' => '== ફાઇલ અસ્તિત્વ ધારાવે છે ==
 સર્વસામાન્ય ફાઇલ સંગ્રહમાં [[:$1]] પહેલેથી મોજૂદ છે.  આ સ્થળે કોઇ અન્ય ફાઇલ હટાવતા વિહરમાન ફાઇલની માહિતી પર આ ફાઇલ લખાશે.',
 'file-exists-sharedrepo' => 'પસંદ કરેલ ફાઇલ ના નામે અન્ય ફાઇલ પહેલેથી સર્વ સામાન્ય ફાઇલ સંગ્રહમાં મોજૂદ છે/
@@ -2808,7 +2816,7 @@ $1',
 'allmessagesdefault' => 'મૂળ સંદેશ',
 'allmessagescurrent' => 'વર્તમાન દસ્તાવેજ',
 'allmessagestext' => 'આ મિડિયાવિકિ નામસ્થળમાં આવેલ પ્રણાલીજનિત સંદેશાની યાદી આ મુજબ છે.
-જો તમે મિડિયાયાવિકિના સ્થાનીયકરણમાં મદદરૂપ થવા ઇચ્છતા હોવ તો કૃપયા [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] અને [//translatewiki.net translatewiki.net]ની મુલાકાત લો.',
+જો તમે મિડિયાયાવિકિના સ્થાનીયકરણમાં મદદરૂપ થવા ઇચ્છતા હોવ તો કૃપયા [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] અને [//translatewiki.net translatewiki.net]ની મુલાકાત લો.',
 'allmessagesnotsupportedDB' => "આ પાનું ન વાપરી શકાશે કેમકે '''\$wgUseDatabaseMessages'''  નિષ્ક્રીય કરાયું છે",
 'allmessages-filter-legend' => 'ચાળણી',
 'allmessages-filter' => 'સ્થાનીયકરણ સ્થિતિ દ્વારા ચાળો',
@@ -2823,6 +2831,8 @@ $1',
 'thumbnail-more' => 'વિસ્તૃત કરો',
 'filemissing' => 'ફાઇલ ગાયબ',
 'thumbnail_error' => 'નાની છબી (થંબનેઇલ-thumbnail) બનાવવામાં ત્રુટિ: $1',
+'thumbnail_error_remote' => '$1 તરફથી ક્ષતિ સંદેશ:
+$2',
 'djvu_page_error' => 'DjVu પાનું સીમાની બહાર',
 'djvu_no_xml' => 'DjVu ફાઇલ માટે XML લાવવા અસમર્થ',
 'thumbnail-temp-create' => 'હંગામી થમ્બનેલ ફાઈલ ન બનાવી શકાઈ',
@@ -2904,7 +2914,7 @@ $1',
 'tooltip-pt-anonuserpage' => 'IP સરનામું માટેના સભ્ય પાનામાં તમે ફેરફાર કરી રહ્યાં છો.',
 'tooltip-pt-mytalk' => 'તમારૂં ચર્ચાનું પાનું',
 'tooltip-pt-anontalk' => 'આ IP સરનામા દ્વારા થયેલ ફેરફારની ચર્ચા',
-'tooltip-pt-preferences' => 'મારà«\80 àªªàª¸àª\82દ',
+'tooltip-pt-preferences' => 'તમારà«\80 àªªàª¸àª\82દàª\97à«\80àª\93',
 'tooltip-pt-watchlist' => 'તમે દેખરેખ રાખી રહ્યાં હોવ તેવા પાનાઓની યાદી',
 'tooltip-pt-mycontris' => 'તમારા યોગદાનની યાદી',
 'tooltip-pt-login' => 'આપને લોગ ઇન કરવા ભલામણ કરવામાં આવે છે, જોકે તે આવશ્યક નથી',
@@ -2930,9 +2940,9 @@ $1',
 'tooltip-n-mainpage-description' => 'મુખ્ય પાના પર જાઓ',
 'tooltip-n-portal' => 'પરિયોજના વિષે, આપ શું કરી શકો અને વસ્તુઓ ક્યાં શોધશો',
 'tooltip-n-currentevents' => 'પ્રસ્તુત ઘટનાની પૃષ્ઠભૂમિની માહિતિ શોધો',
-'tooltip-n-recentchanges' => 'વિકિમાં હાલમા થયેલા ફેરફારોની સૂચિ.',
+'tooltip-n-recentchanges' => 'વિકિમાં હાલમાં થયેલ ફેરફારોની સૂચિ',
 'tooltip-n-randompage' => 'કોઇ પણ એક લેખ બતાવો',
-'tooltip-n-help' => 'શોધવા માટેની જગ્યા.',
+'tooltip-n-help' => 'શોધવા માટેની જગ્યા',
 'tooltip-t-whatlinkshere' => 'અહીં જોડાતા બધાં વિકિ પાનાઓની યાદી',
 'tooltip-t-recentchangeslinked' => 'આ પાના પરની કડીઓ વાળા લેખોમાં તાજેતરમાં થયેલા ફેરફારો',
 'tooltip-feed-rss' => 'આ પાના માટે આર.એસ.એસ. ફીડ',
@@ -2992,6 +3002,8 @@ $1',
 'spambot_username' => 'મિડિયાવિકી સ્પેમ સફાઇ',
 'spam_reverting' => ' $1 પર કડી ન ધરાવતા છેલ્લા ફેરેફાર પર પુનઃ સ્થાપન કરાય છે',
 'spam_blanking' => 'બધા ફેરફારોમાં  $1 પર કડી હતી, આને હટાવી દેવામાં આવે છે',
+'simpleantispam-label' => "સ્પામ-વિરોધી તપાસ.
+આને '''ના''' ભરશો!",
 
 # Info page
 'pageinfo-title' => ' "$1" માટે માહિતી',
@@ -3073,7 +3085,7 @@ $1',
 'file-nohires' => 'આથી વધુ આવર્તન ઉપલબ્ધ નથી.',
 'svg-long-desc' => 'SVG ફાઇલ, માત્ર $1 × $2 પીક્સલ, ફાઇલનું કદ: $3',
 'svg-long-error' => 'અયોગ્ય SVG ફાઇલ: $1',
-'show-big-image' => 'મહતà«\8dતમ àª\86વરà«\8dતન',
+'show-big-image' => 'મà«\82ળભà«\81ત àª«àª¾àª\87લ',
 'show-big-image-preview' => 'આ મહાવરા દ્રશ્યનું માપ: $1.',
 'show-big-image-other' => 'અન્ય {{PLURAL:$2|આવર્તન|આવર્તનો}}: $1.',
 'show-big-image-size' => '$1 × $2 પીક્સલ',
@@ -3539,7 +3551,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'બાહ્ય સોફ્ટવેર વાપરીને આ ફાઇલમાં ફેરફાર કરો',
-'edit-externally-help' => '(વધુ માહિતી માટે [//www.mediawiki.org/wiki/Manual:External_editors સેટ-અપ સૂચનાઓ] જુઓ)',
+'edit-externally-help' => '(વધુ માહિતી માટે [https://www.mediawiki.org/wiki/Manual:External_editors સેટ-અપ સૂચનાઓ] જુઓ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'બધા',
@@ -3655,7 +3667,7 @@ $5
 'autosumm-blank' => 'પાનું ખાલી કરી દેવાયું',
 'autosumm-replace' => 'માહિતીને "$1" થી બદલી',
 'autoredircomment' => '[[$1]] પર દિશાનિર્દેશિત',
-'autosumm-new' => '$1થà«\80 àª¶àª°à«\82 àª¥àª¤à«\81àª\82 àª¨àªµà«\81àª\82 àªªàª¾àª¨à«\81àª\82 àª¬àª¾àª¨વ્યું',
+'autosumm-new' => '$1થà«\80 àª¶àª°à«\82 àª¥àª¤à«\81àª\82 àª¨àªµà«\81àª\82 àªªàª¾àª¨à«\81àª\82 àª¬àª¨àª¾વ્યું',
 
 # Live preview
 'livepreview-loading' => 'લવાઇ રહ્યું છે...',
@@ -3720,7 +3732,7 @@ $5
 'version-hook-subscribedby' => 'દ્વ્રારા લાભાન્વીત',
 'version-version' => '(આવૃત્તિ $1)',
 'version-license' => 'પરવાનો',
-'version-poweredby-credits' => "આ વિકિ  '''[//www.mediawiki.org/ MediaWiki]''' દ્વારા ચાલે છે, પ્રકાશનાધિકાર © 2001-$1 $2.",
+'version-poweredby-credits' => "આ વિકિ  '''[https://www.mediawiki.org/ MediaWiki]''' દ્વારા ચાલે છે, પ્રકાશનાધિકાર © 2001-$1 $2.",
 'version-poweredby-others' => 'અન્યો',
 'version-poweredby-translators' => 'ટ્રાન્સલેટવિકિ.નેટ ભાષાંતરકર્તાઓ',
 'version-license-info' => 'મિડિયાવિકિ એક મુક્ત સોફ્ટવેર છે. તમે તેનું પુનઃવિતરણ કરી શકો છો અને/અથવા તેને the Free Software Foundation દ્વારા પ્રકાશિત  GNU General Public License હેઠળ તેના સંસ્કરણ 2 ને કે તે પછીના સંસ્કરણ   મઠારી શકો છો . 
@@ -3757,9 +3769,8 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'ખાસ પાનાં',
-'specialpages-note' => '----
-* નિયમિત ખાસ પાનાં.
-* <span class="mw-specialpagerestricted">ખાસ પાનાં પ્રતિબંધિત.</span>',
+'specialpages-note' => '* નિયમિત ખાસ પાનાં.
+* <span class="mw-specialpagerestricted">પ્રતિબંધિત ખાસ પાનાં.</span>',
 'specialpages-group-maintenance' => 'સમારકામ અહેવાલ',
 'specialpages-group-other' => 'અન્ય ખાસ પાનાઓ',
 'specialpages-group-login' => 'પ્રવેશ / ખાતુ બનાવો',
@@ -3818,9 +3829,10 @@ $5
 
 # Database error messages
 'dberr-header' => 'આ વિકિમાં તકલીફ છે',
-'dberr-problems' => 'દિલàª\97à«\80રà«\80! àª\86 àª¸àª¾àª\87àª\9f àª¤àª\95નિàª\95à«\80 àª\85ડàª\9aણ અનુભવી રહી છે.',
+'dberr-problems' => 'માફ àª\95રશà«\8b! àª\86 àª¸àª¾àª\87àª\9f àª¤àª\95નિàª\95à«\80 àª\85ડàª\9aણà«\8b અનુભવી રહી છે.',
 'dberr-again' => 'થોડી વાર રાહ જોઈને ફરી પેજ લોડ કરવાનો પ્રયત્ન કરો.',
 'dberr-info' => '(માહિતી સંચય સર્વર : $1નો સંપર્ક નથી કરી શકાયો)',
+'dberr-info-hidden' => '(ડેટાબેઝ સર્વર સાથે જોડાણ થઇ શકતું નથી)',
 'dberr-usegoogle' => 'તેસમયા દરમ્યાન તમે ગુગલ દ્વારા શોધી શકો',
 'dberr-outofdate' => 'આપણી માહિતી સંબંધી તેમની સૂચિ કાલાતિત હોઇ શકે.',
 'dberr-cachederror' => 'વિનંતિ કરેલ પાનાની આ એક સંગ્રહીત પ્રત માત્ર છે અને તે અધ્યતન ન પણ હોય.',
@@ -3864,12 +3876,12 @@ $5
 'revdelete-uname-unhid' => 'વપરાશકર્તા નામ છુપાવેલ નથીં',
 'revdelete-restricted' => 'પ્રબઁધકોના ફેરફાર કરવા પર પ્રતિબંધ મુકાયો',
 'revdelete-unrestricted' => 'પ્રબંધકોના ફેરફાર કરવા પર પ્રતિબંધ હટાવાયો.',
-'logentry-move-move' => '$1એ {{GENDER:$2|ખસેડાયું }} પાના $3ને $4 પર ખસેડ્યું',
+'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-move-move_redir-noredirect' => '$1એ દિશાનિર્દેશન કરીને પાના $3ને $4 પર {{GENDER:$2|વાળ્યું}} પણ પાછળ દિશાનિર્દેશન છોડ્યું નહી',
-'logentry-patrol-patrol' => '$1 આવૃત્તિ ચિહ્નિત થયેલ પાનાં $4 $3 ચોકી કરવા ફરવા નીકળવું',
-'logentry-patrol-patrol-auto' => '$1 આપોઆપ ચિહ્નિત ચોકી પહેરો કરવા લાગ્યા આવૃત્તિ પાનું $4 $3',
+'logentry-patrol-patrol' => 'પાનાં $3 ની આવૃત્તિ $4 ને $1 વડે ચોકી કરવા માટે {{GENDER:$2|નિશાનીત}} કરેલ છે',
+'logentry-patrol-patrol-auto' => 'પાનાં $3 ની આવૃત્તિ $4 ને $1 એ આપમેળે ચોકી કરવા માટે {{GENDER:$2|નિશાનીત}} કરેલ છે',
 'logentry-newusers-newusers' => 'સભ્ય ખાતું $1 {{GENDER:$2|બનાવવામાં આવ્યું}}',
 'logentry-newusers-create' => 'સભ્ય ખાતું $1 {{GENDER:$2|બનાવવામાં આવ્યું}}',
 'logentry-newusers-create2' => 'સભ્ય ખાતું $3 $1 વડે {{GENDER:$2|બનાવવામાં આવ્યું હતું}}',
@@ -3959,4 +3971,8 @@ $5
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|બાઇટ|બાઇટ્સ}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|બાઇટ|બાઇટ્સ}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'પરિણામ:',
+'expand_templates_ok' => 'મંજૂર',
+
 );
index 1e2aafe..716bbb5 100644 (file)
@@ -266,8 +266,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Feddynit ass "$1"',
 'youhavenewmessages' => 'Ta $1 ayd ($2).',
-'newmessageslink' => 'çhaghteraghtyn noa',
-'newmessagesdifflink' => "caghlaa s'jerree",
 'youhavenewmessagesmulti' => 'Ta çhaghteraghtyn noa ayd er $1',
 'editsection' => 'reagh',
 'editold' => 'reagh',
@@ -609,7 +607,6 @@ My t'ou uss son ronsaghey dagh cooid (as shen goaill stiagh duillagyn resooney,
 'preferences' => 'Tosheeaghtyn',
 'mypreferences' => 'My hosheeaghtyn',
 'prefs-edits' => 'Earroo caghlaaghyn:',
-'prefsnologin' => 'Cha nel oo loggit stiagh',
 'changepassword' => 'Fockle yn arrey y cheaghley',
 'prefs-skin' => 'Crackan',
 'skin-preview' => 'Roie-haishbynys',
@@ -1410,7 +1407,7 @@ Bee adsyn elley follit dy seyr-obbragh.<br />
 
 # External editor support
 'edit-externally' => 'Reagh yn coadan shoh lesh sheeyntagh mooie',
-'edit-externally-help' => 'Jeeagh er [//www.mediawiki.org/wiki/Manual:External_editors saraghyn soiaghey seose] son tooilley oayllys.',
+'edit-externally-help' => 'Jeeagh er [https://www.mediawiki.org/wiki/Manual:External_editors saraghyn soiaghey seose] son tooilley oayllys.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'yn clane',
@@ -1478,4 +1475,8 @@ Bee adsyn elley follit dy seyr-obbragh.<br />
 'searchsuggest-search' => 'Ronsaghey',
 'searchsuggest-containing' => 'goaill stiagh...',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'OK',
+'expand_templates_preview' => 'Roie-haishbynys',
+
 );
index 770bd89..34097c7 100644 (file)
  * @author Jetlag
  * @author Mnemonic kek
  * @author Urhixidur
+ * @author Xiaomingyan
  */
 
+$fallback = 'zh-hant';
+
 $messages = array(
 # User preference toggles
 'tog-underline' => '鏈接加底線:',
@@ -288,8 +291,6 @@ $1',
 'ok' => '做得',
 'retrievedfrom' => '來自"$1"',
 'youhavenewmessages' => '汝有$1($2)。',
-'newmessageslink' => '新消息',
-'newmessagesdifflink' => '上擺更改',
 'youhavenewmessagesfromusers' => '汝有來自{{PLURAL:$3|另一位用戶|$3位用戶}}嘅$1($2)。',
 'youhavenewmessagesmanyusers' => '汝有來自多位用戶嘅$1( $2 )。',
 'newmessageslinkplural' => '{{PLURAL:$1|一條新信息|新信息}}',
@@ -896,8 +897,6 @@ Liá-chhṳ chhà-fûng he yù $1 só fûng ke. Tông-chûng ke ngièn-yîn he '
 # Preferences page
 'preferences' => '偏好設定',
 'mypreferences' => '偏好設定',
-'prefsnologin' => '還吂登入',
-'prefsnologintext' => 'Ngì pit-sî chhai-siên [[Special:UserLogin|tên-ngi̍p]] chhòi-nèn sat-chṳ ke-ngìn chhâm-su.',
 'changepassword' => '更改密碼',
 'prefs-skin' => '外皮',
 'skin-preview' => '預覽',
@@ -1643,7 +1642,7 @@ chhiáng chhai hàng-thung chṳ̂-chhièn siên liáu-kié khì-thâ khó-nèn
 'allmessagesdefault' => '默認信息文字',
 'allmessagescurrent' => 'Tông-chhièn ke vùn-sṳ',
 'allmessagestext' => 'Liá-piên lie̍t-chhut só-yû hí-khó thin-chṳ ke ne-thúng kie-mien.
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => 'Ne-thúng kie-mien kûng-yung chhu-yî kôan-pit chong-thai (wgUseDatabaseMessages)。',
 
 # Thumbnails
@@ -1809,7 +1808,7 @@ Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and
 'file-info-size' => '$1 × $2像素,文件大小:$3,MIME類型:$4',
 'file-nohires' => '無做得提供嘅還較高分辨率。',
 'svg-long-desc' => 'SVG文件,尺寸:$1×$2像素,文件大細:$3',
-'show-big-image' => '完分辨率',
+'show-big-image' => '完分辨率',
 
 # Special:NewFiles
 'newimages' => 'Sîn-kien thù-chhiong ke va̍k-lòng',
@@ -1852,7 +1851,7 @@ Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and
 
 # External editor support
 'edit-externally' => '用外部應用程序編寫本文件',
-'edit-externally-help' => '(請參詳[//www.mediawiki.org/wiki/Manual:External_editors 設定步驟]了解詳細資訊)',
+'edit-externally-help' => '(請參詳[https://www.mediawiki.org/wiki/Manual:External_editors 設定步驟]了解詳細資訊)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
index b0084fa..13d61b5 100644 (file)
@@ -276,8 +276,6 @@ $messages = array(
 'ok' => 'Hiki nō',
 'retrievedfrom' => 'Kiʻi ʻia mai "$1"',
 'youhavenewmessages' => 'He $1 ($2) kāu.',
-'newmessageslink' => 'mau memo hou',
-'newmessagesdifflink' => 'loli hope',
 'youhavenewmessagesmulti' => 'He mau memo kou ma $1',
 'editsection' => 'e ho‘ololi',
 'editold' => 'e ho‘ololi',
@@ -816,7 +814,7 @@ Hiki iā ʻoe ke ʻikena i kāna molekumu.',
 'ilsubmit' => 'Huli',
 
 # External editor support
-'edit-externally-help' => '(E ʻike i nā [//www.mediawiki.org/wiki/Manual:External_editors aʻo palapala no ka hoʻokuene ʻana])',
+'edit-externally-help' => '(E ʻike i nā [https://www.mediawiki.org/wiki/Manual:External_editors aʻo palapala no ka hoʻokuene ʻana])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'apau',
@@ -857,4 +855,8 @@ Hiki iā ʻoe ke ʻikena i kāna molekumu.',
 # Special:Tags
 'tags-edit' => 'e hoʻololi',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Hiki nō',
+'expand_templates_preview' => 'Nāmua',
+
 );
index 4400c4d..869bfb9 100644 (file)
@@ -12,6 +12,7 @@
  * @author Dekel E
  * @author Drorsnir
  * @author Guycn1
+ * @author Guycn2
  * @author Hoo
  * @author Ijon
  * @author Inkbug
@@ -65,12 +66,12 @@ $namespaceGenderAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'משתמשים_פעילים' ),
        'Allmessages'               => array( 'הודעות_המערכת' ),
+       'AllMyUploads'              => array( 'כל_ההעלאות_שלי' ),
        'Allpages'                  => array( 'כל_הדפים' ),
        'Ancientpages'              => array( 'דפים_מוזנחים' ),
        'Badtitle'                  => array( 'כותרת_שגויה' ),
        'Blankpage'                 => array( 'דף_ריק' ),
        'Block'                     => array( 'חסימה', 'חסימת_כתובת', 'חסימת_משתמש' ),
-       'Blockme'                   => array( 'חסום_אותי' ),
        'Booksources'               => array( 'משאבי_ספרות', 'משאבי_ספרות_חיצוניים' ),
        'BrokenRedirects'           => array( 'הפניות_לא_תקינות', 'הפניות_שבורות' ),
        'Categories'                => array( 'קטגוריות', 'רשימת_קטגוריות' ),
@@ -82,10 +83,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'הרשמה_לחשבון' ),
        'Deadendpages'              => array( 'דפים_ללא_קישורים' ),
        'DeletedContributions'      => array( 'תרומות_מחוקות' ),
-       'Disambiguations'           => array( 'פירושונים', 'דפי_פירושונים' ),
        'DoubleRedirects'           => array( 'הפניות_כפולות' ),
        'EditWatchlist'             => array( 'עריכת_רשימת_המעקב' ),
        'Emailuser'                 => array( 'שליחת_דואר_למשתמש' ),
+       'ExpandTemplates'           => array( 'פריסת_תבניות' ),
        'Export'                    => array( 'ייצוא', 'ייצוא_דפים' ),
        'Fewestrevisions'           => array( 'הגרסאות_המעטות_ביותר', 'הדפים_בעלי_מספר_העריכות_הנמוך_ביותר' ),
        'FileDuplicateSearch'       => array( 'חיפוש_קבצים_כפולים' ),
@@ -130,10 +131,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'דפים_מוגנים' ),
        'Protectedtitles'           => array( 'כותרות_מוגנות' ),
        'Randompage'                => array( 'אקראי', 'דף_אקראי' ),
+       'RandomInCategory'          => array( 'דף_אקראי_בקטגוריה' ),
        'Randomredirect'            => array( 'הפניה_אקראית' ),
        'Recentchanges'             => array( 'שינויים_אחרונים' ),
        'Recentchangeslinked'       => array( 'שינויים_בדפים_המקושרים' ),
        'Redirect'                  => array( 'הפניה' ),
+       'ResetTokens'               => array( 'איפוס_אסימונים' ),
        'Revisiondelete'            => array( 'מחיקת_ושחזור_גרסאות' ),
        'Search'                    => array( 'חיפוש' ),
        'Shortpages'                => array( 'דפים_קצרים' ),
@@ -153,7 +156,7 @@ $specialPageAliases = array(
        'Unwatchedpages'            => array( 'דפים_שאינם_במעקב' ),
        'Upload'                    => array( 'העלאה', 'העלאת_קובץ_לשרת' ),
        'UploadStash'               => array( 'מאגר_העלאות' ),
-       'Userlogin'                 => array( 'כניסה_לחשבון', 'כניסה', 'כניסה_/_הרשמה_לחשבון' ),
+       'Userlogin'                 => array( 'כניסה_לחשבון', 'כניסה' ),
        'Userlogout'                => array( 'יציאה_מהחשבון', 'יציאה' ),
        'Userrights'                => array( 'ניהול_הרשאות_משתמש', 'הפיכת_משתמש_למפעיל_מערכת', 'הענקת_או_ביטול_הרשאת_בוט' ),
        'Version'                   => array( 'גרסה', 'גרסת_התוכנה' ),
@@ -637,12 +640,10 @@ $1',
 'backlinksubtitle' => '→ $1',
 'retrievedfrom' => 'מקור: $1',
 'youhavenewmessages' => 'יש לך $1 ($2).',
-'newmessageslink' => 'הודעות חדשות',
-'newmessagesdifflink' => 'השוואה לגרסה הקודמת',
 'youhavenewmessagesfromusers' => 'יש לך $1 {{PLURAL:$3|ממשתמש אחר|מ־$3 משתמשים}} ($2).',
 'youhavenewmessagesmanyusers' => 'יש לך $1 ממשתמשים רבים ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|הודעה חדשה|הודעות חדשות}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|שינוי אחרון|שינויים אחרונים}}',
+'newmessageslinkplural' => '{{PLURAL:$1|הודעה חדשה|999=הודעות חדשות}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|שינוי אחרון|999=שינויים אחרונים}}',
 'youhavenewmessagesmulti' => 'יש לך הודעות חדשות ב־$1',
 'editsection' => 'עריכה',
 'editold' => 'עריכה',
@@ -689,7 +690,7 @@ $1',
 'nosuchspecialpage' => 'אין דף מיוחד בשם זה',
 'nospecialpagetext' => '<strong>ביקשתם דף מיוחד שאינו קיים.</strong>
 
-ר×\90×\95 ×\92×\9d ×\90ת [[Special:SpecialPages|רש×\99×\9eת ×\94×\93פ×\99×\9d ×\94×\9e×\99×\95×\97×\93×\99×\9d ×\94תק×\99× ×\99×\9d]].',
+ראו את [[Special:SpecialPages|רשימת הדפים המיוחדים התקינים]].',
 
 # General errors
 'error' => 'שגיאה',
@@ -773,7 +774,8 @@ $2',
 'invalidtitle-knownnamespace' => 'כותרת בלתי־תקינה עם מרחב השם "$2" ושם דף "$3"',
 'invalidtitle-unknownnamespace' => 'כותרת בלתי־תקינה עם מרחב שם בלתי־ידוע מספר $1 ושם דף "$2"',
 'exception-nologin' => 'לא בחשבון',
-'exception-nologin-text' => 'כדי לראות את הדף הזה או לבצע את הפעולה הזאת צריך להיכנס לחשבון באתר הוויקי הזה.',
+'exception-nologin-text' => 'אנא [[Special:Userlogin|היכנסו לחשבון]] כדי לראות את הדף הזה או לבצע את הפעולה הזו.',
+'exception-nologin-text-manual' => 'אנא $1 כדי לראות את הדף הזה או לבצע את הפעולה הזו.',
 
 # Virus scanner
 'virus-badscanner' => "הגדרות שגויות: סורק הווירוסים אינו ידוע: ''$1''",
@@ -786,7 +788,7 @@ $2',
 שימו לב כי ייתכן שדפים אחדים ימשיכו להיות מוצגים כאילו אתם עדיין מחוברים לחשבון עד שתנקו את המטמון של הדפדפן שלכם.",
 'welcomeuser' => 'ברוך בואך, $1!',
 'welcomecreation-msg' => 'חשבונך נוצר.
 ×\90 ×\9c×\90 ×\9cש×\9b×\95×\97 ×\9c×\94ת×\90×\99×\9d ×\90ת [[Special:Preferences|×\94×¢×\93פ×\95ת ×\94×\9eשת×\9eש]] שלך ב{{grammar:תחילית|{{SITENAME}}}}.',
\91×\90פשר×\95ת×\9a ×\9c×\94ת×\90×\99×\9d ×\90ת [[Special:Preferences|×\94×\94×¢×\93פ×\95ת]] שלך ב{{grammar:תחילית|{{SITENAME}}}}.',
 'yourname' => 'שם משתמש:',
 'userlogin-yourname' => 'שם משתמש',
 'userlogin-yourname-ph' => 'יש להקליד את שם המשתמש',
@@ -820,7 +822,7 @@ $2',
 'gotaccount' => 'כבר נרשמתם? $1.',
 'gotaccountlink' => 'כניסה לחשבון',
 'userlogin-resetlink' => 'שכחת את פרטי הכניסה?',
-'userlogin-resetpassword-link' => '×\90×\99פ×\95ס ×\94ס×\99ס×\9e×\94',
+'userlogin-resetpassword-link' => 'ש×\9b×\97ת ×\90ת ×\94ס×\99ס×\9e×\94?',
 'helplogin-url' => 'Help:כניסה לחשבון',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|עזרה בכניסה לחשבון]]',
 'userlogin-loggedin' => 'אתם כבר מחוברים לחשבון {{GENDER:$1|$1}}.
@@ -876,7 +878,7 @@ $2',
 'passwordtooshort' => 'סיסמאות חייבות להיות באורך {{PLURAL:$1|תו אחד|$1 תווים}} לפחות.',
 'password-name-match' => 'סיסמתכם חייבת להיות שונה משם המשתמש שלכם.',
 'password-login-forbidden' => 'השימוש בשם המשתמש והסיסמה האלה נאסר.',
-'mailmypassword' => 'ש×\9c×\97×\95 ×\9c×\99 ×¡×\99ס×\9e×\94 ×\97×\93שה',
+'mailmypassword' => '×\90×\99פ×\95ס ×¡×\99ס×\9eה',
 'passwordremindertitle' => 'סיסמה זמנית חדשה מ{{grammar:תחילית|{{SITENAME}}}}',
 'passwordremindertext' => 'מישהו (ככל הנראה אתם, מכתובת ה־IP מספר $1) ביקש סיסמה
 חדשה לכניסה לחשבון ב{{GRAMMAR:תחילית|{{SITENAME}}}} ($4). נוצרה סיסמה זמנית למשתמש "$2",
@@ -890,7 +892,7 @@ $2',
 'passwordsent' => 'סיסמה חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור "$1".
 אנא היכנסו חזרה לאתר אחרי שתקבלו אותה.',
 'blocked-mailpassword' => 'כתובת ה־IP שלכם חסומה מעריכה, ולפיכך אינכם מורשים להשתמש באפשרות שחזור הסיסמה כדי למנוע ניצול לרעה של התכונה.',
-'eauthentsent' => '×\93×\95×\90\9c ×\90×\99×\9e×\95ת × ×©×\9c×\97 ×\9c×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×§×\91עת.
+'eauthentsent' => '×\93×\95×\90\9c ×\90×\99×\9e×\95ת × ×©×\9c×\97 ×\9c×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×¦×\95×\99× ×\94.
 לפני שדברי דוא"ל אחרים יישלחו לחשבון הזה, יהיה עליך לפעול לפי ההוראות בדוא"ל, כדי לאשר שהחשבון אכן שייך לך.',
 'throttled-mailpassword' => 'כבר נשלח דוא"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|־$1 השעות האחרונות}}.
 כדי למנוע ניצול לרעה, יכול להישלח רק דוא"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.',
@@ -898,8 +900,8 @@ $2',
 'acct_creation_throttle_hit' => 'מבקרים באתר זה דרך כתובת ה־IP שלכם כבר יצרו {{PLURAL:$1|חשבון אחד|$1 חשבונות}} ביום האחרון. זהו המקסימום המותר בתקופה זו.
 לפיכך, מבקרים דרך כתובת ה־IP הזו לא יכולים ליצור חשבונות נוספים ברגע זה.',
 'emailauthenticated' => 'כתובת הדוא"ל שלך אומתה ב־$3, $2.',
-'emailnotauthenticated' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9b×\9d ×¢×\93×\99×\99×\9f ×\9c×\90 ×\90×\95שרה.
\9c×\90 ×\99×\99ש×\9c×\97 ×\90×\9c×\99×\9b×\9d ×\93×\95×\90\9c ×¢×\91×\95ר ×\90×£ ×\90×\97ת ×\9e×\94×\90פשר×\95×\99ות הבאות.',
+'emailnotauthenticated' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9b×\9d ×¢×\93×\99×\99×\9f ×\9c×\90 ×\90×\95×\9eתה.
\9c×\90 ×\99×\99ש×\9c×\97 ×\90×\9c×\99×\9b×\9d ×\93×\95×\90\9c ×¢×\91×\95ר ×\90×£ ×\90×\97ת ×\9e×\94ת×\9b×\95× ות הבאות.',
 'noemailprefs' => 'אנא ציינו כתובת דוא"ל בהעדפות שלכם כדי שתכונות אלה יעבדו.',
 'emailconfirmlink' => 'אישור כתובת הדוא"ל שלך',
 'invalidemailaddress' => 'כתובת הדוא"ל אינה מתקבלת כיוון שנראה שהיא בפורמט לא נכון.
@@ -948,8 +950,8 @@ $2',
 
 # Special:PasswordReset
 'passwordreset' => 'איפוס סיסמה',
-'passwordreset-text-one' => '×\9e×\9c×\90×\95 ×\98×\95פס ×\96×\94 ×\9b×\93×\99 ×\9c×\90פס ×\90ת ×\94ס×\99ס×\9e×\94.',
-'passwordreset-text-many' => '{{PLURAL:$1||×\9e×\9c×\90×\95 ×\90×\97×\93 ×\9e×\94ש×\93×\95ת ×\94×\91×\90×\99×\9d ×\9b×\93×\99 ×\9c×\90פס ×\90ת ×\94ס×\99ס×\9e×\94.}}',
+'passwordreset-text-one' => '×\9e×\9c×\90×\95 ×\98×\95פס ×\96×\94 ×\9b×\93×\99 ×\9cק×\91×\9c ×¡×\99ס×\9e×\94 ×\96×\9e× ×\99ת ×\91×\93×\95×\90\9c.',
+'passwordreset-text-many' => '{{PLURAL:$1||×\9e×\9c×\90×\95 ×\90×\97×\93 ×\9e×\94ש×\93×\95ת ×\94×\91×\90×\99×\9d ×\9b×\93×\99 ×\9cק×\91×\9c ×¡×\99ס×\9e×\94 ×\96×\9e× ×\99ת ×\91×\93×\95×\90\9c.}}',
 'passwordreset-legend' => 'איפוס סיסמה',
 'passwordreset-disabled' => 'איפוסי סיסמה בוטלו באתר ויקי זה.',
 'passwordreset-emaildisabled' => 'שירותי הדוא"ל בוטלו באתר ויקי זה.',
@@ -986,7 +988,7 @@ $2
 
 # Special:ChangeEmail
 'changeemail' => 'שינוי כתובת דוא"ל',
-'changeemail-header' => 'שינוי כתוב דוא"ל של חשבון',
+'changeemail-header' => 'שינוי כתובת הדואר האלקטרוני בחשבון',
 'changeemail-text' => 'מלאו טופס זה כדי לשנות את כתובת הדואר האלקטרוני שלכם. יהיה עליכם למלא סיסמה כדי לאשר את השינוי.',
 'changeemail-no-info' => 'עליכם להיכנס לחשבון כדי לגשת לדף זה ישירות.',
 'changeemail-oldemail' => 'כתובת דוא"ל נוכחית:',
@@ -1021,7 +1023,7 @@ $2
 'headline_sample' => 'כותרת',
 'headline_tip' => 'כותרת – דרגה 2',
 'nowiki_sample' => 'טקסט לא מעוצב',
-'nowiki_tip' => '×\98קס×\98 ×\9c×\90 ×\9e×¢×\95צ×\91 (×\94תע×\9c×\9d ×\9eס×\99×\9e× ×\99 ×\95×\99ק×\99)',
+'nowiki_tip' => '×\94תע×\9c×\9e×\95ת ×\9e×¢×\99צ×\95×\91 ×\95×\99ק×\99',
 'image_tip' => 'קובץ המוצג בתוך הדף',
 'media_tip' => 'קישור לקובץ מדיה',
 'sig_tip' => 'חתימה + שעה',
@@ -1332,17 +1334,17 @@ $2
 'revdelete-suppress-text' => "יש להשתמש בהסתרה מלאה '''אך ורק''' במקרים הבאים:
 * מידע שעלול להיות לשון הרע
 * חשיפת מידע אישי
-*: '''×\9bת×\95×\91×\95ת ×\91ת×\99×\9d ×\95×\9eספר×\99 ×\98×\9cפ×\95×\9f, ×\9eספר×\99 ×\91×\99×\98×\95×\97 ×\9c×\90×\95×\9e×\99, וכדומה'''",
+*: '''×\9bת×\95×\91×\95ת ×\91ת×\99×\9d ×\95×\9eספר×\99 ×\98×\9cפ×\95×\9f, ×\9eספר×\99 ×\96×\99×\94×\95×\99 ×\9e×\93×\99נת×\99×\99×\9d, וכדומה'''",
 'revdelete-legend' => 'הגדרת הגבלות התצוגה',
-'revdelete-hide-text' => '×\94סתרת ×ª×\95×\9b×\9f ×\94×\92רס×\94',
+'revdelete-hide-text' => 'תוכן הגרסה',
 'revdelete-hide-image' => 'הסתרת תוכן הקובץ',
 'revdelete-hide-name' => 'הסתרת הפעולה ודף היעד',
-'revdelete-hide-comment' => '×\94סתרת ×ª×§×¦×\99ר ×\94ער×\99×\9b×\94',
-'revdelete-hide-user' => '×\94סתרת ×©×\9d ×\94×\9eשת×\9eש ×\90×\95 ×\9bת×\95×\91ת ×\94Ö¾IP ×©×\9c ×\94×¢×\95ר×\9a',
+'revdelete-hide-comment' => 'תקציר העריכה',
+'revdelete-hide-user' => 'שם המשתמש או כתובת ה־IP של העורך',
 'revdelete-hide-restricted' => 'הסתרת המידע גם ממפעילי המערכת',
 'revdelete-radio-same' => '(ללא שינוי)',
-'revdelete-radio-set' => '×\9b×\9f',
-'revdelete-radio-unset' => '×\9c×\90',
+'revdelete-radio-set' => '×\9e×\95סתר',
+'revdelete-radio-unset' => '×\92×\9c×\95×\99',
 'revdelete-suppress' => 'הסתרת המידע גם ממפעילי המערכת',
 'revdelete-unsuppress' => 'הסרת הגבלות בגרסאות המשוחזרות',
 'revdelete-log' => 'סיבה:',
@@ -1500,8 +1502,7 @@ $1",
 'preferences' => 'העדפות',
 'mypreferences' => 'העדפות',
 'prefs-edits' => 'מספר עריכות:',
-'prefsnologin' => 'לא נכנסת לחשבון',
-'prefsnologintext' => 'עליכם <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} להיכנס לחשבון]</span> כדי לשנות העדפות משתמש.',
+'prefsnologintext2' => 'אנא $1 כדי לשנות העדפות משתמש.',
 'changepassword' => 'שינוי סיסמה',
 'prefs-skin' => 'עיצוב',
 'skin-preview' => 'תצוגה מקדימה',
@@ -1590,9 +1591,9 @@ $1",
 'gender-unknown' => 'איני רוצה לומר',
 'gender-male' => 'הוא עורך דפים בוויקי',
 'gender-female' => 'היא עורכת דפים בוויקי',
-'prefs-help-gender' => '×\90×\99×\9f ×\97×\95×\91×\94 ×\9c×\9e×\9c×\90 ×\90ת ×\94×\94×¢×\93פ×\94 ×\94×\96×\90ת.
\94ת×\9b× ×\94 ×\9eשת×\9eשת ×\91×\9e×\99×\93×¢ ×\94×\96×\94 ×\9b×\93×\99 ×\9cפנ×\95ת ×\90×\9c×\99×\9a ×\90×\95 ×\90×\9c×\99×\99×\9a ×\95×\9c×\94×\96×\9b×\99ר ×\90×\95ת×\9a ×\9c×\90×\97ר×\99×\9d במין הדקדוקי הנכון.
\94×\9e×\99×\93×¢ ×\94×\96×\94 ×\99×\94×\99×\94 ×¦×\99×\91×\95ר×\99.',
+'prefs-help-gender' => '×\90×\99×\9f ×\97×\95×\91×\94 ×\9c×\9e×\9c×\90 ×\94×¢×\93פ×\94 ×\96×\95.
\94×\9eער×\9bת ×\9eשת×\9eשת ×\91×\9e×\99×\93×¢ ×\96×\94 ×\9b×\93×\99 ×\9cפנ×\95ת ×\90×\9c×\99×\9a\90×\9c×\99×\99×\9a ×\95×\9cצ×\99×\99×\9f ×\90ת ×©×\9d ×\94×\9eשת×\9eש ×©×\9c×\9a במין הדקדוקי הנכון.
+המידע יהיה ציבורי.',
 'email' => 'דוא"ל',
 'prefs-help-realname' => 'השם האמיתי הוא אופציונאלי.
 אם תבחרו לספקו, הוא ישמש לייחוס עבודתכם אליכם.',
@@ -1803,6 +1804,9 @@ $1",
 'recentchanges-label-minor' => 'זוהי עריכה משנית',
 'recentchanges-label-bot' => 'עריכה זו בוצעה על ידי בוט',
 'recentchanges-label-unpatrolled' => 'עריכה זו טרם נבדקה',
+'recentchanges-label-plusminus' => 'מספר הבתים שבו השתנה גודל הדף',
+'recentchanges-legend-newpage' => '(ראו גם [[Special:NewPages|רשימת דפים חדשים]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "להלן {{PLURAL:$1|השינוי האחרון|'''$1''' השינויים האחרונים}} {{PLURAL:$2|ביום האחרון|ביומיים האחרונים|ב־$2 הימים האחרונים}}, עד $5, $4:",
 'rcnotefrom' => 'להלן <b>$1</b> השינויים האחרונים שבוצעו החל מתאריך <b>$2</b>:',
 'rclistfrom' => 'הצגת שינויים חדשים החל מ־$1',
@@ -2248,7 +2252,8 @@ $1',
 'doubleredirectstext' => 'בדף הזה מופיעה רשימת דפי הפניה שמפנים לדפי הפניה אחרים.
 כל שורה מכילה קישור לשתי ההפניות הראשונות, וכן את היעד של ההפניה השנייה, שהיא לרוב היעד ה"אמיתי" של ההפניה, שההפניה הראשונה אמורה להצביע אליו.
 פריטים <del>מחוקים</del> כבר תוקנו.',
-'double-redirect-fixed-move' => '[[$1]] הועבר. כעת הוא הפניה לדף [[$2]].',
+'double-redirect-fixed-move' => '[[$1]] הועבר.
+כעת זו הפניה לדף [[$2]].',
 'double-redirect-fixed-maintenance' => 'תיקון הפניה כפולה מ[[$1]] ל[[$2]].',
 'double-redirect-fixer' => 'מתקן הפניות',
 
@@ -2330,7 +2335,7 @@ $1',
 'notargettitle' => 'אין דף מטרה',
 'notargettext' => 'לא ציינתם דף מטרה או משתמש לגביו תבוצע פעולה זו.',
 'nopagetitle' => 'אין דף מטרה כזה',
-'nopagetext' => 'דף המטרה שציינתם אינו קיים.',
+'nopagetext' => 'דף המטרה שציינת אינו קיים.',
 'pager-newer-n' => '{{PLURAL:$1|הבאה|$1 הבאות}}',
 'pager-older-n' => '{{PLURAL:$1|הקודמת|$1 הקודמות}}',
 'suppress' => 'הסתרה',
@@ -2537,9 +2542,9 @@ $PAGEINTRO $NEWPAGE
 בדואר האלקטרוני: $PAGEEDITOR_EMAIL
 באתר: $PAGEEDITOR_WIKI
 
-לא תהיינה הודעות על פעולות נוספות עד שתבקרו בדף. באפשרותכם גם לאפס את דגלי ההודעות בכל הדפים שברשימת המעקב.
+לא תהיינה הודעות על פעולות נוספות עד שתבקרו בדף כשאתם מחוברים לחשבון. באפשרותכם גם לאפס את דגלי ההודעות בכל הדפים שברשימת המעקב.
 
-             מערכת ההודעות של {{SITENAME}}
+מערכת ההודעות של {{SITENAME}}
 
 --
 כדי לשנות את ההגדרות של הודעות הדוא"ל הנשלחות אליכם, בקרו בדף
@@ -2741,7 +2746,7 @@ $1',
 
 # Contributions
 'contributions' => 'תרומות {{GENDER:$1|המשתמש|המשתמשת}}',
-'contributions-title' => 'תרומות של המשתמש $1',
+'contributions-title' => 'תרומות של ה{{GENDER:$1|משתמש|משתמשת}} $1',
 'mycontris' => 'תרומות',
 'contribsub2' => 'עבור {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'לא נמצאו שינויים המתאימים לקריטריונים אלו.',
@@ -2967,7 +2972,7 @@ $1',
 במקרים אלו, תצטרכו להעביר או לשלב את הדפים באופן ידני, אם תרצו.',
 'movearticle' => 'העברת דף:',
 'moveuserpage-warning' => "'''אזהרה:''' אתם עומדים להעביר דף משתמש. שימו לב שרק הדף יועבר וששם המשתמש '''לא''' ישתנה.",
-'movenologin' => 'לא נכנסתם לחשבון',
+'movenologin' => 'לא נכנסת לחשבון',
 'movenologintext' => 'עליכם [[Special:UserLogin|להיכנס לחשבון]] כדי להעביר דפים.',
 'movenotallowed' => 'אינכם מורשים להעביר דפים.',
 'movenotallowedfile' => 'אינכם מורשים להעביר קבצים.',
@@ -3151,13 +3156,13 @@ $2',
 'javascripttest-qunit-heading' => 'מערך בדיקות QUnit ל־JavaScript של מדיה־ויקי',
 
 # Tooltip help for the actions
-'tooltip-pt-userpage' => '×\93×£ ×\94×\9eשת×\9eש ×©×\9c×\9b×\9d',
+'tooltip-pt-userpage' => '×\93×£ ×\94×\9eשת×\9eש ×©×\9c×\9a',
 'tooltip-pt-anonuserpage' => 'דף המשתמש של משתמש אנונימי זה',
-'tooltip-pt-mytalk' => '×\93×£ ×\94ש×\99×\97×\94 ×©×\9c×\9b×\9d',
+'tooltip-pt-mytalk' => '×\93×£ ×\94ש×\99×\97×\94 ×©×\9c×\9a',
 'tooltip-pt-anontalk' => 'שיחה על תרומות המשתמש האנונימי',
-'tooltip-pt-preferences' => '×\94×\94×¢×\93פ×\95ת ×©×\9c×\9b×\9d',
+'tooltip-pt-preferences' => '×\94×\94×¢×\93פ×\95ת ×©×\9c×\9a',
 'tooltip-pt-watchlist' => 'רשימת הדפים שאתם עוקבים אחרי השינויים בהם',
-'tooltip-pt-mycontris' => 'רש×\99×\9eת ×\94תר×\95×\9e×\95ת ×©×\9c×\9b×\9d',
+'tooltip-pt-mycontris' => 'רש×\99×\9eת ×\94תר×\95×\9e×\95ת ×©×\9c×\9a',
 'tooltip-pt-login' => 'מומלץ להירשם, אך אין חובה לעשות כן',
 'tooltip-pt-anonlogin' => 'מומלץ להירשם, אך אין חובה לעשות כן',
 'tooltip-pt-logout' => 'יציאה מהחשבון',
@@ -3206,7 +3211,7 @@ $2',
 'tooltip-ca-nstab-help' => 'צפייה בדף העזרה',
 'tooltip-ca-nstab-category' => 'צפייה בדף הקטגוריה',
 'tooltip-minoredit' => 'סימון עריכה זו כמשנית',
-'tooltip-save' => 'שמירת השינויים שביצעתם',
+'tooltip-save' => 'שמירת השינויים שביצעת',
 'tooltip-preview' => 'תצוגה מקדימה, אנא השתמשו באפשרות זו לפני השמירה!',
 'tooltip-diff' => 'צפייה בשינויים שערכתם בטקסט',
 'tooltip-compareselectedversions' => 'צפייה בהשוואת שתי גרסאות של דף זה',
@@ -3268,6 +3273,8 @@ $2',
 'spam_reverting' => 'שחזור לגרסה אחרונה שלא כוללת קישורים ל־$1',
 'spam_blanking' => 'כל הגרסאות כוללות קישורים ל־$1, מרוקן את הדף',
 'spam_deleting' => 'כל הגרסאות כוללות קישורים ל־$1, מוחק את הדף',
+'simpleantispam-label' => "בדיקת אנטי־ספאם.
+'''אל''' תמלאו שדה זה!",
 
 # Info page
 'pageinfo-title' => 'מידע על "$1"',
@@ -3281,6 +3288,7 @@ $2',
 'pageinfo-length' => 'אורך הדף (בבתים)',
 'pageinfo-article-id' => 'מזהה הדף',
 'pageinfo-language' => 'שפת התוכן של הדף',
+'pageinfo-content-model' => 'סוג התוכן של הדף',
 'pageinfo-robot-policy' => 'איסוף על ידי רובוטים של מנועי חיפוש',
 'pageinfo-robot-index' => 'מותר',
 'pageinfo-robot-noindex' => 'אסור',
@@ -3367,7 +3375,7 @@ $1',
 'svg-long-desc' => 'קובץ SVG, הגודל המקורי: <span dir="ltr">$1 × $2</span> פיקסלים, גודל הקובץ: $3',
 'svg-long-desc-animated' => 'קובץ SVG מונפש, הגודל המקורי: <span dir="ltr">$1 × $2</span> פיקסלים, גודל הקובץ: $3',
 'svg-long-error' => 'קובץ SVG לא תקין: $1',
-'show-big-image' => 'ת×\9e×\95× ×\94 ×\91ר×\96×\95×\9c×\95צ×\99×\94 ×\92×\91×\95×\94×\94 ×\99×\95תר',
+'show-big-image' => '×\9cק×\95×\91×¥ ×\94×\9eק×\95ר×\99',
 'show-big-image-preview' => 'גודל תצוגה זו: $1.',
 'show-big-image-other' => '{{PLURAL:$2|רזולוציה אחרת|רזולוציות אחרות}}: $1.',
 'show-big-image-size' => '<span dir="ltr">$1 × $2</span> פיקסלים',
@@ -3632,6 +3640,10 @@ $1',
 'exif-compression-2' => 'קידוד הופמן מואתם חד-מימדי לאורך ריצה CCITT קבוצה 3',
 'exif-compression-3' => 'קידוד פקס CCITT קבוצה 3',
 'exif-compression-4' => 'קידוד פקס CCITT קבוצה 4',
+'exif-compression-6' => 'JPEG (ישן)',
+'exif-compression-8' => 'Deflate (של Adobe)',
+'exif-compression-32773' => 'PackBits (של Macintosh RLE)',
+'exif-compression-32946' => 'Deflate (של PKZIP)',
 
 'exif-copyrighted-true' => 'מוגן בזכויות יוצרים',
 'exif-copyrighted-false' => 'מצב זכויות היוצרים לא הוגדר',
@@ -3815,6 +3827,8 @@ $1',
 
 'exif-isospeedratings-overflow' => 'מעל 65535',
 
+'exif-maxaperturevalue-value' => '$1 APEX (יחידות: f/$2)',
+
 'exif-iimcategory-ace' => 'אמנויות, תרבות ובידור',
 'exif-iimcategory-clj' => 'פשע ומשפט',
 'exif-iimcategory-dis' => 'אסונות ותאונות',
@@ -3840,7 +3854,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'עריכת קובץ זה באמצעות יישום חיצוני',
-'edit-externally-help' => '(ראו את [//www.mediawiki.org/wiki/Manual:External_editors הוראות ההתקנה] למידע נוסף)',
+'edit-externally-help' => '(ראו את [https://www.mediawiki.org/wiki/Manual:External_editors הוראות ההתקנה] למידע נוסף)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'הכול',
@@ -3850,7 +3864,7 @@ $1',
 
 # Email address confirmation
 'confirmemail' => 'אימות כתובת דוא"ל',
-'confirmemail_noemail' => '×\90×\99×\9f ×\9c×\9b×\9d ×\9bת×\95×\91ת ×\93×\95×\90\9c ×ª×§×¤×\94 ×\94×\9e×\95×\92×\93רת ×\91[[Special:Preferences|×\94×¢×\93פ×\95ת ×\94×\9eשת×\9eש]] ×©×\9c×\9b×\9d.',
+'confirmemail_noemail' => '×\90×\99×\9f ×\9c×\9a ×\9bת×\95×\91ת ×\93×\95×\90\9c ×ª×§×¤×\94 ×\94×\9e×\95×\92×\93רת ×\91[[Special:Preferences|×\94×¢×\93פ×\95ת ×\94×\9eשת×\9eש]] ×©×\9c×\9a.',
 'confirmemail_text' => 'אתר זה דורש שתאמתו את כתובת הדוא"ל שלכם לפני שתשתמשו בשירותי הדוא"ל. לחצו על הכפתור למטה כדי לשלוח דוא"ל עם קוד אימות לכתובת הדוא"ל שהזנתם. טענו את הקישור בדפדפן שלכם כדי לאשר שכתובת הדוא"ל תקפה.',
 'confirmemail_pending' => 'קוד אימות דוא"ל כבר נשלח אליכם; אם יצרתם את החשבון לאחרונה, ייתכן שתרצו לחכות מספר דקות עד שיגיע לפני שתנסו לבקש קוד חדש.',
 'confirmemail_send' => 'לשלוח קוד אימות',
@@ -3862,9 +3876,9 @@ $1',
 תוכנת שליחת הדוא"ל החזירה את ההודעה הבאה: $1',
 'confirmemail_invalid' => 'קוד האימות שגוי. ייתכן שפג תוקפו.',
 'confirmemail_needlogin' => 'עליכם לבצע $1 כדי לאמת את כתובת הדוא"ל שלכם.',
-'confirmemail_success' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9b×\9d אושרה.
\9bעת ×\91×\90פשר×\95ת×\9b×\9d [[Special:UserLogin|×\9c×\94×\99×\9bנס ×\9c×\97ש×\91×\95×\9f ×©×\9c×\9b×\9d]] וליהנות מהאתר.',
-'confirmemail_loggedin' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9b×\9d אושרה כעת.',
+'confirmemail_success' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9a אושרה.
\9bעת ×\91×\90פשר×\95ת×\9a [[Special:UserLogin|×\9c×\94×\99×\9bנס ×\9c×\97ש×\91×\95×\9f ×©×\9c×\9a]] וליהנות מהאתר.',
+'confirmemail_loggedin' => '×\9bת×\95×\91ת ×\94×\93×\95×\90\9c ×©×\9c×\9a אושרה כעת.',
 'confirmemail_error' => 'שגיאה בשמירת קוד האימות.',
 'confirmemail_subject' => 'קוד אימות דוא"ל מ{{grammar:תחילית|{{SITENAME}}}}',
 'confirmemail_body' => 'מישהו, כנראה אתם (מכתובת ה־IP הזו: $1),
@@ -4086,7 +4100,7 @@ $5
 'version-hook-subscribedby' => 'הפונקציה הרושמת',
 'version-version' => '(גרסה $1)',
 'version-license' => 'רישיון',
-'version-poweredby-credits' => "אתר הוויקי הזה מופעל על ידי '''[//www.mediawiki.org/ מדיה־ויקי]''', © 2001–$1 $2.",
+'version-poweredby-credits' => "אתר הוויקי הזה מופעל על ידי '''[https://www.mediawiki.org/ מדיה־ויקי]''', © 2001–$1 $2.",
 'version-poweredby-others' => 'אחרים',
 'version-poweredby-translators' => 'מתרגמי translatewiki.net',
 'version-credits-summary' => 'אנו רוצים להודות לאנשים הבאים על תרומתם ל[[Special:Version|מדיה־ויקי]].',
@@ -4105,7 +4119,7 @@ $5
 # Special:Redirect
 'redirect' => 'הפניה לפי שם קובץ, מספר משתמש או מספר גרסה',
 'redirect-legend' => 'הפניה לקובץ או לדף',
-'redirect-summary' => 'דף מיוחד זה מפנה לקובץ (בהינתן שם הקובץ), לדף (בהינתן מספר גרסה), או לדף משתמש (בהינתן מספר משתמש).',
+'redirect-summary' => 'דף מיוחד זה מפנה לקובץ (בהינתן שם הקובץ), לדף (בהינתן מספר גרסה), או לדף משתמש (בהינתן מספר משתמש). דוגמאות לשימוש: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], או [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'מעבר',
 'redirect-lookup' => 'סוג:',
 'redirect-value' => 'ערך:',
@@ -4127,8 +4141,8 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'דפים מיוחדים',
-'specialpages-note' => '----
-* דפים מיוחדים רגילים.
+'specialpages-note-top' => 'מקרא',
+'specialpages-note' => '* דפים מיוחדים רגילים.
 * <span class="mw-specialpagerestricted">דפים מיוחדים מוגבלים.</span>',
 'specialpages-group-maintenance' => 'דיווחי תחזוקה',
 'specialpages-group-other' => 'דפים מיוחדים אחרים',
@@ -4182,9 +4196,9 @@ $5
 'compare-rev1' => 'גרסה 1',
 'compare-rev2' => 'גרסה 2',
 'compare-submit' => 'השוואה',
-'compare-invalid-title' => 'שם הדף שציינתם אינו תקין.',
-'compare-title-not-exists' => 'הדף שציינתם אינו קיים.',
-'compare-revision-not-exists' => 'הגרסה שציינתם אינה קיימת.',
+'compare-invalid-title' => 'שם הדף שציינת אינו תקין.',
+'compare-title-not-exists' => 'הדף שציינת אינו קיים.',
+'compare-revision-not-exists' => 'הגרסה שציינת אינה קיימת.',
 
 # Database error messages
 'dberr-header' => 'בעיה בוויקי',
@@ -4342,4 +4356,21 @@ $5
 'limitreport-expansiondepth' => 'עומק הפריסה הגבוה ביותר',
 'limitreport-expensivefunctioncount' => 'מספר פונקציות המפענח שגוזלות משאבים',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'פריסת תבניות',
+'expand_templates_intro' => 'הדף המיוחד הזה מקבל כמות מסוימת של טקסט ופורס את כל התבניות שבתוכו באופן רקורסיבי.
+הוא גם פורס פונקציות מפענח כגון
+<code><nowiki>{{</nowiki>#תנאי:...}}</code>, ומשתנים כגון
+<code><nowiki>{{</nowiki>יום נוכחי}}</code>.
+למעשה, הוא פורס פחות או יותר כל דבר בסוגריים מסולסלים כפולים.',
+'expand_templates_title' => 'כותרת ההקשר לפענוח, בשביל משתנים כגון {{FULLPAGENAME}} וכדומה:',
+'expand_templates_input' => 'טקסט הקלט:',
+'expand_templates_output' => 'תוצאה',
+'expand_templates_xml_output' => 'פלט XML',
+'expand_templates_ok' => 'אישור',
+'expand_templates_remove_comments' => 'הסרת הערות',
+'expand_templates_remove_nowiki' => 'הסרת תגי <nowiki> בתוצאה',
+'expand_templates_generate_xml' => 'הצגת עץ הפענוח של XML',
+'expand_templates_preview' => 'תצוגה מקדימה',
+
 );
index 1a6a7a0..f2273ba 100644 (file)
@@ -79,10 +79,9 @@ $specialPageAliases = array(
        'Allmessages'               => array( 'सभी_सन्देश', 'सभी_संदेश' ),
        'Allpages'                  => array( 'सभी_पृष्ठ', 'सभी_पन्ने' ),
        'Ancientpages'              => array( 'पुराने_पृष्ठ', 'पुराने_पन्ने' ),
-       'Badtitle'                  => array( 'à¤\96़राब_शà¥\80रà¥\8dषà¤\95' ),
+       'Badtitle'                  => array( 'खराब_शीर्षक' ),
        'Blankpage'                 => array( 'रिक्त_पृष्ठ', 'खाली_पृष्ठ' ),
        'Block'                     => array( 'अवरोधन', 'आइ_पी_अवरोधन', 'सदस्य_अवरोधन' ),
-       'Blockme'                   => array( 'स्वावरोधन', 'स्व_अवरोधन', 'मुझे_रोकिये' ),
        'Booksources'               => array( 'पुस्तक_स्रोत', 'किताब_स्रोत' ),
        'BrokenRedirects'           => array( 'टूटे_पुनर्निर्देश', 'टूटे_अनुप्रेष' ),
        'Categories'                => array( 'श्रेणियाँ' ),
@@ -94,10 +93,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'खाता_बनाएँ', 'खाता_बनायें', 'खाता_खोलें' ),
        'Deadendpages'              => array( 'बन्द_पृष्ठ', 'बन्द_पन्ने' ),
        'DeletedContributions'      => array( 'हटाए_गए_योगदान', 'हटाये_गये_योगदान' ),
-       'Disambiguations'           => array( 'बहुविकल्पी_कड़ियाँ', 'बहुविकल्पित' ),
        'DoubleRedirects'           => array( 'दुगुने_पुनर्निर्देश', 'दुगुने_अनुप्रेष' ),
        'EditWatchlist'             => array( 'ध्यानसूची_सम्पादन', 'ध्यानसूची_संपादन', 'ध्यानसूची_सम्पादन_करें' ),
        'Emailuser'                 => array( 'ईमेल_करें', 'सदस्य_को_ईमेल_करें' ),
+       'ExpandTemplates'           => array( 'साँचे_खोलें', 'साँचे_बढ़ाएँ' ),
        'Export'                    => array( 'निर्यात' ),
        'Fewestrevisions'           => array( 'न्यूनतम_अवतरण', 'कम_सम्पादित_पृष्ठ' ),
        'FileDuplicateSearch'       => array( 'फ़ाइल_प्रति_खोज', 'फाइल_प्रति_खोज', 'संचिका_प्रति_खोज' ),
@@ -462,8 +461,6 @@ $1',
 'ok' => 'ठीक है',
 'retrievedfrom' => '"$1" से लिया गया',
 'youhavenewmessages' => 'आपके लिए $1 हैं। ($2)',
-'newmessageslink' => 'नए सन्देश',
-'newmessagesdifflink' => 'पिछला बदलाव',
 'youhavenewmessagesfromusers' => 'आपके लिये {{PLURAL:$3|एक अन्य सदस्य|$3 अन्य सदस्यों}} के $1 हैं। ($2)',
 'youhavenewmessagesmanyusers' => 'आपके लिये $1 हैं। ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|एक नया सन्देश|नये सन्देश}}',
@@ -1331,8 +1328,6 @@ $1",
 'preferences' => 'मेरी वरीयताएँ',
 'mypreferences' => 'पसंद',
 'prefs-edits' => 'संपादन संख्या:',
-'prefsnologin' => 'लॉग इन नहीं किया है',
-'prefsnologintext' => 'वरीयताएँ बदलने के लिए आपको <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} सत्रारंभ]</span> करना होगा।',
 'changepassword' => 'कूटशब्द बदलें',
 'prefs-skin' => 'त्वचा',
 'skin-preview' => 'झलक',
@@ -1633,6 +1628,7 @@ HTML टैग की जाँच करें।',
 'recentchanges-label-minor' => 'यह एक छोटा सम्पादन है',
 'recentchanges-label-bot' => 'यह संपादन एक बॉट द्वारा किया गया था',
 'recentchanges-label-unpatrolled' => 'यह संपादन अभी जाँचा नहीं गया है',
+'recentchanges-legend-newpage' => '$1 - नया पन्ना',
 'rcnote' => "$5, $4 के पहले के '''$2''' {{PLURAL:$2|दिन|दिनों}} में  {{PLURAL:$1|हुआ '''$1''' बदलाव निम्न है| हुए '''$1''' बदलाव निम्न हैं}}।",
 'rcnotefrom' => "नीचे '''$2''' के बाद से ('''$1''' तक) हुए बदलाव दर्शाए गये हैं।",
 'rclistfrom' => '$1 से नये बदलाव दिखाएँ',
@@ -2891,7 +2887,7 @@ $1 को बाध्य करने का कारण है: "$2"',
 'allmessagesname' => 'नाम',
 'allmessagesdefault' => 'डिफॉल्ट पाठ',
 'allmessagescurrent' => 'वर्तमान पाठ',
-'allmessagestext' => 'ये मीडियाविकि नामस्थान में उपलब्ध प्रणाली संदेशों की एक सूची है। यदि आप सामान्य मीडियाविकि क्षेत्रीयकरण में योगदान देना चाहें तो कृपया [//www.mediawiki.org/wiki/Localisation मीडियाविकि क्षेत्रीयकरण] व [//translatewiki.net translatewiki.net] को देखें।',
+'allmessagestext' => 'ये मीडियाविकि नामस्थान में उपलब्ध प्रणाली संदेशों की एक सूची है। यदि आप सामान्य मीडियाविकि क्षेत्रीयकरण में योगदान देना चाहें तो कृपया [https://www.mediawiki.org/wiki/Localisation मीडियाविकि क्षेत्रीयकरण] व [//translatewiki.net translatewiki.net] को देखें।',
 'allmessagesnotsupportedDB' => "इस पृष्ठ का इस्तेमाल नहीं कर सकते क्योंकी '''\$wgUseDatabaseMessages''' बंद हैं।",
 'allmessages-filter-legend' => 'छानें',
 'allmessages-filter' => 'अनुकूलन स्थिति के आधार पर छानें:',
@@ -3087,6 +3083,8 @@ $1 को बाध्य करने का कारण है: "$2"',
 'spam_reverting' => '$1 को कड़ी ना होने वाले पुराने अवतरण को पुनर्स्थापित कर रहें हैं',
 'spam_blanking' => 'सभी अवतरणोंमें $1 को कड़ियां हैं, पूरा पाठ निकाल रहें हैं',
 'spam_deleting' => 'सभी अवतरणों में $1 की कड़ी थी, हटाया जा रहा है',
+'simpleantispam-label' => "ऍन्टी-स्पैम जाँच.
+इसे भरें '''नहीं'''!",
 
 # Info page
 'pageinfo-title' => '"$1" के लिये जानकारी',
@@ -3640,7 +3638,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'बाहरी प्रणाली का उपयोग करते हुए इस सञ्चिका को सम्पादित करें ।',
-'edit-externally-help' => '(और जानकारी के लिए [//www.mediawiki.org/wiki/Manual:External_editors जमाव निर्देश] देखें)',
+'edit-externally-help' => '(और जानकारी के लिए [https://www.mediawiki.org/wiki/Manual:External_editors जमाव निर्देश] देखें)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'सभी',
@@ -3877,7 +3875,7 @@ $5
 'version-hook-subscribedby' => 'ने सदस्यत्व लिया',
 'version-version' => '(अवतरण $1)',
 'version-license' => 'अनुज्ञापत्र',
-'version-poweredby-credits' => "यह विकि  '''[//www.mediawiki.org/ MediaWiki]''' द्वारा संचालित है, कॉपीराइट © 2001 - $1  $2 ।",
+'version-poweredby-credits' => "यह विकि  '''[https://www.mediawiki.org/ MediaWiki]''' द्वारा संचालित है, कॉपीराइट © 2001 - $1  $2 ।",
 'version-poweredby-others' => 'अन्य',
 'version-software' => 'इन्स्टॉल की हुई प्रणाली',
 'version-software-product' => 'प्रोडक्ट',
@@ -3902,8 +3900,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'विशेष पृष्ठ',
-'specialpages-note' => '----
-* साधारण विशेष पृष्ठ।
+'specialpages-note' => '* साधारण विशेष पृष्ठ।
 * <span class="mw-specialpagerestricted">प्रतिबंधित विशेष पृष्ठ।</span>',
 'specialpages-group-maintenance' => 'अनुरक्षण रिपोर्ट',
 'specialpages-group-other' => 'अन्य विशेष पृष्ठ',
@@ -4094,4 +4091,20 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|शताब्दी}}',
 'duration-millennia' => '$1 {{PLURAL:$1|सहस्राब्दी}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'साँचा विस्तार',
+'expand_templates_intro' => 'यह विशेष पृष्ठ पाठ इनपुट लेता है और सभी साँचों को विस्तृत करता है।
+यह <code><nowiki>{{</nowiki>#language:…}}</code> जैसे पार्सर फंक्शनों और
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code> जैसे वेरियेबलों को भी विस्तृत करता है।
+यह दोहरे कोष्ठकों में दिया लगभग सब कुछ विस्तृत करता है।',
+'expand_templates_title' => 'कन्टेक्स्ट शीर्षक, जैसे {{FULLPAGENAME}} आदि के लिए:',
+'expand_templates_input' => 'इनपुट पाठ:',
+'expand_templates_output' => 'परिणाम',
+'expand_templates_xml_output' => 'XML आउटपुट',
+'expand_templates_ok' => 'ओके',
+'expand_templates_remove_comments' => 'टिप्पणी हटायें',
+'expand_templates_remove_nowiki' => 'परिणाम में <nowiki> टैग हटाएँ',
+'expand_templates_generate_xml' => 'XML का पार्स (parse) वृक्ष दर्शायें',
+'expand_templates_preview' => 'झलक',
+
 );
index ac292cb..00f5cfc 100644 (file)
@@ -308,8 +308,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => '"$1" se lawa gais hae',
 'youhavenewmessages' => 'Aapke pass hai $1 ($2).',
-'newmessageslink' => 'nawaa khabar',
-'newmessagesdifflink' => 'pahile waala badlao',
 'youhavenewmessagesfromusers' => 'Aap ke lage {{PLURAL:$3|duusra sadasya|$3 sadasya}} ke lage se $1 hae ($2).',
 'youhavenewmessagesmanyusers' => 'Aap ke lage dher sadasya se $1 hae ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ek nawaa sandes|nawaa sandes}}',
@@ -1169,8 +1167,6 @@ Yaad rakhna ki uu log ke {{SITENAME}} ke index saait purana hoi.',
 'preferences' => 'Pasand',
 'mypreferences' => 'Pasand',
 'prefs-edits' => 'Badlao ke number:',
-'prefsnologin' => 'Aap abhi logged in nai hai',
-'prefsnologintext' => 'Aaap ke <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logged in]</span> chaahi rahe ke user preferences ke badle ke khatir.',
 'changepassword' => 'Pasword ke badlo',
 'prefs-skin' => 'Skin',
 'skin-preview' => 'Jhalak',
@@ -1465,6 +1461,7 @@ Iske $1 {{PLURAL:$1|character|characters}} se kamti rahe ke chaahi.',
 'recentchanges-label-minor' => 'Ii ek chhota badlao hae',
 'recentchanges-label-bot' => 'Ii badlao ke ek bot karis hae',
 'recentchanges-label-unpatrolled' => 'Ii badlao pe abhi pahraa nai dewa gais hae.',
+'recentchanges-legend-newpage' => '$1 - nawaa panna',
 'rcnote' => "Niche {{PLURAL:$1|hai '''1''' badlao|aakhri hai '''$1''' badlao}} pahile {{PLURAL:$2|din|'''$2''' din}}, $5, $4 talak.",
 'rcnotefrom' => "Niche '''$2''' se badlao hai ('''$1''' tak )",
 'rclistfrom' => '$1 se suruu kar ke nawaa badlao dekhao',
@@ -2714,7 +2711,7 @@ Duusra case me aap ek link ke bhi use kare saktaa hai, jaise ki [[{{#Special:Exp
 'allmessagesdefault' => 'Default text',
 'allmessagescurrent' => 'Abhi ke text',
 'allmessagestext' => 'Ii ek system sandes ke suchi hai jon ki MediaWiki namespace me pawa jaae sake hai.
-Agar aap generic MediaWiki localisation ke yogdaan de mangtaa hai tab meharbani kar ke [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] aur [//translatewiki.net translatewiki.net]  pe jao.',
+Agar aap generic MediaWiki localisation ke yogdaan de mangtaa hai tab meharbani kar ke [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] aur [//translatewiki.net translatewiki.net]  pe jao.',
 'allmessagesnotsupportedDB' => "Ii panna ke kaam me nai lawa jaae sake hai kahe ki '''\$wgUseDatabaseMessages''' ke band kar dewa gais hai.",
 'allmessages-filter-legend' => 'Chaalo',
 'allmessages-filter' => 'Customisation state se chhaano',
@@ -3464,7 +3461,7 @@ Wahii line pe aur koi jorr exception consider karaa jai i.e. jahaan pe panna sak
 
 # External editor support
 'edit-externally' => 'Ii file ke bahaari program me kaam me laae ke badlo',
-'edit-externally-help' => '(Aur jaankari khatir [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] ke dekho)',
+'edit-externally-help' => '(Aur jaankari khatir [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] ke dekho)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sab',
index 1c611e3..2b35ef2 100644 (file)
@@ -277,8 +277,6 @@ Lantawa ang [[Special:Version|panid sang mga bersiyon]].',
 'ok' => 'Sige',
 'retrievedfrom' => 'Ginkuha halin sa "$1"',
 'youhavenewmessages' => 'Ikaw may $1 ($2).',
-'newmessageslink' => 'mga bag-ong mensahe',
-'newmessagesdifflink' => 'nagligad nga ginbag-o',
 'youhavenewmessagesfromusers' => 'May yara ka sang $1 halin sa {{PLURAL:$3|lain nga manuggamit|$3 mga manuggamit}} ($2).',
 'youhavenewmessagesmanyusers' => 'May yara ka sang $1 halin sa madamo nga manuggamit ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|isa ka bag-o nga mensahe|bag-o nga mga mensahe}}',
@@ -1094,8 +1092,6 @@ Tandai nga ang ila nga palasulundan sang mga unod sang {{SITENAME}} mahimo nga m
 'preferences' => 'Mga Ginabasehan',
 'mypreferences' => 'Mga Ginabasehan',
 'prefs-edits' => 'Numero sang mga gin-ilisan:',
-'prefsnologin' => 'Wala naka-sulod',
-'prefsnologintext' => 'Kinahanglan nga ikaw <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} nakasulod]</span> agod nga mabuhat ang pag-ilis sang mga ginapalabi.',
 'changepassword' => 'Ilisan ang pasword',
 'prefs-skin' => 'Panit',
 'skin-preview' => 'Ipakita subong',
@@ -1240,7 +1236,7 @@ Ang imo adres sang e-mail wala ginapakita kon kontakon ka sang iban.',
 'group-all' => '(tanan)',
 
 'group-user-member' => '{{GENDER:$1|naga-usar}}',
-'group-autoconfirmed-member' => '{GENDER:$1|naga-usar nga awtomatikong nakompirma}}',
+'group-autoconfirmed-member' => '{{GENDER:$1|naga-usar nga awtomatikong nakompirma}}',
 'group-bot-member' => '{{GENDER:$1|bot}}',
 'group-sysop-member' => '{{GENDER:$1|tagdumala}}',
 'group-bureaucrat-member' => '{{GENDER:$1|byurokratiko}}',
@@ -1417,7 +1413,7 @@ Mga Pahina sa [[Special:Watchlist|imo lista-lantaw]] ay '''dukot'''.",
 'upload-recreate-warning' => "'''Abiso: Ang isa ka file nga amo ang iya ngalan ginpanas na ukon ginsaylo'''
 
 Ang log sang pagpanas kag pagsaylo para sa sini nga panid ginahatag diri para sa imo nga kombinyensya.",
-'uploadtext' => "Usaron ang porma sa idalum para makakarga sang mga file. Para matan-aw ukon mapangita ang mga file nga ginkarga na, kadto sa:[Special:FileList|lista sang mga files nga ginkarga]], ang mga ginkarga liwat nakalista sa: [[Special:Log/upload|lista sang mga ginkarga]], ang mga ginpanas [[Special:Log/delete|lista sang mga ginpanas]].
+'uploadtext' => "Usaron ang porma sa idalum para makakarga sang mga file. Para matan-aw ukon mapangita ang mga file nga ginkarga na, kadto sa:[[Special:FileList|lista sang mga files nga ginkarga]], ang mga ginkarga liwat nakalista sa: [[Special:Log/upload|lista sang mga ginkarga]], ang mga ginpanas [[Special:Log/delete|lista sang mga ginpanas]].
 
 Para maupod ang isa ka file sa isa ka panid, usaron ang sini nga sugpon sa mga masunod nga mga porma:
 * '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' para mausar ang bilog nga bersyon sang file
@@ -1884,7 +1880,7 @@ Ang iban ay pagataguon sang default.
 
 # External editor support
 'edit-externally' => 'Islan ini nga file gamit ang eksternal nga aplikasyon',
-'edit-externally-help' => '(Lantawa ang [//www.mediawiki.org/wiki/Manual:External_editors tudlo sa pag panugod] para sa mga dugang nga impormasyon)',
+'edit-externally-help' => '(Lantawa ang [https://www.mediawiki.org/wiki/Manual:External_editors tudlo sa pag panugod] para sa mga dugang nga impormasyon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tanan',
@@ -1932,4 +1928,7 @@ Ang iban ay pagataguon sang default.
 'revdelete-unrestricted' => 'ginkakas nga pagbawal sa mga administrador',
 'rightsnone' => '(wala)',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'Ipakita subong',
+
 );
index baeb6b8..3d68980 100644 (file)
@@ -69,7 +69,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Stare_stranice' ),
        'Blankpage'                 => array( 'Prazna_stranica' ),
        'Block'                     => array( 'Blokiraj' ),
-       'Blockme'                   => array( 'Blokiraj_me' ),
        'Booksources'               => array( 'Traži_ISBN' ),
        'BrokenRedirects'           => array( 'Kriva_preusmjeravanja' ),
        'Categories'                => array( 'Kategorije' ),
@@ -79,7 +78,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Stvori_račun' ),
        'Deadendpages'              => array( 'Slijepe_ulice' ),
        'DeletedContributions'      => array( 'Obrisani_doprinosi' ),
-       'Disambiguations'           => array( 'Razdvojbe' ),
        'DoubleRedirects'           => array( 'Dvostruka_preusmjeravanja' ),
        'Emailuser'                 => array( 'Elektronička_pošta', 'E-mail' ),
        'Export'                    => array( 'Izvezi' ),
@@ -590,8 +588,6 @@ $1',
 'ok' => 'U redu',
 'retrievedfrom' => 'Dobavljeno iz "$1"',
 'youhavenewmessages' => 'Imate $1 ($2).',
-'newmessageslink' => 'nove poruke',
-'newmessagesdifflink' => 'zadnja promjena na stranici za razgovor',
 'youhavenewmessagesfromusers' => 'Imate $1 {{PLURAL:$3||od $3 suradnika|od $3 suradnika}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od više suradnika ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|$1 nove poruke|$1 novih poruka}}',
@@ -762,8 +758,10 @@ Ne zaboravite prilagoditi Vaše [[Special:Preferences|{{SITENAME}} postavke]].',
 'gotaccount' => "Već imate suradnički račun? '''$1'''.",
 'gotaccountlink' => 'Prijavite se',
 'userlogin-resetlink' => 'Zaboravili ste detalje vaše prijave?',
-'userlogin-resetpassword-link' => 'Ponovno postavi zaporku',
+'userlogin-resetpassword-link' => 'Zaboravili ste zaporku?',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoć pri prijavi]]',
+'userlogin-loggedin' => 'Već ste prijavljeni kao {{GENDER:$1|$1}}.
+Rabite donji obrazac da biste se prijavili kao drugi suradnik.',
 'userlogin-createanother' => 'Stvori još jedan račun',
 'createacct-join' => 'Upišite ispod svoje podatke.',
 'createacct-another-join' => 'Upišite dolje podatke o novom računu.',
@@ -822,16 +820,16 @@ koristiti staru lozinku.',
 'noemailcreate' => 'Morate navesti važeću e-mail adresu',
 'passwordsent' => 'Nova je lozinka poslana na e-mail adresu suradnika "$1"',
 'blocked-mailpassword' => 'Vašoj IP adresi je blokirano uređivanje stranica, a da bi se spriječila nedopuštena radnja, mogućnost zahtijevanja nove lozinke je također onemogućena.',
-'eauthentsent' => 'Na navedenu adresu poslan je e-mail s potvrdom.
-Prije nego što pošaljemo daljnje poruke, molimo Vas da otvorite e-mail i slijedite u njemu sadržana uputstva kako biste potvrdili da je e-mail adresa zaista Vaša.',
+'eauthentsent' => 'Na navedenu adresu poslana je e-poruka s potvrdom.
+Prije nego što pošaljemo daljnje poruke, molimo Vas otvorite e-poruku i slijedite u njemu sadržana uputstva kako biste potvrdili da je adresa e-pošte zaista Vaša.',
 'throttled-mailpassword' => 'Već Vam je poslan e-mail za promjenu zaporke, u {{PLURAL:$1|zadnjih sat vremena|zadnja $1 sata|zadnjih $1 sati}}.
 Da bi spriječili zloupotrebu, moguće je poslati samo jedan e-mail za promjenu zaporke {{PLURAL:$1|svakih sat vremena|svaka $1 sata|svakih $1 sati}}.',
 'mailerror' => 'Pogrješka pri slanju e-pošte: $1',
 'acct_creation_throttle_hit' => 'Posjetitelji ovog wikija koji rabe Vašu IP adresu napravili su {{PLURAL:$1|1 račun|$1 računa}} u posljednjem danu, što je najveći dopušteni broj u tom vremenskom razdoblju.
 Zbog toga posjetitelji s ove IP adrese trenutačno ne mogu otvoriti nove suradničke račune.',
-'emailauthenticated' => 'vaša e-mail adresa je ovjerena $2 u $3.',
-'emailnotauthenticated' => 'Vaša e-mail adresa još nije ovjerena.
-Ne možemo poslati e-mail ni u jednoj od sljedećih naredbi.',
+'emailauthenticated' => 'Vaša adresa e-pošte potvrđena je $2 u $3.',
+'emailnotauthenticated' => 'Vaša adresa e-pošte još nije potvrđena.
+Ne možemo poslati e-poruku ni u jednoj od sljedećih naredbi.',
 'noemailprefs' => 'Nije navedena adresa elektroničke pošte, stoga sljedeće naredbe ne će raditi.',
 'emailconfirmlink' => 'Potvrdite svoju e-mail adresu',
 'invalidemailaddress' => 'Ne mogu prihvatiti e-mail adresu jer nije valjano oblikovana.
@@ -850,6 +848,8 @@ Molimo Vas pričekajte $1 prije nego što pokušate ponovno.',
 'login-abort-generic' => 'Vaša prijava bila je neuspješna - Prekinuto',
 'loginlanguagelabel' => 'Jezik: $1',
 'suspicious-userlogout' => 'Vaš zahtjev za odjavu je odbijen jer to izgleda kao da je poslan preko pokvarenog preglednika ili keširanog posrednika (proxyja).',
+'createacct-another-realname-tip' => 'Pravo ime nije obvezno. 
+Ako ga navedete, bit će korišteno za pripisivanje Vaših doprinosa.',
 
 # Email sending
 'php-mail-error-unknown' => 'Nepoznata pogrješka u funkciji PHP-poruke()',
@@ -877,6 +877,7 @@ Možda ste već uspješno promijenili Vašu lozinku ili ste zatražili novu priv
 # Special:PasswordReset
 'passwordreset' => 'Ponovno postavi lozinku',
 'passwordreset-text-one' => 'Ispunite ovaj obrazac ako želite ponovno postaviti Vašu zaporku.',
+'passwordreset-text-many' => '{{PLURAL:$1|Ispunite jedno od polja za ponovno postavljanje Vaše zaporke.}}',
 'passwordreset-legend' => 'Poništi lozinku',
 'passwordreset-disabled' => 'Poništavanje lozinke je onemogućeno na ovom wikiju.',
 'passwordreset-emaildisabled' => 'Funkcija e-pošte je onemogućena na ovom wikiju.',
@@ -1405,8 +1406,6 @@ Više informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{F
 'preferences' => 'Postavke',
 'mypreferences' => 'Moje postavke',
 'prefs-edits' => 'Broj uređivanja:',
-'prefsnologin' => 'Niste prijavljeni',
-'prefsnologintext' => 'Morate biti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prijavljeni]</span> za podešavanje suradničkih postavki.',
 'changepassword' => 'Promjena lozinke',
 'prefs-skin' => 'Izgled',
 'skin-preview' => 'Pregled',
@@ -1443,6 +1442,7 @@ Više informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{F
 'recentchangesdays-max' => '(maksimalno $1 {{PLURAL:$1|dan|dana}})',
 'recentchangescount' => 'Zadani broj izmjena koje se prikazuju:',
 'prefs-help-recentchangescount' => 'Ovo uključuje nedavne promjene, stare izmjene, i evidencije.',
+'prefs-help-watchlist-token2' => 'Ovo je tajni ključ prema sažetku Vašeg popisa praćenja. Svaki suradnik kojem je poznat, moći će čitati Vaš popis praćenih stranica. Ne dijelite ga ni s kim. [[Special:ResetTokens|Kliknite ovdje ako ga želite ponovo postaviti]].',
 'savedprefs' => 'Vaše postavke su sačuvane.',
 'timezonelegend' => 'Vremenska zona:',
 'localtime' => 'Lokalno vrijeme:',
@@ -1690,6 +1690,7 @@ Ne smije biti duži od $1 {{PLURAL:$1|znaka|znaka|znakova}}.',
 'recentchanges-label-minor' => 'Ovo je manja izmjena',
 'recentchanges-label-bot' => 'Ovu izmjenu napravio je bot',
 'recentchanges-label-unpatrolled' => 'Ova izmjena još nije pregledana',
+'recentchanges-legend-newpage' => '$1 - nova stranica',
 'rcnote' => "{{PLURAL:$1|Slijedi zadnja '''$1''' promjena|Slijede zadnje '''$1''' promjene|Slijedi zadnjih '''$1''' promjena}} u {{PLURAL:$2|zadnjem '''$2''' danu|zadnja '''$2''' dana|zadnjih '''$2''' dana}}, od $5, $4.",
 'rcnotefrom' => 'Slijede promjene od <b>$2</b> (prikazano ih je do <b>$1</b>).',
 'rclistfrom' => 'Prikaži nove promjene počevši od $1',
@@ -2898,7 +2899,7 @@ U potonjem slučaju možete rabiti i poveznicu, npr. [[{{#Special:Export}}/{{Med
 'allmessagesname' => 'Ime',
 'allmessagesdefault' => 'Prvotni tekst',
 'allmessagescurrent' => 'Trenutačni tekst',
-'allmessagestext' => 'Ovo je popis svih sistemskih poruka u imenskom prostoru MediaWiki. Molimo posjetite [//www.mediawiki.org/wiki/Localisation lokalizaciju MediaWikija] i [//translatewiki.net translatewiki.net] ako želite doprinijeti lokalizaciji MediaWiki softvera.',
+'allmessagestext' => 'Ovo je popis svih sistemskih poruka u imenskom prostoru MediaWiki. Molimo posjetite [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWikija] i [//translatewiki.net translatewiki.net] ako želite doprinijeti lokalizaciji MediaWiki softvera.',
 'allmessagesnotsupportedDB' => "Ova stranica ne može biti korištena jer je isključen parametar '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Filtriraj',
 'allmessages-filter' => 'Filtriraj prema prilagođenom obliku:',
@@ -3091,6 +3092,8 @@ Razlog je vjerojatno vanjska poveznica koja se nalazi na crnom popisu.',
 'spam_reverting' => 'Vraćam na zadnju inačicu koja ne sadrži poveznice na $1',
 'spam_blanking' => 'Sve inačice sadrže poveznice na $1, brišem cjelokupni sadržaj',
 'spam_deleting' => 'Sve inačice sadržale su poveznice na $1, brišem cjelokupni sadržaj',
+'simpleantispam-label' => "Anti-spam provjera.
+'''Ne''' ispunjavajte ovo!",
 
 # Info page
 'pageinfo-title' => 'Podatci o stranici "$1"',
@@ -3647,7 +3650,7 @@ Svaka sljedeća poveznica u istom retku je izuzetak, npr. kod stranica gdje se s
 
 # External editor support
 'edit-externally' => 'Uredi koristeći se vanjskom aplikacijom',
-'edit-externally-help' => '(Vidi [//www.mediawiki.org/wiki/Manual:External_editors setup upute] za više informacija)',
+'edit-externally-help' => '(Vidi [https://www.mediawiki.org/wiki/Manual:External_editors setup upute] za više informacija)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sve',
@@ -3887,9 +3890,9 @@ Također možete koristiti [[Special:EditWatchlist|standardni editor]].',
 'version-hook-subscribedby' => 'Pretplaćeno od',
 'version-version' => '(Inačica $1)',
 'version-license' => 'Licencija',
-'version-poweredby-credits' => "Ovaj wiki pogoni '''[//www.mediawiki.org/ MediaWiki]''', autorska prava © 2001-$1 $2.",
+'version-poweredby-credits' => "Ovaj wiki pogoni '''[https://www.mediawiki.org/ MediaWiki]''', autorska prava © 2001-$1 $2.",
 'version-poweredby-others' => 'ostali',
-'version-credits-summary' => 'Željeli bismo se zahvaliti sljedećim suradnicima na njihovom doprinosu [[Special:Version|MediaWikiju]].',
+'version-credits-summary' => 'Željeli bismo zahvaliti sljedećim suradnicima na njihovom doprinosu [[Special:Version|MediaWikiju]].',
 'version-license-info' => 'MediaWiki je slobodni softver; možete ga distribuirati i/ili mijenjati pod uvjetima GNU opće javne licencije u obliku u kojem ju je objavila Free Software Foundation; bilo verzije 2 licencije, ili (Vama na izbor) bilo koje kasnije verzije.
 
 MediaWiki je distribuiran u nadi da će biti koristan, no BEZ IKAKVOG JAMSTVA; čak i bez impliciranog jamstva MOGUĆNOSTI PRODAJE ili PRIKLADNOSTI ZA ODREĐENU NAMJENU. Pogledajte GNU opću javnu licenciju za više detalja.
@@ -3921,8 +3924,7 @@ Trebali ste primiti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju GNU opće javne lic
 
 # Special:SpecialPages
 'specialpages' => 'Posebne stranice',
-'specialpages-note' => '----
-* Normalne posebne stranice
+'specialpages-note' => '* Normalne posebne stranice
 * <span class="mw-specialpagerestricted">Posebne stranice s ograničenim pristupom.</span>',
 'specialpages-group-maintenance' => 'Izvještaji za održavanje',
 'specialpages-group-other' => 'Ostale posebne stranice',
@@ -4120,4 +4122,20 @@ Inače, možete ispuniti jednostavan obrazac u nastavku. Vaš komentar biti će
 # Image rotation
 'rotate-comment' => 'Sliku je $1 zaokrenuo za {{PLURAL:$1|stupanj|stupnja|stupnjeva}} u smjeru kazaljke na satu.',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Prikaz sadržaja predložaka',
+'expand_templates_intro' => 'Ova posebna stranica omogućuje unos wikiteksta i prikazuje njegov rezultat,
+uključujući i (rekurzivno, tj. potpuno) sve uključene predloške u wikitekstu.
+Prikazuje i rezultate funkcija kao <nowiki>{{</nowiki>#language:...}} i varijabli
+kao <nowiki>{{</nowiki>CURRENTDAY}}. Funkcionira pozivanjem parsera same MedijeWiki.',
+'expand_templates_title' => 'Kontekstni naslov stranice, za {{FULLPAGENAME}} i sl.:',
+'expand_templates_input' => 'Ulazni tekst:',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'XML kod',
+'expand_templates_ok' => 'Prikaži',
+'expand_templates_remove_comments' => 'Ukloni komentare',
+'expand_templates_remove_nowiki' => 'Ukloni <nowiki> tagove u rezultatima.',
+'expand_templates_generate_xml' => 'Prikaži XML stablo',
+'expand_templates_preview' => 'Vidi kako će izgledati',
+
 );
index 55add6b..a72e2a5 100644 (file)
@@ -70,7 +70,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Najstarše_strony' ),
        'Blankpage'                 => array( 'Prózdna_strona' ),
        'Block'                     => array( 'Blokować' ),
-       'Blockme'                   => array( 'Blokowanje_proksijow' ),
        'Booksources'               => array( 'Pytanje_po_ISBN' ),
        'BrokenRedirects'           => array( 'Skóncowane_daleposrědkowanja' ),
        'Categories'                => array( 'Kategorije' ),
@@ -80,7 +79,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Konto_wutworić' ),
        'Deadendpages'              => array( 'Strony_bjez_wotkazow' ),
        'DeletedContributions'      => array( 'Zničene_přinoški' ),
-       'Disambiguations'           => array( 'Rozjasnjenja_wjazmyslnosće' ),
        'DoubleRedirects'           => array( 'Dwójne_daleposrědkowanja' ),
        'Emailuser'                 => array( 'E-Mejl' ),
        'Export'                    => array( 'Eksport' ),
@@ -162,12 +160,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Dohladawane změny w aktualnych změnach schować',
 'tog-newpageshidepatrolled' => 'Dohladowane strony z lisćiny nowych stronow schować',
 'tog-extendwatchlist' => 'Lisćinu wobkedźbowankow wočinić, zo by wšě změny widźał, nic jenož najnowše',
-'tog-usenewrc' => 'Skupinske změny po stronje w aktualnych změnach a wobkedźbowankach (trjeba JavaScript)',
+'tog-usenewrc' => 'Změny po stronje w aktualnych změnach a wobkedźbowankach zeskupjeć',
 'tog-numberheadings' => 'Nadpisma awtomatisce čisłować',
-'tog-showtoolbar' => 'Gratowu lajstu pokazać (wužaduje sej JavaScript)',
-'tog-editondblclick' => 'Strony z dwójnym kliknjenjom wobdźěłować (wužaduje sej JavaScript)',
+'tog-showtoolbar' => 'Wobdźěłowansku lajstu pokazać',
+'tog-editondblclick' => 'Strony z dwójnym kliknjenjom wobdźěłować',
 'tog-editsection' => 'Wobdźěłowanje jednotliwych wotrězkow přez wotkazy [wobdźěłać] zmóžnić',
-'tog-editsectiononrightclick' => 'Wobdźěłowanje jednotliwych wotrězkow přez kliknjenje z prawej tastu na nadpisma wotrězkow zmóžnić (wužaduje sej JavaScript)',
+'tog-editsectiononrightclick' => 'Wobdźěłowanje wotrězkow přez kliknjenje z prawej tastu na nadpisma wotrězkow zmóžnić',
 'tog-showtoc' => 'Zapis wobsaha pokazać (za strony z wjace hač 3 nadpismami)',
 'tog-rememberpassword' => 'Přizjewjenje na tutym wobhladowaku sej spomjatkować (za maksimalnje $1 {{PLURAL:$1|dźeń|dnjej|dny|dnjow}})',
 'tog-watchcreations' => 'Strony, kotrež wutworjam a dataje, kotrež nahrawam, swojim wobkedźbowankam přidać',
@@ -185,7 +183,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Ličbu wobkedźbowacych wužiwarjow pokazać',
 'tog-oldsig' => 'Eksistowaca signatura:',
 'tog-fancysig' => 'Ze signaturu kaž z wikitekstom wobchadźeć  (bjez awtomatiskeho wotkaza)',
-'tog-uselivepreview' => 'Live-přehlad wužiwać (wužaduje sej JavaScript) (eksperimentalny)',
+'tog-uselivepreview' => 'Live-přehlad wužiwać (eksperimentalny)',
 'tog-forceeditsummary' => 'Mje skedźbnić, jeli zabudu zjeće',
 'tog-watchlisthideown' => 'Moje změny we wobkedźbowankach schować',
 'tog-watchlisthidebots' => 'Změny awtomatiskich programow (botow) we wobkedźbowankach schować',
@@ -198,6 +196,7 @@ $messages = array(
 'tog-showhiddencats' => 'Schowane kategorije pokazać',
 'tog-norollbackdiff' => 'Rozdźěl po wróćostajenju zanjechać',
 'tog-useeditwarning' => 'Warnować, hdyž so wobdźěłowanska strona z njeskładowanymi změnami wopušća',
+'tog-prefershttps' => 'Po přizjewjenju přeco wěsty zwisk wužiwać',
 
 'underline-always' => 'Přeco',
 'underline-never' => 'Ženje',
@@ -298,7 +297,7 @@ $messages = array(
 'newwindow' => '(wočinja so w nowym woknje)',
 'cancel' => 'Přetorhnyć',
 'moredotdotdot' => 'Wjace…',
-'morenotlisted' => 'Dalše njepodate...',
+'morenotlisted' => 'Tuta lisćina dospołna njeje.',
 'mypage' => 'Strona',
 'mytalk' => 'Diskusija',
 'anontalk' => 'Diskusijna strona tuteje IP.adresy',
@@ -401,7 +400,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Wo {{GRAMMAR:lokatiw|{{SITENAME}}}}',
 'aboutpage' => 'Project:Wo',
-'copyright' => 'Wobsah steji pod $1.',
+'copyright' => 'Wobsah pod $1 k dispoziciji steji, jeli njeje so hinak podało.',
 'copyrightpage' => '{{ns:project}}:Awtorske prawa',
 'currentevents' => 'Aktualne podawki',
 'currentevents-url' => 'Project:Aktualne podawki',
@@ -427,12 +426,10 @@ $1',
 'ok' => 'W porjadku',
 'retrievedfrom' => 'Z "$1"',
 'youhavenewmessages' => 'Maš $1 ($2).',
-'newmessageslink' => 'nowe powěsće',
-'newmessagesdifflink' => 'poslednja změna',
 'youhavenewmessagesfromusers' => 'Maš $1 wot {{PLURAL:$3|druheho wužiwarja|$3 wužiwarjow|$3 wužiwarjow|$3 wužiwarjow}} ($2).',
 'youhavenewmessagesmanyusers' => 'Maš $1 wot wjele wužiwarjow ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|nowu powěsć|nowej powěsći|nowe powěsće}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|poslednja změna|poslednjej změnje|poslednje změny|poslednje změny}}',
+'newmessageslinkplural' => '{{PLURAL:$1|nowu powěsć|999=nowej powěsći|999=nowe powěsći}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|poslednja změna|999=poslednjej změnje|999=poslednje změny}}',
 'youhavenewmessagesmulti' => 'Maš nowe powěsće: $1',
 'editsection' => 'wobdźěłać',
 'editold' => 'wobdźěłać',
@@ -484,6 +481,12 @@ Płaćiwe specialne strony hodźa so pod [[Special:SpecialPages|lisćinu special
 # General errors
 'error' => 'Zmylk',
 'databaseerror' => 'Zmylk w datowej bance',
+'databaseerror-text' => 'Zmylk w datowej bance je wustupił.
+To móže na programowy zmylk w softwarje pokazać.',
+'databaseerror-textcl' => 'Zmylk w datowej bance je wustupił.',
+'databaseerror-query' => 'Wotprašenje: $1',
+'databaseerror-function' => 'Funkcija: $1',
+'databaseerror-error' => 'Zmylk: $1',
 'laggedslavemode' => "'''Kedźbu:''' Je móžno, zo strona žane zaktualizowanja njewobsahuje.",
 'readonly' => 'Datowa banka je zawrjena',
 'enterlockreason' => 'Zapodaj přičinu za zawrjenje a přibližny čas, hdy budźe zawrjenje zběhnjene',
@@ -517,6 +520,7 @@ Móže być, zo je hižo wot někoho druheho wušmórnjena.',
 'cannotdelete-title' => 'Strona "$1" njehodźi so zhašeć',
 'delete-hook-aborted' => 'Zhašenje přez hoku přetorhnjene.
 Njeje žane wujasnjenje podała.',
+'no-null-revision' => 'Nowa nulowa wersija za stronu "$1" njeda so wutworić',
 'badtitle' => 'Wopačny titul',
 'badtitletext' => 'Požadane mjeno strony běše njepłaćiwy, prózdny abo njekorektny titul z mjezyrěčneho abo interwikijoweho wotkaza. Snano wobsahuje jedne znamješko abo wjacore znamješka, kotrež w titulach dowolene njejsu.',
 'perfcached' => 'Slědowace daty pochadźeja z pufrowaka a njejsu snano cyle aktualne. Maksimalnje {{PLURAL:$1|jedyn wuslědk|$1 wuslědkaj|$1 wuslědki|$1 wuslědkow}} w pufrowaku k dispoziciji {{PLURAL:$1|steji|stejitej|steja|steji}}.',
@@ -553,7 +557,8 @@ Administrator, kiž je jón zawrěł, je tule přičinu podał: "$3".',
 'invalidtitle-knownnamespace' => 'Njepłaćiwy titul z mjenowym rumom "$2" a tekstom "$3"',
 'invalidtitle-unknownnamespace' => 'Njepłaćiwy titul z njeznatym mjenowym rumom $1 a tekstom "$2"',
 'exception-nologin' => 'Njejsy přizjewjeny',
-'exception-nologin-text' => 'Tuta strona abo akcija sej wužaduje, zo sy na tutym wikiju přizjewjeny.',
+'exception-nologin-text' => 'Prošu [[Special:Userlogin|přizjew so]], zo by přistup na tutu stronu abo akciju měł.',
+'exception-nologin-text-manual' => 'Zo by přistup na tutu stronu abo akciju měł, dyrbiš so $1.',
 
 # Virus scanner
 'virus-badscanner' => "Špatna konfiguracija: Njeznaty wirusowy skener: ''$1''",
@@ -563,14 +568,14 @@ Administrator, kiž je jón zawrěł, je tule přičinu podał: "$3".',
 # Login and logout pages
 'logouttext' => "'''{{GENDER:|Sy|Sy}} nětko {{GENDER:|wotzjewjeny|wotzjewjena}}.'''
 
-Móžeš {{GRAMMAR:akuzatiw|{{SITENAME}}}} nětko anonymnje dale wužiwać abo so ze samsnym abo druhim wužiwarskim mjenom <span class='plainlinks'>[$1 zaso přizjewić]</span>.
-Wobkedźbuj, zo so někotre strony dale jewja, kaž by hišće přizjewjeny był, doniž pufrowak swojeho wobhladowaka njewuprózdnješ.",
+Kedźbu: Je móžno, zo někotre strony so snano takle pokazuja, kaž by ty hišće přizjewjeny był, doniž pufrowak twojeho wobhladowaka njewuprózdniš.",
 'welcomeuser' => 'Witaj $1',
 'welcomecreation-msg' => 'Twoje konto bu wutworjene.
 Njezabudź swoje [[Special:Preferences|nastajenja za {{GRAMMAR:akuzatiw|{{SITENAME}}}}]] změnić.',
 'yourname' => 'Wužiwarske mjeno:',
 'userlogin-yourname' => 'Wužiwarske mjeno',
 'userlogin-yourname-ph' => 'Zapodaj swoje wužiwarske mjeno',
+'createacct-another-username-ph' => 'Wužiwarske mjeno zapodać',
 'yourpassword' => 'Hesło:',
 'userlogin-yourpassword' => 'Hesło',
 'userlogin-yourpassword-ph' => 'Zapodaj swoje hesło',
@@ -600,14 +605,18 @@ Njezabudź swoje [[Special:Preferences|nastajenja za {{GRAMMAR:akuzatiw|{{SITENA
 'gotaccount' => 'Maš hižo wužiwarske konto? $1.',
 'gotaccountlink' => 'Přizjewić',
 'userlogin-resetlink' => 'Přizjewjenske daty zabył?',
-'userlogin-resetpassword-link' => 'Hesło anulować',
+'userlogin-resetpassword-link' => 'Sy swoje hesło zabył?',
 'helplogin-url' => 'Help:Přizjewić',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoc za přizjewjenje]]',
+'userlogin-loggedin' => 'Sy hižo jako {{GENDER:$1|$1 přizjewjeny|$1 přizjewjena}}. Wužij slědowacy formular, zo by so jako druhi wužiwar přizjewił.',
+'userlogin-createanother' => 'Dalše konto załožić',
 'createacct-join' => 'Zapodaj deleka swoje informacije.',
+'createacct-another-join' => 'Zapodaj deleka informacije noweho konta.',
 'createacct-emailrequired' => 'E-mejlowa adresa',
 'createacct-emailoptional' => 'E-mejlowa adresa (opcionalny)',
 'createacct-email-ph' => 'Zapodaj swoju e-mejlowu adresu',
-'createaccountmail' => 'Nachwilne přidatne hesło wužiwać a jo na slědowacu e-mejlowu adresu pósłać',
+'createacct-another-email-ph' => 'E-mejlowu adresu zapodać',
+'createaccountmail' => 'Nachwilne připadne hesło wužiwać a jo na slědowacu e-mejlowu adresu pósłać',
 'createacct-realname' => 'Woprawdźite mjeno (opcionalny)',
 'createaccountreason' => 'Přičina:',
 'createacct-reason' => 'Přičina',
@@ -615,6 +624,7 @@ Njezabudź swoje [[Special:Preferences|nastajenja za {{GRAMMAR:akuzatiw|{{SITENA
 'createacct-captcha' => 'Wěstotna kontrola',
 'createacct-imgcaptcha-ph' => 'Zapodaj tekst, kotryž deleka widźiš',
 'createacct-submit' => 'Twoje konto załožić',
+'createacct-another-submit' => 'Dalše konto załožić',
 'createacct-benefit-heading' => '{{SITENAME}} je so wot ludźi kaž ty wutworił.',
 'createacct-benefit-body1' => '{{PLURAL:$1|změna|změnje|změny|změnow}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|strona|stronje|strony|stronow}}',
@@ -655,12 +665,12 @@ Jeli něchtó druhi wo nowe hesło prosył abo ty sy so zaso na swoje hesło dop
 'passwordsent' => 'Nowe hesło bu na e-mejlowu adresu zregistrowanu za wužiwarja „$1” pósłane.
 Prošu přizjew so znowa, po tym zo sy je přijał.',
 'blocked-mailpassword' => 'Twoja IP-adresa je přećiwo wobdźěłowanju zablokowana, a tohodla njeje dowolene, funkciju za wobnowjenje hesłow wužiwać, zo by znjewužiwanju zadźěwało.',
-'eauthentsent' => 'Wobkrućenska e-mejlka bu na naspomnjenu e-mejlowu adresu pósłana.
-Prjedy hač so druha e-mejlka na konto pósćele, dyrbiš so po instrukcijach w e-mejlce měć, zo by wobkrućił, zo konto je woprawdźe twoje.',
+'eauthentsent' => 'Wobkrućenska e-mejlka je so na podatu e-mejlowu adresu pósłała.
+Prjedy hač so druha e-mejlka na konto pósćele, dyrbiš so po instrukcijach w e-mejlce měć, zo by wobkrućił, zo konto woprawdźe tebi słuša.',
 'throttled-mailpassword' => 'E-mejl za anulowanje hesło je so za {{PLURAL:$1|poslednju hodźinu|poslednjej $1 hodźinje|poslednje $1 hodźiny|poslednich $1 hodźin}} pósłała. Zo by znjewužiwanju zadźěwało, so jenož jedna e-mejl za anulowanje hesła na {{PLURAL:$1|hodźinu|$1 hodźinje|$1 hodźiny|$1 hodźin}} pósćele.',
 'mailerror' => 'Zmylk při słanju e-mejlki: $1',
 'acct_creation_throttle_hit' => 'Wopytowarjo tutoho wikija, kotřiž twoju IP-adresu wužiwaja, su {{PLURAL:$1|1 konto|$1 kontaj|$1 konty|$1 kontow}} posledni dźeń wutworił, štož je maksimalna ličba za tutu periodu. Wopytowarjo, kotřiž tutu IP-adresu wužiwaja, njemóža tuchwilu dalše konta wutworić.',
-'emailauthenticated' => 'Twoja e-mejlowa adresa bu $2 $3 hodź. wobkrućena.',
+'emailauthenticated' => 'Twoja e-mejlowa adresa je so $2 $3 hodź. wobkrućiła.',
 'emailnotauthenticated' => 'Twoja e-mejlowa adresa hišće wobkrućena njeje. Žana e-mejlka budźe so za slědowace funkcije słać.',
 'noemailprefs' => 'Podaj e-mejlowu adresu w swojich nastajenjach, zo bychu tute funkcije k dispoziciji stali.',
 'emailconfirmlink' => 'Swoju e-mejlowu wobkrućić',
@@ -674,10 +684,12 @@ Prjedy hač so druha e-mejlka na konto pósćele, dyrbiš so po instrukcijach w
 
 Móžeš tutu zdźělenku ignorować, jeli so wužiwarske konto zmylnje wutworiło.',
 'usernamehasherror' => 'Wužiwarske mjeno njesmě hašowe znamješka wpbsahować',
-'login-throttled' => 'Sy přehusto spytał so přizjewić. Počakaj prošu, prjedy hač znowa spytaš.',
+'login-throttled' => 'Sy přehusto spytał so přizjewić. Počakaj prošu $1, prjedy hač hišće raz spytaš.',
 'login-abort-generic' => 'Twoje přizjewjenje njebě wuspěšne - přetorhnjene',
 'loginlanguagelabel' => 'Rěč: $1',
 'suspicious-userlogout' => 'Twoje naprašowanje za wotzjewjenje bu wotpokazane, dokelž zda so, jako by so přez wobškodźeny wobhladowak abo pufrowacy proksy pósłało',
+'createacct-another-realname-tip' => '* Woprawdźite mjeno je opcionalne.
+Jeli jo podaš, budźe so to wužiwać, zo by přinoški přirjadowało.',
 
 # Email sending
 'php-mail-error-unknown' => 'Njeznaty zmylk w PHP-funkciji mail()',
@@ -693,7 +705,7 @@ Móžeš tutu zdźělenku ignorować, jeli so wužiwarske konto zmylnje wutwori
 'newpassword' => 'Nowe hesło:',
 'retypenew' => 'Nowe hesło wospjetować:',
 'resetpass_submit' => 'Hesło posrědkować a so přizjewić',
-'changepassword-success' => 'Twoje hesło bu wuspěšnje změnjene! Nětko přizjewjenje běži...',
+'changepassword-success' => 'Twoje hesło je so wuspěšnje změniło!',
 'resetpass_forbidden' => 'Hesła njedadźa so změnić.',
 'resetpass-no-info' => 'Dyrbiš so přizjewić, zo by direktny přistup na tutu stronu měł.',
 'resetpass-submit-loggedin' => 'Hesło změnić',
@@ -706,7 +718,7 @@ Snano sy swoje hesło hižo wuspěšnje změnił abo nowe nachwilne hesło poža
 # Special:PasswordReset
 'passwordreset' => 'Hesło wróćo stajić',
 'passwordreset-text-one' => 'Wupjelń tutón formular, zo by swoje hesło anulował.',
-'passwordreset-text-many' => '{{PLURAL:$1|Zapodaj jedyn z datow, zo by swoje hesło anulował.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Zapodaj jedne z polow, zo by swoje hesło wróćo stajił.}}',
 'passwordreset-legend' => 'Hesło wróćo stajić',
 'passwordreset-disabled' => 'Wróćostajenje hesłow je so na  tutym wikiju znjemóžniło.',
 'passwordreset-emaildisabled' => 'E-mejlowe funkcije su so na tutym wikiju znjemóžnili.',
@@ -746,6 +758,19 @@ Nachwilne hesło: $2',
 'changeemail-submit' => 'E-mejlowu adresu změnić',
 'changeemail-cancel' => 'Přetorhnyć',
 
+# Special:ResetTokens
+'resettokens' => 'Tokeny wróćo stajić',
+'resettokens-text' => 'Móžeš tokeny wróćo stajić, kotrež přistup na wěste priwatne daty dowoleja, kotrež su z twojim kontom zwjazane.
+
+Ty dyrbjał zo činić, jeli sy je zmylnje z někim dźělił abo jelic twoje konto je so napadało.',
+'resettokens-no-tokens' => 'Tokeny za wróćostajenje njejsu.',
+'resettokens-legend' => 'Tokeny wróćo stajić',
+'resettokens-tokens' => 'Tokeny:',
+'resettokens-token-label' => '$1 (aktualna hódnota: $2)',
+'resettokens-watchlist-token' => 'Token za webkanal (Atom/RSS) [[Special:Watchlist|změnow na stronach w twojich wobkedźbowankach]]',
+'resettokens-done' => 'Tokeny wróćostajene.',
+'resettokens-resetbutton' => 'Wubrane tokeny wróćo stajić',
+
 # Edit page toolbar
 'bold_sample' => 'Tučny tekst',
 'bold_tip' => 'Tučny tekst',
@@ -821,9 +846,7 @@ Móžno, zo je so přesunył abo zhašał, mjeztym zo sej wobhladuješ stronu.',
 'loginreqlink' => 'přizjewić',
 'loginreqpagetext' => 'Dyrbiš so $1, zo by strony čitać móhł.',
 'accmailtitle' => 'Hesło bu pósłane.',
-'accmailtext' => "Připadnje spłodźene hesło za [[User talk:$1|$1]] bu do $2 pósłane.
-
-Hesło za tute nowe konto da so na stronje ''[[Special:ChangePassword|hesło změnić]]'' při přizjewjenju změnić.",
+'accmailtext' => "Připadnje spłodźene hesło za [[User talk:$1|$1]] bu na $2 pósłane. Daj so na stronje ''[[Special:ChangePassword|hesło změnić]]'' při přizjewjenju změnić.",
 'newarticle' => '(Nowy)',
 'newarticletext' => 'Sy wotkaz k stronje slědował, kotraž hišće njeeksistuje. Zo by stronu wutworił, wupjelń slědowace tekstowe polo (hlej [[{{MediaWiki:Helppage}}|stronu pomocy]] za dalše informacije). Jeli sy zmylnje tu, klikń prosće na tłóčatko <b>Wróćo</b> we swojim wobhladowaku.',
 'anontalkpagetext' => "---- ''To je diskusijna strona za anonymneho wužiwarja, kiž hišće konto wutworił njeje abo je njewužiwa. Dyrbimy tohodla numerisku IP-adresu wužiwać, zo bychmy jeho/ju identifikowali. Tajka IP-adresa hodźi so wot wjacorych wužiwarjow zhromadnje wužiwać. Jeli sy anonymny wužiwar a měniš, zo buchu irelewantne komentary k tebi pósłane, [[Special:UserLogin/signup|wutwor prošu konto]] abo [[Special:UserLogin|přizjew so]], zo by přichodnu šmjatańcu z anonymnymi wužiwarjemi wobešoł.''",
@@ -1059,18 +1082,19 @@ Móžeš sej tutón rozdźěl wobhladać; podrobnosće namakaš w [{{fullurl:{{#
 Druzy administratorojo na {{GRAMMAR:lokatiw|{{SITENAME}}}} móža hišće na schowany tekst přistup měć a jón z pomocu samsneho interfejsa wobnowić, chibazo tež přidatne prawa su wobmjezowane.",
 'revdelete-confirm' => 'Prošu potwjerdź, zo chceš to činić, zo rozumiš konsekwency a zo činiš to po [[{{MediaWiki:Policy-url}}|prawidłach]].',
 'revdelete-suppress-text' => "Potłóčenje dyrbjało so '''jenož''' za slědowace pady wužiwać:
+* Potencielnje křiwdźace informacije
 * Njepřihódne wosobinske informacije
-*: ''bydlenske adresy a telefonowe čisła, čisła socialneho zawěsćenja atd.''",
+*: ''Bydlenske adresy a telefonowe čisła, čisła socialneho zawěsćenja atd.''",
 'revdelete-legend' => 'Wobmjezowanja za widźomnosć nastajić',
-'revdelete-hide-text' => 'Tekst tuteje wersije schować',
+'revdelete-hide-text' => 'Tekst wersije',
 'revdelete-hide-image' => 'Wobsah wobraza schować',
 'revdelete-hide-name' => 'Akciju a cil schować',
-'revdelete-hide-comment' => 'Zjeće schować',
-'revdelete-hide-user' => 'Wužiwarske mjeno/IP-adresu schować',
+'revdelete-hide-comment' => 'Zjeće změnow',
+'revdelete-hide-user' => 'Mjeno/IP-adresa wobdźěłarja',
 'revdelete-hide-restricted' => 'Daty wot administratorow kaž tež te druhich wužiwarjow potłóčić',
 'revdelete-radio-same' => '(njezměnić)',
-'revdelete-radio-set' => 'Haj',
-'revdelete-radio-unset' => '',
+'revdelete-radio-set' => 'Schowany',
+'revdelete-radio-unset' => 'Widźomny',
 'revdelete-suppress' => 'Přičinu wušmórnjenja tež za administratorow schować',
 'revdelete-unsuppress' => 'Wobmjezowanja za wobnowjene wersije zběhnyć',
 'revdelete-log' => 'Přičina:',
@@ -1150,6 +1174,7 @@ Zawěsć, zo tuta změna stawiznisku kontinuitu strony wobchowuje.',
 'compareselectedversions' => 'Wubranej wersiji přirunać',
 'showhideselectedversions' => 'Wubrane wersije pokazać/schować',
 'editundo' => 'cofnyć',
+'diff-empty' => '(Žadyn rozdźěl)',
 'diff-multi' => '({{PLURAL:$1|Jedna mjezywersija|$1 mjezywersiji|$1 mjezywersije|$1 mjezywersijow}} wot {{PLURAL:$2|jednoho wužiwarja|$2 wužiwarjow|$2 wužiwarjow|$2 wužiwarjow}} {{PLURAL:$1|njepokazana|njepokazanej|njepokazane|njepokazane}})',
 'diff-multi-manyusers' => '({{PLURAL:$1|Jedna mjezywersija|$1 mjezywersiji|$1 mjezywersije|$1 mjezywersijow}} wot wjace hač {{PLURAL:$2|jednoho wužiwarja|$2 wužiwarjow|$2 wužiwarjow|$2 wužiwarjow}} {{PLURAL:$1|njepokazana|njepokazanej|njepokazane|njepokazane}})',
 'difference-missing-revision' => '{{PLURAL:$2|Jedna wersija|$2 wersiji|$2 wersije|$2 wersijow}} tutoho rozdźěla ($1) {{PLURAL:$2|njeje so namakała|njejstej so namakałoj|njejsu namakali|njeje so namakało}}.
@@ -1224,8 +1249,7 @@ Spytaj swoje naprašowanje z prefiksom ''all:'' wužiwać, zo by wšón wobsah (
 'preferences' => 'Nastajenja',
 'mypreferences' => 'Nastajenja',
 'prefs-edits' => 'Ličba změnow:',
-'prefsnologin' => 'Njepřizjewjeny',
-'prefsnologintext' => 'Dyrbiš <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} přizjewjeny]</span>  być, zo by móhł nastajenja postajić.',
+'prefsnologintext2' => 'Dyrbiš so $1, zo by wužiwarske nastajenja postajił.',
 'changepassword' => 'Hesło změnić',
 'prefs-skin' => 'Drasta',
 'skin-preview' => 'Přehlad',
@@ -1250,7 +1274,7 @@ Spytaj swoje naprašowanje z prefiksom ''all:'' wužiwać, zo by wšón wobsah (
 'prefs-rendering' => 'Napohlad',
 'saveprefs' => 'Składować',
 'resetprefs' => 'Njeskładowane změny zaćisnyć',
-'restoreprefs' => 'Wšě standardne nastajenja wobnowić',
+'restoreprefs' => 'Wšě standardne nastajenja wobnowić (w druhich wotrězkach)',
 'prefs-editing' => 'Wobdźěłowanje',
 'rows' => 'Rjadki:',
 'columns' => 'Stołpiki:',
@@ -1262,6 +1286,9 @@ Spytaj swoje naprašowanje z prefiksom ''all:'' wužiwać, zo by wšón wobsah (
 'recentchangesdays-max' => '(Maksimalnje $1 {{PLURAL:$1|dźeń|dnjej|dny|dnjow}})',
 'recentchangescount' => 'Ličba stronow, kotraž ma so po standardźe pokazać:',
 'prefs-help-recentchangescount' => 'To zapřijima aktualne změny, stawizny stronow a protokole.',
+'prefs-help-watchlist-token2' => 'To je tajny kluč k webkanalej twojich wobkedźbowankow.
+Něchtó, kotryž jón znaje, móže twoje wobkedźbowanki čitać, njedźěl jón tohodla.
+[[Special:ResetTokens|Klikń tu, jeli dybiš jón wróćo stajić]].',
 'savedprefs' => 'Nastajenja buchu składowane.',
 'timezonelegend' => 'Časowe pasmo:',
 'localtime' => 'Lokalny čas:',
@@ -1306,11 +1333,13 @@ Móžeš tutu stronu wužiwać, zo by swoje nastajenja na standardne hódnoty sy
 'badsig' => 'Njepłaćiwa signatura, prošu HTML přepruwować.',
 'badsiglength' => 'Twoja signatura je předołha.
 Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} dołha być.',
-'yourgender' => 'Splah:',
-'gender-unknown' => 'Njepodaty',
-'gender-male' => 'Muski',
-'gender-female' => 'Žónski',
-'prefs-help-gender' => 'Opcionalny: wužiwa so za po splahu specifiske narěčenje přez softwaru. Tuta informacija budźe zjawna.',
+'yourgender' => 'Što chceš podać?',
+'gender-unknown' => 'Nochcu ničo wo tym podać',
+'gender-male' => 'Wón wobdźěłuje wikistrony',
+'gender-female' => 'Wona wobdźěłuje wikistrony',
+'prefs-help-gender' => 'Tute podaće je opcionalne:
+Softwara wužiwa jeho hódnotu, zo by će z pomocu wotpowědneho gramatikaliskeho roda narěčała a druhich na tebje pokazała.
+Tuta informacija budźe zjawna.',
 'email' => 'E-mejl',
 'prefs-help-realname' => '* Woprawdźite mjeno (opcionalne): jeli so rozsudźiš to zapodać, budźe to so wužiwać, zo by tebi woprawnjenje za twoje dźěło dało.',
 'prefs-help-email' => 'E-mejlowa adresa je opcionalna, ale zmóžnja ći nowe hesło emejlować, jeli sy swoje hesło zabył.',
@@ -1321,7 +1350,7 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'prefs-signature' => 'Podpis',
 'prefs-dateformat' => 'Datumowy format',
 'prefs-timeoffset' => 'Časowe wotchilenje',
-'prefs-advancedediting' => 'Powšitkowny',
+'prefs-advancedediting' => 'Powšitkowne nastajenja',
 'prefs-editor' => 'Editor',
 'prefs-preview' => 'Přehlad',
 'prefs-advancedrc' => 'Rozšěrjene opcije',
@@ -1331,7 +1360,9 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'prefs-displayrc' => 'Zwobraznjenske opcije',
 'prefs-displaysearchoptions' => 'Zwobraznjenske opcije',
 'prefs-displaywatchlist' => 'Zwobraznjenske opcije',
+'prefs-tokenwatchlist' => 'Token',
 'prefs-diffs' => 'Rozdźěle',
+'prefs-help-prefershttps' => 'Tute nastajenje so po twojim přichodnym přizjewjenju wuskutkuje.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Zda so, zo e-mejlowa adresa je płaćiwa',
@@ -1355,10 +1386,10 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'userrights-no-interwiki' => 'Nimaš prawo wužiwarske prawa w druhich wikijach změnić.',
 'userrights-nodatabase' => 'Datowa banka $1 njeeksistuje abo lokalna njeje.',
 'userrights-nologin' => 'Dyrbiš so z admininstratorowym kontom [[Special:UserLogin|přizjewić]], zo by wužiwarske prawa změnił.',
-'userrights-notallowed' => 'Twoje konto nima trěbne prawa, zo by wužiwarske prawa přidźěliło abo zebrało.',
+'userrights-notallowed' => 'Nimaš trěbne prawa, zo by wužiwarske prawa přidźěliło abo zebrało.',
 'userrights-changeable-col' => 'Skupiny, kotrež móžeš změnić',
 'userrights-unchangeable-col' => 'Skupiny, kotrež njemóžeš změnić',
-'userrights-conflict' => 'Konflikt wužiwarskich prawow! Prošu čiń swoje změny hišće raz.',
+'userrights-conflict' => 'Konflikt změnow wužiwarskich prawow! Prošu přepruwuj a wobkruć swoje změny.',
 'userrights-removed-self' => 'Sy swoje prawa wuspěšnje wotstronił. Tohodla nimaš hižo přistup na tutu stronu měć.',
 
 # Groups
@@ -1403,7 +1434,7 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'right-reupload-shared' => 'Dataje w hromadźe wužiwanej repozitoriju lokalnje přepisać',
 'right-upload_by_url' => 'Dataju z URL-adresy nahrać',
 'right-purge' => 'Pufrowak sydła za stronu bjez wobkrućenskeje strony wuprózdnić',
-'right-autoconfirmed' => 'Połzaškitane strony wobdźěłać',
+'right-autoconfirmed' => 'Žane wobmjezowanje přez IP-bazowane limity',
 'right-bot' => 'Ma so jako awtomatiski proces wobjednać',
 'right-nominornewtalk' => 'Snadne změny k diskusijnym stronam zwobraznjenje nowych powěsćow wuwołać njedać',
 'right-apihighlimits' => 'Wyše limity wi API-naprašowanjach wužiwać',
@@ -1424,7 +1455,7 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'right-ipblock-exempt' => 'Blokowanja IP, awtomatiske blokowanje a blokowanja wobwodow wobeńć',
 'right-proxyunbannable' => 'Automatiske blokowanja proksyjow wobeńć',
 'right-unblockself' => 'Swójske blokowanje zběhnyć',
-'right-protect' => 'Škitowe schodźenki změnić a škitanu stronu wobdźěłać',
+'right-protect' => 'Škitowe schodźenki změnić a z kaskadami škitane strony wobdźěłać',
 'right-editprotected' => 'Strony wobdźěłać, kotrež su přez "{{int:protect-level-sysop}}" škitane',
 'right-editsemiprotected' => 'Strony wobdźěłać, kotrež su přez "{{int:protect-level-autoconfirmed}}" škitane',
 'right-editinterface' => 'Wužiwarski powjerch wobdźěłać',
@@ -1489,8 +1520,8 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'action-block' => 'Wobdźěłanju přez wužiwarja zadźěwać',
 'action-protect' => 'škitowe runiny za tutu stronu změnić',
 'action-rollback' => 'Změny poslednjeho wužiwarja, kiž je wěstu stronu wobdźěłał, spěšnje wróćo stajić',
-'action-import' => 'Tutu stronu z druheho wikija importować',
-'action-importupload' => 'Tutu stronu z datajoweho nahraća importować',
+'action-import' => 'Strony z druheho wikija importować',
+'action-importupload' => 'Strony z datajoweho nahraća importować',
 'action-patrol' => 'Změny druhich wužiwarjiw jako dohladowane markować',
 'action-autopatrol' => 'twoju změnu jako dohladowanu markować dać',
 'action-unwatchedpages' => 'lisćinu njewobkedźbowanych stronow zwobraznić',
@@ -1506,6 +1537,8 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|změna|změnje|změny|změnow}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|wot poslednjeho wopyta}}',
+'enhancedrc-history' => 'historija',
 'recentchanges' => 'Aktualne změny',
 'recentchanges-legend' => 'Opcije aktualnych změnow',
 'recentchanges-summary' => 'Na tutej stronje móžeš najaktualniše změny w {{GRAMMAR:lokatiw|{{SITENAME}}}} wobkedźbować.',
@@ -1515,6 +1548,9 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'recentchanges-label-minor' => 'To je snadna změna',
 'recentchanges-label-bot' => 'Tuta změna bu přez roboćik přewjedźena',
 'recentchanges-label-unpatrolled' => 'Tuta změnu hišće njebu přepruwowana',
+'recentchanges-label-plusminus' => 'Změnjena wulkosć strony (w bajtach)',
+'recentchanges-legend-newpage' => '(hlej tež [[Special:NewPages|lisćinu nowych stronow]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Deleka {{PLURAL:$1|je '''1''' změna|stej poslednjej '''$1''' změnje|su poslednje '''$1''' změny|je poslednich '''$1''' změnow}} za {{PLURAL:$2|posledni dźeń|poslednjej '''$2''' dnjej|poslednje '''$2''' dny|poslednich '''$2''' dnjow}}, staw wot $4, $5.",
 'rcnotefrom' => "Deleka so změny wot '''$2''' pokazuja (hač k '''$1''').",
 'rclistfrom' => 'Nowe změny pokazać, započinajo z $1',
@@ -1538,7 +1574,7 @@ Smě mjenje hač $1 {{PLURAL:$1|znamješko|znamješce|znamješka|znamješkow}} d
 'rc-change-size' => '$1 {{PLURAL:$1|bajt|bajtaj|bajty|bajtow}}',
 'rc-change-size-new' => '$1 {{PLURAL:$1|bajt|bajtaj|bajty|bajtow}} po změnje',
 'newsectionsummary' => 'Nowy wotrězk: /* $1 */',
-'rc-enhanced-expand' => 'Podrobnosće pokazać (wužaduje sej JavaScript)',
+'rc-enhanced-expand' => 'Podrobnosće pokazać',
 'rc-enhanced-hide' => 'Podrobnosće schować',
 'rc-old-title' => 'prěnjotnje wutworjeny jako "$1"',
 
@@ -1799,8 +1835,7 @@ Za optimalnu wěstotu je img_auth.php znjemóžnjeny.',
 'upload_source_file' => ' (dataja na twojim ličaku)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Tuta specialna strona pokazuje wšě nahrate dataje.
-Jeli so po wužiwarju filtruje, pokazuja so jenož dataje, při kotrychž tón wužiwar je najnowšu wersiju nahrał.',
+'listfiles-summary' => 'Tuta specialna strona pokazuje wšě nahrate dataje.',
 'listfiles_search_for' => 'Za mjenom wobraza pytać:',
 'imgfile' => 'dataja',
 'listfiles' => 'Lisćina datajow',
@@ -1811,6 +1846,10 @@ Jeli so po wužiwarju filtruje, pokazuja so jenož dataje, při kotrychž tón w
 'listfiles_size' => 'wulkosć (byte)',
 'listfiles_description' => 'wopisanje',
 'listfiles_count' => 'Wersije',
+'listfiles-show-all' => 'Stare wersije wobrazow zapřijeć',
+'listfiles-latestversion' => 'Aktualna wersija',
+'listfiles-latestversion-yes' => 'Haj',
+'listfiles-latestversion-no' => 'Ně',
 
 # File description page
 'file-anchor-link' => 'Dataja',
@@ -1903,6 +1942,13 @@ Snano chceš wopisanje na jeje [$2 stronje datajoweho wopisanja] wobdźěłać.'
 'randompage' => 'Připadny nastawk',
 'randompage-nopages' => 'W {{PLURAL:$2|slědowacym mjenowym rumje|slědowacymaj mjenowymaj rumomaj|slědowacych mjenowych rumach|slědowacych mjenowych rumach}} žane strony njejsu: $1',
 
+# Random page in category
+'randomincategory' => 'Připadna strona w kategoriji',
+'randomincategory-invalidcategory' => '"$1" płaćiwe kategorijowe mjeno njeje.',
+'randomincategory-nopages' => 'W kategoriji [[:Category:$1|$1]] žane strony njejsu.',
+'randomincategory-selectcategory' => 'Připadna strona z kategorija: $1 $2',
+'randomincategory-selectcategory-submit' => 'Wotesłać',
+
 # Random redirect
 'randomredirect' => 'Připadne daleposrědkowanje',
 'randomredirect-nopages' => 'Žane daleposrědkowanja w mjenowym rumje "$1".',
@@ -1933,6 +1979,8 @@ Snano chceš wopisanje na jeje [$2 stronje datajoweho wopisanja] wobdźěłać.'
 'pageswithprop-text' => 'Tuta strona nalistuje strony, kotrež wěstu kajkosć strony wužiwaja.',
 'pageswithprop-prop' => 'Mjeno kajkosće:',
 'pageswithprop-submit' => 'Wotpósłać',
+'pageswithprop-prophidden-long' => 'Hódnota kajkosće dołheho teksta schowana ($1)',
+'pageswithprop-prophidden-binary' => 'binarna kajkostna hódnota schowana ($1)',
 
 'doubleredirects' => 'Dwójne daleposrědkowanja',
 'doubleredirectstext' => 'Tuta strona nalistuje strony, kotrež k druhim daleposrědkowanskim stronam dale posrědkuja.
@@ -1989,6 +2037,7 @@ Kóžda rjadka wobsahuje wotkazy k prěnjemu a druhemu daleposrědkowanju kaž t
 'mostrevisions' => 'Nastawki z najwjace wersijemi',
 'prefixindex' => 'Wšě strony z prefiksom',
 'prefixindex-namespace' => 'Wšě strony z prefiksom (mjenowy rum $1)',
+'prefixindex-strip' => 'Prefiks w lisćinje wotrězać',
 'shortpages' => 'Krótke nastawki',
 'longpages' => 'Dołhe nastawki',
 'deadendpages' => 'Nastawki bjez wotkazow',
@@ -2004,6 +2053,7 @@ Kóžda rjadka wobsahuje wotkazy k prěnjemu a druhemu daleposrědkowanju kaž t
 'listusers' => 'Lisćina wužiwarjow',
 'listusers-editsonly' => 'Jenož wužiwarjow ze změnami pokazać',
 'listusers-creationsort' => 'Po datumje wutworjenja sortěrować',
+'listusers-desc' => 'Po spadowacym porjedźe sortěrować',
 'usereditcount' => '$1 {{PLURAL:$1|změna|změnje|změny|změnow}}',
 'usercreated' => 'je so $1 $2 hodź. {{GENDER:$3|wutworił|wutworiła}}',
 'newpages' => 'Nowe strony',
@@ -2106,7 +2156,8 @@ Znajmjeńša hłowna domena je trěbna, na přikład "*.org".<br />
 # Special:ListGroupRights
 'listgrouprights' => 'Prawa wužiwarskeje skupiny',
 'listgrouprights-summary' => 'Slěduje lisćina wužiwarskich skupinow na tutej wikiju z jich wotpowědnymi přistupnymi prawami. Tu móžeš [[{{MediaWiki:Listgrouprights-helppage}}|dalše informacije]] wo jednotliwych prawach namakać.',
-'listgrouprights-key' => '* <span class="listgrouprights-granted">Garantowane prawo</span>
+'listgrouprights-key' => 'Legenda:
+* <span class="listgrouprights-granted">Garantowane prawo</span>
 * <span class="listgrouprights-revoked">Wotwołane prawo</span>',
 'listgrouprights-group' => 'Skupina',
 'listgrouprights-rights' => 'Prawa',
@@ -2220,7 +2271,7 @@ Staj so z wobdźěłarjom do zwiska:
 e-mejl: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Njebudu žane druhe zdźělenki w padźe dalšich změnow, chibazo wopytaš tutu stronu.
+Njebudu žane druhe zdźělenki w padźe dalšeje aktiwity, chibazo wopytaš tutu stronu. mjeztym zo sy přizjewjeny.
 Móžeš tež zdźělenske marki za wšě swoje wobkedźbowane strony we swojich wobkedźbowankach wróćo stajić.
 
 Twój přećelny zdźělenski system {{GRAMMAR:genitiw|{{SITENAME}}}}
@@ -2263,10 +2314,12 @@ Prošu potwjerdź, zo maš wotpohlad to činić, zo rozumiš sćěwki a zo to wo
 'deletecomment' => 'Přičina:',
 'deleteotherreason' => 'Druha/přidatna přičina:',
 'deletereasonotherlist' => 'Druha přičina',
-'deletereason-dropdown' => '*Zwučene přičiny za wušmórnjenje
+'deletereason-dropdown' => '* Zwučene přičiny za wušmórnjenje
+** Spam
+** Wandalizm
+** Přeńdźenje awtorskeho prawa
 ** Požadanje awtora
-** Zranjenje copyrighta
-** Wandalizm',
+** Defektne dalesposrědkowanje',
 'delete-edit-reasonlist' => 'Přičiny za wušmórnjenje wobdźěłać',
 'delete-toobig' => 'Tuta strona ma z wjace hač $1 {{PLURAL:$1|wersiju|wersijomaj|wersijemi|wersijemi}} wulke wobdźěłanske stawizny. Wušmórnjenje tajkich stronow bu wobmjezowane, zo by připadne přetorhnjenje {{SITENAME}} wobešło.',
 'delete-warning-toobig' => 'Tuta strona ma z wjace hač $1 {{PLURAL:$1|wersiju|wersijomaj|wersijemi|wersijemi}} wulke wobdźěłanske stawizny. Wušmórnjenje móže operacije datoweje banki {{SITENAME}} přetorhnyć; pokročuj z kedźbliwosću.',
@@ -2284,7 +2337,7 @@ Prošu potwjerdź, zo maš wotpohlad to činić, zo rozumiš sćěwki a zo to wo
 Poslednja změna bě wot wužiwarja [[User:$3|$3]] ([[User talk:$3|Diskusija]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Zjeće wobdźěłanja bě: \"''\$1''\".",
 'revertpage' => 'Změny [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskusija]]) cofnjene a nawróćene k poslednjej wersiji wužiwarja [[User:$1|$1]]',
-'revertpage-nouser' => 'Staji změny wot (wužiwarske mjeno wotstronjene) na předchadnu wersiju wot [[User:$1|$1]] wróćo',
+'revertpage-nouser' => 'Změny su so wot schowaneho wužiwarja anulowali a předchadna wersija wužiwarja {{GENDER:$1|[[User:$1|$1]]}} je so wobnowiła',
 'rollback-success' => 'Změny wužiwarja $1 cofnjene; wróćo na wersiju wužiwarja $2.',
 
 # Edit tokens
@@ -2418,7 +2471,7 @@ $1',
 'contributions' => 'Přinoški {{GENDER:$1|wužiwarja|wužiwarki}}',
 'contributions-title' => 'Wužiwarske přinoški wot „$1“',
 'mycontris' => 'Přinoški',
-'contribsub2' => 'za wužiwarja $1 ($2)',
+'contribsub2' => 'Za {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Žane změny, kotrež podatym kriterijam wotpowěduja.',
 'uctop' => '(aktualny)',
 'month' => 'wot měsaca (a do toho):',
@@ -2710,7 +2763,7 @@ W poslednim padźe móžeš tež wotkaz wužiwać, na př. „[[{{#Special:Expor
 'allmessagesname' => 'Mjeno',
 'allmessagesdefault' => 'Standardny tekst',
 'allmessagescurrent' => 'Aktualny tekst',
-'allmessagestext' => 'To je lisćina systemowych zdźělenkow, kotrež w mjenowym rumje MediaWiki k dispoziciji steja. Prošu wopytaj [//www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jeli chceš k powšitkownej lokalizaciji MediaWiki přinošować.',
+'allmessagestext' => 'To je lisćina systemowych zdźělenkow, kotrež w mjenowym rumje MediaWiki k dispoziciji steja. Prošu wopytaj [https://www.mediawiki.org/wiki/Localisation lokalizaciju MediaWiki] a [//translatewiki.net translatewiki.net], jeli chceš k powšitkownej lokalizaciji MediaWiki přinošować.',
 'allmessagesnotsupportedDB' => "Tuta strona njeda so wužiwać, dokelž '''\$wgUseDatabaseMessages''' bu znjemóžnjeny.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Po přiměrjenskim stawje filtrować:',
@@ -2869,6 +2922,7 @@ $2',
 'tooltip-undo' => 'anuluje tutu změnu a wočinja wobdźěłowanski formular w přehladowym modusu. Zmóžnja přičinu w zjeću přidać.',
 'tooltip-preferences-save' => 'Nastajenja składować',
 'tooltip-summary' => 'Zapodaj krótke zjeće',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* CSS w tutej dataji budźe so na wšěch stronow wuskutkować. */',
@@ -2901,6 +2955,8 @@ $2',
 'spam_reverting' => 'wróćo na poslednju wersiju, kotraž wotkazy na $1 njewobsahuje',
 'spam_blanking' => 'Wšě wersije z wotkazami do $1 so porjedźeja',
 'spam_deleting' => 'Wšě wersije z wotkazami do $1 so zhašeja',
+'simpleantispam-label' => "Kontrola přećiwo spamej.
+Tu '''NIČO''' njezapisać!",
 
 # Info page
 'pageinfo-title' => 'Informacije za stronu "$1"',
@@ -2914,13 +2970,14 @@ $2',
 'pageinfo-length' => 'Dołhosć strony (w bajtach)',
 'pageinfo-article-id' => 'ID strony',
 'pageinfo-language' => 'Rěč wobsaha strony',
-'pageinfo-robot-policy' => 'Status pytawy',
-'pageinfo-robot-index' => 'Indeksujomny',
-'pageinfo-robot-noindex' => 'Njeindeksujomny',
+'pageinfo-content-model' => 'Model wobsaha strony',
+'pageinfo-robot-policy' => 'Indicěrowanje přez roboty',
+'pageinfo-robot-index' => 'Dowoleny',
+'pageinfo-robot-noindex' => 'Zakazany',
 'pageinfo-views' => 'Ličba zwobraznjenjow',
 'pageinfo-watchers' => 'Ličba wobkedźbowarjow strony',
 'pageinfo-few-watchers' => 'Mjenje hač $1 {{PLURAL:$1|wobkedźbowar|wobkedźbowarjej|wobkedźbowarje|wobkedźbowarjow}}',
-'pageinfo-redirects-name' => 'Dalesposrědkowanja k tutej stronje',
+'pageinfo-redirects-name' => 'Ličba dalesposrědkowanjow k tutej stronje',
 'pageinfo-redirects-value' => '$1',
 'pageinfo-subpages-name' => 'Podstrony tuteje strony',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|dalesposrědkowanje|dalesposrědkowani|dalesposrědkowanja|dalesposrědkowanjow}}; $3 {{PLURAL:$3|njedalesposrědkowanje|njedalesposrědkowani|njedalesposrědkowanja|njedalesposrědkowanjow}})',
@@ -3000,7 +3057,7 @@ $1',
 'svg-long-desc' => 'SVG-dataja, zakładna wulkosć: $1 × $2 pikselow, datajowa wulkosć: $3',
 'svg-long-desc-animated' => 'Animěrowana SVG-dataja, zakładnej wotměraj $1 × $2 pikselow, datajowa wulkosć: $3',
 'svg-long-error' => 'Njepłaćiwa SVG-dataja: $1',
-'show-big-image' => 'Wersija z wyšim rozeznaćom',
+'show-big-image' => 'Originalna dataja',
 'show-big-image-preview' => 'Wulkosć tutoho přehlada: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Druhe rozeznaće|Druhej rozeznaći|Druhe rozeznaća|Druhe rozeznaća}}: $1.',
 'show-big-image-size' => '$1 × $2 pikselow',
@@ -3259,7 +3316,7 @@ Nasledne wotkazy na samsnej lince definuja wuwzaća, hdźež so wobraz smě naje
 'exif-compression-4' => 'CCITT skupina 4 faksowe kodowanje',
 
 'exif-copyrighted-true' => 'Přez awtorske prawo škitany',
-'exif-copyrighted-false' => 'Zjawnosći přistupny',
+'exif-copyrighted-false' => 'Status awtorskeho prawa njepostajeny',
 
 'exif-unknowndate' => 'Njeznaty datum',
 
@@ -3465,7 +3522,7 @@ Nasledne wotkazy na samsnej lince definuja wuwzaća, hdźež so wobraz smě naje
 
 # External editor support
 'edit-externally' => 'Dataju z eksternym programom wobdźěłać',
-'edit-externally-help' => '(Hlej [//www.mediawiki.org/wiki/Manual:External_editors pokiwy za instalaciju] za dalše informacije)',
+'edit-externally-help' => '(Hlej [https://www.mediawiki.org/wiki/Manual:External_editors pokiwy za instalaciju] za dalše informacije)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'wšě',
@@ -3515,7 +3572,7 @@ Tute wobkrućenski kod spadnje $4.',
 'confirmemail_body_set' => 'Něchtó, najskerje ty, wot IP-adresy $1,
 je e-mejlowu adresu konta "$2" na {{GRAMMAR:lokatiw|{{SITENAME}}}} na tutu adresu stajił.
 
-Zo by wobkrućił, zo tute konto ći woprawdźe słuša a zo bychu so e-mejlowe funkcije na {{GRAMMAR:lokatiw|{{SITENAME}}}} znowa aktiwizowali, wočiń tutón wotkaz w swojim wobhladowaku:
+Zo by wobkrućił, zo tute konto ći woprawdźe słuša a zo bychu so e-mejlowe funkcije na {{GRAMMAR:lokatiw|{{SITENAME}}}} aktiwizowali, wočiń tutón wotkaz w swojim wobhladowaku:
 
 $3
 
@@ -3553,6 +3610,9 @@ Prošu potwjerdź, zo chceš tutu stronu woprawdźe znowa wutworić.",
 'confirm-unwatch-button' => 'W porjadku',
 'confirm-unwatch-top' => 'Tutu stronu z wobkedźbowankow wotstronić?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '← předchadna strona',
 'imgmultipagenext' => 'přichodna strona →',
@@ -3644,8 +3704,9 @@ Móžeš tež [[Special:EditWatchlist|standardnu wobdźěłowansku stronu]] wuž
 'version-hook-subscribedby' => 'Abonowany wot',
 'version-version' => '(Wersija $1)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Tutón wiki so wot  '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2 podpěruje.",
+'version-poweredby-credits' => "Tutón wiki so wot  '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2 podpěruje.",
 'version-poweredby-others' => 'druzy',
+'version-poweredby-translators' => 'Přełožowarjo na translatewiki.net',
 'version-credits-summary' => 'Dźakujemy so slědowacym wosobam za jich přinoški k [[Special:Version|MediaWiki]]',
 'version-license-info' => 'MediaWiki je swobodna softwara: móžeš ju pod wuměnjenjemi licency GNU General Public License, wozjewjeneje wot załožby Free Software Foundation, rozdźělić a/abo změnić: pak pod wersiju 2 licency pak pod někajkej pozdźišej wersiju.
 
@@ -3662,7 +3723,8 @@ Ty měł [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licency GNU General Public Lic
 # Special:Redirect
 'redirect' => 'Po datajowym mjenje, wužiwarju abo wersijowym ID dale sposrědkować',
 'redirect-legend' => 'Do dataje abo strony dale sposrědkować',
-'redirect-summary' => 'Tuta specialna strona so do dataje (datajowe mjeno je podate), strony (wersijowy ID je podaty) abo wužiwarskeje strony (numeriski wužiwarski ID je podaty) dale sposrědkuje.',
+'redirect-summary' => 'Tuta specialna strona so do dataje (datajowe mjeno je podate), strony (wersijowy ID je podaty) abo wužiwarskeje strony (numeriski wužiwarski ID je podaty) dale sposrědkuje. Wužiće:
+[[{{#Special:Redirect}}/file/Přikład.jpg]], [[{{#Special:Redirect}}/revision/328429]] abo [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Los',
 'redirect-lookup' => 'Pytać:',
 'redirect-value' => 'Hódnota:',
@@ -3684,10 +3746,9 @@ Ty měł [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licency GNU General Public Lic
 
 # Special:SpecialPages
 'specialpages' => 'Specialne strony',
-'specialpages-note' => '----
-* Normalne specialne strony.
-* <span class="mw-specialpagerestricted">Specialne strony z wobmjezowanym přistupom.</span>
-* <span class="mw-specialpagecached">Specialne strony z pufrowaka (móža zestarjene być).</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Normalne specialne strony.
+* <span class="mw-specialpagerestricted">Specialne strony z wobmjezowanym přistupom.</span>',
 'specialpages-group-maintenance' => 'Hladanske lisćiny',
 'specialpages-group-other' => 'Druhe specialne strony',
 'specialpages-group-login' => 'Přizjewić/Konto załožić',
@@ -3719,12 +3780,16 @@ Ty měł [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licency GNU General Public Lic
 'tags' => 'Płaćiwe taflički změnow',
 'tag-filter' => 'Filter [[Special:Tags|tafličkow]]:',
 'tag-filter-submit' => 'Filter',
+'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Značka|Značce|Znački}}]]: $2)',
 'tags-title' => 'Taflički',
 'tags-intro' => 'Tuta strona nalistuje taflički, z kotrymiž softwara móže změnu markěrować a jich woznam.',
 'tags-tag' => 'Mjeno taflički',
 'tags-display-header' => 'Napohlad na lisćinach změnow',
 'tags-description-header' => 'Dospołne wopisanje woznama',
+'tags-active-header' => 'Aktiwny?',
 'tags-hitcount-header' => 'Změny z tafličkami',
+'tags-active-yes' => 'Haj',
+'tags-active-no' => 'Ně',
 'tags-edit' => 'změnić',
 'tags-hitcount' => '$1 {{PLURAL:$1|změna|změnje|změny|změnow}}',
 
@@ -3745,6 +3810,7 @@ Ty měł [{{SERVER}}{{SCRIPTPATH}}/COPYING kopiju licency GNU General Public Lic
 'dberr-problems' => 'Wodaj! Tute sydło ma techniske ćežkosće.',
 'dberr-again' => 'Počakń někotre mjeńšiny a zaktualizuj stronu.',
 'dberr-info' => '(Njeje móžno ze serwerom datoweje banki zwjazać: $1)',
+'dberr-info-hidden' => '(Kontakt z datobankowym serwerom móžno njeje)',
 'dberr-usegoogle' => 'Mjeztym móžeš z pomocu Google pytać.',
 'dberr-outofdate' => 'Wobkedźbuj, zo jich indeksy našeho wobsaha móhli zestarjene być.',
 'dberr-cachederror' => 'Slědowaca je pufrowana kopija požadaneje strony a móhła zestarjena być.',
@@ -3880,4 +3946,32 @@ Hewak móžeš slědowacy jednory formular wužiwać. Twój komentar přida so s
 # Image rotation
 'rotate-comment' => 'Wobraz wo $1 {{PLURAL:$1|stopjeń|stopnjej|stopnje|stopnjow}} w směrje časnika wjerćany',
 
+# Limit report
+'limitreport-title' => 'Profilowanske daty parsera:',
+'limitreport-cputime' => 'Časowe wužiwanje CPU',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|sekunda|sekundźe|sekundy|sekundow}}',
+'limitreport-walltime' => 'Wužiwanje woprawdźiteho časa',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekunda|sekundźe|sekundy|sekundow}}',
+'limitreport-ppvisitednodes' => 'Ličba wopytanych sukow preprocesora',
+'limitreport-ppgeneratednodes' => 'Spłodźena ličba sukow preprocesora',
+'limitreport-postexpandincludesize' => 'Wulkosć zapřijimanja po ekspandowanju',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bajt|bajtaj|bajty|bajtow}}',
+'limitreport-templateargumentsize' => 'Wulkosć předłohoweho argumenta',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bajt|bajtaj|bajty|bajtow}}',
+'limitreport-expansiondepth' => 'Najwyša ekspansijowa hłubokosć',
+'limitreport-expensivefunctioncount' => 'Ličba naročnych parserowych funkcijow',
+
+# Special:ExpandTemplates
+'expandtemplates' => 'Předłohi ekspandować',
+'expand_templates_intro' => 'Na tutej specialnej stronje móžeš tekst zapodać a wšitke do njeje zapřijate předłohi so rekursiwnje ekspanduja. Tež funkcije parsera kaž <code><nowiki>{{</nowiki>#language:...}}</code> a wariable kaž <code><nowiki>{{</nowiki>CURRENTDAY}}</code> so wuhódnočeja – faktisce wšo, štož steji mjezy dwójnymaj wopušatymaj spinkomaj.',
+'expand_templates_title' => 'Kontekstowy titul, za {{FULLPAGENAME}} atd.:',
+'expand_templates_input' => 'Tekst zapodać:',
+'expand_templates_output' => 'Wuslědk',
+'expand_templates_xml_output' => 'Wudaće XML',
+'expand_templates_ok' => 'W porjadku',
+'expand_templates_remove_comments' => 'Komentary wotstronić',
+'expand_templates_remove_nowiki' => 'Taflički <nowiki> we wuslědku potłóčić',
+'expand_templates_generate_xml' => 'Analyzowy štom XML pokazać',
+'expand_templates_preview' => 'Přehlad',
+
 );
index c07491d..2328f58 100644 (file)
@@ -48,7 +48,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'MovèTit' ),
        'Blankpage'                 => array( 'PajVid' ),
        'Block'                     => array( 'Bloke', 'BlokeIP', 'BlokeItilizatè' ),
-       'Blockme'                   => array( 'BlokeM' ),
        'Booksources'               => array( 'SousLiv' ),
        'BrokenRedirects'           => array( 'RedireksyonKase' ),
        'Categories'                => array( 'Kategori' ),
@@ -59,9 +58,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'KreyeKont' ),
        'Deadendpages'              => array( 'PajEnpas' ),
        'DeletedContributions'      => array( 'SiprimeKontribisyon' ),
-       'Disambiguations'           => array( 'Tokay' ),
        'DoubleRedirects'           => array( 'RedireksyonDoub' ),
        'Emailuser'                 => array( 'ImèlItilizatè' ),
+       'ExpandTemplates'           => array( 'EtannModèl' ),
        'Export'                    => array( 'Ekspòte' ),
        'Fewestrevisions'           => array( 'MwensRevizyon' ),
        'FileDuplicateSearch'       => array( 'ChacheFichyeDoub' ),
@@ -103,6 +102,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'PajPwoteje' ),
        'Protectedtitles'           => array( 'TitPwoteje' ),
        'Randompage'                => array( 'Oaza', 'PajOaza' ),
+       'RandomInCategory'          => array( 'OazaNanKategori' ),
        'Randomredirect'            => array( 'RedireksyonOaza' ),
        'Recentchanges'             => array( 'ChanjmanResan' ),
        'Recentchangeslinked'       => array( 'LyenChanjmanResan', 'ChanjmanAk' ),
@@ -396,8 +396,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Rekipere depi « $1 »',
 'youhavenewmessages' => 'Ou genyen $1 ($2).',
-'newmessageslink' => 'nouvo mesaj',
-'newmessagesdifflink' => 'dènye chanjman',
 'youhavenewmessagesmulti' => 'Ou genyen nouvo mesaj sou $1.',
 'editsection' => 'modifye',
 'editold' => 'modifye',
@@ -1340,7 +1338,7 @@ Nenpòt lòt lyen nan menm liy nan konsidere kòm yon eksèpsyon, i.e. paj kote
 
 # External editor support
 'edit-externally' => 'Modifye fichye sa a nan aplikasyon pa ou (ki pa nan sistèm an, sou machin ou pa egzanp).',
-'edit-externally-help' => '(Gade [//www.mediawiki.org/wiki/Manual:External_editors komand ak enstriksyon yo] pou plis enfòmasyon oubyen pou konnen plis)',
+'edit-externally-help' => '(Gade [https://www.mediawiki.org/wiki/Manual:External_editors komand ak enstriksyon yo] pou plis enfòmasyon oubyen pou konnen plis)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tout',
index 5ad847a..1550e04 100644 (file)
@@ -81,7 +81,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Hibás_címek' ),
        'Blankpage'                 => array( 'Üres_lap' ),
        'Block'                     => array( 'Blokkolás' ),
-       'Blockme'                   => array( 'Blokkolj' ),
        'Booksources'               => array( 'Könyvforrások' ),
        'BrokenRedirects'           => array( 'Nem_létező_lapra_mutató_átirányítások', 'Hibás_átirányítások' ),
        'Categories'                => array( 'Kategóriák' ),
@@ -92,10 +91,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Szerkesztői_fiók_létrehozása', 'Felhasználói_fiók_létrehozása' ),
        'Deadendpages'              => array( 'Zsákutcalapok' ),
        'DeletedContributions'      => array( 'Törölt_szerkesztések' ),
-       'Disambiguations'           => array( 'Egyértelműsítő_lapok' ),
        'DoubleRedirects'           => array( 'Kettős_átirányítások', 'Dupla_átirányítások' ),
        'EditWatchlist'             => array( 'Figyelőlista_szerkesztése' ),
        'Emailuser'                 => array( 'E-mail_küldése', 'E-mail_küldése_ezen_szerkesztőnek' ),
+       'ExpandTemplates'           => array( 'Sablonok_kibontása' ),
        'Export'                    => array( 'Lapok_exportálása' ),
        'Fewestrevisions'           => array( 'Legkevesebbet_szerkesztett_lapok' ),
        'FileDuplicateSearch'       => array( 'Duplikátumok_keresése' ),
@@ -588,8 +587,6 @@ További információkat a [[Special:Version|verzióinformációs lapon]] talál
 'ok' => 'OK',
 'retrievedfrom' => 'A lap eredeti címe: „$1”',
 'youhavenewmessages' => '$1 a vitalapodon! ($2 külön is megtekintheted.)',
-'newmessageslink' => 'új üzenet vár',
-'newmessagesdifflink' => 'az utolsó üzenetet',
 'youhavenewmessagesfromusers' => '$2 kaptál {{PLURAL:$3|egy|$3}} szerkesztőtől $1!',
 'youhavenewmessagesmanyusers' => '$2 kaptál több szerkesztőtől $1.',
 'newmessageslinkplural' => '{{PLURAL:$1||}}a vitalapodon',
@@ -1405,8 +1402,6 @@ Ezt általában egy elavult, törölt oldalra mutató laptörténeti hivatkozás
 'preferences' => 'Beállítások',
 'mypreferences' => 'Beállítások',
 'prefs-edits' => 'Szerkesztéseid száma:',
-'prefsnologin' => 'Nem jelentkeztél be',
-'prefsnologintext' => 'Saját beállításaid elmentéséhez <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} be kell jelentkezned.] </span>',
 'changepassword' => 'Jelszócsere',
 'prefs-skin' => 'Felület',
 'skin-preview' => 'előnézet',
@@ -1687,6 +1682,7 @@ A műveletet nem lehet visszavonni.',
 'recentchanges-label-minor' => 'Ez egy apró szerkesztés',
 'recentchanges-label-bot' => 'Ezt a szerkesztést egy bot hajtotta végre',
 'recentchanges-label-unpatrolled' => 'Ezt a szerkesztést még nem ellenőrizték',
+'recentchanges-legend-newpage' => '$1 – új lap',
 'rcnote' => "Alább az utolsó '''{{PLURAL:$2|egy|$2}}''' nap utolsó '''{{PLURAL:$1|egy|$1}}''' változtatása látható. A lap generálásának időpontja $4, $5.",
 'rcnotefrom' => 'Alább a <b>$2</b> óta történt változtatások láthatóak (<b>$1</b> db).',
 'rclistfrom' => '$1 után történt változtatások megtekintése',
@@ -2264,7 +2260,7 @@ Támogatott {{PLURAL:$2|protokoll|protokollok}}: <code>$1</code> (http:// az ala
 
 # Special:ActiveUsers
 'activeusers' => 'Aktív szerkesztők listája',
-'activeusers-intro' => 'Ez a lap azon felhasználók listáját tartalmazza, akik csináltak valamilyen tevékenységet az elmúlt {{PLURAL:$1|egy|$1}} napban.',
+'activeusers-intro' => 'Ez a lap azon felhasználók listáját tartalmazza, akik végeztek valamilyen tevékenységet az elmúlt {{PLURAL:$1|egy|$1}} napban.',
 'activeusers-count' => '$1 szerkesztés az utolsó $3 napban',
 'activeusers-from' => 'Szerkesztők listázása a következő névtől kezdve:',
 'activeusers-hidebots' => 'Botok elrejtése',
@@ -2297,7 +2293,7 @@ Az egyes csoportokról további információt [[{{MediaWiki:Listgrouprights-help
 'emailuser-title-target' => 'E-mail küldése ennek a felhasználónak: $1',
 'emailuser-title-notarget' => 'E-mail küldése a felhasználónak',
 'emailpage' => 'E-mail küldése',
-'emailpagetext' => '{{GENDER:$1|user}} nevű szerkesztő e-mail-címére ezen űrlap kitöltésével üzenetet tudsz küldeni.
+'emailpagetext' => '{{GENDER:$1|felhasználó}}nevű szerkesztő e-mail-címére ezen űrlap kitöltésével üzenetet tudsz küldeni.
 Feladóként a [[Special:Preferences|beállításaid]]nál megadott e-mail-címed fog szerepelni, így a címzett közvetlenül tud majd válaszolni neked.',
 'usermailererror' => 'A levélküldő objektum hibával tért vissza:',
 'defemailsubject' => '{{SITENAME}} e-mail a következő felhasználótól: „$1”',
@@ -2317,10 +2313,10 @@ Feladóként a [[Special:Preferences|beállításaid]]nál megadott e-mail-címe
 'emailsubject' => 'Tárgy:',
 'emailmessage' => 'Üzenet:',
 'emailsend' => 'Küldés',
-'emailccme' => 'Az üzenet másolatát küldje el nekem is e-mailben.',
+'emailccme' => 'Az üzenet másolatát küldje el nekem is e-mailben',
 'emailccsubject' => '$1 szerkesztőnek küldött $2 tárgyú üzenet másolata',
 'emailsent' => 'E-mail elküldve',
-'emailsenttext' => 'Az e-mail üzenetedet elküldtem.',
+'emailsenttext' => 'E-mail üzenetedet elküldtük.',
 'emailuserfooter' => 'Ezt az e-mailt $1 küldte $2 számára, az „E-mail küldése ezen szerkesztőnek” funkció használatával a(z) {{SITENAME}} wikin.',
 
 # User Messenger
@@ -2905,7 +2901,7 @@ Az utóbbi esetben közvetlen hivatkozást is használhatsz, például a [[{{#Sp
 'allmessagesdefault' => 'Alapértelmezett szöveg',
 'allmessagescurrent' => 'Jelenlegi szöveg',
 'allmessagestext' => 'Ezen a lapon a MediaWiki-névtérben elérhető rendszerüzenetek listája látható.
-Ha részt szeretnél venni a MediaWiki fordításában, látogass el a [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation], valamint a [//translatewiki.net translatewiki.net] oldalra.',
+Ha részt szeretnél venni a MediaWiki fordításában, látogass el a [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], valamint a [//translatewiki.net translatewiki.net] oldalra.',
 'allmessagesnotsupportedDB' => "A '''''{{ns:special}}:Allmessages''''' lap nem használható, mert a '''\$wgUseDatabaseMessages''' ki van kapcsolva.",
 'allmessages-filter-legend' => 'Elemek szűrése',
 'allmessages-filter' => 'Módosítás állapota:',
@@ -3113,6 +3109,8 @@ Ez valószínűleg egy olyan link miatt van, ami egy feketelistán lévő oldalr
 'spam_reverting' => 'Visszatérés a $1 lapra mutató hivatkozásokat nem tartalmazó utolsó változathoz',
 'spam_blanking' => 'Az összes változat tartalmazott a $1 lapra mutató hivatkozásokat, kiürítés',
 'spam_deleting' => 'Minden változat tartalmazott $1-re mutató hivatkozást, törlöm',
+'simpleantispam-label' => "Spam elleni ellenőrzés.
+'''NE''' töltsd ezt ki!",
 
 # Info page
 'pageinfo-title' => 'Információk a(z) „$1” lapról',
@@ -3663,7 +3661,7 @@ míg a többi elem a táblázat összecsukása után alapértelmezett esetben re
 
 # External editor support
 'edit-externally' => 'A fájl szerkesztése külső alkalmazással',
-'edit-externally-help' => '(Lásd a [//www.mediawiki.org/wiki/Manual:External_editors használati utasítást] (angolul) a beállításához.)',
+'edit-externally-help' => '(Lásd a [https://www.mediawiki.org/wiki/Manual:External_editors használati utasítást] (angolul) a beállításához.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'bármikor',
@@ -3846,7 +3844,7 @@ minden egyes sor egy figyelt lap címe. Ha kész vagy, kattints a lista alatt ta
 'version-hook-subscribedby' => 'Használja',
 'version-version' => '(verzió: $1)',
 'version-license' => 'Licenc',
-'version-poweredby-credits' => "Ez a wiki '''[//www.mediawiki.org/ MediaWiki]''' szoftverrel működik, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ez a wiki '''[https://www.mediawiki.org/ MediaWiki]''' szoftverrel működik, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'mások',
 'version-poweredby-translators' => 'translatewiki.net fordítók',
 'version-credits-summary' => 'Szeretnénk elismerni a következő személyek hozzájárulását a [[Special:Version|MediaWiki]] szoftverhez.',
@@ -3875,8 +3873,7 @@ A MediaWikit abban a reményben terjesztjük, hogy hasznos lesz, de GARANCIA NÉ
 
 # Special:SpecialPages
 'specialpages' => 'Speciális lapok',
-'specialpages-note' => '----
-* Mindenki számára elérhető speciális lapok.
+'specialpages-note' => '* Mindenki számára elérhető speciális lapok.
 * <span class="mw-specialpagerestricted">Korlátozott hozzáférésű speciális lapok.</span>',
 'specialpages-group-maintenance' => 'Állapotjelentések',
 'specialpages-group-other' => 'További speciális lapok',
@@ -4068,4 +4065,18 @@ A MediaWikit abban a reményben terjesztjük, hogy hasznos lesz, de GARANCIA NÉ
 # Image rotation
 'rotate-comment' => 'Elforgattam a képet $1 fokkal, az óramutató járásával megegyező irányban',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Sablonok kibontása',
+'expand_templates_intro' => 'Ez a speciális lap a bevitt szövegekben megkeresi a sablonokat és rekurzívan kibontja őket.
+Kibontja az elemző függvényeket (pl. <nowiki>{{</nowiki>#language:...}}), és a változókat (pl. <nowiki>{{</nowiki>CURRENTDAY}}) is – mindent, ami a kettős kapcsos zárójelek között van.',
+'expand_templates_title' => 'Szöveg címe, például {{FULLPAGENAME}} sablonhoz:',
+'expand_templates_input' => 'Vizsgálandó szöveg',
+'expand_templates_output' => 'Eredmény',
+'expand_templates_xml_output' => 'XML kimenet',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Megjegyzések eltávolítása',
+'expand_templates_remove_nowiki' => '<nowiki> tagek mellőzése az eredményben',
+'expand_templates_generate_xml' => 'XML elemzési fa mutatása',
+'expand_templates_preview' => 'Előnézet',
+
 );
index aa7b289..47f7404 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Ahmed-Najib-Biabani-Ibrahimkhel
  * @author Chaojoker
+ * @author M hamlet
  * @author Nemo bis
  * @author Pandukht
  * @author Reedy
@@ -205,14 +206,12 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Բոլորէջերը' ),
        'Ancientpages'              => array( 'Ամենահինէջերը' ),
        'Block'                     => array( 'Արգելափակել այփին' ),
-       'Blockme'                   => array( 'Արգելափակել' ),
        'Booksources'               => array( 'Գրքայինաղբյուրները' ),
        'BrokenRedirects'           => array( 'Կոտրվածվերահղումները' ),
        'Categories'                => array( 'Կատեգորիաները' ),
        'ChangePassword'            => array( 'Նորգաղտնաբառ' ),
        'Contributions'             => array( 'Ներդրումները' ),
        'Deadendpages'              => array( 'Հղումչպարունակողէջերը' ),
-       'Disambiguations'           => array( 'Երկիմաստէջերը' ),
        'DoubleRedirects'           => array( 'Կրկնակիվերահղումները' ),
        'Emailuser'                 => array( 'Գրելնամակ' ),
        'Export'                    => array( 'Արտահանելէջերը' ),
@@ -284,16 +283,16 @@ $messages = array(
 'tog-extendwatchlist' => 'Ընդարձակել հսկացանկը՝ ցույց տալով բոլոր փոփոխությունները, այլ ոչ միայն վերջինները',
 'tog-usenewrc' => 'Խմբավորել փոփոխությունները Վերջին փոփոխություններում և հսկացանկում (պահանջում է JavaScript)',
 'tog-numberheadings' => 'Ինքնաթվագրել վերնագրերը',
-'tog-showtoolbar' => 'Ցույց տալ խմբագրումների գործիքների վահանակը (JavaScript)',
-'tog-editondblclick' => 'Խմբագրել էջերը կրկնակի մատնահարմամբ (JavaScript)',
+'tog-showtoolbar' => 'Ցույց տալ խմբագրումների գործիքների վահանակը',
+'tog-editondblclick' => 'Խմբագրել էջերը կրկնակի մատնահարմամբ',
 'tog-editsection' => 'Ցույց տալ [խմբագրել] հղումը ամեն բաժնի համար',
-'tog-editsectiononrightclick' => 'Խմբագրել բաժինները վերնագրի աջ մատնահարմամբ (JavaScript)',
+'tog-editsectiononrightclick' => 'Խմբագրել բաժինները վերնագրի աջ մատնահարմամբ',
 'tog-showtoc' => 'Ցույց տալ բովանդակությունը (3  կամ ավել վերնագրեր ունեցող էջերի համար)',
 'tog-rememberpassword' => 'Հիշել իմ մուտքագրված տվյալներն այս համակարգչում ($1 {{PLURAL:$1|օրից}} ոչ ավել ժամկետով)',
 'tog-watchcreations' => 'Ավելացնել իմ ստեղծած էջերը և բեռնած նիշքերը հսկացանկին',
 'tog-watchdefault' => 'Ավելացնել իմ խմբագրած էջերը և նիշքերը հսկացանկին',
 'tog-watchmoves' => 'Ավելացնել իմ վերնավանած էջերը և նիշքերը հսկացանկին',
-'tog-watchdeletion' => 'Ավելացնել իմ ջնջած էջերը հսկացանկին',
+'tog-watchdeletion' => 'Ավելացնել իմ ջնջած էջերը և նիշքերը իմ հսկացանկին',
 'tog-minordefault' => 'Նշել խմբագրումները որպես չնչին ըստ լռության',
 'tog-previewontop' => 'Ցույց տալ նախադիտումը խմբագրման դաշտից առաջ',
 'tog-previewonfirst' => 'Նախադիտել մինչև առաջին խմբագրությունը',
@@ -418,6 +417,7 @@ $messages = array(
 'newwindow' => '(բացվելու է նոր պատուհանի մեջ)',
 'cancel' => 'Բեկանել',
 'moredotdotdot' => 'Ավելին...',
+'morenotlisted' => 'Այս ցանկը լիարժեք չէ։',
 'mypage' => 'Իմ էջը',
 'mytalk' => 'Քննարկում',
 'anontalk' => 'Քննարկում այս IP-հասցեի համար',
@@ -473,6 +473,7 @@ $messages = array(
 'create-this-page' => 'Ստեղծել այս էջը',
 'delete' => 'Ջնջել',
 'deletethispage' => 'Ջնջել այս էջը',
+'undeletethispage' => 'Վերականգնել այս էջը',
 'undelete_short' => 'Վերականգնել {{PLURAL:$1|մեկ խմբագրում|$1 խմբագրում}}',
 'viewdeleted_short' => 'Դիտել {{PLURAL:$1|ջնջված խմբագրում}}',
 'protect' => 'Պաշտպանել',
@@ -544,14 +545,13 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Ստացված է «$1» էջից',
 'youhavenewmessages' => 'Դուք ունեք $1 ($2)։',
-'newmessageslink' => 'Նոր հաղորդագրություն',
-'newmessagesdifflink' => 'վերջին փոփոխությունը',
-'newmessageslinkplural' => '{{PLURAL:$1|նոր հաղորդագրություն|նոր հաղորդագրություններ}}',
-'newmessagesdifflinkplural' => '$1 {{PLURAL:$1|փոփոխում|փոփոխումներ}}',
+'youhavenewmessagesmanyusers' => 'Դուք ունեք $1 մի քանի օգտագործողից ($2)։',
+'newmessageslinkplural' => '{{PLURAL:$1|նոր հաղորդագրություն|999=նոր հաղորդագրություններ}}',
+'newmessagesdifflinkplural' => 'վերջին {{PLURAL:$1|փոփոխում|999=փոփոխումներ}}',
 'youhavenewmessagesmulti' => 'Դուք նոր ուղերձներ եք ստացել $1 վրա',
 'editsection' => 'խմբագրել',
 'editold' => 'խմբագրել',
-'viewsourceold' => 'Õ¤Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö\84Õ«Õ¯Õ¸Õ¤Õ¥Ö\80Õ¨',
+'viewsourceold' => 'դիտել վիքիկոդը',
 'editlink' => 'խմբագրել',
 'viewsourcelink' => 'դիտել ելատեքստը',
 'editsectionhint' => 'Խմբագրել բաժինը. $1',
@@ -600,6 +600,12 @@ $1',
 # General errors
 'error' => 'Սխալ',
 'databaseerror' => 'Տվյալների բազայի սխալ',
+'databaseerror-text' => 'Տվյալների բազայի հարցման սխալ է առաջացել։
+Սա կարող է ծրագրային բագի պատճառով լինել։',
+'databaseerror-textcl' => 'Տվյալների բազայի հարցման սխալ է առաջացել։',
+'databaseerror-query' => 'Հարցում՝ $1',
+'databaseerror-function' => 'Ֆունկցիա՝ $1',
+'databaseerror-error' => 'Սխալ՝ $1',
 'laggedslavemode' => 'Զգուշացում. էջը կարող է չպարունակել վերջին փոփոխությունները։',
 'readonly' => 'Տվյալների բազան կողպված է',
 'enterlockreason' => 'Նշեք կողպման պատճառը և մոտավոր ժամկետը',
@@ -639,7 +645,7 @@ $1',
 'wrong_wfQuery_params' => 'Անթույլատրելի պարամետրեր wfQuery() ֆունկցիայի համար<br />
 Ֆունկցիա՝ $1<br />
 Հայցում՝ $2',
-'viewsource' => 'Ô´Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö\84Õ«Õ¯Õ¸Õ¤Õ¥Ö\80Õ¨',
+'viewsource' => 'Դիտել վիքիկոդը',
 'viewsource-title' => 'Դիտել $1 էջի աղբյուրը',
 'actionthrottled' => 'Գործողությունը արգելափակվեց',
 'actionthrottledtext' => 'Որպես հակա-սպամային միջոց, այս գործողության չափից շատ կատարումը կարճ ժամանակահատվածի ընթացքում սահմանափակված է։ Խնդրում ենք փորձել կրկին մի քանի րոպե անց։',
@@ -656,11 +662,14 @@ $2',
 'namespaceprotected' => 'Դուք չունեք «$1» անվանատարածքի էջերի խմբագրման իրավունք։',
 'customcssprotected' => 'Դուք չեք կարող խմբագրել այս CSS էջը, քանի որ այն պարունակում է այլ մասնակցի անձնական նախընտրանքներ։',
 'customjsprotected' => 'Դուք չեք կարող խմբագրել այս ՋավաՍկրիպտ էջը, քանի որ այն պարունակում է այլ մասնակցի անձնական նախընտրանքներ։',
+'mycustomcssprotected' => 'Դուք բավարար իրավունքներ չունեք այս CSS էջը խմբագրելու համար։',
+'mycustomjsprotected' => 'Դուք բավարար իրավունքներ չունեք այս JavaScript էջը խմբագրելու համար։',
+'mypreferencesprotected' => 'Դուք բավարար իրավունքներ չունեք Ձեր նախընտրությունները խմբագրելու համար։',
 'ns-specialprotected' => '«{{ns:special}}» անվանատարածքի էջերը չեն կարող խմբագրվել։',
 'titleprotected' => "Այս անվանմամբ էջի ստեղծումը արգելվել է [[User:$1|$1]] մասնակցի կողմից։
 Տրված պատճառն է՝ ''$2''։",
 'exception-nologin' => 'Չեք մտել համակարգ',
-'exception-nologin-text' => 'Ô±ÕµÕ½ Õ§Õ»Õ¨ Õ¤Õ«Õ¿Õ¥Õ¬Õ¸Ö\82 Õ¯Õ¡Õ´ Õ£Õ¸Ö\80Õ®Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶ Õ¯Õ¡Õ¿Õ¡Ö\80Õ¥Õ¬Õ¸Ö\82 Õ°Õ¡Õ´Õ¡Ö\80 Õ¤Õ¸Ö\82Ö\84 ÕºÕ¥Õ¿Ö\84 Õ§ Õ´Õ¸Ö\82Õ¿Ö\84 Õ£Õ¸Ö\80Õ®Õ¥Ö\84 Õ¡ÕµÕ½ Õ¾Õ«Ö\84Õ«։',
+'exception-nologin-text' => 'Ô½Õ¶Õ¤Ö\80Õ¸Ö\82Õ´ Õ¥Õ¶Ö\84, [[Special:Userlogin|Õ´Õ¸Ö\82Õ¿Ö\84 Õ£Õ¸Ö\80Õ®Õ¥Ö\84]]Õ\9d Õ¡ÕµÕ½ Õ§Õ»Õ¨ Õ¤Õ«Õ¿Õ¥Õ¬Õ¸Ö\82 Õ¯Õ¡Õ´ Õ£Õ¸Ö\80Õ®Õ¸Õ²Õ¸Ö\82Õ©ÕµÕ¸Ö\82Õ¶Õ¨ Õ¯Õ¡Õ¿Õ¡Ö\80Õ¥Õ¬Õ¸Ö\82 Õ°Õ¡Õ´Õ¡Ö\80։',
 
 # Virus scanner
 'virus-badscanner' => "Սխալ կարգավորւմ։ Անծանոթ վիրուսների զննիչ. ''$1''",
@@ -677,6 +686,7 @@ $2',
 'yourname' => 'Մասնակցի անուն՝',
 'userlogin-yourname' => 'Մասնակցային անուն',
 'userlogin-yourname-ph' => 'Մուտքագրեք ձեր մասնակցային անունը',
+'createacct-another-username-ph' => 'Մուտքագրեք մասնակցի անունը',
 'yourpassword' => 'Գաղտնաբառ՝',
 'userlogin-yourpassword' => 'Գաղտնաբառ',
 'userlogin-yourpassword-ph' => 'Մուտքագրեք ձեր գաղտնաբառը',
@@ -706,11 +716,13 @@ $2',
 'gotaccount' => "Դուք արդեն գրանցվա՞ծ եք։ '''$1'''։",
 'gotaccountlink' => 'Մուտք գործեք համակարգ',
 'userlogin-resetlink' => 'Մոռացե՞լ եք Ձեր հաշվի տվյալները։',
-'userlogin-resetpassword-link' => 'Զրոյացնել ձեր գաղտնաբառը։',
+'userlogin-resetpassword-link' => 'Մոռացե՞լ եք գաղտնաբառը',
+'userlogin-createanother' => 'Ստեղծել այլ հաշիվ',
 'createacct-join' => 'Մուտքագրեք Ձեր տեղեկությունները ստորև',
 'createacct-emailrequired' => 'Էլ–փոստի հասցե',
 'createacct-emailoptional' => 'Էլ–փոստի հասցե (ոչ պարտադիր)',
 'createacct-email-ph' => 'Մուտքագրեք ձեր էլ–փոստի հասցեն',
+'createacct-another-email-ph' => 'Մուտքագրեք էլ․ փոստի հասցեն',
 'createaccountmail' => 'Օգտագործել ժամանակավոր պատահական գաղտնաբառ, որը կուղարկվի ձեր էլ–փոստի հասցեին։',
 'createacct-realname' => 'Իրական անուն (պարտադիր չէ)',
 'createaccountreason' => 'Պատճառը՝',
@@ -1217,12 +1229,12 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'preferences' => 'Նախընտրություններ',
 'mypreferences' => 'Նախընտրություններ',
 'prefs-edits' => 'Խմբագրումների քանակը.',
-'prefsnologin' => 'Դուք չեք մտել համակարգ',
-'prefsnologintext' => 'Մասնակցային նախընտրությունները փոփոխելու համար անհրաժեշտ է <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} մտնել համակարգ]</span>։',
+'prefsnologintext2' => 'Նախընտրությունները փոփոխելու համար անհրաժեշտ է $1։',
 'changepassword' => 'Փոխել գաղտնաբառը',
 'prefs-skin' => 'Տեսք',
 'skin-preview' => 'նախադիտել',
 'datedefault' => 'Առանց նախընտրության',
+'prefs-beta' => 'Փորձնական հնարավորություններ',
 'prefs-datetime' => 'Օր ու ժամ',
 'prefs-personal' => 'Անձնական',
 'prefs-rc' => 'Վերջին փոփոխություններ',
@@ -1371,6 +1383,7 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'right-upload' => 'Նիշքերի բեռնում',
 'right-upload_by_url' => 'Բեռնել նիշքեր ինտերնետային հասցեից',
 'right-delete' => 'Էջերի ջնջում',
+'right-rollback' => 'Արագ հետ գլորել տվյալ էջը վերջին անգամ խմբագրած մասնակցի խմբագրումները',
 
 # Special:Log/newusers
 'newuserlogpage' => 'Մասնակիցների գրանցման տեղեկամատյան',
@@ -1390,6 +1403,7 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'action-delete' => 'Ջնջել այս էջը',
 'action-deleterevision' => 'Ջնջել այս փոփոխությունը',
 'action-deletedhistory' => 'Դիտել այս էջի ջնջված պատմությունը',
+'action-rollback' => 'արագ հետ գլորել էջը վերջին անգամ խմբագրած մասնակցի կատարած փոփոխությունները',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|փոփոխություն|փոփոխություն}}',
@@ -1401,6 +1415,7 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'recentchanges-label-minor' => 'Սա չնչին խմբագրում է',
 'recentchanges-label-bot' => 'Այս խմբագրումը կատարվել է բոտի կողմից',
 'recentchanges-label-unpatrolled' => 'Այս խմբագրումը դեռ չի պարեկվել',
+'recentchanges-legend-newpage' => '$1 - նոր էջ',
 'rcnote' => 'Ստորև բերված են վերջին <strong>$1</strong> փոփոխությունները վերջին <strong>$2</strong> {{PLURAL:$2|օրվա|օրվա}} ընթացքում՝ $5, $4-ի դրությամբ։',
 'rcnotefrom' => "Ստորև բերված են փոփոխությունները սկսած՝ '''$2''' (մինչև՝ '''$1''')։",
 'rclistfrom' => 'Ցույց տալ նոր փոփոխությունները սկսած $1',
@@ -1905,11 +1920,12 @@ $NEWPAGE
 'rollback' => 'Հետ գլորել խմբագրումները',
 'rollback_short' => 'Հետ գլորել',
 'rollbacklink' => 'հետ գլորել',
+'rollbacklinkcount' => 'հետ գլորել $1 {{PLURAL:$1|խմբագրում}}',
 'rollbackfailed' => 'Հետ գլորումը ձախողվեց',
 'cantrollback' => 'Չհաջողվեց հետ շրջել խմբագրումը։ Վերջին ներդրումը կատարվել է էջի միակ հեղինակի կողմից։',
-'alreadyrolled' => 'Õ\89Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö\81 Õ°Õ¥Õ¿ Õ£Õ¬Õ¸Ö\80Õ¥Õ¬ [[:$1]] Õ§Õ»Õ« Õ¾Õ¥Ö\80Õ»Õ«Õ¶ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ¶Õ¥Ö\80Õ¨Õ\9d Õ¯Õ¡Õ¿Õ¡Ö\80Õ¾Õ¡Õ® [[User:$2|$2]] ([[User talk:$2|Õ\94Õ¶Õ¶Õ¡Ö\80Õ¯Õ¸Ö\82Õ´]]) Õ´Õ¡Õ½Õ¶Õ¡Õ¯Ö\81Õ« Õ¯Õ¸Õ²Õ´Õ«Ö\81Ö\89 Õ\84Õ¥Õ¯ Õ¸Ö\82Ö\80Õ«Õ·Õ¨ Õ¡Ö\80Õ¤Õ¥Õ¶ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¥Õ¬ Õ§ Õ¯Õ¡Õ´ Õ°Õ¥Õ¿ Õ§ Õ£Õ¬Õ¸Ö\80Õ¥Õ¬ էջը։
+'alreadyrolled' => 'Õ\89Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö\81 Õ°Õ¥Õ¿ Õ£Õ¬Õ¸Ö\80Õ¥Õ¬ [[:$1]] Õ§Õ»Õ¸Ö\82Õ´ [[User:$2|$2]] ([[User talk:$2|Õ\94Õ¶Õ¶Õ¡Ö\80Õ¯Õ¸Ö\82Õ´]]) Õ´Õ¡Õ½Õ¶Õ¡Õ¯Ö\81Õ« Õ¾Õ¥Ö\80Õ»Õ«Õ¶ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ¶Õ¥Ö\80Õ¨â\80¤ Õ´Õ¥Õ¯ Õ¸Ö\82Ö\80Õ«Õ·Õ¶ Õ¡Ö\80Õ¤Õ¥Õ¶ Õ°Õ¥Õ¿ Õ§ Õ£Õ¬Õ¸Ö\80Õ¥Õ¬ Õ¯Õ¡Õ´ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¥Õ¬ Õ§ էջը։
 
\8eÕ¥Ö\80Õ»Õ«Õ¶ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ¨ Õ¯Õ¡Õ¿Õ¡Ö\80Õ¾Õ¥Õ¬ Õ§ [[User:$3|$3]] ([[User talk:$3|Õ\94Õ¶Õ¶Õ¡Ö\80Õ¯Õ¸Ö\82Õ´]]) Õ´Õ¡Õ½Õ¶Õ¡Õ¯Ö\81Õ« Õ¯Õ¸Õ²Õ´Õ«Ö\81։',
\8eÕ¥Ö\80Õ»Õ«Õ¶ Õ­Õ´Õ¢Õ¡Õ£Ö\80Õ¸Ö\82Õ´Õ¨ Õ¯Õ¡Õ¿Õ¡Ö\80Õ¥Õ¬ Õ§ [[User:$3|$3]] ([[User talk:$3|Õ\94Õ¶Õ¶Õ¡Ö\80Õ¯Õ¸Ö\82Õ´]]) Õ´Õ¡Õ½Õ¶Õ¡Õ¯Õ«Ö\81Õ¨։',
 'editcomment' => "Խմբագրման մեկնաբանումն էր. «''$1''»։",
 'revertpage' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|քննարկում]]) մասնակցի խմբագրումները հետ են շրջվել [[User:$1|$1]] մասնակցի վերջին տարբերակին։',
 'revertpage-nouser' => 'Հետ շրջվեց (անունը ջնջված է) մասնակցի խմբագրումը՝ [[User:$1|$1]] մասնակցի տարբերակին',
@@ -2269,7 +2285,7 @@ $1',
 'allmessagesdefault' => 'Ուղերձի լռելյայն տեքստ',
 'allmessagescurrent' => 'Ընթացիկ տեքստ',
 'allmessagestext' => 'Ստորև բերված է «MediaWiki» անվանատարածքի բոլոր համակարգային ուղերձների ցանկը։
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "Այս էջը չի գործում, քանի որ '''\$wgUseDatabaseMessages''' հատկանիշը անջատված է։",
 'allmessages-filter-all' => 'Բոլորը',
 'allmessages-language' => 'Լեզու',
@@ -2563,7 +2579,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Խմբագրել այս նիշքը արտաքին խմբագրիչով',
-'edit-externally-help' => '(Մանրամասնությունների համար տես [//www.mediawiki.org/wiki/Manual:External_editors տեղակայման հրահանգները])',
+'edit-externally-help' => '(Մանրամասնությունների համար տես [https://www.mediawiki.org/wiki/Manual:External_editors տեղակայման հրահանգները])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'բոլոր',
@@ -2689,6 +2705,7 @@ $3
 
 # Special:Version
 'version' => 'ՄեդիաՎիքի տարբերակը',
+'version-poweredby-credits' => "Այս վիքին աշխատում է '''[https://www.mediawiki.org/ MediaWiki]'''֊ով, copyright © 2001-$1 $2։",
 
 # Special:FileDuplicateSearch
 'fileduplicatesearch' => 'Փնտրել կրկնօրինակ պատկերներ',
@@ -2703,9 +2720,8 @@ $3
 
 # Special:SpecialPages
 'specialpages' => 'Սպասարկող էջեր',
-'specialpages-note' => '----
-* Հասարակ հատուկ էջեր։
-* <strong class="mw-specialpagerestricted">Սահմանափակված հատուկ էջեր։</strong>',
+'specialpages-note' => '* Հասարակ հատուկ էջեր։
+* <span class="mw-specialpagerestricted">Սահմանափակված հատուկ էջեր։</span>',
 'specialpages-group-maintenance' => 'Տեխնիկական սպասարկման տեղեկատուներ',
 'specialpages-group-other' => 'Այլ հատուկ էջեր',
 'specialpages-group-login' => 'Մտնել / Գրանցվել',
@@ -2790,4 +2806,7 @@ $3
 'duration-centuries' => '$1 {{PLURAL:$1|դար}}',
 'duration-millennia' => '$1 {{PLURAL:$1|հազարամյակ}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Կաղապարների ընդարձակում',
+
 );
index 438d9a7..265e46f 100644 (file)
@@ -14,6 +14,7 @@
  * @author McDutchie
  * @author Nemo bis
  * @author Reedy
+ * @author Shirayuki
  * @author Yfdyh000
  * @author לערי ריינהארט
  */
@@ -52,7 +53,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Titulo_invalide' ),
        'Blankpage'                 => array( 'Pagina_vacue' ),
        'Block'                     => array( 'Blocar', 'Blocar_IP', 'Blocar_usator' ),
-       'Blockme'                   => array( 'Blocar_me' ),
        'Booksources'               => array( 'Fontes_de_libros' ),
        'BrokenRedirects'           => array( 'Redirectiones_rupte' ),
        'Categories'                => array( 'Categorias' ),
@@ -64,10 +64,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crear_conto' ),
        'Deadendpages'              => array( 'Paginas_sin_exito' ),
        'DeletedContributions'      => array( 'Contributiones_delite' ),
-       'Disambiguations'           => array( 'Disambiguationes' ),
        'DoubleRedirects'           => array( 'Redirectiones_duple' ),
        'EditWatchlist'             => array( 'Modificar_observatorio' ),
        'Emailuser'                 => array( 'Inviar_e-mail_a_un_usator' ),
+       'ExpandTemplates'           => array( 'Expander_patronos' ),
        'Export'                    => array( 'Exportar' ),
        'Fewestrevisions'           => array( 'Le_minus_versiones' ),
        'FileDuplicateSearch'       => array( 'Recerca_de_files_duplice' ),
@@ -109,6 +109,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Paginas_protegite' ),
        'Protectedtitles'           => array( 'Titulos_protegite' ),
        'Randompage'                => array( 'Aleatori', 'Pagina_aleatori' ),
+       'RandomInCategory'          => array( 'Aleatori_in_categoria' ),
        'Randomredirect'            => array( 'Redirection_aleatori' ),
        'Recentchanges'             => array( 'Modificationes_recente' ),
        'Recentchangeslinked'       => array( 'Modificationes_recente_ligate', 'Modificationes_connexe' ),
@@ -418,12 +419,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Obtenite de "$1"',
 'youhavenewmessages' => 'Tu ha $1 ($2).',
-'newmessageslink' => 'nove messages',
-'newmessagesdifflink' => 'ultime modification',
 'youhavenewmessagesfromusers' => 'Tu ha $1 de {{PLURAL:$3|un altere usator|$3 usatores}} ($2).',
 'youhavenewmessagesmanyusers' => 'Tu ha $1 de multe usatores ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un nove message|$1 nove messages}}',
-'newmessagesdifflinkplural' => 'ultime {{PLURAL:$1|modification|modificationes}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un nove message|999=nove messages}}',
+'newmessagesdifflinkplural' => 'ultime {{PLURAL:$1|modification|999=modificationes}}',
 'youhavenewmessagesmulti' => 'Tu ha nove messages in $1',
 'editsection' => 'modificar',
 'editold' => 'modificar',
@@ -555,7 +554,8 @@ Le administrator qui lo blocava offereva iste explication: "$3".',
 'invalidtitle-knownnamespace' => 'Titulo invalide con spatio de nomines "$2" e texto "$3"',
 'invalidtitle-unknownnamespace' => 'Titulo invalide con spatio de nomines incognite $1 e texto "$2"',
 'exception-nologin' => 'Non identificate',
-'exception-nologin-text' => 'Iste pagina o action necessita que tu aperi session in iste wiki.',
+'exception-nologin-text' => '[[Special:Userlogin|Aperi session]] pro poter acceder a iste pagina o action.',
+'exception-nologin-text-manual' => 'Es necessari $1 pro poter acceder a iste pagina o action.',
 
 # Virus scanner
 'virus-badscanner' => "Configuration incorrecte: programma antivirus non cognoscite: ''$1''",
@@ -602,7 +602,7 @@ Non oblida personalisar tu [[Special:Preferences|preferentias in {{SITENAME}}]].
 'gotaccount' => "Tu jam ha un conto? '''$1'''.",
 'gotaccountlink' => 'Aperir session',
 'userlogin-resetlink' => 'Datos de authentication oblidate?',
-'userlogin-resetpassword-link' => 'Reinitialisar contrasigno',
+'userlogin-resetpassword-link' => 'Contrasigno oblidate?',
 'helplogin-url' => 'Help:Aperir session',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Adjuta a aperir session]]',
 'userlogin-loggedin' => 'Tu ha jam aperite session como {{GENDER:$1|$1}}.
@@ -674,8 +674,8 @@ e continuar a usar le contrasigno original.',
 'passwordsent' => 'Un nove contrasigno ha essite inviate al adresse de e-mail registrate pro "$1".
 Per favor aperi session de novo post reciper lo.',
 'blocked-mailpassword' => 'Tu adresse IP es blocate de facer modificationes, e pro impedir le abuso, le uso del function pro recuperar contrasignos es equalmente blocate.',
-'eauthentsent' => 'Un e-mail de confirmation ha essite inviate al adresse de e-mail specificate.
-Pro poter reciper altere e-mail a iste conto, tu debe sequer le instructiones in iste e-mail pro confirmar que le conto es realmente tue.',
+'eauthentsent' => 'Un message de confirmation ha essite inviate al adresse de e-mail specificate.
+Pro permitter que le systema invia altere messages a iste adresse, tu debe sequer le instructiones in iste message pro confirmar que le adresse es realmente tue.',
 'throttled-mailpassword' => 'Un message pro le reinitialisation del contrasigno ha jam essite inviate intra le ultime {{PLURAL:$1|hora|$1 horas}}.
 Pro prevenir le abuso, solmente un message pro le reinitialisation del contrasigno essera inviate per {{PLURAL:$1|hora|$1 horas}}.',
 'mailerror' => 'Error de inviar e-mail: $1',
@@ -874,7 +874,7 @@ Per favor entra e valida tu adresse de e-mail per medio de tu [[Special:Preferen
 'nosuchsectiontext' => 'Tu ha tentate modificar un section que non existe.
 Illo pote haber essite displaciate o delite durante que tu legeva le pagina.',
 'loginreqtitle' => 'Identification necessari',
-'loginreqlink' => 'aperir un session',
+'loginreqlink' => 'aperir session',
 'loginreqpagetext' => 'Tu debe $1 pro poter vider altere paginas.',
 'accmailtitle' => 'Contrasigno inviate.',
 'accmailtext' => "Un contrasigno generate aleatorimente pro [[User talk:$1|$1]] ha essite inviate a $2. Illo pote esser cambiate in le pagina ''[[Special:ChangePassword|Cambiar contrasigno]]'' post que tu ha aperite un session.",
@@ -988,7 +988,7 @@ Tu pote retornar e modificar un pagina existente, o [[Special:UserLogin|aperir u
 'permissionserrors' => 'Error de permission',
 'permissionserrorstext' => 'Tu non ha le permission de facer isto, pro le sequente {{PLURAL:$1|motivo|motivos}}:',
 'permissionserrorstext-withaction' => 'Tu non ha le permission de $2, pro le sequente {{PLURAL:$1|motivo|motivos}}:',
-'recreate-moveddeleted-warn' => "'''Attention: Tu es sur le puncto de recrear un pagina que esseva anteriormente delite.'''
+'recreate-moveddeleted-warn' => "'''Attention: Tu es sur le puncto de recrear un pagina que ha essite delite anteriormente.'''
 
 Tu deberea considerar si il es appropriate continuar a modificar iste pagina.
 Ecce le registro de deletiones e de renominationes pro iste pagina:",
@@ -1136,18 +1136,19 @@ function, o le version specificate non existe, o tu essaya celar le version actu
 Altere administratores in {{SITENAME}} continuara a poter acceder al contento celate e pote restaurar lo per medio de iste mesme interfacie, si non se ha definite restrictiones additional.",
 'revdelete-confirm' => 'Per favor confirma que tu ha le intention de facer isto, que tu comprende le consequentias, e que tu face isto in accordo con [[{{MediaWiki:Policy-url}}|le politica]].',
 'revdelete-suppress-text' => "Le suppression debe '''solmente''' esser usate pro le sequente casos:
-* Informationes personal inappropriate
+* Information potentialmente diffamatori
+* Information personal inappropriate
 *: ''adresses de domicilio e numeros de telephono, numeros de securitate social, etc.''",
 'revdelete-legend' => 'Definir restrictiones de visibilitate',
-'revdelete-hide-text' => 'Celar le texto del version',
+'revdelete-hide-text' => 'Texto del version',
 'revdelete-hide-image' => 'Celar le contento del file',
 'revdelete-hide-name' => 'Celar action e objectivo',
-'revdelete-hide-comment' => 'Celar le summario del modification',
-'revdelete-hide-user' => 'Celar le nomine de usator o adresse IP del modificator',
+'revdelete-hide-comment' => 'Summario del modification',
+'revdelete-hide-user' => 'Nomine de usator o adresse IP del modificator',
 'revdelete-hide-restricted' => 'Supprimer le datos a administratores assi como a alteres',
 'revdelete-radio-same' => '(non cambiar)',
-'revdelete-radio-set' => 'Si',
-'revdelete-radio-unset' => 'No',
+'revdelete-radio-set' => 'Celate',
+'revdelete-radio-unset' => 'Visibile',
 'revdelete-suppress' => 'Supprimer le datos a administratores assi como a alteres',
 'revdelete-unsuppress' => 'Eliminar restrictiones super versiones restaurate',
 'revdelete-log' => 'Motivo:',
@@ -1306,8 +1307,7 @@ Nota que lor indices del contento de {{SITENAME}} pote esser obsolete.',
 'preferences' => 'Preferentias',
 'mypreferences' => 'Preferentias',
 'prefs-edits' => 'Numero de modificationes:',
-'prefsnologin' => 'Tu non ha aperite un session',
-'prefsnologintext' => 'Tu debe <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aperir session]</span> pro configurar preferentias de usator.',
+'prefsnologintext2' => 'Es necessari $1 pro definir le preferentias de usator.',
 'changepassword' => 'Cambiar contrasigno',
 'prefs-skin' => 'Apparentia',
 'skin-preview' => 'Previsualisation',
@@ -1568,7 +1568,7 @@ Si tu opta pro dar lo, isto essera usate pro dar te attribution pro tu contribut
 'action-reupload' => 'superscriber iste file existente',
 'action-reupload-shared' => 'supplantar iste file in un repositorio commun',
 'action-upload_by_url' => 'incargar iste file ab un adresse URL',
-'action-writeapi' => 'usar le API de scriptura',
+'action-writeapi' => 'usar le API pro modificar le wiki',
 'action-delete' => 'deler iste pagina',
 'action-deleterevision' => 'deler iste version',
 'action-deletedhistory' => 'vider le historia delite de iste pagina',
@@ -1607,6 +1607,8 @@ Si tu opta pro dar lo, isto essera usate pro dar te attribution pro tu contribut
 'recentchanges-label-minor' => 'Isto es un modification minor',
 'recentchanges-label-bot' => 'Iste modification ha essite effectuate per un robot',
 'recentchanges-label-unpatrolled' => 'Iste modification non ha ancora essite patruliate',
+'recentchanges-label-plusminus' => 'Le dimension del pagina ha cambiate de iste numero de bytes',
+'recentchanges-legend-newpage' => '(vide etiam le [[Special:NewPages|lista de nove paginas]])',
 'rcnote' => "Infra es {{PLURAL:$1|'''1''' modification|le ultime '''$1''' modificationes}} in le ultime {{PLURAL:$2|die|'''$2''' dies}}, actualisate le $4 a $5.",
 'rcnotefrom' => 'infra es le modificationes a partir de <b>$2</b> (usque a <b>$1</b>).',
 'rclistfrom' => 'Monstrar nove modificationes a partir de $1',
@@ -2349,7 +2351,7 @@ Pro contactar le redactor:
 mail: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Tu non recipera altere notificationes de activitate si tu non visita iste pagina. Tu pote anque reinitialisar le optiones de notification pro tote le paginas in tu observatorio.
+Tu non recipera altere notificationes de activitate si tu non visita iste pagina con session aperte. Tu pote anque reinitialisar le optiones de notification pro tote le paginas in tu observatorio.
 
 Le systema de notification de {{SITENAME}}, a tu servicio
 
@@ -2887,7 +2889,7 @@ In le secunde caso tu pote etiam usar un ligamine, p.ex. [[{{#Special:Export}}/{
 'allmessagesdefault' => 'Texto predefinite',
 'allmessagescurrent' => 'Texto actual',
 'allmessagestext' => 'Isto es un lista de messages de systema disponibile in le spatio de nomines MediaWiki.
-Per favor visita [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si tu desira contribuer al localisation general de MediaWiki.',
+Per favor visita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si tu desira contribuer al localisation general de MediaWiki.',
 'allmessagesnotsupportedDB' => "Iste pagina non pote esser usate proque '''\$wgUseDatabaseMessages''' ha essite disactivate.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar per stato de personalisation:',
@@ -3091,6 +3093,8 @@ Le causa es probabilemente un ligamine verso un sito externe que es presente in
 'spam_reverting' => 'Revertite al ultime version que non contine ligamines a $1',
 'spam_blanking' => 'Tote le versiones contineva ligamines a $1. Le pagina es vacuate.',
 'spam_deleting' => 'Tote le versiones contineva ligamines a $1. Le pagina es delite.',
+'simpleantispam-label' => "Verification anti-spam.
+'''NON''' completa isto!",
 
 # Info page
 'pageinfo-title' => 'Informationes pro "$1"',
@@ -3104,6 +3108,7 @@ Le causa es probabilemente un ligamine verso un sito externe que es presente in
 'pageinfo-length' => 'Dimension del pagina (in bytes)',
 'pageinfo-article-id' => 'ID del pagina',
 'pageinfo-language' => 'Lingua del contento del pagina',
+'pageinfo-content-model' => 'Modello de contento de pagina',
 'pageinfo-robot-policy' => 'Indexation per robots',
 'pageinfo-robot-index' => 'Permittite',
 'pageinfo-robot-noindex' => 'Non permittite',
@@ -3189,7 +3194,7 @@ Le execution de illo pote compromitter le securitate de tu systema.",
 'svg-long-desc' => 'File SVG, dimensiones nominal: $1 × $2 pixels, grandor del file: $3',
 'svg-long-desc-animated' => 'File SVG animate, dimensiones nominal: $1 × $2 pixels, grandor del file: $3',
 'svg-long-error' => 'File SVG invalide: $1',
-'show-big-image' => 'Plen resolution',
+'show-big-image' => 'File original',
 'show-big-image-preview' => ' Dimension de iste previsualisation: $1.',
 'show-big-image-other' => 'Altere {{PLURAL:$2|resolution|resolutiones}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3657,7 +3662,7 @@ Le alteres essera initialmente celate.
 
 # External editor support
 'edit-externally' => 'Modificar iste file con un programma externe',
-'edit-externally-help' => '(Vide le [//www.mediawiki.org/wiki/Manual:External_editors instructiones de configuration] pro ulterior informationes)',
+'edit-externally-help' => '(Vide le [https://www.mediawiki.org/wiki/Manual:External_editors instructiones de configuration] pro ulterior informationes)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'totes',
@@ -3760,6 +3765,9 @@ Per favor confirma que tu realmente vole recrear iste pagina.",
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Remover iste pagina de tu observatorio?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '“$1”',
+
 # Multipage image navigation
 'imgmultipageprev' => '← precedente pagina',
 'imgmultipagenext' => 'sequente pagina →',
@@ -3845,7 +3853,7 @@ Tu pote etiam [[Special:EditWatchlist|usar le editor standard]].',
 'version-hook-subscribedby' => 'Subscribite per',
 'version-version' => '(Version $1)',
 'version-license' => 'Licentia',
-'version-poweredby-credits' => "Iste wiki es actionate per '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Iste wiki es actionate per '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'alteres',
 'version-poweredby-translators' => 'Traductores de translatewiki.net',
 'version-credits-summary' => 'Nos vole recognoscer le sequente personas pro lor contribution a [[Special:Version|MediaWiki]].',
@@ -3866,7 +3874,7 @@ Vos deberea haber recipite [{{SERVER}}{{SCRIPTPATH}}/COPYING un exemplar del Lic
 # Special:Redirect
 'redirect' => 'Rediriger per nomine de file, ID de usator o ID de version',
 'redirect-legend' => 'Rediriger a un file o pagina',
-'redirect-summary' => 'Iste pagina special redirige a un file (si es date le nomine de un file), a un pagina (si es date un ID de version) o a un pagina de usator (si es date un ID de usator numeric).',
+'redirect-summary' => 'Iste pagina special redirige a un file (si es date le nomine de un file), a un pagina (si es date un ID de version) o a un pagina de usator (si es date un ID de usator numeric). Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] o [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Va',
 'redirect-lookup' => 'Cercar:',
 'redirect-value' => 'Valor:',
@@ -3888,10 +3896,9 @@ Vos deberea haber recipite [{{SERVER}}{{SCRIPTPATH}}/COPYING un exemplar del Lic
 
 # Special:SpecialPages
 'specialpages' => 'Paginas special',
-'specialpages-note' => '----
-* Paginas special normal.
-* <span class="mw-specialpagerestricted">Paginas special restringite.</span>
-* <span class="mw-specialpagecached">Paginas special del cache (poterea esser obsolete).</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Paginas special normal.
+* <span class="mw-specialpagerestricted">Paginas special restringite.</span>',
 'specialpages-group-maintenance' => 'Reportos de mantenentia',
 'specialpages-group-other' => 'Altere paginas special',
 'specialpages-group-login' => 'Aperir session / crear conto',
@@ -4104,4 +4111,21 @@ Si non, tu pote usar le formulario facile hic infra. Tu commento essera addite a
 'limitreport-expansiondepth' => 'Maxime profunditate de expansion',
 'limitreport-expensivefunctioncount' => 'Numero de functiones analysator costose',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expander patronos',
+'expand_templates_intro' => 'Iste pagina special prende texto e expande recursivemente tote le patronos in illo.
+Illo expande etiam le functiones del analysator syntactic como
+<code><nowiki>{{</nowiki>#language:…}}</code>, e variabiles como
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+De facto, illo expande quasi toto inter accolladas duple.',
+'expand_templates_title' => 'Titulo de contexto, pro {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Texto de entrata:',
+'expand_templates_output' => 'Resultato',
+'expand_templates_xml_output' => 'Output XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Eliminar commentos',
+'expand_templates_remove_nowiki' => 'Supprimer le etiquettas <nowiki> in le resultato',
+'expand_templates_generate_xml' => 'Monstrar arbore syntactic XML',
+'expand_templates_preview' => 'Previsualisation',
+
 );
index e4442bf..aa6074f 100644 (file)
@@ -135,7 +135,7 @@ $magicWords = array(
        'subjectpagename'           => array( '1', 'NAMAHALAMANUTAMA', 'NAMAHALAMANARTIKEL', 'NAMMANTAMA', 'NAMMANTIKEL', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
        'subjectpagenamee'          => array( '1', 'NAMAHALAMANUTAMAE', 'NAMAHALAMANARTIKELE', 'NAMMANTAMAE', 'NAMMANTIKELE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
        'msg'                       => array( '0', 'PSN:', 'PESAN:', 'MSG:' ),
-       'subst'                     => array( '0', 'GNT:', 'GANTI:', 'SUBST:' ),
+       'subst'                     => array( '0', 'GNT:', 'GANTI:', 'TUKAR:', 'SUBST:' ),
        'msgnw'                     => array( '0', 'TPL:', 'MSGNW:' ),
        'img_thumbnail'             => array( '1', 'jmpl', 'jempol', 'mini', 'miniatur', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'jmpl=$1', 'jempol=$1', 'mini=$1', 'miniatur=$1', 'thumbnail=$1', 'thumb=$1' ),
@@ -145,8 +145,9 @@ $magicWords = array(
        'img_center'                => array( '1', 'pus', 'pusat', 'center', 'centre' ),
        'img_framed'                => array( '1', 'bing', 'bingkai', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'nirbing', 'tanpabingkai', 'frameless' ),
-       'img_page'                  => array( '1', 'hal=$1', 'halaman=$1', 'hal $1', 'halaman $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'lurus', 'lurus=$1', 'lurus $1', 'tegak', 'tegak=$1', 'tegak $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_lang'                  => array( '1', 'bhs=$1', 'lang=$1' ),
+       'img_page'                  => array( '1', 'hal=$1', 'halaman=$1', 'hal_$1', 'halaman_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'lurus', 'lurus=$1', 'lurus_$1', 'tegak', 'tegak=$1', 'tegak_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'tepi', 'batas', 'border' ),
        'img_baseline'              => array( '1', 'gada', 'garis_dasar', 'baseline' ),
        'img_sub'                   => array( '1', 'upa', 'sub' ),
@@ -164,8 +165,8 @@ $magicWords = array(
        'server'                    => array( '0', 'PELADEN', 'SERVER' ),
        'servername'                => array( '0', 'NAMAPELADEN', 'NAMASERVER', 'NAMPEL', 'SERVERNAME' ),
        'scriptpath'                => array( '0', 'LOKASISKRIP', 'SCRIPTPATH' ),
-       'grammar'                   => array( '0', 'TATABAHASA', 'TASA', 'GRAMMAR:' ),
-       'gender'                    => array( '0', 'JANTINA', 'GENDER:' ),
+       'grammar'                   => array( '0', 'TATABAHASA:', 'TASA:', 'GRAMMAR:' ),
+       'gender'                    => array( '0', 'JANTINA:', 'GENDER:' ),
        'notitleconvert'            => array( '0', '__TANPAKONVERSIJUDUL__', '__NIRKODUL__', '__NOTITLECONVERT__', '__NOTC__' ),
        'nocontentconvert'          => array( '0', '__TANPAKONVERSIISI__', '__NIRKOSI__', '__NOCONTENTCONVERT__', '__NOCC__' ),
        'currentweek'               => array( '1', 'MINGGUKINI', 'MIKIN', 'CURRENTWEEK' ),
@@ -218,6 +219,9 @@ $magicWords = array(
        'staticredirect'            => array( '1', '__PENGALIHANSTATIK__', '__PENGALIHANSTATIS__', '__PETIK__', '__PETIS__', '__STATICREDIRECT__' ),
        'protectionlevel'           => array( '1', 'TINGKATPERLINDUNGAN', 'TIPER', 'PROTECTIONLEVEL' ),
        'formatdate'                => array( '0', 'formattanggal', 'formatdate', 'dateformat' ),
+       'pagesincategory_all'       => array( '0', 'semua', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'halaman', 'pages' ),
+       'pagesincategory_files'     => array( '0', 'berkas', 'files' ),
 );
 
 $specialPageAliases = array(
@@ -228,7 +232,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Judul_yang_buruk' ),
        'Blankpage'                 => array( 'Halaman_kosong', 'HalamanKosong' ),
        'Block'                     => array( 'Blokir_pengguna', 'BlokirPengguna' ),
-       'Blockme'                   => array( 'Blokir_saya', 'BlokirSaya' ),
        'Booksources'               => array( 'Sumber_buku', 'SumberBuku' ),
        'BrokenRedirects'           => array( 'Pengalihan_rusak', 'PengalihanRusak' ),
        'Categories'                => array( 'Daftar_kategori', 'DaftarKategori', 'Kategori' ),
@@ -240,10 +243,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Buat_akun', 'BuatAkun' ),
        'Deadendpages'              => array( 'Halaman_buntu', 'HalamanBuntu' ),
        'DeletedContributions'      => array( 'Kontribusi_yang_dihapus', 'KontribusiDihapus' ),
-       'Disambiguations'           => array( 'Disambiguasi' ),
        'DoubleRedirects'           => array( 'Pengalihan_ganda', 'PengalihanGanda' ),
        'EditWatchlist'             => array( 'Sunting_daftar_pantauan' ),
        'Emailuser'                 => array( 'Surel_pengguna', 'SurelPengguna' ),
+       'ExpandTemplates'           => array( 'Kembangkan_templat', 'KembangkanTemplat' ),
        'Export'                    => array( 'Ekspor_halaman', 'Ekspor' ),
        'Fewestrevisions'           => array( 'Perubahan_tersedikit', 'PerubahanTersedikit' ),
        'FileDuplicateSearch'       => array( 'Pencarian_berkas_duplikat', 'PencarianBerkasDuplikat' ),
@@ -286,6 +289,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Halaman_yang_dilindungi', 'HalamanDilindungi' ),
        'Protectedtitles'           => array( 'Judul_yang_dilindungi', 'JudulDilindungi' ),
        'Randompage'                => array( 'Halaman_sembarang', 'HalamanSembarang' ),
+       'RandomInCategory'          => array( 'Sembarang_di_kategori', 'SembarangDiKategori' ),
        'Randomredirect'            => array( 'Pengalihan_sembarang', 'PengalihanSembarang' ),
        'Recentchanges'             => array( 'Perubahan_terbaru', 'PerubahanTerbaru', 'RC', 'PT' ),
        'Recentchangeslinked'       => array( 'Perubahan_terkait', 'PerubahanTerkait' ),
@@ -481,8 +485,6 @@ $messages = array(
 'broken-file-category' => 'Halaman dengan gambar rusak',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Tentang',
 'article' => 'Halaman isi',
 'newwindow' => '(buka di jendela baru)',
@@ -620,8 +622,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Diperoleh dari "$1"',
 'youhavenewmessages' => 'Anda mempunyai $1 ($2).',
-'newmessageslink' => 'pesan baru',
-'newmessagesdifflink' => 'perubahan terakhir',
 'youhavenewmessagesfromusers' => 'Anda memiliki $1 dari {{PLURAL:$3|$3 pengguna lain}} ($2).',
 'youhavenewmessagesmanyusers' => 'Anda memiliki $1 dari pengguna lain ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|pesan baru}}',
@@ -1465,8 +1465,6 @@ Perlu diingat bahwa indeks Google untuk konten {{SITENAME}} mungkin belum mencak
 'preferences' => 'Preferensi',
 'mypreferences' => 'Preferensi',
 'prefs-edits' => 'Jumlah suntingan:',
-'prefsnologin' => 'Belum masuk log',
-'prefsnologintext' => 'Anda harus <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} masuk log]</span> untuk mengeset preferensi Anda.',
 'changepassword' => 'Ganti kata sandi',
 'prefs-skin' => 'Kulit',
 'skin-preview' => 'Pratayang',
@@ -1770,6 +1768,7 @@ Jika Anda memberikannya, nama asli Anda akan digunakan untuk memberi pengenalan
 'recentchanges-label-minor' => 'Ini adalah suntingan kecil',
 'recentchanges-label-bot' => 'Suntingan ini dilakukan oleh bot',
 'recentchanges-label-unpatrolled' => 'Suntingan ini belum terpatroli',
+'recentchanges-legend-newpage' => '$1 - halaman baru',
 'rcnote' => "Berikut adalah {{PLURAL:$1|'''1'''|'''$1'''}} perubahan terbaru dalam {{PLURAL:$2|'''1''' hari|'''$2''' hari}} terakhir, sampai $4 pukul $5.",
 'rcnotefrom' => 'Di bawah ini adalah perubahan sejak <strong>$2</strong> (ditampilkan sampai <strong>$1</strong> perubahan).',
 'rclistfrom' => 'Perlihatkan perubahan terbaru sejak $1',
@@ -2686,7 +2685,6 @@ Lihat [[Special:Log/delete|log penghapusan]] untuk data penghapusan dan pengemba
 $1',
 'undelete-show-file-confirm' => 'Apakah Anda yakin ingin melihat revisi yang telah dihapus dari berkas "<nowiki>$1</nowiki>" per $3, $2?',
 'undelete-show-file-submit' => 'Ya',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'Ruang nama:',
@@ -3007,7 +3005,7 @@ Jika Anda hanya ingin mengimpor versi terbaru, Anda melakukannya lebih cepat den
 'allmessagesdefault' => 'Teks baku',
 'allmessagescurrent' => 'Teks sekarang',
 'allmessagestext' => 'Ini adalah daftar semua pesan sistem yang tersedia dalam ruang nama MediaWiki.
-Silakan kunjungi [//www.mediawiki.org/wiki/Localisation Pelokalan MediaWiki] dan [//translatewiki.net translatewiki.net] jika Anda ingin berkontribusi untuk pelokalan generik MediaWiki.',
+Silakan kunjungi [https://www.mediawiki.org/wiki/Localisation Pelokalan MediaWiki] dan [//translatewiki.net translatewiki.net] jika Anda ingin berkontribusi untuk pelokalan generik MediaWiki.',
 'allmessagesnotsupportedDB' => "Halaman ini tidak dapat digunakan karena '''\$wgUseDatabaseMessages''' telah dimatikan.",
 'allmessages-filter-legend' => 'Penyaring',
 'allmessages-filter' => 'Saring dengan keadaan kustomisasi:',
@@ -3218,6 +3216,8 @@ Ini mungkin disebabkan oleh pranala ke situs luar yang termasuk dalam daftar hit
 'spam_reverting' => 'Membatalkan ke versi terakhir yang tak memiliki pranala ke $1',
 'spam_blanking' => 'Semua revisi yang memiliki pranala ke $1, kosong',
 'spam_deleting' => 'Semua revisi yang memiliki pranala ke $1, penghapusan',
+'simpleantispam-label' => "Pemeriksaan anti-spam.
+Masukan ini '''DILARANG'''!",
 
 # Info page
 'pageinfo-title' => 'Informasi untuk "$1"',
@@ -3319,7 +3319,7 @@ Jika dijalankan, sistem Anda akan berisiko terserang.",
 'svg-long-desc' => 'Berkas SVG, nominal $1 × $2 piksel, besar berkas: $3',
 'svg-long-desc-animated' => 'Berkas SVG animasi, biasanya $1 x $2 piksel, ukuran gambar: $3',
 'svg-long-error' => 'Berkas SVG tidak sah: $1',
-'show-big-image' => 'Resolusi penuh',
+'show-big-image' => 'Ukuran asli',
 'show-big-image-preview' => 'Ukuran pratayang ini: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Resolusi|Resolusi}} lain: $1.',
 'show-big-image-size' => '$1 × $2 piksel',
@@ -3863,7 +3863,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'Sunting berkas ini dengan aplikasi luar',
-'edit-externally-help' => '(Lihat [//www.mediawiki.org/wiki/Manual:External_editors instruksi pengaturan] untuk informasi lebih lanjut)',
+'edit-externally-help' => '(Lihat [https://www.mediawiki.org/wiki/Manual:External_editors instruksi pengaturan] untuk informasi lebih lanjut)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'semua',
@@ -4100,7 +4100,7 @@ Anda juga dapat [[Special:EditWatchlist|menggunakan penyunting standar Anda]].',
 'version-version' => '(Versi $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Lisensi',
-'version-poweredby-credits' => "Wiki ini didukung oleh '''[//www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki ini didukung oleh '''[https://www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
 'version-poweredby-others' => 'lainnya',
 'version-poweredby-translators' => 'penerjemah translatewiki.net',
 'version-credits-summary' => 'Kami ingin mengakui orang-orang berikut atas kontribusinya terhadap [[Special:Version|MediaWiki]].',
@@ -4143,8 +4143,7 @@ Anda seharusnya telah menerima [{{SERVER}}{{SCRIPTPATH}}/COPYING salinan Lisensi
 
 # Special:SpecialPages
 'specialpages' => 'Halaman istimewa',
-'specialpages-note' => '----
-* Halaman istimewa normal.
+'specialpages-note' => '* Halaman istimewa normal.
 * <span class="mw-specialpagerestricted">Halaman istimewa terlarang.</span>
 * <span class="mw-specialpagecached">Halaman istimewa tersinggah (mungkin usang).</span>',
 'specialpages-group-maintenance' => 'Laporan pemeliharaan',
@@ -4352,4 +4351,17 @@ Jika tidak, Anda dapat menggunakan formulir mudah di bawah ini. Komentar Anda ak
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bita|bita}}',
 'limitreport-expensivefunctioncount' => 'Perhitungan fungsi parser yang mahal',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Pengembangan templat',
+'expand_templates_intro' => 'Halaman istimewa ini mengambil teks dan mengembangkan semua templat di dalamnya secara rekursif. Halaman ini juga menerjemahkan semua fungsi parser seperti <code><nowiki>{{</nowiki>#language:…}}</code> dan variabel seperti <code><nowiki>{{</nowiki>CURRENTDAY}}</code>. Bahkan bisa dibilang mengembangkan segala sesuatu yang berada di antara dua tanda kurung.',
+'expand_templates_title' => 'Judul konteks, untuk {{FULLPAGENAME}} dan lain-lain:',
+'expand_templates_input' => 'Teks masukan:',
+'expand_templates_output' => 'Hasil',
+'expand_templates_xml_output' => 'Hasil XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Buang komentar',
+'expand_templates_remove_nowiki' => 'Tidak menampilkan tag <nowiki> pada hasilnya',
+'expand_templates_generate_xml' => 'Tampilkan pohon parser XML',
+'expand_templates_preview' => 'Pratayang',
+
 );
index 0112545..6c3b7ee 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Jmb
  * @author Kaganer
+ * @author Makuba
  * @author Malafaya
  * @author Reedy
  * @author Remember the dot
@@ -43,7 +44,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Págines_antiqui' ),
        'Blankpage'                 => array( 'Págine_in_blanc' ),
        'Block'                     => array( 'Blocar', 'Blocar_IP', 'Blocar_usator' ),
-       'Blockme'                   => array( 'Blocar_in_mi_self' ),
        'Booksources'               => array( 'Fontes_de_libres' ),
        'BrokenRedirects'           => array( 'Redirectionmentes_ínperfect' ),
        'ChangePassword'            => array( 'Change_parol-clave' ),
@@ -53,7 +53,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crear_conto' ),
        'Deadendpages'              => array( 'Págines_moderat' ),
        'DeletedContributions'      => array( 'Contributiones_deletet' ),
-       'Disambiguations'           => array( 'Disambiguitones' ),
        'DoubleRedirects'           => array( 'Redirectionmentes_duplic' ),
        'EditWatchlist'             => array( 'Redacter_liste_de_págines_vigilat' ),
        'Emailuser'                 => array( 'Email_de_usator' ),
@@ -139,17 +138,17 @@ $messages = array(
 'tog-hideminor' => 'Ocultar redactiones minori in nov changes',
 'tog-hidepatrolled' => 'Ocultar redactiones vigilat in nov changes',
 'tog-newpageshidepatrolled' => 'Ocultar págines vigilat de liste de nov págines',
-'tog-usenewrc' => 'Usar nov changes augmentat (exige JavaScript)',
+'tog-usenewrc' => 'Ordinar changes in «Recent changes» e li liste de vigila secun págines',
 'tog-numberheadings' => 'Auto-numerar rublicas',
-'tog-showtoolbar' => 'Monstrar barre de utensile de redaction (exige JavaScript)',
-'tog-editondblclick' => 'Redacter págines in clacca duplic (exige JavaScript)',
+'tog-showtoolbar' => 'Monstrar barre de redactional utensiles',
+'tog-editondblclick' => 'Redacter págines per duplic clacca',
 'tog-editsection' => 'Permisser redaction de division usant catenunes [redacter]',
-'tog-editsectiononrightclick' => 'Permisser redaction de division per clacca dextri in titules de division (exige JavaScript)',
+'tog-editsectiononrightclick' => 'Redacter singul sectiones per dextri clacca',
 'tog-showtoc' => 'Monstrar tabelle de contenetes (por págines che plu de 3 divisiones)',
 'tog-rememberpassword' => 'Memorar mi registre in ti computator (por um max de $1 {{PLURAL:$1|die|dies}})',
-'tog-watchcreations' => 'Adjunter págines que yo crear por mi liste de págines vigilat',
-'tog-watchdefault' => 'Adjunter págines que yo redacter por mi liste de págines vigilat',
-'tog-watchmoves' => 'Adjunter págines que yo mover por mi liste de págines vigilat',
+'tog-watchcreations' => 'Automaticmen viligar págines e files, queles yo ha creat.',
+'tog-watchdefault' => 'Automaticmen vigilar págines e files, queles yo ha redactet.',
+'tog-watchmoves' => 'Automaticmen vigilar págines e files, queles yo move.',
 'tog-watchdeletion' => 'Adjunter págines que yo deleter por mi liste de págines vigilat',
 'tog-minordefault' => 'Marcar omni li redactiones minori per contumacie',
 'tog-previewontop' => 'Monstrar prevision ante de buxe de redaction',
@@ -159,9 +158,9 @@ $messages = array(
 'tog-enotifusertalkpages' => 'Inviar me e-mail quande mi págine de discussion es changeat',
 'tog-enotifrevealaddr' => 'Revelar mi adresse de e-mail in notificationes de e-mail',
 'tog-shownumberswatching' => 'Monstrar li númere de usatores vigilant',
-'tog-oldsig' => 'Prevision de signature in existentie:',
+'tog-oldsig' => 'Existent subscrition:',
 'tog-fancysig' => 'Tractar signature quam textu wiki (sin un catenun auto-crate)',
-'tog-uselivepreview' => 'Usar prevision in vivi (exige JavaScript) (experimental)',
+'tog-uselivepreview' => 'Strax monstrar prevision (experimental)',
 'tog-forceeditsummary' => 'Suggester me quande intrar un redaction che summarium in blanc',
 'tog-watchlisthideown' => 'Ocultar mi redactiones del liste de págines vigilat',
 'tog-watchlisthidebots' => 'Ocultar redactiones de machine del liste de págines vigilat',
@@ -174,15 +173,23 @@ $messages = array(
 'tog-showhiddencats' => 'Monstrar categories ne visibil',
 'tog-noconvertlink' => 'Desvalidar conversion de titul de catenun',
 'tog-norollbackdiff' => 'Omisser change pos de efectuar un rollback',
+'tog-prefershttps' => 'Sempre usar un secur connection, si tui session es activ.',
 
 'underline-always' => 'Sempre',
 'underline-never' => 'Nequande',
-'underline-default' => 'Criterie de navigator',
+'underline-default' => 'secun li usatori surfacie o li navigator',
+
+# Font style option in Special:Preferences
+'editfont-style' => 'Styl del lítteres in li redactional fenestre:',
+'editfont-default' => 'Standard del navigator',
+'editfont-monospace' => 'Lítteres con egal largitá',
+'editfont-sansserif' => 'Lítteres sin serifes',
+'editfont-serif' => 'Lítteres con serifes',
 
 # Dates
 'sunday' => 'soledí',
 'monday' => 'lunedí',
-'tuesday' => 'mardí',
+'tuesday' => 'martedí',
 'wednesday' => 'mercurdí',
 'thursday' => 'jovedí',
 'friday' => 'venerdí',
@@ -198,7 +205,7 @@ $messages = array(
 'february' => 'februar',
 'march' => 'marte',
 'april' => 'april',
-'may_long' => 'may',
+'may_long' => 'mai',
 'june' => 'junio',
 'july' => 'julí',
 'august' => 'august',
@@ -210,9 +217,9 @@ $messages = array(
 'february-gen' => 'februar',
 'march-gen' => 'marte',
 'april-gen' => 'april',
-'may-gen' => 'may',
+'may-gen' => 'mai',
 'june-gen' => 'junio',
-'july-gen' => 'juli',
+'july-gen' => 'julí',
 'august-gen' => 'august',
 'september-gen' => 'septembre',
 'october-gen' => 'octobre',
@@ -222,7 +229,7 @@ $messages = array(
 'feb' => 'feb',
 'mar' => 'mar',
 'apr' => 'apr',
-'may' => 'may',
+'may' => 'mai',
 'jun' => 'jun',
 'jul' => 'jul',
 'aug' => 'aug',
@@ -230,6 +237,18 @@ $messages = array(
 'oct' => 'oct',
 'nov' => 'nov',
 'dec' => 'dec',
+'january-date' => '$1 januar',
+'february-date' => '$1 februar',
+'march-date' => '$1 marte',
+'april-date' => '$1 april',
+'may-date' => '$1 mai',
+'june-date' => '$1 junio',
+'july-date' => '$1 julí',
+'august-date' => '$1 august',
+'september-date' => '$1 septembre',
+'october-date' => '$1 octobre',
+'november-date' => '$1 novembre',
+'december-date' => '$1 decembre',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Categorie|Categories}}',
@@ -237,26 +256,34 @@ $messages = array(
 'subcategories' => 'Subcategories',
 'category-media-header' => 'Multimedia in categorie "$1"',
 'category-empty' => "''Ti categorie currentmen ne contene págines o media.''",
-'hidden-categories' => '{{PLURAL:$1|Categorie ocultat|Categories ocultat}}',
+'hidden-categories' => '{{PLURAL:$1|Celat categorie|Celat categories}}',
+'hidden-category-category' => 'Celat categories',
 'category-subcat-count' => '{{PLURAL:$2|Ti categorie ha solmen li sequent subcategorie.|Ti categorie ha li sequent {{PLURAL:$1|subcategorie|$1 subcategories}}, de un total de $2.}}',
+'category-subcat-count-limited' => 'Ti-ci categorie contene li secuent {{PLURAL:$1|subcategorie|$1 subcategories}}.',
 'category-article-count' => '{{PLURAL:$2|Ti categorie contene solmen li sequent págine.|Li sequent {{PLURAL:$1|págine es|$1 págine es}} in ti categorie, de un total de $2.}}',
+'category-article-count-limited' => 'Li secuent {{PLURAL:$1|págine|$1 pagines}} es contenet in ti-ci categorie:',
 'category-file-count' => '{{PLURAL:$2|Ti categorie contene solmen li sequent file.|Li sequent {{PLURAL:$1|file es|$1 files es}} in ti categorie, de un total de $2.}}',
+'category-file-count-limited' => 'Li secuent {{PLURAL:$1|file|$1 files}} es contenet in ti-ci categorie:',
 'listingcontinuesabbrev' => 'cont.',
+'index-category' => 'Indexat págines',
 'noindex-category' => 'Págines ne indexet',
+'broken-file-category' => 'Págines con ruptet file-links.',
 
 'about' => 'Concernent',
 'article' => 'Articul',
-'newwindow' => '(inaugurar in nov planca de fenestre)',
+'newwindow' => '(es apertet in un nov fenestre)',
 'cancel' => 'Anullar',
 'moredotdotdot' => 'Plu...',
-'mypage' => 'Mi págine',
-'mytalk' => 'Mi discussion',
+'morenotlisted' => 'Ti liste ne es complet.',
+'mypage' => 'Págine',
+'mytalk' => 'Conversation',
 'anontalk' => 'Discussion por ti ci IP',
 'navigation' => 'Navigation',
 'and' => '&#32;e',
 
 # Cologne Blue skin
 'qbfind' => 'Constatar',
+'qbbrowse' => 'Travider',
 'qbedit' => 'Redacter',
 'qbpageoptions' => 'Págine de optiones',
 'qbmyoptions' => 'Mi optiones',
@@ -270,16 +297,17 @@ $messages = array(
 'vector-action-protect' => 'Gardar',
 'vector-action-undelete' => 'Restituer',
 'vector-action-unprotect' => 'Desgardar',
-'vector-simplesearch-preference' => 'Premisser suggestiones de sercha argumentat (pelle Vector solmen)',
+'vector-simplesearch-preference' => 'Simplificat serch-liste (solmen Vector)',
 'vector-view-create' => 'Crear',
 'vector-view-edit' => 'Redacter',
-'vector-view-history' => 'Vider historie',
+'vector-view-history' => 'Historie de versiones',
 'vector-view-view' => 'Leer',
 'vector-view-viewsource' => 'Vider fonte',
 'actions' => 'Actiones',
 'namespaces' => 'Spacies de nómine',
 'variants' => 'Variantes',
 
+'navigation-heading' => 'Navigational menú',
 'errorpagetitle' => 'Errore',
 'returnto' => 'Retornar a $1.',
 'tagline' => 'De {{SITENAME}}',
@@ -289,41 +317,48 @@ $messages = array(
 'go' => 'Ear',
 'searcharticle' => 'Ear',
 'history' => 'Historie',
-'history_short' => 'Historie',
+'history_short' => 'Historie de versiones',
 'updatedmarker' => 'modernisat desde mi ultim visitation',
-'printableversion' => 'Version por impression',
-'permalink' => 'Catenun permanent',
+'printableversion' => 'Version a printar',
+'permalink' => 'Permanent referentie',
+'print' => 'Printar',
+'view' => 'Leer',
 'edit' => 'Redacter',
 'create' => 'Crear',
 'editthispage' => 'Redacter',
+'create-this-page' => 'Crear ti págine',
 'delete' => 'Deleter',
 'deletethispage' => 'Deleter ti págine',
+'undeletethispage' => 'Restaurar ti págine',
 'undelete_short' => 'Restaurar {{PLURAL:$1|1 modification|$1 modificationes}}',
+'viewdeleted_short' => 'Vider {{PLURAL:$1|un deletet version|$1 deletet versiones}}',
 'protect' => 'Gardar',
-'protect_change' => 'Change',
+'protect_change' => 'changer',
 'protectthispage' => 'Gardar ti págine',
 'unprotect' => 'Changear protection',
 'unprotectthispage' => 'Changear protection de ti págine',
 'newpage' => 'Nov págine',
 'talkpage' => 'Parlar in ti págine',
-'talkpagelinktext' => 'Discussion',
+'talkpagelinktext' => 'Conversation',
 'specialpage' => 'Págine special',
-'personaltools' => 'Utensiles personal',
+'personaltools' => 'Mi utensiles',
 'postcomment' => 'Nov division',
 'articlepage' => 'Vider li articul',
 'talk' => 'Discussion',
-'views' => 'Vistas',
-'toolbox' => 'Buxe de utensiles',
+'views' => 'Aspectes',
+'toolbox' => 'Utensiles',
 'userpage' => 'Vider págine del usator',
 'projectpage' => 'Vider págine de projecte',
 'imagepage' => 'Vider li págine de figura',
+'mediawikipage' => 'Vider págine de missagies',
 'templatepage' => 'Vider li págine de avise',
 'viewhelppage' => 'Vider págine de auxilie',
+'categorypage' => 'Vider categorial págine',
 'viewtalkpage' => 'Vider discussion',
 'otherlanguages' => 'Altri lingues',
 'redirectedfrom' => '(Redirectet de $1)',
 'redirectpagesub' => 'Págine de redirecterion',
-'lastmodifiedat' => 'Ti págine esset per ultim témpor redactet in $1, in $2.',
+'lastmodifiedat' => 'Ti-ci págine ha redactet in ultim li $1, clocca $2.',
 'viewcount' => 'Ti págine ha esset accesset {{PLURAL:$1|un vez|$1 vezes}}.',
 'protectedpage' => 'Un protectet págine',
 'jumpto' => 'Saltar a:',
@@ -337,19 +372,19 @@ $1',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Concernent {{SITENAME}}',
-'aboutpage' => 'Project:Concernent',
-'copyright' => 'Contenete disponibil sub $1.',
+'aboutpage' => 'Project:Concernent_{{SITENAME}}',
+'copyright' => 'Contenete attiņibil sub $1, si ne altrimen indicat.',
 'copyrightpage' => '{{ns:project}}:Jure editorial',
-'currentevents' => 'Eventus current',
-'currentevents-url' => 'Project:Eventus current',
+'currentevents' => 'Actual evenimentes',
+'currentevents-url' => 'Project:Actual evenimentes',
 'disclaimers' => 'Advertimentes',
-'disclaimerpage' => 'Project:Advertimentes comun',
-'edithelp' => 'Redacter auxilie',
+'disclaimerpage' => 'Project:Advertimentes',
+'edithelp' => 'Redactori auxilie',
 'helppage' => 'Help:Contenete',
-'mainpage' => 'Págine principal',
-'mainpage-description' => 'Págine principal',
-'portal' => 'Págine de comunité',
-'portal-url' => 'Project:Págine de comunité',
+'mainpage' => 'Principal págine',
+'mainpage-description' => 'Principal págine',
+'portal' => 'Portale del communité',
+'portal-url' => 'Project:Portale del communité',
 'privacy' => 'Politica de privatie',
 'privacypage' => 'Project:Politica de privatie',
 
@@ -357,18 +392,16 @@ $1',
 'versionrequiredtext' => 'Version $1 de MediaWiki es exiget por usar ti págine.
 Vider [[Special:Version|págine de version]].',
 
-'retrievedfrom' => 'Recuperat de "$1"',
+'retrievedfrom' => 'Cargat de «$1»',
 'youhavenewmessages' => 'Vu have $1 ($2).',
-'newmessageslink' => 'nov missages',
-'newmessagesdifflink' => 'vider missages antiqui',
 'youhavenewmessagesmulti' => 'Vu have nov missages in $1',
 'editsection' => 'redacter',
 'editold' => 'redacter',
 'viewsourceold' => 'vider fonte',
 'editlink' => 'redacter',
 'viewsourcelink' => 'vider fonte',
-'editsectionhint' => 'Redacter division: $1',
-'toc' => 'Contenetes',
+'editsectionhint' => 'Redacter section: $1',
+'toc' => 'Contenete',
 'showtoc' => 'monstrar',
 'hidetoc' => 'ocultar',
 'thisisdeleted' => 'Vider o restaurar $1?',
@@ -378,9 +411,9 @@ Vider [[Special:Version|págine de version]].',
 'red-link-title' => '$1 (págine ne existe)',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Articul',
+'nstab-main' => 'Págine',
 'nstab-user' => 'Págine de usator',
-'nstab-special' => 'Págine special',
+'nstab-special' => 'Special págine',
 'nstab-project' => 'Págine de projecte',
 'nstab-image' => 'Figura',
 'nstab-mediawiki' => 'Missage',
@@ -390,12 +423,13 @@ Vider [[Special:Version|págine de version]].',
 
 # General errors
 'error' => 'Erra',
-'missing-article' => 'Li funde de datas ne constatat li textu de un págine que it posse constatar, nominat "$1" $2.
+'missing-article' => 'Li textu de «$1» $2 ne ha esset trovat in li data-base.
+
+It es possibil, que ti págine ha esset deleet o movet.
 
-Ti es usualmen causat per sequent un diferentie ne modernisat o catenun de historie por un págine que ha esset deletet.
 
-Si ti ne es li casu, vu posse have constatat un bug in li software.
-Pleser raporta it por un [[Special:ListUsers/sysop|administrator]], formant note de li URL.',
+Si to ne es just, tu ha forsan trovat un erra in li programma.
+Ples raporta it a un [[Special:ListUsers/sysop|administrator]], notante li URL.',
 'missingarticle-rev' => '(revision#: $1)',
 'unexpected' => 'Valor ínexpectat: "$1"="$2".',
 'badtitle' => 'Titul mal',
@@ -415,9 +449,9 @@ Li motive dat es "\'\'$2\'\'".',
 'virus-unknownscanner' => 'antivírus desconosset:',
 
 # Login and logout pages
-'logouttext' => "'''Vu ha terminat vor session.'''
-Vu posse continuar usar {{SITENAME}} anonimimen, o vu posse <span class='plainlinks'>[$1 aperter un session denov]</span> quam li sam usator o quam un diferent usator.
-Nota que alcun págines posse continuar esser monstrat quam si vu esset registrat, til que vu vacua li cache de tui navigator.",
+'logouttext' => "'''Tu ha terminat tui session.'''
+
+Nota, que alcun págines posse continualmen esser monstrat quasi tu vell ancor esser inregistrat, til que tu vacua li cache de tui navigator.",
 'yourname' => 'Nómine de usator:',
 'yourpassword' => 'Parol-clave:',
 'yourpasswordagain' => 'Parol-clave denov:',
@@ -429,7 +463,7 @@ Nota que alcun págines posse continuar esser monstrat quam si vu esset registra
 'userlogin' => 'Crear un conto o intrar',
 'userloginnocreate' => 'Intrar',
 'logout' => 'Surtida',
-'userlogout' => 'Surtida',
+'userlogout' => 'Surtir',
 'notloggedin' => 'Vu ne ha intrat',
 'nologin' => 'Ne have un conto? $1.',
 'nologinlink' => 'Crear un conto',
@@ -465,27 +499,27 @@ Por preventer misusa, solmen un parol-clave amemora va esser inviat per {{PLURAL
 'passwordreset-username' => 'Vor nómine usatori',
 
 # Edit page toolbar
-'bold_sample' => 'Textu in nigri',
-'bold_tip' => 'Textu in nigri',
-'italic_sample' => 'Textu cursivmen',
-'italic_tip' => 'Textu cursivmen',
-'link_sample' => 'Titul de catenun',
-'link_tip' => 'Catenun intern',
-'extlink_sample' => 'http://www.example.com titul de catenun',
-'extlink_tip' => 'Catenun extern (memorar prefixe http://)',
-'headline_sample' => 'Division de nivelle 2',
-'headline_tip' => 'Division de nivelle 2',
-'nowiki_sample' => 'Ignorar formate wiki',
+'bold_sample' => 'Nigri textu',
+'bold_tip' => 'Nigri textu',
+'italic_sample' => 'Cursiv textu',
+'italic_tip' => 'Cursiv textu',
+'link_sample' => 'Nómine de referentie',
+'link_tip' => 'Intern referentie',
+'extlink_sample' => 'http://www.example.com nómine del referentie',
+'extlink_tip' => 'Extern referentie (ne oblivia prefixar http://)',
+'headline_sample' => 'Titul de nivell 2',
+'headline_tip' => 'Titul de nivell 2',
+'nowiki_sample' => 'Intrar ínformatat textu ci.',
 'nowiki_tip' => 'Ignorar formate wiki',
-'image_tip' => 'File fixat',
-'media_tip' => 'Catenun in file de multimedia',
-'sig_tip' => 'Tui signature che hor e date',
-'hr_tip' => 'Linea horizontal (use sin excess)',
+'image_tip' => 'Fixat file',
+'media_tip' => 'Referentie a un multimedial file.',
+'sig_tip' => 'Tui subscrit con hor e date',
+'hr_tip' => 'Horizontal linea (ples usar sin excess)',
 
 # Edit pages
-'summary' => 'Summarium:',
+'summary' => 'Resummation:',
 'subject' => 'Tema/Division:',
-'minoredit' => 'Ti es un redaction minori',
+'minoredit' => 'To es un bagatellic change',
 'watchthis' => 'Vigilar ti págine',
 'savearticle' => 'Conservar págine',
 'preview' => 'Prevision',
@@ -503,12 +537,10 @@ Tui adresse de IP va esser registrat in historico de redactiones de ti págine."
 'newarticletext' => "Vu have sequet un catenun por un págine que ne existe ancor.
 Por crear li págine, comensa tippant in li buxe in infra (vider li [[{{MediaWiki:Helppage}}|págine de auxilie]] por plu informationes).
 Si vu es ci per errore, clacca in li buton '''retornar''' in tui navigator.",
-'noarticletext' => 'Vi currentmen ne textu in ti págine.
-Vu posse [[Special:Search/{{PAGENAME}}|serchar por ti titul de págine]] in altri págines,
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchar li diariumes relatet], o [{{fullurl:{{FULLPAGENAME}}|action=edit}} redacter ti págine]</span>.',
-'noarticletext-nopermission' => 'Vi currentmen ne textu in ti págine.
-Vu posse [[Special:Search/{{PAGENAME}}|serchar por titul de ti págine]] in altri págines,
-o <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchar li diariumes relatet]</span>.',
+'noarticletext' => 'Actualmen ti-ci págine ancor ne contene alquel textu.
+Tu posse <span class="plainlinks">[{{fullurl:{{FULLPAGENAME}}|action=edit}} redacter]</span> it, [[Special:Search/{{PAGENAME}}|serchar]] su titul in altri págines o regardar li relatent <span class="plainlinks">[{{fullurl:{{#special:Log}}|page={{FULLPAGENAMEE}}}} logs]</span>.',
+'noarticletext-nopermission' => 'Actualmen ti págine ne contene textu e tu ne have permission crear ti págine.
+Tu posse [[Special:Search/{{PAGENAME}}|serchar]] su titul sur altri págines o regardar li <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} relatent logs].</span>',
 'userpage-userdoesnotexist' => 'Conto de usator "$1" ne es registrat.
 Pleser controla si vu cari crear/redacter ti págine.',
 'userpage-userdoesnotexist-view' => 'Conto de usator "$1" ne es registrat.',
@@ -538,7 +570,7 @@ Li ultim intrada in li historico es sub li condition infra por referentie:",
 'templatesused' => '{{PLURAL:$1|Avise|Avises}} usat in ti págine:',
 'templatesusedpreview' => '{{PLURAL:$1|Avise|Avises}} usat in ti prevision:',
 'templatesusedsection' => '{{PLURAL:$1|Avise|Avises}} usat in ti division:',
-'template-protected' => '(gardat)',
+'template-protected' => '(protectet)',
 'template-semiprotected' => '(medie-gardat)',
 'hiddencategories' => 'Ti págine es un membre de {{PLURAL:$1|1 categorie ocultat|$1 categories ocultat}}:',
 'permissionserrorstext-withaction' => 'Vu ne have permission por $2, por li sequent {{PLURAL:$1|motive|motives}}:',
@@ -550,9 +582,8 @@ Li deletion e diarium de movement por li págine es sub li condition ci por conv
 Li deletion e diarium de movement por li págine es sub li condition in infra por referentie.',
 
 # Parser/template warnings
-'post-expand-template-inclusion-warning' => "'''Advertiment:''' Avise que include dimension es anc grand.
-Alcun avises va ne esser includet.",
-'post-expand-template-inclusion-category' => 'Págines u avise que include dimension es excedet',
+'post-expand-template-inclusion-warning' => "'''Advertiment:''' Li grandore del includet shablones es tro grand. Alcun shablones ne posse esser includet.",
+'post-expand-template-inclusion-category' => 'Págines, in queles li maximal grandore del includet shablones es excedet',
 'post-expand-template-argument-warning' => "'''Advertiment:''' Ti págine contene in un minim argumente de avise quel ha un anc mensura de expansion grand.
 Tis argumentes have esset omisset.",
 'post-expand-template-argument-category' => 'Págines contenent argumentes de avise omisset',
@@ -566,10 +597,10 @@ Tis argumentes have esset omisset.",
 # History pages
 'viewpagelogs' => 'Vider diariumes por ti págine',
 'currentrev' => 'Ultim revision',
-'currentrev-asof' => 'Ultim revision quam de $1',
+'currentrev-asof' => 'Actual version de $2, clocca $3',
 'revisionasof' => 'Revision de $1',
 'revision-info' => 'Revision de $1 e il ha fabricat de $2',
-'previousrevision' => '← Revision antiqui',
+'previousrevision' => '← Anteyan version',
 'nextrevision' => 'Revision sequent →',
 'currentrevisionlink' => 'Ultim revision',
 'cur' => 'hod',
@@ -581,17 +612,17 @@ Tis argumentes have esset omisset.",
 Legende: '''({{int:cur}})''' = diferenties che ultim revision, '''({{int:last}})''' = diferenties que antecede li revision, '''{{int:minoreditletter}}''' = redaction minori.",
 'history-fieldset-title' => 'Historie de navigation',
 'history-show-deleted' => 'Deletet solmen',
-'histfirst' => 'Plu antiqui',
-'histlast' => 'Plu recent',
+'histfirst' => 'max veľi',
+'histlast' => 'max nov',
 
 # Revision feed
 'history-feed-item-nocomment' => '$1 in $2',
 
 # Revision deletion
 'rev-delundel' => 'monstrar/ocultar',
-'revdel-restore' => 'change visibilitá',
-'revdel-restore-deleted' => 'revisiones deletet',
-'revdel-restore-visible' => 'revisiones visibil',
+'revdel-restore' => 'changer visibilitá',
+'revdel-restore-deleted' => 'deletet revisiones',
+'revdel-restore-visible' => 'visibil revisiones',
 
 # Suppression log
 'suppressionlog' => 'Diarium de supression',
@@ -609,19 +640,19 @@ Vider li [[Special:IPBlockList|liste de bloc de IP]] por li liste de bloces e ba
 'diff-multi' => '({{PLURAL:$1|Un revision intermediari|$1 revisiones intermediari}} per {{PLURAL:$2|un usator|$2 usatores}} ne monstrat)',
 
 # Search results
-'searchresults' => 'Serchar resultates',
-'searchresults-title' => 'Serchar resultates por "$1"',
+'searchresults' => 'Serch-resultates',
+'searchresults-title' => 'Serch-resultates por «$1»',
 'toomanymatches' => 'Anc mult concurses esset retornat, pleser prova un question diferent',
 'titlematches' => 'Resultates in li titules de págines',
 'textmatches' => 'Resultates in textu de págines',
-'prevn' => '{{PLURAL:$1|$1}} anteriori',
-'nextn' => 'proxim {{PLURAL:$1|$1}}',
-'prevn-title' => 'Anteriori $1 {{PLURAL:$1|resultate|resultates}}',
-'nextn-title' => 'Proxim $1 {{PLURAL:$1|resultate|resultates}}',
+'prevn' => 'anteyan {{PLURAL:$1|$1}}',
+'nextn' => 'secuent {{PLURAL:$1|$1}}',
+'prevn-title' => 'Anteyan $1 {{PLURAL:$1|resultate|resultates}}',
+'nextn-title' => 'Secuent $1 {{PLURAL:$1|resultate|resultates}}',
 'shown-title' => 'Monstrar $1 {{PLURAL:$1|resultate|resultates}} per págine',
-'viewprevnext' => 'Vider ($1 {{int:pipe-separator}} $2) ($3)',
+'viewprevnext' => 'Monstrar ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''Vi un págine nominat \"[[:\$1]]\" in ti wiki.'''",
-'searchmenu-new' => "'''Crear li págine \"[[:\$1]]\" in ti wiki!'''",
+'searchmenu-new' => "'''Crear li págine «[[:$1]]» in ti wiki.'''",
 'searchprofile-articles' => 'Págines de contenete',
 'searchprofile-project' => 'Auxilie e Págines de projecte',
 'searchprofile-images' => 'Multimedia',
@@ -629,24 +660,23 @@ Vider li [[Special:IPBlockList|liste de bloc de IP]] por li liste de bloces e ba
 'searchprofile-advanced' => 'Avansat',
 'searchprofile-articles-tooltip' => 'Serchar in $1',
 'searchprofile-project-tooltip' => 'Serchar in $1',
-'searchprofile-images-tooltip' => 'Serchar por files',
-'searchprofile-everything-tooltip' => 'Serchar omni li contenete (includent págines de discussion)',
-'searchprofile-advanced-tooltip' => 'Serchar in spacies de nómine de hábitu',
+'searchprofile-images-tooltip' => 'Serchar files',
+'searchprofile-everything-tooltip' => 'Serchar in li tot contenete (includent págines de conversation)',
+'searchprofile-advanced-tooltip' => 'Serchar in special spacies de nómine',
 'search-result-size' => '$1 ({{PLURAL:$2|1 parol|$2 paroles}})',
 'search-result-category-size' => '{{PLURAL:$1|1 membre|$1 membres}} ({{PLURAL:$2|1 subcategory|$2 subcategories}}, {{PLURAL:$3|1 file|$3 files}})',
-'search-redirect' => '(redirectet de $1)',
-'search-section' => '(division $1)',
-'search-suggest' => 'Vu intentet: $1',
+'search-redirect' => '(redirection de «$1»)',
+'search-section' => '(section $1)',
+'search-suggest' => 'Esque tu ha intentet: «$1»?',
 'searchrelated' => 'relatet',
-'searchall' => 'Omni',
-'showingresultsheader' => "{{PLURAL:$5|Resultate '''$1''' de '''$3'''|Resultates '''$1 - $2''' de '''$3'''}} por '''$4'''",
-'search-nonefound' => 'Ne esset constatat resultates por li question.',
+'searchall' => 'omni',
+'showingresultsheader' => "{{PLURAL:$5|Resultate '''$1''' de '''$3'''|Resultates '''$1  $2''' de '''$3'''}} por '''$4'''",
+'search-nonefound' => 'Tu sercha ne ha trovat un resultate.',
 'powersearch' => 'Serchar avansat',
 
 # Preferences page
 'preferences' => 'Preferenties',
-'mypreferences' => 'Mi preferenties',
-'prefsnologin' => 'Vu ne ha intrat',
+'mypreferences' => 'Preferenties',
 'changepassword' => 'Modificar passa-parol',
 'skin-preview' => 'Prevision',
 'saveprefs' => 'Conservar',
@@ -738,21 +768,21 @@ Tui adresse de e-mail ne es revelat quande altri usatores contacter vu.',
 'rclinks' => 'Monstrar li $1 ultim modificationes fat durante li $2 ultim dies<br />$3.',
 'diff' => 'dif',
 'hist' => 'hist',
-'hide' => 'Ocultar',
+'hide' => 'Celar',
 'show' => 'Monstrar',
 'minoreditletter' => 'm',
 'newpageletter' => 'N',
 'boteditletter' => 'b',
-'rc-enhanced-expand' => 'Monstar detallies (exige JavaScript)',
+'rc-enhanced-expand' => 'Monstrar detaľes (per JavaScript)',
 'rc-enhanced-hide' => 'Ocultar detallies',
 
 # Recent changes linked
 'recentchangeslinked' => 'Changes referet',
 'recentchangeslinked-feed' => 'Relatet modificationes',
-'recentchangeslinked-toolbox' => 'Changes referet',
+'recentchangeslinked-toolbox' => 'Changes in referentiat págines',
 'recentchangeslinked-title' => 'Changes relatet por "$1"',
-'recentchangeslinked-summary' => "Ti es un liste de changes fat recentmen por págines ligat de un págine specificat (o por membres de un categorie specificat).
-Págines in [[Special:Watchlist|tui liste de págines vigilat]] es '''nigri'''.",
+'recentchangeslinked-summary' => "To es un liste del nov changes in li referentiat págines (respectivmen in li membres del categorie).
+Págines in [[Special:Watchlist|tui liste de vigilat págines]] es '''nigri'''.",
 'recentchangeslinked-page' => 'Nómine de págine:',
 'recentchangeslinked-to' => 'Monstrar changes por págines ligat por li págine disposit in vice',
 
@@ -826,22 +856,22 @@ Vu posse provar in un témpor minu activ.',
 
 # File description page
 'file-anchor-link' => 'Figura',
-'filehist' => 'Historic de figura',
-'filehist-help' => 'Clacca in un date/témpor por vider li file quam it aparit in ti témpor.',
+'filehist' => 'Versiones del file',
+'filehist-help' => 'Clacca a un date/témpore por vider ti version.',
 'filehist-revert' => 'reverter',
-'filehist-current' => 'current',
-'filehist-datetime' => 'Date/Témpor',
+'filehist-current' => 'actual',
+'filehist-datetime' => 'Version de',
 'filehist-thumb' => 'Miniatura',
-'filehist-thumbtext' => 'Miniatura por version quam de $1',
+'filehist-thumbtext' => 'Miniatura por li version de $2, clocca $3',
 'filehist-user' => 'Usator',
 'filehist-dimensions' => 'Dimensiones',
 'filehist-filesize' => 'Mesura de file',
-'filehist-comment' => 'Comentarie',
-'imagelinks' => 'Usu del file',
+'filehist-comment' => 'Commentarie',
+'imagelinks' => 'Usada del file',
 'linkstoimage' => 'Li sequent {{PLURAL:$1|catenun de págine|$1 catenunes de págines}} por ti file:',
 'nolinkstoimage' => 'Hay nequant págine que liga por ti file.',
-'sharedupload-desc-here' => 'Ti file es de $1 e posse esser usat per altri projectes.
-Li descrition es in li [$2 págine de descrition del file] ta e es monstrat in infra.',
+'sharedupload-desc-here' => 'Ti file es de $1 e posse esser usat de altri projectes.
+Li descrition in su [$2 págine de descrition] es monstrat in infra.',
 'uploadnewversion-linktext' => 'Cargar un nov version de ti file',
 
 # File deletion
@@ -862,7 +892,7 @@ Li descrition es in li [$2 págine de descrition del file] ta e es monstrat in i
 'unusedtemplateswlh' => 'altri catenunes',
 
 # Random page
-'randompage' => 'Págine sporadic',
+'randompage' => 'Págine in hasard',
 
 # Statistics
 'statistics' => 'Statistica',
@@ -942,11 +972,11 @@ Li descrition es in li [$2 págine de descrition del file] ta e es monstrat in i
 
 # Special:AllPages
 'allpages' => 'Omni li págines',
-'alphaindexline' => '$1 til $2',
+'alphaindexline' => '$1 till $2',
 'nextpage' => 'Proxim págine ($1)',
 'prevpage' => 'Ultim págine ($1)',
 'allarticles' => 'Omni li articules',
-'allpagessubmit' => 'Ear',
+'allpagessubmit' => 'Applicar',
 
 # Special:Categories
 'categories' => 'Categories',
@@ -973,8 +1003,8 @@ Li descrition es in li [$2 págine de descrition del file] ta e es monstrat in i
 'usermessage-template' => 'MediaWiki:UserMessage',
 
 # Watchlist
-'watchlist' => 'Liste de págines vigilat',
-'mywatchlist' => 'Mi liste de págines vigilat',
+'watchlist' => 'Vigilat págines',
+'mywatchlist' => 'Vigilat págines',
 'watchlistfor2' => 'Por $1 $2',
 'watchlistanontext' => 'Pleser $1 por vider o redacter articules in tui liste de págines vigilat.',
 'watchnologin' => 'Vu ne ha intrat',
@@ -1081,11 +1111,11 @@ $1',
 'blanknamespace' => '(Principal)',
 
 # Contributions
-'contributions' => 'Contributiones de usator',
+'contributions' => 'Contributiones de {{GENDER:$1|usator|usatoressa}}',
 'contributions-title' => 'Contributiones de usator por $1',
-'mycontris' => 'Mi contributiones',
-'contribsub2' => 'Por $1 ($2)',
-'uctop' => '(prim)',
+'mycontris' => 'Contributiones',
+'contribsub2' => 'De {{GENDER:$3|$1}} ($2)',
+'uctop' => '(actual)',
 'month' => 'De mensu (e anterioris):',
 'year' => 'De annu (e anterioris):',
 
@@ -1101,35 +1131,35 @@ $1',
 'sp-contributions-submit' => 'Serchar',
 
 # What links here
-'whatlinkshere' => 'Quo catenunes ci',
+'whatlinkshere' => 'Referenties a ti-ci págine',
 'whatlinkshere-title' => 'Págines quo liga por "$1"',
 'whatlinkshere-page' => 'Págine:',
 'linkshere' => "Li sequent págines liga por '''[[:$1]]''':",
 'nolinkshere' => "Nequant págine liga por '''[[:$1]]'''.",
 'isredirect' => 'págine de redirecterion',
 'istemplate' => 'inclusion',
-'isimage' => 'catenun de figura',
+'isimage' => 'referentie a un file',
 'whatlinkshere-prev' => '{{PLURAL:$1|anterior|$1 anterioris}}',
 'whatlinkshere-next' => '{{PLURAL:$1|proxim|proxim $1}}',
 'whatlinkshere-links' => '← catenunes',
 'whatlinkshere-hideredirs' => '$1 redirectiones',
 'whatlinkshere-hidetrans' => '$1 transclusiones',
 'whatlinkshere-hidelinks' => '$1 catenunes',
-'whatlinkshere-hideimages' => '$1 catenunes de figura',
+'whatlinkshere-hideimages' => '$1 referenties a picturas.',
 'whatlinkshere-filters' => 'Filtres',
 
 # Block/unblock
 'blockip' => 'Blocar usator',
 'ipbreason' => 'Motive:',
-'ipboptions' => '2 hores:2 hours,1 die:1 day,3 dies:3 days,1 semane:1 week,2 semanes:2 weeks,1 mensu:1 month,3 mensues:3 months,6 mensues:6 months,1 annu:1 year,inprecise:infinite',
+'ipboptions' => '2 hores:2 hours,1 die:1 day,3 dies:3 days,1 semane:1 week,2 semanes:2 weeks,1 mensu:1 month,3 mensus:3 months,6 mensus:6 months,1 annu:1 year,ínfinit:infinite',
 'ipbotheroption' => 'altri',
 'ipblocklist' => 'Usatores blocat',
 'ipblocklist-submit' => 'Serchar',
 'infiniteblock' => 'infinit',
 'blocklink' => 'blocar',
 'unblocklink' => 'desblocar',
-'change-blocklink' => 'change bloc',
-'contribslink' => 'contribs',
+'change-blocklink' => 'changer blocada',
+'contribslink' => 'contributiones',
 'blocklogpage' => 'Diarium de bloc',
 'blocklogentry' => '"[[$1]]" hat blocat che un témpor de expiration de $2 $3',
 'block-log-flags-nocreate' => 'creation de conto debilisat',
@@ -1170,69 +1200,69 @@ Pleser fuse les manualmen.'''",
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'Tui págine de usator',
 'tooltip-pt-anonuserpage' => 'Li págine de usator por li adresse de IP vu es redactent quam',
-'tooltip-pt-mytalk' => 'Tui págine de discussion',
+'tooltip-pt-mytalk' => 'Tui págine de conversation',
 'tooltip-pt-anontalk' => 'Discussion pri redactiones de adresses de IP',
 'tooltip-pt-preferences' => 'Tui preferenties',
-'tooltip-pt-watchlist' => 'Li liste de págines quo vu controla li changes',
+'tooltip-pt-watchlist' => 'Liste de vigilat págines',
 'tooltip-pt-mycontris' => 'Liste de tui contributiones',
-'tooltip-pt-login' => 'Vu es incorageat por crear un conto; támen, it ne esser mandatorio',
+'tooltip-pt-login' => 'Tu es incorrageat crear un conto, ma to ne es un deventie.',
 'tooltip-pt-anonlogin' => 'Vu es incorageat por crear un conto; támen, it ne esser mandatorio',
-'tooltip-pt-logout' => 'Surtida',
-'tooltip-ca-talk' => 'Discussion pri li contenete de págine',
-'tooltip-ca-edit' => 'Vu posse redacter ti págine. Pleser usar li buton "Monstrar prevision" ante de conservar',
-'tooltip-ca-addsection' => 'Comensar un nov division',
-'tooltip-ca-viewsource' => 'Ti págine es gardat. Vu posse vider li contenete',
-'tooltip-ca-history' => 'Revisiones passat de ti págine',
+'tooltip-pt-logout' => 'Surtir',
+'tooltip-ca-talk' => 'Discussion pri li articul.',
+'tooltip-ca-edit' => 'Redacter ti págine. Ples usar li buton de prevision antequam conservar.',
+'tooltip-ca-addsection' => 'Comensar un nov section',
+'tooltip-ca-viewsource' => 'Ti págine es protectet. Ma tu posse vider e copiar su fonte.',
+'tooltip-ca-history' => 'Passat versiones de ti págine',
 'tooltip-ca-protect' => 'Gardar ti págine',
 'tooltip-ca-unprotect' => 'Desgardar ti págine',
 'tooltip-ca-delete' => 'Deleter ti págine',
 'tooltip-ca-undelete' => 'Restaurar li redactiones executet pro ti págine ante de it esser deletet',
 'tooltip-ca-move' => 'Mover ti págine',
-'tooltip-ca-watch' => 'Adjunter ti págine pro tui liste de págines vigilat',
+'tooltip-ca-watch' => 'Adjunter ti págine a tui liste de vigilat págines',
 'tooltip-ca-unwatch' => 'Desvigilar ti págine de tui liste de págines vigilat',
 'tooltip-search' => 'Serchar {{SITENAME}}',
 'tooltip-search-go' => 'Ear por un págine che ti nómine exact, si it exister',
-'tooltip-search-fulltext' => 'Serchar págines che ti textu',
-'tooltip-p-logo' => 'Visita li págine principal',
-'tooltip-n-mainpage' => 'Visita li págine principal',
-'tooltip-n-mainpage-description' => 'Visita li págine principal',
-'tooltip-n-portal' => 'Pri li projecte, quo vu posse executer, u constatar coses',
-'tooltip-n-currentevents' => 'Constata funde de information sur eventus current',
-'tooltip-n-recentchanges' => 'Li liste de nov changes vice wiki',
-'tooltip-n-randompage' => 'Cargar un págine sporadic',
-'tooltip-n-help' => 'Li loco por constatar auxilie',
-'tooltip-t-whatlinkshere' => 'Liste de omni págines que liga quel por ci',
-'tooltip-t-recentchangeslinked' => 'Nov changes in págines ligat in ti págine',
+'tooltip-search-fulltext' => 'Serchar págines, queles contene ti textu',
+'tooltip-p-logo' => 'Principal págine',
+'tooltip-n-mainpage' => 'Monstrar li principal págine',
+'tooltip-n-mainpage-description' => 'Visitar li principal págine',
+'tooltip-n-portal' => 'Pri li projecte, quo tu posse far, u tu posse trovar alquó',
+'tooltip-n-currentevents' => 'Fundal informationes pri actual evenimentes',
+'tooltip-n-recentchanges' => 'Liste de nov changes in li wiki',
+'tooltip-n-randompage' => 'Cargar un págine in hasard',
+'tooltip-n-help' => 'Monstrar un págine de auxilie',
+'tooltip-t-whatlinkshere' => 'Liste de omni págines ligant a ci.',
+'tooltip-t-recentchangeslinked' => 'Nov changes in págines ligat fro ti págine',
 'tooltip-feed-rss' => 'Feed RSS por ti págine',
 'tooltip-feed-atom' => 'Feed atom por ti págine',
 'tooltip-t-contributions' => 'Vider li liste de contributiones de ti usator',
 'tooltip-t-emailuser' => 'Inviar un e-mail por ti usator',
 'tooltip-t-upload' => 'Cargar files',
-'tooltip-t-specialpages' => 'Liste de omni págines special',
-'tooltip-t-print' => 'Version por impression de ti págine',
-'tooltip-t-permalink' => 'Catenun permanent por ti revision de págine',
-'tooltip-ca-nstab-main' => 'Vider li págine de contenete',
+'tooltip-t-specialpages' => 'Liste de omni special págines',
+'tooltip-t-print' => 'Printabil version de ti-ci págine',
+'tooltip-t-permalink' => 'Permanent referentie a ti version del págine',
+'tooltip-ca-nstab-main' => 'Vider li articul',
 'tooltip-ca-nstab-user' => 'Vider li págine de usator',
 'tooltip-ca-nstab-media' => 'Vider li págine de media',
 'tooltip-ca-nstab-special' => 'Ti es un págine special, vu ne posse redacter it',
 'tooltip-ca-nstab-project' => 'Vider li págine de projecte',
 'tooltip-ca-nstab-image' => 'Vider li págine de figura',
 'tooltip-ca-nstab-mediawiki' => 'Vider li missage de sistema',
-'tooltip-ca-nstab-template' => 'Vider li avise',
+'tooltip-ca-nstab-template' => 'Monstrar li shablone',
 'tooltip-ca-nstab-help' => 'Vider li págine de auxilie',
-'tooltip-ca-nstab-category' => 'Vider li págine de categorie',
+'tooltip-ca-nstab-category' => 'Monstrar li categorial págine',
 'tooltip-minoredit' => 'Marcar to ci quam un redaction minori',
 'tooltip-save' => 'Conservar tui changes',
-'tooltip-preview' => 'Monstrar tui changes, pleser usar ante de conservar!',
+'tooltip-preview' => 'Previder tui changes. Ples usar to antequam conservar!',
 'tooltip-diff' => 'Monstrar quel changes vu executet in li textu',
 'tooltip-compareselectedversions' => 'Vider li differenties inter li du revisiones selectet de ti págine',
 'tooltip-watch' => 'Adjunter ti págine por tui liste de págines vigilat',
 'tooltip-recreate' => 'Recrear li págine por plan anteriori de delete',
 'tooltip-upload' => 'Comensar cargament de file',
-'tooltip-rollback' => '"Rollback" reverte redaction(es) de ti págine executet per li ultim contributor in un claccar',
-'tooltip-undo' => '"Undo" reverte ti redaction e inaugura li forme de redaction in modo de prevision. It concede adjuntent un rason in li summarium.',
+'tooltip-rollback' => 'Desfá omni ultim changes del págine, queles ha esset executet del sam usator, per un sol clacca',
+'tooltip-undo' => '«Desfar» reverte solmen ti-ci redaction e monstra li resultate in prevision, porque tu posse indicar un rason in li linea de resumé.',
 'tooltip-preferences-save' => 'Conservar preferenties',
-'tooltip-summary' => 'Intrar un summarium curt',
+'tooltip-summary' => 'Ples intrar un curt resummation.',
 
 # Stylesheets
 'vector.css' => '/* CSS colocat ci va afectar usatores de pelle Vector */',
@@ -1250,7 +1280,7 @@ Pleser fuse les manualmen.'''",
 'file-info-size' => '$1 × $2 pixeles, dimension de file: $3, tip MIME: $4',
 'file-nohires' => 'Nequant resolution max alt disponibil.',
 'svg-long-desc' => '(file SVG, nominalmen $1 × $2 pixeles, mesura de file: $3)',
-'show-big-image' => 'Resolution complet',
+'show-big-image' => 'Original file',
 
 # Special:NewFiles
 'newimages' => 'Galerie de nov images',
@@ -1260,11 +1290,11 @@ Pleser fuse les manualmen.'''",
 'video-dims' => '$1, $2×$3',
 
 # Bad image list
-'bad_image_list' => 'Li formate es quam seque:
+'bad_image_list' => 'Formate:
 
-Solmen listar detallies (lineas comensant che *) es considerat.
-Li prim catenun in un linea deve esser un catenun por un file maliciosi.
-Alqual catenunes subsequent in li linea identic es considerat por esser exceptiones, i.e. págines u li file posse ocurrer in linea identic.',
+Solmen lineas comensant per un * es considerat.
+Strax pos li * deve secuer un referentie a un mal file.
+Secuent referenties in li sam linea defini exceptiones, u li file es leyalmen monstrat.',
 
 # Metadata
 'metadata' => 'Metadata',
@@ -1287,7 +1317,7 @@ Altri va esser ocultat per contumacie.
 
 # External editor support
 'edit-externally' => 'Redacter ti file usant un aplication extern',
-'edit-externally-help' => '(Vider li [//www.mediawiki.org/wiki/Manual:External_editors instructiones de installation] por plu information)',
+'edit-externally-help' => '(Vide li [https://www.mediawiki.org/wiki/Manual:External_editors instructiones de installation] por plu mult information)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'omni',
@@ -1360,7 +1390,7 @@ Vu posse anc [[Special:EditWatchlist|usar li redactor uniform]].',
 'version-software-version' => 'Version',
 
 # Special:SpecialPages
-'specialpages' => 'Págines special',
+'specialpages' => 'Special págines',
 'specialpages-group-maintenance' => 'Raportes de conservation',
 'specialpages-group-other' => 'Altri págines special',
 'specialpages-group-login' => 'Intrar / crear conto',
index d80520c..626ea8d 100644 (file)
@@ -331,8 +331,6 @@ Lé [[Special:Version|ụdì ihü]].',
 'ok' => 'Ngwanu',
 'retrievedfrom' => "Wefụtàrà ya shí ''$1''",
 'youhavenewmessages' => 'I nwèrè $1 ($2).',
-'newmessageslink' => 'Ozi ohúrù',
-'newmessagesdifflink' => 'mkpete azu ihe gbanwere',
 'youhavenewmessagesmulti' => 'Inwere eziohu na $1',
 'editsection' => 'mèzi',
 'editold' => 'mèzi',
@@ -746,7 +744,6 @@ Nwàné ótù okwu íshí na ihe Í nè tú jí ''háníle:'' Í tuó ihe nílé
 # Preferences page
 'preferences' => 'Otu ha dosẹrẹ ihe',
 'mypreferences' => 'Otú m shị na dose ihem',
-'prefsnologin' => 'I bátà bò',
 'changepassword' => 'Gbanwe okwu éjị à gáfe',
 'prefs-skin' => 'Akpụkpọ',
 'skin-preview' => 'Lètú',
@@ -865,6 +862,7 @@ Nwàné ótù okwu íshí na ihe Í nè tú jí ''háníle:'' Í tuó ihe nílé
 'recentchanges-legend' => 'Nràlụ màkà Ihe gbanwere ubwá',
 'recentchanges-feed-description' => 'Chóputà ihe ógẹ ǹsò na wiki ímé órírí nke á.',
 'recentchanges-label-minor' => 'Ihe bu orü ntakírí',
+'recentchanges-legend-newpage' => '$1 - ihü ohúrù',
 'rcnote' => "Na àlà {{PLURAL:$1|bu gbanwere '''1'''|bu gbanwere mgbèdè nke '''$1'''}} na mgbèdè {{PLURAL:$2|chi|chi '''$2'''}}, na mgbe $5, $4.",
 'rclistfrom' => 'Zìrí ihe gbanwere ọhúrù shí $1',
 'rcshowhideminor' => 'orü ntákírí $1',
@@ -1607,7 +1605,7 @@ Nke ozor gí zonari na áká onwe ha.
 
 # External editor support
 'edit-externally' => 'Rüo na élú usòrò nke na ngwa ọrụ nsónùsòrò nke ọzȯ',
-'edit-externally-help' => '(Lé nà [//www.mediawiki.org/wiki/Manual:External_editors nkụzí mbídó] màkà nkúzí ozor)',
+'edit-externally-help' => '(Lé nà [https://www.mediawiki.org/wiki/Manual:External_editors nkụzí mbídó] màkà nkúzí ozor)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'nke níle',
@@ -1738,4 +1736,7 @@ Nke ozor gí zonari na áká onwe ha.
 # Search suggestions
 'searchsuggest-search' => 'Chọwa',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Ngwanu',
+
 );
index 3449654..68acfcc 100644 (file)
@@ -252,7 +252,7 @@ $messages = array(
 'articlepage' => 'Kitaen ti naglaon a panid',
 'talk' => 'Pagtungtungan',
 'views' => 'Dagiti pangkitaan',
-'toolbox' => 'Kahon ti ramit',
+'toolbox' => 'Ramramit',
 'userpage' => 'Kitaen ti panid ti agar-aramat',
 'projectpage' => 'Kitaen ti panid ti gandat',
 'imagepage' => 'Kitaen ti panid ti papeles',
@@ -309,8 +309,6 @@ Kitaen ti [[Special:Version|panid ti bersion]].',
 'ok' => 'Sige',
 'retrievedfrom' => 'Naala manipud idiay "$1"',
 'youhavenewmessages' => 'Addaanka ti $1 ($2).',
-'newmessageslink' => 'dagiti baro a mensahe',
-'newmessagesdifflink' => 'naudi a sinukatan',
 'youhavenewmessagesfromusers' => 'Adda $1 manipud {{PLURAL:$3|ti sabali nga agar-aramat|kadagiti $3 a sabsabali nga agar-aramat}} ($2).',
 'youhavenewmessagesmanyusers' => 'Adda $1 manipud kadagiti adu nga agar-aramat ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|baro a mensahem|dagiti baro a mensahem}}',
@@ -495,9 +493,12 @@ Dimo liplipatan a sukatan dagiti kakaykayatam idiay [[Special:Preferences|{{SITE
 'gotaccount' => 'Addaanka kadin ti pakabilangam? $1.',
 'gotaccountlink' => 'Sumrek',
 'userlogin-resetlink' => 'Nalipatam dagiti salaysay ti pagserrekmo?',
-'userlogin-resetpassword-link' => 'Iyasentar manen ti kontrasenias',
+'userlogin-resetpassword-link' => 'Nalipatam ti kontraseniasmo?',
 'helplogin-url' => 'Help:Panagserrek',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Tulong iti panagserrek]]',
+'userlogin-loggedin' => 'Nakastrekkan a kas ni {{GENDER:$1|$1}}.
+Usaren ti porma dita baba tapno sumrek a kas sabali nga agar-aramat.',
+'userlogin-createanother' => 'Agaramid pay ti sabali a pakabilangan',
 'createacct-join' => 'Ikabil ti pakaammom dita baba.',
 'createacct-another-join' => 'Ikabil ti pakaammo ti baro a pakabilangan dita baba.',
 'createacct-emailrequired' => 'Esurat a pagtaengan',
@@ -565,16 +566,16 @@ No sabali ti nagkiddaw, wenno no malagipmo pay ti kontrasenias mo ket dimon kaya
 'passwordsent' => 'Naipatuloden ti baro a kontrasenias iti esurat a pagtaengan a nairehistro kenni "$1".
 Pangngaasi a sumrekka manen kalpasan ti pannakaawatmo.',
 'blocked-mailpassword' => 'Ti IP a pagtaengam ket naserraan manipud ti panag-urnos, isunga saan a mapalubosan nga agusar ti annong ti panagipulang ti kontrasenias tapno mapawilan ti panag-abuso.',
-'eauthentsent' => 'Naipatuloden ti pammasingked nga esurat iti naited nga esurat a pagtaengan.
-Sakbay ti ania man nga esurat ti maipatulod iti pakabilangan, masapul a surotem dagiti maibagbaga iti esurat, tapno mapasingkedan a ti pakabilangan ket agpayso a kukuam.',
+'eauthentsent' => 'Naipatuloden ti pammatalged nga esurat iti naikeddeng nga esurat a pagtaengan.
+Sakbay a maipatulod ti aniaman nga esurat iti pakabilangan, masapul a surotem dagiti maibagbaga iti esurat, tapno mapatalgedan ti pakabilangan ket agpayso a kukuam.',
 'throttled-mailpassword' => 'Ti panangiyasentar manen ti kontrasenias ket naipatuloden, iti kaunegan ti napalabas a {{PLURAL:$1|nga oras|$1 nga or-oras}}.
 Tapno maipawilan ti panag-abuso, maysa laeng a panangiyasentar manen ti kontrasenias ti maipatulod iti kada {{PLURAL:$1|nga oras|$1 nga or-oras}}.',
 'mailerror' => 'Biddut iti panangipatulod ti surat: $1',
 'acct_creation_throttle_hit' => 'Dagiti sumarungkar ti daytoy a wiki nga agus-usar ti IP a pagtaengan ket nakaaramid {{PLURAL:$1|iti 1 a pakabilangan|kadagiti $1 a pakabilangan}} iti nasakbayan nga aldaw, nga isu laeng ti kaadu a maipalubos iti daytoy a paset ti panawen.
 A kas ti nagbanagan, dagiti agsarsarungkar nga agus-usar ti IP a pagtaengan ket agdama a saanda a mabalin a makaaramid kadagiti pakabilangan.',
-'emailauthenticated' => 'Napasingkedan ti esurat a pagtaengan idi $2 idi $3.',
-'emailnotauthenticated' => 'Saan pay a napasingkedan ti esuratmo.
-Awan ti esurat a naipatulod para kadagiti sumaganad a langa.',
+'emailauthenticated' => 'Ti esurat a pagtaengam ket napatalgedan idi $2 idi $3.',
+'emailnotauthenticated' => 'Saan pay a napatalgedan ti esuratmo a pagtaengan.
+Awanto ti esurat a maipatulod para kadagiti sumaganad a langa.',
 'noemailprefs' => 'Ipanaganan ti esurat a pagtaengan tapno agbalin dagitoy a langa.',
 'emailconfirmlink' => 'Pasingkedam ti esurat a pagtaengam',
 'invalidemailaddress' => 'Ti esurat a pagtaengan ket saan a maawat ngamin ket kasla adda ti saan a napudno a porma.
@@ -1027,15 +1028,15 @@ Dagiti sabsabali nga administrador idiay {{SITENAME}} ket mabalinda a serrekan t
 * Di maiparbeng a  kabukbukodan a pakaammo
 * : ''dagiti pagtaengan ken numero ti telepono, numero ti sosial a seguridad, ken dadduma pay.''",
 'revdelete-legend' => 'Ikabil dagiti panagiparit ti panagkita',
-'revdelete-hide-text' => 'Ilemmeng ti testo ti binaliwan',
+'revdelete-hide-text' => 'Testo ti binaliwan',
 'revdelete-hide-image' => 'Ilemmeng ti linaon ti papeles',
 'revdelete-hide-name' => 'Ilemmeng ti aramid ken puntaan',
-'revdelete-hide-comment' => 'Ilemmeng ti pakabuklan ti inurnos',
-'revdelete-hide-user' => 'Ilemmeng ti nagan ti agar-amat/ti IP a pagtaengan',
+'revdelete-hide-comment' => 'Pakabuklan ti inurnos',
+'revdelete-hide-user' => 'Nagan ti agar-amat/ti IP a pagtaengan',
 'revdelete-hide-restricted' => 'Depdepen ti datos a naggapu kadagiti administrador ken dagiti sabsabali',
 'revdelete-radio-same' => '(saan a sukatan)',
-'revdelete-radio-set' => 'Wen',
-'revdelete-radio-unset' => 'Saan',
+'revdelete-radio-set' => 'Makita',
+'revdelete-radio-unset' => 'Nailemmeng',
 'revdelete-suppress' => 'Depdepen ti datos manipud kadagiti administrador ken dagiti sabsabali',
 'revdelete-unsuppress' => 'Ikkaten dagiti pannakaiparit kadagiti naisubli a binaliwan',
 'revdelete-log' => 'Rason:',
@@ -1193,8 +1194,6 @@ Laglagipem laeng a dagiti pagsurotan nagyan ti {{SITENAME}} ket baka baak.',
 'preferences' => 'Kakaykayatan',
 'mypreferences' => 'Kakaykayatan',
 'prefs-edits' => 'Bilang dagiti inurnos:',
-'prefsnologin' => 'Saan a nakastrek',
-'prefsnologintext' => 'Masapul a <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} nakastrekka]</span> tapno makapili kadagiti kakaykayatam.',
 'changepassword' => 'Baliwan ti kontrasenias',
 'prefs-skin' => 'Kudil',
 'skin-preview' => 'Ipadas',
@@ -2265,10 +2264,12 @@ Kitaen ti $2 para iti pannakrehistro dagiti naudi a naikkat.',
 'deletecomment' => 'Rason:',
 'deleteotherreason' => 'Sabali/maipatinayon a rason:',
 'deletereasonotherlist' => 'Sabali a rason',
-'deletereason-dropdown' => '*Kadawyan a rasrason ti panagikkat
-** Kiddaw ti mannurat
+'deletereason-dropdown' => '* Kadawyan a rasrason ti panagikkat
+** Spam
+** Bandalismo
 ** Panaglabsing iti karbengan ti panagipablaak
-** Bandalismo',
+** Kiddaw ti mannurat
+** Naputed a baw-ing',
 'delete-edit-reasonlist' => 'Urnosen dagiti rason ti panagikkat',
 'delete-toobig' => 'Daytoy a panid ket dakkel ti pakasaritaanna, sumurok a  $1 {{PLURAL:a panagbaliwan|dagiti panagbaliwan}}.
 Ti panagikkat ti kastoy a pammpanid ket naparitan tapno mapawilan ti saan nga inkarkaro a pannakadadael ti {{SITENAME}}.',
@@ -2754,7 +2755,7 @@ No iti kinaudi a kaso mabalinmo nga usaren ti silpo, a kas pagarigan [[{{#Specia
 'allmessagesdefault' => 'Kasisigud a testo ti mensahe',
 'allmessagescurrent' => 'Agdama a testo ti mensahe',
 'allmessagestext' => 'Daytoy ti listaan dagiti mensahe ti sistema a magun-od idiay MediaWiki a nagan ti espasio.
-Pangngaasi a bisitaen ti [//www.mediawiki.org/wiki/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.',
+Pangngaasi a bisitaen ti [https://www.mediawiki.org/wiki/Localisation Lokalisasion ti MediaWiki] ken [//translatewiki.net translatewiki.net] no kayatmo ti agparawad kadagiti sapasap a panagipatarus ti MediaWiki.',
 'allmessagesnotsupportedDB' => "Saan a mausar daytoy a panid ngamin ket ti '''\$wgUseDatabaseMessages''' ket nabaldado.",
 'allmessages-filter-legend' => 'Sagat',
 'allmessages-filter' => 'Sagaten babaen ti naipaduma a kasasaad:',
@@ -2945,6 +2946,8 @@ Daytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a pagsaada
 'spam_reverting' => 'Ipasubli ti kinaudi a panagbaliw nga awan dagiti linaon a silpo idiay $1',
 'spam_blanking' => 'Dagiti amin a panagbaliw ket aglaon kadagiti silpo idiay $1, iblanko',
 'spam_deleting' => 'Dagiti amin a panagbaliw ket naglaon kadagiti silpo idiay $1, ik-ikkaten',
+'simpleantispam-label' => "Kontra-spam a panagkita.
+ '''Saan''' a suratan daytoy!",
 
 # Info page
 'pageinfo-title' => 'Pakaammo para iti "$1"',
@@ -2958,6 +2961,7 @@ Daytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a pagsaada
 'pageinfo-length' => 'Kaatiddog ti panid (kadagiti byte)',
 'pageinfo-article-id' => 'ID ti panid',
 'pageinfo-language' => 'Pagsasao ti naglaon a panid',
+'pageinfo-content-model' => 'Modelo ti linaon ti panid',
 'pageinfo-robot-policy' => 'Panagpasurot babaen dagiti robot',
 'pageinfo-robot-index' => 'Maipalubos',
 'pageinfo-robot-noindex' => 'Saan a maipalubos',
@@ -2978,7 +2982,7 @@ Daytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a pagsaada
 'pageinfo-magic-words' => 'Salamangka  {{PLURAL:$1|a balikas|a balbalikas}} ($1)',
 'pageinfo-hidden-categories' => 'Nailemmeng {{PLURAL:$1|a kategoria|a katkategoria}} ($1)',
 'pageinfo-templates' => 'Nailak-am {{PLURAL:$1|a plantilia|a planplantilia}} ($1)',
-'pageinfo-transclusions' => '{{PLURAL:$1|A panid|A pampanid}} ti nailak-am idiay ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|Panid|Pampanid}} a nakailak-aman ($1)',
 'pageinfo-toolboxlink' => 'Pakaammo ti panid',
 'pageinfo-redirectsto' => 'Maibaw-ing idiay',
 'pageinfo-redirectsto-info' => 'pakaammo',
@@ -3500,7 +3504,7 @@ Dagiti dadduma ket mailemmeng a kinasigud.
 
 # External editor support
 'edit-externally' => 'Baliwan daytoy a papeles babaen ti akinruar nga aplikasion',
-'edit-externally-help' => '(Kitaen ti [//www.mediawiki.org/wiki/Manual:External_editors instruksion iti panangikabil] para iti ad-adu pay a pakaammo).',
+'edit-externally-help' => '(Kitaen ti [https://www.mediawiki.org/wiki/Manual:External_editors instruksion iti panangikabil] para iti ad-adu pay a pakaammo).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'amin',
@@ -3689,7 +3693,7 @@ Mabalinmo pay nga [[Special:EditWatchlist|usaren ti dati a panagurnos]].',
 'version-hook-subscribedby' => 'Umanamong babaen ti',
 'version-version' => '(Bersion $1)',
 'version-license' => 'Lisensia',
-'version-poweredby-credits' => "Daytoy a wiki ket pinaandar ti '''[//www.mediawiki.org/ MediaWiki]''', karbengan a kopia © 2001-$1 $2.",
+'version-poweredby-credits' => "Daytoy a wiki ket pinaandar ti '''[https://www.mediawiki.org/ MediaWiki]''', karbengan a kopia © 2001-$1 $2.",
 'version-poweredby-others' => 'dadduma pay',
 'version-poweredby-translators' => 'agipatpatarus ti translatewiki.net',
 'version-credits-summary' => 'Kayatmi koma a pammadayawan dagiti sumaganad a tao para kadagiti inparawadda iti [[Special:Version|MediaWiki]].',
@@ -3708,7 +3712,10 @@ Naka-awatka koman ti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU Sapasap a
 # Special:Redirect
 'redirect' => 'Ibaw-ing babaen ti papeles, agar-aramat, wenno ID ti panagbaliw',
 'redirect-legend' => 'Ibaw-ing iti papeles wenno panid',
-'redirect-summary' => 'Daytoy nga espesial a panid ket maibaw-ing iti papeles (iti nagan ti papeles), ti panid (iti ID ti panagbaliw), wenno ti panid ti agar-aramat (iti numeriko nga ID ti agar-aramat).',
+'redirect-summary' => 'Daytoy nga espesial a panid ket maibaw-ing iti papeles (iti nagan ti papeles), ti panid (iti ID ti panagbaliw), wenno ti panid ti agar-aramat (iti numeriko nga ID ti agar-aramat). Panag-usar:
+[[{{#Special:Redirect}}/file/Example.jpg]], 
+[[{{#Special:Redirect}}/revision/328429]], wenno
+[[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Inkan',
 'redirect-lookup' => 'Kitaen:',
 'redirect-value' => 'Pateg:',
@@ -3730,8 +3737,7 @@ Naka-awatka koman ti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopia iti GNU Sapasap a
 
 # Special:SpecialPages
 'specialpages' => 'Espesial a pampanid',
-'specialpages-note' => '----
-* Kadawyan nga espesial a pampanid.
+'specialpages-note' => '* Kadawyan nga espesial a pampanid.
 * <span class="mw-specialpagerestricted">Nagawidan nga espesial a pampanid.</span>',
 'specialpages-group-maintenance' => 'Dagiti padamag ti panagtaripato',
 'specialpages-group-other' => 'Sabsabali pay nga espesial a pampanid',
@@ -3945,4 +3951,21 @@ Nupay kasta, mau-sarmo ti nakabuklan dita baba. Ti komentario nga itedmo ket mai
 'limitreport-expansiondepth' => 'Kangatuan a panagpadakkel ti kauneg',
 'limitreport-expensivefunctioncount' => 'Bilang ti nangina nga annong ti parser',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Palawaen dagiti plantilia',
+'expand_templates_intro' => 'Daytoy nga espesial a panid ket agala ti testo ken palawaenna amin dagiti plantilia iti unegna a minaig iti daytoy.
+Palawaenna pay dagiti nasuportaran a parser a pamay-an a kas ti
+<code><nowiki>{{</nowiki>#language:…}}</code> ken dagiti nadumaduma a kita a kas ti
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. 
+Iti kinapudno, palawaenna amin dagiti adda ti doble a tukol.',
+'expand_templates_title' => 'Titulo ti kontesto, para iti {{FULLPAGENAME}} kdpy.:',
+'expand_templates_input' => 'Maikabil a testo:',
+'expand_templates_output' => 'Nagbanagan',
+'expand_templates_xml_output' => 'XML a maiparang',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Ikkaten dagiti komentario',
+'expand_templates_remove_nowiki' => 'Parmeken dagiti <nowiki> nga etiketa kadagiti nagbanagan',
+'expand_templates_generate_xml' => 'Iparang ti XML parse a kayo',
+'expand_templates_preview' => 'Pamadasan',
+
 );
index 0626ea7..378afdf 100644 (file)
@@ -213,7 +213,7 @@ $messages = array(
 'articlepage' => 'Йоазув тӀа бӀаргтасса',
 'talk' => 'Дувцам',
 'views' => 'БӀаргтассамаш',
-'toolbox' => 'Ð\93Ó\80орсаш',
+'toolbox' => 'Ð\93Ó\80ирсаш',
 'userpage' => 'Дакъалаьцачунна оагӀуве бӀаргтасса',
 'projectpage' => 'Хьахьоадайтама оагӀуве бӀаргтасса',
 'imagepage' => 'Паьла оагӀув тӀа бӀаргтасса',
@@ -264,8 +264,6 @@ $messages = array(
 'ok' => 'ХӀаа',
 'retrievedfrom' => '"$1" ГӀувам',
 'youhavenewmessages' => 'Оаш $1 ($2) дӀайийцад',
-'newmessageslink' => 'керда хоамаш',
-'newmessagesdifflink' => 'тӀехьара хувцамаш',
 'youhavenewmessagesmulti' => 'Оаш $1чу керда хоамаш дӀайийцад',
 'editsection' => 'хувца',
 'editold' => 'хувца',
@@ -464,7 +462,7 @@ $messages = array(
 'history-fieldset-title' => 'Искара бӀаргтасса',
 'history-show-deleted' => 'ДӀадаьккхараш мара',
 'histfirst' => 'къаьнараш',
-'histlast' => 'ха яннараш',
+'histlast' => 'кердараш',
 'historyempty' => '(даьсса)',
 
 # Revision feed
@@ -555,7 +553,6 @@ $messages = array(
 # Preferences page
 'preferences' => 'Оттамаш',
 'mypreferences' => 'Оттамаш',
-'prefsnologin' => 'Шо чудаьнна дац',
 'changepassword' => 'КъайладIоaгIа дIахувцар',
 'prefs-skin' => 'БIагала куц',
 'skin-preview' => 'Хьажа',
@@ -864,8 +861,8 @@ $messages = array(
 'contributions' => '{{GENDER:$1|Дакъалаьцархочунна}} къахьегам',
 'contributions-title' => '$1 дакъалаьцархочунна къахьегам',
 'mycontris' => 'Са къахьегам',
-'contribsub2' => '$1 ($2) баь болх',
-'uctop' => '(тIехьара)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) баь болх',
+'uctop' => '(xIанзара)',
 'month' => 'Цхьа бутт хьалхагIа (кхы хьалхагIа)',
 'year' => 'Цхьа шу хьалхагIа (кхы хьалхагIа):',
 
@@ -1027,7 +1024,7 @@ $messages = array(
 'file-info-size' => '$1 × $2 фихсам, паьла дустам: $3, MIME-тайп: $4',
 'file-nohires' => 'Укхал доккхагIа доржам дац',
 'svg-long-desc' => 'SVG-паьл, $1 × $2 фихелашца, паьла дустам: $3',
-'show-big-image' => 'Ð¥Ñ\8cадоккÑ\85адаÑ\8c сурт',
+'show-big-image' => 'Ð¥Ñ\8cалÑ\85агIаÑ\80а сурт',
 
 # Special:NewFiles
 'noimages' => 'Суртaш бIаргагуш дац.',
@@ -1088,7 +1085,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'Йола болхоагIувца паьла гIалатах мукъаяьккха',
-'edit-externally-help' => '(ма даррачунга хьажа [//www.mediawiki.org/wiki/Manual:External_editors хьаоттама кулгалхо])',
+'edit-externally-help' => '(ма даррачунга хьажа [https://www.mediawiki.org/wiki/Manual:External_editors хьаоттама кулгалхо])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'деррига',
index 599890c..db812d1 100644 (file)
@@ -337,8 +337,6 @@ Videz [[Special:Version|versiono-pagino]].',
 'ok' => 'O.K.',
 'retrievedfrom' => 'Obtenita de "$1"',
 'youhavenewmessages' => 'Vu havas $1 ($2).',
-'newmessageslink' => 'nova mesaji',
-'newmessagesdifflink' => 'lasta chanjo',
 'youhavenewmessagesmulti' => 'Vu havas nova mesaji ye $1',
 'editsection' => 'redaktar',
 'editold' => 'redaktar',
@@ -691,8 +689,6 @@ Probez prefixizar vua demando kun ''all:'' por serchar omna kontenajo (inkluzant
 'preferences' => 'Preferaji',
 'mypreferences' => 'Preferaji',
 'prefs-edits' => 'Nombro di redaktaji:',
-'prefsnologin' => 'Vu ne eniris',
-'prefsnologintext' => 'Vu mustas <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} enirir]</span> por establisar la preferaji.',
 'changepassword' => 'Chanjar pasovorto',
 'prefs-skin' => 'Pelo',
 'skin-preview' => 'Pre-videz',
@@ -811,6 +807,7 @@ Ol mustas ne havar plu kam $1 {{PLURAL:$1|litero|literi}}.',
 'recentchanges-label-newpage' => 'Ca redaktajo kreis nova pagino',
 'recentchanges-label-minor' => 'Ica es mikra redaktajo',
 'recentchanges-label-bot' => 'Ta chanjo facita da bot',
+'recentchanges-legend-newpage' => '$1 - nova pagino',
 'rcnote' => "Infre esas la lasta {{PLURAL:$1|'''1''' chanjo|'''$1''' chanji}} dum la lasta {{PLURAL:$2|dio|'''$2''' dii}} ye $5, $4.",
 'rcnotefrom' => "Infre esas la lasta chanji depos '''$2''' (montrita til '''$1''').",
 'rclistfrom' => 'Montrar nova chanji startante de $1',
@@ -1304,7 +1301,7 @@ Voluntez selektar altra nomo.',
 'allmessages' => 'Omna sistemo-mesaji',
 'allmessagesname' => 'Nomo',
 'allmessagestext' => 'Ico esas listo di omna sistemo-mesaji disponebla en la MediaWiki nomaro.
-Voluntez vizitar [//www.mediawiki.org/wiki/Localisation MediaWiki Lokizado] e [//translatewiki.net translatewiki.net] se vu volus kontributar ad generala MediaWiki lokizado.',
+Voluntez vizitar [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokizado] e [//translatewiki.net translatewiki.net] se vu volus kontributar ad generala MediaWiki lokizado.',
 'allmessages-language' => 'Linguo:',
 
 # Thumbnails
@@ -1553,4 +1550,9 @@ Vu darfos adjuntar kauso en la rezumo.',
 'searchsuggest-search' => 'Serchez',
 'searchsuggest-containing' => 'quan kontenas...',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Rezulto',
+'expand_templates_ok' => 'O.K.',
+'expand_templates_preview' => 'Previdar',
+
 );
index 1350fd5..a5f2b8b 100644 (file)
@@ -139,7 +139,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Elstu_síður' ),
        'Blankpage'                 => array( 'Auð_síða' ),
        'Block'                     => array( 'Banna_vistföng' ),
-       'Blockme'                   => array( 'Banna_mig' ),
        'Booksources'               => array( 'Bókaheimildir' ),
        'BrokenRedirects'           => array( 'Brotnar_tilvísanir' ),
        'Categories'                => array( 'Flokkar' ),
@@ -151,7 +150,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Búa_til_aðgang' ),
        'Deadendpages'              => array( 'Botnlangar' ),
        'DeletedContributions'      => array( 'Eydd_framlög' ),
-       'Disambiguations'           => array( 'Tenglar_í_aðgreiningarsíður' ),
        'DoubleRedirects'           => array( 'Tvöfaldar_tilvísanir' ),
        'EditWatchlist'             => array( 'Breyta_vaktlista' ),
        'Emailuser'                 => array( 'Senda_tölvupóst' ),
@@ -231,6 +229,7 @@ $specialPageAliases = array(
 $separatorTransformTable = array( ',' => '.', '.' => ',' );
 $linkPrefixExtension = true;
 $linkTrail = '/^([áðéíóúýþæöa-z-–]+)(.*)$/sDu';
+$linkPrefixCharset = 'áÁðÐéÉíÍóÓúÚýÝþÞæÆöÖA-Za-z–-';
 
 $messages = array(
 # User preference toggles
@@ -371,14 +370,12 @@ $messages = array(
 'noindex-category' => 'Óraðaðar skrár',
 'broken-file-category' => 'Síður með brotna myndatengla',
 
-'linkprefix' => '/^(.*?)([áÁðÐéÉíÍóÓúÚýÝþÞæÆöÖA-Za-z-–]+)$/sDu',
-
 'about' => 'Um',
 'article' => 'Efnissíða',
 'newwindow' => '(opnast í nýjum glugga)',
 'cancel' => 'Hætta við',
 'moredotdotdot' => 'Meira...',
-'morenotlisted' => 'fleiri ekki skráð...',
+'morenotlisted' => 'Þessi listi er ekki tæmandi.',
 'mypage' => 'Síða',
 'mytalk' => 'Spjall',
 'anontalk' => 'Spjallsíða þessa vistfangs.',
@@ -481,7 +478,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Um {{SITENAME}}',
 'aboutpage' => 'Project:Um verkefnið',
-'copyright' => 'Efni má nota samkvæmt $1.',
+'copyright' => 'Efni má nota samkvæmt $1 nema kemur fram annars.',
 'copyrightpage' => '{{ns:project}}:Höfundarréttur',
 'currentevents' => 'Potturinn',
 'currentevents-url' => 'Project:Potturinn',
@@ -508,8 +505,6 @@ Sjá [[Special:Version|útgáfusíðuna]].',
 'ok' => 'Í lagi',
 'retrievedfrom' => 'Sótt frá „$1“',
 'youhavenewmessages' => 'Þú hefur fengið $1 ($2).',
-'newmessageslink' => 'ný skilaboð',
-'newmessagesdifflink' => 'síðasta breyting',
 'youhavenewmessagesfromusers' => 'Þú hefur $1 frá {{PLURAL:$3|öðrum notanda|$3 notendum}} ($2)',
 'youhavenewmessagesmanyusers' => 'Þú hefur $1 frá mörgum notendum ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ein|}} ný skilaboð',
@@ -563,6 +558,7 @@ Sjá [[Special:Version|útgáfusíðuna]].',
 # General errors
 'error' => 'Villa',
 'databaseerror' => 'Gagnagrunnsvilla',
+'databaseerror-error' => 'Villa: $1',
 'laggedslavemode' => 'Viðvörun: Síðan inniheldur ekki nýjustu uppfærslur.',
 'readonly' => 'Gagnagrunnur læstur',
 'enterlockreason' => 'Gefðu fram ástæðu fyrir læsingunni, og einnig áætlun
@@ -651,6 +647,7 @@ Ekki gleyma að breyta [[Special:Preferences|{{SITENAME}} stillingunum]] þínum
 'yourname' => 'Notandanafn:',
 'userlogin-yourname' => 'Notandanafn',
 'userlogin-yourname-ph' => 'Skrifaðu inn notendanafnið þitt',
+'createacct-another-username-ph' => 'Skrifaðu inn notendanafnið',
 'yourpassword' => 'Lykilorð:',
 'userlogin-yourpassword' => 'Lykilorð',
 'userlogin-yourpassword-ph' => 'Skrifaðu niður lykilorðið þitt',
@@ -683,10 +680,15 @@ Ekki gleyma að breyta [[Special:Preferences|{{SITENAME}} stillingunum]] þínum
 'userlogin-resetpassword-link' => 'Endursetja lykilorð',
 'helplogin-url' => 'Help:Innskráning',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hjálp við innskráningu]]',
+'userlogin-loggedin' => 'Þú ert búin(n) að skrá þig inn sem {{GENDER:$1|$1}}.
+Notaðu eyðablaðið fyrir neðan til að skrá þig inn sem annar notandi.',
+'userlogin-createanother' => 'Stofna annan aðgang',
 'createacct-join' => 'Sláðu inn þínar upplýsingar fyrir neðan.',
+'createacct-another-join' => 'Skrifaðu upplýsingar um nýja aðganginn fyrir neðan.',
 'createacct-emailrequired' => 'Netfang',
 'createacct-emailoptional' => 'Netfang (valfrjálst)',
 'createacct-email-ph' => 'Skrifaðu niður netfangið þitt',
+'createacct-another-email-ph' => 'Skrifaðu netfang',
 'createaccountmail' => 'Nota handahófsvalið bráðabirgðalykilorð og senda það á netfangið sem er tilgreint hér fyrir neðan',
 'createacct-realname' => 'Raunverulegt nafn (valfrjálst)',
 'createaccountreason' => 'Ástæða:',
@@ -695,6 +697,7 @@ Ekki gleyma að breyta [[Special:Preferences|{{SITENAME}} stillingunum]] þínum
 'createacct-captcha' => 'Öryggis athugun',
 'createacct-imgcaptcha-ph' => 'Sláðu inn textann að ofan',
 'createacct-submit' => 'Búa til aðganginn',
+'createacct-another-submit' => 'Stofna annan aðgang',
 'createacct-benefit-heading' => '{{SITENAME}} er skrifuð af fólki eins og þér.',
 'createacct-benefit-body1' => '{{PLURAL:$1|breyting|breytingar}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|síða|síður}}',
@@ -764,10 +767,11 @@ Gjörðu svo vel og settu inn netfang á gildu formi eða tæmdu reitinn.',
 Þú getur hunsað þessi skilaboð, ef villa hefur átt sér stað.',
 'usernamehasherror' => 'Notendanöfn mega ekki innihalda kassa (#)',
 'login-throttled' => 'Þér hefur mistekist að skrá þig inn undir þessu notendanafni of oft.
-Vinsamlegast reynið aftur síðar.',
+Vinsamlegast bíðið $1 áður en þú reynir aftur.',
 'login-abort-generic' => 'Innskráningin misheppnaðist - hætt var við hana.',
 'loginlanguagelabel' => 'Tungumál: $1',
 'suspicious-userlogout' => 'Beiðni um útskráningu hafnað því hún var líklegast send frá biluðum vafra eða vefseli sem hefur vistað vefsíðuna í flýtiminni.',
+'createacct-another-realname-tip' => 'Alvöru nafn er valfrjálst. Ef þú kýst að gefa það upp, verður það notað til að gefa þér heiður af verkum þínum.',
 
 # Email sending
 'php-mail-error-unknown' => 'Óþekkt villa í PHP mail() aðgerð.',
@@ -784,7 +788,7 @@ Til að klára að skrá þig inn, verður þú að endurstilla lykilorðið hé
 'newpassword' => 'Nýja lykilorðið',
 'retypenew' => 'Endurtaktu nýja lykilorðið:',
 'resetpass_submit' => 'Skrifaðu aðgangsorðið og skráðu þig inn',
-'changepassword-success' => 'Aðgangsorðinu þínu hefur verið breytt! Skráir þig inn...',
+'changepassword-success' => 'Það tókst að breyta lykilorðinu þínu!',
 'resetpass_forbidden' => 'Ekki er hægt að breyta lykilorðum',
 'resetpass-no-info' => 'Þú verður að vera skráð(ur) inn til að hafa aðgang að þessari síðu.',
 'resetpass-submit-loggedin' => 'Breyta lykilorði',
@@ -839,6 +843,18 @@ Tímabundið lykilorð: $2',
 'changeemail-submit' => 'Breyta netfangi',
 'changeemail-cancel' => 'Hætta við',
 
+# Special:ResetTokens
+'resettokens' => 'Endurstilla lykla',
+'resettokens-text' => 'Hér getur þú endurstillt lykla sem veita þér aðgang að ákveðnum persónuupplýsingum um aðganginn þinn.
+
+Þú átt að gera það ef þú ert búin(n) að deila þeim með einhverjum öðrum óviljandi eða ef búið er að brjóta inn í aðganginn þinn.',
+'resettokens-no-tokens' => 'Það eru engir lyklar að endurstilla.',
+'resettokens-legend' => 'Endurstilla lykla',
+'resettokens-tokens' => 'Lyklar:',
+'resettokens-token-label' => '$1 (núverandi gildi: $2)',
+'resettokens-done' => 'Lyklarnir hafa verið endurstilltir.',
+'resettokens-resetbutton' => 'Endurstilla valda lykla',
+
 # Edit page toolbar
 'bold_sample' => 'Feitletraður texti',
 'bold_tip' => 'Feitletraður texti',
@@ -1018,7 +1034,7 @@ Verndunarskrá síðunnar er gefin fyrir neðan til tilvísunar.",
 'nocreate-loggedin' => 'Þú hefur ekki leyfi til að skapa nýjar síður.',
 'sectioneditnotsupported-title' => 'Hlutabreyting er ekki virk',
 'sectioneditnotsupported-text' => 'Hlutabreyting er ekki virk á þessari síðu.',
-'permissionserrors' => 'Leyfisvillur',
+'permissionserrors' => 'Leyfisvilla',
 'permissionserrorstext' => 'Þú hefur ekki leyfi til að gera þetta, af eftirfarandi {{PLURAL:$1|ástæðu|ástæðum}}:',
 'permissionserrorstext-withaction' => 'Þú hefur ekki réttindi til að $2, af eftirfarandi {{PLURAL:$1|ástæðu|ástæðum}}:',
 'recreate-moveddeleted-warn' => "'''Viðvörun: Þú ert að endurskapa síðu sem áður hefur verið eytt.'''
@@ -1077,6 +1093,7 @@ Hluti sniðsins verður ekki með.",
 'undo-failure' => 'Breytinguna var ekki hægt að taka tilbaka vegna breytinga í millitíðinni.',
 'undo-norev' => 'Ekki var hægt að taka breytinguna aftr því að hún er ekki til eða henni var eytt.',
 'undo-summary' => 'Tek aftur breytingu $1 frá [[Special:Contributions/$2|$2]] ([[User talk:$2|spjall]])',
+'undo-summary-username-hidden' => 'Afturkalla breytingu $1 eftir faldan notanda',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Ekki hægt að búa til aðgang',
@@ -1105,7 +1122,7 @@ Skýringartexti: (nú) = skoðanamunur á núverandi útgáfu,
 'history-fieldset-title' => 'Skoða breytingaskrá',
 'history-show-deleted' => 'Eingöngu eyddar breytingar',
 'histfirst' => 'elstu',
-'histlast' => 'yngstu',
+'histlast' => 'nýjustu',
 'historysize' => '({{PLURAL:$1|1 bæti|$1 bæti}})',
 'historyempty' => '(tóm)',
 
@@ -1169,15 +1186,15 @@ Frekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGE
 * Óviðeigandi persónulegar upplýsingar
 *: ''heimilisfang, símanúmer, kennitala, osfrv.''",
 'revdelete-legend' => 'Setja sjáanlegar hamlanir',
-'revdelete-hide-text' => 'Fela breytingatexta',
+'revdelete-hide-text' => 'Breytingatexti',
 'revdelete-hide-image' => 'Fela efni skráar',
 'revdelete-hide-name' => 'Fela aðgerð og mark',
-'revdelete-hide-comment' => 'Fela breytingarágrip',
-'revdelete-hide-user' => 'Fela notandanafn/vistfang',
+'revdelete-hide-comment' => 'Breytingarágrip',
+'revdelete-hide-user' => 'Notandanafn/vistfang',
 'revdelete-hide-restricted' => 'Dylja gögn frá stjórnendum og öðrum',
 'revdelete-radio-same' => '(ekki breyta)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'Nei',
+'revdelete-radio-set' => 'Sjáanlegt',
+'revdelete-radio-unset' => 'Falið',
 'revdelete-suppress' => 'Dylja gögn frá stjórnendum og öðrum',
 'revdelete-unsuppress' => 'Fjarlægja takmarkanir á endurvöktum breytingum',
 'revdelete-log' => 'Ástæða:',
@@ -1259,6 +1276,7 @@ Athugaðu að með því að nota flakktenglana er þessi dálkur endurstilltur.
 'compareselectedversions' => 'Bera saman valdar útgáfur',
 'showhideselectedversions' => 'Sýna/fela valdar breytingar',
 'editundo' => 'Taka aftur þessa breytingu',
+'diff-empty' => '(Enginn munur)',
 'diff-multi' => '({{PLURAL:$1|Ein millibreyting ekki sýnd|$1 millibreytingar ekki sýndar}} frá {{PLURAL:$2|notanda|$2 notendum}}.)',
 'diff-multi-manyusers' => '({{PLURAL:$1|Ein millibreyting ekki sýnd|$1 millibreytingar ekki sýndar}} frá fleiri en {{PLURAL:$2|einum notanda|$2 notendum}}.)',
 'difference-missing-revision' => '{{PLURAL:$2|Ein útgáfa|$2 útgáfur}} samanburðarins ($1) {{PLURAL:$2|fannst|fundust}} ekki.
@@ -1334,8 +1352,6 @@ Athugaðu að skrár þeirra yfir {{SITENAME}}-efni kunna að vera úreltar.',
 'preferences' => 'Stillingar',
 'mypreferences' => 'Mínar stillingar',
 'prefs-edits' => 'Fjöldi breytinga:',
-'prefsnologin' => 'Ekki innskráður',
-'prefsnologintext' => 'Þú verður að vera <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} skráð(ur) inn]</span> til að breyta notandastillingum.',
 'changepassword' => 'Breyta lykilorði',
 'prefs-skin' => 'Þema',
 'skin-preview' => 'Forskoða',
@@ -1360,7 +1376,7 @@ Athugaðu að skrár þeirra yfir {{SITENAME}}-efni kunna að vera úreltar.',
 'prefs-rendering' => 'Útlit',
 'saveprefs' => 'Vista',
 'resetprefs' => 'Endurstilla valmöguleika',
-'restoreprefs' => 'Endurheimta allar stillingar',
+'restoreprefs' => 'Endurstilla allar sjálfgefnar stillingar (í öllum hlutum)',
 'prefs-editing' => 'Breytingarflipinn',
 'rows' => 'Raðir',
 'columns' => 'Dálkar',
@@ -1416,10 +1432,10 @@ Ekki er hægt að taka þessa breytingu til baka.',
 'badsig' => 'Ógild hrá undirskrift. Athugaðu HTML-kóða.',
 'badsiglength' => 'Undirskriftin er of löng.
 Hún þarf að vera færri en $1 {{PLURAL:$1|stafur|stafir}}.',
-'yourgender' => 'Kyn:',
-'gender-unknown' => 'Ã\93skilgreint',
-'gender-male' => 'Karl',
-'gender-female' => 'Kona',
+'yourgender' => 'Hvernig vilt þú helst lýsa þér?',
+'gender-unknown' => 'Ã\89g vil heldur ekki gefa upp',
+'gender-male' => 'Hann breytir wikisíðum',
+'gender-female' => 'Hún breytir wikisíðum',
 'prefs-help-gender' => 'Valfrjálst: notað til að aðgreina kynin í meldingum hugbúnaðarins. Þessar upplýsingar verða aðgengilegar öllum.',
 'email' => 'Tölvupóstur',
 'prefs-help-realname' => 'Alvöru nafn er valfrjálst.
@@ -1433,7 +1449,9 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'prefs-signature' => 'Undirskrift',
 'prefs-dateformat' => 'Dagasnið',
 'prefs-timeoffset' => 'Tímamismunur',
-'prefs-advancedediting' => 'Háþróaðir möguleikar',
+'prefs-advancedediting' => 'Almennir valkostir',
+'prefs-editor' => 'Ritsjóri',
+'prefs-preview' => 'Forskoðun',
 'prefs-advancedrc' => 'Háþróaðir möguleikar',
 'prefs-advancedrendering' => 'Háþróaðir möguleikar',
 'prefs-advancedsearchoptions' => 'Háþróaðir möguleikar',
@@ -1441,7 +1459,9 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'prefs-displayrc' => 'Útlitsmöguleikar',
 'prefs-displaysearchoptions' => 'Útlitsmöguleikar',
 'prefs-displaywatchlist' => 'Útlitsmöguleikar',
+'prefs-tokenwatchlist' => 'Lykill',
 'prefs-diffs' => 'Breytingar',
+'prefs-help-prefershttps' => 'Þessi stilling tekur gildi í næsta skiptið sem þú skráir inn.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Netfang virðist vera virkt.',
@@ -1465,9 +1485,11 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'userrights-no-interwiki' => 'Þú hefur ekki leyfi til að breyta notandaréttindum á öðrum wiki-síðum.',
 'userrights-nodatabase' => 'Gagnagrunnurinn $1 er ekki til eða ekki staðbundinn.',
 'userrights-nologin' => 'Þú verður að [[Special:UserLogin|innskrá]] þig á möppudýraaðgang til að geta útdeilt notandaréttindum.',
-'userrights-notallowed' => 'Þinn aðgangur hefur ekki réttindi til að útdeila notandaréttindum.',
+'userrights-notallowed' => 'Þú hefur ekki réttindi til að útdeila eða draga til baka notandaréttini.',
 'userrights-changeable-col' => 'Hópar sem þú getur breytt',
 'userrights-unchangeable-col' => 'Hópar sem þú getur ekki breytt',
+'userrights-conflict' => 'Árekstur í að breyta notandaréttindum! Vinsamlegast skoðaðu aftur og staðfestu breytingar þínar.',
+'userrights-removed-self' => 'Þér hefur tekist að fjarlægja þín eigin réttindi. Vegna þess mátt þú ekki lengur skoða þessa síðu.',
 
 # Groups
 'group' => 'Hópur:',
@@ -1533,13 +1555,19 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'right-proxyunbannable' => 'Sneiða hjá sjálfvirkum proxy-bönnum',
 'right-unblockself' => 'Afbanna sjálfan sig',
 'right-protect' => 'Breyta verndunarstigi og breyta vernduðum síðum',
-'right-editprotected' => 'Breyta verndaðar síður (án keðjuverndunar)',
+'right-editprotected' => 'Breyta síðum vernduðum sem „{{int:protect-level-sysop}}“',
+'right-editsemiprotected' => 'Breyta síðum vernduðum sem „{{int:protect-level-autoconfirmed}}“',
 'right-editinterface' => 'Breyta notandaviðmótinu',
 'right-editusercssjs' => 'Breyta CSS- og JS-skrám annarra',
 'right-editusercss' => 'Breyta CSS-skrám annarra',
 'right-edituserjs' => 'Breyta JS-skrám annarra',
 'right-editmyusercss' => 'Breyta þinni eigin CSS-notandaskrá',
 'right-editmyuserjs' => 'Breyta þinni eigin JavaScript-notandaskrá',
+'right-viewmywatchlist' => 'Skoða þinn eigin vaktlista',
+'right-editmywatchlist' => 'Breyta þínum eigin vaktlista. Athugið að nokkrar aðgerðir bæta enn við síður án þessa réttindis.',
+'right-viewmyprivateinfo' => 'Skoða þínar eigin persónuupplýsingar (t.d. netfang, alvörunafn)',
+'right-editmyprivateinfo' => 'Breyta þínum eigin persónuupplýsingum (t.d. netfangi, alvörunafni)',
+'right-editmyoptions' => 'Breyta þínum eigin stillingum',
 'right-rollback' => 'Taka snögglega aftur breytingar síðasta notanda sem breytti síðunni',
 'right-markbotedits' => 'Merkja endurtektar breytingar sem vélmennabreytingar',
 'right-noratelimit' => 'Sneiða hjá takmörkunum',
@@ -1591,8 +1619,8 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'action-block' => 'Banna notandanum að gera breytingar',
 'action-protect' => 'breyta verndunarstigum fyrir þessa síðu',
 'action-rollback' => 'Taka snögglega aftur breytingar síðasta notanda sem breytti ákveðinni síðu',
-'action-import' => 'Flytja inn þessa skrá frá öðrum wiki',
-'action-importupload' => 'Flytja inn þessa síðu frá skráar upphali',
+'action-import' => 'flytja inn síður frá öðrum wiki',
+'action-importupload' => 'flytja inn síður frá skráarupphali',
 'action-patrol' => 'Merkja breytingar annara sem yfirfarnar',
 'action-autopatrol' => 'Merkja eigin breytingu sem yfirfarna',
 'action-unwatchedpages' => 'Skoða lista yfir óvaktaðar síður',
@@ -1601,17 +1629,25 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'action-userrights-interwiki' => 'breyta notandaréttindum annarra notenda á öðrum wiki-verkefnum',
 'action-siteadmin' => 'læsa eða opna gagnagrunninn',
 'action-sendemail' => 'senda tölvupósta',
+'action-editmywatchlist' => 'breyta vaktlistanum þínum',
+'action-viewmywatchlist' => 'skoða vaktlistann þinn',
+'action-viewmyprivateinfo' => 'skoða persónuupplýsingar þínar',
+'action-editmyprivateinfo' => 'breyta persónuupplýsingum þínum',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|breyting|breytingar}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|síðan síðustu heimsókn}}',
+'enhancedrc-history' => 'breytingaskrá',
 'recentchanges' => 'Nýlegar breytingar',
 'recentchanges-legend' => 'Stillingar nýlegra breytinga',
 'recentchanges-summary' => 'Hér geturðu fylgst með nýjustu breytingunum.',
+'recentchanges-noresult' => 'Engar breytingar í uppgefna tímabilinu sem passa við þessa mælikvarða.',
 'recentchanges-feed-description' => 'Hér er hægt að fylgjast með nýlegum breytingum á {{SITENAME}}.',
 'recentchanges-label-newpage' => 'Þessi breyting skapaði nýja síðu',
 'recentchanges-label-minor' => 'Þetta er minniháttar breyting',
 'recentchanges-label-bot' => 'Þessi breytingar var gerð af vélmenni',
 'recentchanges-label-unpatrolled' => 'Þessi breyting hefur ekki verið yfirfarin',
+'recentchanges-legend-newpage' => '$1 - ný síða',
 'rcnote' => "Að neðan {{PLURAL:$1|er '''1''' breyting|eru síðustu '''$1''' breytingar}} síðast {{PLURAL:$2|liðinn dag|liðna '''$2''' daga}}, frá $5, $4.",
 'rcnotefrom' => "Að neðan eru breytingar síðan '''$2''' (allt að '''$1''' sýndar).",
 'rclistfrom' => 'Sýna breytingar frá og með $1',
@@ -1634,7 +1670,7 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'rc_categories_any' => 'Alla',
 'rc-change-size-new' => '$1 {{PLURAL:$1|bæt|bæti}} eftir breytingu',
 'newsectionsummary' => 'Nýr hluti: /* $1 */',
-'rc-enhanced-expand' => 'Sýna upplýsingar (þarfnast JavaScript)',
+'rc-enhanced-expand' => 'Sýna upplýsingar',
 'rc-enhanced-hide' => 'Fela ítarefni',
 'rc-old-title' => 'Upphaflega búin til undir nafninu "$1"',
 
@@ -1654,8 +1690,7 @@ Síður á [[Special:Watchlist|vaktlistanum þínum]] eru '''feitletraðar'''.",
 'reuploaddesc' => 'Aftur á innhlaðningarformið.',
 'upload-tryagain' => 'Sendu breytta myndlýsingu',
 'uploadnologin' => 'Óinnskráð(ur)',
-'uploadnologintext' => 'Þú verður að vera [[Special:UserLogin|skráð(ur) inn]]
-til að hlaða inn skrám.',
+'uploadnologintext' => 'Þú verður $1 til að hala upp skrár.',
 'upload_directory_missing' => 'Mappa upphlaða ($1) er týnd og vefþjónninn gat ekki búið hana til.',
 'upload_directory_read_only' => 'Mistókst að skrifa í möppu upphlaða ($1) á vefþjóni.',
 'uploaderror' => 'Villa í innhlaðningu',
@@ -1894,8 +1929,7 @@ Athugaðu hvort síðan sé aðgengileg, bíddu í smástund og reyndu aftur.
 'upload_source_file' => '(skrá á tölvunni þinni)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Þessi kerfissíða sýnir allar upphlaðnar skrár.
-Þegar hún er síuð ákveðnu notendanafni birtast eingöngu myndir frá honum.',
+'listfiles-summary' => 'Þessi kerfissíða sýnir allar upphlaðnar skrár.',
 'listfiles_search_for' => 'Leita að miðilsnafni:',
 'imgfile' => 'skrá',
 'listfiles' => 'Skráalisti',
@@ -1906,6 +1940,10 @@ Athugaðu hvort síðan sé aðgengileg, bíddu í smástund og reyndu aftur.
 'listfiles_size' => 'Stærð (bæti)',
 'listfiles_description' => 'Lýsing',
 'listfiles_count' => 'Útgáfur',
+'listfiles-show-all' => 'Taka með gamlar útgáfur af myndum',
+'listfiles-latestversion' => 'Núverandi útgáfa',
+'listfiles-latestversion-yes' => 'Já',
+'listfiles-latestversion-no' => 'Nei',
 
 # File description page
 'file-anchor-link' => 'Skrá',
@@ -2002,6 +2040,13 @@ Leitarstrengurinn á að vera á þessu formi: efnistag/myndasnið, t.d. <code>i
 'randompage' => 'Handahófsvalin grein',
 'randompage-nopages' => 'Það eru engar síður í {{PLURAL:$2|nafnrýminu|nafnrýmunum}}: $1.',
 
+# Random page in category
+'randomincategory' => 'Handhófsvalin síða í flokki',
+'randomincategory-invalidcategory' => '„$1“ er ekki gilt flokkarheiti',
+'randomincategory-nopages' => 'Það eru engar síður í flokkinum [[:Category:$1|$1]].',
+'randomincategory-selectcategory' => 'Fá handhófsvalda síðu úr flokkinum: $1 $2.',
+'randomincategory-selectcategory-submit' => 'Fara',
+
 # Random redirect
 'randomredirect' => 'Handahófsvalin tilvísun',
 'randomredirect-nopages' => 'Það eru engar tilvísanir í nafnrýminu „$1“.',
@@ -2027,6 +2072,10 @@ Leitarstrengurinn á að vera á þessu formi: efnistag/myndasnið, t.d. <code>i
 'statistics-users-active-desc' => 'Notendur sem hafa framkvæmt aðgerð {{PLURAL:$1|síðastliðin dag|síðastliðna $1 daga}}',
 'statistics-mostpopular' => 'Mest skoðuðu síður',
 
+'pageswithprop' => 'Síður með eiginleika',
+'pageswithprop-legend' => 'Síður með síðueiginleika',
+'pageswithprop-text' => 'Á þessari síðu er listi yfir síður sem hafa ákveðna síðueiginleika.',
+'pageswithprop-prop' => 'Heiti eiginleika:',
 'pageswithprop-submit' => 'Áfram',
 
 'doubleredirects' => 'Tvöfaldar tilvísanir',
@@ -2086,6 +2135,7 @@ Hún er tilvísun á [[$2]].',
 'mostrevisions' => 'Síður eftir fjölda breytinga',
 'prefixindex' => 'Allar síður með forskeyti',
 'prefixindex-namespace' => 'Allar síður með forskeyti ($1 nafnrými)',
+'prefixindex-strip' => 'Fjarlægja forskeyti í listanum',
 'shortpages' => 'Stuttar síður',
 'longpages' => 'Langar síður',
 'deadendpages' => 'Botnlangar',
@@ -2101,6 +2151,7 @@ Hún er tilvísun á [[$2]].',
 'listusers' => 'Notendalisti',
 'listusers-editsonly' => 'Sýna eingöngu notendur með breytingar',
 'listusers-creationsort' => 'Raða eftir stofndegi',
+'listusers-desc' => 'Raða í lækkandi röð',
 'usereditcount' => '$1 {{PLURAL:$1|breyting|breytingar}}',
 'usercreated' => '{{GENDER:$3|Stofnað|}} $1 $2',
 'newpages' => 'Nýjustu greinar',
@@ -2530,7 +2581,7 @@ $1',
 'contributions' => 'Framlög {{GENDER:$1|notanda}}',
 'contributions-title' => 'Framlög notanda $1',
 'mycontris' => 'Framlög',
-'contribsub2' => 'Eftir $1 ($2)',
+'contribsub2' => 'Eftir {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Engar breytingar fundnar sem passa við þessa viðmiðun.',
 'uctop' => '(núverandi)',
 'month' => 'Frá mánuðinum (og fyrr):',
@@ -2839,7 +2890,7 @@ Ef síðari möguleikinn á við getur þú einnig notað tengil, til dæmis
 'allmessagesdefault' => 'Sjálfgefinn skilaboða texti',
 'allmessagescurrent' => 'Núverandi texti',
 'allmessagestext' => 'Þetta er listi yfir kerfismeldingar í Melding-nafnrýminu.
-Vinsamlegast heimsæktu [//www.mediawiki.org/wiki/Localisation MediaWiki-staðfæringuna] og [//translatewiki.net translatewiki.net] ef þú vilt taka þátt í almennri MediaWiki-staðfæringu.',
+Vinsamlegast heimsæktu [https://www.mediawiki.org/wiki/Localisation MediaWiki-staðfæringuna] og [//translatewiki.net translatewiki.net] ef þú vilt taka þátt í almennri MediaWiki-staðfæringu.',
 'allmessagesnotsupportedDB' => "Það er ekki hægt að nota '''{{ns:special}}:Allmessages''' því '''\$wgUseDatabaseMessages''' hefur verið gerð óvirk.",
 'allmessages-filter-legend' => 'Sía',
 'allmessages-filter' => 'Sía með breytingarstöðu:',
@@ -3036,6 +3087,8 @@ Vinsamlegast reyndu aftur.',
 'spam_reverting' => 'Tek aftur síðustu breytingu sem inniheldur ekki tengil á $1',
 'spam_blanking' => 'Allar útgáfur innihéldu tengla á $1, tæmi síðuna',
 'spam_deleting' => 'Allar útgáfur innihéldu tengla á $1, eyði síðunni',
+'simpleantispam-label' => "Kæfuvörn.
+'''EKKI''' fylla þetta út!",
 
 # Info page
 'pageinfo-title' => 'Upplýsingar um $1',
@@ -3050,12 +3103,12 @@ Vinsamlegast reyndu aftur.',
 'pageinfo-article-id' => 'Einkennisnúmer síðunnar',
 'pageinfo-language' => 'Tungumál síðunnar',
 'pageinfo-robot-policy' => 'Leitarvélastaða',
-'pageinfo-robot-index' => 'Skráanleg',
-'pageinfo-robot-noindex' => 'Óskráanleg',
+'pageinfo-robot-index' => 'Heimilað',
+'pageinfo-robot-noindex' => 'Ekki heimilað',
 'pageinfo-views' => 'Fjöldi innlita',
 'pageinfo-watchers' => 'Fjöldi notenda, sem vakta síðuna',
 'pageinfo-few-watchers' => 'Vöktuð af færri en $1 {{PLURAL:$1|notanda|notendum}}',
-'pageinfo-redirects-name' => 'Tilvísanir til þessarar síðu',
+'pageinfo-redirects-name' => 'Fjöldi tilvísana til þessarar síðu',
 'pageinfo-subpages-name' => 'Undirsíður þessarar síðu',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|tilvísun|tilvísanir}}; $3 {{PLURAL:$3|ekki tilvísun|ekki tilvísanir}})',
 'pageinfo-firstuser' => 'Stofnandi síðunnar',
@@ -3361,6 +3414,7 @@ Ef skránni hefur verið breytt, kann að vera að einhverjar upplýsingar eigi
 'exif-disclaimer' => 'Fyrirvari',
 'exif-contentwarning' => 'Viðvörun innihalds myndar',
 'exif-giffilecomment' => 'GIF athugasemd',
+'exif-intellectualgenre' => 'Tegund hlutar',
 'exif-scenecode' => 'IPTC kóði myndefnis',
 'exif-event' => 'Lýsir viðburðinum',
 'exif-organisationinimage' => 'Lýsir félaginu',
@@ -3564,7 +3618,7 @@ Ef skránni hefur verið breytt, kann að vera að einhverjar upplýsingar eigi
 
 # External editor support
 'edit-externally' => 'Breyta þessari skrá með utanaðkomandi hugbúnaði',
-'edit-externally-help' => '(Sjá [//www.mediawiki.org/wiki/Manual:External_editors leiðbeiningar] fyrir meiri upplýsingar)',
+'edit-externally-help' => '(Sjá [https://www.mediawiki.org/wiki/Manual:External_editors leiðbeiningar] fyrir meiri upplýsingar)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'allt',
@@ -3653,6 +3707,9 @@ Vinsamlegast staðfestu að þú viljir endurvekja hana.',
 'confirm-unwatch-button' => 'Í lagi',
 'confirm-unwatch-top' => 'Fjarlægja þessa síðu af vaktlistanum þínum?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1”',
+
 # Multipage image navigation
 'imgmultipageprev' => '← fyrri síða',
 'imgmultipagenext' => 'næsta síða →',
@@ -3731,7 +3788,7 @@ einn titil í hverri línu.
 'version-hook-subscribedby' => 'Í áskrift af',
 'version-version' => '(Útgáfa $1)',
 'version-license' => 'Leyfi',
-'version-poweredby-credits' => "Þessi wiki er knúin af '''[//www.mediawiki.org/ MediaWiki]''', höfundaréttur © 2001-$1 $2.",
+'version-poweredby-credits' => "Þessi wiki er knúin af '''[https://www.mediawiki.org/ MediaWiki]''', höfundaréttur © 2001-$1 $2.",
 'version-poweredby-others' => 'aðrir',
 'version-license-info' => 'MediaWiki er frjáls hugbúnaður; þú mátt endurútgefa hann og/eða breyta honum undir GNU General Public leyfi eins og það er gefið út af Free Software stofnuninni, annaðhvort útgáfu 2 eða (að þínu mati) hvaða nýrri útgáfa sem er.
 
@@ -3764,8 +3821,7 @@ MediaWiki er útgefin í þeirri von að hann sé gagnlegur, en ÁN ALLRAR ÁBYR
 
 # Special:SpecialPages
 'specialpages' => 'Kerfissíður',
-'specialpages-note' => '----
-* Venjulegar kerfisíður.
+'specialpages-note' => '* Venjulegar kerfisíður.
 * <span class="mw-specialpagerestricted">Kerfisíður með takmörkuðum aðgangi.</span>',
 'specialpages-group-maintenance' => 'Viðhaldsskýrslur',
 'specialpages-group-other' => 'Aðrar kerfissíður',
@@ -3803,7 +3859,10 @@ MediaWiki er útgefin í þeirri von að hann sé gagnlegur, en ÁN ALLRAR ÁBYR
 'tags-tag' => 'Nafn tags',
 'tags-display-header' => 'Útlit í breytingarskrá',
 'tags-description-header' => 'Tæmandi merkingarlýsing',
+'tags-active-header' => 'Virkt?',
 'tags-hitcount-header' => 'Merktar breytingar',
+'tags-active-yes' => 'Já',
+'tags-active-no' => 'Nei',
 'tags-edit' => 'breyta',
 'tags-hitcount' => '$1 {{PLURAL:$1|breyting|breytingar}}',
 
@@ -3824,6 +3883,7 @@ MediaWiki er útgefin í þeirri von að hann sé gagnlegur, en ÁN ALLRAR ÁBYR
 'dberr-problems' => 'Því miður!Tæknilegir örðugleikar eru á þessari síðu.',
 'dberr-again' => 'Reyndu að bíða í nokkrar mínútur og endurhladdu síðan síðuna.',
 'dberr-info' => '(Mistókst að hafa samband við gagnaþjón: $1)',
+'dberr-info-hidden' => '(Mistókst að hafa samband við gagnaþjón)',
 'dberr-usegoogle' => 'Þú getur notað Google til að leita á meðan.',
 'dberr-outofdate' => 'Athugaðu að afrit þeirra gætu verið úreld.',
 'dberr-cachederror' => 'Þetta er afritað eintak af umbeðinni síðu og gæti verið úreld.',
@@ -3959,4 +4019,16 @@ Ef ekki, þá getur þú notað einfalt eyðublað hér fyrir neðan. Athugasemd
 # Image rotation
 'rotate-comment' => 'Myndinni var snúið um $1 {{PLURAL:$1|gráðu|gráður}} réttsælis',
 
+# Limit report
+'limitreport-walltime' => 'Rauntímanotkun',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekúnda|sekúndur}}',
+
+# Special:ExpandTemplates
+'expand_templates_input' => 'Inntakstexti:',
+'expand_templates_output' => 'Útkoma',
+'expand_templates_xml_output' => 'XML-úttak',
+'expand_templates_ok' => 'Í lagi',
+'expand_templates_remove_comments' => 'Fjarlægja athugasemdir',
+'expand_templates_preview' => 'Forskoða',
+
 );
index f554aed..cfb5db5 100644 (file)
@@ -121,7 +121,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'TitoloErrato' ),
        'Blankpage'                 => array( 'PaginaVuota' ),
        'Block'                     => array( 'Blocca' ),
-       'Blockme'                   => array( 'BloccaProxy' ),
        'Booksources'               => array( 'RicercaISBN' ),
        'BrokenRedirects'           => array( 'RedirectErrati' ),
        'Categories'                => array( 'Categorie' ),
@@ -133,10 +132,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'CreaAccount' ),
        'Deadendpages'              => array( 'PagineSenzaUscita' ),
        'DeletedContributions'      => array( 'ContributiCancellati' ),
-       'Disambiguations'           => array( 'Disambigua' ),
        'DoubleRedirects'           => array( 'RedirectDoppi' ),
        'EditWatchlist'             => array( 'ModificaOsservati', 'ModificaOsservatiSpeciali', 'ModificaListaSeguiti' ),
        'Emailuser'                 => array( 'InviaEMail' ),
+       'ExpandTemplates'           => array( 'EspandiTemplate' ),
        'Export'                    => array( 'Esporta' ),
        'Fewestrevisions'           => array( 'PagineConMenoRevisioni' ),
        'FileDuplicateSearch'       => array( 'CercaFileDuplicati' ),
@@ -180,6 +179,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'PagineProtette' ),
        'Protectedtitles'           => array( 'TitoliProtetti' ),
        'Randompage'                => array( 'PaginaCasuale' ),
+       'RandomInCategory'          => array( 'CasualeInCategoria' ),
        'Randomredirect'            => array( 'RedirectCasuale' ),
        'Recentchanges'             => array( 'UltimeModifiche' ),
        'Recentchangeslinked'       => array( 'ModificheCorrelate' ),
@@ -201,8 +201,9 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'TemplateNonUsati' ),
        'Unwatchedpages'            => array( 'PagineNonOsservate' ),
        'Upload'                    => array( 'Carica' ),
-       'Userlogin'                 => array( 'Entra', 'Login' ),
-       'Userlogout'                => array( 'Esci', 'Logout' ),
+       'UploadStash'               => array( 'CodaCaricamenti' ),
+       'Userlogin'                 => array( 'Entra' ),
+       'Userlogout'                => array( 'Esci' ),
        'Userrights'                => array( 'PermessiUtente' ),
        'Version'                   => array( 'Versione' ),
        'Wantedcategories'          => array( 'CategorieRichieste' ),
@@ -311,7 +312,7 @@ $messages = array(
 'tog-watchdeletion' => 'Aggiungi le pagine e i file cancellati agli osservati speciali',
 'tog-minordefault' => 'Indica ogni modifica come minore (solo come predefinito)',
 'tog-previewontop' => "Mostra l'anteprima sopra la casella di modifica e non sotto",
-'tog-previewonfirst' => "Mostra l'anteprima per la prima modifica",
+'tog-previewonfirst' => "Mostra l'anteprima almeno una volta prima di salvare",
 'tog-nocache' => 'Disabilita la cache delle pagine del browser',
 'tog-enotifwatchlistpages' => 'Inviami una email quando viene modificata una pagina o un file presente tra gli osservati speciali',
 'tog-enotifusertalkpages' => 'Segnalami via e-mail le modifiche alla mia pagina di discussione',
@@ -564,12 +565,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Estratto da "$1"',
 'youhavenewmessages' => 'Hai $1 ($2).',
-'newmessageslink' => 'nuovi messaggi',
-'newmessagesdifflink' => 'ultima modifica',
 'youhavenewmessagesfromusers' => 'Hai $1 da {{PLURAL:$3|un altro utente|$3 utenti}} ($2).',
 'youhavenewmessagesmanyusers' => 'Hai $1 da molti utenti ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un nuovo messaggio|nuovi messaggi}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|ultima modifica|ultime modifiche}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un nuovo messaggio|999=nuovi messaggi}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|ultima modifica|999=ultime modifiche}}',
 'youhavenewmessagesmulti' => 'Hai nuovi messaggi su $1',
 'editsection' => 'modifica',
 'editold' => 'modifica',
@@ -699,7 +698,8 @@ L\'amministratore che lo ha bloccato ha fornito questa motivazione: "$3".',
 'invalidtitle-knownnamespace' => 'Titolo non valido con namespace "$2" e testo "$3"',
 'invalidtitle-unknownnamespace' => 'Titolo non valido con namespace sconosciuto "$1" e testo "$2"',
 'exception-nologin' => 'Accesso non effettuato',
-'exception-nologin-text' => "Questa pagina o azione richiede che tu abbia effettuato l'accesso su questa wiki.",
+'exception-nologin-text' => "Si prega di [[Special:Userlogin|eseguire l'accesso]] per poter accedere a questa pagina o azione.",
+'exception-nologin-text-manual' => 'Si prega di $1 per poter accedere a questa pagina o azione.',
 
 # Virus scanner
 'virus-badscanner' => "Errore di configurazione: antivirus sconosciuto: ''$1''",
@@ -746,7 +746,7 @@ Non dimenticare di personalizzare le [[Special:Preferences|preferenze di {{SITEN
 'gotaccount' => 'Hai già un accesso? $1.',
 'gotaccountlink' => 'Entra',
 'userlogin-resetlink' => 'Hai dimenticato i tuoi dati di accesso?',
-'userlogin-resetpassword-link' => 'Reimposta la tua password',
+'userlogin-resetpassword-link' => 'Hai dimenticato la password?',
 'helplogin-url' => 'Help:Login',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Aiuto con il login]]',
 'userlogin-loggedin' => 'Sei già connesso come {{GENDER:$1|$1}}.
@@ -793,7 +793,7 @@ Assicurati di avere attivato i cookie, ricarica questa pagina e riprova.",
 'passwordtooshort' => 'Le password devono contenere almeno {{PLURAL:$1|1 carattere|$1 caratteri}}.',
 'password-name-match' => 'La password deve essere diversa dal nome utente.',
 'password-login-forbidden' => "L'uso di questo nome utente e password è stato proibito.",
-'mailmypassword' => 'Invia una nuova password al mio indirizzo e-mail',
+'mailmypassword' => 'Reimposta password',
 'passwordremindertitle' => 'Servizio Password Reminder di {{SITENAME}}',
 'passwordremindertext' => 'Qualcuno (probabilmente tu, con indirizzo IP $1) ha richiesto l\'invio di una nuova password di accesso a {{SITENAME}} ($4).
 Una password temporanea per l\'utente "$2" è stata impostata a "$3".
@@ -805,8 +805,8 @@ Se non sei stato tu a fare la richiesta, oppure hai ritrovato la password e non
 'passwordsent' => 'Una nuova password è stata inviata all\'indirizzo e-mail registrato per l\'utente "$1".
 Per favore, effettua un accesso non appena la ricevi.',
 'blocked-mailpassword' => 'Per prevenire abusi, non è consentito usare la funzione "Invia nuova password" da un indirizzo IP bloccato.',
-'eauthentsent' => "Un messaggio e-mail di conferma è stato spedito all'indirizzo indicato.
-Per abilitare l'invio di messaggi e-mail per questo accesso è necessario seguire le istruzioni che vi sono indicate, in modo da confermare che si è i legittimi proprietari dell'indirizzo",
+'eauthentsent' => "Un messaggio email di conferma è stato spedito all'indirizzo indicato.
+Per abilitare l'invio di messaggi email per questo utente è necessario seguire le istruzioni che vi sono indicate, in modo da confermare che si è i legittimi proprietari dell'indirizzo.",
 'throttled-mailpassword' => 'Una email di reimpostazione della password è già stata inviata da meno di {{PLURAL:$1|1 ora|$1 ore}}.
 Per prevenire abusi, la funzione di reimpostazione della password può essere usata solo una volta ogni {{PLURAL:$1|ora|$1 ore}}.',
 'mailerror' => "Errore nell'invio del messaggio: $1",
@@ -862,7 +862,7 @@ La password potrebbe essere stata già cambiata, oppure potrebbe essere stata ri
 # Special:PasswordReset
 'passwordreset' => 'Reimposta password',
 'passwordreset-text-one' => 'Compila questo modulo per reimpostare la tua password.',
-'passwordreset-text-many' => '{{PLURAL:$1|Compila uno dei campi per reimpostare la tua password.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Compila uno dei campi per ricevere una password temporanea tramite email.}}',
 'passwordreset-legend' => 'Reimposta password',
 'passwordreset-disabled' => 'La reimpostazione delle password è stata disabilitata su questa wiki',
 'passwordreset-emaildisabled' => 'Le funzionalità di posta elettronica sono state disabilitate su questa wiki.',
@@ -1233,19 +1233,20 @@ In quanto amministratore puoi visualizzare questo confronto di versioni; potrebb
 'revdelete-text' => "'''Le versioni cancellate restano visibili nella cronologia della pagina, mentre il testo contenuto non è accessibile al pubblico.'''
 Gli altri amministratori di {{SITENAME}} potranno accedere comunque ai contenuti nascosti e ripristinarli attraverso questa stessa interfaccia, se non sono state impostate altre limitazioni in fase di installazione del sito.",
 'revdelete-confirm' => 'Per favore conferma che questo è quanto intendi fare, che sei consapevole delle conseguenze, e che stai facendo questo nel rispetto delle [[{{MediaWiki:Policy-url}}|linee guida]].',
-'revdelete-suppress-text' => "La rimozione deve essere utilizzata '''unicamente''' nei seguenti casi:
-* Dati personali inopportuni
+'revdelete-suppress-text' => "La rimozione dovrebbe essere utilizzata '''unicamente''' nei seguenti casi:
+* informazioni potenzialmente diffamatorie
+* dati personali inopportuni
 *: ''indirizzi, numeri di telefono, codici fiscali, ecc.''",
 'revdelete-legend' => 'Imposta le seguenti limitazioni sulle versioni cancellate:',
-'revdelete-hide-text' => 'Nascondi il testo della versione',
+'revdelete-hide-text' => 'Testo della versione',
 'revdelete-hide-image' => 'Nascondi i contenuti del file',
 'revdelete-hide-name' => 'Nascondi azione e oggetto della stessa',
-'revdelete-hide-comment' => "Nascondi l'oggetto della modifica o la motivazione dell'azione",
-'revdelete-hide-user' => "Nascondi il nome o l'indirizzo IP dell'autore",
+'revdelete-hide-comment' => "Oggetto della modifica o motivazione dell'azione",
+'revdelete-hide-user' => "Nome o indirizzo IP dell'autore",
 'revdelete-hide-restricted' => 'Nascondi le informazioni indicate anche agli amministratori',
 'revdelete-radio-same' => '(non cambiare)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'No',
+'revdelete-radio-set' => 'Nascondi',
+'revdelete-radio-unset' => 'Mostra',
 'revdelete-suppress' => 'Nascondi le informazioni anche agli amministratori',
 'revdelete-unsuppress' => 'Elimina le limitazioni sulle revisioni ripristinate',
 'revdelete-log' => 'Motivo:',
@@ -1395,8 +1396,7 @@ I dettagli possono essere trovati nel [{{fullurl:{{#Special:Log}}/delete|page={{
 'preferences' => 'Preferenze',
 'mypreferences' => 'preferenze',
 'prefs-edits' => 'Modifiche effettuate:',
-'prefsnologin' => 'Accesso non effettuato',
-'prefsnologintext' => 'Per poter personalizzare le preferenze è necessario effettuare l\'<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} accesso]</span>.',
+'prefsnologintext2' => "Si prega di $1 per impostare le preferenze dell'utente.",
 'changepassword' => 'Cambia password',
 'prefs-skin' => 'Aspetto grafico (skin)',
 'skin-preview' => 'Anteprima',
@@ -1694,6 +1694,9 @@ Il tuo indirizzo non viene rivelato quando gli altri utenti ti contattano.',
 'recentchanges-label-minor' => 'Questa è una modifica minore',
 'recentchanges-label-bot' => 'Questa modifica è stata effettuata da un bot',
 'recentchanges-label-unpatrolled' => 'Questa modifica non è stata ancora verificata',
+'recentchanges-label-plusminus' => 'La dimensione della pagina è cambiata di questo numero di byte',
+'recentchanges-legend-newpage' => "(vedi anche [[Special:NewPages|l'elenco delle nuove pagine]])",
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Di seguito {{PLURAL:$1|è elencata la modifica più recente apportata|sono elencate le '''$1''' modifiche più recenti apportate}} al sito {{PLURAL:$2|nelle ultime 24 ore|negli scorsi '''$2''' giorni}}; i dati sono aggiornati alle $5 del $4.",
 'rcnotefrom' => "Di seguito sono elencate le modifiche apportate a partire da '''$2''' (fino a '''$1''').",
 'rclistfrom' => 'Mostra le modifiche apportate a partire da $1',
@@ -2316,9 +2319,9 @@ Potrebbero esserci [[{{MediaWiki:Listgrouprights-helppage}}|ulteriori informazio
 'mailnologin' => 'Nessun indirizzo cui inviare il messaggio',
 'mailnologintext' => 'Per inviare messaggi e-mail ad altri utenti è necessario [[Special:UserLogin|accedere al sito]] e aver registrato un indirizzo valido nelle proprie [[Special:Preferences|preferenze]].',
 'emailuser' => "Scrivi all'utente",
-'emailuser-title-target' => 'Invia una e-mail a questo {{GENDER:$1|utente}}',
-'emailuser-title-notarget' => 'Invia una e-mail a un utente',
-'emailpage' => "Invia un messaggio e-mail all'utente",
+'emailuser-title-target' => 'Invia una email a questo {{GENDER:$1|utente}}',
+'emailuser-title-notarget' => 'Invia una email a un utente',
+'emailpage' => "Invia un messaggio email all'utente",
 'emailpagetext' => 'Usare il modulo sottostante per inviare un messaggio e-mail all\'{{GENDER:$1|utente}} indicato. L\'indirizzo specificato nelle [[Special:Preferences|preferenze]] del mittente apparirà nel campo "Da:" del messaggio per consentire al destinatario di rispondere direttamente.',
 'usermailererror' => "L'oggetto mail ha restituito l'errore:",
 'defemailsubject' => 'Messaggio da {{SITENAME}} dall\'utente "$1"',
@@ -2342,7 +2345,7 @@ Potrebbero esserci [[{{MediaWiki:Listgrouprights-helppage}}|ulteriori informazio
 'emailccsubject' => 'Copia del messaggio inviato a $1: $2',
 'emailsent' => 'Messaggio inviato',
 'emailsenttext' => 'Il messaggio e-mail è stato inviato.',
-'emailuserfooter' => 'Questa e-mail è stata inviata da $1 a $2 attraverso la funzione "Invia un messaggio e-mail all\'utente" su {{SITENAME}}.',
+'emailuserfooter' => 'Questa email è stata inviata da $1 a $2 attraverso la funzione "Invia un messaggio email all\'utente" su {{SITENAME}}.',
 
 # User Messenger
 'usermessage-summary' => 'Messaggio di sistema',
@@ -2410,9 +2413,9 @@ Contatta l\'autore:
 via posta elettronica: $PAGEEDITOR_EMAIL
 sul sito: $PAGEEDITOR_WIKI
 
-Non verranno inviate altre notifiche in caso di ulteriori attività, se non visiti la pagina. Inoltre, è possibile modificare le impostazioni di notifica per tutte le pagine nella lista degli osservati speciali.
+Non verranno inviate altre notifiche in caso di ulteriori attività, se non visiti la pagina dopo aver effettuato l\'accesso. Inoltre, è possibile modificare le impostazioni di notifica per tutte le pagine nella lista degli osservati speciali.
 
-             Il sistema di notifica di {{SITENAME}}, al tuo servizio
+Il sistema di notifica di {{SITENAME}}, al tuo servizio
 
 --
 Per modificare le impostazioni delle notifiche via posta elettronica, visita 
@@ -2676,7 +2679,7 @@ Indicare il motivo specifico per il quale si procede al blocco (per esempio, cit
 ** Nome utente non consono',
 'ipb-hardblock' => 'Impedisci agli utenti registrati di contribuire da questo indirizzo IP',
 'ipbcreateaccount' => 'Impedisci la registrazione',
-'ipbemailban' => "Impedisci all'utente l'invio di e-mail",
+'ipbemailban' => "Impedisci all'utente l'invio di email",
 'ipbenableautoblock' => "Blocca automaticamente l'ultimo indirizzo IP usato dall'utente e i successivi con cui vengono tentate modifiche",
 'ipbsubmit' => "Blocca l'utente",
 'ipbother' => 'Durata non in elenco:',
@@ -2906,7 +2909,7 @@ In quest'ultimo caso si può anche utilizzare un collegamento, ad esempio [[{{#S
 'allmessagesdefault' => 'Testo predefinito',
 'allmessagescurrent' => 'Testo attuale',
 'allmessagestext' => 'Questa è la lista di tutti i messaggi di sistema disponibili nel namespace MediaWiki.
-Visitare [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se si desidera contribuire alla localizzazione generica di MediaWiki.',
+Visitare [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se si desidera contribuire alla localizzazione generica di MediaWiki.',
 'allmessagesnotsupportedDB' => "Non è possibile utilizzare questa pagina perché il flag '''\$wgUseDatabaseMessages''' non è attivo.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtra per stato di modifica:',
@@ -3038,7 +3041,7 @@ Tutte le operazioni di importazione trans-wiki sono registrate nel [[Special:Log
 'tooltip-feed-rss' => 'Feed RSS per questa pagina',
 'tooltip-feed-atom' => 'Feed Atom per questa pagina',
 'tooltip-t-contributions' => 'Lista dei contributi di questo utente',
-'tooltip-t-emailuser' => 'Invia un messaggio e-mail a questo utente',
+'tooltip-t-emailuser' => 'Invia un messaggio email a questo utente',
 'tooltip-t-upload' => 'Carica file multimediali',
 'tooltip-t-specialpages' => 'Lista di tutte le pagine speciali',
 'tooltip-t-print' => 'Versione stampabile di questa pagina',
@@ -3115,6 +3118,8 @@ Tutte le operazioni di importazione trans-wiki sono registrate nel [[Special:Log
 'spam_reverting' => "Ripristinata l'ultima versione priva di collegamenti a $1",
 'spam_blanking' => 'Pagina svuotata, tutte le versioni contenevano collegamenti a $1',
 'spam_deleting' => 'Pagina cancellata, tutte le versioni contenevano collegamenti a $1',
+'simpleantispam-label' => "Controllo anti-spam.
+'''NON''' riempire!",
 
 # Info page
 'pageinfo-title' => 'Informazioni per "$1"',
@@ -3128,6 +3133,7 @@ Tutte le operazioni di importazione trans-wiki sono registrate nel [[Special:Log
 'pageinfo-length' => 'Lunghezza della pagina (in byte)',
 'pageinfo-article-id' => 'ID della pagina',
 'pageinfo-language' => 'Lingua del contenuto della pagina',
+'pageinfo-content-model' => 'Modello del contenuto della pagina',
 'pageinfo-robot-policy' => 'Indicizzazione per i robot',
 'pageinfo-robot-index' => 'Consentito',
 'pageinfo-robot-noindex' => 'Non consentito',
@@ -3207,7 +3213,7 @@ $1',
 'svg-long-desc' => 'file in formato SVG, dimensioni nominali $1 × $2 pixel, dimensione del file: $3',
 'svg-long-desc-animated' => 'file in formato SVG animato, dimensioni nominali $1 × $2 pixel, dimensione del file: $3',
 'svg-long-error' => 'File SVG non valido: $1',
-'show-big-image' => 'Versione ad alta risoluzione',
+'show-big-image' => 'File originale',
 'show-big-image-preview' => 'Dimensioni di questa anteprima: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Altra risoluzione|Altre risoluzioni}}: $1.',
 'show-big-image-size' => '$1 × $2 pixel',
@@ -3684,7 +3690,7 @@ I collegamenti successivi, sulla stessa riga, sono considerati come eccezioni (o
 
 # External editor support
 'edit-externally' => 'Modifica questo file usando un programma esterno',
-'edit-externally-help' => '(Per maggiori informazioni consultare le [//www.mediawiki.org/wiki/Manual:External_editors istruzioni])',
+'edit-externally-help' => '(Per maggiori informazioni consultare le [https://www.mediawiki.org/wiki/Manual:External_editors istruzioni])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tutte',
@@ -3699,7 +3705,7 @@ I collegamenti successivi, sulla stessa riga, sono considerati come eccezioni (o
 'confirmemail_pending' => "Il codice di conferma è già stato spedito via posta elettronica; se l'account è stato
 creato di recente, si prega di attendere l'arrivo del codice per qualche minuto prima
 di tentare di richiederne uno nuovo.",
-'confirmemail_send' => 'Invia un codice di conferma via e-mail.',
+'confirmemail_send' => 'Invia un codice di conferma via email.',
 'confirmemail_sent' => 'Messaggio e-mail di conferma inviato.',
 'confirmemail_oncreate' => "Un codice di conferma è stato spedito all'indirizzo
 di posta elettronica indicato. Il codice non è necessario per accedere al sito,
@@ -3783,6 +3789,7 @@ Per favore, conferma che vuoi veramente ricreare questa pagina.",
 
 # Separators for various lists, etc.
 'percent' => '$1&#160;%',
+'quotation-marks' => '«$1»',
 
 # Multipage image navigation
 'imgmultipageprev' => '← pagina precedente',
@@ -3877,7 +3884,7 @@ Si noti che è anche possibile [[Special:EditWatchlist|modificare la lista con l
 'version-hook-subscribedby' => 'Sottoscrizioni',
 'version-version' => '(Versione $1)',
 'version-license' => 'Licenza',
-'version-poweredby-credits' => "Questo wiki è realizzato con '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Questo wiki è realizzato con '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'altri',
 'version-poweredby-translators' => 'traduttori di translatewiki.net',
 'version-credits-summary' => 'Siamo lieti di riconoscere le seguenti persone per aver contribuito a [[Special:Version|MediaWiki]].',
@@ -3898,7 +3905,8 @@ Questo programma deve essere distribuito assieme ad [{{SERVER}}{{SCRIPTPATH}}/CO
 # Special:Redirect
 'redirect' => 'Reindirizzamento da file, utente o ID versione',
 'redirect-legend' => 'Reindirizza a un file o una pagina',
-'redirect-summary' => 'Questa pagina speciale reindirizza a un file (specificando il nome del file), a una pagina (specificando un ID di versione) o a un utente (specificando un ID utente numerico).',
+'redirect-summary' => 'Questa pagina speciale reindirizza a un file (specificando il nome del file), a una pagina (specificando un ID di versione) o a un utente (specificando un ID utente numerico).
+Esempi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Vai',
 'redirect-lookup' => 'Ricerca:',
 'redirect-value' => 'Valore:',
@@ -3920,10 +3928,9 @@ Questo programma deve essere distribuito assieme ad [{{SERVER}}{{SCRIPTPATH}}/CO
 
 # Special:SpecialPages
 'specialpages' => 'Pagine speciali',
-'specialpages-note' => '----
-* Pagine speciali non riservate.
-* <span class="mw-specialpagerestricted">Pagine speciali riservate ad alcune categorie di utenti.</span>
-* <span class="mw-specialpagecached">Pagine speciali disponibili in versione cache (potrebbero essere obsolete).</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Pagine speciali non riservate.
+* <span class="mw-specialpagerestricted">Pagine speciali riservate ad alcune categorie di utenti.</span>',
 'specialpages-group-maintenance' => 'Resoconti di manutenzione',
 'specialpages-group-other' => 'Altre pagine speciali',
 'specialpages-group-login' => 'Accesso / creazione utenze',
@@ -4135,4 +4142,21 @@ Questo programma deve essere distribuito assieme ad [{{SERVER}}{{SCRIPTPATH}}/CO
 'limitreport-expansiondepth' => 'Massima profondità di espansione',
 'limitreport-expensivefunctioncount' => 'Numero funzioni parser dispendiose',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espansione dei template',
+'expand_templates_intro' => 'Questa pagina speciale elabora un testo espandendo tutti i template presenti.
+Calcola inoltre il risultato delle funzioni supportate dal parser come
+<code><nowiki>{{</nowiki>#language:…}}</code> e delle variabili di sistema quali
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>,
+vale a dire praticamente tutto ciò che si trova tra doppie parentesi graffe.',
+'expand_templates_title' => 'Contesto (per {{FULLPAGENAME}} ecc.):',
+'expand_templates_input' => 'Testo da espandere:',
+'expand_templates_output' => 'Risultato',
+'expand_templates_xml_output' => 'Output in formato XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Ignora i commenti',
+'expand_templates_remove_nowiki' => 'Elimina il tag <nowiki> nel risultato',
+'expand_templates_generate_xml' => 'Mostra albero sintattico XML',
+'expand_templates_preview' => 'Anteprima',
+
 );
index 29a2f53..da30f99 100644 (file)
@@ -120,7 +120,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( '不正なページ名' ),
        'Blankpage'                 => array( '白紙ページ' ),
        'Block'                     => array( '投稿ブロック', 'ブロック' ),
-       'Blockme'                   => array( '自己ブロック' ),
        'Booksources'               => array( '文献資料', '書籍情報源' ),
        'BrokenRedirects'           => array( '迷子のリダイレクト', '壊れたリダイレクト' ),
        'Categories'                => array( 'カテゴリ', 'カテゴリ一覧' ),
@@ -132,10 +131,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'アカウント作成', 'アカウントの作成' ),
        'Deadendpages'              => array( '有効なページへのリンクがないページ', '行き止まりページ' ),
        'DeletedContributions'      => array( '削除された投稿記録', '削除された投稿履歴', '削除歴' ),
-       'Disambiguations'           => array( '曖昧さ回避のページ', '曖昧さ回避' ),
        'DoubleRedirects'           => array( '二重リダイレクト', '二重転送' ),
        'EditWatchlist'             => array( 'ウォッチリストの編集', 'ウォッチリスト編集' ),
        'Emailuser'                 => array( 'メール送信', 'ウィキメール' ),
+       'ExpandTemplates'           => array( 'テンプレートを展開' ),
        'Export'                    => array( 'データ書き出し', 'データー書き出し', 'エクスポート' ),
        'Fewestrevisions'           => array( '編集履歴の少ないページ', '版の少ない項目', '版の少ないページ' ),
        'FileDuplicateSearch'       => array( '重複ファイル検索' ),
@@ -180,10 +179,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( '保護されているページ' ),
        'Protectedtitles'           => array( '作成保護されているページ名' ),
        'Randompage'                => array( 'おまかせ表示' ),
+       'RandomInCategory'          => array( 'カテゴリ内おまかせ表示', 'カテゴリ中のランダムなページ' ),
        'Randomredirect'            => array( 'おまかせリダイレクト', 'おまかせ転送' ),
        'Recentchanges'             => array( '最近の更新', '最近更新したページ' ),
        'Recentchangeslinked'       => array( '関連ページの更新状況', 'リンク先の更新状況' ),
        'Redirect'                  => array( '転送', 'リダイレクト' ),
+       'ResetTokens'               => array( 'トークンの再設定' ),
        'Revisiondelete'            => array( '版指定削除', '特定版削除' ),
        'Search'                    => array( '検索' ),
        'Shortpages'                => array( '短いページ' ),
@@ -642,12 +643,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => '「$1」から取得',
 'youhavenewmessages' => '$1があります ($2)。',
-'newmessageslink' => '新着メッセージ',
-'newmessagesdifflink' => '最新の差分',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|他の利用者|$3 人の利用者}}からの$1があります ($2)。',
 'youhavenewmessagesmanyusers' => '多数の利用者からの$1があります ($2)。',
 'newmessageslinkplural' => '{{PLURAL:$1|新着メッセージ}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|最新の差分|最新版までの差分}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|最新の差分|999=最新版までの差分}}',
 'youhavenewmessagesmulti' => '$1に新着メッセージがあります',
 'editsection' => '編集',
 'editold' => '編集',
@@ -782,7 +781,8 @@ $2',
 'invalidtitle-knownnamespace' => '名前空間名「$2」と名前「$3」の組み合わせはページ名として無効です',
 'invalidtitle-unknownnamespace' => '不明な名前空間番号 $1 と名前「$2」の組み合わせはページ名として無効です',
 'exception-nologin' => 'ログインしていません',
-'exception-nologin-text' => 'このページまたは操作には、このウィキへのログインが必要です。',
+'exception-nologin-text' => 'このページまたは操作にアクセスできるようにするには[[Special:Userlogin|ログイン]]してください。',
+'exception-nologin-text-manual' => 'このページまたは操作にアクセスできるようにするには$1してください。',
 
 # Virus scanner
 'virus-badscanner' => "環境設定が不適合です: 不明なウイルス対策ソフトウェア: ''$1''",
@@ -795,7 +795,7 @@ $2',
 ページによっては、ブラウザーのキャッシュをクリアするまで、ログインしているかのように表示され続ける場合があるためご注意ください。",
 'welcomeuser' => 'ようこそ、$1さん!',
 'welcomecreation-msg' => 'アカウントが作成されました。
-[[Special:Preferences|{{SITENAME}}の個人設定]]の変更も忘れないようにしてください。',
+お好みで[[Special:Preferences|{{SITENAME}}の個人設定]]を変更できます。',
 'yourname' => '利用者名:',
 'userlogin-yourname' => '利用者名',
 'userlogin-yourname-ph' => '利用者名を入力',
@@ -829,7 +829,7 @@ $2',
 'gotaccount' => 'アカウントを既に持っている場合、$1。',
 'gotaccountlink' => 'ログインしてください',
 'userlogin-resetlink' => 'ログイン情報をお忘れですか?',
-'userlogin-resetpassword-link' => 'パスワードを再設定',
+'userlogin-resetpassword-link' => 'パスワードをお忘れですか?',
 'helplogin-url' => 'Help:ログイン',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|ログインのヘルプ]]',
 'userlogin-loggedin' => '{{GENDER:$1|$1}} として既にログインしています。
@@ -864,9 +864,9 @@ $2',
 {{SITENAME}}では利用者のログインに Cookie を使用します。
 ご使用のブラウザーでは Cookie が無効になっています。
 Cookie を有効にしてから、新しい利用者名とパスワードでログインしてください。',
-'nocookieslogin' => '{{SITENAME}}ではログインにCookieを使用します。
-Cookieを無効にしているようです。
-Cookieを有効にしてから、もう一度試してください。',
+'nocookieslogin' => '{{SITENAME}}ではログインに Cookie を使用します。
+Cookie を無効にしているようです。
+Cookie を有効にしてから、もう一度試してください。',
 'nocookiesfornew' => '発信元を確認できなかったため、アカウントは作成されませんでした。
 Cookieを有効にしていることを確認して、このページを再読込してもう一度試してください。',
 'nocookiesforlogin' => '{{int:nocookieslogin}}',
@@ -887,7 +887,7 @@ Cookieを有効にしていることを確認して、このページを再読
 'passwordtooshort' => 'パスワードは {{PLURAL:$1|$1 文字}}以上にしてください。',
 'password-name-match' => 'パスワードは利用者名とは異なる必要があります。',
 'password-login-forbidden' => 'この利用者名とパスワードの使用は禁止されています。',
-'mailmypassword' => '新しいパスワードをメールで送信',
+'mailmypassword' => 'パスワードを再設定',
 'passwordremindertitle' => '{{SITENAME}}の仮パスワード通知',
 'passwordremindertext' => '誰か (おそらくあなた) が IP アドレス $1 から{{SITENAME}} ($4) のログイン用パスワードの再発行を申請しました。
 利用者「$2」の仮パスワードが作成され「$3」に設定されました。
@@ -908,9 +908,9 @@ Cookieを有効にしていることを確認して、このページを再読
 'mailerror' => 'メールを送信する際にエラーが発生しました: $1',
 'acct_creation_throttle_hit' => 'あなたと同じ IP アドレスでこのウィキに訪れた人が、最近 24 時間で {{PLURAL:$1|$1 アカウント}}を作成しており、これはこの期間で作成が許可されている最大数です。
 そのため、現在この IP アドレスではアカウントをこれ以上作成できません。',
-'emailauthenticated' => 'メールアドレスは$2 $3に認証済みです。',
-'emailnotauthenticated' => 'メールアドレスが認証されていません。
-認証されるまで、以下のいかなる機能でもメールは送信されません。',
+'emailauthenticated' => 'メールアドレスは$2 $3に確認済みです。',
+'emailnotauthenticated' => 'メールアドレスが確認されていません。
+確認されるまで、以下のいかなる機能でもメールは送信されません。',
 'noemailprefs' => 'これらの機能を有効にするには、個人設定でメールアドレスを登録してください。',
 'emailconfirmlink' => 'あなたのメールアドレスを確認',
 'invalidemailaddress' => '入力されたメールアドレスが正しい形式に従っていないため、受け付けられません。
@@ -961,8 +961,8 @@ $1待ってから再度試してください。',
 
 # Special:PasswordReset
 'passwordreset' => 'パスワードの再設定',
-'passwordreset-text-one' => 'パスワードを再設定するにはこのフォームに記入してください。',
-'passwordreset-text-many' => '{{PLURAL:$1|パスワードを再設定するにはいずれかの欄に記入してください。}}',
+'passwordreset-text-one' => '仮パスワードをメールで受け取るにはこのフォームに記入してください。',
+'passwordreset-text-many' => '{{PLURAL:$1|仮パスワードをメールで受け取るにはいずれかの欄に記入してください。}}',
 'passwordreset-legend' => 'パスワードの再設定',
 'passwordreset-disabled' => 'パスワードの再設定は、このウィキでは無効になっています。',
 'passwordreset-emaildisabled' => 'メール機能は、このウィキでは無効化されています。',
@@ -1365,17 +1365,17 @@ $3が示した理由: ''$2''",
 'revdelete-suppress-text' => "秘匿は、'''以下の場合に限って'''使用すべきです:
 * 名誉毀損のおそれがある記述
 * 非公開個人情報
-*: ''自宅の住所、電話番号、社会保障番号など''",
+*: ''自宅の住所、電話番号、個人を識別できる公的な番号など''",
 'revdelete-legend' => '閲覧レベル制限を設定',
-'revdelete-hide-text' => '版の本文を隠す',
+'revdelete-hide-text' => '版の本文',
 'revdelete-hide-image' => 'ファイル内容を隠す',
 'revdelete-hide-name' => '操作および対象を隠す',
-'revdelete-hide-comment' => '編集の要約を隠す',
-'revdelete-hide-user' => '投稿者の利用者名またはIPを隠す',
+'revdelete-hide-comment' => '編集の要約',
+'revdelete-hide-user' => '投稿者の利用者名/IPアドレス',
 'revdelete-hide-restricted' => '他の利用者と同様に管理者からもデータを隠す',
 'revdelete-radio-same' => '(変更しない)',
-'revdelete-radio-set' => 'はい',
-'revdelete-radio-unset' => 'いいえ',
+'revdelete-radio-set' => '非公開',
+'revdelete-radio-unset' => '閲覧可能',
 'revdelete-suppress' => '他の利用者と同様に管理者からもデータを隠す',
 'revdelete-unsuppress' => '復元版に対する制限を除去',
 'revdelete-log' => '理由:',
@@ -1534,8 +1534,7 @@ $1",
 'preferences' => '個人設定',
 'mypreferences' => '個人設定',
 'prefs-edits' => '編集回数:',
-'prefsnologin' => 'ログインしていません',
-'prefsnologintext' => '個人設定を変更するためには<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ログイン]</span>する必要があります。',
+'prefsnologintext2' => '個人設定を変更するには$1してください。',
 'changepassword' => 'パスワードの変更',
 'prefs-skin' => '外装',
 'skin-preview' => 'プレビュー',
@@ -1841,6 +1840,9 @@ $1 {{PLURAL:$1|文字}}以下である必要があります。',
 'recentchanges-label-minor' => 'これは細部の編集です',
 'recentchanges-label-bot' => 'この編集はボットによって行われました',
 'recentchanges-label-unpatrolled' => 'この編集はまだ巡回されていません',
+'recentchanges-label-plusminus' => 'ページ サイズの増減 (バイト単位)',
+'recentchanges-legend-newpage' => '([[Special:NewPages|新しいページ一覧]]も参照してください)',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "$4 $5 までの{{PLURAL:$2|'''$2'''日間}}になされた{{PLURAL:$1|'''$1'''件の変更}}は以下の通りです。",
 'rcnotefrom' => "以下は'''$2'''以降の更新です (最大 '''$1''' 件)。",
 'rclistfrom' => '$1以降の更新を表示する',
@@ -2593,9 +2595,9 @@ $PAGEINTRO $NEWPAGE
 メール: $PAGEEDITOR_EMAIL
 ウィキ: $PAGEEDITOR_WIKI
 
-このページを訪れない限り、これ以上の活動に対する通知は送信されません。ウォッチリスト内のすべてのページについて、通知を再設定することもできます。
\83­ã\82°ã\82¤ã\83³ã\81\97ã\81\9fç\8a¶æ\85\8bã\81§ã\81\93ã\81®ã\83\9aã\83¼ã\82¸ã\82\92訪ã\82\8cã\81ªã\81\84é\99\90ã\82\8aã\80\81ã\81\93ã\82\8c以ä¸\8aã\81®æ´»å\8b\95ã\81«å¯¾ã\81\99ã\82\8bé\80\9aç\9f¥ã\81¯é\80\81ä¿¡ã\81\95ã\82\8cã\81¾ã\81\9bã\82\93ã\80\82ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88å\86\85ã\81®ã\81\99ã\81¹ã\81¦ã\81®ã\83\9aã\83¼ã\82¸ã\81«ã\81¤ã\81\84ã\81¦ã\80\81é\80\9aç\9f¥ã\82\92å\86\8d設å®\9aã\81\99ã\82\8bã\81\93ã\81¨ã\82\82ã\81§ã\81\8dã\81¾ã\81\99ã\80\82
 
-                         {{SITENAME}}通知システム
+{{SITENAME}}通知システム
 
 --
 メール通知の設定は、以下のページで変更してください:
@@ -3128,7 +3130,7 @@ $1 のブロックの理由は「''$2''」です。",
 'allmessagesdefault' => '既定のメッセージ文',
 'allmessagescurrent' => '現在のメッセージ文',
 'allmessagestext' => 'これは MediaWiki 名前空間で利用できるシステム メッセージの一覧です。
-MediaWiki 全般のローカライズ (地域化) に貢献したい場合は、[//www.mediawiki.org/wiki/Localisation/ja MediaWiki のローカライズ]や [//translatewiki.net?setlang=ja translatewiki.net] をご覧ください。',
+MediaWiki 全般のローカライズ (地域化) に貢献したい場合は、[https://www.mediawiki.org/wiki/Localisation/ja MediaWiki のローカライズ]や [//translatewiki.net?setlang=ja translatewiki.net] をご覧ください。',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages'''が無効のため、このページを使用できません。",
 'allmessages-filter-legend' => '絞り込み',
 'allmessages-filter' => '変更状態により絞り込む:',
@@ -3295,6 +3297,7 @@ $2',
 'tooltip-undo' => '「取り消し」はこの編集を差し戻し、編集画面をプレビュー付きで開きます。要約欄に理由を追加できます。',
 'tooltip-preferences-save' => '設定を保存する',
 'tooltip-summary' => '短い要約を入力してください',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* ここに記述したCSSはすべての外装に反映されます */',
@@ -3344,6 +3347,8 @@ $2',
 'spam_reverting' => '$1へのリンクを含まない最新の版に差し戻し',
 'spam_blanking' => 'すべての版が$1へのリンクを含んでいます。白紙化します。',
 'spam_deleting' => 'すべての版が$1へのリンクを含んでいます。削除します。',
+'simpleantispam-label' => "スパム攻撃防止用のチェックです。
+ここに値を決して入力'''しない'''でください。",
 
 # Info page
 'pageinfo-title' => '「$1」の情報',
@@ -3357,6 +3362,7 @@ $2',
 'pageinfo-length' => 'ページの長さ (バイト単位)',
 'pageinfo-article-id' => 'ページ ID',
 'pageinfo-language' => 'ページ本文の言語',
+'pageinfo-content-model' => 'ページのコンテンツ モデル',
 'pageinfo-robot-policy' => 'ロボットによるインデックス作成',
 'pageinfo-robot-index' => '許可',
 'pageinfo-robot-noindex' => '不許可',
@@ -3445,7 +3451,7 @@ $1',
 'svg-long-desc' => 'SVG ファイル、$1 × $2 ピクセル、ファイルサイズ: $3',
 'svg-long-desc-animated' => 'アニメーション SVG ファイル、$1 × $2 ピクセル、ファイルサイズ: $3',
 'svg-long-error' => '無効な SVG ファイル: $1',
-'show-big-image' => '高解像度での画像',
+'show-big-image' => '元のファイル',
 'show-big-image-preview' => 'このプレビューのサイズ: $1。',
 'show-big-image-other' => 'その他の{{PLURAL:$2|解像度}}: $1。',
 'show-big-image-size' => '$1 × $2 ピクセル',
@@ -3972,7 +3978,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => '外部アプリケーションを使用してこのファイルを編集',
-'edit-externally-help' => '(詳しくは[//www.mediawiki.org/wiki/Manual:External_editors 設定手順]をご覧ください)',
+'edit-externally-help' => '(詳しくは[https://www.mediawiki.org/wiki/Manual:External_editors 設定手順]をご覧ください)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'すべて',
@@ -4082,6 +4088,7 @@ $5
 'pipe-separator' => '&#32;|&#32;',
 'word-separator' => '&#32;',
 'parentheses' => '($1)',
+'quotation-marks' => '「$1」',
 
 # Multipage image navigation
 'imgmultipageprev' => '&larr;前ページ',
@@ -4239,7 +4246,7 @@ $5
 'version-hook-subscribedby' => '使用個所',
 'version-version' => '(バージョン $1)',
 'version-license' => 'ライセンス',
-'version-poweredby-credits' => "このウィキは、'''[//www.mediawiki.org/ MediaWiki]''' (copyright © 2001-$1 $2) で動作しています。",
+'version-poweredby-credits' => "このウィキは、'''[https://www.mediawiki.org/ MediaWiki]''' (copyright © 2001-$1 $2) で動作しています。",
 'version-poweredby-others' => 'その他',
 'version-poweredby-translators' => 'translatewiki.net の翻訳者たち',
 'version-credits-summary' => '[[Special:Version|MediaWiki]] に貢献した以下の人たちに感謝します。',
@@ -4260,7 +4267,7 @@ MediaWikiは、有用であることを期待して配布されていますが
 # Special:Redirect
 'redirect' => 'ファイル名、利用者ID、版IDでの転送',
 'redirect-legend' => 'ファイルまたはページヘの転送',
-'redirect-summary' => 'この特別ページは、ファイル (ファイル名を指定)、ページ (版 ID を指定)、利用者ページ (利用者 ID を整数で指定) に転送されます。',
+'redirect-summary' => 'この特別ページは、ファイル (ファイル名を指定)、ページ (版 ID を指定)、利用者ページ (利用者 ID を整数で指定) に転送されます。使用例: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]]',
 'redirect-submit' => '実行',
 'redirect-lookup' => '検索の種類:',
 'redirect-value' => '値:',
@@ -4282,8 +4289,8 @@ MediaWikiは、有用であることを期待して配布されていますが
 
 # Special:SpecialPages
 'specialpages' => '特別ページ',
-'specialpages-note' => '----
-* 通常の特別ページ
+'specialpages-note-top' => '凡例',
+'specialpages-note' => '* 通常の特別ページ
 * <span class="mw-specialpagerestricted">制限されている特別ページ</span>',
 'specialpages-group-maintenance' => 'メンテナンス報告',
 'specialpages-group-other' => 'その他の特別ページ',
@@ -4497,4 +4504,20 @@ MediaWikiは、有用であることを期待して配布されていますが
 'limitreport-expansiondepth' => '展開の最大深さ',
 'limitreport-expensivefunctioncount' => '高負荷パーサー関数の数',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'テンプレートを展開',
+'expand_templates_intro' => 'この特別ページは、入力したテキストに含まれるすべてのテンプレートを再帰的に展開します。
+<code><nowiki>{{</nowiki>#language:…}}</code> のようなパーサー関数や、
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code> のような変数も展開します。
+つまり、二重中括弧で囲まれたものほぼすべてを展開します。',
+'expand_templates_title' => '{{FULLPAGENAME}} などで使用するページ名:',
+'expand_templates_input' => '展開するテキスト:',
+'expand_templates_output' => '展開結果',
+'expand_templates_xml_output' => 'XML 出力',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'コメントを除去',
+'expand_templates_remove_nowiki' => '結果に含まれる <nowiki> タグを表示しない',
+'expand_templates_generate_xml' => 'XML 構文解析ツリーを表示',
+'expand_templates_preview' => 'プレビュー',
+
 );
index a5f8339..eb674e9 100644 (file)
@@ -270,8 +270,6 @@ Si [[Special:Version|voerjan piej]].',
 'ok' => 'OK',
 'retrievedfrom' => 'Richriiv frahn "$1"',
 'youhavenewmessages' => 'Yu gat $1 ($2).',
-'newmessageslink' => 'nyuu mechiz',
-'newmessagesdifflink' => 'laas chienj',
 'youhavenewmessagesmulti' => 'Yu gat nyuu mechiz pahn $1',
 'editsection' => 'edit',
 'editold' => 'edit',
@@ -1067,7 +1065,7 @@ Ada wandem wi aid bai difaalt.
 
 # External editor support
 'edit-externally' => 'Yuuz extoernal aplikieshan fi edit dis fail',
-'edit-externally-help' => '(Si di [//www.mediawiki.org/wiki/Manual:External_editors setop inschrokshan] fi muo infamieshan)',
+'edit-externally-help' => '(Si di [https://www.mediawiki.org/wiki/Manual:External_editors setop inschrokshan] fi muo infamieshan)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'aal',
index 6c315de..07f6c36 100644 (file)
@@ -315,8 +315,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Sumber artikel iki saka kaca situs web: "$1"',
 'youhavenewmessages' => 'Panjenengan kagungan $1 ($2).',
-'newmessageslink' => 'warta énggal',
-'newmessagesdifflink' => 'mirsani bédané saka révisi sadurungé',
 'youhavenewmessagesfromusers' => 'Sampéyan nduwé $1 saka  {{PLURAL:$3|panganggo liya|$3 panganggo}} ($2).',
 'youhavenewmessagesmanyusers' => 'Sampéyang nduwé $1 saka akèh panganggo ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|layang anyar|layang anyar}}',
@@ -1064,8 +1062,6 @@ Rinciané bisa ditemokaké nèng [{{fullurl:{{#Special:Log}}/delete|page={{FULLP
 'preferences' => 'Preferensi (pilihan)',
 'mypreferences' => 'Préferènsi',
 'prefs-edits' => 'Gunggungé suntingan:',
-'prefsnologin' => 'Durung mlebu log',
-'prefsnologintext' => 'Panjenengan kudu <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}}| mlebu log]</span> kanggo ngowahin préferènsi njenengan.',
 'changepassword' => 'Ganti tembung sandi',
 'prefs-skin' => 'Kulit',
 'skin-preview' => 'Pratilik',
@@ -1340,6 +1336,7 @@ Alamat layang èlèktronik Sampéyan ora dituduhaké nalika wong liya ngubungi S
 'recentchanges-label-minor' => 'Iki suntingan sithik',
 'recentchanges-label-bot' => 'Suntingan iki diayahi déning bot',
 'recentchanges-label-unpatrolled' => 'Suntingan iki durung dipatroli',
+'recentchanges-legend-newpage' => '$1 - kaca anyar',
 'rcnote' => 'Ing ngisor iki kapacak {{PLURAL:$1|pangowahan|owah-owahan}} pungkasan ing  <strong>$2</strong> dina pungkasan ing $5, $4.',
 'rcnotefrom' => 'Ing ngisor iki owah-owahan wiwit <strong>$2</strong> (kapacak nganti <strong>$1</strong> owah-owahan).',
 'rclistfrom' => 'Saiki nuduhaké owah-owahan wiwit tanggal $1',
@@ -2543,7 +2540,7 @@ Yèn panjenengan namun péngin ngimpor vèrsi pungkasan, panjenengan uga bisa ng
 'allmessagesdefault' => 'Tèks baku',
 'allmessagescurrent' => 'Tèks saiki',
 'allmessagestext' => 'Iki dhaptar kabèh pesen saka sistem sing ana ing bilik jeneng MediaWiki.
-Mangga pirsani [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] lan [//translatewiki.net translatewiki.net] yèn panjenengan arep kontribusi ing lokalisasi generik MediaWiki.',
+Mangga pirsani [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] lan [//translatewiki.net translatewiki.net] yèn panjenengan arep kontribusi ing lokalisasi generik MediaWiki.',
 'allmessagesnotsupportedDB' => "Kaca iki ora bisa dienggo amerga '''\$wgUseDatabaseMessages''' dipatèni.",
 'allmessages-filter-legend' => 'Penyaring',
 'allmessages-filter' => 'Saring nganggo kahanan kustomisasi:',
@@ -2728,6 +2725,8 @@ Mbokmanawa iki disebabaké anané pranala jaba sing klebu daftar ireng.',
 'spam_reverting' => 'Mbalèkaké menyang vèrsi pungkasan sing ora ana pranalané menyang $1',
 'spam_blanking' => 'Kabèh révisi sing duwé pranala menyang $1, pangosongan',
 'spam_deleting' => 'Kabèh benahan sing nduwé pranala nèng $1, dibusaki',
+'simpleantispam-label' => "Pamariksan anti-spam.
+'''Aja''' diisèkaké!",
 
 # Info page
 'pageinfo-title' => 'Inpormasi kanggo "$1"',
@@ -3272,7 +3271,7 @@ Pranala-pranala sabanjuré ing baris sing padha dianggep minangka ''pengecualian
 
 # External editor support
 'edit-externally' => 'Sunting berkas iki mawa aplikasi jaba',
-'edit-externally-help' => '(Deleng [//www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] kanggo informasi sabanjuré)',
+'edit-externally-help' => '(Deleng [https://www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] kanggo informasi sabanjuré)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kabèh',
@@ -3443,7 +3442,7 @@ Panjenengan uga bisa [[Special:EditWatchlist|nganggo éditor standar panjenengan
 'version-hook-subscribedby' => 'Dilanggani déning',
 'version-version' => '(Vèrsi $1)',
 'version-license' => 'Lisènsi',
-'version-poweredby-credits' => "Wiki iki disengkuyung déning '''[//www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki iki disengkuyung déning '''[https://www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
 'version-poweredby-others' => 'liyané',
 'version-credits-summary' => 'Kami ingin mengakui orang-orang berikut atas kontribusinya terhadap [[Special:Version|MediaWiki]].',
 'version-license-info' => 'MediaWiki adalah perangkat lunak bebas; Anda diperbolehkan untuk mendistribusikan dan/atau memodfikasinya dengan persyaratan Lisensi Publik Umum GNU yang diterbitkan oleh Free Software Foundation; versi 2 atau terbaru.
@@ -3471,8 +3470,7 @@ Anda seharusnya telah menerima [{{SERVER}}{{SCRIPTPATH}}/COPYING salinan Lisensi
 
 # Special:SpecialPages
 'specialpages' => 'Kaca istiméwa',
-'specialpages-note' => '----
-* Kaca astamiwa biasa.
+'specialpages-note' => '* Kaca astamiwa biasa.
 * <span class="mw-specialpagerestricted">Kaca astamiwa kawatesan.</span>',
 'specialpages-group-maintenance' => 'Lapuran pangopènan',
 'specialpages-group-other' => 'Kaca-kaca astaméwa liyané',
@@ -3662,4 +3660,21 @@ Utawa, Sampéyan bisa nganggo pormulir gampang ngisor. Tanggepan Sampéyan bakal
 # Image rotation
 'rotate-comment' => 'Gambar diubengaké $1 {{PLURAL:$1|drajat|drajat}} sak arah domé jam',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Cithakan dikembangaké',
+'expand_templates_intro' => 'Kaca astaméwa iki njupuk sawetara tèks lan ngembangaké kabèh cithakan sajroning iku sacara rékursif.
+Kaca iki uga ngembangaké fungsi parser kaya ta
+<nowiki>{{</nowiki>#language:…}}, lan variabel kaya ta
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;sajatiné mèh kabèh sing ana ing antara rong tandha kurung akolade.
+Perkara iki dilakokaké caranémawa nyeluk tahapan parser sing rélévan saka MediaWiki dhéwé.',
+'expand_templates_title' => 'Irah-irahan kontèks, kanggo {{FULLPAGENAME}} lan sabanjuré:',
+'expand_templates_input' => 'Tèks sumber:',
+'expand_templates_output' => 'Pituwas (kasil)',
+'expand_templates_xml_output' => 'Pituwas XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Busaken komentar',
+'expand_templates_remove_nowiki' => 'Brèdèl tag <nowiki> nèng asilé',
+'expand_templates_generate_xml' => 'Tuduhna uwit parser XML',
+'expand_templates_preview' => 'Pratayang',
+
 );
index ff4feb7..18a6cfa 100644 (file)
@@ -66,7 +66,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'ცუდი_სათაური' ),
        'Blankpage'                 => array( 'ცარიელი_გვერდი' ),
        'Block'                     => array( 'დაბლოკვა' ),
-       'Blockme'                   => array( 'დამბლოკე' ),
        'BrokenRedirects'           => array( 'გაწყვეტილი_გადამისამართება' ),
        'Categories'                => array( 'კატეგორიები' ),
        'ChangeEmail'               => array( 'ელ-ფოსტის_შეცვლა' ),
@@ -75,7 +74,6 @@ $specialPageAliases = array(
        'Confirmemail'              => array( 'ელ-ფოსტის_დადასტურება' ),
        'Contributions'             => array( 'წვლილი' ),
        'CreateAccount'             => array( 'ანგარიშის_შექმნა' ),
-       'Disambiguations'           => array( 'მრავალმნიშვნელოვნება' ),
        'DoubleRedirects'           => array( 'ორმაგი_გადამისამართება' ),
        'EditWatchlist'             => array( 'კონტროლის_სიის_რედაქტირება' ),
        'Emailuser'                 => array( 'მიწერა_მომხმარებელს' ),
@@ -176,7 +174,7 @@ $messages = array(
 'tog-hidepatrolled' => 'დამალეთ შესწორებული რედაქტირებები ბოლო ცვლილებებში',
 'tog-newpageshidepatrolled' => 'დამალეთ შემოწმებული გვერდები ახალი გვერდების სიიდან',
 'tog-extendwatchlist' => 'გავრცობილი კონტროლის სია ყველა დაკავშირებული ცვლილების ჩვენების ჩათვლით',
-'tog-usenewrc' => 'ბოლო ცვლილებების და კონტროლის სიის ცვლილებების დაჯგუფება (საჭიროა ჯავასკრიპტი)',
+'tog-usenewrc' => 'ბოლო ცვლილებების და კონტროლის სიის ცვლილებების დაჯგუფება',
 'tog-numberheadings' => 'ავტომატურად დანომრე ქვესათაურები',
 'tog-showtoolbar' => 'რედაქტირების პანელის ჩვენება',
 'tog-editondblclick' => 'გვერდების რედაქტირება ორმაგი დაწკაპუნებით',
@@ -310,8 +308,6 @@ $messages = array(
 'broken-file-category' => 'გვერდები ფაილების არასწორი ბმულებით',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'შესახებ',
 'article' => 'სტატია',
 'newwindow' => '(ახალ ფანჯარაში)',
@@ -420,7 +416,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}}-ის შესახებ',
 'aboutpage' => 'Project:შესახებ',
-'copyright' => 'შინაარსი წარმოდგენილია $1 პირობებით.',
+'copyright' => 'შინაარსი წარმოდგენილია $1 პირობებით (თუ სხვა არ არის მითითებული).',
 'copyrightpage' => '{{ns:project}}:საავტორო უფლებები',
 'currentevents' => 'მიმდინარე მოვლენები',
 'currentevents-url' => 'Project:მიმდინარე მოვლენები',
@@ -449,8 +445,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'მოძიებულია „$1“-დან',
 'youhavenewmessages' => 'თქვენ გაქვთ $1 ($2).',
-'newmessageslink' => 'ახალი შეტყობინებები',
-'newmessagesdifflink' => 'განსხვავება წინა ვერსიასთან',
 'youhavenewmessagesfromusers' => 'თქვენ გაქვთ $1 {{PLURAL:$3|სხვა მომხმარებლისგან|$3 მომხმარებლებისგან}} ($2).',
 'youhavenewmessagesmanyusers' => 'თქვენ გაქვთ $1 ბევრი მომხმარებლისგან ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ახალი შეტყობინება|ახალი შეტყობინება}}',
@@ -588,11 +582,9 @@ $2',
 'virus-unknownscanner' => 'უცნობი ანტივირუსი:',
 
 # Login and logout pages
-'logouttext' => "'''á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83\9bá\83\9fá\83\90á\83\9bá\83\90á\83\93 á\83¡á\83\98á\83¡á\83¢á\83\94á\83\9bá\83\98á\83\93á\83\90á\83\9c á\83\92á\83\90á\83¡á\83£á\83\9aá\83\98 á\83®á\83\90á\83 á\83\97.'''
+'logouttext' => "'''á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83\9bá\83\9fá\83\90á\83\9bá\83\90á\83\93 á\83\92á\83\90á\83¡á\83£á\83\9aá\83\98 á\83®á\83\90á\83 á\83\97 á\83¡á\83\98á\83¡á\83¢á\83\94á\83\9bá\83\98á\83\93á\83\90á\83\9c.'''
 
-შეგიძლიათ გამოიყენოთ {{SITENAME}} ანონიმურად, ან შეგიძლიათ
-<span class='plainlinks'>[$1 შეხვიდეთ ისევ]</span> როგორც იგივე ან სხვა მომხმარებელი.
-შენიშნეთ, რომ ზოგიერთ გვერდზე შესაძლოა ისევ უჩვენებდეს რომ შესული ხართ სანამ თქვენი ბრაუზერის მეხსიერებას არ გაწმენდთ.",
+ზოგიერთმა გვერდმა შესაძლოა ისევ ისე გააგრძელოს ჩვენება თითქოს თქვენ ჯერ კიდევ სისტემაში იყოთ. ამის მოსაგვარებლად საჭიროა თქვენი ბრაუზერის მეხსიერების გაწმენდა.",
 'welcomeuser' => 'მოგესალმებით, $1!',
 'welcomecreation-msg' => 'თქვენი ანგარიში შექმნილია.
 არ დაგავიწყდეთ თქვენი [[Special:Preferences|{{SITENAME}}-ის კონფიგურაციის]] შეცვლა.',
@@ -629,15 +621,16 @@ $2',
 'gotaccount' => "უკვე რეგისტრირებული ხართ? '''$1'''",
 'gotaccountlink' => 'შესვლა',
 'userlogin-resetlink' => 'ავტორიზაციის მონაცემები დაგავიწყდათ?',
-'userlogin-resetpassword-link' => 'á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98á\83¡ á\83\9bá\83\9dá\83ªá\83\98á\83\9aá\83\94á\83\91á\83\90',
+'userlogin-resetpassword-link' => 'á\83\93á\83\90á\83\92á\83\90á\83\95á\83\98á\83¬á\83§á\83\93á\83\90á\83\97 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98?',
 'helplogin-url' => 'Help:შესვლა',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|დახმარება სისტემაში შესასვლელად]]',
+'userlogin-createanother' => 'სხვა ანგარიშის შექმნა',
 'createacct-join' => 'ქვემოთ მიუთითეთ ინფორმაცია თქვენ შესახებ.',
 'createacct-emailrequired' => 'ელ. ფოსტის მისამართი',
 'createacct-emailoptional' => 'ელ. ფოსტის მისამართი (არასავალდებულო)',
 'createacct-email-ph' => 'შეიყვანეთ თქვენი ელ. ფოსტის მისამართი',
 'createacct-another-email-ph' => 'შეიყვანეთ ელ.ფოსტის მისამართი',
-'createaccountmail' => 'á\83\92á\83\90á\83\9bá\83\9dá\83\98á\83§á\83\94á\83\9cá\83\94á\83\97 á\83¨á\83\94á\83\9bá\83\97á\83®á\83\95á\83\94á\83\95á\83\98á\83\97á\83\9dá\83\91á\83\98á\83¡ á\83\9bá\83\94á\83\97á\83\9dá\83\93á\83\98á\83\97 á\83¨á\83\94á\83 á\83©á\83\94á\83£á\83\9aá\83\98 á\83\93á\83 á\83\9dá\83\94á\83\91á\83\98á\83\97á\83\98 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98 á\83\93á\83\90 á\83\9bá\83\98á\83¡á\83\98 á\83\92á\83\90á\83\92á\83\96á\83\90á\83\95á\83\9cá\83\90 á\83¥á\83\95á\83\94á\83\9bá\83\9dá\83\97 á\83\9bá\83\98á\83\97á\83\98á\83\97á\83\94á\83\91á\83£á\83\9a á\83\94á\83\9a. á\83¤á\83\9dá\83¡á\83¢á\83\98á\83¡ á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\96á\83\94:',
+'createaccountmail' => 'á\83\92á\83\90á\83\9bá\83\9dá\83\98á\83§á\83\94á\83\9cá\83\94á\83\97 á\83¨á\83\94á\83\9bá\83\97á\83®á\83\95á\83\94á\83\95á\83\98á\83\97á\83\9dá\83\91á\83\98á\83¡ á\83\9bá\83\94á\83\97á\83\9dá\83\93á\83\98á\83\97 á\83¨á\83\94á\83 á\83©á\83\94á\83£á\83\9aá\83\98 á\83\93á\83 á\83\9dá\83\94á\83\91á\83\98á\83\97á\83\98 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98 á\83\93á\83\90 á\83\9bá\83\98á\83¡á\83\98 á\83\92á\83\90á\83\90á\83\92á\83\96á\83\90á\83\95á\83\9cá\83\94á\83\97 á\83\9bá\83\98á\83\97á\83\98á\83\97á\83\94á\83\91á\83£á\83\9a á\83\94á\83\9a\83¤á\83\9dá\83¡á\83¢á\83\98á\83¡ á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\96á\83\94',
 'createacct-realname' => 'ნამდვილი სახელი (არააუცილებელი)',
 'createaccountreason' => 'მიზეზი:',
 'createacct-reason' => 'მიზეზი',
@@ -692,16 +685,16 @@ $2',
 'passwordsent' => 'ახალი პაროლი გაიგზავნა ელ-ფოსტით მომხმარებელს "$1".
 გთხოვთ შეხვიდეთ სისტემაში მისი მიღების შემდეგ.',
 'blocked-mailpassword' => 'თქვენი IP მისამართი რედაქტირებისთვის დაბლოკილია, ამიტომ არ შეგიძლიათ პაროლის აღდგენის გამოყენება კონფლიქტის გამო.',
-'eauthentsent' => 'დამადასტურებელი შეტყობინება გაიგზავნა თქვენს მიერ მითითებულ ელ. ფოსტის მისამართზე.
-სანამ ნებისმიერი სხვა შეტყობინება გაიგზავნებოდეს თქვენს ანგარიშზე, გთხოვთ მიჰყვეთ ელ.
-ფოსტაში მითითებულ ინსტრუქციებს, რათა დაადასტუროთ რომ ანგარიში ნამდვილად თქვენია.',
+'eauthentsent' => 'A confirmation email has been sent to the specified email address.
+Before any other email is sent to the account, you will have to follow the instructions in the email, to confirm that the account is actually yours.',
 'throttled-mailpassword' => 'პაროლის შეხსენება უკვე გაგზავნილია ბოლო {{PLURAL:$1|საათის|$1 საათის}} განმავლობაში.
 ბოროტად გამოყენების თავიდან აცილებისთვის, მხოლოდ ერთი შეხსენება იგზავნება ყოველ {{PLURAL:$1|საათში|$1 საათში}}.',
 'mailerror' => 'შეცდომა ფოსტის გაგზავნაში: $1',
 'acct_creation_throttle_hit' => '24 საათის განმავლობაში თქვენი IP-მისამართითან {{PLURAL:$1|შეიქმნა $1 ანგარიში|შეიქმნა $1 ანგარიშები|შეიქმნა $1 ანგარიშის}}, რაც არის აკრძალული დროის ამ მონაკვეთისთის.
 აქედან გამომდინარე თქვენი IP-მისამართის მქონე მომხმარებლები ვეღარ შექმნიან ანგარიშები.',
-'emailauthenticated' => 'თქვენი ელ. ფოსტის მისამართი გადამოწმებულია $2 $3-ზე.',
-'emailnotauthenticated' => 'თქვენი ელ. ფოსტის მისამართი ჯერ არ არის გადამოწმებული. შემდეგი ფუნქციები გამორთულია.',
+'emailauthenticated' => 'თქვენი ელ.ფოსტის მისამართი დადასტურებულია $2 $3-ზე.',
+'emailnotauthenticated' => 'თქვენი ელ.ფოსტის მისამართი ჯერ არ არის დადასტურებული. 
+არცერთი შემდეგი ფუნქციისათვის წერილები არ გამოიგზავნება.',
 'noemailprefs' => 'თქვენ არ გაქვთ ელ. ფოსტის მისამართი მითითებული,აღნიშნული ფუნქციები ამის გამო არ დროისთვის შეუძლებელია.',
 'emailconfirmlink' => 'დაადასტურეთ თქვენი ელ. ფოსტის მისამართი',
 'invalidemailaddress' => 'ელ. ფოსტის მისამართი არ იქნა მიღებული, ვინაიდან იგი არასწორი ფორმატითაა წარმოდგენილი.
@@ -715,8 +708,8 @@ $2',
 
 შეგიძლიათ ყურადღება არ მიაქციოთ ამ შეტყობინებას, თუ ანგარიში შეცდომით შეიქმნა.',
 'usernamehasherror' => 'მომხმარებლის სახელი არ უნდა შეიცავდეს დიეზის სიმბოლოს.',
-'login-throttled' => 'თქვენ განახორციელეთ ძალიან ბევრი პაროლის შეყვანა ამ ანგარიშისთვის.
-გამორებით შეყვანამდე გთხოვთ დაელოდოთ.',
+'login-throttled' => 'You have made too many recent login attempts.
+Please wait $1 before trying again.',
 'login-abort-generic' => 'თქვენი ავტორიზაცია წარუმატებელია – გაუქმდა',
 'loginlanguagelabel' => 'ენა: $1',
 'suspicious-userlogout' => 'თქვენი მოთხოვნა გასვლის შესახებ გაუქმებულია, რადგანაც იგი გავს ქეშირებადი პროქსის ან არაკორექტული ბრაუზერის მოთხოვნას.',
@@ -735,7 +728,7 @@ $2',
 'newpassword' => 'ახალი პაროლი:',
 'retypenew' => 'ახალი პაროლი განმეორებით:',
 'resetpass_submit' => 'მიუთითეთ პაროლი და დარეგისტრირდით',
-'changepassword-success' => 'თქვენი პაროლი წარმატებით შეიცვალა! ამჟამად რეგისტრირდებით...',
+'changepassword-success' => 'თქვენი პაროლი წარმატებით შეიცვალა!',
 'resetpass_forbidden' => 'პაროლის შეცვლა შეუძლებელია',
 'resetpass-no-info' => 'კონკრეტულად ამ გვერდთან სამუშაოდ თქვენ უნდა წარადგინოთ თავი სისტემისადმი.',
 'resetpass-submit-loggedin' => 'პაროლის შეცვლა',
@@ -748,7 +741,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'პაროლის აღდგენა',
 'passwordreset-text-one' => 'შეავსეთ ეს ფორმა, რათა კვლავ დააყენოთ თქვენი პაროლი.',
-'passwordreset-text-many' => '{{PLURAL:$1|á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98á\83¡ á\83\97á\83\90á\83\95á\83\98á\83\93á\83\90á\83\9c á\83\93á\83\90á\83¡á\83\90á\83§á\83\94á\83\9cá\83\94á\83\91á\83\9aá\83\90á\83\93 á\83¨á\83\94á\83\98á\83§á\83\95á\83\90á\83\9cá\83\94á\83\97 á\83\9bá\83\9dá\83\9cá\83\90á\83ªá\83\94á\83\9bá\83\97á\83\90 á\83\94á\83 á\83\97\83\94á\83 á\83\97á\83\98 á\83\9cá\83\90á\83¬á\83\98ლი.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98á\83¡ á\83\97á\83\90á\83\95á\83\98á\83\93á\83\90á\83\9c á\83\93á\83\90á\83¡á\83\90á\83§á\83\94á\83\9cá\83\94á\83\91á\83\9aá\83\90á\83\93 á\83¨á\83\94á\83\90á\83\95á\83¡á\83\94á\83\97 á\83\94á\83 á\83\97\83\94á\83 á\83\97á\83\98 á\83\95á\83\94ლი.}}',
 'passwordreset-legend' => 'პაროლის აღდგენა',
 'passwordreset-disabled' => 'ამ ვიკიში პაროლის კვლავ დაყენების ფუნქცია გამორთულია.',
 'passwordreset-emaildisabled' => 'ამ ვიკიში ელ.ფოსტის ფუნქციები გამორთულია.',
@@ -880,8 +873,9 @@ $2
 'loginreqlink' => 'შესვლა',
 'loginreqpagetext' => 'თქვენ უნდა $1 სხვა გვერდები აჩვენოთ.',
 'accmailtitle' => 'პაროლი გაგზავნილია.',
-'accmailtext' => "მომხმარებელი [[User talk:$1|$1]]-სთვის შექმნილია ახალი პაროლი, შექმნილი შემთხვევითი სიმბოლოებისგან გაიგზავნა $2 ელექტრონულ მისამართზე.
-სისტემისადმი თავის წარდგენის შემდეგ თქვენ შეგიძლლიათ ''[[Special:ChangePassword|შეცვალოთ პაროლი]]''.",
+'accmailtext' => "შემთხვევითი მეთოდით შექმნილი პაროლი მომხმარებლისათვის [[User talk:$1|$1]] გაგზავნილია მისამართზე $2.
+
+ავტორიზაციის გავლის შემდეგ შესაძლებელი იქნება ამ ანგარიშის  ''[[Special:ChangePassword|პაროლის შეცვლა]]'' ანგარიშში შესვლის გვერდზე.",
 'newarticle' => '(ახალი)',
 'newarticletext' => 'ბმულის მეშვეობით თქვენ მოხვდით გვერდზე, რომელიც ჯერ არ არსებობს.
 გვერდის შესაქმნელად შეიყვანეთ ინფორმაცია ქვემო ფანჯარაში
@@ -1012,7 +1006,7 @@ $2
 
 # Content models
 'content-model-wikitext' => 'ვიკიტექსტი',
-'content-model-text' => 'á\83£á\83\91á\83 á\83\90á\83\9aá\83\9d ტექსტი',
+'content-model-text' => 'á\83©á\83\95á\83\94á\83£á\83\9aá\83\94á\83\91á\83 á\83\98á\83\95á\83\98 ტექსტი',
 'content-model-javascript' => 'ჯავასკრიპტი',
 'content-model-css' => 'CSS',
 
@@ -1136,15 +1130,15 @@ $3 -ემ ამგვარი ახსნა : ''$2''",
 * მიუსადეგი პირადი ინფორმაცია
 *: ''სახლის მისამართი, ტელეფონისა და პასპორტის ნომერი და მისთ. ''",
 'revdelete-legend' => 'შეზღუდვის დაყენება',
-'revdelete-hide-text' => 'შეცვლილი ტექსტის დამალვა',
+'revdelete-hide-text' => 'შეცვლილი ტექსტი',
 'revdelete-hide-image' => 'ფაილის შინაარსის დამალვა',
 'revdelete-hide-name' => 'დამალეთ მოქმედება და მისი ობიექტი',
-'revdelete-hide-comment' => 'რედაქტირების კომენტარის დამალვა',
-'revdelete-hide-user' => 'რედაქტორის მომხ. სახელის/IP-ს დამალვა',
+'revdelete-hide-comment' => 'რედაქტირების კომენტარი',
+'revdelete-hide-user' => 'რედაქტორის მომხმარებლის სახელი/IP-მისამართი',
 'revdelete-hide-restricted' => 'დამალეთ მონაცემები ადმინისტრატორთაგან',
 'revdelete-radio-same' => '(არ შეცვალოთ)',
-'revdelete-radio-set' => 'á\83\93á\83\98á\83\90á\83®',
-'revdelete-radio-unset' => 'á\83\90á\83 á\83\90',
+'revdelete-radio-set' => 'á\83®á\83\98á\83\9aá\83£á\83\9aá\83\98',
+'revdelete-radio-unset' => 'á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83£á\83\9aá\83\98',
 'revdelete-suppress' => 'დამალეთ მონაცემები ადმინისტრატორთაგან',
 'revdelete-unsuppress' => 'მოხსენით შეზღუდვა ვერსიების აღდგენისგან',
 'revdelete-log' => 'მიზეზი:',
@@ -1165,7 +1159,7 @@ $1",
 'revdelete-show-no-access' => 'ჩანაწერის გახსნის შეცდომა $2-დან, $1: ეს ჩანაწერი მონიშნულია როგორც «შეზღუდული». თქვენ მას ვერ იხილავთ.',
 'revdelete-modify-no-access' => 'ჩანაწერის გასწორების შეცდომა $2-დან, $1: ეს ჩანაწერი მონიშნულია როგორც «შეზღუდული». თქვენ მას ვერ იხილავთ.',
 'revdelete-modify-missing' => 'შეცდომა ID $1 ნაწეის რედაქტირებისას, იგი არ იმყოფება მონაცემთა ბაზაში!',
-'revdelete-no-change' => "'''ყურადღება:''' ჩანაწერს $2, $1 უკვე ავს მოთხოვნილი ხილვადობის კონფიგურაცია.",
+'revdelete-no-change' => "'''á\83§á\83£á\83 á\83\90á\83\93á\83¦á\83\94á\83\91á\83\90:''' á\83©á\83\90á\83\9cá\83\90á\83¬á\83\94á\83 á\83¡ $2, $1 á\83£á\83\99á\83\95á\83\94 á\83\90á\83¥á\83\95á\83¡ á\83\9bá\83\9dá\83\97á\83®á\83\9dá\83\95á\83\9cá\83\98á\83\9aá\83\98 á\83®á\83\98á\83\9aá\83\95á\83\90á\83\93á\83\9dá\83\91á\83\98á\83¡ á\83\99á\83\9dá\83\9cá\83¤á\83\98á\83\92á\83£á\83 á\83\90á\83ªá\83\98á\83\90.",
 'revdelete-concurrent-change' => 'შეცდომა ჩანაწერის შესწორებისას $2-დან, $1: მისი სტატუსი უკვე შეცვლილია სხვა ვინმეს მიერ თქვენი რედაქირეის სესიის დროს.
 თხოვთ შეამოწმოთ ყველა ჟღნალი',
 'revdelete-only-restricted' => 'თქვენ ვერ დამალავთ ჩანაწერს ($2 $1) ადმინისტრატორისგან მანამ, სანამ არ აირჩევთ დამალვის სხვა პარამეტრებს.',
@@ -1297,8 +1291,6 @@ $1",
 'preferences' => 'კონფიგურაცია',
 'mypreferences' => 'კონფიგურაცია',
 'prefs-edits' => 'რედაქციების რაოდენობა:',
-'prefsnologin' => 'შესული არ ხართ',
-'prefsnologintext' => 'თქვენ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} რეგისტრირებული უნდა იყოთ]</span> მომხმარებლის კონფიგურაციის შესაცვლელად.',
 'changepassword' => 'პაროლის შეცვლა',
 'prefs-skin' => 'გარეკანი',
 'skin-preview' => 'წინასწარი გადახედვა',
@@ -1323,7 +1315,7 @@ $1",
 'prefs-rendering' => 'იერსახე',
 'saveprefs' => 'შენახვა',
 'resetprefs' => 'გადატვირთვა',
-'restoreprefs' => 'á\83\99á\83\9dá\83\9cá\83¤á\83\98á\83\92á\83£á\83 á\83\90á\83ªá\83\98á\83\98á\83¡ á\83¡á\83\90á\83¬á\83§á\83\98á\83¡á\83\96á\83\94 á\83\93á\83\90á\83\91á\83 á\83£á\83\9cá\83\94á\83\91á\83\90',
+'restoreprefs' => 'á\83§á\83\95á\83\94á\83\9aá\83\90 á\83¡á\83\90á\83¬á\83§á\83\98á\83¡á\83\98 á\83\9eá\83\90á\83 á\83\90á\83\9bá\83\94á\83¢á\83 á\83\98á\83¡ á\83\90á\83¦á\83\93á\83\92á\83\94á\83\9cá\83\90 (á\83§á\83\95á\83\94á\83\9aá\83\90 á\83¡á\83\94á\83¥á\83ªá\83\98á\83\90á\83¨á\83\98)',
 'prefs-editing' => 'რედაქტირება',
 'rows' => 'რიგები:',
 'columns' => 'სვეტები',
@@ -1384,8 +1376,9 @@ $1",
 'gender-unknown' => 'მითითებას არ ვთვლი საჭიროდ',
 'gender-male' => 'ის (მამრობითი) არედაქტირებს ვიკი-გვერდებს',
 'gender-female' => 'ის (მდედრობითი) არედაქტირებს ვიკი-გვერდებს',
-'prefs-help-gender' => 'არასავალდებულო ველი: გამოიყენება პროგრამული უზრუნველყოფის იმ შეტყობინებებისთვის, რომლებიც ადამიანის სქესზეა დამოკიდებული.
-ეს ინფორმაცია საზოგადოებრივი  იქნება.',
+'prefs-help-gender' => 'ამ პარამეტრის დაყენება არასავალდებულოა.
+პროგრამული უზრუნველყოფა ამ ინფორმაციას იყენებს მხოლოდ სწორი გრამატიკული სქესით მომართვისათვის.
+ეს ინფორმაცია საჯარო იქნება ყველასათვის.',
 'email' => 'ელ. ფოსტა',
 'prefs-help-realname' => 'ნამდვილი სახელის მითითება აუცილებელი არ არის, მაგრამ თუ მიუთითებთ ის გამოყენებული იქნება თქვენი ნამუშევრის აღსანიშნავად.',
 'prefs-help-email' => 'ელ. ფოსტის მისამართი არ არის სავალდებულო, მაგრამ მისი მითითება იძლევა ახალი პაროლის გამოგზავნის საშუალებას თქვენი პაროლის დავიწყების შემთხვევაში.',
@@ -1481,7 +1474,7 @@ $1",
 'right-reupload-shared' => 'ფაილთა შეცვლა საერთო საცავიდან ლოკალურებით',
 'right-upload_by_url' => 'ფაილის ატვირთვა URL-დან',
 'right-purge' => 'ქეშის გაწმენდა დადასტურების გვერდის გარეშე',
-'right-autoconfirmed' => 'á\83\9cá\83\90á\83¬á\83\98á\83\9aá\83\9dá\83\91á\83 á\83\98á\83\95 á\83\93á\83\90á\83ªá\83£á\83\9aá\83\98 á\83\92á\83\95á\83\94á\83 á\83\93á\83\94á\83\91á\83\98á\83¡ á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\90',
+'right-autoconfirmed' => 'á\83¡á\83\98á\83©á\83¥á\83\90á\83 á\83\98á\83¡ á\83¨á\83\94á\83\96á\83¦á\83£á\83\93á\83\95á\83\90 IP á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\96á\83\94 á\83\90á\83  á\83\90á\83 á\83\98á\83¡',
 'right-bot' => 'ჩაითვალო ავტომატურ პროცესად',
 'right-nominornewtalk' => 'მცირე რედაქტირებების არ ქონის შემთხვევაში ჩაირთვება ახალ შეტყობინებათა რეჟიმი',
 'right-apihighlimits' => 'ნაკლები შეზღუდვა API-მოთხოვნებზე',
@@ -1502,7 +1495,7 @@ $1",
 'right-ipblock-exempt' => 'IP ბლოკის, ავტობლოკის და დიაპაზონთა ბლოკის გასვლა',
 'right-proxyunbannable' => 'პროქსის ავტობლოკის გადასვლა',
 'right-unblockself' => 'საკუთარი თავის განბლოკვა',
-'right-protect' => 'გვერდების დაცვის დონის შეცვლა და დაცული გვერდების რედაქტირება',
+'right-protect' => 'á\83\92á\83\95á\83\94á\83 á\83\93á\83\94á\83\91á\83\98á\83¡ á\83\93á\83\90á\83ªá\83\95á\83\98á\83¡ á\83\93á\83\9dá\83\9cá\83\98á\83¡ á\83¨á\83\94á\83ªá\83\95á\83\9aá\83\90 á\83\93á\83\90 á\83\99á\83\90á\83¡á\83\99á\83\90á\83\93á\83£á\83 á\83\90á\83\93 á\83\93á\83\90á\83ªá\83£á\83\9aá\83\98 á\83\92á\83\95á\83\94á\83 á\83\93á\83\94á\83\91á\83\98á\83¡ á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\90',
 'right-editprotected' => 'გვერდების რედაქტირება რომლებიც დაცულია როგორც „{{int:protect-level-sysop}}“',
 'right-editsemiprotected' => 'გვერდების რედაქტირება რომლებიც დაცულია როგორც „{{int:protect-level-autoconfirmed}}“',
 'right-editinterface' => 'მომხმარებლის ინტერფეისის შეცვლა',
@@ -1590,6 +1583,7 @@ $1",
 'recentchanges-label-minor' => 'ეს არის მცირე შესწორება',
 'recentchanges-label-bot' => 'ეს არის ბოტის რედაქტირება',
 'recentchanges-label-unpatrolled' => 'ეს რედაქტირება გადაუმოწმებელია',
+'recentchanges-legend-newpage' => '$1 - ახალი გვერდი',
 'rcnote' => "ქვემოთ იხილეთ ბოლო '''$1''' ცვლილება უკანასკნელი '''$2''' დღის მანძილზე, $5, $4 მდგომარეობით.",
 'rcnotefrom' => "ქვემოთ მოყვანილია ცვლილებები '''$2'''-დან (ნაჩვენებია '''$1''').",
 'rclistfrom' => 'ახალი ცვლილებების ჩვენება დაწყებული $1-დან',
@@ -1717,7 +1711,7 @@ $1",
 'savefile' => 'ფაილის შენახვა',
 'uploadedimage' => 'აიტვირთა „[[$1]]“',
 'overwroteimage' => 'ატვირთულია „[[$1]]-ის“ ახალი ვერსია',
-'uploaddisabled' => 'á\83\90á\83¢á\83\95á\83\98á\83 á\83\97á\83\95á\83\90 á\83¨á\83\94á\83£á\83«á\83\9aá\83\94á\83\91á\83\94á\83\9aá\83\98á\83\90',
+'uploaddisabled' => 'á\83\90á\83¢á\83\95á\83\98á\83 á\83\97á\83\95á\83\90 á\83\92á\83\90á\83\9bá\83\9dá\83 á\83\97á\83£á\83\9aá\83\98á\83\90.',
 'copyuploaddisabled' => 'URL ატვირთვა გაღიშულია',
 'uploadfromurl-queued' => 'თქვენი ატვირთვა რიგში ჩადგა.',
 'uploaddisabledtext' => 'ფაილების ატვირთვა შეუძლებელია.',
@@ -1865,8 +1859,7 @@ $1',
 'upload_source_file' => ' (ფაილი შენს კომპიუტერზე)',
 
 # Special:ListFiles
-'listfiles-summary' => 'ეს სპეციალური გვერდი აჩვენებს ყველა ატვირთულ ფაილს.
-მომხმარებლების მიხედვით გაფილტვრისას, ნაჩვენები იქნება ამ მომხმარებლის მხოლოდ ახალი ატვირთვები.',
+'listfiles-summary' => 'ეს სპეციალური გვერდი აჩვენებს ყველა ატვირთულ ფაილს.',
 'listfiles_search_for' => 'ძიება სურათის სახელის მიხედვით:',
 'imgfile' => 'ფაილი',
 'listfiles' => 'სურათების სია',
@@ -1978,6 +1971,8 @@ $1',
 'randompage-nopages' => '{{PLURAL:$2|სახელთა შემდეგი სივრცე|სახელთა შემდეგ სივრცეში}} "$1" არ არის გვერდები.',
 
 # Random page in category
+'randomincategory' => 'კატეგორიის შემთხვევითი გვერდი',
+'randomincategory-invalidcategory' => 'კატეგორია „$1“ არ არსებობს.',
 'randomincategory-selectcategory-submit' => 'მიდი',
 
 # Random redirect
@@ -1995,7 +1990,7 @@ $1',
 'statistics-pages' => 'გვერდები',
 'statistics-pages-desc' => 'ვიკის ყველა გვერდი, განხილვის, გადამისამართების და სხვ. ჩათვლით.',
 'statistics-files' => 'ატვირთული ფაილები',
-'statistics-edits' => 'á\83\92á\83\95á\83\94á\83 á\83\93á\83\98á\83¡ á\83¨á\83\94á\83¡á\83¬á\83\9dá\83 á\83\94á\83\91á\83\94á\83\91á\83\98 á\83\9eá\83 á\83\9dá\83\94á\83¥á\83¢á\83\98á\83¡ {{SITENAME}} á\83¨á\83\94á\83¥á\83\9bá\83\9cá\83\98á\83¡ á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92',
+'statistics-edits' => 'á\83\92á\83\95á\83\94á\83 á\83\93á\83\98á\83¡ á\83¨á\83\94á\83¡á\83¬á\83\9dá\83 á\83\94á\83\91á\83\94á\83\91á\83\98 á\83\9bá\83\90á\83¡ á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92 á\83 á\83\90á\83ª á\83¨á\83\94á\83\98á\83¥á\83\9bá\83\9cá\83\90 á\83\9eá\83 á\83\9dá\83\94á\83¥á\83¢á\83\98 {{SITENAME}}',
 'statistics-edits-average' => 'რედაქტირების საერთო რაოდენობა გვერდზე',
 'statistics-views-total' => 'სულ ხილვა',
 'statistics-views-total-desc' => 'სათვალავში არ მიიღება არარსებული და სამუშაო გვერდების გადახედვა',
@@ -2350,9 +2345,11 @@ $UNWATCHURL
 'deleteotherreason' => 'სხვა/დამატებითი მიზეზი:',
 'deletereasonotherlist' => 'სხვა მიზეზი',
 'deletereason-dropdown' => '* წაშლის ხშირი მიზეზები
-** ავტორის თხოვნით
+** სპამი
+** ვანდალიზმი
 ** საავტორო უფლების დარღვევა
-** ვანდალიზმი',
+** ავტორის მოთხოვნით
+** გატეხილი გადამისამართება',
 'delete-edit-reasonlist' => 'წაშლის მიზეზების რედაქტირება',
 'delete-toobig' => 'ამ გვერდს ძალიან გრძელი ისტორია გააჩნია,  $1 {{PLURAL:$1|ვერსიაზე|ვერსიიებზე|ვერსიებზე}} მეტი. მისი წაშლა აიკრძალა {{SITENAME}}-ის კორექტურად მუშაობის უზრუნველყოფისთვის.',
 'delete-warning-toobig' => 'ამ გვერდს ძალიან გრძელი ისტორია გააჩნია,  $1 {{PLURAL:$1|ვერსიაზე|ვერსიიებზე|ვერსიებზე}} მეტი.
@@ -2373,7 +2370,7 @@ $UNWATCHURL
 ბოლო ცვლილებები შეიტანა  [[User:$3|$3]] ([[User talk:$3|განხილვა]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "რედაქტირება განმარტებული იყო როგორც: \"''\$1''\".",
 'revertpage' => '[[Special:Contributions/$2|$2]]-ის რედაქტირება გაუქმდა; აღდგა ბოლოს [[User:$1|$1]]-ის მიერ რედაქტირებული ვერსია',
-'revertpage-nouser' => 'á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9a (á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡ á\83¡á\83\90á\83®á\83\94á\83\9aá\83\98 á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83£á\83\9aá\83\98á\83\90)-á\83\98á\83¡ á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\90 á\83\93á\83\90á\83\91á\83 á\83£á\83\9cá\83\94á\83\91á\83£á\83\9aá\83\98á\83\90 á\83\95á\83\94á\83 á\83¡á\83\98á\83\90á\83\96á\83\94 [[User:$1|$1]]',
+'revertpage-nouser' => 'á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡ (á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡ á\83¡á\83\90á\83®á\83\94á\83\9aá\83\98 á\83\93á\83\90á\83\9bá\83\90á\83\9aá\83£á\83\9aá\83\98á\83\90) á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\94á\83\91á\83\98 á\83\93á\83\90á\83\91á\83 á\83£á\83\9cá\83\94á\83\91á\83£á\83\9aá\83\98á\83\90 á\83\95á\83\94á\83 á\83¡á\83\98á\83\90á\83\96á\83\94 {{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'გაუქმდა შესწორება $1; დაბრუნება ვერსიაზე $2.',
 
 # Edit tokens
@@ -2501,7 +2498,6 @@ $1',
 $1',
 'undelete-show-file-confirm' => 'დარწმუნებული ხართ, რომ გსურთ ფაილ <nowiki>$1</nowiki>-ის წაშლილი ვერსიის ხილვა $2 $3-დან?',
 'undelete-show-file-submit' => 'ჰო',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'სახელთა სივრცე:',
@@ -2512,10 +2508,10 @@ $1',
 'blanknamespace' => '(მთავარი)',
 
 # Contributions
-'contributions' => '{{GENDER:$1|á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9aá\83\98}} წვლილი',
+'contributions' => '{{GENDER:$1|á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\9aá\83\98á\83¡}} წვლილი',
 'contributions-title' => 'მომხმარებლის წვლილი $1',
 'mycontris' => 'წვლილი',
-'contribsub2' => '$1 ($2) თვის',
+'contribsub2' => 'მომხმარებელი {{GENDER:$3|$1}} წვლილი ($2)',
 'nocontribs' => 'ძებნისას მითითებული პარამეტრების შესაბამისი არც ერთი ცვლილება ნაპოვნი არ არის',
 'uctop' => '(მიმდინარე)',
 'month' => 'თვე:',
@@ -2822,7 +2818,7 @@ $1',
 'allmessagesdefault' => 'სტანდარტული ტექსტი',
 'allmessagescurrent' => 'მიმდინარე ტექსტი',
 'allmessagestext' => 'ეს არის სისემურ შეტყობინებათა სია «MediaWiki» სახელთა სივრცეში.
-გთხოვთ ეწვიოთ  [//www.mediawiki.org/wiki/Localisation ლოკალიზაციის აღმწერ] გვერდს [//translatewiki.net translatewiki.net] პროექტს, თუ გსურთ MediaWiki ლოკალიზაციაში წვლილის შეტანა.',
+გთხოვთ ეწვიოთ  [https://www.mediawiki.org/wiki/Localisation ლოკალიზაციის აღმწერ] გვერდს [//translatewiki.net translatewiki.net] პროექტს, თუ გსურთ MediaWiki ლოკალიზაციაში წვლილის შეტანა.',
 'allmessagesnotsupportedDB' => '{{ns:special}}:AllMessages-ის უზრუნველყოფა არ ხდება, ვინაიდან wgUseDatabaseMessages გამორთულია.',
 'allmessages-filter-legend' => 'ფილტრი',
 'allmessages-filter' => 'ფილტრი ცვლილებების სტატუსით:',
@@ -2983,7 +2979,7 @@ $2',
 'tooltip-undo' => 'შეტანილი ცვლილებების გაუქმება და წინასწარ გადახედვის ჩვენება, გაუქმების მიზეზის სქოლიოში ჩაწერასთან ერთად.',
 'tooltip-preferences-save' => 'შეინახეთ კონფიგურაცია',
 'tooltip-summary' => 'შეიყვანეთ მოკლე სქოლიო',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/** აქ ჩასმული CSS გამოყენებული იქნება გაფორმების ყველა გარეკანზე */',
@@ -3023,6 +3019,8 @@ $2',
 'spam_reverting' => 'დაბრუნება ბოლო ვერსიასთან, რომელიც არ შეიცავს ბმულს $1-თან',
 'spam_blanking' => 'ყველა გვერდი შეიცავს ბმულს $1-გვერდზე. გასუფთავება',
 'spam_deleting' => 'ყველა ვერსია შეიცავდა ბმულს $1-ზე, მიმდინარეობს წაშლა',
+'simpleantispam-label' => "სპამის საწინააღმდეგო შემოწმება.
+ეს '''არ''' შეავსოთ!",
 
 # Info page
 'pageinfo-title' => 'ინფორმაცია „$1“-თვის',
@@ -3036,7 +3034,7 @@ $2',
 'pageinfo-length' => 'გვერდის სიგრძე (ბაიტებში)',
 'pageinfo-article-id' => 'გვერდის ID',
 'pageinfo-language' => 'გვერდის შინაარსის ენა',
-'pageinfo-robot-policy' => 'á\83¡á\83\90á\83«á\83\98á\83\94á\83\91á\83\9d á\83¡á\83\98á\83¡á\83¢á\83\94á\83\9bá\83\98á\83¡ á\83¡á\83¢á\83\90á\83¢á\83£á\83¡á\83\98',
+'pageinfo-robot-policy' => 'á\83\98á\83\9cá\83\93á\83\94á\83¥á\83¡á\83\90á\83ªá\83\98á\83\90 á\83¡á\83\90á\83«á\83\98á\83\94á\83\91á\83\9d á\83 á\83\9dá\83\91á\83\9dá\83¢á\83\94á\83\91á\83\98á\83\97',
 'pageinfo-robot-index' => 'დაშვებულია',
 'pageinfo-robot-noindex' => 'არ არის დაშვებული',
 'pageinfo-views' => 'ხილვების რაოდენობა',
@@ -3630,7 +3628,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'ამ ფაილის რედაქტირებისას გამოიყენეთ გარე პროგრამა',
-'edit-externally-help' => '(დაწვრილებითი ინფორმაციისთვის იხილეთ [//www.mediawiki.org/wiki/Manual:External_editors ჩადგმის ინსტრუქციები])',
+'edit-externally-help' => '(დაწვრილებითი ინფორმაციისთვის იხილეთ [https://www.mediawiki.org/wiki/Manual:External_editors ჩადგმის ინსტრუქციები])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ყველა',
@@ -3691,20 +3689,18 @@ $5
 
 წერილი მოძველდება $4.',
 'confirmemail_body_set' => 'ვიღაცამ, შესაძლოა თქვენ, IP მისამართით $1,
\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\90 á\83\90á\83\9cá\83\90á\83 á\83\98á\83¨á\83\98á\83¡ á\83\98á\83\9bá\83\94á\83\98á\83\9aá\83\98 "$2" á\83\90á\83\9b á\83\94á\83\9a\83¤á\83\9dá\83¡á\83¢á\83\98á\83¡ á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\98á\83\97 {{SITENAME}}-á\83\96á\83\94.
\83\9eá\83 á\83\9dá\83\94á\83¥á\83¢á\83¨á\83\98 {{SITENAME}} á\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\90 á\83\94á\83\9a\83¤á\83\9dá\83¡á\83¢á\83\98á\83¡ á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\98 á\83\90á\83\9cá\83\92á\83\90á\83 á\83\98á\83¨á\83\98á\83¡á\83\90á\83\97á\83\95á\83\98á\83¡ "$2" á\83\90á\83\9b á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\98á\83\97.
 
 იმის დასადასტურებლად, რომ ეს ანგარიში ნამდვილად თქვენ გეკუთვნით
-და ელ-ფოსტის შესაძლებლობების  გადააქტიურებლად {{SITENAME}} გვერდზე,
-
-გახსენით ეს ბმული თქვენს ბრაუზერში:
+და ელ.ფოსტის შესაძლებლობების  გასააქტიურებლად საიტზე {{SITENAME}}, გახსენით ეს ბმული თქვენს ბრაუზერში:
 
 $3
 
\83\97á\83£ á\83\94á\83¡ á\83\97á\83¥á\83\95á\83\94á\83\9c *á\83\90á\83 * á\83\98á\83§á\83\90á\83\95á\83\98á\83\97, á\83\9bá\83\90á\83¨á\83\98á\83\9c á\83\9cá\83£ á\83¨á\83\94á\83®á\83\95á\83\90á\83\9aá\83\97 á\83\9bá\83\98á\83§á\83\94á\83\95á\83\98á\83\97 á\83\90á\83\9b á\83\91á\83\9bá\83£á\83\9aá\83¡ á\83\98á\83\9bá\83\94á\83\98á\83\9aá\83\98á\83¡ á\83¨á\83\94á\83\9bá\83\9dá\83¬á\83\9bá\83\94á\83\91á\83\98á\83¡ á\83\92á\83\90á\83¡á\83\90á\83\97á\83\98á\83¨á\83\90á\83\93.
\83\97á\83£ á\83\94á\83¡ á\83\97á\83¥á\83\95á\83\94á\83\9c *á\83\90á\83 * á\83\98á\83§á\83\90á\83\95á\83\98á\83\97, á\83\9bá\83\90á\83¨á\83\98á\83\9c á\83\94á\83\9a\83¤á\83\9dá\83¡á\83¢á\83\98á\83¡ á\83\9bá\83\98á\83¡á\83\90á\83\9bá\83\90á\83 á\83\97á\83\98á\83¡ á\83\93á\83\90á\83¡á\83¢á\83£á\83 á\83\94á\83\91á\83\98á\83¡ á\83\92á\83\90á\83¡á\83\90á\83£á\83¥á\83\9bá\83\94á\83\91á\83\9aá\83\90á\83\93, á\83\92á\83\90á\83\93á\83\90á\83\93á\83\98á\83\97 á\83\90á\83\9b á\83\91á\83\9bá\83£á\83\9aá\83\96á\83\94:
 
 $5
 
-წერილი მოძველდება $4.',
+წერილის ვადის გასვლის თარიღია $4.',
 'confirmemail_invalidated' => 'ელ-ფოსტის დადასტურება გაუქმდა',
 'invalidateemail' => 'ელ-ფოსტის დადასტურების გაუქმება',
 
@@ -3856,7 +3852,7 @@ $5
 'version-version' => '(ვერსია $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'ლიცენზია',
-'version-poweredby-credits' => "ეს ვიკი მუშაობს '''[//www.mediawiki.org/ MediaWiki]'''-ს ძრავზე, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "ეს ვიკი მუშაობს '''[https://www.mediawiki.org/ MediaWiki]'''-ს ძრავზე, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'სხვები',
 'version-poweredby-translators' => 'translatewiki.net-ის მთარგმნელები',
 'version-credits-summary' => 'გვინდა მადლობა გადავუხადოთ შემდეგ მომხმარებლებს მათი წვლილისათვის [[Special:Version|მედიავიკის]] განვითარებაში.',
@@ -3898,8 +3894,7 @@ MediaWiki ვრცელდება იმ იმედით, რომ ი
 
 # Special:SpecialPages
 'specialpages' => 'სპეციალური გვერდები',
-'specialpages-note' => '----
-* ჩვეულებრივი სპეცგვერდები.
+'specialpages-note' => '* ჩვეულებრივი სპეცგვერდები.
 * <span class="mw-specialpagerestricted">სპეცგვერდები შეზღუდული მისაწვდომობით.</span>',
 'specialpages-group-maintenance' => 'ტექნიკური მომსახურების ანგარიშები',
 'specialpages-group-other' => 'სხვა სპეციალური გვერდები',
@@ -4097,8 +4092,20 @@ MediaWiki ვრცელდება იმ იმედით, რომ ი
 
 # Limit report
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|წამი}}',
+'limitreport-walltime' => 'რეალურ დროში გამოყენება',
 'limitreport-walltime-value' => '$1 {{PLURAL:$1|წამი}}',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|ბაიტი}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|ბაიტი}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'გაშლილი თარგები',
+'expand_templates_title' => 'კონტექსტის სათაური, {{FULLPAGENAME}}-სთვის და ა.შ.:',
+'expand_templates_input' => 'შესაყვანი ტექსტი:',
+'expand_templates_output' => 'შედეგი',
+'expand_templates_xml_output' => 'XML-ის გამოტანა',
+'expand_templates_ok' => 'შესრულება',
+'expand_templates_remove_comments' => 'კომენტარების წაშლა',
+'expand_templates_remove_nowiki' => 'ტეგების დათრგუნვა <nowiki> შედეგში',
+'expand_templates_preview' => 'წინა',
+
 );
index 147e19a..d519ac2 100644 (file)
@@ -54,7 +54,6 @@ $specialPageAliases = array(
        'Categories'                => array( 'Kategoriyalar' ),
        'Contributions'             => array( 'Paydalanıwshı u\'lesi' ),
        'Deadendpages'              => array( 'Hesh betke siltemeytug\'ın betler' ),
-       'Disambiguations'           => array( 'Ko\'p ma\'nisliler' ),
        'DoubleRedirects'           => array( 'Qos burıwshılar' ),
        'Emailuser'                 => array( 'Xat jiberiw' ),
        'Export'                    => array( 'Eksport' ),
@@ -151,6 +150,7 @@ $dateFormats = array(
 );
 
 $linkTrail = "/^((?:[a-zıʼ’“»]|'(?!'))+)(.*)$/sDu";
+$linkPrefixCharset = 'a-zıA-Zİ\\x80-\\xff';
 
 $messages = array(
 # User preference toggles
@@ -264,8 +264,6 @@ $messages = array(
 'category-file-count-limited' => "Usı kategoriyada to'mendegi {{PLURAL:$1|fayl|$1 fayl}} bar.",
 'listingcontinuesabbrev' => 'dawamı',
 
-'linkprefix' => '/^(.*?)([a-zıA-Zİ\\x80-\\xff]+)$/sDu',
-
 'about' => 'Haqqında',
 'article' => "Mag'lıwmat beti",
 'newwindow' => "(jan'a aynada)",
@@ -386,8 +384,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => '"$1" saytınan alıng\'an',
 'youhavenewmessages' => 'Sizge $1 bar ($2).',
-'newmessageslink' => "jan'a xabarlar",
-'newmessagesdifflink' => "aqırg'ı o'zgeris",
 'youhavenewmessagesmulti' => "$1 betinde sizge jan'a xabarlar bar",
 'editsection' => "o'zgertiw",
 'editold' => "o'zgertiw",
@@ -850,8 +846,6 @@ Barlıq mag'lıwmat tu'rin (sonın' ishinde sa'wbet betlerdi, shablonlardı h.t.
 'preferences' => 'Sazlawlar',
 'mypreferences' => "Menin' sazlawlarım",
 'prefs-edits' => "O'zgertiwler sanı:",
-'prefsnologin' => 'Kirilmegen',
-'prefsnologintext' => 'Sazlawların\'ızdı ornatıw ushın <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kiriwin\'iz]</span> sha\'rt.',
 'changepassword' => "Paroldi o'zgertiw",
 'prefs-skin' => "Sırtqı ko'rinis",
 'skin-preview' => 'Korip al',
@@ -1039,6 +1033,7 @@ Barlıq mag'lıwmat tu'rin (sonın' ishinde sa'wbet betlerdi, shablonlardı h.t.
 'recentchanges-label-minor' => "Bul kishi o'zgeris",
 'recentchanges-label-bot' => "Bul o'zgeristi bot kiritti",
 'recentchanges-label-unpatrolled' => "Bul o'zgeris ele baqlanbag'an",
+'recentchanges-legend-newpage' => '$1 - taza bet',
 'rcnote' => "To'mende $4, $5 waqtındag'ı aqırg'ı {{PLURAL:$2|ku'ndegi|'''$2''' ku'ndegi}} {{PLURAL:$1|'''1''' o'zgeris ko'rsetilgen|aqırg'ı '''$1''' o'zgeris ko'rsetilgen}}.",
 'rcnotefrom' => "To'mende '''$2''' baslap '''$1''' shekemgi o'zgerisler ko'rsetilgen.",
 'rclistfrom' => "$1 waqtınan baslap jan'a o'zgerisler ko'rset",
@@ -1645,7 +1640,7 @@ Basqa atama saylan'",
 'allmessagesdefault' => 'Defolt tekst',
 'allmessagescurrent' => "Ha'zirgi tekst",
 'allmessagestext' => "Bul {{ns:mediawiki}} isimler ko'pligindegi bar bolg'an sistema xabarları dizimi.
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.",
 
 # Thumbnails
 'thumbnail-more' => "U'lkeytiw",
@@ -1805,7 +1800,7 @@ Eger fayl jaratılg'anınan keyin o'zgertilgen bolsa, geybir parametrleri o'zger
 
 # External editor support
 'edit-externally' => "Bul fayldı sırtqı bag'darlama arqalı o'zgertiw",
-'edit-externally-help' => "(Ko'birek mag'lıwmat ushın [//www.mediawiki.org/wiki/Manual:External_editors ornatıw jolların] qaran')",
+'edit-externally-help' => "(Ko'birek mag'lıwmat ushın [https://www.mediawiki.org/wiki/Manual:External_editors ornatıw jolların] qaran')",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => "ha'mmesin",
index 27bff4d..ec45e1d 100644 (file)
@@ -300,8 +300,6 @@ $1',
 'ok' => 'Seɣbel',
 'retrievedfrom' => 'Yettwaddem seg "$1"',
 'youhavenewmessages' => 'Ɣur-k $1 ($2).',
-'newmessageslink' => 'Izen amaynut',
-'newmessagesdifflink' => 'Abeddel aneggaru',
 'youhavenewmessagesfromusers' => 'Tesɛiḍ $1 n {{PLURAL:$3|useqdac nniḍen|$3 iseqdacen nniḍen}} ( $2 ).',
 'youhavenewmessagesmanyusers' => 'Tesɛiḍ $1 n aṭas n iseqdacen ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|izen amaynut|inzan imaynuten}}',
@@ -1045,8 +1043,6 @@ Tzemreḍ ad affeḍ tilɣa deg [{{fullurl:{{#Special:Log}}/delete|page={{FULLPA
 'preferences' => 'Isemyifiyen',
 'mypreferences' => 'Isemyifiyen inu',
 'prefs-edits' => 'Amḍan n ibeddlilen :',
-'prefsnologin' => 'Ur tekcimeḍ ara',
-'prefsnologintext' => 'Ilaq ad iliḍ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} qqeneḍ]</span> iwakken ad beddeleḍ iɣewwaren ik/im n useqdac.',
 'changepassword' => 'Beddel awal n tbaḍnit',
 'prefs-skin' => 'Aglim',
 'skin-preview' => 'Pre-timeẓriwt',
@@ -2302,7 +2298,7 @@ Anda tebɣiḍ tesmimeḍ "[[:$1]]" yella yagi. tebɣiḍ ad temḥuḍ iwakken
 'allmessagesdefault' => 'Aḍris ameslugen',
 'allmessagescurrent' => 'Aḍris n tura',
 'allmessagestext' => 'Wagi d-umuɣ n inzan yestufan deg tallunt MediaWiki.
-Ẓeṛ [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dɣa [//translatewiki.net translatewiki.net] ma tebɣiḍ ad ɛiweneḍ i usideg imcettel n MediaWiki.',
+Ẓeṛ [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dɣa [//translatewiki.net translatewiki.net] ma tebɣiḍ ad ɛiweneḍ i usideg imcettel n MediaWiki.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' ut yezmir ara ad yettuseqdac axaṭer '''\$wgUseDatabaseMessages''' yettwakkes.",
 'allmessages-filter-legend' => 'Tastayt',
 'allmessages-filter-unmodified' => 'Ur yebeqqeḍ ara',
@@ -2811,7 +2807,7 @@ Izdayen nniḍen ɣef yiwen ajerriḍ llan d tisuraf, am isebtar ɣef anta tugna
 
 # External editor support
 'edit-externally' => 'Beddel afaylu-yagi s usnas aberrani.',
-'edit-externally-help' => 'Ẓer [//www.mediawiki.org/wiki/Manual:External_editors taknut] iwakken ad tessneḍ kter.',
+'edit-externally-help' => 'Ẓer [https://www.mediawiki.org/wiki/Manual:External_editors taknut] iwakken ad tessneḍ kter.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'akk',
index 05dddd7..d96e86b 100644 (file)
@@ -310,8 +310,6 @@ $1',
 'ok' => 'ОК',
 'retrievedfrom' => 'Къыздырахар: "$1"',
 'youhavenewmessages' => 'КъыпхуэкӀуауэ уиӀэ $1 ($2).',
-'newmessageslink' => 'тхыгъэщIэхэр',
-'newmessagesdifflink' => 'иужьрей зэхъуэкІыныгъэр',
 'youhavenewmessagesmulti' => 'КъыпхуэкӀуауэ уиӀэ тхыгъэщӀэхэр $1 идеж',
 'editsection' => 'гъэтэрэзын',
 'editold' => 'гъэтэрэзын',
@@ -970,8 +968,6 @@ $1",
 'preferences' => 'Зэгъэзэхуэпхъэхэр',
 'mypreferences' => 'Си зэгъэзэхуэгъуэхэр',
 'prefs-edits' => 'Гъэтэрэзыгъуэхэм я бжыгъэр:',
-'prefsnologin' => 'Системэм зыкъебгъэцӀыхуакъым',
-'prefsnologintext' => 'ЦӀыхухэтым и зэгъэзэхуэгъуэхэм уелэжьын щхьэкӀэ системэм <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} зыкъебгъэцӀыхун хуэй]</span>',
 'prefs-skin' => 'ЗэфӀэгъувэным и теухуапхъэ',
 'prefs-datetime' => 'Махуэмрэ зэманымрэ',
 'prefs-personal' => 'Ныбжыгъуэ къэӀохугъуэ',
@@ -1338,7 +1334,7 @@ $1",
 
 # External editor support
 'edit-externally' => 'Файлыр гъэтэрэзын, нэгъуэщӀ программэ и сэбэпкӀэ',
-'edit-externally-help' => '(нэхъыбу еплъ [//www.mediawiki.org/wiki/Manual:External_editors илъхьэным и тепсэлъыхьыгъуэ])',
+'edit-externally-help' => '(нэхъыбу еплъ [https://www.mediawiki.org/wiki/Manual:External_editors илъхьэным и тепсэлъыхьыгъуэ])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'псори',
index b9c6760..f4efb63 100644 (file)
 $fallback = 'ur';
 $rtl = true;
 
+$namespaceNames = array(
+       NS_MAIN             => '',
+       NS_MEDIA            => 'میڈیا',
+       NS_SPECIAL          => 'خاص',
+       NS_TALK             => 'مشقولگی',
+       NS_USER             => 'ممبار/یوزر',
+);
+
 $messages = array(
 # User preference toggles
 'tog-underline' => 'ربطو خط کشیدگی',
@@ -269,8 +277,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => '‘‘$1’’ نقل کاردو',
 'youhavenewmessages' => 'تہ بچے ای $1 شیر۔ ($2)',
-'newmessageslink' => 'نوغ پیغامات',
-'newmessagesdifflink' => 'تـجـدیـد مـاقـبل آخـراری فـرق',
 'youhavenewmessagesmulti' => 'ء$1 تہ بچے نوغ نوغ پیغامات شینی',
 'editsection' => 'ترمیم',
 'editold' => 'ترمیم',
@@ -1074,8 +1080,8 @@ HTML tags لوڑے.',",
 
 # External editor support
 'edit-externally' => 'ھیہ مسلو ایڈیٹ کورے',
-'edit-externally-help' => '(See the [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)
-(مزید معلوماتو بچے ھیہ لنکہ بوغے [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] )',
+'edit-externally-help' => '(See the [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)
+(مزید معلوماتو بچے ھیہ لنکہ بوغے [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] )',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'سف',
index 8f18ce2..f338c06 100644 (file)
@@ -8,6 +8,7 @@
  * @file
  *
  * @author Erdemaslancan
+ * @author Gorizon
  * @author Mirzali
  */
 
@@ -177,8 +178,6 @@ $messages = array(
 'noindex-category' => 'Pelê bêendeksıni',
 'broken-file-category' => 'Peli be gıreunê dosyeunê sıkıtau',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Heqa',
 'article' => 'Pela tedeesteyu',
 'newwindow' => '(zerrê pençerê dê newey de beno ra)',
@@ -282,7 +281,7 @@ $1',
 'pool-errorunknown' => 'Xeta nêzanıtiye',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
-'aboutsite' => 'Heqa {{SITENAME}} de',
+'aboutsite' => 'Heqdé {{SITENAME}}',
 'aboutpage' => 'Project:Heqa',
 'copyright' => 'Zerrek bınê $1 dero.',
 'copyrightpage' => '{{ns:project}}:Telifheqiye',
@@ -311,8 +310,6 @@ $1',
 'pagetitle-view-mainpage' => '',
 'retrievedfrom' => '"$1" ra ard',
 'youhavenewmessages' => 'Yê sıma $1 ($2) esto.',
-'newmessageslink' => 'mesacê newey',
-'newmessagesdifflink' => 'vurnaiso peyên',
 'youhavenewmessagesmulti' => '$1 de mesacê sımaê newey estê',
 'editsection' => 'bıvurne',
 'editold' => 'bıvurne',
@@ -766,8 +763,6 @@ Diqet kerê, beno ke tedeestê {{SITENAME}} uza endi rozane niyê.",
 'preferences' => 'Tercihi',
 'mypreferences' => 'Tercihê mı',
 'prefs-edits' => 'Numra vurnaisun:',
-'prefsnologin' => 'Cı nêkota',
-'prefsnologintext' => 'Sıma gunê <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} cı kuyê]</span> ke dıma tercihunê karberi bınusnê.',
 'changepassword' => 'Parola bıvurne',
 'prefs-skin' => 'Çerme',
 'skin-preview' => 'Verqayt',
@@ -906,6 +901,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'recentchanges-label-minor' => 'No zu vurnaiso qıckeko',
 'recentchanges-label-bot' => 'No vurnais terefê zu boti ra bi',
 'recentchanges-label-unpatrolled' => 'No vurnais hona çım ra ranêvêrdo',
+'recentchanges-legend-newpage' => '$1 - pela newiye',
 'rcnote' => "Cêr {{PLURAL:$1|'''1''' vurnaiso peyên|'''$1''' vurnaisê peyêni}} be {{PLURAL:$2|roza peyêne|'''$2''' rozunê peyênunê}} $5, $4 ra estê.",
 'rcnotefrom' => "Cêr de vurnayîşê esto ke '''$2''' ra raver  (heta '''$1''' mucnayiyo).",
 'rclistfrom' => '$1 ra hata nıka vurnaisunê newu bıasne',
@@ -1503,7 +1499,7 @@ Eke dosya de peydêna vuriyais biyo ki, beno ke taê melumati gorê vurnaisê ne
 
 # External editor support
 'edit-externally' => 'Na dosya be mırecaetê de teberi bıvurne',
-'edit-externally-help' => '(Serba daêna melumati qaytê pelga [//www.mediawiki.org/wiki/Manual:External_editors ayarê gurenaena teberi] be)',
+'edit-externally-help' => '(Serba daêna melumati qaytê pelga [https://www.mediawiki.org/wiki/Manual:External_editors ayarê gurenaena teberi] be)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'pêro',
@@ -1530,8 +1526,7 @@ Eke dosya de peydêna vuriyais biyo ki, beno ke taê melumati gorê vurnaisê ne
 
 # Special:SpecialPages
 'specialpages' => 'Pelê xaşi',
-'specialpages-note' => '----
-* Pelê xususiyê normali.
+'specialpages-note' => '* Pelê xususiyê normali.
 * <span class="mw-specialpagerestricted">Pelê xususiyê mehcuri.</span>',
 'specialpages-group-maintenance' => 'Tebliğê baxımi',
 'specialpages-group-other' => 'Pelê xususiyê bini',
index 0e98531..e96812a 100644 (file)
@@ -311,7 +311,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'بارلىق_بەتتەر' ),
        'Ancientpages'              => array( 'ەسكى_بەتتەر' ),
        'Block'                     => array( 'جايدى_بۇعاتتاۋ', 'IP_بۇعاتتاۋ' ),
-       'Blockme'                   => array( 'وزدىكتىك_بۇعاتتاۋ', 'وزدىك_بۇعاتتاۋ', 'مەنى_بۇعاتتاۋ' ),
        'Booksources'               => array( 'كىتاپ_قاينارلارى' ),
        'BrokenRedirects'           => array( 'جارامسىز_ايداعىشتار', 'جارامسىز_ايداتۋلار' ),
        'Categories'                => array( 'ساناتتار' ),
@@ -320,7 +319,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'ۇلەسى' ),
        'CreateAccount'             => array( 'جاڭا_تىركەلگى', 'تىركەلگى_جاراتۋ' ),
        'Deadendpages'              => array( 'تۇيىق_بەتتەر' ),
-       'Disambiguations'           => array( 'ايرىقتى_بەتتەر' ),
        'DoubleRedirects'           => array( 'شىنجىرلى_ايداعىشتار', 'شىنجىرلى_ايداتۋلار' ),
        'Emailuser'                 => array( 'حات_جىبەرۋ' ),
        'Export'                    => array( 'سىرتقا_بەرۋ' ),
@@ -606,8 +604,6 @@ $messages = array(
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => '«$1» بەتىنەن الىنعان',
 'youhavenewmessages' => 'سىزگە $1 بار ($2).',
-'newmessageslink' => 'جاڭا حابارلار',
-'newmessagesdifflink' => 'سوڭعى وزگەرىسىنە',
 'youhavenewmessagesmulti' => '$1 دەگەندە جاڭا حابارلار بار',
 'editsection' => 'وڭدەۋ',
 'editold' => 'وڭدەۋ',
@@ -1127,8 +1123,6 @@ $3 كەلتىرىلگەن سەبەبى: ''$2''",
 'preferences' => 'باپتالىمدار',
 'mypreferences' => 'باپتالىمدارىم',
 'prefs-edits' => 'وڭدەمە سانى:',
-'prefsnologin' => 'كىرمەگەنسىز',
-'prefsnologintext' => 'باپتاۋىڭىزدى قويۋ ٴۇشىن [[Special:UserLogin|كىرۋىڭىز]] ٴتىيىستى.',
 'changepassword' => 'قۇپىييا ٴسوزدى وزگەرتۋ',
 'prefs-skin' => 'مانەرلەر',
 'skin-preview' => 'قاراپ شىعۋ',
@@ -2121,7 +2115,7 @@ MediaWiki جۇيەسىنىڭ [[{{#special:Import}}|سىرتتان الۋ بەت
 'allmessagesdefault' => 'ادەپكى ٴماتىنى',
 'allmessagescurrent' => 'اعىمدىق ٴماتىنى',
 'allmessagestext' => 'مىندا {{ns:mediawiki}} ەسىم اياسىندا جەتىمدى جۇيە حابار ٴتىزىمى بەرىلەدى.
-ەگەر امبەباپ MediaWiki جەرسىندىرۋگە ۇلەس قوسقىڭىز كەلسە [//www.mediawiki.org/wiki/Localisation MediaWiki جەرسىندىرۋ بەتىنە] جانە [//translatewiki.net translatewiki.net جوباسىنا] بارىپ شىعىڭىز.',
+ەگەر امبەباپ MediaWiki جەرسىندىرۋگە ۇلەس قوسقىڭىز كەلسە [https://www.mediawiki.org/wiki/Localisation MediaWiki جەرسىندىرۋ بەتىنە] جانە [//translatewiki.net translatewiki.net جوباسىنا] بارىپ شىعىڭىز.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' وشىرىلگەن سەبەبىنەن '''{{ns:special}}:AllMessages''' بەتى قولدانىلمايدى.",
 
 # Thumbnails
@@ -2606,7 +2600,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'بۇل فايلدى شەتتىك قوندىرما ارقىلى وڭدەۋ',
-'edit-externally-help' => 'كوبىرەك اقپارات ٴۇشىن [//www.mediawiki.org/wiki/Manual:External_editors ورناتۋ نۇسقامالارىن] قاراڭىز.',
+'edit-externally-help' => 'كوبىرەك اقپارات ٴۇشىن [https://www.mediawiki.org/wiki/Manual:External_editors ورناتۋ نۇسقامالارىن] قاراڭىز.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'بارلىق',
@@ -2818,8 +2812,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'ارنايى بەتتەر',
-'specialpages-note' => '----
-* كادىمگى ارنايى بەتتەر.
+'specialpages-note' => '* كادىمگى ارنايى بەتتەر.
 * <strong class="mw-specialpagerestricted">شەكتەلگەن ارنايى بەتتەر.</strong>',
 'specialpages-group-maintenance' => 'باپتاۋ باياناتتارى',
 'specialpages-group-other' => 'تاعى باسقا ارنايى بەتتەر',
@@ -2839,4 +2832,20 @@ $5
 'revdelete-unrestricted' => 'اكىمشىلەردەن تىيىمداردى الاستادى',
 'rightsnone' => '(ەشقانداي)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'ۇلگىلەردى ۇلعايتۋ',
+'expand_templates_intro' => 'وسى قۇرال ارنايى بەتى الدەبىر ٴماتىندى الادى دا,
+بۇنىڭ ىشىندەگى بارلىق كىرىكتەلگەن ۇلگىلەردى مەيلىنشە ۇلعايتادى.
+مىنا <nowiki>{{#language:...}} سىيياقتى جوڭدەتۋ فۋنكتسىييالارىن دا, جانە {{CURRENTDAY}}
+سىيياقتى اينامالىلارىن دا ۇلعايتادى (ناقتى ايتقاندا, قوس قابات ساداق جاقشالار اراسىنداعى بارلىعىن).
+بۇنى ٴوز MediaWiki باعدارلاماسىنان قاتىستى جوڭدەتۋ ساتىن شاقىرىپ ىستەلىنەدى.',
+'expand_templates_title' => 'ٴماتىن ارالىق اتاۋى ({{FULLPAGENAME}} ت.ب. بەتتەر ٴۇشىن):',
+'expand_templates_input' => 'كىرىس ٴماتىنى:',
+'expand_templates_output' => 'ناتىيجەسى',
+'expand_templates_xml_output' => 'XML شىعارۋى',
+'expand_templates_ok' => 'جارايدى',
+'expand_templates_remove_comments' => 'ماندەمەلەرىن الاستاتىپ?',
+'expand_templates_generate_xml' => 'XML وڭدەتۋ بۇتاقتارىن كورسەت',
+'expand_templates_preview' => 'قاراپ شىعۋ',
+
 );
index 8163914..af2b638 100644 (file)
@@ -281,7 +281,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Барлық_беттер' ),
        'Ancientpages'              => array( 'Ескі_беттер' ),
        'Block'                     => array( 'Жайды_бұғаттау', 'IP_бұғаттау' ),
-       'Blockme'                   => array( 'Өздіктік_бұғаттау', 'Өздік_бұғаттау', 'Мені_бұғаттау' ),
        'Booksources'               => array( 'Кітап_қайнарлары' ),
        'BrokenRedirects'           => array( 'Жарамсыз_айдағыштар', 'Жарамсыз_айдатулар' ),
        'Categories'                => array( 'Санаттар' ),
@@ -290,7 +289,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Үлесі' ),
        'CreateAccount'             => array( 'Жаңа_тіркелгі', 'Тіркелгі_Жарату' ),
        'Deadendpages'              => array( 'Тұйық_беттер' ),
-       'Disambiguations'           => array( 'Айрықты_беттер' ),
        'DoubleRedirects'           => array( 'Шынжырлы_айдағыштар', 'Шынжырлы_айдатулар' ),
        'Emailuser'                 => array( 'Хат_жіберу' ),
        'Export'                    => array( 'Сыртқа_беру' ),
@@ -635,12 +633,10 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => '«$1» бетінен алынған',
 'youhavenewmessages' => 'Сізде $1 бар ($2).',
-'newmessageslink' => 'жаңа хабарламалар',
-'newmessagesdifflink' => 'соңғы өзгерiсіне',
 'youhavenewmessagesfromusers' => 'Сіз {{PLURAL:$3|басқа қатысушыдан|$3 қатысушыдан}} $1 алдыңыз ($2).',
 'youhavenewmessagesmanyusers' => 'Сіз бірнеше қатысушыдан $1 алдыңыз ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|жаңа хабарлама|жаңа хабарламалар}}',
-'newmessagesdifflinkplural' => 'соңғы {{PLURAL:$1|өзгеріс|өзгерістер}}',
+'newmessageslinkplural' => '{{PLURAL:$1|жаңа хабарлама|999=жаңа хабарламалар}}',
+'newmessagesdifflinkplural' => 'соңғы {{PLURAL:$1|өзгеріс|999=өзгерістер}}',
 'youhavenewmessagesmulti' => '$1 дегенде жаңа хабарламалар бар',
 'editsection' => 'өңдеу',
 'editold' => 'өңдеу',
@@ -766,7 +762,7 @@ $2',
 'invalidtitle-knownnamespace' => '"$2" есім кеңістік түрі және  "$3" мәтіні жарамсыз',
 'invalidtitle-unknownnamespace' => 'Нөмері $1 белгісіз есім кеңістік түрі және "$2" мәтіні жарамсыз',
 'exception-nologin' => 'Кірмегенсіз',
-'exception-nologin-text' => 'Бұл бет немесе әрекет бұл уикиге кіріуіңізді міндеттейді.',
+'exception-nologin-text' => 'Бұл әрекетке немесе бетке қатынау үшін [[Special:Userlogin|кіріңіз]].',
 
 # Virus scanner
 'virus-badscanner' => 'Дұрыс емес ішқұрылым. Белгісіз вирус сканері: $1',
@@ -814,9 +810,10 @@ $2',
 'gotaccount' => "Бұған дейін тіркеліп пе едіңіз? '''$1'''.",
 'gotaccountlink' => 'Кіріңіз',
 'userlogin-resetlink' => 'Қатысушы атын не құпия сөзді ұмыттыңыз ба?',
-'userlogin-resetpassword-link' => 'Құпия сөздіңізді ысыру',
+'userlogin-resetpassword-link' => 'Құпия сөздіңізді ұмыттыңыз ба?',
 'helplogin-url' => 'Help:Тіркелу',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Тіркелуге көмек]]',
+'userlogin-createanother' => 'Басқа тіркелгі жасау',
 'createacct-join' => 'Төменге өзіңіз туралы ақпарат енгізіңіз.',
 'createacct-another-join' => 'Төменге жаңа тіркелгі туралы ақпарат енгізіңіз.',
 'createacct-emailrequired' => 'Е-пошта мекен-жайы:',
@@ -1027,7 +1024,7 @@ IP-мекенжайыңыз бұл беттің түзету тарихында
 'blockednoreason' => 'еш себебі келтірілмеген',
 'whitelistedittext' => 'Беттерді өңдеу үшін сізде $1 болуы керек.',
 'confirmedittext' => 'Беттерді өңдеу үшін алдын ала Е-пошта мекенжайыңызды құптауыңыз жөн.
-Е-пошта мекенжайыңызды [Special:Preferences}}|қатысушы бапталымдарыңыз]] арқылы қойыңыз да жарамдылығын тексеріп шығыңыз.',
+Е-пошта мекенжайыңызды [[Special:Preferences|қатысушы бапталымдарыңыз]] арқылы қойыңыз да жарамдылығын тексеріп шығыңыз.',
 'nosuchsectiontitle' => 'Бұл бөлімді табу мүмкін емес',
 'nosuchsectiontext' => 'Сіз бұрын болмаған бөлімді өзгертпекшісіз.
 Мүмкін бұл бетті қарап жатқаныңызда ол бөлім жойылған немесе басқа орынға көшірілген.',
@@ -1248,8 +1245,8 @@ $3 келтірілген себебі: ''$2''",
 'revdelete-hide-user' => 'Өңдеуші атын (IP мекенжайын) жасыр',
 'revdelete-hide-restricted' => 'Осы тиымдарды әкімшілерге қолдану және бұл тілдесуді құлыптау',
 'revdelete-radio-same' => '(өзгертпе)',
-'revdelete-radio-set' => 'Ð\98Ó\99',
-'revdelete-radio-unset' => 'Ð\96оÒ\9b',
+'revdelete-radio-set' => 'Ð\96аÑ\81Ñ\8bÑ\80Ñ\8bлÒ\93ан',
+'revdelete-radio-unset' => 'Ð\9aÓ©Ñ\80Ñ\81еÑ\82Ñ\96лген',
 'revdelete-suppress' => 'Деректерді баршаға ұқсас әкімшілерден де шеттету',
 'revdelete-unsuppress' => 'Қалпына келтірілген түзетулерден тиымдарды аластау',
 'revdelete-log' => 'Себебі:',
@@ -1382,8 +1379,6 @@ $1",
 'preferences' => 'Баптаулар',
 'mypreferences' => 'Баптаулар',
 'prefs-edits' => 'Өңдеме саны:',
-'prefsnologin' => 'Кірмегенсіз',
-'prefsnologintext' => 'Қатысушы бапталымдарыңызды жөндеу үшін <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} кіруіңіз]</span> жөн.',
 'changepassword' => 'Құпия сөзді өзгерту',
 'prefs-skin' => 'Мәнерлер',
 'skin-preview' => 'Қарап шығу',
@@ -1667,6 +1662,7 @@ $1",
 'recentchanges-label-minor' => 'Бұл шағын өңдеме',
 'recentchanges-label-bot' => 'Бұл өңдемені бот жасады.',
 'recentchanges-label-unpatrolled' => 'Бұл өңдеме әлі тексеруден өтпеді.',
+'recentchanges-legend-newpage' => '$1 - жаңа бет',
 'rcnote' => "Төменде $5, $4 кезіне дейінгі соңғы {{PLURAL:$2|күндегі|'''$2''' күндегі}}, {{PLURAL:$1| '''1''' өзгеріс|соңғы '''$1''' өзгеріс}}  көрсетіледі.",
 'rcnotefrom' => "Төменде '''$2''' кезінен бергі ('''$1''' жеткенше дейін) өзгерістер көрсетіледі.",
 'rclistfrom' => '$1 кезінен бергі жаңа өзгерістерді көрсет.',
@@ -2470,7 +2466,7 @@ $1',
 # Contributions
 'contributions' => '{{GENDER:$1|Қатысушы}} үлестері',
 'contributions-title' => '$1 есімді қатысушының үлесі',
-'mycontris' => 'ҮлеÑ\81Ñ\82еÑ\80',
+'mycontris' => 'ҮлеÑ\81Ñ\96м',
 'contribsub2' => '$1 ($2) үлесі',
 'nocontribs' => 'Осы іздеу шартына сәйкес өзгерістер табылған жоқ.',
 'uctop' => '(ағымдағы)',
@@ -2751,7 +2747,7 @@ MediaWiki жүйесінің [[{{#special:Import}}|сырттан алу бет
 'allmessagesdefault' => 'Әдепкі мәтіні',
 'allmessagescurrent' => 'Ағымдық мәтіні',
 'allmessagestext' => 'Мында {{ns:mediawiki}} есім аясында жетімді жүйе хабар тізімі беріледі.
-Егер әмбебап MediaWiki жерсіндіруге үлес қосқыңыз келсе [//www.mediawiki.org/wiki/Localisation MediaWiki жерсіндіру бетіне] және [//translatewiki.net translatewiki.net жобасына] барып шығыңыз.',
+Егер әмбебап MediaWiki жерсіндіруге үлес қосқыңыз келсе [https://www.mediawiki.org/wiki/Localisation MediaWiki жерсіндіру бетіне] және [//translatewiki.net translatewiki.net жобасына] барып шығыңыз.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' өшірілген себебінен '''{{#special:AllMessages}}''' беті қолданылмайды.",
 'allmessages-filter-legend' => 'Сүзгі',
 'allmessages-filter-unmodified' => 'Өзгертілмегендер',
@@ -3403,7 +3399,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Бұл файлды шеттік қондырма арқылы өңдеу',
-'edit-externally-help' => '(көбірек ақпарат үшін [//www.mediawiki.org/wiki/Manual:External_editors орнату нұсқауларын] қараңыз)',
+'edit-externally-help' => '(көбірек ақпарат үшін [https://www.mediawiki.org/wiki/Manual:External_editors орнату нұсқауларын] қараңыз)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'барлық',
@@ -3641,8 +3637,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Арнайы беттер',
-'specialpages-note' => '----
-* Кәдімгі арнайы беттер.
+'specialpages-note' => '* Кәдімгі арнайы беттер.
 * <span class=="mw-specialpagerestricted">Шектелген арнайы беттер.</span>',
 'specialpages-group-maintenance' => 'Техникалық талқылау есептері',
 'specialpages-group-other' => 'Тағы басқа арнайы беттер',
@@ -3751,4 +3746,20 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|ғасыр|ғасыр}}',
 'duration-millennia' => '$1 {{PLURAL:$1|мың жылдық|мың жылдық}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Үлгілерді ұлғайту',
+'expand_templates_intro' => 'Осы құрал арнайы беті әлдебір мәтінді алады да,
+бұның ішіндегі барлық кіріктелген үлгілерді мейлінше ұлғайтады.
+Мына <nowiki>{{</nowiki>#language:...}} сияқты жөңдету функцияларын да, және <nowiki>{{</nowiki>CURRENTDAY}}
+сияқты айнамалыларын да ұлғайтады (нақты айтқанда, қос қабат садақ жақшалар арасындағы барлығын).
+Бұны өз MediaWiki бағдарламасынан қатысты жөңдету сатын шақырып істелінеді.',
+'expand_templates_title' => 'Мәтін аралық атауы ({{FULLPAGENAME}} т.б. беттер үшін):',
+'expand_templates_input' => 'Кіріс мәтіні:',
+'expand_templates_output' => 'Нәтижесі',
+'expand_templates_xml_output' => 'XML шығаруы',
+'expand_templates_ok' => 'Жарайды',
+'expand_templates_remove_comments' => 'Мәндемелерін аластатып?',
+'expand_templates_generate_xml' => 'XML өңдету бұтақтарын көрсет',
+'expand_templates_preview' => 'Қарап шығу',
+
 );
index 67e7cf7..42acac4 100644 (file)
@@ -276,7 +276,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Barlıq_better' ),
        'Ancientpages'              => array( 'Eski_better' ),
        'Block'                     => array( 'Jaýdı_buğattaw', 'IP_buğattaw' ),
-       'Blockme'                   => array( 'Özdiktik_buğattaw', 'Özdik_buğattaw', 'Meni_buğattaw' ),
        'Booksources'               => array( 'Kitap_qaýnarları' ),
        'BrokenRedirects'           => array( 'Jaramsız_aýdağıştar', 'Jaramsız_aýdatwlar' ),
        'Categories'                => array( 'Sanattar' ),
@@ -285,7 +284,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Ülesi' ),
        'CreateAccount'             => array( 'Jaña_tirkelgi', 'Tirkelgi_Jaratw' ),
        'Deadendpages'              => array( 'Tuýıq_better' ),
-       'Disambiguations'           => array( 'Aýrıqtı_better' ),
        'DoubleRedirects'           => array( 'Şınjırlı_aýdağıştar', 'Şınjırlı_aýdatwlar' ),
        'Emailuser'                 => array( 'Xat_jiberw' ),
        'Export'                    => array( 'Sırtqa_berw' ),
@@ -569,8 +567,6 @@ $messages = array(
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => '«$1» betinen alınğan',
 'youhavenewmessages' => 'Sizge $1 bar ($2).',
-'newmessageslink' => 'jaña xabarlar',
-'newmessagesdifflink' => 'soñğı özgerisine',
 'youhavenewmessagesmulti' => '$1 degende jaña xabarlar bar',
 'editsection' => 'öñdew',
 'editold' => 'öñdew',
@@ -1090,8 +1086,6 @@ Añğartpa: {{SITENAME}} torabınıñ mağlumat tizbeleri eskirgen bolwı mümki
 'preferences' => 'Baptalımdar',
 'mypreferences' => 'Baptalımdarım',
 'prefs-edits' => 'Öñdeme sanı:',
-'prefsnologin' => 'Kirmegensiz',
-'prefsnologintext' => 'Baptawıñızdı qoyw üşin [[Special:UserLogin|kirwiñiz]] tïisti.',
 'changepassword' => 'Qupïya sözdi özgertw',
 'prefs-skin' => 'Mänerler',
 'skin-preview' => 'Qarap şığw',
@@ -2085,7 +2079,7 @@ Soñğı jağdaýda siltemeni de, mısalı «{{{{ns:mediawiki}}:Mainpage}}» bet
 'allmessagesdefault' => 'Ädepki mätini',
 'allmessagescurrent' => 'Ağımdıq mätini',
 'allmessagestext' => 'Mında {{ns:mediawiki}} esim ayasında jetimdi jüýe xabar tizimi beriledi.
-Eger ämbebap MediaWiki jersindirwge üles qosqıñız kelse [//www.mediawiki.org/wiki/Localisation MediaWiki jersindirw betine] jäne [//translatewiki.net translatewiki.net jobasına] barıp şığıñız.',
+Eger ämbebap MediaWiki jersindirwge üles qosqıñız kelse [https://www.mediawiki.org/wiki/Localisation MediaWiki jersindirw betine] jäne [//translatewiki.net translatewiki.net jobasına] barıp şığıñız.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' öşirilgen sebebinen '''{{ns:special}}:AllMessages''' beti qoldanılmaýdı.",
 
 # Thumbnails
@@ -2569,7 +2563,7 @@ Basqaları ädepkiden jasırıladı.
 
 # External editor support
 'edit-externally' => 'Bul faýldı şettik qondırma arqılı öñdew',
-'edit-externally-help' => 'Köbirek aqparat üşin [//www.mediawiki.org/wiki/Manual:External_editors ornatw nusqamaların] qarañız.',
+'edit-externally-help' => 'Köbirek aqparat üşin [https://www.mediawiki.org/wiki/Manual:External_editors ornatw nusqamaların] qarañız.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'barlıq',
@@ -2777,8 +2771,7 @@ Tağı da [[Special:EditWatchlist|qalıpalğan öñdewişti paýdalana]] alasız
 
 # Special:SpecialPages
 'specialpages' => 'Arnaýı better',
-'specialpages-note' => '----
-* Kädimgi arnaýı better.
+'specialpages-note' => '* Kädimgi arnaýı better.
 * <strong class="mw-specialpagerestricted">Şektelgen arnaýı better.</strong>',
 'specialpages-group-maintenance' => 'Baptaw bayanattarı',
 'specialpages-group-other' => 'Tağı basqa arnaýı better',
@@ -2798,4 +2791,20 @@ Tağı da [[Special:EditWatchlist|qalıpalğan öñdewişti paýdalana]] alasız
 'revdelete-unrestricted' => 'äkimşilerden tïımdardı alastadı',
 'rightsnone' => '(eşqandaý)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Ülgilerdi ulğaýtw',
+'expand_templates_intro' => 'Osı qural arnaýı beti äldebir mätindi aladı da,
+bunıñ işindegi barlıq kiriktelgen ülgilerdi meýlinşe ulğaýtadı.
+Mına <nowiki>{{</nowiki>#language:...}} sïyaqtı jöñdetw fwnkcïyaların da, jäne <nowiki>{{</nowiki>CURRENTDAY}}
+sïyaqtı aýnamalıların da ulğaýtadı (naqtı aýtqanda, qos qabat sadaq jaqşalar arasındağı barlığın).
+Bunı öz MediaWiki bağdarlamasınan qatıstı jöñdetw satın şaqırıp istelinedi.',
+'expand_templates_title' => 'Mätin aralıq atawı ({{FULLPAGENAME}} t.b. better üşin):',
+'expand_templates_input' => 'Kiris mätini:',
+'expand_templates_output' => 'Nätïjesi',
+'expand_templates_xml_output' => 'XML şığarwı',
+'expand_templates_ok' => 'Jaraýdı',
+'expand_templates_remove_comments' => 'Mändemelerin alastatıp?',
+'expand_templates_generate_xml' => 'XML öñdetw butaqtarın körset',
+'expand_templates_preview' => 'Qarap şığw',
+
 );
index c4e951b..ebef206 100644 (file)
@@ -100,7 +100,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'ទំព័រចាស់ៗ' ),
        'Blankpage'                 => array( 'ទំព័រទទេ' ),
        'Block'                     => array( 'រាំងខ្ទប់IP' ),
-       'Blockme'                   => array( 'រាំងខ្ទប់' ),
        'Booksources'               => array( 'ប្រភពសៀវភៅ' ),
        'BrokenRedirects'           => array( 'ការបញ្ជូនបន្តដែលខូច' ),
        'Categories'                => array( 'ចំណាត់ថ្នាក់ក្រុម' ),
@@ -111,7 +110,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'បង្កើតគណនី' ),
        'Deadendpages'              => array( 'ទំព័រទាល់' ),
        'DeletedContributions'      => array( 'ការរួមចំណែកដែលត្រូវបានលុបចោល' ),
-       'Disambiguations'           => array( 'ចំណងជើងស្រដៀងគ្នា' ),
        'DoubleRedirects'           => array( 'ការបញ្ជូនបន្តទ្វេដង' ),
        'Emailuser'                 => array( 'អ្នកប្រើប្រាស់អ៊ីមែល' ),
        'Export'                    => array( 'នាំចេញ' ),
@@ -308,7 +306,7 @@ $messages = array(
 'tog-prefershttps' => 'ប្រើប្រាស់ការតភ្ជាប់មានសុវត្ថិភាពជានិច្ចពេលកត់ឈ្មោះចូល',
 
 'underline-always' => 'ជានិច្ច',
-'underline-never' => 'á\9e\80á\9e»á\9f\86á\9e¢á\9f\84យសោះ',
+'underline-never' => 'á\9e\80á\9e»á\9f\86á\9e²á\9f\92យសោះ',
 'underline-default' => 'តាមលំនាំដើមនៃ​កម្មវិធី​រុករក​',
 
 # Font style option in Special:Preferences
@@ -402,8 +400,6 @@ $messages = array(
 'broken-file-category' => 'ទំព័រទាំងឡាយដែលដាច់តំណភ្ជាប់',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'អំពី',
 'article' => 'មាតិកាអត្ថបទ',
 'newwindow' => '(បើក​លើ​បង្អួច​ថ្មី)',
@@ -482,7 +478,7 @@ $messages = array(
 'articlepage' => 'មើលខ្លឹមសារទំព័រ​',
 'talk' => 'ការពិភាក្សា',
 'views' => 'គំហើញ',
-'toolbox' => 'ប្រអប់​ឧបករណ៍',
+'toolbox' => '​ឧបករណ៍',
 'userpage' => 'មើលទំព័រអ្នកប្រើប្រាស់',
 'projectpage' => 'មើល​ទំព័រគម្រោង',
 'imagepage' => 'មើល​ទំព័រ​ឯកសារ',
@@ -512,7 +508,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'អំពី{{SITENAME}}',
 'aboutpage' => 'Project:អំពី',
-'copyright' => 'á\9e\9aá\9e\80á\9f\92á\9e\9fá\9e¶á\9e\9fá\9e·á\9e\91á\9f\92á\9e\92á\9e·á\9e\82á\9f\92á\9e\9aá\9e\94á\9f\8bá\9e\99á\9f\89á\9e¶á\9e\84á\9e\8aá\9f\84á\9e\99$1។',
+'copyright' => 'á\9e\81á\9f\92á\9e\9bá\9e¹á\9e\98á\9e\9fá\9e¶á\9e\9aá\9e¢á\9e\8fá\9f\92á\9e\90á\9e\94á\9e\91á\9e\94á\9f\92á\9e\9aá\9e¾á\9e\94á\9f\92á\9e\9aá\9e¶á\9e\9fá\9f\8bá\9e\94á\9e¶á\9e\93á\9e\80á\9f\92á\9e\9aá\9f\84á\9e\98á\9e¢á\9e¶á\9e\87á\9f\92á\9e\89á\9e¶á\9e\94á\9e\8eá\9f\92á\9e\8c$1 á\9e\9bá\9e¾á\9e\80á\9e\9bá\9f\82á\9e\84á\9e\8fá\9f\82á\9e\98á\9e¶á\9e\93á\9e\94á\9e\89á\9f\92á\9e\87á\9e¶á\9e\80á\9f\8bá\9e\95á\9f\92á\9e\9fá\9f\81á\9e\84á\9e\96á\9e¸á\9e\93á\9f\84á\9f\87។',
 'copyrightpage' => '{{ns:project}}:រក្សាសិទ្ធិ​',
 'currentevents' => 'ព្រឹត្តិការណ៍​ថ្មីៗ',
 'currentevents-url' => 'Project:ព្រឹត្តិការណ៍​ថ្មីៗ',
@@ -543,8 +539,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'បានពី "$1"',
 'youhavenewmessages' => 'អ្នកមាន $1 ($2)។',
-'newmessageslink' => 'សារថ្មីៗ',
-'newmessagesdifflink' => 'បន្លាស់ប្ដូរចុងក្រោយ',
 'youhavenewmessagesfromusers' => 'អ្នកមាន $1 ទទួលបានពី {{PLURAL:$3|អ្នកប្រើប្រាស់ម្នាក់|អុ្នកប្រើប្រាស់ចំនួន $3 នាក់}} ($2)។',
 'youhavenewmessagesmanyusers' => 'អ្នកមាន $1 ទទួលបានពីអ្នកប្រើប្រាស់ជាច្រើន ($2)។',
 'newmessageslinkplural' => '{{PLURAL:$1|សារថ្មីមួយ|សារថ្មី}}',
@@ -602,6 +596,7 @@ $1',
 # General errors
 'error' => 'មានបញ្ហា',
 'databaseerror' => 'មូលដ្ឋានទិន្នន័យមានបញ្ហា',
+'databaseerror-error' => 'កំហុស៖ $1',
 'laggedslavemode' => "'''ប្រយ័ត្ន៖''' ទំព័រនេះ​ប្រហែលជាគ្មានព័ត៌មានទាន់សម័យទេ។",
 'readonly' => 'មូលដ្ឋានទិន្នន័យត្រូវបានចាក់សោ',
 'enterlockreason' => 'សូមផ្ដល់ហេតុផលសម្រាប់ការជាប់សោ ព្រមទាំងកាលបរិច្ឆេទដោះសោវិញ',
@@ -673,7 +668,7 @@ $2',
 'invalidtitle-knownnamespace' => 'ចំណងជើងមិនត្រឹមត្រូវដែលមានលំហឈ្មោះ "$2" និងអត្ថបទ "$3"',
 'invalidtitle-unknownnamespace' => 'ចំណងជើងមិនត្រឹមត្រូវដែលមានលំហឈ្មោះមិនស្គាល់លេខ $1 និងអត្ថបទ "$2"',
 'exception-nologin' => 'មិនទាន់កត់ឈ្មោះចូលទេ',
-'exception-nologin-text' => 'á\9e\91á\9f\86á\9e\96á\9f\90á\9e\9aá\9e¬á\9e\9fá\9e\80á\9e\98á\9f\92á\9e\98á\9e\97á\9e¶á\9e\96á\9e\93á\9f\81á\9f\87á\9e\8fá\9e\98á\9f\92á\9e\9aá\9e¼á\9e\9cá\9e¢á\9f\84á\9e\99á\9e¢á\9f\92á\9e\93á\9e\80á\9e\92á\9f\92á\9e\9cá\9e¾á\9e\80á\9e¶á\9e\9aá\9e\80á\9e\8fá\9f\8bá\9e\88á\9f\92á\9e\98á\9f\84á\9f\87á\9e\85á\9e¼á\9e\9bá\9e\91á\9f\85á\9e\80á\9f\92á\9e\93á\9e»á\9e\84á\9e\9cá\9e·á\9e\82á\9e¸នេះ។',
+'exception-nologin-text' => 'á\9e\9fá\9e¼á\9e\98[[Special:Userlogin|lá\9e\80á\9e\8fá\9f\8bá\9e\88á\9f\92á\9e\98á\9f\84á\9f\87á\9e\85á\9e¼á\9e\9b]]á\9e\8aá\9e¾á\9e\98á\9f\92á\9e\94á\9e¸á\9e\85á\9e¼á\9e\9bá\9e¢á\9e¶á\9e\93á\9e\91á\9f\86á\9e\96á\9f\90á\9e\9aá\9e¬á\9e\92á\9f\92á\9e\9cá\9e¾á\9e\9fá\9e\80á\9e\98á\9f\92á\9e\98á\9e\97á\9e¶á\9e\96នេះ។',
 
 # Virus scanner
 'virus-badscanner' => "ការ​កំណត់​រចនា​សម្ព័ន្ធ​មិន​ល្អ​៖ កម្មវិធី​ស្កេន​មេរោគមិន​ស្គាល់​៖ ''$1''",
@@ -721,9 +716,10 @@ $2',
 'gotaccount' => "បើលោកអ្នកមានគណនីសម្រាប់ប្រើហើយ  សូម'''$1'''។",
 'gotaccountlink' => 'កត់ឈ្មោះចូល',
 'userlogin-resetlink' => 'តើអ្នកភ្លេចព័ត៌មានលម្អិតសម្រាប់កត់ឈ្មោះចូលហើយ?',
-'userlogin-resetpassword-link' => 'á\9e\9fá\9f\92á\9e\8aá\9e¶á\9e\9aá\9e\96á\9e¶á\9e\80á\9f\92á\9e\99á\9e\9fá\9e\98á\9f\92á\9e\84á\9e¶á\9e\8fá\9f\8bá\9e\9aá\9e\94á\9e\9fá\9f\8bá\9e¢á\9f\92á\9e\93á\9e\80',
+'userlogin-resetpassword-link' => 'á\9e¢á\9f\92á\9e\93á\9e\80á\9e\97á\9f\92á\9e\9bá\9f\81á\9e\85á\9e\96á\9e¶á\9e\80á\9f\92á\9e\99á\9e\9fá\9e\98á\9f\92á\9e\84á\9e¶á\9e\8fá\9f\8bá\9e á\9e¾á\9e\99?',
 'helplogin-url' => 'Help:ការកត់ឈ្មោះចូល',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|ជំនួយក្នុងការកត់ឈ្មោះចូល]]',
+'userlogin-createanother' => 'បង្កើតគណនីមួយទៀត',
 'createacct-join' => 'បំពេញព័ត៌មានរបស់អ្នកខាងក្រោម។',
 'createacct-another-join' => 'បញ្ចូលព័ត៌មានគណនីថ្មីខាងក្រោម។',
 'createacct-emailrequired' => 'អាសយដ្ឋានអ៊ីមែល',
@@ -795,7 +791,7 @@ $2',
 
 សូម​កត់ឈ្មោះចូល​ម្តងទៀត​បន្ទាប់ពី​អ្នក​បាន​ទទួល​ពាក្យសម្ងាត់ថ្មីនោះ។',
 'blocked-mailpassword' => 'អាសយដ្ឋានIPត្រូវបានហាមឃាត់មិនអោយធ្វើការកែប្រែ និងមិនអនុញ្ញាតឱ្យប្រើប្រាស់មុខងារសង្គ្រោះពាក្យសម្ងាត់ដើម្បីបង្ការការបំពានទេ។',
-'eauthentsent' => 'á\9e¢á\9f\8aá\9e¸á\9e\98á\9f\82á\9e\9bâ\80\8bá\9e\9fá\9e\98á\9f\92á\9e\9aá\9e¶á\9e\94á\9f\8bâ\80\8bá\9e\95á\9f\92á\9e\91á\9f\80á\9e\84á\9e\95á\9f\92á\9e\91á\9e¶á\9e\8fá\9f\8bâ\80\8bá\9e\94á\9e\89á\9f\92á\9e\87á\9e¶á\9e\80á\9f\8bá\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e¶á\9e\93á\9e\95á\9f\92á\9e\89á\9e¾á\9e\91á\9f\85â\80\8bá\9e¢á\9e¶á\9e\9fá\9e\99á\9e\8aá\9f\92á\9e\8bá\9e¶á\9e\93á\9e¢á\9f\8aá\9e¸á\9e\98á\9f\82á\9e\9bâ\80\8bá\9e\8aá\9f\82á\9e\9bá\9e\94á\9e¶á\9e\93á\9e\85á\9e»á\9f\87á\9e\8fá\9f\92á\9e\9aá\9eហើយ។
+'eauthentsent' => 'á\9e¢á\9f\8aá\9e¸á\9e\98á\9f\82á\9e\9bâ\80\8bá\9e\9fá\9e\98á\9f\92á\9e\9aá\9e¶á\9e\94á\9f\8bâ\80\8bá\9e\95á\9f\92á\9e\91á\9f\80á\9e\84á\9e\95á\9f\92á\9e\91á\9e¶á\9e\8fá\9f\8bâ\80\8bá\9e\94á\9e\89á\9f\92á\9e\87á\9e¶á\9e\80á\9f\8bá\9e\8fá\9f\92á\9e\9aá\9e¼á\9e\9cá\9e\94á\9e¶á\9e\93á\9e\95á\9f\92á\9e\89á\9e¾á\9e\91á\9f\85â\80\8bá\9e¢á\9e¶á\9e\9fá\9e\99á\9e\8aá\9f\92á\9e\8bá\9e¶á\9e\93á\9e¢á\9f\8aá\9e¸á\9e\98á\9f\82á\9e\9bâ\80\8bá\9e\8aá\9f\82á\9e\9bá\9e\94á\9e¶á\9e\93á\9e\95á\9f\92á\9e\8aá\9e\9bá\9f\8bá\9e\87á\9e¼á\9e\93ហើយ។
 
 មុននឹងមាន​អ៊ីមែលផ្សេងមួយទៀត​ត្រូវផ្ញើទៅ​គណនីនេះ អ្នកត្រូវតែ​ធ្វើតាមសេចក្តីណែនាំ​ក្នុងអ៊ីមែល​នោះ ដើម្បីបញ្ជាក់ថា​គណនីបច្ចុប្បន្ន​ពិតជា​របស់អ្នកពិតប្រាកដមែន។',
 'throttled-mailpassword' => 'អ៊ីមែលប្ដូរពាក្យសម្ងាត់ត្រូវបានផ្ញើទៅឱ្យអ្នកតាំងពី{{PLURAL:$1|មួយម៉ោង|$1ម៉ោង}}មុននេះហើយ។
@@ -1236,15 +1232,15 @@ $2
 * ព័ត៌មាន​ផ្ទាល់​ខ្លួន​ ឯកជន​មិន​សមរម្យ​
 *: ''អាសយដ្ឋាននៃ​គេហដ្ឋាន​​ ​លេខ​ទូរស័ព្ទ និងលេខ​សន្តិសុខ​សង្គម​ជាដើម​''",
 'revdelete-legend' => 'ដាក់កំហិតគំហើញ',
-'revdelete-hide-text' => 'á\9e\94á\9e·á\9e\91á\9e\94á\9e¶á\9f\86á\9e\84á\9e\83á\9f\92á\9e\9bá\9e¶á\9e\93á\9f\83កំណែប្រែ',
+'revdelete-hide-text' => 'á\9e\94á\9e·á\9e\91á\9e\94á\9e¶á\9f\86á\9e\84á\9e¢á\9e\8fá\9f\92á\9e\90á\9e\94á\9e\91កំណែប្រែ',
 'revdelete-hide-image' => 'បិទបាំងខ្លឹមសារនៃឯកសារ',
 'revdelete-hide-name' => 'បិទបាំងសកម្មភាពនិងគោលដៅ',
-'revdelete-hide-comment' => 'á\9e\94á\9e·á\9e\91á\9e\94á\9e¶á\9f\86á\9e\84á\9e\80á\9f\86á\9e\8eá\9f\82á\9e\94á\9f\92á\9e\9aá\9f\82á\9e\9cá\9e·á\9e\85á\9e¶á\9e\9a',
-'revdelete-hide-user' => 'á\9e\94á\9e·á\9e\91á\9e\94á\9e¶á\9f\86á\9e\84á\9e¢á\9e\8fá\9f\92á\9e\8fá\9e\93á\9e¶á\9e\98â\80\8bá\9e¬á\9e¢á\9e¶á\9e\9fá\9e\99á\9e\8aá\9f\92á\9e\8bá\9e¶á\9e\93IP របស់អ្នកកែប្រែ',
+'revdelete-hide-comment' => 'á\9e\80á\9f\82á\9e\94á\9f\92á\9e\9aá\9f\82á\9e\85á\9f\86á\9e\8eá\9e¶á\9e\9aá\9e\96á\9e\93á\9f\92á\9e\99á\9e\9bá\9f\8b',
+'revdelete-hide-user' => 'á\9e¢á\9e\8fá\9f\92á\9e\8fá\9e\93á\9e¶á\9e\98â\80\8bá\9e¬á\9e¢á\9e¶á\9e\9fá\9e\99á\9e\8aá\9f\92á\9e\8bá\9e¶á\9e\93IPរបស់អ្នកកែប្រែ',
 'revdelete-hide-restricted' => 'ដាក់កំហិត​ទិន្នន័យ​ពី​អ្នកអភិបាល ក៏​ដូចជា​អ្នក​ដទៃ​ទៀត',
 'revdelete-radio-same' => '(មិនផ្លាស់ប្ដូរ)',
-'revdelete-radio-set' => 'á\9e\94á\9e¶á\9e\91\9e\85á\9e¶á\9e\9f',
-'revdelete-radio-unset' => 'á\9e\91á\9f\81',
+'revdelete-radio-set' => 'á\9e\9bá\9e¶á\9e\80á\9f\8b',
+'revdelete-radio-unset' => 'á\9e\98á\9e¾á\9e\9bá\9e\83á\9e¾á\9e\89',
 'revdelete-suppress' => 'លាក់ទិន្នន័យពីអ្នកថែទាំប្រព័ន្ធ ព្រមទាំងពីសមាជិកដទៃទៀតផងដែរ',
 'revdelete-unsuppress' => 'ដកចេញការដាក់កំហិតលើកំណែដែលបានស្តារឡើងវិញ',
 'revdelete-log' => 'មូលហេតុ៖',
@@ -1399,8 +1395,6 @@ $1",
 'preferences' => 'ចំណង់ចំណូលចិត្ត',
 'mypreferences' => 'ចំណង់ចំណូលចិត្ត​',
 'prefs-edits' => 'ចំនួនកំណែប្រែ៖',
-'prefsnologin' => 'មិនទាន់កត់ឈ្មោះចូលទេ',
-'prefsnologintext' => 'អ្នកចាំបាច់ត្រូវតែ<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} កត់ឈ្មោះចូល]</span> ដើម្បីកំណត់ចំណង់ចំណូលចិត្តរបស់អ្នក។',
 'changepassword' => 'ប្តូរពាក្យសម្ងាត់',
 'prefs-skin' => 'សំបក',
 'skin-preview' => 'មើលជាមុន',
@@ -1667,8 +1661,8 @@ $1",
 'action-block' => 'ហាមឃាត់អ្នកប្រើប្រាស់នេះមិនឱ្យធ្វើការកែប្រែ',
 'action-protect' => 'ប្ដូរកម្រិតការពារសម្រាប់ទំព័រនេះ',
 'action-rollback' => 'ត្រឡប់យ៉ាងរហ័សនូវកំណែប្រែទំព័រវិសេសណាមួយ​ដែលធ្វើឡើងដោយ​អ្នកប្រើប្រាស់ចុងក្រោយគេ។',
-'action-import' => 'á\9e\93á\9e¶á\9f\86á\9e\85á\9e¼á\9e\9bá\9e\91á\9f\86á\9e\96á\9f\90á\9e\9aá\9e\93á\9f\81á\9f\87á\9e\96á\9e¸á\9e\9cá\9e·á\9e\82á\9e¸á\9e\95á\9f\92á\9e\9fá\9f\81á\9e\84á\9e\98á\9e½á\9e\99á\9e\91á\9f\80á\9e\8f',
-'action-importupload' => 'á\9e\93á\9e¶á\9f\86á\9e\85á\9e¼á\9e\9bá\9e\91á\9f\86á\9e\96á\9f\90á\9e\9aá\9e\93á\9f\81á\9f\87á\9e\96á\9e¸á\9e¯á\9e\80á\9e\9fá\9e¶á\9e\9aá\9e\8aá\9f\82á\9e\9bá\9e\94á\9e¶á\9e\93á\9e\95á\9f\92á\9e\91á\9e»á\9e\80á\9e¡á\9e¾á\9e\84',
+'action-import' => 'នាំចូលទំព័រពីវិគីផ្សេងមួយទៀត',
+'action-importupload' => 'នាំចូលទំព័រពីឯកសារដែលបានផ្ទុកឡើង',
 'action-patrol' => 'ចំណាំកំណែប្រែរបស់អ្នកដទៃថាបានល្បាត',
 'action-autopatrol' => 'ផ្ដល់សិទ្ធិឱ្យគេចំណាំកំណែរបស់អ្នកថាបានល្បាត',
 'action-unwatchedpages' => 'មើលបញ្ជីនៃទំព័រមិនតាមដាន',
@@ -1694,6 +1688,7 @@ $1",
 'recentchanges-label-minor' => 'នេះជាការកែប្រែតិចតួចមួយប៉ុណ្ណោះ',
 'recentchanges-label-bot' => 'ការកែប្រែនេះត្រូវបានធ្វើឡើងដោយរូបយន្ត',
 'recentchanges-label-unpatrolled' => 'ការកែប្រែនេះមិនទាន់ត្រូវបានល្បាតទេ',
+'recentchanges-legend-newpage' => '$1 - ទំព័រថ្មី',
 'rcnote' => "ខាងក្រោម​នេះ​ជា​{{PLURAL:$1|១បន្លាស់ប្ដូរ|'''$1'''បន្លាស់ប្ដូរ}}​ចុងក្រោយក្នុងរយៈពេល​{{PLURAL:$2|ថ្ងៃ|'''$2'''ថ្ងៃ}}​ចុងក្រោយគិតត្រឹម$5 $4 ។",
 'rcnotefrom' => "ខាងក្រោមនេះជាបន្លាស់ប្ដូរនានាគិតចាប់តាំងពី '''$2''' (បង្ហាញអតិបរមាចំនួន '''$1''')។",
 'rclistfrom' => 'បង្ហាញបន្លាស់ប្ដូរថ្មីៗចាប់តាំងពី $1',
@@ -2161,6 +2156,7 @@ $1',
 'listusers' => 'បញ្ជីអ្នកប្រើប្រាស់',
 'listusers-editsonly' => 'បង្ហាញតែអ្នកប្រើប្រាស់ដែលបានកែប្រែអត្ថបទប៉ុណ្ណោះ',
 'listusers-creationsort' => 'តម្រៀបតាមលំដាប់កាលបរិច្ឆេទបង្កើត',
+'listusers-desc' => 'តម្រៀបជាលំដាប់ពីលើចុះក្រោម',
 'usereditcount' => '$1 {{PLURAL:$1|កំណែប្រែ|កំណែប្រែ}}',
 'usercreated' => '{{GENDER:$3|បានបង្កើត}}នៅ$1  $2',
 'newpages' => 'ទំព័រថ្មីៗ',
@@ -2590,7 +2586,7 @@ $1',
 'contributions' => 'ការរួមចំណែក​របស់{{GENDER:$1|អ្នកប្រើប្រាស់}}',
 'contributions-title' => 'ការរួមចំណែករបស់អ្នកប្រើប្រាស់ $1',
 'mycontris' => 'ការរួមចំណែក',
-'contribsub2' => 'សម្រាប់ $1 ($2)',
+'contribsub2' => 'សម្រាប់{{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'គ្មានការផ្លាស់ប្តូរត្រូវបានឃើញដូចនឹងលក្ខណៈវិនិច្ឆ័យទាំងនេះ។',
 'uctop' => '(បច្ចុប្បន្ន)',
 'month' => 'ខែ៖',
@@ -3114,7 +3110,7 @@ $1',
 'svg-long-desc' => 'ឯកសារប្រភេទSVG  $1 × $2 ភីកសែល ទំហំឯកសារ៖ $3',
 'svg-long-desc-animated' => 'ឯកសារជីវចល SVG, ជាធម្មតា $1 × $2 ភិចសែល, ទំហំឯកសារ: $3',
 'svg-long-error' => 'ឯកសារ SVG គ្មានសុពលភាព៖ $1',
-'show-big-image' => 'á\9e\9aá\9e¼á\9e\94á\9e\97á\9e¶á\9e\96á\9e\96á\9f\81á\9e\89',
+'show-big-image' => 'á\9e\9aá\9e¼á\9e\94á\9e\97á\9e¶á\9e\96á\9e\8aá\9e¾á\9e\98',
 'show-big-image-preview' => 'ទំហំរបស់ការមើលមុននេះ: $1។',
 'show-big-image-other' => '{{PLURAL:$2|ភាពម៉ត់|ភាពម៉ត់}}ផ្សេងទៀត៖ $1។',
 'show-big-image-size' => '$1 × $2 ភីកសែ',
@@ -3446,7 +3442,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'កែប្រែ​ឯកសារ​នេះដោយប្រើប្រាស់​កម្មវិធី​ខាងក្រៅ',
-'edit-externally-help' => '(សូមមើល[//www.mediawiki.org/wiki/Manual:External_editors ការណែនាំ​អំពី​ការ​ប្រើប្រាស់​]សម្រាប់​​ព័ត៌មាន​បន្ថែម)',
+'edit-externally-help' => '(សូមមើល[https://www.mediawiki.org/wiki/Manual:External_editors ការណែនាំ​អំពី​ការ​ប្រើប្រាស់​]សម្រាប់​​ព័ត៌មាន​បន្ថែម)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ទាំងអស់',
@@ -3639,7 +3635,7 @@ $5
 'version-hook-subscribedby' => 'បានជាវ ជាប្រចាំ ដោយ',
 'version-version' => '(កំណែ $1)',
 'version-license' => 'អាជ្ញាប័ណ្ណ',
-'version-poweredby-credits' => "វិគីនេះឧបត្ថម្ភដោយ '''[//www.mediawiki.org/ មេឌាវិគី]''', រក្សាសិទ្ធ © ២០០១-$1 $2។",
+'version-poweredby-credits' => "វិគីនេះឧបត្ថម្ភដោយ '''[https://www.mediawiki.org/ មេឌាវិគី]''', រក្សាសិទ្ធ © ២០០១-$1 $2។",
 'version-poweredby-others' => 'អ្នកដទៃទៀត',
 'version-software' => 'ផ្នែកទន់​ដែល​បានដំឡើង',
 'version-software-product' => 'ផលិតផល',
@@ -3802,4 +3798,12 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|សតវត្សរ៍|សតវត្សរ៍}}',
 'duration-millennia' => '$1 {{PLURAL:$1|សហសវត្សរ៍|សហសវត្សរ៍}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'ពង្រីកទំព័រគំរូ',
+'expand_templates_input' => 'សរសេរឃ្លា',
+'expand_templates_output' => 'លទ្ធផល',
+'expand_templates_ok' => 'យល់ព្រម',
+'expand_templates_remove_comments' => 'ដកចេញ វិចារនានា',
+'expand_templates_preview' => 'បង្ហាញការមើលជាមុន',
+
 );
index 060371e..c8ff643 100644 (file)
@@ -332,8 +332,6 @@ $messages = array(
 'ok' => 'ಸರಿ',
 'retrievedfrom' => '"$1" ಇಂದ ಪಡೆಯಲ್ಪಟ್ಟಿದೆ',
 'youhavenewmessages' => 'ನಿಮಗೆ $1 ಇವೆ ($2).',
-'newmessageslink' => 'ಹೊಸ ಸಂದೇಶಗಳು',
-'newmessagesdifflink' => 'ಕೊನೆಯ ಬದಲಾವಣೆ',
 'newmessagesdifflinkplural' => 'ಕಡೆಯ {{PLURAL:$1|ಬದಲಾವಣೆ|ಬದಲಾವಣೆಗಳು}}',
 'youhavenewmessagesmulti' => '$1 ಅಲ್ಲಿ ನಿಮಗೆ ಹೊಸ ಸಂದೇಶಗಳಿವೆ',
 'editsection' => 'ಬದಲಾಯಿಸಿ',
@@ -918,8 +916,6 @@ $2',
 'preferences' => 'ಪ್ರಾಶಸ್ತ್ಯಗಳು',
 'mypreferences' => 'ಪ್ರಾಶಸ್ತ್ಯಗಳು',
 'prefs-edits' => 'ಸಂಪಾದನೆಗಳ ಸಂಖ್ಯೆ:',
-'prefsnologin' => 'ಲಾಗಿನ್ ಆಗಿಲ್ಲ',
-'prefsnologintext' => 'ಬಳಕೆದಾರ ಪ್ರಾಶಸ್ತ್ಯಗಳನ್ನು ಬದಲಾಯಿಸಲು ನೀವು <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ಲಾಗ್ ಇನ್]</span> ಆಗಿರಬೇಕು.',
 'changepassword' => 'ಪ್ರವೇಶ ಪದ ಬದಲಾಯಿಸಿ',
 'prefs-skin' => 'ಚರ್ಮ',
 'skin-preview' => 'ಮುನ್ನೋಟ',
@@ -2042,7 +2038,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ಬಾಹ್ಯ ತಂತ್ರಾಂಶವನ್ನು ಉಪಯೋಗಿಸಿ ಇದನ್ನು ಸಂಪಾದಿಸಿ',
-'edit-externally-help' => '(ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗೆ [//www.mediawiki.org/wiki/Manual:External_editors ಸ್ಥಾಪನೆಯ ನಿರ್ದೇಶಗಳನ್ನು] ನೋಡಿ)',
+'edit-externally-help' => '(ಹೆಚ್ಚಿನ ಮಾಹಿತಿಗೆ [https://www.mediawiki.org/wiki/Manual:External_editors ಸ್ಥಾಪನೆಯ ನಿರ್ದೇಶಗಳನ್ನು] ನೋಡಿ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ಎಲ್ಲಾ',
@@ -2210,4 +2206,7 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|ಶತಮಾನ|ಶತಮಾನಗಳು}}',
 'duration-millennia' => '$1 {{PLURAL:$1|ಸಹಸ್ರಮಾನ|ಸಹಸ್ರಮಾನಗಳು}}',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'ಮುನ್ನೋಟ',
+
 );
index 7906d14..1ddf8f3 100644 (file)
@@ -41,7 +41,7 @@
 
 $namespaceNames = array(
        NS_MEDIA            => '미디어',
-       NS_SPECIAL          => '특수기능',
+       NS_SPECIAL          => '특수',
        NS_TALK             => '토론',
        NS_USER             => '사용자',
        NS_USER_TALK        => '사용자토론',
@@ -59,7 +59,8 @@ $namespaceNames = array(
 );
 
 $namespaceAliases = array(
-       '특'  => NS_SPECIAL,
+       '특' => NS_SPECIAL,
+       '특수기능' => NS_SPECIAL,
        'MediaWiki토론' => NS_MEDIAWIKI_TALK,
        '그림' => NS_FILE,
        '파일토론' => NS_FILE_TALK,
@@ -68,12 +69,12 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( '활동적인사용자' ),
        'Allmessages'               => array( '모든메시지' ),
+       'AllMyUploads'              => array( '모든내올린파일', '모든내파일' ),
        'Allpages'                  => array( '모든문서' ),
        'Ancientpages'              => array( '오래된문서' ),
        'Badtitle'                  => array( '잘못된제목', '인식불가제목', '잘못된이름', '인식불가이름' ),
        'Blankpage'                 => array( '빈문서' ),
        'Block'                     => array( '차단', 'IP차단', '사용자차단' ),
-       'Blockme'                   => array( '자기차단', '자가차단' ),
        'Booksources'               => array( '책찾기' ),
        'BrokenRedirects'           => array( '끊긴넘겨주기' ),
        'Categories'                => array( '분류' ),
@@ -85,19 +86,19 @@ $specialPageAliases = array(
        'CreateAccount'             => array( '계정만들기', '가입' ),
        'Deadendpages'              => array( '막다른문서' ),
        'DeletedContributions'      => array( '삭제된기여' ),
-       'Disambiguations'           => array( '동음이의', '동음이의문서' ),
        'DoubleRedirects'           => array( '이중넘겨주기' ),
        'EditWatchlist'             => array( '주시문서목록편집' ),
        'Emailuser'                 => array( '이메일보내기' ),
+       'ExpandTemplates'           => array( '틀전개' ),
        'Export'                    => array( '내보내기' ),
        'Fewestrevisions'           => array( '역사짧은문서' ),
-       'FileDuplicateSearch'       => array( '중복파일찾기' ),
+       'FileDuplicateSearch'       => array( '중복파일검색', '중복파일찾기' ),
        'Filepath'                  => array( '파일경로', '그림경로' ),
        'Import'                    => array( '가져오기' ),
        'Invalidateemail'           => array( '이메일인증취소', '이메일인증해제' ),
        'JavaScriptTest'            => array( '자바스크립트시험', '자바스크립트테스트' ),
-       'BlockList'                 => array( 'ì°¨ë\8b¨ë\90\9cì\82¬ì\9a©ì\9e\90', 'ì°¨ë\8b¨ëª©ë¡\9d', 'IPì°¨ë\8b¨ëª©ë¡\9d' ),
-       'LinkSearch'                => array( '링크찾기', '링크검색' ),
+       'BlockList'                 => array( 'ì°¨ë\8b¨ëª©ë¡\9d', 'IPì°¨ë\8b¨ëª©ë¡\9d', 'ì°¨ë\8b¨ë\90\9cì\82¬ì\9a©ì\9e\90' ),
+       'LinkSearch'                => array( '링크검색', '링크찾기' ),
        'Listadmins'                => array( '관리자', '관리자목록' ),
        'Listbots'                  => array( '봇', '봇목록' ),
        'Listfiles'                 => array( '파일', '그림', '파일목록', '그림목록' ),
@@ -109,7 +110,7 @@ $specialPageAliases = array(
        'Lonelypages'               => array( '외톨이문서', '홀로된문서' ),
        'Longpages'                 => array( '긴문서' ),
        'MergeHistory'              => array( '역사합치기' ),
-       'MIMEsearch'                => array( 'MIME찾기', 'MIME검색' ),
+       'MIMEsearch'                => array( 'MIME검색', 'MIME찾기' ),
        'Mostcategories'            => array( '많이분류된문서' ),
        'Mostimages'                => array( '많이쓰는파일', '많이쓰는그림' ),
        'Mostinterwikis'            => array( '인터위키많은문서' ),
@@ -133,12 +134,14 @@ $specialPageAliases = array(
        'Protectedpages'            => array( '보호된문서' ),
        'Protectedtitles'           => array( '만들기보호된문서', '생성보호된문서' ),
        'Randompage'                => array( '임의문서' ),
+       'RandomInCategory'          => array( '분류에있는임의문서' ),
        'Randomredirect'            => array( '임의넘겨주기' ),
        'Recentchanges'             => array( '최근바뀜' ),
        'Recentchangeslinked'       => array( '링크최근바뀜' ),
        'Redirect'                  => array( '넘겨주기' ),
+       'ResetTokens'               => array( '토큰재설정' ),
        'Revisiondelete'            => array( '특정판삭제' ),
-       'Search'                    => array( '찾기', '검색' ),
+       'Search'                    => array( '검색', '찾기' ),
        'Shortpages'                => array( '짧은문서' ),
        'Specialpages'              => array( '특수문서', '특수기능' ),
        'Statistics'                => array( '통계' ),
@@ -155,7 +158,7 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( '안쓰는틀', '쓰이지않는틀' ),
        'Unwatchedpages'            => array( '주시안되는문서' ),
        'Upload'                    => array( '올리기', '파일올리기', '그림올리기', '업로드' ),
-       'UploadStash'               => array( '올린비공개파일' ),
+       'UploadStash'               => array( '올린비공개파일', '비공개로올린파일' ),
        'Userlogin'                 => array( '로그인' ),
        'Userlogout'                => array( '로그아웃' ),
        'Userrights'                => array( '권한조정', '관리자하기', '봇하기' ),
@@ -239,6 +242,7 @@ $magicWords = array(
        'img_center'                => array( '1', '가운데', 'center', 'centre' ),
        'img_framed'                => array( '1', '프레임', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', '프레임없음', 'frameless' ),
+       'img_lang'                  => array( '1', '언어=$1', 'lang=$1' ),
        'img_page'                  => array( '1', '문서=$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', '위오른쪽', '위오른쪽=$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', '테두리', 'border' ),
@@ -281,6 +285,7 @@ $magicWords = array(
        'revisionyear'              => array( '1', '판년', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', '판타임스탬프', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', '판사용자', 'REVISIONUSER' ),
+       'revisionsize'              => array( '1', '판크기', 'REVISIONSIZE' ),
        'plural'                    => array( '0', '복수:', '복수형:', 'PLURAL:' ),
        'fullurl'                   => array( '0', '전체주소:', 'FULLURL:' ),
        'fullurle'                  => array( '0', '전체주소E:', 'FULLURLE:' ),
@@ -505,7 +510,7 @@ $messages = array(
 
 # Cologne Blue skin
 'qbfind' => '찾기',
-'qbbrowse' => '탐색',
+'qbbrowse' => '찾아보기',
 'qbedit' => '편집',
 'qbpageoptions' => '문서 기능',
 'qbmyoptions' => '내 사용자 문서',
@@ -520,7 +525,7 @@ $messages = array(
 'vector-action-protect' => '보호',
 'vector-action-undelete' => '되살리기',
 'vector-action-unprotect' => '보호 설정 바꾸기',
-'vector-simplesearch-preference' => '단순한 찾기 막대 사용하기 (벡터 스킨 전용)',
+'vector-simplesearch-preference' => '단순한 검색 막대 사용하기 (벡터 스킨 전용)',
 'vector-view-create' => '만들기',
 'vector-view-edit' => '편집',
 'vector-view-history' => '역사',
@@ -535,8 +540,8 @@ $messages = array(
 'returnto' => '$1 문서로 돌아갑니다.',
 'tagline' => '{{SITENAME}}',
 'help' => '도움말',
-'search' => '찾기',
-'searchbutton' => '찾기',
+'search' => '검색',
+'searchbutton' => '검색',
 'go' => '보기',
 'searcharticle' => '보기',
 'history' => '문서 역사',
@@ -586,7 +591,7 @@ $messages = array(
 'protectedpage' => '보호된 문서',
 'jumpto' => '이동:',
 'jumptonavigation' => '둘러보기',
-'jumptosearch' => '찾기',
+'jumptosearch' => '검색',
 'view-pool-error' => '서버가 과부하에 걸렸습니다.
 너무 많은 사용자가 이 문서를 보려고 하고 있습니다.
 이 문서를 다시 열기 전에 잠시만 기다려주세요.
@@ -625,14 +630,12 @@ $1',
 
 'ok' => '확인',
 'retrievedfrom' => '원본 주소 "$1"',
-'youhavenewmessages' => '다른 사용자가 $1에 글을 남겼습니다. ($2)',
-'newmessageslink' => '사용자 토론',
-'newmessagesdifflink' => '마지막으로 바뀐 내용',
-'youhavenewmessagesfromusers' => '{{PLURAL:$3|다른 사용자가|사용자 $3명이}} $1에 글을 남겼습니다. ($2)',
-'youhavenewmessagesmanyusers' => '여러 사용자가 $1에 글을 남겼습니다. ($2)',
-'newmessageslinkplural' => '{{PLURAL:$1|사용자 토론}}',
+'youhavenewmessages' => '다른 사용자가 남긴 $1가 있습니다. ($2)',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|다른 사용자가|사용자 $3명이}} 남긴 $1가 있습니다. ($2)',
+'youhavenewmessagesmanyusers' => '여러 사용자가 남긴 $1가 있습니다. ($2)',
+'newmessageslinkplural' => '{{PLURAL:$1|새 메시지}}',
 'newmessagesdifflinkplural' => '마지막으로 {{PLURAL:$1|바뀐 내용}}',
-'youhavenewmessagesmulti' => '다른 사용자가 $1에 글을 남겼습니다',
+'youhavenewmessagesmulti' => '다른 사용자가 $1에 남긴 새 메시지가 있습니다',
 'editsection' => '편집',
 'editold' => '편집',
 'viewsourceold' => '원본 보기',
@@ -697,9 +700,10 @@ URL을 잘못 입력하였거나, 잘못된 링크를 따라갔을 수 있습니
 관리자가 데이터베이스를 잠글 때 남긴 메시지는 다음과 같습니다: $1',
 'missing-article' => '데이터베이스에서 "$1" 문서의 $2 텍스트를 찾지 못했습니다.
 
\82­ì \9cë\90\9c ë¬¸ì\84\9cì\9d\98 ì\97­ì\82¬/ë¹\84êµ\90 ë¬¸ì\84\9c를 보려고 시도할 때 이러한 문제가 발생할 수 있습니다.
\82­ì \9cë\90\9c ë¬¸ì\84\9cì\9d\98 ì\98¤ë\9e\98ë\90\9c ì°¨ì\9d´ë\82\98 ì\97­ì\82¬ ë§\81í\81¬를 보려고 시도할 때 이러한 문제가 발생할 수 있습니다.
 
-또는, 프로그램 버그가 발생했을 수도 있습니다. [[Special:ListUsers/sysop|관리자]]에게 오류가 나는 URL을 알려주세요.',
+그렇지 않다면, 소프트웨어에 버그가 발생했을 수도 있습니다.
+[[Special:ListUsers/sysop|관리자]]에게 URL을 참조하여 알려주세요.',
 'missingarticle-rev' => '(판번호: $1)',
 'missingarticle-diff' => '(차이: $1, $2)',
 'readonly_lag' => '슬레이브 데이터베이스가 마스터 서버의 자료를 새로 고치는 중입니다. 데이터베이스가 자동으로 잠겨 있습니다.',
@@ -763,7 +767,8 @@ $2',
 'invalidtitle-knownnamespace' => '제목 오류: "$2" 이름공간과 "$3" 텍스트',
 'invalidtitle-unknownnamespace' => '제목 오류: 알 수 없는 $1 이름공간 번호와, "$2" 텍스트',
 'exception-nologin' => '로그인하지 않음',
-'exception-nologin-text' => '이 문서나 행동은 이 위키에 로그인을 해야 합니다.',
+'exception-nologin-text' => '이 행동을 하거나 이 문서에 접근하려면 [[Special:Userlogin|로그인]]하십시오.',
+'exception-nologin-text-manual' => '이 문서에 접근하거나 이 행동을 하려면 $1하십시오.',
 
 # Virus scanner
 'virus-badscanner' => "잘못된 설정: 알 수 없는 바이러스 검사기: '''$1'''",
@@ -810,7 +815,7 @@ $2',
 'gotaccount' => '계정이 이미 있다면, $1.',
 'gotaccountlink' => '로그인하세요',
 'userlogin-resetlink' => '사용자 이름이나 비밀번호를 잊으셨나요?',
-'userlogin-resetpassword-link' => 'ë\82´ ë¹\84ë°\80ë²\88í\98¸ ì\9e¬ì\84¤ì \95',
+'userlogin-resetpassword-link' => 'ë¹\84ë°\80ë²\88í\98¸ë¥¼ ì\9e\8aì\9c¼ì\85¨ë\82\98ì\9a\94?',
 'helplogin-url' => 'Help:로그인',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|로그인에 관한 도움말]]',
 'userlogin-loggedin' => '이미 $1로 로그인되어 있습니다. 아래의 양식으로 다른 계정으로 로그인하세요.',
@@ -866,7 +871,7 @@ $2',
 'passwordtooshort' => '비밀번호는 {{PLURAL:$1|$1 글자}} 이상이어야 합니다.',
 'password-name-match' => '비밀번호는 사용자 이름과 반드시 달라야 합니다.',
 'password-login-forbidden' => '이 사용자 이름과 비밀번호는 사용할 수 없습니다.',
-'mailmypassword' => '새 비밀번호를 이메일로 보내기',
+'mailmypassword' => '비밀번호 초기화',
 'passwordremindertitle' => '{{SITENAME}}의 새 임시 비밀번호',
 'passwordremindertext' => '$1 IP 주소에서 누군가가 아마 자신이 {{SITENAME}} ($4)의 새 비밀번호를 요청했습니다.
 "$2" 사용자의 임시 비밀번호는 "$3"로 설정되었습니다. 이것이 자신이 의도한 바라면
@@ -881,13 +886,13 @@ $2',
 비밀번호를 받고 다시 로그인해 주세요.',
 'blocked-mailpassword' => '당신의 IP 주소는 편집을 할 수 없게 차단되어 있어서 악용하지 못하도록 비밀번호 되살리기 기능 사용이 금지됩니다.',
 'eauthentsent' => '입력한 이메일로 확인 이메일을 보냈습니다.
-ê²\8cì \95ì\97\90ì\84\9c ë\8b¤ë¥¸ ì\9d´ë©\94ì\9d¼ë¡\9c ë³´ë\82´ê¸° ì \84ì\97\90 ì\9d´ë©\94ì\9d¼ ë\82´ì\9a©ì\9d\98 ì§\80ì\8b\9cë\8c\80ë¡\9c ê³\84ì \95 í\99\95ì\9d¸ ì \88차를 ì\8b¤í\96\89í\95´ ì£¼ì\8b­ì\8b\9cì\98¤.',
+ë\8b¤ë¥¸ ëª¨ë\93  í\98\95í\83\9cì\9d\98 ì\9d´ë©\94ì\9d¼ì\9d\84 ë\8b¹ì\8b ì\9d\98 ê³\84ì \95ì\9c¼ë¡\9c ë³´ë\82´ê¸° ì \84ì\97\90, ê³\84ì \95ì\9d´ ì \95ë§\90 ë\8b¹ì\8b ì\9d\98 ê²\83ì\9d¸ì§\80 í\99\95ì\9d¸í\95\98기 ì\9c\84í\95´ ì\9d´ë©\94ì\9d¼ ë\82´ì\9a©ì\9d\98 ì§\80ì\8b\9cë\8c\80ë¡\9c ê³\84ì \95 í\99\95ì\9d¸ ì \88차를 ì\8b¤í\96\89í\95´ ì£¼ì\85\94ì\95¼ í\95©ë\8b\88ë\8b¤.',
 'throttled-mailpassword' => '비밀번호 재설정 이메일을 이미 최근 {{PLURAL:$1|$1시간}} 안에 보냈습니다.
 악용을 방지하기 위해 비밀번호 재설정 메일은 {{PLURAL:$1|$1시간}}마다 오직 하나씩만 보낼 수 있습니다.',
 'mailerror' => '메일 보내기 오류: $1',
 'acct_creation_throttle_hit' => '당신의 IP 주소를 이용한 방문자가 이전에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.
 따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.',
-'emailauthenticated' => '이메일 주소는 $2 $3에 인증되었습니다.',
+'emailauthenticated' => '이메일 주소는 $2 에 $3 에서 인증되었습니다.',
 'emailnotauthenticated' => '이메일 주소를 인증하지 않았습니다.
 이메일 확인 절차를 거치지 않으면 다음 이메일 기능을 사용할 수 없습니다.',
 'noemailprefs' => '이 기능을 사용하기 위해서는 사용자 환경 설정에서 이메일 주소를 설정해야 합니다.',
@@ -940,7 +945,7 @@ $1 기다렸다가 다시 시도하세요.',
 # Special:PasswordReset
 'passwordreset' => '비밀번호 재설정',
 'passwordreset-text-one' => '비밀번호를 재설정하려면 이 양식을 작성해주세요.',
-'passwordreset-text-many' => '{{PLURAL:$1|비밀번호를 재설정하려면 필드 중 하나를 채우세요.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|이메일로 임시 비밀번호를 발급받으려면 필드 중 하나를 채우세요.}}',
 'passwordreset-legend' => '비밀번호 재설정',
 'passwordreset-disabled' => '이 위키에서는 비밀번호를 재설정할 수 없습니다.',
 'passwordreset-emaildisabled' => '이 위키에서 이메일 기능이 비활성화되어 있습니다.',
@@ -1079,20 +1084,20 @@ $1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대
 'accmailtitle' => '비밀번호를 보냈습니다',
 'accmailtext' => '[[User talk:$1|$1]] 사용자의 비밀번호가 임의로 만들어져 $2(으)로 보냈습니다. 로그인하고 나서 [[Special:ChangePassword|비밀번호를 바꿀]] 수 있습니다.',
 'newarticle' => '(새 문서)',
-'newarticletext' => "ì\9d´ ë¬¸ì\84\9cë\8a\94 ì\95\84ì§\81 ë§\8cë\93¤ì\96´ì§\80ì§\80 ì\95\8aì\95\98습니다.
-새 문서를 만들려면 아래의 상자에 문서 내용을 입력하면 됩니다(자세한 내용은 [[{{MediaWiki:Helppage}}|도움말]]을 읽어 주세요).
-ë§\8cì\95½ ì\9e\98못 ì°¾ì\95\84ì\98¨ ë¬¸ì\84\9cë\9d¼ë©´ ì\9b¹ 브라우저의 '''뒤로''' 버튼을 눌러 주세요.",
+'newarticletext' => "ì\95\84ì§\81 ì\97\86ë\8a\94 ë¬¸ì\84\9cì\9d\98 ë§\81í\81¬ë¥¼ ë\94°ë\9d¼ì\99\94습니다.
+새 문서를 만들려면 아래 상자에 내용을 입력하면 됩니다. (자세한 내용은 [[{{MediaWiki:Helppage}}|도움말 문서]]를 참고하세요)
+ë§\8cì\95½ ì\9e\98못 ì°¾ì\95\84ì\99\94ë\8b¤ë©´, 브라우저의 '''뒤로''' 버튼을 눌러 주세요.",
 'anontalkpagetext' => '----
 여기는 계정을 만들지 않았거나 사용하고 있지 않은 익명 사용자를 위한 토론 문서입니다.
 익명 사용자를 구별하기 위해서는 숫자로 된 IP 주소를 사용해야만 합니다.
 IP 주소는 여러 사용자가 공유할 수 있습니다.
 자신과 관계없는 의견이 자신에게 남겨져 있어 불쾌하다고 생각하는 익명 사용자는 [[Special:UserLogin/signup|계정을 만들고]] [[Special:UserLogin|로그인해서]] 나중에 다른 익명 사용자에게 줄 혼란을 줄일 수 있습니다.',
 'noarticletext' => '이 문서가 현재 존재하지 않습니다.
-이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|거나]],
+이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|검색하거나]],
 이 문서에 관련된 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 기록]을 확인하거나,
 문서를 직접 [{{fullurl:{{FULLPAGENAME}}|action=edit}} 편집]</span>할 수 있습니다.',
 'noarticletext-nopermission' => '이 문서가 현재 존재하지 않습니다.
-이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|거나]], 이 문서에 관련된 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 기록]을 확인할 수 있습니다.</span> 그러나 이 문서를 만들 수 있는 권한은 없습니다.',
+이 문서와 제목이 비슷한 문서가 있는지 [[Special:Search/{{PAGENAME}}|검색하거나]], 이 문서에 관련된 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 기록]을 확인할 수 있습니다.</span> 그러나 이 문서를 만들 수 있는 권한은 없습니다.',
 'missing-revision' => '"{{PAGENAME}}"이라는 문서의 #$1판이 존재하지 않습니다.
 
 이 문제는 주로 삭제된 문서를 가리키는 오래된 문서 역사 링크로 인해 발생합니다.
@@ -1285,7 +1290,7 @@ $2개 보다 적게 {{PLURAL:$2|써야}} 하지만 {{PLURAL:$1|지금은 $1개
 'history-feed-item-nocomment' => '$2에 대한 $1의 편집',
 'history-feed-empty' => '요청한 문서가 존재하지 않습니다.
 해당 문서가 삭제되었거나, 문서 이름이 바뀌었을 수 있습니다.
-[[Special:Search|찾기]]를 사용해 관련 문서를 찾아보세요.',
+[[Special:Search|ì\9c\84í\82¤ì\9d\98 ê²\80ì\83\89]]ì\9d\84 사용해 관련 문서를 찾아보세요.',
 
 # Revision deletion
 'rev-deleted-comment' => '(편집 요약 삭제됨)',
@@ -1339,15 +1344,15 @@ $2개 보다 적게 {{PLURAL:$2|써야}} 하지만 {{PLURAL:$1|지금은 $1개
 * 부적절한 개인 정보
 *: 집 주소, 전화번호, 주민등록번호 등",
 'revdelete-legend' => '보이기 제한을 설정',
-'revdelete-hide-text' => '판의 내용을 숨기기',
+'revdelete-hide-text' => '판 내용',
 'revdelete-hide-image' => '파일을 숨기기',
 'revdelete-hide-name' => '기록 내용과 대상을 숨기기',
-'revdelete-hide-comment' => '편집 요약을 숨기기',
-'revdelete-hide-user' => '편집자의 사용자 이름/IP를 숨기기',
+'revdelete-hide-comment' => '편집 요약',
+'revdelete-hide-user' => '편집자의 사용자 이름/IP 주소',
 'revdelete-hide-restricted' => '관리자도 보지 못하게 숨기기',
 'revdelete-radio-same' => '(바꾸지 않음)',
-'revdelete-radio-set' => 'ì\98\88',
-'revdelete-radio-unset' => '아니오',
+'revdelete-radio-set' => 'ì\88¨ê²¨ì§\90',
+'revdelete-radio-unset' => '보여짐',
 'revdelete-suppress' => '문서 내용을 관리자에게도 보이지 않게 숨기기',
 'revdelete-unsuppress' => '되살린 판에 대한 제한을 해제',
 'revdelete-log' => '이유:',
@@ -1438,11 +1443,11 @@ $1",
 자세한 내용은 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 삭제 기록]에서 확인할 수 있습니다.',
 
 # Search results
-'searchresults' => '찾기 결과',
-'searchresults-title' => '"$1"에 대한 찾기 결과',
-'searchresulttext' => '{{SITENAME}}의 찾기 기능에 대한 자세한 정보는 [[{{MediaWiki:Helppage}}|{{int:help}}]] 문서를 참고해주세요.',
-'searchsubtitle' => '\'\'\'[[:$1]]\'\'\' 문서를 고 있습니다. ([[Special:Prefixindex/$1|이름이 "$1" 접두어로 시작하는 문서 목록]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|"$1" 문서를 가리키는 문서 목록]])',
-'searchsubtitleinvalid' => "찾은 단어 '''$1'''",
+'searchresults' => '검색 결과',
+'searchresults-title' => '"$1"에 대한 검색 결과',
+'searchresulttext' => '{{SITENAME}} 검색에 대한 자세한 정보는 [[{{MediaWiki:Helppage}}|{{int:help}}]] 문서를 참고하세요.',
+'searchsubtitle' => '\'\'\'[[:$1]]\'\'\' 문서를 검색하고 있습니다. ([[Special:Prefixindex/$1|이름이 "$1" 접두어로 시작하는 문서 목록]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|"$1" 문서를 가리키는 문서 목록]])',
+'searchsubtitleinvalid' => "'''$1''' 검색어로 검색했습니다",
 'toomanymatches' => '일치하는 결과가 너무 많습니다. 다른 검색어를 입력해주세요.',
 'titlematches' => '문서 제목 일치',
 'notitlematches' => '해당하는 제목 없음',
@@ -1454,20 +1459,20 @@ $1",
 'nextn-title' => '다음 {{PLURAL:$1|결과}} $1개',
 'shown-title' => '쪽마다 {{PLURAL:$1|결과}} $1개씩 보기',
 'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3) 보기',
-'searchmenu-legend' => '찾기 설정',
+'searchmenu-legend' => '검색 설정',
 'searchmenu-exists' => "'''이 위키에 \"[[:\$1]]\"의 이름을 가진 문서가 있습니다.'''",
 'searchmenu-new' => "'''이 위키에 \"[[:\$1]]\" 문서를 만드세요!'''",
-'searchmenu-prefix' => '[[Special:PrefixIndex/$1|이 접두어로 시작하는 문서 찾기]]',
+'searchmenu-prefix' => '[[Special:PrefixIndex/$1|이 접두어로 시작하는 문서 찾아보기]]',
 'searchprofile-articles' => '본문',
 'searchprofile-project' => '도움말 및 프로젝트 문서',
 'searchprofile-images' => '멀티미디어',
-'searchprofile-everything' => '모든 문서 찾기',
+'searchprofile-everything' => '모든 문서',
 'searchprofile-advanced' => '고급',
-'searchprofile-articles-tooltip' => '$1에서 찾기',
-'searchprofile-project-tooltip' => '$1에서 찾기',
-'searchprofile-images-tooltip' => '파일 찾기',
-'searchprofile-everything-tooltip' => '토론 문서를 포함한 모든 문서 찾기',
-'searchprofile-advanced-tooltip' => '다음 설정한 이름공간에서 찾기',
+'searchprofile-articles-tooltip' => '$1에서 검색',
+'searchprofile-project-tooltip' => '$1에서 검색',
+'searchprofile-images-tooltip' => '파일 검색',
+'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-result-score' => '유사도: $1%',
@@ -1478,35 +1483,35 @@ $1",
 'search-interwiki-default' => '$1 결과:',
 'search-interwiki-more' => '(더 보기)',
 'search-relatedarticle' => '관련',
-'mwsuggest-disable' => '찾기 제안 비활성화',
-'searcheverything-enable' => '모든 이름공간에서 찾기',
+'mwsuggest-disable' => '검색 제안 비활성화',
+'searcheverything-enable' => '모든 이름공간에서 검색',
 'searchrelated' => '관련',
 'searchall' => '모두',
 'showingresults' => "'''$2'''번 부터의 {{PLURAL:$1|결과 '''1'''개|결과 '''$1'''개}}입니다.",
 'showingresultsnum' => "'''$2'''번 부터의 {{PLURAL:$3|결과 '''1'''개|결과 '''$3'''개}} 입니다.",
 'showingresultsheader' => "'''$4''' 검색어에 대하여 {{PLURAL:$5|결과 '''$3'''개 중 '''$1'''개|결과 '''$3'''개 중 '''$1 - $2'''번째}}를 보여 주고 있습니다",
-'nonefound' => "'''참고''': 몇개의 이름공간만 기본 찾을 범위입니다. 토론이나 틀 등의 모든 자료를 찾하기 위해서는 접두어로 '''all:''' 어떤 이름공간을 위해서는 접두어로 그 이름공간을 쓸 수 있습니다.",
-'search-nonefound' => '찾기 결과가 없습니다.',
-'powersearch' => '고급 찾기',
-'powersearch-legend' => '고급 찾기',
-'powersearch-ns' => '다음 이름공간에서 찾기:',
+'nonefound' => "'''참고''': 일부 이름공간만 기본으로 검색합니다.
+토론 문서나 틀 등의 모든 내용을 검색하려면 접두어로 '''all:'''를 시도하거나, 원하는 이름공간을 접두어로 사용하세요.",
+'search-nonefound' => '검색어와 일치하는 결과가 없습니다.',
+'powersearch' => '고급 검색',
+'powersearch-legend' => '고급 검색',
+'powersearch-ns' => '다음 이름공간에서 검색:',
 'powersearch-redir' => '넘겨주기 목록',
-'powersearch-field' => '찾기',
+'powersearch-field' => '검색',
 'powersearch-togglelabel' => '확인:',
 'powersearch-toggleall' => '모두',
 'powersearch-togglenone' => '모두 제외',
-'search-external' => '바깥 찾기',
-'searchdisabled' => '{{SITENAME}} 찾기 기능이 비활성화되어 있습니다.
¸°ë\8a¥ì\9d´ ì\9e\91ë\8f\99í\95\98ì§\80 ì\95\8aë\8a\94 ë\8f\99ì\95\88ì\97\90ë\8a\94 êµ¬ê¸\80(Google)ì\9d\84 ì\9d´ì\9a©í\95´ ì°¾ì\9d\84 수 있습니다.
-ê²\80ì\83\89 ì\97\94ì§\84ì\9d\98 ë\82´ì\9a©ì\9d\80 ìµ\9cì\8b ì\9d´ ì\95\84ë\8b\90 ì\88\98 ì\9e\88ë\8b¤ë\8a\94 ì \90ì\9d\84 ì£¼ì\9d\98í\95´ì£¼세요.',
-'search-error' => '는 동안 오류가 발생했습니다: $1',
+'search-external' => '바깥 검색',
+'searchdisabled' => '{{SITENAME}} 검색이 비활성화되어 있습니다.
²\80ì\83\89ì\9d´ ì\9e\91ë\8f\99í\95\98ì§\80 ì\95\8aë\8a\94 ë\8f\99ì\95\88ì\97\90ë\8a\94 Google(구ê¸\80\9d\84 í\86µí\95´ ê²\80ì\83\89í\95  수 있습니다.
+ê²\80ì\83\89 ì\97\94ì§\84ì\9d\98 ë\82´ì\9a©ì\9d\80 ìµ\9cì\8b ì\9d´ ì\95\84ë\8b\90 ì\88\98 ì\9e\88ë\8b¤ë\8a\94 ì \90ì\9d\84 ì°¸ê³ í\95\98세요.',
+'search-error' => '검색하는 동안 오류가 발생했습니다: $1',
 
 # Preferences page
 'preferences' => '사용자 환경 설정',
 'mypreferences' => '환경 설정',
 'prefs-edits' => '편집 횟수:',
-'prefsnologin' => '로그인하지 않음',
-'prefsnologintext' => '사용자 환경 설정을 바꾸려면 먼저 <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 로그인]</span>해야 합니다.',
+'prefsnologintext2' => '사용자 환경 설정을 설정하려면 $1하십시오.',
 'changepassword' => '비밀번호 바꾸기',
 'prefs-skin' => '스킨',
 'skin-preview' => '미리 보기',
@@ -1535,7 +1540,7 @@ $1",
 'prefs-editing' => '편집 상자',
 'rows' => '줄 수:',
 'columns' => '열 수:',
-'searchresultshead' => '찾기',
+'searchresultshead' => '검색',
 'resultsperpage' => '쪽마다 보이는 결과 수:',
 'stub-threshold' => '링크를 <a href="#" class="stub">토막글</a> 형식으로 보여줄 문서 크기 (바이트 수):',
 'stub-threshold-disabled' => '비활성화됨',
@@ -1565,9 +1570,9 @@ $1",
 'timezoneregion-indian' => '인도양',
 'timezoneregion-pacific' => '태평양',
 'allowemail' => '다른 사용자가 보낸 이메일을 받음',
-'prefs-searchoptions' => '찾기',
+'prefs-searchoptions' => '검색',
 'prefs-namespaces' => '이름공간',
-'defaultns' => '다음 이름공간에서 찾기:',
+'defaultns' => '다음 이름공간에서 검색:',
 'default' => '기본값',
 'prefs-files' => '파일',
 'prefs-custom-css' => '사용자 CSS',
@@ -1659,7 +1664,7 @@ HTML 태그를 확인하세요.',
 'group-bot' => '봇',
 'group-sysop' => '관리자',
 'group-bureaucrat' => '사무관',
-'group-suppress' => '오버사이트',
+'group-suppress' => '기록보호자',
 'group-all' => '(모두)',
 
 'group-user-member' => '{{GENDER:$1|사용자}}',
@@ -1667,14 +1672,14 @@ HTML 태그를 확인하세요.',
 'group-bot-member' => '{{GENDER:$1|봇}}',
 'group-sysop-member' => '{{GENDER:$1|관리자}}',
 'group-bureaucrat-member' => '{{GENDER:$1|사무관}}',
-'group-suppress-member' => '{{GENDER:$1|오버사이트}}',
+'group-suppress-member' => '{{GENDER:$1|기록보호자}}',
 
 'grouppage-user' => '{{ns:project}}:일반 사용자',
 'grouppage-autoconfirmed' => '{{ns:project}}:자동 인증된 사용자',
 'grouppage-bot' => '{{ns:project}}:봇',
 'grouppage-sysop' => '{{ns:project}}:관리자',
 'grouppage-bureaucrat' => '{{ns:project}}:사무관',
-'grouppage-suppress' => '{{ns:project}}:오버사이트',
+'grouppage-suppress' => '{{ns:project}}:기록보호자',
 
 # Rights
 'right-read' => '문서 읽기',
@@ -1705,7 +1710,7 @@ HTML 태그를 확인하세요.',
 'right-deleterevision' => '문서의 특정 판을 삭제하고 되살리기',
 'right-deletedhistory' => '삭제된 문서의 내용을 제외한 역사를 보기',
 'right-deletedtext' => '삭제된 문서의 내용과 편집상의 차이를 보기',
-'right-browsearchive' => '삭제된 문서 찾기',
+'right-browsearchive' => '삭제된 문서 검색',
 'right-undelete' => '삭제된 문서 되살리기',
 'right-suppressrevision' => '관리자도 보지 못하도록 숨겨진 판을 검토하고 되살리기',
 'right-suppressionlog' => '숨겨진 기록을 보기',
@@ -1739,7 +1744,7 @@ HTML 태그를 확인하세요.',
 'right-patrolmarks' => '최근 바뀜에서 검토 표시를 보기',
 'right-unwatchedpages' => '주시되지 않은 문서 목록 보기',
 'right-mergehistory' => '문서의 역사를 합침',
-'right-userrights' => '모든 사용자의 권한 조정',
+'right-userrights' => '사용자의 모든 권한 조정',
 'right-userrights-interwiki' => '다른 위키의 사용자 권한을 조정',
 'right-siteadmin' => '데이터베이스를 잠그거나 잠금 해제',
 'right-override-export-depth' => '5단계로 링크된 문서를 포함하여 문서를 내보내기',
@@ -1773,7 +1778,7 @@ HTML 태그를 확인하세요.',
 'action-delete' => '이 문서 삭제하기',
 'action-deleterevision' => '이 판을 삭제',
 'action-deletedhistory' => '이 문서의 삭제된 기여의 역사 보기',
-'action-browsearchive' => '삭제된 문서 찾기',
+'action-browsearchive' => '삭제된 문서 검색',
 'action-undelete' => '이 문서 되살리기',
 'action-suppressrevision' => '이 숨겨진 판을 검토하고 되살릴',
 'action-suppressionlog' => '비공개 기록 보기',
@@ -1786,7 +1791,7 @@ HTML 태그를 확인하세요.',
 'action-autopatrol' => '자신의 편집을 검토된 것으로 표시할',
 'action-unwatchedpages' => '주시되지 않은 문서 목록 보기',
 'action-mergehistory' => '이 문서의 역사 합치기',
-'action-userrights' => '모든 사용자의 권한을 조정',
+'action-userrights' => '사용자의 모든 권한 조정',
 'action-userrights-interwiki' => '다른 위키의 사용자 권한을 조정',
 'action-siteadmin' => '데이터베이스를 잠그거나 잠금 해제하기',
 'action-sendemail' => '이메일 보내기',
@@ -1808,6 +1813,8 @@ HTML 태그를 확인하세요.',
 'recentchanges-label-minor' => '사소한 편집',
 'recentchanges-label-bot' => '봇의 편집',
 'recentchanges-label-unpatrolled' => '아직 검토하지 않은 편집',
+'recentchanges-label-plusminus' => '바이트로 표기된 바뀐 문서 크기',
+'recentchanges-legend-newpage' => '([[Special:NewPages|새 문서의 목록]]도 참고하세요)',
 'rcnote' => "다음은 $4 $5 까지의 {{PLURAL:$2|'''$2'''일}}동안 {{PLURAL:$1|바뀐 문서 '''$1'''개입니다}}.",
 'rcnotefrom' => "다음은 '''$2'''에서부터 바뀐 문서 '''$1'''개입니다.",
 'rclistfrom' => '$1 이래로 새로 바뀐 문서 보기',
@@ -1858,7 +1865,7 @@ HTML 태그를 확인하세요.',
 
 이 문서의 최근 삭제 기록과 이동 기록을 참고하십시오:",
 'uploadtext' => "파일을 올리기 위해서는 아래의 양식을 채워주세요.
-[[Special:FileList|파일 목록]]에서 이전에 올라온 파일을 찾을 수 있습니다. [[Special:Log/upload|올리기 기록]]에는 파일이 올라온 기록이 남습니다. 삭제 기록은 [[Special:Log/delete|삭제 기록]]에서 볼 수 있습니다.
+[[Special:FileList|파일 목록]]에서 이전에 올라온 파일을 검색할 수 있습니다. [[Special:Log/upload|올리기 기록]]에는 파일이 올라온 기록이 남습니다. 삭제 기록은 [[Special:Log/delete|삭제 기록]]에서 볼 수 있습니다.
 
 문서에 파일을 넣으려면 아래 방법 중 하나를 사용하세요.
 * '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' 파일의 온전한 모양을 사용하고자 할 때
@@ -2107,7 +2114,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 
 # Special:ListFiles
 'listfiles-summary' => '이 특수 문서는 모든 올려진 파일을 보여줍니다.',
-'listfiles_search_for' => '다음 이름을 가진 미디어 찾기:',
+'listfiles_search_for' => '다음 미디어 이름 검색:',
 'imgfile' => '파일',
 'listfiles' => '파일 목록',
 'listfiles_thumb' => '섬네일',
@@ -2138,7 +2145,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'filehist-dimensions' => '크기',
 'filehist-filesize' => '파일 크기',
 'filehist-comment' => '덧글',
-'filehist-missing' => 'í\8c\8cì\9d¼ì\9d\84 ì°¾ì\9d\84 ì\88\98 없음',
+'filehist-missing' => 'í\8c\8cì\9d¼ì\9d´ 없음',
 'imagelinks' => '이 파일을 사용하는 문서',
 'linkstoimage' => '다음 {{PLURAL:$1|문서 $1개}}가 이 파일을 가리키고 있습니다:',
 'linkstoimage-more' => '$1개 이상의 {{PLURAL:$1|문서}}가 이 파일을 가리키고 있습니다.
@@ -2197,8 +2204,8 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'filedelete-maintenance-title' => '파일을 삭제할 수 없습니다',
 
 # MIME search
-'mimesearch' => 'MIME 찾기',
-'mimesearch-summary' => 'MIME 타입에 해당하는 파일을 찾습니다.
+'mimesearch' => 'MIME 검색',
+'mimesearch-summary' => 'MIME 유형에 해당하는 파일을 검색합니다.
 다음 형태로 입력해주세요: 내용종류/하위종류, 예를 들어 <code>image/jpeg</code>',
 'mimetype' => 'MIME 종류:',
 'download' => '다운로드',
@@ -2346,7 +2353,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'notargettitle' => '해당하는 문서 없음',
 'notargettext' => '기능을 수행할 대상 문서나 사용자를 지정하지 않았습니다.',
 'nopagetitle' => '해당하는 문서 없음',
-'nopagetext' => 'ì°¾ë\8a\94 문서가 존재하지 않습니다.',
+'nopagetext' => 'ì§\80ì \95í\95\9c ë\8c\80ì\83\81 문서가 존재하지 않습니다.',
 'pager-newer-n' => '{{PLURAL:$1|다음 1개|다음 $1개}}',
 'pager-older-n' => '{{PLURAL:$1|이전 1개|이전 $1개}}',
 'suppress' => '오버사이트',
@@ -2354,9 +2361,9 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 
 # Book sources
 'booksources' => '책 찾기',
-'booksources-search-legend' => 'ì±\85 ì°¾ê¸°',
+'booksources-search-legend' => 'ì±\85 ì\9b\90본 ê²\80ì\83\89',
 'booksources-isbn' => 'ISBN:',
-'booksources-go' => '찾기',
+'booksources-go' => '검색',
 'booksources-text' => '아래의 목록은 새 책이나 중고 책을 판매하는 바깥 사이트로, 원하는 책의 정보를 얻을 수 있습니다.',
 'booksources-invalid-isbn' => '입력한 ISBN이 잘못된 것으로 보입니다. 원본과 대조해 보세요.',
 
@@ -2368,7 +2375,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'alllogstext' => '{{SITENAME}}에서의 기록이 모두 나와 있습니다.
 기록 종류, 사용자 이름, 문서 이름을 선택해서 볼 수 있습니다. (대소문자를 구별합니다.)',
 'logempty' => '일치하는 항목이 없습니다.',
-'log-title-wildcard' => '다음 글로 시작하는 제목 찾기',
+'log-title-wildcard' => '다음 글로 시작하는 제목 검색',
 'showhideselectedlogentries' => '선택한 기록 항목 보이기/숨기기',
 
 # Special:AllPages
@@ -2410,10 +2417,10 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'sp-deletedcontributions-contribs' => '기여',
 
 # Special:LinkSearch
-'linksearch' => '바깥 링크 찾기',
-'linksearch-pat' => '찾기 패턴:',
+'linksearch' => '바깥 링크 검색',
+'linksearch-pat' => '검색 패턴:',
 'linksearch-ns' => '이름공간:',
-'linksearch-ok' => '찾기',
+'linksearch-ok' => '검색',
 'linksearch-text' => '"*.wikipedia.org"와 같이 와일드 카드를 사용할 수 있습니다.
 적어도 "*.org"와 같이 최상위 도메인을 입력해야 합니다.<br />
 지원하는 {{PLURAL:$2|프로토콜}}: <code>$1</code> (프로토콜을 지정하지 않을 때 기본값은 http://)',
@@ -2554,7 +2561,7 @@ $PAGEINTRO $NEWPAGE
 이메일: $PAGEEDITOR_EMAIL
 위키: $PAGEEDITOR_WIKI
 
-이 문서를 열기 전에는 다른 알림 이메일을 더 이상 보내지 않습니다. 모든 주시 문서의 알림 딱지를 초기화할 수도 있습니다.
+로그인한 상태에서 이 문서를 열기 전에는 다른 알림 이메일을 더 이상 보내지 않습니다. 모든 주시 문서의 알림 딱지를 초기화할 수도 있습니다.
 
 {{SITENAME}} 알림 시스템
 
@@ -2739,11 +2746,11 @@ $1',
 
 [[Special:Log/delete|삭제 기록]]에서 최근의 삭제와 되살리기 기록을 볼 수 있습니다.",
 'undelete-header' => '최근에 삭제한 문서에 대한 기록은 [[Special:Log/delete|여기]]에서 볼 수 있습니다.',
-'undelete-search-title' => '삭제된 문서 찾기',
-'undelete-search-box' => '삭제된 문서 찾기',
+'undelete-search-title' => '삭제된 문서 검색',
+'undelete-search-box' => '삭제된 문서 검색',
 'undelete-search-prefix' => '다음으로 시작하는 문서 보기:',
-'undelete-search-submit' => '찾기',
-'undelete-no-results' => 'ì\82­ì \9cë\90\9c ë¬¸ì\84\9c ë³´ì¡´ì\97\90ì\84\9c ì\9d¼ì§\80하는 문서를 찾을 수 없습니다.',
+'undelete-search-submit' => '검색',
+'undelete-no-results' => 'ì\82­ì \9cë\90\9c ë¬¸ì\84\9c ë³´ì¡´ì\97\90ì\84\9c ì\9d¼ì¹\98하는 문서를 찾을 수 없습니다.',
 'undelete-filename-mismatch' => '타임스탬프가 $1인 파일의 버전을 되살릴 수 없습니다: 파일 이름이 일치하지 않습니다.',
 'undelete-bad-store-key' => '타임스탬프가 $1인 파일의 버전을 되살릴 수 없습니다: 파일이 삭제되기 전에 사라졌습니다.',
 'undelete-cleanup-error' => '사용되지 않는 보존된 파일 "$1"을 삭제하는 데 오류가 발생했습니다.',
@@ -2768,7 +2775,7 @@ $1',
 # Contributions
 'contributions' => '{{GENDER:$1|사용자}} 기여',
 'contributions-title' => '$1 사용자의 기여 목록',
-'mycontris' => '기여 목록',
+'mycontris' => '기여',
 'contribsub2' => '{{GENDER:$3|$1}}($2)의 기여',
 'nocontribs' => '지정한 조건과 일치하는 바뀜을 찾을 수 없습니다.',
 'uctop' => '(최신)',
@@ -2788,10 +2795,10 @@ $1',
 해당 사용자의 차단 기록은 다음과 같습니다:',
 'sp-contributions-blocked-notice-anon' => '이 IP 주소는 현재 차단되어 있습니다.
 차단 기록은 다음과 같습니다:',
-'sp-contributions-search' => '기여 찾기',
+'sp-contributions-search' => '기여 검색',
 'sp-contributions-username' => 'IP 주소 또는 사용자 이름:',
 'sp-contributions-toponly' => '최신판만 보기',
-'sp-contributions-submit' => '찾기',
+'sp-contributions-submit' => '검색',
 'sp-contributions-explain' => '',
 
 # What links here
@@ -2868,7 +2875,7 @@ $1',
 'unblocked-id' => '$1 차단이 해제되었습니다.',
 'blocklist' => '차단된 사용자 목록',
 'ipblocklist' => '차단된 사용자',
-'ipblocklist-legend' => '차단 중인 사용자 찾기',
+'ipblocklist-legend' => '차단 사용자 찾기',
 'blocklist-userblocks' => '계정에 대한 차단 숨기기',
 'blocklist-tempblocks' => '기한이 정해진 차단을 숨기기',
 'blocklist-addressblocks' => '단일 IP 차단을 숨기기',
@@ -2879,7 +2886,7 @@ $1',
 'blocklist-by' => '차단한 관리자',
 'blocklist-params' => '차단 설정',
 'blocklist-reason' => '이유',
-'ipblocklist-submit' => '찾기',
+'ipblocklist-submit' => '검색',
 'ipblocklist-localblock' => '로컬 차단',
 'ipblocklist-otherblocks' => '다른 {{PLURAL:$1|차단}} 기록',
 'infiniteblock' => '무기한',
@@ -3085,7 +3092,7 @@ $1 사용자가 차단된 이유는 다음과 같습니다: "$2"',
 'allmessagesdefault' => '기본 메시지 글',
 'allmessagescurrent' => '현재 문자열',
 'allmessagestext' => '미디어위키 이름공간에 있는 모든 시스템 메시지의 목록입니다.
-미디어위키의 번역 작업에 관심이 있으면 [//www.mediawiki.org/wiki/Localisation 미디어위키 지역화]나 [//translatewiki.net translatewiki.net]에 참가해주세요.',
+미디어위키의 번역 작업에 관심이 있으면 [https://www.mediawiki.org/wiki/Localisation 미디어위키 지역화]나 [//translatewiki.net translatewiki.net]에 참가해주세요.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages'''가 비활성화되어 있어서 이 문서를 사용할 수 없습니다.",
 'allmessages-filter-legend' => '필터',
 'allmessages-filter' => '수정 상태로 거르기:',
@@ -3098,7 +3105,7 @@ $1 사용자가 차단된 이유는 다음과 같습니다: "$2"',
 
 # Thumbnails
 'thumbnail-more' => '실제 크기로',
-'filemissing' => '파일 사라짐',
+'filemissing' => '파일이 없음',
 'thumbnail_error' => '섬네일을 만드는 중 오류 발생: $1',
 'thumbnail_error_remote' => '$1에서 반환한 오류 메시지:
 $2',
@@ -3108,7 +3115,7 @@ $2',
 'thumbnail-dest-create' => '대상 경로에 섬네일을 저장할 수 없습니다.',
 'thumbnail_invalid_params' => '섬네일 매개변수가 잘못되었습니다.',
 'thumbnail_dest_directory' => '새 목적 디렉터리를 만들 수 없습니다.',
-'thumbnail_image-type' => 'í\95´ë\8b¹ í\8c\8cì\9d¼ í\98\95ì\8b\9dì\9d\80 ì§\80ì\9b\90í\95\98ì§\80 ì\95\8aì\8aµë\8b\88ë\8b¤',
+'thumbnail_image-type' => '그림 í\98\95ì\8b\9dì\9d´ ì§\80ì\9b\90ë\90\98ì§\80 ì\95\8aì\8aµë\8b\88ë\8b¤',
 'thumbnail_gd-library' => 'GD 라이브러리 설정이 잘못되었습니다: $1 함수를 찾을 수 없습니다.',
 'thumbnail_image-missing' => '파일을 찾을 수 없습니다: $1',
 
@@ -3190,7 +3197,7 @@ $2',
 'tooltip-pt-anontalk' => '현재 사용하는 IP 주소에 대한 토론 문서',
 'tooltip-pt-preferences' => '사용자 환경 설정',
 'tooltip-pt-watchlist' => '주시문서에 대한 바뀜 목록',
-'tooltip-pt-mycontris' => '내 기여 목록',
+'tooltip-pt-mycontris' => '내 기여 목록',
 'tooltip-pt-login' => '꼭 로그인해야 하는 것은 아니지만, 로그인을 권장합니다.',
 'tooltip-pt-anonlogin' => '꼭 필요한 것은 아니지만, 로그인을 하면 편리한 점이 많습니다.',
 'tooltip-pt-logout' => '로그아웃',
@@ -3207,9 +3214,9 @@ $2',
 'tooltip-ca-move' => '문서 이동하기',
 'tooltip-ca-watch' => '이 문서를 주시문서 목록에 추가',
 'tooltip-ca-unwatch' => '이 문서를 주시문서 목록에서 제거',
-'tooltip-search' => '{{SITENAME}} 찾기',
+'tooltip-search' => '{{SITENAME}} 검색',
 'tooltip-search-go' => '이 이름의 문서가 존재하면 그 문서로 바로 가기',
-'tooltip-search-fulltext' => '이 문자열이 포함된 문서 찾기',
+'tooltip-search-fulltext' => '이 문자열이 포함된 문서 검색',
 'tooltip-p-logo' => '대문으로 가기',
 'tooltip-n-mainpage' => '대문으로 가기',
 'tooltip-n-mainpage-description' => '대문으로 가기',
@@ -3252,7 +3259,7 @@ $2',
 'tooltip-undo' => '"편집 취소" 기능을 사용하면 이 편집이 되돌려지고 차이 보기 기능이 미리 보기 형식으로 나타납니다. 편집 요약에 이 편집을 왜 되돌리는지에 대한 이유를 쓸 수 있습니다.',
 'tooltip-preferences-save' => '환경 설정 저장하기',
 'tooltip-summary' => '짧은 요약을 적어주세요',
-'tooltip-iwiki' => '$2 - $1',
+'interlanguage-link-title' => '$2 - $1',
 
 # Stylesheets
 'common.css' => '/* 이 CSS 설정은 모든 스킨에 동일하게 적용됩니다 */',
@@ -3298,10 +3305,12 @@ $2',
 'spamprotectiontext' => '스팸 필터가 문서 저장을 막았습니다.
 바깥 사이트로 연결하는 링크 중에 블랙리스트에 포함된 사이트가 있을 것입니다.',
 'spamprotectionmatch' => '문제가 되는 부분은 다음과 같습니다: $1',
-'spambot_username' => 'MediaWiki 스팸 제거',
+'spambot_username' => '미디어위키 스팸 정리',
 'spam_reverting' => '$1(을)를 포함하지 않는 최신 버전으로 되돌림',
 'spam_blanking' => '모든 버전에 $1 링크를 포함하고 있어 차단함',
 'spam_deleting' => '모든 버전에 $1 링크를 포함하고 있어 삭제함',
+'simpleantispam-label' => "스팸 방지 검사입니다.
+이것을 입력하지 '''마세요'''!",
 
 # Info page
 'pageinfo-title' => '"$1" 문서에 대한 정보',
@@ -3315,6 +3324,7 @@ $2',
 'pageinfo-length' => '문서 길이 (바이트)',
 'pageinfo-article-id' => '문서 ID',
 'pageinfo-language' => '문서 내용 언어',
+'pageinfo-content-model' => '문서 콘텐츠 모델',
 'pageinfo-robot-policy' => '로봇에 의한 색인',
 'pageinfo-robot-index' => '허용됨',
 'pageinfo-robot-noindex' => '불허됨',
@@ -3402,7 +3412,7 @@ $1',
 'svg-long-desc' => 'SVG 파일, 실제 크기 $1 × $2 픽셀, 파일 크기: $3',
 'svg-long-desc-animated' => '애니메이션 SVG 파일, 실제 크기 $1 × $2 픽셀, 파일 크기: $3',
 'svg-long-error' => '잘못된 SVG 파일: $1',
-'show-big-image' => 'ìµ\9cë\8c\80 í\95´ì\83\81ë\8f\84',
+'show-big-image' => 'ì\9b\90본 í\8c\8cì\9d¼',
 'show-big-image-preview' => '미리 보기 크기: $1',
 'show-big-image-other' => '다른 {{PLURAL:$2|해상도}}: $1',
 'show-big-image-size' => '$1 × $2 픽셀',
@@ -3422,7 +3432,7 @@ $1',
 'newimages-label' => '파일 이름 (또는 그 일부분):',
 'showhidebots' => '(봇을 $1)',
 'noimages' => '그림이 없습니다.',
-'ilsubmit' => '찾기',
+'ilsubmit' => '검색',
 'bydate' => '날짜',
 'sp-newimages-showfrom' => '$1 $2부터 올라온 파일 목록 보기',
 
@@ -3431,7 +3441,7 @@ $1',
 'minutes' => '$1분',
 'hours' => '$1시간',
 'days' => '$1일',
-'weeks' => '{{PLURAL:$1|$1주}}',
+'weeks' => '$1주',
 'months' => '$1달',
 'years' => '$1년',
 'ago' => '$1 전',
@@ -3466,8 +3476,8 @@ Variants for Chinese language
 
 # Metadata
 'metadata' => '메타데이터',
-'metadata-help' => '이 파일은 카메라나 스캐너에서 기록한 부가 정보를 가지고 있습니다.
-프로그램에서 파일을 편집할 경우, 새로 저장한 그림 파일에 일부 부가 정보가 빠질 수 있습니다.',
+'metadata-help' => '이 파일은 그 파일을 만들거나 디지털화하는 데 사용되는 카메라나 스캐너에서 기록한 부가 정보를 가지고 있습니다.
+프로그램에서 파일을 편집할 경우, 새로 저장한 파일에 일부 부가 정보가 빠질 수 있습니다.',
 'metadata-expand' => '자세한 정보 보이기',
 'metadata-collapse' => '자세한 정보 숨기기',
 'metadata-fields' => '파일 메타데이터 표가 접혀 있을 때, 이 메시지에 올라와 있는 다음 속성값만이 기본적으로 보이게 됩니다.
@@ -3653,7 +3663,7 @@ Variants for Chinese language
 'exif-preferredattributionname' => '이 저작물을 이용할 때 보일 저작자 이름',
 'exif-pngfilecomment' => 'PNG 파일 주석',
 'exif-disclaimer' => '면책 조항',
-'exif-contentwarning' => '콘텐츠 경고',
+'exif-contentwarning' => '내용 경고',
 'exif-giffilecomment' => 'GIF 파일 주석',
 'exif-intellectualgenre' => '항목 종류',
 'exif-subjectnewscode' => '주제 코드',
@@ -3880,8 +3890,8 @@ Variants for Chinese language
 'exif-urgency-other' => '사용자 정의 ($1)',
 
 # External editor support
-'edit-externally' => '이 파일을 바깥 프로그램을 사용해서 편집하기',
-'edit-externally-help' => '(자세한 정보는 [//www.mediawiki.org/wiki/Manual:External_editors 설치 방법]을 참고하세요)',
+'edit-externally' => '이 파일을 바깥 어플리케이션을 사용해 편집하기',
+'edit-externally-help' => '(자세한 정보는 [https://www.mediawiki.org/wiki/Manual:External_editors 설치 방법]을 참고하세요)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '모두',
@@ -3901,7 +3911,7 @@ Variants for Chinese language
 'confirmemail_send' => '인증 코드를 메일로 보내기',
 'confirmemail_sent' => '인증 이메일을 보냈습니다.',
 'confirmemail_oncreate' => '확인 이메일을 보냈습니다.
-이 확인 과정은 로그인하는 데에 필요하지는 않지만, 위키 프로그램에서 제공하는 이메일 기능을 사용하기 위해서 필요합니다.',
+이 확인 과정은 로그인하는 데에 필요하지는 않지만, 위키에서 제공하는 이메일 기능을 사용하기 위해서 필요합니다.',
 'confirmemail_sendfailed' => '{{SITENAME}}에서 인증 이메일을 보낼 수 없습니다.
 이메일 주소를 잘못 입력했는지 확인해주세요.
 
@@ -3984,6 +3994,9 @@ $5
 'confirm-unwatch-button' => '확인',
 'confirm-unwatch-top' => '이 문서를 주시문서 목록에서 뺄까요?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '“$1”',
+
 # Multipage image navigation
 'imgmultipageprev' => '← 이전 페이지',
 'imgmultipagenext' => '다음 페이지 →',
@@ -4071,16 +4084,16 @@ $5
 'version-hook-subscribedby' => '훅이 사용된 위치',
 'version-version' => '(버전 $1)',
 'version-license' => '라이선스',
-'version-poweredby-credits' => "이 위키는 '''[//www.mediawiki.org/ MediaWiki]'''를 기반으로 작동합니다. Copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "이 위키는 '''[https://www.mediawiki.org/ MediaWiki]'''(미디어위키)를 기반으로 작동합니다. Copyright © 2001-$1 $2.",
 'version-poweredby-others' => '그 외 다른 개발자',
 'version-poweredby-translators' => 'translatewiki.net 번역자',
-'version-credits-summary' => '[[Special:Version|미디어위키]]에 기여한 다음 사람í\95\9cí\85\8c ê°\90ì\82¬ë\93\9c립ë\8b\88ë\8b¤.',
+'version-credits-summary' => '[[Special:Version|미디어위키]]에 기여한 다음 사람ì\97\90ê²\8c ê°\90ì\82¬ë\93\9c립ë\8b\88ë\8b¤.',
 'version-license-info' => "미디어위키는 자유 소프트웨어입니다. 당신은 자유 소프트웨어 재단이 발표한 GNU 일반 공중 사용 허가서 버전 2나 그 이후 버전에 따라 이 파일을 재배포하거나 수정할 수 있습니다.
 
 미디어위키가 유용하게 사용될 수 있기를 바라지만 '''상용으로 사용'''되거나 '''특정 목적에 맞을 것'''이라는 것을 '''보증하지 않습니다'''. 자세한 내용은 GNU 일반 공중 사용 허가서 전문을 참고하십시오.
 
 당신은 이 프로그램을 통해 [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU 일반 공중 사용 허가서 전문]을 받았습니다. 그렇지 않다면, Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA로 편지를 보내주시거나 [//www.gnu.org/licenses/old-licenses/gpl-2.0.html 온라인으로 읽어보시기] 바랍니다.",
-'version-software' => '설치된 프로그램',
+'version-software' => '설치된 소프트웨어',
 'version-software-product' => '제품',
 'version-software-version' => '버전',
 'version-entrypoints' => 'URL 진입점',
@@ -4092,8 +4105,8 @@ $5
 # Special:Redirect
 'redirect' => '파일, 사용자나 판 ID별 넘겨주기',
 'redirect-legend' => '파일이나 문서로 넘겨주기',
-'redirect-summary' => '이 특수 문서는 파일(파일 이름을 지정), 문서(판 ID를 지정)나 사용자 문서(사용자 ID를 정수로 지정)로 넘겨줍니다.',
-'redirect-submit' => '기',
+'redirect-summary' => '이 특수 문서는 파일(파일 이름을 지정), 문서(판 ID를 지정)나 사용자 문서(사용자 ID를 정수로 지정)로 넘겨줍니다. 사용법: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], 혹은 [[{{#Special:Redirect}}/user/101]].',
+'redirect-submit' => '기',
 'redirect-lookup' => '찾을 종류:',
 'redirect-value' => '값:',
 'redirect-user' => '사용자 ID',
@@ -4102,11 +4115,11 @@ $5
 'redirect-not-exists' => '값을 찾을 수 없습니다',
 
 # Special:FileDuplicateSearch
-'fileduplicatesearch' => '중복된 파일 찾기',
-'fileduplicatesearch-summary' => '파일 해시값을 이용해 중복 파일을 찾습니다.',
-'fileduplicatesearch-legend' => '중복 찾기',
+'fileduplicatesearch' => '중복된 파일 검색',
+'fileduplicatesearch-summary' => '파일 해시값을 이용해 중복 파일을 검색합니다.',
+'fileduplicatesearch-legend' => '중복 검색',
 'fileduplicatesearch-filename' => '파일 이름:',
-'fileduplicatesearch-submit' => '찾기',
+'fileduplicatesearch-submit' => '검색',
 'fileduplicatesearch-info' => '$1 × $2 픽셀<br />파일 크기: $3<br />MIME 유형: $4',
 'fileduplicatesearch-result-1' => '"$1" 파일과 중복된 파일이 없습니다.',
 'fileduplicatesearch-result-n' => '"$1" 파일은 {{PLURAL:$2|중복 파일이 $2개}} 있습니다.',
@@ -4114,8 +4127,8 @@ $5
 
 # Special:SpecialPages
 'specialpages' => '특수 문서 목록',
-'specialpages-note' => '----
-* 일반 특수 문서입니다.
+'specialpages-note-top' => '범례',
+'specialpages-note' => '* 일반 특수 문서입니다.
 * <span class="mw-specialpagerestricted">제한된 특수 문서입니다.</span>',
 'specialpages-group-maintenance' => '관리용 목록',
 'specialpages-group-other' => '다른 특수 문서',
@@ -4199,8 +4212,8 @@ $5
 'htmlform-chosen-placeholder' => '선택하세요',
 
 # SQLite database support
-'sqlite-has-fts' => '$1 (본문 전체 찾기)',
-'sqlite-no-fts' => '$1 (본문은 찾기에서 제외)',
+'sqlite-has-fts' => '$1 (본문 전체 검색 지원)',
+'sqlite-no-fts' => '$1 (본문 전체 검색 지원 제외)',
 
 # New logging system
 'logentry-delete-delete' => '$1 사용자가 $3 문서를 {{GENDER:$2|삭제했습니다}}',
@@ -4255,7 +4268,7 @@ $5
 'feedback-bugnew' => '확인했습니다. 새로운 버그 보고서를 작성합니다.',
 
 # Search suggestions
-'searchsuggest-search' => '찾기',
+'searchsuggest-search' => '검색',
 'searchsuggest-containing' => '다음 문자열 포함...',
 
 # API errors
@@ -4329,4 +4342,20 @@ $5
 'limitreport-expansiondepth' => '최대 전개 깊이',
 'limitreport-expensivefunctioncount' => '부하 높은 파서 함수 수',
 
+# Special:ExpandTemplates
+'expandtemplates' => '틀 전개',
+'expand_templates_intro' => '이 특수 문서는 글의 모든 틀을 끝까지 풀어 줍니다.
+<code><nowiki>{{</nowiki>#language:…}}</code> 같은 파서 함수나
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code> 같은 변수를 풀어줍니다.
+사실 두개의 중괄호 사이에 있는 것은 거의 모두 풀어줍니다.',
+'expand_templates_title' => '문서 이름 ({{FULLPAGENAME}} 등):',
+'expand_templates_input' => '전개할 내용:',
+'expand_templates_output' => '결과',
+'expand_templates_xml_output' => 'XML 출력',
+'expand_templates_ok' => '확인',
+'expand_templates_remove_comments' => '주석 제거',
+'expand_templates_remove_nowiki' => '결과에서 <nowiki> 태그를 숨기기',
+'expand_templates_generate_xml' => 'XML 구문 트리 보기',
+'expand_templates_preview' => '미리 보기',
+
 );
index ab8c0d5..1d2463e 100644 (file)
@@ -165,8 +165,6 @@ $messages = array(
 
 'retrievedfrom' => 'Öшмöс "$1"',
 'youhavenewmessages' => 'Тэныт локтiс $1 ($2).',
-'newmessageslink' => 'виль юöррез',
-'newmessagesdifflink' => 'медбöрьяись вильмöтöм',
 'youhavenewmessagesmulti' => '$1 юкöтын тэ понда мыйкö эм',
 'editsection' => 'мöдкодьсьöтны',
 'editold' => 'мöдкодьсьöтны',
@@ -742,7 +740,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'Редактируйтны этiйö файлсö мöд программа пыр',
-'edit-externally-help' => '(унажык видзöт: [//www.mediawiki.org/wiki/Manual:External_editors удж кежö лöсьöтны туйдöтан])',
+'edit-externally-help' => '(унажык видзöт: [https://www.mediawiki.org/wiki/Manual:External_editors удж кежö лöсьöтны туйдöтан])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'быдöс',
index b886dce..7892a93 100644 (file)
@@ -45,7 +45,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Бютеу_бетле' ),
        'Blankpage'                 => array( 'Бош_бет' ),
        'Block'                     => array( 'Блок_эт' ),
-       'Blockme'                   => array( 'Мени_блок_эт' ),
        'Booksources'               => array( 'Китабланы_къайнакълары' ),
        'BrokenRedirects'           => array( 'Джыртылгъан_редиректле' ),
        'Categories'                => array( 'Категорияла' ),
@@ -57,7 +56,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Тергеу_джазыуну_къура', 'Къошулуучуну_къура', 'Регистрация_эт' ),
        'Deadendpages'              => array( 'Чыкъмазча_бетле' ),
        'DeletedContributions'      => array( 'Кетерилген_къошум' ),
-       'Disambiguations'           => array( 'Кёб_магъаналы' ),
        'DoubleRedirects'           => array( 'Экили_редирект' ),
        'EditWatchlist'             => array( 'Кёздеги_тизмени_тюрлендир' ),
        'Emailuser'                 => array( 'Къошулуучугъа_джазма', 'Джазма_ий' ),
@@ -383,8 +381,6 @@ $1',
 'ok' => 'ОК',
 'retrievedfrom' => 'Чыкъгъаны — «$1»',
 'youhavenewmessages' => 'Сизге $1 келдиле ($2).',
-'newmessageslink' => 'джангы билдириуле',
-'newmessagesdifflink' => 'сюзюу бетигизни ахыр тюрлениую',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Башха бир къошулуучудан|$3 къошулуучудан}} сеннге $1 келди ($2).',
 'youhavenewmessagesmanyusers' => 'Талай къошулуучудан $1 барды. ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|джангы билдириу|джангы билдириуле}}',
@@ -1167,8 +1163,6 @@ $1",
 'preferences' => 'Джарашдырыула',
 'mypreferences' => 'Джарашдырыула',
 'prefs-edits' => 'Тюрлендириулени саны:',
-'prefsnologin' => 'Системагъа кесигизни танытмагъансыз',
-'prefsnologintext' => 'Къошулуучуну джарашдырыуларын тюрлендирир ючюн <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} системагъа кесигизни танытыргъа]</span> керексиз.',
 'changepassword' => 'Паролну ауушдур',
 'prefs-skin' => 'Джасауу',
 'skin-preview' => 'Ал къарау',
@@ -1448,6 +1442,7 @@ $1 {{PLURAL:$1|символдан|символладан}} кеб болургъ
 'recentchanges-label-minor' => 'Бу гитче тюрлениудю',
 'recentchanges-label-bot' => 'Бу тюрлендириуню бот этгенди',
 'recentchanges-label-unpatrolled' => 'Бу тюрлендириу алкъын патруль этилинмегенди',
+'recentchanges-legend-newpage' => '$1 — джангы бет',
 'rcnote' => '$4 $5 заманнга, арт {{PLURAL:$1|1|$1}} тюрлениу {{PLURAL:$2|1|$2}}  кюнню ичинде',
 'rcnotefrom' => 'Тюбюрекде <strong>$2</strong> башлаб (<strong>$1</strong> дери) тюрлендириуле кёрюнедиле',
 'rclistfrom' => '$1 башлаб джангы тюрлениулени кёргюз',
@@ -2583,7 +2578,7 @@ $1',
 'allmessagesdefault' => 'Оригинал текст',
 'allmessagescurrent' => 'Хайырлана тургъан текст',
 'allmessagestext' => 'Бу тизме MediaWiki ат аламында бар болгъан система билдириулени тизмесиди.
-MediaWiki локализациясына юлюш къошаргъа излей эсегиз, [//www.mediawiki.org/wiki/Localisation MediaWiki локализация] бла [//translatewiki.net translatewiki.net] сайтлагъа киригиз.',
+MediaWiki локализациясына юлюш къошаргъа излей эсегиз, [https://www.mediawiki.org/wiki/Localisation MediaWiki локализация] бла [//translatewiki.net translatewiki.net] сайтлагъа киригиз.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' джабыкъ болгъаны ючюн '''{{ns:special}}:Allmessages''' хайырланыугъа ачыкъ тюлдю.",
 'allmessages-filter-legend' => 'Фильтр',
 'allmessages-filter' => 'Тюрлендириуюне кёре фильтрлендир:',
@@ -3279,7 +3274,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Бу файлны тыш программа бла тюрлендиригиз',
-'edit-externally-help' => '(толу информациягъа мында къарагъыз: [//www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
+'edit-externally-help' => '(толу информациягъа мында къарагъыз: [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'бютеу',
@@ -3506,7 +3501,7 @@ $5
 'version-hook-subscribedby' => 'Абонент болгъан',
 'version-version' => '(Версия $1)',
 'version-license' => 'Лицензия',
-'version-poweredby-credits' => "Бу вики '''[//www.mediawiki.org/ MediaWiki]''' программа бла ишлейди, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Бу вики '''[https://www.mediawiki.org/ MediaWiki]''' программа бла ишлейди, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'башхала',
 'version-license-info' => 'MediaWiki эркин программа джазыуду, сиз аны GNU General Public License лицензияны (эркин программа джазыуланы фонду чыгъаргъан; экинчи версиясы неда андан кеч къайсысы да) шартларына кёре джаяргъа эмда/неда тюрлендирирге боллукъсуз.
 
@@ -3533,8 +3528,7 @@ MediaWiki хайырлы боллукъду деген умут бла джай
 
 # Special:SpecialPages
 'specialpages' => 'Къуллукъчу бетле',
-'specialpages-note' => '----
-* Тюз къуллукъчу бетле.
+'specialpages-note' => '* Тюз къуллукъчу бетле.
 * <span class="mw-specialpagerestricted">Кирирге эркинлик чекленнген къуллукъчу бетле.</span>
 * <span class="mw-specialpagecached">Кэш этилген къуллукъчу бетле (эски болургъа боллукъдула).</span>',
 'specialpages-group-maintenance' => 'Техника баджарыуну отчетлары',
@@ -3687,4 +3681,7 @@ MediaWiki хайырлы боллукъду деген умут бла джай
 'duration-centuries' => '$1 {{PLURAL:$1|ёмюр}}',
 'duration-millennia' => '$1 {{PLURAL:$1|мингджыллыкъ}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Шаблонланы ачыу',
+
 );
index b9a9ac7..e914148 100644 (file)
@@ -112,7 +112,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Ahl_Atikelle' ),
        'Blankpage'                 => array( 'Leddijje_Sigge' ),
        'Block'                     => array( 'IP-Sperre' ),
-       'Blockme'                   => array( 'Proxy-Sperre' ),
        'Booksources'               => array( 'ISBN', 'Böcher', 'Böösher' ),
        'BrokenRedirects'           => array( 'Ömleitunge_en_et_Leere' ),
        'Categories'                => array( 'Saachjruppe' ),
@@ -123,7 +122,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Aanmelde', 'Medmaacher_wääde', 'Metmaacher_wääde' ),
        'Deadendpages'              => array( 'Sigge_ohne_Links_dren' ),
        'DeletedContributions'      => array( 'Fotjeschmeße' ),
-       'Disambiguations'           => array( 'Wat-es-dat-Sigge', 'Watt_ėßß_datt?' ),
        'DoubleRedirects'           => array( 'Ömleitunge_op_Ömleitunge' ),
        'Emailuser'                 => array( 'Email', 'E-mail' ),
        'Export'                    => array( 'Expocht' ),
@@ -431,7 +429,7 @@ $messages = array(
 'articlepage' => 'Aanluure wat op dä Sigg drop steiht',
 'talk' => 'Klaafe',
 'views' => 'Aansichte',
-'toolbox' => 'Werkzüch',
+'toolbox' => 'Wärkzüsch',
 'userpage' => 'Däm Metmaacher sing Sigg aanluure',
 'projectpage' => 'De Projeksigg aanluure',
 'imagepage' => 'De Sigg övver die Dattei aanluure',
@@ -461,7 +459,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Övver {{GRAMMAR:Akkusativ|{{ucfirst:{{SITENAME}}}}}}',
 'aboutpage' => 'Project:Övver {{GRAMMAR:Akkusativ|{{ucfirst:{{SITENAME}}}}}}',
-'copyright' => 'Dä Enhald steiht unger de $1.',
+'copyright' => 'Dä Enhald steiht unger dä Lezänz $1, ußer wann ußdröklesch jäd anders jesaad es.',
 'copyrightpage' => '{{ns:project}}:Lizenz',
 'currentevents' => 'Et Neuste',
 'currentevents-url' => 'Project:Et Neuste',
@@ -488,8 +486,6 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Di Sigg heh stamp vun „$1“.',
 'youhavenewmessages' => 'Do häs $1 ($2).',
-'newmessageslink' => 'neu Metdeilunge op Dinger Klaafsigg',
-'newmessagesdifflink' => 'Ungerscheid zor vürletzte Version',
 'youhavenewmessagesfromusers' => 'Do häs $1 vun {{PLURAL:$3|enem|$3|keinem}} andere Metmaacher ($2)',
 'youhavenewmessagesmanyusers' => 'Do häs $1 vun andere Metmaacher ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|en neuje Nohreesch|neu Nohreeschte|kein neuje Nohreeschte}}',
@@ -685,7 +681,9 @@ Wann De wells, künnts De Ding [[Special:Preferences|Enschtällonge aanpaße]].'
 'userlogin-resetpassword-link' => 'Paßwoot verjäße?',
 'helplogin-url' => 'Help:Övver et Enlogge',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hölp bem Enlogge]]',
+'userlogin-createanother' => 'Donn ene zohsäzlejje Zohjang aanlääje',
 'createacct-join' => 'Jiv Ding Daate en:',
+'createacct-another-join' => 'Maach de nüüdeje Aanjaabe för dä neue Zohjaang.',
 'createacct-emailrequired' => 'Ding Addräß för de <i lang="en">e-mail</i>',
 'createacct-emailoptional' => 'Ding Addräß för de <i lang="en">e-mail</i>, kann fott bliive',
 'createacct-email-ph' => 'Jiv Ding Addräß för de <i lang="en">e-mail</i> en!',
@@ -772,7 +770,7 @@ Ene schöne Jroß vun {{GRAMMAR:Dat|{{SITENAME}}}}.
 'noemailcreate' => 'Do moß en jöltijje Adräß för Ding <i lang="en">e-mail</i> aanjävve',
 'passwordsent' => 'E neu Passwood es aan de E-Mail Adress vun däm Metmaacher „$1“ ungerwähs. Meld dich domet aan, wann De et häs. Dat ahle Passwood bliev erhalde un kann och noch jebruch wääde, bes dat De Dich et eetste Mol met däm Neue enjelogg häs.',
 'blocked-mailpassword' => 'Ding IP Adress es blockeet.',
-'eauthentsent' => 'En <i lang="en">e-mail</i> es jäz ungerwähs aan di Adräß, di en de Enschtällonge schteiht. Ih dat <i lang="en">e-mails</i> övver {{GRAMMAR:Genitiv iere male|{{ucfirst:{{SITENAME}}}}}} <i lang="en">e-mail</i>-Knopp verscheck wääde künne, moß de <i lang="en">e-mail</i>-Adräß eets ens beschtäätesch woode sin. Wat mer doför maache moß, schteiht en dä <i lang="en">e-mail</i> dren, di jrad avjescheck woode es.',
+'eauthentsent' => 'En <i lang="en">e-mail</i> es jäz ungerwähs aan di Adräß en de Enschtällonge. Ih dat mieh <i lang="en">e-mails</i> verscheck wääde künne, moß mer maache, wat en dä <i lang="en">e-mail</i> dren schteiht, öm ze beschtääteje, dat di Adräß schtemmp.',
 'throttled-mailpassword' => 'En Erennerung för di Passwood es alld ongerwähs, un mieh wi eimol en {{PLURAL:$1|der Schtond|$1 Schtonde|nidd ens ener Schtond}} dommer kein schecke.',
 'mailerror' => 'Fähler beim E-Mail Verschecke: $1.',
 'acct_creation_throttle_hit' => '<b>Schad.</b>
@@ -806,6 +804,9 @@ Waad e Wielsche ävver $1, ih dat De et wider versöhks.',
 'loginlanguagelabel' => 'Sproch: $1',
 'suspicious-userlogout' => "Do bes '''nit''' ußjelogg.
 Et süht us, wi wann ene kappodde Brauser udder <i lang=\"en\">proxy</i>ẞööver met Zwescheschpeischer noh däm Ußlogge jefrooch hät.",
+'createacct-another-realname-tip' => 'Dä reschteje Nahme kam_mer fott lohße.
+
+Wann dä aanjejovve es, weet_e jebruch, öm öffentlesch de Schriiver för Beidrääsch ze nänne.',
 
 # Email sending
 'php-mail-error-unknown' => 'Nit bekannte Fähler met dä Funxjohn <code lang="en">mail()</code> vum PHP',
@@ -821,7 +822,7 @@ Et süht us, wi wann ene kappodde Brauser udder <i lang=\"en\">proxy</i>ẞööv
 'newpassword' => 'Et neue Passwood:',
 'retypenew' => 'Noch ens dat neue Passwood:',
 'resetpass_submit' => 'E neu Zweschepasswood övvermeddele un aanmellde',
-'changepassword-success' => 'Passwood jeändert. Jetz küdd_et Enlogge&nbsp;…',
+'changepassword-success' => 'Et Paßwood es jeändert.',
 'resetpass_forbidden' => 'E Passwoot kann nit jeändert wääde.',
 'resetpass-no-info' => 'Do mööts ad enjelogg sin, öm tiräk op di Sigg jonn ze dörve',
 'resetpass-submit-loggedin' => 'Passwood tuusche',
@@ -834,6 +835,8 @@ Do häs Der enzwesche e neu Zweschepaßwood jehollt.',
 
 # Special:PasswordReset
 'passwordreset' => 'Et Paßwoot zeröck säze',
+'passwordreset-text-one' => 'Föll dat Fommolaa uß, öm Ding Paßwoot ze ändere.',
+'passwordreset-text-many' => '{{PLURAL:$1|Föll ei Fäld en däm Fommolaa uß, öm Ding Paßwoot ze ändere.}}',
 'passwordreset-legend' => 'Et Paßwoot zeröck säze',
 'passwordreset-disabled' => 'Et Paßwoot zeröck ze säze es heh em Wiki afjeschalldt.',
 'passwordreset-emaildisabled' => 'Heh dat Wiki määt nix met <i lang="en">e-mail</i>!',
@@ -886,6 +889,9 @@ Do moß Ding Paßwoot enjävve, öm Ding Änderong ze bschtäätejje.',
 'changeemail-submit' => 'Lohß jonn!',
 'changeemail-cancel' => 'Ophüre',
 
+# Special:ResetTokens
+'resettokens-token-label' => '$1 (Em Momang es et: $2)',
+
 # Edit page toolbar
 'bold_sample' => 'Fätte Schreff',
 'bold_tip' => 'Fätte Schreff',
@@ -1129,13 +1135,14 @@ Ene Jrond weße mer nit.',
 'edit-gone-missing' => 'Kunnt di Sigg nit änndere. Se schingk verschwunde un weed fottjeschemeße woode sin.',
 'edit-conflict' => 'Dubbelt beärbeit.',
 'edit-no-change' => 'Do häs ja nix aan dä Sigg jeändert, do dom_mer och nix domet.',
+'postedit-confirmation' => 'Ding Änderunge sin nit faßjehallde.',
 'edit-already-exists' => 'Kunnt kei neu Sigg aanlääje. Di Sigg jidd_et ald.',
 'defaultmessagetext' => 'Dä standaadmäßije Tex',
 'content-failed-to-parse' => 'Et wohr nit müjjelesch, dä Enhalld met däm <i lang="en">MIME-Typ</i> $2 för en Dattei met $1 dren ze verwooschte: $3.',
 'invalid-content-data' => 'Di Daate en dä Sigg sen onjöltesch.',
 'content-not-allowed-here' => 'Ene Enhalld vun dä Zoot „$1“ es op dä Sigg „[[$2]]“ nit zohjelohße.',
-'editwarning-warning' => 'Wann de vun hee dä Sigg fott jeihß, doh künnte all Ding Änderunge aan dä Sigg verschött jonn.
-Do kanns heh di Warnung affschallde, wann de aanjemelldt un enjelogg bes, dann kriß de se nieh mieh wider. Jangk doför en dä Affschnett „{{int:prefs-editing}}“ en Dinge Enshtellunge.',
+'editwarning-warning' => 'Wann de vun hee dä Sigg fott jeihß, doh künnte all Ding Änderonge aan dä Sigg verschött jonn.
+Do kanns heh di Warnung affschallde, wann de aanjemelldt un enjelogg bes, dann kriß de se nieh mieh wider. Jangk doför en dä Afschnett „{{int:prefs-editing}}“ en Dinge Enschtellonge.',
 
 # Content models
 'content-model-wikitext' => 'Wikitäx',
@@ -1155,7 +1162,7 @@ Do kanns heh di Warnung affschallde, wann de aanjemelldt un enjelogg bes, dann k
 'parser-template-loop-warning' => 'Schablon roofe sesch em Kringel op: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Schablone refe sesch zo öff sellver op ($1)',
 'language-converter-depth-warning' => 'Zoh vill Verschachtelunge (övver $1) beim Täx-Ömwandelle vun ein Shprooch en andere.',
-'node-count-exceeded-category' => 'Sigge, woh dä  node-count övverschredde es',
+'node-count-exceeded-category' => 'Sigge, woh dä <i lang="en" xml:lang="en">node-count</i> övverschredde es',
 'node-count-exceeded-warning' => 'Heh di Sigg hät dä <i lang="en" xml:lang="en">node-count</i> övverschredde',
 'expansion-depth-exceeded-category' => 'Sigge, woh de <i lang="en" xml:lang="en">expansion depth</i> övverschredde es',
 'expansion-depth-exceeded-warning' => 'Heh di Sigg hät de <i lang="en" xml:lang="en">expansion depth</i> övverschredde',
@@ -1348,6 +1355,7 @@ Donn de Version makeere bes wohen (inklusive) dat övverdraare wäde sull. Donn
 'compareselectedversions' => 'Dun de markeete Version verjliche',
 'showhideselectedversions' => 'De ußjewählte Versione aanzeije udder vershteiche',
 'editundo' => 'De letzte Änderung zeröck nämme',
+'diff-empty' => '(Keine Ongerscheid)',
 'diff-multi' => '(Mer don hee {{PLURAL:$1|eij Version|$1 Versione|keij Version}} dozwesche beim Verjliesche översprenge. Di sin vun jesamp {{PLURAL:$2|einem Metmaacher|$2 Metmaachere|keinem Metmaacher}} jemaat woode)',
 'diff-multi-manyusers' => '({{PLURAL:$1|Ein Version|$1 Versione|kei Version}} dozwesche vun mieh wi {{PLURAL:$2|einem Metmaacher|$2 Metmaachere|keinem Metmaacher}} wääde nit jezeish)',
 'difference-missing-revision' => '{{PLURAL:$2|Ein Version|$2 Versione}} vun heh däm Verjlisch zwesche Versione ($1) {{PLURAL:$2|hammer}} nit jefonge.
@@ -1433,8 +1441,6 @@ dat dänne ehr Daate topaktoell sin,
 'preferences' => 'ming Enstellunge',
 'mypreferences' => 'Enstellunge',
 'prefs-edits' => 'Aanzahl Änderunge am Wiki:',
-'prefsnologin' => 'Nit enjelogg',
-'prefsnologintext' => 'Do mööts ald <span class="plainlinks">[{{fullurl:{{#special:UserLogin}}|returnto=$1}} enjelogg]</span> sin, öm Ding Enstellunge ze ändere.',
 'changepassword' => 'Passwood *',
 'prefs-skin' => 'Et Ussinn',
 'skin-preview' => 'Vör-Ansich',
@@ -1637,6 +1643,10 @@ dat dänne ehr Daate topaktoell sin,
 'right-editusercssjs' => 'Anderlücks CSS- un JS-Dateie ändere',
 'right-editusercss' => 'Anderlücks CSS-Dateie ändere',
 'right-edituserjs' => 'Anderlücks JS-Dateie ändere',
+'right-editmyusercss' => 'De eije <i lang="en" xml:lang="en">CSS</i> Datteije aanlääje un ändere',
+'right-editmyuserjs' => 'Eije JaavaSkrepp-Datteije aanlääje un ändere',
+'right-viewmywatchlist' => 'De eije Oppaßleß beloore',
+'right-editmyoptions' => 'De eije Enschtällonge ändere',
 'right-rollback' => 'All de letzte Änderunge fom letzte Metmaacher aan ene Sigg retur maache',
 'right-markbotedits' => 'Retur jemaate Änderonge als Bot-Änderung makeere',
 'right-noratelimit' => 'Kein Beschränkunge dorch Jrenze (<i lang="en">[http://www.mediawiki.org/wiki/Manual:%24wgRateLimits $wgRateLimits]</i>)',
@@ -1688,8 +1698,8 @@ dat dänne ehr Daate topaktoell sin,
 'action-block' => 'hee dämm Metmaacher et Sigge Ändere ze verbeede',
 'action-protect' => 'hee dä Sigg iere Sigge-Schotz ze ändere',
 'action-rollback' => 'all de letzte Änderunge fom letzte Metmaacher aan ene beshtemmpte Sigg flöck retur ze maache',
-'action-import' => 'hee di Sigg uss enem andere Wiki ze empotteere',
-'action-importupload' => 'hee di Sigg uss ene huhjelaade Datei ze impotteere',
+'action-import' => 'Sigge uss_enem andere Wiki ze empotteere',
+'action-importupload' => 'Sigge uss_ene huhjelaade Dattei ze empotteere',
 'action-patrol' => 'anderlüx Änderunge als „nohjeloort“ ze makeere',
 'action-autopatrol' => 'Ding eije Änderunge sälver als „nohjeloort“ ze makeere',
 'action-unwatchedpages' => 'de Leß met de Sigg en kei Oppassleß aanzeloore',
@@ -1698,19 +1708,25 @@ dat dänne ehr Daate topaktoell sin,
 'action-userrights-interwiki' => 'dä Metmaacher fun ander Wikis ier Rääschte ze ändere',
 'action-siteadmin' => 'de Datebank ze sperre udder widder freizejävve',
 'action-sendemail' => '<i lang="en">e-mails</i> ze verschecke',
+'action-editmywatchlist' => 'de eije Oppaßleß ze ändere',
+'action-viewmywatchlist' => 'de eije Oppaßleß ze belooere',
+'action-viewmyprivateinfo' => 'de eije päsöönlesche Aanjaabe ze belooere',
 'action-editmyprivateinfo' => 'Ding päsöönlesche Aanjaabe ze ändere',
 
 # Recent changes
 'nchanges' => '{{PLURAL:$1|Ein Änderong|$1 Änderonge|Kein Änderong}}',
+'enhancedrc-since-last-visit' => '{{PLURAL:$1|Ein|$1|Kein}} zigg_em läzde Aanloore',
 'enhancedrc-history' => 'Väsjohne',
 'recentchanges' => 'Neuste Änderonge',
 'recentchanges-legend' => 'Enstellunge',
 'recentchanges-summary' => 'Op dä Sigg hee sin de neuste Änderunge am Wiki opjeliss.',
+'recentchanges-noresult' => 'Nit verändert en dä Zigg met de aanjejovve Beschrängkonge.',
 'recentchanges-feed-description' => 'Op dämm Abonnomang-Kannal (<i lang="en">Feed</i>) kannze de {{int:recentchanges}} aam Wiki en Laif un en Färve metloore.',
 'recentchanges-label-newpage' => 'Heh di Sigg es neu dobei jekumme met dä Änderung',
 'recentchanges-label-minor' => 'Heh dat es en Mini-Änderung',
 'recentchanges-label-bot' => 'Di Änderung es fun enem Bot jemaat woode',
 'recentchanges-label-unpatrolled' => 'Heh di Änderung es noch nit nohjeloort',
+'recentchanges-legend-newpage' => '$1 - neu Sigg',
 'rcnote' => '{{PLURAL:$1|Heh es de letzte Änderung us|Heh sin de letzte <strong>$1</strong> Änderunge us|Et jit <strong>kei</strong> Änderunge en}} {{PLURAL:$2|däm letzte Daach|de letzte <strong>$2</strong> Dääsch|dä Zick}} vum <strong>$4</strong> aff <strong>$5</strong> Uhr beß jetz.',
 'rcnotefrom' => 'Hee {{PLURAL:$1|es ein|sin bes op <strong>$1</strong>|es keine}} fun de Änderunge zick dem <strong>$3</strong> öm <strong>$4</strong> Uhr opjelėß.',
 'rclistfrom' => 'Zeich de Änderunge vum $1 aan',
@@ -2538,10 +2554,12 @@ Do kanns hee noh Hölp luure:
 'deletecomment' => 'Aanlaß odder Jrund:',
 'deleteotherreason' => 'Ander Jrund oder Zosätzlich:',
 'deletereasonotherlist' => 'Ander Jrund',
-'deletereason-dropdown' => '* Alljemein Jrönde
-** dä Schriever wollt et esu
+'deletereason-dropdown' => '* Alljemein Jrönde för et Fottschmiiße
+** SPAM
+** et wohd jät kapott jemaat
 ** wohr jäje et Urhävverrääsch
-** et wohd jet kapott jemaat',
+** dä Schriever wolld et esu
+** kappodde Ömleidong',
 'delete-edit-reasonlist' => 'De Jrönde för et Fottschmieße beärbeide',
 'delete-toobig' => 'Di Sigg hät {{PLURAL:$1|ein Version|$1 Versione|jaa kein Version}}. Dat sinn_er ärsch fill. Domet unsere ẞööver do nit draan en de Kneen jeit, dom_mer esu en Sigg nit fottschmieße.',
 'delete-warning-toobig' => 'Di Sigg hät {{PLURAL:$1|ein Version|$1 Versione|jakein Version}}. Dat sinn_er ärsch fill. Wann De die all fottschmieße wells, dat kann dem Wiki sing Datenbangk schwer ußbremse.',
@@ -3024,7 +3042,7 @@ zo jroße Lass för dä ẞööver.',
 'allmessagesdefault' => 'Dä standaadmäßije Tex',
 'allmessagescurrent' => 'Esu es dä Tex jetz',
 'allmessagestext' => 'Heh kütt en Liss met Texte, Texstöck, un Nohreechte em Appachtemeng „MediaWiki“ — Do draan Ändere löht et Wiki anders ußsin, dat darf dröm nit Jede maache.
-Wenn De jenerell aan [//www.mediawiki.org/wiki/Localisation MediaWiki singe Översezung] jet anders han wells, do jangk noh [//translatewiki.net translatewiki.net].',
+Wenn De jenerell aan [https://www.mediawiki.org/wiki/Localisation MediaWiki singe Översezung] jet anders han wells, do jangk noh [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => '<strong>Dat wor nix!</strong> Mer künne „{{#special:allmessages}}“ nit zeije, <code>$wgUseDatabaseMessages</code> es usjeschalt!',
 'allmessages-filter-legend' => 'Ußsöhke — wat för en Täxte o Nohreeshte aazeije?',
 'allmessages-filter' => 'Zohshtand:',
@@ -3237,6 +3255,7 @@ Esu kam_mer noch en Aanmärkong en „{{int:summary}}“ maache.',
 'spam_reverting' => 'De letzte Version ohne de Links op „$1“ widder zerröckjehollt.',
 'spam_blanking' => 'All die Versione hatte Links op „$1“, die sin jetz erus jemaht.',
 'spam_deleting' => 'All di Versione met Lenks op „$1“ wääde fott jeschmeße',
+'simpleantispam-label' => 'SPAMschotz — donn hee nix endraare!',
 
 # Info page
 'pageinfo-title' => 'Övver di Sigg: „$1“',
@@ -3823,7 +3842,7 @@ Donoh kumme, en däsellve Reih, Links op Sigge wo die Datei trotz dämm jenehm e
 
 # External editor support
 'edit-externally' => 'Dun de Datei met enem externe Projramm bei Dr om Rechner bearbeide',
-'edit-externally-help' => '(Luur en de [//www.mediawiki.org/wiki/Manual:External_editors Aanleidong för de Enschtallazjuhn] noh mieh Henwiese)',
+'edit-externally-help' => '(Luur en de [https://www.mediawiki.org/wiki/Manual:External_editors Aanleidong för de Enschtallazjuhn] noh mieh Henwiese)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'all',
@@ -4075,7 +4094,7 @@ Dä Shtanndat-Zoot-Schlößel „$1“ övverschriif dä älldere Zoot-Schlöße
 'version-hook-subscribedby' => 'Opjeroofe vun',
 'version-version' => '(Väsjohn $1)',
 'version-license' => 'Lėzänz',
-'version-poweredby-credits' => "Dat Wiki heh löp met '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Dat Wiki heh löp met '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'sönß wää',
 'version-poweredby-translators' => 'de Övversäzer em translatewiki.net',
 'version-credits-summary' => 'Mer bedanke ons för iehr Beidrähsch zom [[Special:Version|MediaWiki]] bei:',
@@ -4118,8 +4137,7 @@ Do sullts en [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie vun dä <i lang="en">GNU Ge
 
 # Special:SpecialPages
 'specialpages' => '{{int:nstab-special}}e',
-'specialpages-note' => '----
-* {{int:nstab-special}}e för jede Metmaacher.
+'specialpages-note' => '* {{int:nstab-special}}e för jede Metmaacher.
 * <span class="mw-specialpagerestricted">{{int:nstab-special}}e för Metmaacher met besönder Räächde.</span>
 * <span class="mw-specialpagecached">Em Zwescheshpeisher jehallde {{int:nstab-special}}e. Di künnte ovverhollt sind.</span>',
 'specialpages-group-maintenance' => 'Waadungsleste',
@@ -4342,4 +4360,21 @@ Wat De doh enjiß, kütt met Dingem Metmaachername un Dingem Brauser op die Sigg
 'limitreport-expensivefunctioncount' => 'Oproofe vun „düüre“ Fonxjuhne em Paaser',
 'limitreport-expensivefunctioncount-value' => '$1 vun $2',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Schablone üvverpröfe',
+'expand_templates_intro' => 'Heh di Extrasigg nemmp Täx aan un lühß alle Oproofe vun <code lang="en"><nowiki>{{</nowiki>&nbsp;…&nbsp;}}</code> Klammere op.
+Och verschaachtelte.
+Derbei jehüüere enschtalleete Paaserfunxjuhne, alsu esu jät wi
+<code lang="en"><nowiki>{{</nowiki>#language:…}}</code>, udder Varijaable, dat es esu jät wi
+<code lang="en"><nowiki>{{</nowiki>CURRENTDAY}}</code>.',
+'expand_templates_title' => 'Dä Siggetitel, also wat för {{FULLPAGENAME}} uew. enjeföllt weed:',
+'expand_templates_input' => 'Wat De üvverpröfe wells:',
+'expand_templates_output' => 'Wat erus kütt es',
+'expand_templates_xml_output' => 'XML ußjevve',
+'expand_templates_ok' => 'Lohß Jonn!',
+'expand_templates_remove_comments' => 'De ėnner Kommentare fottloohße',
+'expand_templates_remove_nowiki' => 'Donn de <nowiki>-Befähle ongerdröcke en dämm, wadd_eruß kütt',
+'expand_templates_generate_xml' => 'Och dä XML-Parser-Boum zeije',
+'expand_templates_preview' => 'Vör-Aansich',
+
 );
index 09da332..bca1072 100644 (file)
@@ -83,7 +83,7 @@ $magicWords = array(
        'notoc'                     => array( '0', '_NAVEROKTUNE_', '__NOTOC__' ),
        'nogallery'                 => array( '0', '_GALERÎTUNE_', '__NOGALLERY__' ),
        'toc'                       => array( '0', '_NAVEROK_', '__TOC__' ),
-       'currentmonth1'             => array( '1', 'MEHANIHA1', 'CURRENTMONTH1' ),
+       'currentmonth1'             => array( '1', 'MEHA_NIHA_1', 'CURRENTMONTH1' ),
        'currentday'                => array( '1', 'ROJA_NIHA', 'CURRENTDAY' ),
        'currentday2'               => array( '1', 'ROJA_NIHA2', 'CURRENTDAY2' ),
        'currenttime'               => array( '1', 'DEMA_NIHA', 'CURRENTTIME' ),
@@ -105,6 +105,8 @@ $magicWords = array(
        'language'                  => array( '0', '#ZIMAN', '#LANGUAGE:' ),
        'numberofadmins'            => array( '1', 'HEJMARA_RÊVEBERAN', 'NUMBEROFADMINS' ),
        'special'                   => array( '0', 'taybet', 'special' ),
+       'pagesincategory_all'       => array( '0', 'hemû', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'rûpel', 'pages' ),
 );
 
 $messages = array(
@@ -350,8 +352,6 @@ $messages = array(
 'ok' => 'Baş e',
 'retrievedfrom' => 'Ji "$1" hatiye standin.',
 'youhavenewmessages' => '$1 yên te hene ($2).',
-'newmessageslink' => 'Peyamên nû',
-'newmessagesdifflink' => 'cudayî ji guhertoya berê',
 'youhavenewmessagesfromusers' => 'Ji {{PLURAL:$3|bikarhênerekê/î|$3 bikarhêneran}}, ji bo te $1 ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|peyameke nû heye|peyamên nû hene}}',
 'newmessagesdifflinkplural' => '{{PLURAL:$1|guherandin|guherandinên dawî}}',
@@ -878,8 +878,6 @@ Sedema qedexekirina $3 ev e: ''$2''",
 'preferences' => 'Tercîhên min',
 'mypreferences' => 'Tercihên min',
 'prefs-edits' => 'Hejmarê guherandinan:',
-'prefsnologin' => 'Xwe tomar nekir',
-'prefsnologintext' => 'Tu gireke xwe <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} qeydbikê]</span> ji bo guherandina tercihên bikarhêneran.',
 'changepassword' => 'Şîfreyê biguherîne',
 'prefs-skin' => 'Pêste',
 'skin-preview' => 'Pêşdîtin',
@@ -1056,6 +1054,7 @@ Sedema qedexekirina $3 ev e: ''$2''",
 'recentchanges-legend' => 'Vebijarkên guherandinên dawî',
 'recentchanges-summary' => 'Guhertinên herî dawî yên wîkiyê li ser vê rûpelê bişopîne.',
 'recentchanges-label-minor' => 'Ev guhertineka biçûk e',
+'recentchanges-legend-newpage' => '$1 - rûpela nû',
 'rcnote' => "Jêr {{PLURAL:$1|guherandinek|'''$1''' guherandinên dawî}} di {{PLURAL:$2|rojê|'''$2''' rojên dawî}} de ji $3 şûnde tên nîşan dan.",
 'rclistfrom' => 'Guherandinên ji $1 şûnde nîşan bide',
 'rcshowhideminor' => 'Guherandinên biçûk $1',
@@ -2025,7 +2024,7 @@ Ji ber ku girêdaneke derve di wê rûpelê de heye ev pirsgirêk pêk hat.',
 'exif-iimcategory-wea' => 'Hewa',
 
 # External editor support
-'edit-externally-help' => '(Ji bo agahîyên zav [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] li vir binêre)',
+'edit-externally-help' => '(Ji bo agahîyên zav [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] li vir binêre)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'hemû',
@@ -2124,8 +2123,7 @@ Ji kerema xwe zanibe ku tu bi rastî dixwazî vê rûpelê dîsa çêkî.",
 
 # Special:SpecialPages
 'specialpages' => 'Rûpelên taybet',
-'specialpages-note' => '----
-* Rûpelên taybetî ji her kesan ra
+'specialpages-note' => '* Rûpelên taybetî ji her kesan ra
 * <strong class="mw-specialpagerestricted">Rûpelên taybetî ji bikarhêneran bi mafên zêdetir ra</strong>',
 'specialpages-group-other' => 'Rûpelên taybetî yên din',
 'specialpages-group-login' => 'Têkeve',
@@ -2184,4 +2182,9 @@ Ji kerema xwe zanibe ku tu bi rastî dixwazî vê rûpelê dîsa çêkî.",
 'searchsuggest-search' => 'Lêgerîn',
 'searchsuggest-containing' => 'dihundirîne...',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Encam',
+'expand_templates_ok' => 'Baş e',
+'expand_templates_preview' => 'Pêşdîtin',
+
 );
index 99fa094..6fd75d9 100644 (file)
@@ -60,14 +60,13 @@ $namespaceAliases = array(
 );
 
 $specialPageAliases = array(
-       'Activeusers'               => array( 'DevnydhyoryonByw' ),
+       'Activeusers'               => array( 'DevnydhyoryonVyw' ),
        'Allmessages'               => array( 'OllMessajys' ),
        'Allpages'                  => array( 'OllFolennow' ),
        'Ancientpages'              => array( 'FolennowKoth' ),
        'Badtitle'                  => array( 'TitelDrog' ),
        'Blankpage'                 => array( 'FolenWag' ),
        'Block'                     => array( 'Difenna' ),
-       'Blockme'                   => array( 'GulOwDifen' ),
        'Booksources'               => array( 'PennfentynyowLyver' ),
        'BrokenRedirects'           => array( 'DaskedyansowTerrys' ),
        'Categories'                => array( 'Klassys' ),
@@ -79,10 +78,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'FormyaAkont' ),
        'Deadendpages'              => array( 'FolennowFordhDhall' ),
        'DeletedContributions'      => array( 'KevrohowDiles' ),
-       'Disambiguations'           => array( 'Diamstyryansow' ),
        'DoubleRedirects'           => array( 'DaswedyansowDewblek' ),
-       'EditWatchlist'             => array( 'ChanjyaOwRolGolya' ),
+       'EditWatchlist'             => array( 'ChanjyaOwRolWolya' ),
        'Emailuser'                 => array( 'EbostyaDevnydhyer' ),
+       'ExpandTemplates'           => array( 'BrasheSkantlyns' ),
        'Export'                    => array( 'Esperthi' ),
        'Fewestrevisions'           => array( 'AnLyhaAmendyansow' ),
        'Filepath'                  => array( 'HynsAnFolen' ),
@@ -153,36 +152,36 @@ $specialPageAliases = array(
        'Wantedfiles'               => array( 'RestrennowHwansus' ),
        'Wantedpages'               => array( 'FolennowHwansus' ),
        'Wantedtemplates'           => array( 'SkantlynsHwansus' ),
-       'Watchlist'                 => array( 'Rol_golya' ),
+       'Watchlist'                 => array( 'Rol_wolya' ),
        'Whatlinkshere'             => array( 'OwKevrennaOmma' ),
        'Withoutinterwiki'          => array( 'HebInterwiki' ),
 );
 
 $magicWords = array(
-       'redirect'                  => array( '0', '#DASWEDYANS', '#REDIRECT' ),
+       'redirect'                  => array( '0', '#DASKEDYANS', '#REDIRECT' ),
        'numberofpages'             => array( '1', 'NIVERAFOLENNOW', 'NUMBEROFPAGES' ),
        'numberofarticles'          => array( '1', 'NIVERAERTHYGLOW', 'NUMBEROFARTICLES' ),
        'numberoffiles'             => array( '1', 'NIVERARESTRENNOW', 'NUMBEROFFILES' ),
        'numberofusers'             => array( '1', 'NIVERADHEVNYDHYORYON', 'NUMBEROFUSERS' ),
-       'numberofactiveusers'       => array( '1', 'NIVERADHEVNYDHYORYONVEW', 'NUMBEROFACTIVEUSERS' ),
+       'numberofactiveusers'       => array( '1', 'NIVERADHEVNYDHYORYONVYW', 'NUMBEROFACTIVEUSERS' ),
        'numberofedits'             => array( '1', 'NIVERAJANJYOW', 'NUMBEROFEDITS' ),
-       'numberofviews'             => array( '1', 'NIVERAWELOW', 'NUMBEROFVIEWS' ),
+       'numberofviews'             => array( '1', 'NIVERAWELYANSOW', 'NUMBEROFVIEWS' ),
        'pagename'                  => array( '1', 'HANOWANFOLEN', 'PAGENAME' ),
        'fullpagename'              => array( '1', 'HANOWLEUNANFOLEN', 'FULLPAGENAME' ),
        'img_thumbnail'             => array( '1', 'skeusennik', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'skeusennik=$1', 'thumbnail=$1', 'thumb=$1' ),
        'img_right'                 => array( '1', 'dyhow', 'right' ),
-       'img_left'                  => array( '1', 'cledh', 'left' ),
+       'img_left'                  => array( '1', 'kledh', 'left' ),
        'img_none'                  => array( '1', 'nagonan', 'none' ),
-       'img_center'                => array( '1', 'cresel', 'center', 'centre' ),
+       'img_center'                => array( '1', 'kresel', 'center', 'centre' ),
        'img_framed'                => array( '1', 'fremys', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'hebfram', 'frameless' ),
        'img_page'                  => array( '1', 'folen=$1', 'folen_$1', 'page=$1', 'page $1' ),
        'img_top'                   => array( '1', 'gwartha', 'top' ),
-       'img_text_top'              => array( '1', 'text-gwartha', 'text-top' ),
-       'img_middle'                => array( '1', 'cres', 'middle' ),
+       'img_text_top'              => array( '1', 'tekst-gwartha', 'text-top' ),
+       'img_middle'                => array( '1', 'kres', 'middle' ),
        'img_bottom'                => array( '1', 'goles', 'bottom' ),
-       'img_text_bottom'           => array( '1', 'text-goles', 'text-bottom' ),
+       'img_text_bottom'           => array( '1', 'tekst-goles', 'text-bottom' ),
        'img_link'                  => array( '1', 'kevren=$1', 'link=$1' ),
        'sitename'                  => array( '1', 'HANOWANWIASVA', 'SITENAME' ),
        'pageid'                    => array( '0', 'IDANFOLEN', 'PAGEID' ),
@@ -190,18 +189,18 @@ $magicWords = array(
        'servername'                => array( '0', 'HANOWANSERVYER', 'SERVERNAME' ),
        'grammar'                   => array( '0', 'GRAMASEK:', 'GRAMMAR:' ),
        'fullurl'                   => array( '0', 'URLLEUN:', 'FULLURL:' ),
-       'displaytitle'              => array( '1', 'DISQWEDHESANTITEL', 'DISPLAYTITLE' ),
+       'displaytitle'              => array( '1', 'DISKWEDHESANTITEL', 'DISPLAYTITLE' ),
        'language'                  => array( '0', '#YETH:', '#LANGUAGE:' ),
        'numberofadmins'            => array( '1', 'NIVERAVENYSTRORYON', 'NUMBEROFADMINS' ),
        'special'                   => array( '0', 'arbennek', 'special' ),
-       'filepath'                  => array( '0', 'HENSANFOLEN:', 'FILEPATH:' ),
-       'hiddencat'                 => array( '1', '__CLASSCUDHYS__', '__HIDDENCAT__' ),
-       'pagesincategory'           => array( '1', 'RESTRENNOWYNCLASS', 'PAGESINCATEGORY', 'PAGESINCAT' ),
-       'pagesize'                  => array( '1', 'MENSANRESTREN', 'PAGESIZE' ),
+       'filepath'                  => array( '0', 'HYNSANFOLEN:', 'FILEPATH:' ),
+       'hiddencat'                 => array( '1', '__KLASSKUDHYS__', '__HIDDENCAT__' ),
+       'pagesincategory'           => array( '1', 'RESTRENNOWYNKLASS', 'PAGESINCATEGORY', 'PAGESINCAT' ),
+       'pagesize'                  => array( '1', 'MYNSANRESTREN', 'PAGESIZE' ),
        'index'                     => array( '1', '__MENEGVA__', '__INDEX__' ),
        'noindex'                   => array( '1', '__HEBMENEGVA__', '__NOINDEX__' ),
        'numberingroup'             => array( '1', 'NIVERYNBAGAS', 'NUMBERINGROUP', 'NUMINGROUP' ),
-       'url_path'                  => array( '0', 'HENS', 'PATH' ),
+       'url_path'                  => array( '0', 'HYNS', 'PATH' ),
        'pagesincategory_all'       => array( '0', 'oll', 'all' ),
        'pagesincategory_pages'     => array( '0', 'folennow', 'pages' ),
 );
@@ -451,8 +450,6 @@ $1',
 'ok' => 'Sur',
 'retrievedfrom' => 'Daskevys dhyworth "$1"',
 'youhavenewmessages' => "$1 a'gas beus ($2).",
-'newmessageslink' => 'Messajys nowyth',
-'newmessagesdifflink' => 'chanj diwettha',
 'youhavenewmessagesfromusers' => "Hwi a'gas beus $1 dhyworth {{PLURAL:$3|devnydhyer aral|$3 devnydhyer}} ($2).",
 'youhavenewmessagesmanyusers' => "Hwi a'gas beus $1 dhyworth lies devnydhyer ($2).",
 'newmessageslinkplural' => '{{PLURAL:$1|messach nowyth|messajys nowyth}}',
@@ -971,6 +968,7 @@ Ny dhiskwedhir agas trigva ebost pan gestaffo devnydhyoryon erel dhywgh.',
 'recentchanges-label-minor' => 'Chanj byhan yw hemma',
 'recentchanges-label-bot' => 'Gwrys veu an chanj-ma gans bott',
 'recentchanges-label-unpatrolled' => 'Ny veu an chanj-ma patrolyes hwath',
+'recentchanges-legend-newpage' => '$1 - folen nowyth',
 'rcnote' => "A-woles yma {{PLURAL:$1|'''1''' janj|an '''$1''' chanjyow diwettha}} y'n {{PLURAL:$2|dydh|'''$2''' dydh}} diwettha, a-dhia $5, $4.",
 'rclistfrom' => 'Diskwedhes chanjyow nowyth yn unn dhalleth dhyworth $1.',
 'rcshowhideminor' => '$1 chanjyow byhan',
index bac3319..3f97368 100644 (file)
@@ -297,8 +297,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => '"$1" булагынан алынды',
 'youhavenewmessages' => 'Сизге $1 ($2) бар.',
-'newmessageslink' => 'жаңы билдирүүлөр',
-'newmessagesdifflink' => 'соңку өзгөрүү',
 'youhavenewmessagesfromusers' => 'Сиз {{PLURAL:$3|колдонуучудан|$3 колдонуучу}} $1 алдыңыз ($2).',
 'youhavenewmessagesmanyusers' => 'Көп колдонуучулардан сиз $1 алдыңыз ($2).',
 'newmessageslinkplural' => 'жаңы {{PLURAL:$1|билдирүү| билдирүүлөр}}',
@@ -784,7 +782,6 @@ IP дарегиңиз бул барактын оңдоо тарыхына жаз
 'preferences' => 'Ырастоолор',
 'mypreferences' => 'Ырастоолор',
 'prefs-edits' => 'Өзгөртүүлөрдүн саны',
-'prefsnologin' => 'Системге кирген жоксуз',
 'changepassword' => 'Сырсөздү өзгөртүү',
 'prefs-skin' => 'Тема',
 'skin-preview' => 'Алдын ала көрүү',
@@ -1676,7 +1673,7 @@ To include a file in a page, use a link in one of the following forms:
 
 # External editor support
 'edit-externally' => 'Бул файлды сырткы программа колдонуу аркылуу оңдоо',
-'edit-externally-help' => '(Толук маалымат алуу үчүн [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] барагына кайрылсаңыз болот)',
+'edit-externally-help' => '(Толук маалымат алуу үчүн [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] барагына кайрылсаңыз болот)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'баары',
index 178251c..df82069 100644 (file)
@@ -78,7 +78,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Paginae_veterrimae' ),
        'Blankpage'                 => array( 'Pagina_vacua' ),
        'Block'                     => array( 'Usorem_obstruere' ),
-       'Blockme'                   => array( 'Usor_obstructus' ),
        'Booksources'               => array( 'Librorum_fontes' ),
        'BrokenRedirects'           => array( 'Redirectiones_fractae' ),
        'Categories'                => array( 'Categoriae' ),
@@ -88,9 +87,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Rationem_creare' ),
        'Deadendpages'              => array( 'Paginae_sine_nexu' ),
        'DeletedContributions'      => array( 'Conlationes_deletae', 'Conlationes_usoris_deletae' ),
-       'Disambiguations'           => array( 'Paginae_disambiguationis', 'Disambiguationes' ),
        'DoubleRedirects'           => array( 'Redirectiones_duplices' ),
        'Emailuser'                 => array( 'Litteras_electronicas_usori_mittere', 'Littera_electronica' ),
+       'ExpandTemplates'           => array( 'Formulas_resolvere' ),
        'Export'                    => array( 'Exportare', 'Paginas_exportare' ),
        'Fewestrevisions'           => array( 'Paginae_minime_mutatae' ),
        'FileDuplicateSearch'       => array( 'Quaerere_fasciculos_duplices', 'Quaerere_imagines_duplices' ),
@@ -417,12 +416,10 @@ Vide [[Special:Version|paginam versionis]].',
 'ok' => 'Age',
 'retrievedfrom' => 'Receptum de "$1"',
 'youhavenewmessages' => 'Habes $1 ($2).',
-'newmessageslink' => 'nuntia nova',
-'newmessagesdifflink' => 'dissimilia post mutationem ultimam',
 'youhavenewmessagesfromusers' => 'Habes $1 ab {{PLURAL:$3|uno usore alio|usoribus $3}} ($2).',
 'youhavenewmessagesmanyusers' => 'Habes $1 a multis usoribus ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|nuntium novum|nuntia nova}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|dissimilitudo|dissimilitudines}} post mutationem ultimam',
+'newmessageslinkplural' => '{{PLURAL:$1|nuntium novum|999=nuntia nova}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|dissimilitudo|999=dissimilitudines}} post mutationem ultimam',
 'youhavenewmessagesmulti' => 'Habes nuntia nova in $1',
 'editsection' => 'recensere',
 'editold' => 'recensere',
@@ -824,12 +821,13 @@ Titulus: '''({{int:cur}})''' = dissimilis ab emendatione novissima,
 'revdelete-show-file-submit' => 'Sic',
 'revdelete-selected' => "'''{{PLURAL:$2|Emendatio selecta|Emendationes selectae}} paginae [[:$1]]:'''",
 'revdelete-legend' => 'Modificare cohibitiones visibilitatis',
-'revdelete-hide-text' => 'Celare textum emendationis',
+'revdelete-hide-text' => 'Textus emendationis',
 'revdelete-hide-image' => 'Celare contentum fasciculi',
-'revdelete-hide-comment' => 'Celare summarium emendationis',
+'revdelete-hide-comment' => 'Summarium emendationis',
+'revdelete-hide-user' => 'Nomen usoris/locus IP',
 'revdelete-radio-same' => 'non mutare',
-'revdelete-radio-set' => 'Ita vero',
-'revdelete-radio-unset' => 'Minime',
+'revdelete-radio-set' => 'Celare',
+'revdelete-radio-unset' => 'Visibiles/visibilia',
 'revdelete-log' => 'Causa:',
 'revdel-restore' => 'visibilitatem mutare',
 'revdel-restore-deleted' => 'Recensiones deletae',
@@ -897,6 +895,7 @@ Titulus: '''({{int:cur}})''' = dissimilis ab emendatione novissima,
 'searchprofile-articles-tooltip' => 'Quaerere in $1',
 'searchprofile-project-tooltip' => 'Quaerere in $1',
 'searchprofile-images-tooltip' => 'Fasciculos quaerere',
+'searchprofile-everything-tooltip' => 'Omnia perscrutari (etiam paginae disputationis)',
 'searchprofile-advanced-tooltip' => 'In spatiis nominalibus accommotis quaerere',
 'search-result-size' => '$1 ({{PLURAL:$2|1 verbum|$2 verba}})',
 'search-result-score' => 'Gravitas: $1%',
@@ -932,8 +931,6 @@ Conare praefixare tua inquisitionem cum ''all:'' ut quaeras contenta omnia (pagi
 'preferences' => 'Praeferentiae',
 'mypreferences' => 'Praeferentiae',
 'prefs-edits' => 'Numerus recensionum:',
-'prefsnologin' => 'Conventum non est apertum',
-'prefsnologintext' => '<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Conventum aperire]</span> debes ad praeferentias tuas modificandum.',
 'changepassword' => 'Tesseram mutare',
 'prefs-skin' => 'Aspectum',
 'skin-preview' => 'Praevisum',
@@ -1145,6 +1142,8 @@ Si vis id dare, opera tua tibi ascribentur.',
 'recentchanges-label-newpage' => 'Haec recensio paginam novam creavit',
 'recentchanges-label-minor' => 'Haec est recensio minor',
 'recentchanges-label-bot' => 'Hanc emendationem automaton fecit',
+'recentchanges-label-unpatrolled' => 'Haec recensio nondum est examinata',
+'recentchanges-legend-newpage' => '(vide etiam [[Special:NewPages|indicem paginarum novarum]])',
 'rcnote' => "Subter {{PLURAL:$1|est '''1''' nuper mutatum|sunt '''$1''' nuperrime mutata}} in {{PLURAL:$2|die proximo|'''$2''' diebus proximis}} ex $5, $4.",
 'rcnotefrom' => "Subter sunt '''$1''' nuperrime mutata in proxima '''$2''' die.",
 'rclistfrom' => 'Monstrare mutata nova incipiens ab $1',
@@ -1446,7 +1445,7 @@ Adspectum graciliorem potes facere modum indicum, nomen usoris (cave litteras ma
 'allnotinnamespace' => 'Omnes paginae (quibus in spatio nominali $1 exclusis)',
 'allpagesprev' => 'Superior',
 'allpagesnext' => 'Proxima',
-'allpagessubmit' => 'Ire',
+'allpagessubmit' => 'Adhibere',
 'allpagesprefix' => 'Monstrare paginas quibus est praeverbium:',
 'allpagesbadtitle' => 'Nomen paginae datum fuit invalidum aut praverbium interlinguale vel interviciale habuit. Fortasse insunt una aut plus litterarum quae in titulis non possunt inscribier.',
 'allpages-bad-ns' => 'Non est spatium nominale "$1" apud {{grammar:accusative|{{SITENAME}}}}.',
@@ -1473,6 +1472,7 @@ Vide etiam [[Special:WantedCategories|categorias desideratas]].',
 'linksearch-pat' => 'Quaerere per exemplar:',
 'linksearch-ns' => 'Spatium nominale:',
 'linksearch-ok' => 'Quaerere',
+'linksearch-line' => '$1 necta est a $2',
 
 # Special:ListUsers
 'listusers-submit' => 'Monstrare',
@@ -1715,6 +1715,7 @@ Si pagina nova cum ipso nomine post deletionem creata est, emendationes restitut
 # Namespace form on various pages
 'namespace' => 'Spatium nominale:',
 'invert' => 'Selectionem invertere',
+'namespace_association' => 'Spatium nominale pertinens',
 'blanknamespace' => '(principale)',
 
 # Contributions
@@ -2289,7 +2290,7 @@ Paginae nomen petitum "[[:$1]]" iam existit. Vin tu eam delere ut pagina illic m
 
 # External editor support
 'edit-externally' => 'Hunc fasciculum in programmate externali recensere',
-'edit-externally-help' => '(Vide et [//www.mediawiki.org/wiki/Manual:External_editors paginas adiutorias] programmatis externalis)',
+'edit-externally-help' => '(Vide et [https://www.mediawiki.org/wiki/Manual:External_editors paginas adiutorias] programmatis externalis)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'omnes',
@@ -2425,6 +2426,7 @@ Quaesumus, adfirma ut iterum hanc paginam crees.",
 
 # Special:Tags
 'tags' => 'Affixa mutationum validarum',
+'tag-filter' => '[[Special:Tags|Tag]] Colum:',
 'tag-filter-submit' => 'Filtrum',
 'tags-title' => 'Affixa',
 'tags-edit' => 'recensere',
@@ -2462,6 +2464,7 @@ Quaesumus, adfirma ut iterum hanc paginam crees.",
 
 # Search suggestions
 'searchsuggest-search' => 'Quaerere',
+'searchsuggest-containing' => 'continens...',
 
 # API errors
 'api-error-empty-file' => 'Fasciculus inmissus vacuus est.',
@@ -2472,4 +2475,7 @@ Quaesumus, adfirma ut iterum hanc paginam crees.",
 'api-error-mustbeloggedin' => 'Ad fasciculos inmittendos conventum aperire necesse est.',
 'api-error-unknownerror' => 'Error incognitus: "$1".',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Formulas resolvere',
+
 );
index e33bc4d..7e31f50 100644 (file)
@@ -80,7 +80,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'HojasViejas' ),
        'Blankpage'                 => array( 'VaziarHoja' ),
        'Block'                     => array( 'Bloquear' ),
-       'Blockme'                   => array( 'Bloquearme' ),
        'Booksources'               => array( 'FuentesDeLivros' ),
        'BrokenRedirects'           => array( 'DireksionesBozeadas' ),
        'Categories'                => array( 'Katēggorías' ),
@@ -91,10 +90,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'KrîarCuento' ),
        'Deadendpages'              => array( 'HojasSinAtamientos' ),
        'DeletedContributions'      => array( 'AjustamientosEfassados' ),
-       'Disambiguations'           => array( 'Apartamiento_de_senso' ),
        'DoubleRedirects'           => array( 'DireksionesDobles' ),
        'EditWatchlist'             => array( 'TrocarLista_de_Akavidamiento' ),
        'Emailuser'                 => array( 'MandarLetralUsador' ),
+       'ExpandTemplates'           => array( 'AlargarXabblones' ),
        'Export'                    => array( 'AktarearAfuera' ),
        'Fewestrevisions'           => array( 'MankoEddisyones' ),
        'FileDuplicateSearch'       => array( 'BuscarDosyasDobles' ),
@@ -423,8 +422,6 @@ $messages = array(
 'ok' => 'DE ACORDDO',
 'retrievedfrom' => 'Acòjido del adhresso "$1"',
 'youhavenewmessages' => 'Tienes $1 ($2).',
-'newmessageslink' => 'mesajes nuevos',
-'newmessagesdifflink' => 'el trocamiento de alcabo',
 'youhavenewmessagesmulti' => 'Tienes messajes nuevos en $1',
 'editsection' => 'troca',
 'editold' => 'troca',
@@ -1177,7 +1174,7 @@ Los otros campos se van a guardar por defecto.
 
 # External editor support
 'edit-externally' => 'Trocar esto arxivo usando una aplicación eksterna',
-'edit-externally-help' => '(Melda las [//www.mediawiki.org/wiki/Manual:External_editors enstruksiones de configuración] -en inglés- para saber más)',
+'edit-externally-help' => '(Melda las [https://www.mediawiki.org/wiki/Manual:External_editors enstruksiones de configuración] -en inglés- para saber más)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todos',
index 3838aaf..cea0406 100644 (file)
@@ -57,7 +57,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Falschen_Titel' ),
        'Blankpage'                 => array( 'Eidel_Säit' ),
        'Block'                     => array( 'Spären' ),
-       'Blockme'                   => array( 'Mech_spären' ),
        'Booksources'               => array( 'Bicher_mat_hirer_ISBN_sichen' ),
        'BrokenRedirects'           => array( 'Futtis_Viruleedungen' ),
        'Categories'                => array( 'Kategorien' ),
@@ -69,10 +68,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Benotzerkont_opmaachen' ),
        'Deadendpages'              => array( 'Sakgaasse-Säiten' ),
        'DeletedContributions'      => array( 'Geläschte_Kontributiounen' ),
-       'Disambiguations'           => array( 'Homonymie' ),
        'DoubleRedirects'           => array( 'Duebel_Viruleedungen' ),
        'EditWatchlist'             => array( 'Iwwerwaachungslëscht_änneren' ),
        'Emailuser'                 => array( 'Dësem_Benotzer_eng_E-Mail_schécken' ),
+       'ExpandTemplates'           => array( 'Schablounen_erweideren' ),
        'Export'                    => array( 'Exportéieren' ),
        'Fewestrevisions'           => array( 'Säite_mat_de_mannsten_Ännerungen' ),
        'FileDuplicateSearch'       => array( 'No_duebele_Fichieren_sichen' ),
@@ -116,6 +115,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Protegéiert_Säiten' ),
        'Protectedtitles'           => array( 'Gespaarte_Säiten' ),
        'Randompage'                => array( 'Zoufälleg_Säit' ),
+       'RandomInCategory'          => array( 'Zoufälleg_Säit_aus_der_Kategorie' ),
        'Randomredirect'            => array( 'Zoufälleg_Viruleedung' ),
        'Recentchanges'             => array( 'Rezent_Ännerungen' ),
        'Recentchangeslinked'       => array( 'Ännerungen_op_verlinkte_Säiten' ),
@@ -460,12 +460,10 @@ Kuckt d'[[Special:Version|Versiounssäit]].",
 'ok' => 'OK',
 'retrievedfrom' => 'Vun „$1“',
 'youhavenewmessages' => 'Dir hutt $1 ($2).',
-'newmessageslink' => 'nei Messagen',
-'newmessagesdifflink' => 'Lescht Ännerung',
 'youhavenewmessagesfromusers' => 'Dir hutt $1 vu(n) {{PLURAL:$3|engem anere Benotzer|$3 anere Benotzer}} ($2).',
 'youhavenewmessagesmanyusers' => 'Dir hutt $1 vu ville Benotzer ($2)',
-'newmessageslinkplural' => '{{PLURAL:$1|een neie Message|nei Message}}',
-'newmessagesdifflinkplural' => 'lescht {{PLURAL:$1|Ännerung|Ännerungen}}',
+'newmessageslinkplural' => '{{PLURAL:$1|een neie Message|999=nei Messagen}}',
+'newmessagesdifflinkplural' => 'lescht {{PLURAL:$1|Ännerung|999=Ännerungen}}',
 'youhavenewmessagesmulti' => 'Dir hutt nei Messagen op $1',
 'editsection' => 'änneren',
 'editold' => 'änneren',
@@ -517,8 +515,8 @@ All Spezialsäiten déi et gëtt, sinn op der [[Special:SpecialPages|{{int:speci
 # General errors
 'error' => 'Feeler',
 'databaseerror' => 'Datebank Feeler',
-'databaseerror-text' => 'Et ass ee Feeler bäi enger Ufro un Datebank geschitt. Dat deit op e Feeler an der Software.',
-'databaseerror-textcl' => "Et ass e Feeler bäi enger Ufro un d'Datebank geschitt.",
+'databaseerror-text' => 'Et ass ee Feeler bei enger Ufro un Datebank geschitt. Dat deit op e Feeler an der Software.',
+'databaseerror-textcl' => "Et ass e Feeler bei enger Ufro un d'Datebank geschitt.",
 'databaseerror-query' => 'Ufro: $1',
 'databaseerror-function' => 'Funktioun: $1',
 'databaseerror-error' => 'Feeler: $1',
@@ -540,7 +538,7 @@ Mellt dëst w.e.g. bei engem [[Special:ListUsers/sysop|Administrateur]] a vergie
 'internalerror' => 'Interne Feeler',
 'internalerror_info' => 'Interne Feeler: $1',
 'fileappenderrorread' => '"$1" konnt während dem Derbäisetze net gelies ginn.',
-'fileappenderror' => '"$1" konnt net bäi "$2" derbäigesat ginn.',
+'fileappenderror' => '"$1" konnt net bei "$2" derbäigesat ginn.',
 'filecopyerror' => 'De Fichier "$1" konnt net op "$2" kopéiert ginn.',
 'filerenameerror' => 'De Fichier "$1" konnt net op "$2" ëmbenannt ginn.',
 'filedeleteerror' => 'De Fichier "$1" konnt net geläscht ginn.',
@@ -594,10 +592,11 @@ Den Administrateur den d\'Schreiwe gespaart huet, huet dës Erklärung uginn: "$
 'invalidtitle-knownnamespace' => 'Net valabelen Titel mam Nummraum "$2" a mam Text "$3"',
 'invalidtitle-unknownnamespace' => 'Net valabelen Titel mat der onbekannter Nummraum-Zuel $1 a mam Text "$2"',
 'exception-nologin' => 'Net ageloggt',
-'exception-nologin-text' => 'Dës Säit oder Aktioun erfuerdert datt Dir op dëser Wiki ageloggt sidd.',
+'exception-nologin-text' => '[[Special:Userlogin|Loggt Iech w.e.g. a]] fir op dës Säit oder dës Aktioun zougräifen ze kënnen.',
+'exception-nologin-text-manual' => 'Dir musst Iech $1 fir dës Säit kucken ze kënne respektiv fir dës Aktioun ze maachen.',
 
 # Virus scanner
-'virus-badscanner' => "Schlecht Configuratioun: onbekannte  Virescanner: ''$1''",
+'virus-badscanner' => "Schlecht Konfiguratioun: onbekannte Virescanner: ''$1''",
 'virus-scanfailed' => 'De Scan huet net funktionéiert (Code $1)',
 'virus-unknownscanner' => 'onbekannten Antivirus:',
 
@@ -634,14 +633,14 @@ Vergiesst net fir Är [[Special:Preferences|{{SITENAME}} Astellungen]] z'ännere
 'userlogout' => 'Ausloggen',
 'notloggedin' => 'Net ageloggt',
 'userlogin-noaccount' => 'Hutt Dir kee Benotzerkont?',
-'userlogin-joinproject' => 'Maacht mat bäi {{SITENAME}}',
+'userlogin-joinproject' => 'Maacht mat bei {{SITENAME}}',
 'nologin' => 'Hutt Dir kee Benotzerkont? $1.',
 'nologinlink' => 'Neie Benotzerkont maachen',
 'createaccount' => 'Neie Kont opmaachen',
 'gotaccount' => "Dir hutt schonn e Benotzerkont? '''$1'''.",
 'gotaccountlink' => 'Umellen',
 'userlogin-resetlink' => "Hutt Dir d'Detailer vun Ärem Login vergiess?",
-'userlogin-resetpassword-link' => 'Setzt Äert Passwuert zréck',
+'userlogin-resetpassword-link' => 'Hutt Dir Äert Passwuert vergiess?',
 'helplogin-url' => 'Help:Aloggen',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hëllef beim Aloggen]]',
 'userlogin-loggedin' => 'Dir sidd schonn als {{GENDER:$1|$1}} ageloggt.
@@ -707,7 +706,8 @@ Wann een aneren dës Ufro sollt gemaach hunn oder wann Dir Iech an der Zwëschen
 'passwordsent' => 'Een neit Passwuert gouf un déi fir de Benotzer "$1" gespäichert E-Mailadress geschéckt.
 Mellt Iech w.e.g. domat un, soubal Dir et kritt hutt.',
 'blocked-mailpassword' => "Déi vun Iech benotzten IP-Adress ass fir d'Ännere vu Säite gespaart. Fir Mëssbrauch ze verhënneren, gouf d'Méiglechkeet fir een neit Passwuert unzefroen och gespaart.",
-'eauthentsent' => "Eng Confirmatiouns-E-Mail gouf un déi Adress geschéckt déi Dir uginn hutt.<br />
+'eauthentsent' => "Eng Confirmatiouns-E-Mail gouf un déi Adress geschéckt déi Dir uginn hutt.
+
 Ier iergendeng E-Mail vun anere Benotzer op dee Kont geschéckt ka ginn, musst Dir als éischt d'Instructiounen an der Confirmatiouns-E-Mail befollegen, fir ze bestätegen datt de Kont wierklech Ären eegenen ass.",
 'throttled-mailpassword' => "An {{PLURAL:$1|der leschter Stonn|de leschte(n) $1 Stonnen}} eng E-Mail verschéckt fir d'Passwuert zréckzesetzen.
 Fir de Mëssbrauch vun dëser Funktioun ze verhënneren kann nëmmen all {{PLURAL:$1|Stonn|$1 Stonnen}} sou eng Mail verschéckt ginn.",
@@ -715,10 +715,10 @@ Fir de Mëssbrauch vun dëser Funktioun ze verhënneren kann nëmmen all {{PLURA
 'acct_creation_throttle_hit' => 'Visiteure vun dëser Wiki déi Är IP-Adress hu {{PLURAL:$1|schonn $1 Benotzerkont|scho(nn) $1 Benotzerkonten}} an de leschten Deeg opgemaach, dëst ass déi maximal Zuel déi an dësem Zäitraum erlaabt ass.
 Dofir kënne Visiteure déi dës IP-Adress benotzen den Ament keng Benotzerkonten opmaachen.',
 'emailauthenticated' => 'Är E-Mail-Adress gouf den $2 ëm $3 Auer bestätegt.',
-'emailnotauthenticated' => 'Är E-Mail Adress gouf <strong>nach net confirméiert</strong>.<br />
-Dowéinst ass et bis ewell net méiglech, fir déi folgend Funktiounen E-Mailen ze schécken oder ze kréien.',
+'emailnotauthenticated' => 'Är E-Mail Adress gouf nach net confirméiert.
+Dowéinst gëtt fir keng vun dëse Funktiounen E-Maile geschéckt.',
 'noemailprefs' => 'Gitt eng E-Mailadress bei Ären Astellungen un, fir datt déi Funktioune funktionéieren.',
-'emailconfirmlink' => 'Confirméiert Ã¤r E-Mailadress w.e.g..',
+'emailconfirmlink' => 'Confirméiert Ã\84r E-Mailadress w.e.g.',
 'invalidemailaddress' => 'Dës E-Mail-Adress gëtt net akzeptéiert well se en ongëltegt Format (z. B. ongëlteg Zeechen) ze hu schéngt.
 Gitt eng valabel E-Mail-Adress an oder loosst dëst Feld eidel.',
 'cannotchangeemail' => 'Mailadresse vu Benotzerkonte kënnen op dëser Wiki net geännert ginn.',
@@ -735,7 +735,7 @@ Wann dëse Benotzerkont ongewollt ugeluecht gouf, kënnt Dir dës Noriicht einfa
 Waart w.e.g. $1 ier Dir et nach eng Kéier probéiert.',
 'login-abort-generic' => 'Dir sidd net ageloggt - Aloggen ofgebrach',
 'loginlanguagelabel' => 'Sprooch: $1',
-'suspicious-userlogout' => 'Är Ufro fir Iech auszeloggen gouf refuséiert well et sou ausgesäit wéi wa se vun engem Futtise Browser oder Proxy-Tëschespäicher kënnt.',
+'suspicious-userlogout' => 'Är Ufro fir Iech auszeloggen gouf refuséiert well et sou ausgesäit wéi wa se vun engem futtise Browser oder Proxy-Tëschespäicher kënnt.',
 'createacct-another-realname-tip' => "De richtegen Numm ass fakultativ.
 
 Wann Dir en ugitt, gëtt e benotzt fir d'Benotzerattributiounen fir Är Aarbecht zouzeuerdnen.",
@@ -996,7 +996,7 @@ Den Administrateur den d'Datebank gespaart huet, huet dës Erklärung ginn: $1",
 'template-protected' => '(gespaart)',
 'template-semiprotected' => '(gespaart fir net-ugemellten an nei Benotzer)',
 'hiddencategories' => 'Dës Säit gehéiert zu {{PLURAL:$1|1 verstoppter Kategorie|$1 verstoppte Kategorien}}:',
-'edittools' => '<!-- Dësen Text gëtt ënner dem "Ännere"Formulaire esouwéi dem "Eropluede"-Formulaire ugewisen. -->',
+'edittools' => '<!-- Dësen Text gëtt ënner dem "Ännere"-Formulaire souwéi dem "Eropluede"-Formulaire ugewisen. -->',
 'nocreatetext' => "Op {{SITENAME}} gouf d'Schafe vun neie Säite limitéiert. Dir kënnt Säiten déi scho bestinn änneren oder Iech [[Special:UserLogin|umellen]].",
 'nocreate-loggedin' => 'Dir hutt keng Berechtigung fir nei Säiten unzeleeën.',
 'sectioneditnotsupported-title' => 'Ännere vum Abschnitt gëtt net ënnerstëtzt',
@@ -1080,8 +1080,8 @@ De Benotzer $3 huet "$2" als Grond uginn.',
 *k = Kleng Ännerung.",
 'history-fieldset-title' => 'An de Versioune sichen',
 'history-show-deleted' => 'nëmmen déi geläschten',
-'histfirst' => 'eelsten',
-'histlast' => 'neisten',
+'histfirst' => 'eelst',
+'histlast' => 'neist',
 'historysize' => '({{PLURAL:$1|1 Byte|$1 Byten}})',
 'historyempty' => '(eidel)',
 
@@ -1137,22 +1137,23 @@ Dir kënnt dësen Ënnerscheed gesinn; Detailer fannt Dir am [{{fullurl:{{#Speci
 'revdelete-show-file-submit' => 'Jo',
 'revdelete-selected' => "'''{{PLURAL:$2|Gewielt Versioun|Gewielt Versioune}} vu(n) [[:$1]] :'''",
 'logdelete-selected' => "'''Ausgewielten {{PLURAL:$1|Evenement|Evenementer}} aus dem Logbuch:'''",
-'revdelete-text' => "'''Geläschte Versiounen oder aner geläschte Bestanddeeler sinn net méi ëffentlech zougänglech, si stinn awer weiderhin an der Versiounsgeschicht vun der Säit.'''
-Aner {{SITENAME}}-Administrateure kënnen de geläschten Inhalt oder aner geläschte Bestanddeeler weiderhi gesinn a restauréieren, et sief, et gouf festgeluecht, datt déi Limitatioune vum Accès och fir Administrateure gëllen.",
+'revdelete-text' => "'''Geläscht Versiounen oder aner geläscht Bestanddeeler sinn net méi ëffentlech zougänglech, si stinn awer weiderhin an der Versiounsgeschicht vun der Säit.'''
+Aner {{SITENAME}}-Administrateure kënnen de geläschten Inhalt oder aner geläscht Bestanddeeler weiderhi gesinn a restauréieren, et sief, et gouf festgeluecht, datt déi Limitatioune vum Accès och fir Administrateure gëllen.",
 'revdelete-confirm' => "Confirméiert w.e.g. datt Dir dat maache wëllt, datt Dir d'Konsequenze verstitt an datt Dir dëst an Aklang mat de [[{{MediaWiki:Policy-url}}|Richtlinne]] maacht.",
 'revdelete-suppress-text' => "Ënnerdréckung sollt '''nëmmen''' an dëse Fäll benotzt ginn:
+* Informatiounen déi beleidege kéinten
 * Net ubruechte perséinlechen Informatiounen
 *: ''Adressen, Telefonsnummeren, Sozialversécherungsnummeren asw.''",
 'revdelete-legend' => "Limitatioune fir d'Sichtbarkeet festleeën",
-'revdelete-hide-text' => 'Text vun der Versioun verstoppen',
+'revdelete-hide-text' => 'Text vun der Versioun',
 'revdelete-hide-image' => 'Bildinhalt verstoppen',
 'revdelete-hide-name' => 'Logbuch-Aktioun verstoppen',
-'revdelete-hide-comment' => 'Bemierkung verstoppen',
-'revdelete-hide-user' => 'Dem Auteur säi Benotzernumm/IP verstoppen',
+'revdelete-hide-comment' => 'Resumé vun der Ännerung',
+'revdelete-hide-user' => 'Dem Auteur säi Benotzernumm/IP-Adress',
 'revdelete-hide-restricted' => 'Donnéeën och fir Administrateuren suppriméieren geneesou wéi fir déi Aner',
 'revdelete-radio-same' => '(net änneren)',
-'revdelete-radio-set' => 'Jo',
-'revdelete-radio-unset' => 'Neen',
+'revdelete-radio-set' => 'Verstoppt',
+'revdelete-radio-unset' => 'Visibel',
 'revdelete-suppress' => 'Grond vum Läschen och fir Administrateure verstoppt',
 'revdelete-unsuppress' => 'Limitatiounen fir restauréiert Versiounen ophiewen',
 'revdelete-log' => 'Grond:',
@@ -1191,7 +1192,7 @@ Kuckt w.e.g. an de Logbicher no.",
 
 # Suppression log
 'suppressionlog' => 'Lëscht vun de verstoppten a geläschte Säiten',
-'suppressionlogtext' => 'Ënnendrënner ass eng Lëscht vun de geläschte Säiten a Spären a vun den Administrateuren verstopptem Inhalt.
+'suppressionlogtext' => 'Ënnendrënner ass eng Lëscht vun de geläschte Säiten a Spären an Inhalt dee vun den Administrateure verstoppt gouf.
 Kuckt [[Special:BlockList|Lëscht vun Späre]] fir déi aktuell Spären.',
 
 # History merging
@@ -1310,8 +1311,7 @@ Detailer fannt Dir am [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'preferences' => 'Astellungen',
 'mypreferences' => 'Astellungen',
 'prefs-edits' => 'Zuel vun den Ännerungen:',
-'prefsnologin' => 'Net ageloggt',
-'prefsnologintext' => 'Dir musst <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}}ageloggt]</span> sinn, fir Är Astellungen änneren ze kënnen.',
+'prefsnologintext2' => 'Dir musst Iech $1 fir Är Benotzerastellunge festzeleeën',
 'changepassword' => 'Passwuert änneren',
 'prefs-skin' => 'Skin',
 'skin-preview' => 'Kucken',
@@ -1421,6 +1421,7 @@ Dës Informatioun ass ëffentlech.",
 'prefs-displayrc' => 'Optioune vun deem wat gewise gëtt',
 'prefs-displaysearchoptions' => 'Optioune vum Affichage',
 'prefs-displaywatchlist' => 'Optioune vun deem wat gewise gëtt',
+'prefs-tokenwatchlist' => 'Token',
 'prefs-diffs' => 'Ënnerscheeder',
 'prefs-help-prefershttps' => 'Dës Astellung gëtt déi nächste Kéier wierksam wou Dir Iech ageloggt.',
 
@@ -1449,7 +1450,7 @@ Dës Informatioun ass ëffentlech.",
 'userrights-notallowed' => 'Dir hutt net déi néideg Rechter fir Rechter vun anere Benotzer derbäizesetzen oder ewechzehuelen.',
 'userrights-changeable-col' => 'Gruppen déi Dir ännere kënnt',
 'userrights-unchangeable-col' => 'Gruppen déi Dir net ännere kënnt',
-'userrights-conflict' => 'Konflikt bäi de Benotzerrechter! Kuckt Är Ännerunge w.e.g. no a maacht se w.e.g. nach eng Kéier.',
+'userrights-conflict' => 'Konflikt bei de Benotzerrechter! Kuckt Är Ännerunge w.e.g. no a maacht se w.e.g. nach eng Kéier.',
 'userrights-removed-self' => 'Dir hutt Är eege Rechter ewechgeholl. Dofir kënnt Dir net méi op dës Säit zougräifen.',
 
 # Groups
@@ -1608,6 +1609,8 @@ Dës Informatioun ass ëffentlech.",
 'recentchanges-label-minor' => 'Dëst ass eng kleng Ännerung',
 'recentchanges-label-bot' => 'Dës Ännerung gouf vun engem Bot gemaacht',
 'recentchanges-label-unpatrolled' => 'Dës Ännerung gouf nach net nogekuckt',
+'recentchanges-legend-newpage' => '(kuckt och [[Special:NewPages|Lëscht vun den neie Säiten]])',
+'recentchanges-legend-plusminus' => "''(±123)''",
 'rcnote' => "Hei {{PLURAL:$1|ass déi lescht Ännerung|sinn déi lescht '''$1''' Ännerungen}} {{PLURAL:$2|vum leschten Dag|vun de leschten '''$2''' Deeg}}, Stand: $4 ëm $5 Auer.",
 'rcnotefrom' => "Ugewise ginn d'Ännerunge vum '''$2''' un (maximal '''$1''' Ännerunge gi gewisen).",
 'rclistfrom' => 'Nei Ännerunge vu(n) $1 u weisen',
@@ -1659,9 +1662,9 @@ Säite vun [[Special:Watchlist|Ärer Iwwerwaachungslëscht]] si '''fett''' gesch
 
 Hei fannt Dir en Extrait aus dem Läsch- a Réckel-Logbuch fir dëse Fichier.",
 'uploadtext' => "Benotzt dëse Formulaire, fir nei Fichieren eropzelueden.
-Gitt op d'[[Special:FileList|Lëscht vun den eropgeluedene Fichieren]], fir no Fichieren ze sichen déi virdrun eropgeluede goufen, Eropluedunge fannt dir an der [[Special:Log/upload|Lëscht vun den eropgeluedene Fichieren]], geläschte Fichieren am [[Special:Log/delete|Läschlog]].
+Gitt op d'[[Special:FileList|Lëscht vun den eropgeluedene Fichieren]], fir no Fichieren ze sichen déi virdrun eropgeluede goufen, Eropluedunge fannt dir an der [[Special:Log/upload|Lëscht vun den eropgeluedene Fichieren]], geläscht Fichiere stinn am [[Special:Log/delete|Läschlog]].
 
-Fir e '''Bild''' op enger Säit zu benotzen, schreift amplaz vum Bild eng vun dëse Formelen:
+Fir e '''Bild''' op enger Säit ze benotzen, schreift amplaz vum Bild eng vun dëse Formelen:
 * '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichier.jpg]]</nowiki></code>''' fir déi ganz Versioun vum Fichier ze benotzen
 * '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichier.png|200px|thumb|left|alt text]]</nowiki></code>''' fir eng 200 Pixel breet Versioun an enger Këscht am lénke Rand mat 'alt text' als Beschreiwung
 * '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Fichier.ogg]]</nowiki></code>''' fir e Fichier direkt ze verlinken ouni de Fichier ze weisen",
@@ -1850,7 +1853,7 @@ Kuckt  https://www.mediawiki.org/wiki/Manual:Image_Authorization',
 Nèemmen Datenofruff ass erlaabt.',
 'img-auth-streaming' => '"$1" lueden.',
 'img-auth-public' => "D'Funktioun img_auth.php erlaabt et fir Fichieren vun enger privater Wiki erauszeginn.
-Dës Wiki ass als ëffentlech Wiki configuréiert.
+Dës Wiki ass als ëffentlech Wiki konfiguréiert.
 Fir eng optimal Sécherheet ass img_auth.php ausgeschalt.",
 'img-auth-noread' => 'De Benotzer hut keen Zougang fir "$1" ze liesen',
 'img-auth-bad-query-string' => "D'URL huet eng net valabel Rei vun Zeechen.",
@@ -1862,7 +1865,7 @@ Fir eng optimal Sécherheet ass img_auth.php ausgeschalt.",
 'http-read-error' => 'HTTP-Feeler beim Liesen.',
 'http-timed-out' => 'HTTP-Ufro huet ze laang gebraucht (time out).',
 'http-curl-error' => 'Feeler beim Ofruff vun der URL: $1',
-'http-bad-status' => 'Et gouf e Problem bäi der HTTP-Ufro: $1 $2',
+'http-bad-status' => 'Et gouf e Problem bei der HTTP-Ufro: $1 $2',
 
 # Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
 'upload-curl-error6' => "URL ass net z'erreechen",
@@ -2214,9 +2217,9 @@ Et ginn [[{{MediaWiki:Listgrouprights-helppage}}|zousätzlech Informatiounen]] i
 'listgrouprights-removegroup' => 'Kann {{PLURAL:$2|dëse Gruppe|dës Gruppen}} ewechhuelen: $1',
 'listgrouprights-addgroup-all' => 'Kann all Gruppen derbäisetzen',
 'listgrouprights-removegroup-all' => 'Ka Benotzer aus alle Gruppen eraushuelen',
-'listgrouprights-addgroup-self' => "Däerf {{PLURAL:$2|de Grupp|d'Gruppe}} bäi säin eegene Benotzerkont derbäisetzen: $1",
+'listgrouprights-addgroup-self' => "Däerf {{PLURAL:$2|de Grupp|d'Gruppe}} bei säin eegene Benotzerkont derbäisetzen: $1",
 'listgrouprights-removegroup-self' => "Däerf {{PLURAL:$2|de Grupp|d'Gruppe}} vu sengem eegene Benotzerkont ewechhuelen: $1",
-'listgrouprights-addgroup-self-all' => 'däerf all Gruppe bäi säin eegene Benotzerkont derbäisetzen',
+'listgrouprights-addgroup-self-all' => 'däerf all Gruppe bei säin eegene Benotzerkont derbäisetzen',
 'listgrouprights-removegroup-self-all' => 'Däerf all Gruppe vu sengem eegene Benotzerkont ewechhuelen',
 
 # Email user
@@ -2281,7 +2284,7 @@ All weider Ännerungen op dëser Säit an der associéierter Diskussiounssäit g
 'watchmethod-recent' => 'Rezent Ännerunge ginn op iwwerwaacht Säiten iwwerpréift',
 'watchmethod-list' => 'Iwwerwaachte Säite ginn op rezent Ännerungen iwwerpréift',
 'watchlistcontains' => 'Op ärer Iwwerwaachungslëscht $1 {{PLURAL:$1|steet $1 Säit|stinn $1 Säiten}}.',
-'iteminvalidname' => "Problem mat dem Objet '$1', ongëltegen Numm ...",
+'iteminvalidname' => "Problem mam Element '$1', ongëltegen Numm ...",
 'wlnote' => "Hei {{PLURAL:$1|ass déi lescht Ännerung|sinn déi lescht '''$1''' Ännerunge}} vun {{PLURAL:$2|der leschter Stonn|de leschte(n) '''$2''' Stonnen}}, Stand: $3 ëm $4 Auer.",
 'wlshowlast' => "D'Ännerunge vun de leschte(n) $1 Stonnen, $2 Deeg oder $3 (an de leschten 30 Deeg) weisen.",
 'watchlist-options' => 'Optioune vun der Iwwerwaachungslëscht',
@@ -2317,7 +2320,7 @@ Den Editeur kontaktéieren:
 E-Mail: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
-Et gi soulaang keng weider Maile geschéckt, bis Dir d\'Säit nees emol besicht hutt.
+Et gi soulaang keng weider Maile geschéckt, bis Dir d\'Säit nees emol besicht hutt wärend deem Dir ageloggt sidd.
 Op Ärer Iwwerwaachungslëscht kënnt Dir all Benoorichtigungsmarkeren zesummen zErécksetzen.
 
 
@@ -2329,7 +2332,7 @@ Fir d\'Astellungen op Ären E-Mailbenoriichtigungen z\'änneren, besicht w.e.g.
 {{canonicalurl:{{#special:Preferences}}}}
 
 
-Fir d\'Astellungen vun Ärer Iwwerwaachungslëscht z\'änneren, besicht w.e.g.
+Fir d\'Astellunge vun Ärer Iwwerwaachungslëscht z\'änneren, besicht w.e.g.
 {{canonicalurl:Special:Watchlist/edit}}
 
 Feedback a weider Hëllef:
@@ -2396,9 +2399,9 @@ Déi lescht Ännerung vun der Säit ass vum [[User:$3|$3]] ([[User talk:$3|Disku
 
 # Edit tokens
 'sessionfailure-title' => 'Setzungsfeeler',
-'sessionfailure' => 'Et schéngt e Problem mat Ã¤rer Loginséance ze ginn;
-Dës Aktioun gouf aus Sécherheetsgrënn ofgebrach, fir ze verhënneren datt Ã¤r Séance piratéiert ka ginn.
-Klickt w.e.g. op "Zréck" a lued déi Säit vun där Dir komm sidd nei, a versicht et dann nach eng Kéier.',
+'sessionfailure' => 'Et schéngt e Problem mat Ã\84rer Loginseance ze ginn;
+Dës Aktioun gouf aus Sécherheetsgrënn ofgebrach, fir ze verhënneren datt Ã\84r Seance piratéiert ka ginn.
+Klickt w.e.g. op "Zréck" a luet déi Säit vun där Dir komm sidd nei, a versicht et dann nach eng Kéier.',
 
 # Protect
 'protectlogpage' => 'Protektiounslogbuch',
@@ -2480,10 +2483,10 @@ Fir nëmmen eng bestëmmte Versioun vun der Säit ze restauréieren, markéiert
 'undeleterevisions' => '{{PLURAL:$1|1 Versioun|$1 Versiounen}} archivéiert',
 'undeletehistory' => 'Wann Dir dës Säit restauréiert, ginn och all déi al Versioune restauréiert.
 Wann zanter dem Läschen eng nei Säit mat dem selwechten Numm ugeluecht gouf, ginn déi restauréiert Versioune chronologesch an den Historique agedroen.',
-'undeleterevdel' => "D'Restauratioun gëtt net gemaach wann dëst dozou féiert datt déi aktuell Versioun vun der Säit oder vum Fichier deelweis geläscht gëtt.
-A sou Fäll däerf déi neiste Versioun net markéiert ginn oder déi neiste geläschte Versioun muss nees ugewise ginn.",
+'undeleterevdel' => "D'Restauratioun gëtt net gemaach wann dat dozou féiert datt déi aktuell Versioun vun der Säit oder vum Fichier deelweis geläscht gëtt.
+A sou Fäll däerf déi neist Versioun net markéiert ginn oder déi neist geläscht Versioun muss nees ugewise ginn.",
 'undeletehistorynoadmin' => "Dës Säit gouf geläscht. De Grond fir d'Läsche gesitt der ënnen, zesumme mat der Iwwersiicht vun den eenzele Versioune vun der Säit an hiren Auteuren. Déi verschidden Textversioune kënnen awer just vun Administrateure gekuckt a restauréiert ginn.",
-'undelete-revision' => 'Geläschte Versioun vu(n) $1 (Versioun vum $4 um $5 Auer) vum $3:',
+'undelete-revision' => 'Geläscht Versioun vu(n) $1 (Versioun vum $4 um $5 Auer) vum $3:',
 'undeleterevision-missing' => "Ongëlteg oder Versioun déi feelt. Entweder ass de Link falsch oder d'Versioun gouf aus dem Archiv restauréiert oder geläscht.",
 'undelete-nodiff' => 'Et si keng méi al Versiounen do.',
 'undeletebtn' => 'Restauréieren',
@@ -2515,7 +2518,7 @@ Am [[Special:Log/delete|Läsch-Logbuch]] fannt Dir déi geläscht a restauréier
 'undelete-error-long' => 'Beim Restauréiere vun engem Fichier goufe Feeler fonnt:
 
 $1',
-'undelete-show-file-confirm' => '!Sidd Dir sécher, datt dir eng geläschte Versioun vum Fichier „<nowiki>$1</nowiki>“ vum $2 ëm $3 Auer gesi wëllt?',
+'undelete-show-file-confirm' => 'Sidd Dir sécher, datt dir eng geläscht Versioun vum Fichier „<nowiki>$1</nowiki>“ vum $2 um $3 Auer gesi wëllt?',
 'undelete-show-file-submit' => 'Jo',
 
 # Namespace form on various pages
@@ -2838,7 +2841,7 @@ Wann nëmmen déi aktuell Versioun exportéiert soll ginn, kënnt Dir och e Link
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'Aktuellen Text',
 'allmessagestext' => "Dëst ass eng Lëscht vun alle '''Messagen am MediaWiki:Nummraum, déi vun der MediaWiki-Software benotzt ginn.
-Besicht w.e.g. [//www.mediawiki.org/wiki/Localisation MediaWiki Localisatioun] an [//translatewiki.net translatewiki.net] wann Dir wëllt bei de MediaWiki Iwwersetzunge matschaffen.",
+Besicht w.e.g. [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisatioun] an [//translatewiki.net translatewiki.net] wann Dir wëllt bei de MediaWiki Iwwersetzunge matschaffen.",
 'allmessagesnotsupportedDB' => "Dës Säit kann net benotzt gi well '''\$wgUseDatabaseMessages''' ausgeschalt ass.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter nom ugepassten Zoustand:',
@@ -2962,7 +2965,7 @@ Späichert en op Ärem Computer of a luet en hei nees erop.',
 'tooltip-n-mainpage' => "Besicht d'Haaptsäit",
 'tooltip-n-mainpage-description' => "Besicht d'Haaptsäit",
 'tooltip-n-portal' => 'Iwwer de Portal, wat Dir maache kënnt, wou wat ze fannen ass',
-'tooltip-n-currentevents' => "D'Aktualitéit a wat derhanner ass",
+'tooltip-n-currentevents' => "D'Aktualitéit a wat dohanner ass",
 'tooltip-n-recentchanges' => 'Lëscht vun de rezenten Ännerungen op {{SITENAME}}.',
 'tooltip-n-randompage' => 'Zoufälleg Säit',
 'tooltip-n-help' => 'Hëllefsäiten weisen.',
@@ -3001,7 +3004,7 @@ Späichert en op Ärem Computer of a luet en hei nees erop.',
 Erlaabt et e Grond an de Resumé derbäizesetzen.',
 'tooltip-preferences-save' => 'Astellunge späicheren',
 'tooltip-summary' => 'Gitt e kuerze Resumé an',
-'tooltip-iwiki' => '$1 - $2',
+'interlanguage-link-title' => '$1 - $2',
 
 # Stylesheets
 'common.css' => "/* Dës CSS huet nëmmen Afloss op de Skin ''Chick''  */",
@@ -3036,6 +3039,8 @@ Dëst wahrscheinlech duerch en externe Link den op der schwaarzer Lëscht (black
 'spam_reverting' => 'Déi lescht Versioun ouni Linken op $1 restauréieren.',
 'spam_blanking' => 'An alle Versioune ware Linken op $1, et ass elo alles gebotzt.',
 'spam_deleting' => 'All Versioune mat Linken op $1 gi geläscht',
+'simpleantispam-label' => "Anti-Spam Kontroll.
+Fëllt dëst '''NET''' aus!",
 
 # Info page
 'pageinfo-title' => 'Informatioun iwwer "$1"',
@@ -3049,6 +3054,7 @@ Dëst wahrscheinlech duerch en externe Link den op der schwaarzer Lëscht (black
 'pageinfo-length' => 'Gréisst vun der Säit (a Bytes)',
 'pageinfo-article-id' => 'ID (Nummer) vun der Säit',
 'pageinfo-language' => 'Sprooch vum Inhalt vun der Säit',
+'pageinfo-content-model' => 'Modell vun enger Säit mat Inhalt',
 'pageinfo-robot-policy' => 'Indexéierung duerch Botten',
 'pageinfo-robot-index' => 'Erlaabt',
 'pageinfo-robot-noindex' => 'Net erlaabt',
@@ -3107,7 +3113,7 @@ Dëst wahrscheinlech duerch en externe Link den op der schwaarzer Lëscht (black
 'log-show-hide-patrol' => 'Kontroll-Logbuch $1',
 
 # Image deletion
-'deletedrevision' => 'Al, geläschte Versioun $1',
+'deletedrevision' => 'Al, geläscht Versioun vu(n) $1',
 'filedeleteerror-short' => 'Feeler beim Läsche vum Fichier: $1',
 'filedeleteerror-long' => 'Bäim Läsche vum Fichier si Feeler festgestallt ginn:
 
@@ -3134,7 +3140,7 @@ Duerch d'Opmaache vum Fichier kann Äre System beschiedegt ginn.",
 'svg-long-desc' => 'SVG-Fichier, Basisgréisst: $1 × $2 Pixel, Gréisst vum Fichier: $3',
 'svg-long-desc-animated' => 'Animéierten SVG-Fichier, Basisgréisst $1 x $2 Pixel, Gréisst vum Fichier: $3',
 'svg-long-error' => 'Ongëltegen SVG-Fichier: $1',
-'show-big-image' => 'Voll Opléisung',
+'show-big-image' => 'Original Fichier',
 'show-big-image-preview' => 'Gréisst vun dësem Preview: $1.',
 'show-big-image-other' => 'Aner {{PLURAL:$2|Opléisung|Opléisungen}}: $1.',
 'show-big-image-size' => '$1 × $2 Pixel',
@@ -3316,7 +3322,7 @@ Déi aner sinn am Standard verstoppt.
 'exif-gpsdestlongitude' => 'Längt',
 'exif-gpsdestbearingref' => "Referenz fir d'Motivrichtung",
 'exif-gpsdestbearing' => 'Richtung vum Motiv',
-'exif-gpsdestdistanceref' => "Referenz fir d'Distanz bis bäi den Objet (vun der Foto)",
+'exif-gpsdestdistanceref' => "Referenz fir d'Distanz bis bei den Objet (vun der Foto)",
 'exif-gpsdestdistance' => 'Motivdistanz',
 'exif-gpsprocessingmethod' => 'Numm vun der GPS-Prozedur-Method',
 'exif-gpsareainformation' => 'Numm vun der GPS-Géigend',
@@ -3593,7 +3599,7 @@ Déi aner sinn am Standard verstoppt.
 
 # External editor support
 'edit-externally' => 'Dëse Fichier mat engem externe Programm änneren',
-'edit-externally-help' => "(Fir gewuer ze gi wéi dat genee geet liest d'[//www.mediawiki.org/wiki/Manual:External_editors Installatiounsinstruktiounen].)",
+'edit-externally-help' => "(Fir gewuer ze gi wéi dat genee geet liest d'[https://www.mediawiki.org/wiki/Manual:External_editors Installatiounsinstruktiounen].)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'all',
@@ -3680,6 +3686,9 @@ Dëse Confirmatiounscode leeft den $4 of.',
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Dës Säit vun Ärer Iwwerwaachungslëscht erofhuelen?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '← Vireg Säit',
 'imgmultipagenext' => 'nächst Säit →',
@@ -3765,7 +3774,7 @@ Dir kënnt och [[Special:EditWatchlist|de Standard Editeur benotzen]].",
 'version-hook-subscribedby' => 'Opruff vum',
 'version-version' => '(Versioun $1)',
 'version-license' => 'Lizenz',
-'version-poweredby-credits' => "Dës Wiki funktionéiert mat '''[//www.mediawiki.org/ MediaWiki]''', Copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Dës Wiki funktionéiert mat '''[https://www.mediawiki.org/ MediaWiki]''', Copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'anerer',
 'version-poweredby-translators' => 'translatewiki.net Iwwersetzer',
 'version-credits-summary' => "Mir soen dëse Persoune 'Merci' fir hir Mataarbecht u [[Special:Version|MediaWiki]].",
@@ -3784,7 +3793,8 @@ Dir misst eng [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie vun der GNU General Public
 # Special:Redirect
 'redirect' => 'Viruleedung duerch e Fichier, Benotzer oder Versiouns-ID',
 'redirect-legend' => 'Viruleedung op ee Fichier oder eng Säit',
-'redirect-summary' => 'Dës Spezialsäit ass eng Viruleedung op e Fichier (Fichiersnumm uginn), eng Säit (Versiounsnummer uginn) oder eng Benotzersäit (numeresch Benotzeridentifikatioun uginn).',
+'redirect-summary' => 'Dës Spezialsäit ass eng Viruleedung op e Fichier (Fichiersnumm uginn), eng Säit (Versiounsnummer uginn) oder eng Benotzersäit (numeresch Benotzeridentifikatioun uginn).
+Gebrauch: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], oder [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Lass',
 'redirect-lookup' => 'Nosichen:',
 'redirect-value' => 'Wäert:',
@@ -3806,10 +3816,9 @@ Dir misst eng [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie vun der GNU General Public
 
 # Special:SpecialPages
 'specialpages' => 'Spezialsäiten',
-'specialpages-note' => '----
-* Normal Spezialsäiten.
-* <span class="mw-specialpagerestricted">Spezialsäite fir Benotzer mat méi Rechter.</span>
-* <span class="mw-specialpagecached">Spezialsäiten aus dem Tëschespäicher (ka vereelst sinn).</span>',
+'specialpages-note-top' => 'Erklärung',
+'specialpages-note' => '* Normal Spezialsäiten.
+* <span class="mw-specialpagerestricted">Spezialsäite fir Benotzer mat méi Rechter.</span>',
 'specialpages-group-maintenance' => 'Maintenance-Rapporten',
 'specialpages-group-other' => 'Aner Spezialsäiten',
 'specialpages-group-login' => 'Aloggen / Benotzerkont uleeën',
@@ -3938,7 +3947,7 @@ Soss kënnt Dir den einfache Formulär hei drënner benotzen. Är Bemierkung gë
 'feedback-message' => 'Message:',
 'feedback-cancel' => 'Ofbriechen',
 'feedback-submit' => 'Feedback schécken',
-'feedback-adding' => "Feedback gëtt bäi d'Säit derbäigesat...",
+'feedback-adding' => "Feedback gëtt bei d'Säit derbäigesat...",
 'feedback-error1' => 'Feeler: Resultat vum API gouf net erkannt',
 'feedback-error2' => "Feeler: D'Ännerung gouf net gespäichert",
 'feedback-error3' => 'Feeler: Keng Äntwert vum API',
@@ -4015,4 +4024,20 @@ Soss kënnt Dir den einfache Formulär hei drënner benotzen. Är Bemierkung gë
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|Byte|Byten}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|Byte|Byten}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Schablounen expandéieren',
+'expand_templates_intro' => 'Op dëser Spezialsäit kann Text agesat ginn an all Schablounen doran gi rekursiv expandéiert.
+Och Parserfonctioune wéi<code><nowiki>{{</nowiki>#language:…}}</code> a Variabele wéi
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>, ginn ausgewäert.
+Faktesch alles wat tëscht duebelen Accolade steet gëtt ausgewäert.',
+'expand_templates_title' => 'Titel vun der Säit, dëst kann nëtzlech si wa(nn) {{FULLPAGENAME}} benotzt gëtt:',
+'expand_templates_input' => 'Gitt ären Text hei an:',
+'expand_templates_output' => 'Resultat',
+'expand_templates_xml_output' => 'Resultat als XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Bemierkunge läschen',
+'expand_templates_remove_nowiki' => '<nowiki>-Taggen am Resultat suppriméieren',
+'expand_templates_generate_xml' => "Weis d'Struktur vum XML",
+'expand_templates_preview' => 'Kucken ouni ofzespäicheren',
+
 );
index df854b8..849e641 100644 (file)
@@ -286,8 +286,6 @@ $messages = array(
 'ok' => 'ОК',
 'retrievedfrom' => 'Чешне "$1" я',
 'youhavenewmessages' => 'Квез $1 ($2) атанва.',
-'newmessageslink' => 'цӀийи чарар',
-'newmessagesdifflink' => 'Эхиримжи масакӀавилер',
 'youhavenewmessagesmulti' => '"$1"-да квез цӀийи чарар атанва.',
 'editsection' => 'Дуьзар хъувун',
 'editold' => 'Дуьзар хъувун',
@@ -621,7 +619,6 @@ $messages = array(
 'preferences' => 'Туькlуьрун',
 'mypreferences' => 'Зи низамарунар',
 'prefs-edits' => 'Дьузар хъувунрин кьадар',
-'prefsnologin' => 'Куьне гьахьнавач',
 'changepassword' => 'Парол дегишарун',
 'prefs-skin' => 'Къайдадиз ттунин тема',
 'skin-preview' => 'Сифтедин килигун',
@@ -1266,7 +1263,7 @@ Cиягьда авай анжах (* лишандихъ галаз эгечIза
 
 # External editor support
 'edit-externally' => 'И файл патан программа куьмекдалди дуьзар хъувун',
-'edit-externally-help' => '(Алава малумат патал [//www.mediawiki.org/wiki/Manual:External_editors эцигунин регьбервилиз] килига)',
+'edit-externally-help' => '(Алава малумат патал [https://www.mediawiki.org/wiki/Manual:External_editors эцигунин регьбервилиз] килига)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'вири',
index f038432..27d94f1 100644 (file)
@@ -228,8 +228,6 @@ $messages = array(
 'ok' => 'Oce',
 'retrievedfrom' => 'Retraeda de "$1"',
 'youhavenewmessages' => 'Tu ave $1 ($2).',
-'newmessageslink' => 'mesajes nova',
-'newmessagesdifflink' => 'cambia presedente',
 'youhavenewmessagesmulti' => 'Tu ave mesajes nova en $1',
 'editsection' => 'cambia',
 'editold' => 'edita',
@@ -930,7 +928,7 @@ Si la fix ia es cambiada de se stato orijinal, alga detalias pote no es clara en
 
 # External editor support
 'edit-externally' => 'Edita esta fix con un programa esterna',
-'edit-externally-help' => '(Vide la [//www.mediawiki.org/wiki/Manual:External_editors instruis per comensa] per plu instruis)',
+'edit-externally-help' => '(Vide la [https://www.mediawiki.org/wiki/Manual:External_editors instruis per comensa] per plu instruis)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tota',
@@ -955,4 +953,7 @@ Si la fix ia es cambiada de se stato orijinal, alga detalias pote no es clara en
 # Special:SpecialPages
 'specialpages' => 'Pajes spesial',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Oce',
+
 );
index da02d48..7833d4d 100644 (file)
@@ -266,8 +266,6 @@ Kebera ku [[Special:Version|lukalala lw'empandika za MediaWiki]].",
 'ok' => 'Kale',
 'retrievedfrom' => 'Bino bigyidwa ku "$1"',
 'youhavenewmessages' => 'Ofunye $1 ($2).',
-'newmessageslink' => 'obubaka',
-'newmessagesdifflink' => "obusing'obupya",
 'youhavenewmessagesmulti' => 'Ku $1 bakuweerezza obubaka',
 'editsection' => 'kyusa',
 'editold' => 'kyusa',
@@ -1190,7 +1188,7 @@ Yogera nange gwe olina okugyegattira ku eyo esangidwawo.'''",
 'allmessagescurrent' => 'Ebiriwo kakano',
 'allmessagestext' => "Luno lwe lukalala olw'obubaka obwa sisitemu obw'omu kkuŋŋaanizo erya MediaWiki.
 
-Ob'oyagala okuyamba ku kuvvuunula eby'omu MediaWiki yonna, kebera ku [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ne [//translatewiki.net translatewiki.net].",
+Ob'oyagala okuyamba ku kuvvuunula eby'omu MediaWiki yonna, kebera ku [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] ne [//translatewiki.net translatewiki.net].",
 'allmessages-filter-legend' => 'Ensunsula',
 'allmessages-filter' => 'Londamu:',
 'allmessages-filter-unmodified' => 'Ebitannakyusibwamu',
@@ -1309,7 +1307,7 @@ Ebirala biyinza butalabika okujjako ng'okiragidde.
 
 # External editor support
 'edit-externally' => 'Fayiro eno gikolereko mu pulogulamu endala',
-'edit-externally-help' => '[//www.mediawiki.org/wiki/Manual:External_editors Nyiga wano] okuyiga ebisingawo ku kukozesa pulogulamu endala okukola enkyukakyuka.',
+'edit-externally-help' => '[https://www.mediawiki.org/wiki/Manual:External_editors Nyiga wano] okuyiga ebisingawo ku kukozesa pulogulamu endala okukola enkyukakyuka.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Zonna',
index 44efb2f..9183538 100644 (file)
@@ -58,7 +58,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Audste_pagina\'s' ),
        'Blankpage'                 => array( 'Laeg_pagina\'s' ),
        'Block'                     => array( 'Blokkere' ),
-       'Blockme'                   => array( 'Blokkeer_mich' ),
        'Booksources'               => array( 'Bookwinkele' ),
        'BrokenRedirects'           => array( 'Gebraoke_doorverwiezinge' ),
        'Categories'                => array( 'Categorieë' ),
@@ -68,7 +67,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Gebroeker_aonmake' ),
        'Deadendpages'              => array( 'Doedloupende_pagina\'s' ),
        'DeletedContributions'      => array( 'Eweggesjafde_biedrage' ),
-       'Disambiguations'           => array( 'Verdudelikingspagina\'s' ),
        'DoubleRedirects'           => array( 'Dobbel_doorverwiezinge' ),
        'Emailuser'                 => array( 'E-maile' ),
        'Export'                    => array( 'Exportere' ),
@@ -414,8 +412,6 @@ $1',
 'ok' => 'ok',
 'retrievedfrom' => 'Aafkómstig van "$1"',
 'youhavenewmessages' => 'Doe höbs $1 ($2).',
-'newmessageslink' => 'nuuj berichte',
-'newmessagesdifflink' => 'Lèste verangering',
 'youhavenewmessagesmulti' => 'Doe höbs nuuj berichte op $1',
 'editsection' => 'bewèrk',
 'editold' => 'bewirke',
@@ -1154,8 +1150,6 @@ Mèrk op dat hun indexe van {{SITENAME}} content e bietje gedatierd kint zien.',
 'preferences' => 'Veurkäöre',
 'mypreferences' => 'Mien veurkäöre',
 'prefs-edits' => 'Aantal bewèrkinge:',
-'prefsnologin' => 'Neet aangemèld',
-'prefsnologintext' => 'De mós zeen <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aagemeld]</span> óm dien veurkäöre te kónne insjtèlle.',
 'changepassword' => 'Wachwaord verangere',
 'prefs-skin' => '{{SITENAME}}-uterlik',
 'skin-preview' => 'Veurbesjouwing',
@@ -1430,6 +1424,7 @@ Deze informatie is zichbaar veur angere gebroekers.',
 'recentchanges-label-minor' => "Dit is 'n klein bewirking",
 'recentchanges-label-bot' => "Dees bewirking is oetgeveurd door 'ne bot",
 'recentchanges-label-unpatrolled' => 'Dees bewirking is nog neet gekónterleerd',
+'recentchanges-legend-newpage' => '$1 - Nuuj pagina',
 'rcnote' => "Hiejónger {{PLURAL:$1|steit de lètste bewirking|staon de lètste '''$1''' bewirkinge}} van de aafgeloupe {{PLURAL:$2|daag|'''$2''' daag}}, op $4, um $5.",
 'rcnotefrom' => "Verangeringe sins <b>$2</b> (mit 'n maximum van <b>$1</b> verangeringe).",
 'rclistfrom' => 'Tuin de verangeringe vanaaf $1',
@@ -2596,7 +2591,7 @@ In 't letste geval kèns te ouch 'ne link gebroeken, bieveurbild [[{{#Special:Ex
 'allmessagesdefault' => 'Obligaten teks',
 'allmessagescurrent' => 'Hujige teks',
 'allmessagestext' => "Dit is 'n lies van alle systeemberichte besjikbaar in de MediaWiki-naamruumde.
-Bezeuk [//www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] es doe wils biedrage aon lokalisatie.",
+Bezeuk [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] es doe wils biedrage aon lokalisatie.",
 'allmessagesnotsupportedDB' => "Deze pagina kan neet gebroek waere omdet '''\$wgUseDatabaseMessages''' oet steit.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter óp aangepas:',
@@ -2777,6 +2772,8 @@ Meistal wörd dit door 'ne zwarte externe link veroorzaak.",
 'spam_reverting' => 'Bezig mit trökdrèjje nao de letste versie die gein verwiezing haet nao $1',
 'spam_blanking' => "Alle wieziginge mit 'ne link nao $1 waere verwiederd",
 'spam_deleting' => 'Alle wieziginge hawwe links nao $1, wuuertj gewösj',
+'simpleantispam-label' => "Antispemcontrole.
+Vol dit veld '''NEET''' in!",
 
 # Info page
 'pageinfo-title' => 'Informatie euver "$1"',
@@ -3276,7 +3273,7 @@ Alle volgende links die op dezelfde regel sjtaon, waere behanjeld es oetzunjerin
 
 # External editor support
 'edit-externally' => "Bewirk dit bestand mit 'n extern toepassing",
-'edit-externally-help' => '(zuug de [//www.mediawiki.org/wiki/Manual:External_editors setupinsjtructies] veur mie informatie)',
+'edit-externally-help' => '(zuug de [https://www.mediawiki.org/wiki/Manual:External_editors setupinsjtructies] veur mie informatie)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'al',
@@ -3456,7 +3453,7 @@ De kèns ouch [[Special:EditWatchlist|'t sjtanderd bewirkingssjirm gebroeke]].",
 'version-hook-subscribedby' => 'Geabonneerd door',
 'version-version' => '(Versie $1)',
 'version-license' => 'Licentie',
-'version-poweredby-credits' => "Deze wiki weurt aangedreve door '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Deze wiki weurt aangedreve door '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'anger',
 'version-license-info' => "MediaWiki is vrieje sofware; de kins MediaWiki verspreien en/of aanpassen onger de veurwaerde van de GNU General Public License wie gepubliceerd door de Free Software Foundation; ofwaal versie 2 van de Licentie, of - nao diene wönsj - innig later versie.
 
@@ -3483,8 +3480,7 @@ Same mit dit programma heurs se 'n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van d
 
 # Special:SpecialPages
 'specialpages' => "Speciaal pagina's",
-'specialpages-note' => '----
-* Normaal speciaal pagina\'s
+'specialpages-note' => '* Normaal speciaal pagina\'s
 * <strong class="mw-specialpagerestricted">Beperk toegankelike speciaal pagina\'s</strong>
 * <span class="mw-specialpagecached">Speciaal pagina\'s mit allein gegaeves oete cache (meugelik verajerd)</span>',
 'specialpages-group-maintenance' => 'Óngerhajingsrapporter',
@@ -3668,4 +3664,18 @@ Anges kin se-n ouch \'t einvawdig formeleer hieónger gebroeke. Dien commentaar
 'duration-centuries' => '$1 {{PLURAL:$1|ieëf|ieëf}}',
 'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Sjablone plekke',
+'expand_templates_intro' => "Dees speciaal pazjena laes de ingegaeve teks in en plektj (mitte functie subst) recursief alle sjablone in de teks. 't Plek ouch alle parserfuncties wie <nowiki>{{</nowiki>#language:...}} en variabele wie <nowiki>{{</nowiki>CURRENTDAY}} - vriejwaal al tösse dóbbel accolades.
+Hiej veur waere de relevante functies van de MediaWiki-parser gebroek.",
+'expand_templates_title' => 'Contekstitel, veur {{FULLPAGENAME}}, etc:',
+'expand_templates_input' => 'Inlaajteks:',
+'expand_templates_output' => 'Rezultaot',
+'expand_templates_xml_output' => 'XML-oetveur',
+'expand_templates_ok' => 'ok',
+'expand_templates_remove_comments' => 'Wis opmerkinge',
+'expand_templates_remove_nowiki' => "Óngerdrök <nowiki>-tags in 't resultaat",
+'expand_templates_generate_xml' => 'XML-parserboum bekieke',
+'expand_templates_preview' => 'Veurvertoeaning',
+
 );
index 2bd36f8..6a3f1f5 100644 (file)
@@ -55,7 +55,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Tûtte e paggine' ),
        'Ancientpages'              => array( 'Paggine meno reçenti' ),
        'Block'                     => array( 'Blocca' ),
-       'Blockme'                   => array( 'BloccaProxy' ),
        'Booksources'               => array( 'RiçercaISBN' ),
        'Categories'                => array( 'Categorîe' ),
        'ChangePassword'            => array( 'Rimposta paròlla d\'ordine' ),
@@ -384,8 +383,6 @@ $1",
 'ok' => "D'accòrdio",
 'retrievedfrom' => 'Estræto da "$1"',
 'youhavenewmessages' => "Ti gh'æ $1 ($2).",
-'newmessageslink' => 'Nêuvi messaggi',
-'newmessagesdifflink' => 'urtima modiffica',
 'youhavenewmessagesfromusers' => "Ti g'hæ $1 da {{PLURAL:$3|un atro utente|$3 utenti}} ($2).",
 'youhavenewmessagesmanyusers' => "Ti g'hæ $1 da tanti utenti ($2).",
 'newmessageslinkplural' => '{{PLURAL:$1|un noeuvo messaggio|noeuvi messaggi}}',
@@ -1389,7 +1386,7 @@ I inganci sucescivi, in scia mæxima riga, van conscideræ comme eceçioìn (pag
 
 # External editor support
 'edit-externally' => 'Càngia sto file co-in programma esterno',
-'edit-externally-help' => 'Pe avéi ciù informaçioìn amia e [//www.mediawiki.org/wiki/Manual:External_editors istruçioìn] (in ingléize)',
+'edit-externally-help' => 'Pe avéi ciù informaçioìn amia e [https://www.mediawiki.org/wiki/Manual:External_editors istruçioìn] (in ingléize)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Tùtti',
index 3c07476..00ea60d 100644 (file)
@@ -159,8 +159,6 @@ $messages = array(
 
 'retrievedfrom' => 'Ulzõ vȯtštõd "$1"',
 'youhavenewmessages' => 'Täddõn um $1 ($2)',
-'newmessageslink' => 'ūži tīeūţidi',
-'newmessagesdifflink' => 'perri mõitõks',
 'editsection' => 'redigīer',
 'editold' => 'redigīerõgid',
 'viewsourceold' => 'vaņ ovāt-tekstõ',
@@ -732,7 +730,7 @@ Až sugīz nei, sōd līed tōdõs kädūdõks jeddõpēḑõn sōtõ agā jūr
 
 # External editor support
 'edit-externally' => 'Protseššõgid failõ ulīz programmatūraks',
-'edit-externally-help' => '(Vaņ uļļizt redaktōrd adresõs [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] kȭlbatõmiz opātõkst)',
+'edit-externally-help' => '(Vaņ uļļizt redaktōrd adresõs [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] kȭlbatõmiz opātõkst)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tikkiž',
index 34b6dec..aa8317b 100644 (file)
@@ -75,7 +75,6 @@ $specialPageAliases = array(
        'BrokenRedirects'           => array( 'RedirezionS-cepada' ),
        'Categories'                => array( 'Categurij' ),
        'CreateAccount'             => array( 'CreaCünt' ),
-       'Disambiguations'           => array( 'Desambiguazion' ),
        'DoubleRedirects'           => array( 'RedirezionDubia' ),
        'Listadmins'                => array( 'ListaAministradur' ),
        'Listfiles'                 => array( 'Imagin' ),
@@ -344,8 +343,6 @@ $1",
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Utegnüü de "$1"',
 'youhavenewmessages' => "A gh'hii di $1 ($2).",
-'newmessageslink' => 'messagg növ',
-'newmessagesdifflink' => 'diferenza cun la versión de prima',
 'youhavenewmessagesmulti' => "Te gh'hee di messagg növ ins'el $1",
 'editsection' => 'mudifega',
 'editold' => 'mudifega',
@@ -739,6 +736,7 @@ Pröa a giuntagh denanz a la tò ricerca ''all:'' per cercà in tücc i namespac
 'recentchanges-label-minor' => "Quela chì l'è una mudifega piscinina.",
 'recentchanges-label-bot' => "Quela mudifega chì l'ha fada un bot",
 'recentchanges-label-unpatrolled' => "Quela mudifega chì a l'è stada mimga anmò verificada.",
+'recentchanges-legend-newpage' => '$1 - pagina növa',
 'rcnote' => "Chì de sota {{PLURAL:$1|gh'è '''1''' mudifega|a hinn i ültim '''$1''' mudifegh}} in di ültim {{PLURAL:$2|dì|'''$2''' dì}}, a partì dai $5 del $4.",
 'rcnotefrom' => "Chì de sota gh'è la lista di mudifegh de <b>$2</b> (fina a <b>$1</b>).",
 'rclistfrom' => 'Fà vidè i cambiament növ a partì de $1',
@@ -1325,7 +1323,7 @@ I ligam che i vegnen dopu, in sü l'istessa riga, i vegnen cónsideraa di ecezi
 
 # External editor support
 'edit-externally' => 'Redatá chest archivi cunt un prugramari da fö',
-'edit-externally-help' => 'Varda [//www.mediawiki.org/wiki/Manual:External_editors i istrüzión] per avègh püssee infurmazión (in ingles).',
+'edit-externally-help' => 'Varda [https://www.mediawiki.org/wiki/Manual:External_editors i istrüzión] per avègh püssee infurmazión (in ingles).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tücc',
index d7f8a6f..8e1a7d7 100644 (file)
@@ -42,7 +42,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'ການປະກອບສ່ວນ' ),
        'CreateAccount'             => array( 'ສ້າງບັນຊີ' ),
        'Deadendpages'              => array( 'ໜ້າທີ່ບໍ່ມີໜ້າໃດໂຍງມາ' ),
-       'Disambiguations'           => array( 'ແກ້ຄວາມກຳກວມ' ),
        'DoubleRedirects'           => array( 'ໂອນຊ້ອນ' ),
        'Listadmins'                => array( 'ລາຍຊື່ຜູ້ບໍລິຫານລະບົບ' ),
        'Listbots'                  => array( 'ລາຍຊື່ບອຕ' ),
@@ -294,8 +293,6 @@ $messages = array(
 'ok' => 'ຕົກລົງ',
 'retrievedfrom' => 'ຖອນມາຈາກ "$1"',
 'youhavenewmessages' => 'ທ່ານ ມີ $1 ($2).',
-'newmessageslink' => 'ຂໍ້ຄວາມໃໝ່',
-'newmessagesdifflink' => 'ການປ່ຽນແປງຫຼ້າສຸດ',
 'youhavenewmessagesmulti' => 'ທ່ານມີຂໍ້ຄວາມໃໝ່ ຢູ່ $1',
 'editsection' => 'ດັດແກ້',
 'editold' => 'ດັດແກ້',
@@ -899,7 +896,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 
 # External editor support
 'edit-externally' => 'ດັດແກ້ໄຟລ໌ນີ້ໂດຍໂປແກຣມພາຍນອກ',
-'edit-externally-help' => 'ເບິ່ງ ຂໍ້ມູນເພີ່ມຕື່ມ ຢູ່ [//www.mediawiki.org/wiki/Manual:External_editors setup instructions]',
+'edit-externally-help' => 'ເບິ່ງ ຂໍ້ມູນເພີ່ມຕື່ມ ຢູ່ [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions]',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ທັງໝົດ',
@@ -954,4 +951,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 # Special:SpecialPages
 'specialpages' => 'ໜ້າພິເສດ',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'ຂະຫຍາຍແມ່ແບບ',
+
 );
index 0fafbb0..4f23f6d 100644 (file)
@@ -207,8 +207,6 @@ $messages = array(
 'ok' => 'lumelisize',
 'retrievedfrom' => 'Bulukezi ye ng\'i di "$1"',
 'youhavenewmessages' => 'A sa pozefisize $1 ($2).',
-'newmessageslink' => 'nca mulumiwani',
-'newmessagesdifflink' => 'nca petuho te-i',
 'youhavenewmessagesmulti' => 'Nca $1 mulumiwani',
 'editsection' => "hloli ye ng'i",
 'editold' => "hloli ye ng'i",
@@ -459,7 +457,6 @@ Informasi: (bye) = petuho a nca selt,
 'preferences' => 'Petohoni di sebelu',
 'mypreferences' => 'Zwa petohoni di sebelu',
 'prefs-edits' => "Hloli ye ng'inabi:",
-'prefsnologin' => 'Ni menuhile',
 'prefs-skin' => 'PendiBe',
 'skin-preview' => 'PendiBe',
 'datedefault' => 'Ni di petohoni di sebelu',
@@ -881,7 +878,7 @@ Teri yaki, a nyanganyisize.",
 'allmessagesdefault' => 'Selt orge',
 'allmessagescurrent' => 'Selt nca',
 'allmessagestext' => 'Bye mukoloko sa mukoloko di mulumiwani di MediaWiki poo.
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 
 # Thumbnails
 'thumbnail-more' => 'Pusize',
@@ -1011,7 +1008,7 @@ Xete ling'ki kwa lina sa konsidisize desepo. Petulo dimedi inlinenikusize.",
 
 # External editor support
 'edit-externally' => 'Kenki imegi sebilize pagini lakusi',
-'edit-externally-help' => 'Boniselelize [//www.mediawiki.org/wiki/Manual:External_editors instruksi setup] kwa informasi.',
+'edit-externally-help' => 'Boniselelize [https://www.mediawiki.org/wiki/Manual:External_editors instruksi setup] kwa informasi.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'xeti',
diff --git a/languages/messages/MessagesLrc.php b/languages/messages/MessagesLrc.php
new file mode 100644 (file)
index 0000000..d55d4e2
--- /dev/null
@@ -0,0 +1,1098 @@
+<?php
+/** لوری (لوری)
+ *
+ * See MessagesQqq.php for message documentation incl. usage of parameters
+ * To improve a translation please visit http://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ * @author Mogoeilor
+ */
+
+$rtl = true;
+
+$messages = array(
+# User preference toggles
+'tog-underline' => 'هوم پیوند زیرخط دار:',
+'tog-justify' => 'فاصله نيائن سی پاراگرافيا',
+'tog-hideminor' => 'قام كردن ويرايشتيا كؤچك مئن آلشتيا تازه',
+'tog-hidepatrolled' => 'قام كردن ويرايشتيا تیه دیار کرده مئن آلشتيا تازه',
+'tog-newpageshidepatrolled' => 'بلگیا تیه دیار کرده نه مئن نوم گه بلگیا تازه قام کو',
+'tog-extendwatchlist' => 'سیل برگه نه سی نشو دئن تمام آلشتیا واکو نه فقط سی بیشتر تازه باوا.',
+'tog-usenewrc' => 'دسه بنی آلشتیا وا بلگه د آلشتیا تازه و سیل برگ',
+'tog-numberheadings' => 'سربلگه خود شماره گر',
+'tog-showtoolbar' => 'نوار اوزار ويرايشت نشون بيه',
+'tog-editondblclick' => 'بلگيا نه وا دوبار پورنين ويرايشت بكيد',
+'tog-editsection' => 'ممكن بيئن ويرايشت بشخيا وا [ويرايشت]',
+'tog-editsectiononrightclick' => 'بهر ویرایشت نه وا راس کلیک کردن د بهر عنوانیا فعال کو',
+'tog-showtoc' => 'چیا مئن جدول نشو بیه',
+'tog-rememberpassword' => 'اومائن وا مئن منه د ای مرورگر د ویر داشتو(سی بیشترین$1{{PLURAL:$1|day|days}})',
+'tog-watchcreations' => 'بلگیایی که مه راس کمه و فایلیایی که مه سوار کمه اضاف کو د سیل برگه مه',
+'tog-watchdefault' => 'بلگیا و فایلایی که مه ویرایشت کمه اضاف کو د سیل برگم',
+'tog-watchmoves' => 'بلگیاو فایلیایی که مه جاوه جا کمه د سیل برگم اضاف کو',
+'tog-watchdeletion' => 'بلگیا و فایلایی که مه پاک کمه اضاف کو د سیل برگم',
+'tog-minordefault' => 'همه ویرایشتیا کؤچک نه وا پیش فرض بیئن نشو دار کو.',
+'tog-previewontop' => 'پیش سیل نه دما جعوه ویرایشت نشو بیئه',
+'tog-previewonfirst' => 'پیش سیل نه د اولین ویرایشت نشو بیئه',
+'tog-enotifusertalkpages' => 'وختی که بلگه گپسن کارور آلشت پیدا کرد منه وا ایمیل خور کو',
+'tog-shownumberswatching' => 'انازه کاروریایی که د حالت دیئنن نشو بیه',
+'tog-oldsig' => 'امضايی هيئش:',
+'tog-uselivepreview' => 'د پیش سیل زنه استفاده کو',
+'tog-watchlisthideown' => 'قام كو ويرايشت منه د',
+'tog-watchlisthideminor' => 'قام كو ويرايشت کؤچک منه د',
+'tog-diffonly' => 'بلگیایی که شومل فرخیا هارن نشون نیه',
+'tog-showhiddencats' => 'دسه يا قام بيئنه نشون بيه',
+
+'underline-always' => 'هميشه',
+'underline-never' => 'هيژوخت',
+'underline-default' => 'پوسه یا مرورگر پیش فرض',
+
+# Font style option in Special:Preferences
+'editfont-style' => 'راساگه فونت شلک نه ویرایشت کو',
+'editfont-default' => 'مرورگر پیش بینی بیه',
+'editfont-monospace' => 'فونت تک بلگه ای',
+'editfont-sansserif' => 'سان سریف فونت',
+'editfont-serif' => 'فونت سريف',
+
+# Dates
+'sunday' => 'يه شمه',
+'monday' => 'دوشمه',
+'tuesday' => 'سه شمه',
+'wednesday' => 'چارشمه',
+'thursday' => 'پن شمه',
+'friday' => 'جمه',
+'saturday' => 'شمه',
+'sun' => 'يه شمه',
+'mon' => 'دوشمه',
+'tue' => 'سه شمه',
+'wed' => 'چارشمه',
+'thu' => 'پن شمه',
+'fri' => 'جمه',
+'sat' => 'شمه',
+'january' => 'جانويه',
+'february' => 'فبريه',
+'march' => 'مارش',
+'april' => 'آبريل',
+'may_long' => 'ما',
+'june' => 'جوئن',
+'july' => 'جولای',
+'august' => 'اگوست',
+'september' => 'سپتامر',
+'october' => 'اكتور',
+'november' => 'نوامر',
+'december' => 'دسامر',
+'january-gen' => 'جانويه',
+'february-gen' => 'فوريه',
+'march-gen' => 'مارش',
+'april-gen' => 'آوريل',
+'may-gen' => 'ما',
+'june-gen' => 'جوئن',
+'july-gen' => 'جولای',
+'august-gen' => 'اگوست',
+'september-gen' => 'سپتامر',
+'october-gen' => 'اكتور',
+'november-gen' => 'نوامر',
+'december-gen' => 'دسامر',
+'jan' => 'ژانويه',
+'feb' => 'فبريه',
+'mar' => 'مارش',
+'apr' => 'آبريل',
+'may' => 'ما',
+'jun' => 'جوئن',
+'jul' => 'جولا',
+'aug' => 'اوگوست',
+'sep' => 'سپتامر',
+'oct' => 'اكتور',
+'nov' => 'نوامر',
+'dec' => 'دسامر',
+'january-date' => 'جانويه $1',
+'february-date' => 'فوريه  $1',
+'march-date' => 'مارس  $1',
+'april-date' => 'آوريل $1',
+'may-date' => 'ما $1',
+'june-date' => 'جوئن $1',
+'july-date' => 'جولاي  $1',
+'august-date' => 'اوت  $1',
+'september-date' => 'سپتامر $1',
+'october-date' => 'اكتور  $1',
+'november-date' => 'نوامر  $1',
+'december-date' => 'دسامر $1',
+
+# Categories related messages
+'pagecategories' => '{{PLURAL:$1|دسه|دسه يا}}',
+'category_header' => 'بلگيا مئن دسه "$1"',
+'subcategories' => 'زيردسه يا',
+'category-media-header' => 'رسانه د دسه "$1"',
+'category-empty' => 'ای دسه واقعن شومل هیژ بلگه ای یا رسانه ای نی',
+'hidden-categories' => '{{PLURAL:$1|دسته قام بيه|دسته يا قام بيه}}',
+'hidden-category-category' => 'دسه یا قام بیه',
+'category-subcat-count' => '{{جمی:$2|ای دسه شومل بلگه نهاییه .| {{جمی:$1| بلگه هئ|$1 بلگیا هئن}} د ای زیردسه, خارج د $2 کل.}}',
+'category-article-count' => '{{جمی:$2|ای دسه شومل بلگه نهاییه .| {{جمی:$1| بلگه هئ|$1 بلگیا هئن}} د ای دسه, خارج د $2 کل.}}',
+'listingcontinuesabbrev' => 'دماله',
+'index-category' => 'بلگيا سيائه دار',
+'noindex-category' => 'بلگيا بی سيائه',
+'broken-file-category' => 'بلگیایی که هوم پیوند فایلیا اشکسه دارن',
+
+'about' => 'دباره',
+'article' => 'محتوا بلگه',
+'newwindow' => '(نيمدری  تازه وا کو)',
+'cancel' => 'رد كردن',
+'moredotdotdot' => 'بيشتر',
+'morenotlisted' => 'ای ليست كامل نبيه',
+'mypage' => 'بلگه',
+'mytalk' => 'چك چنه',
+'anontalk' => 'دباره نشونی ای آی پی قصه بكيد',
+'navigation' => 'ناوگشتن',
+'and' => '&#32;و',
+
+# Cologne Blue skin
+'qbfind' => 'فهمسن،جسن',
+'qbbrowse' => 'قرض گرتن',
+'qbedit' => 'ويرايشت',
+'qbpageoptions' => 'ای بلگه',
+'qbmyoptions' => 'بلگيا مه',
+'qbspecialpages' => 'بلگيا ويجه',
+'faq' => 'اف ای كيو',
+'faqpage' => 'پروجه:اف اي كيو',
+
+# Vector skin
+'vector-action-addsection' => 'موضوع اضاف بكيد',
+'vector-action-delete' => 'حذف بكيد',
+'vector-action-move' => 'جاوه جا بوئيت',
+'vector-action-protect' => 'حمايت بكيد',
+'vector-action-undelete' => 'حذف نبيئني',
+'vector-action-unprotect' => 'حمايت آلشت بكيد',
+'vector-view-create' => 'راس كردن',
+'vector-view-edit' => 'ويرايشت',
+'vector-view-history' => 'ديئن ويرگار',
+'vector-view-view' => 'حنن',
+'vector-view-viewsource' => 'سرچشمه نه بوينيت',
+'actions' => 'جمشت',
+'namespaces' => 'نوم جا',
+'variants' => 'آلشت ونی يا',
+
+'navigation-heading' => 'منو ناوگشتن',
+'errorpagetitle' => 'غلط',
+'returnto' => 'ورگشت وه $1.',
+'tagline' => 'د {{SITENAME}}',
+'help' => 'هومياری',
+'search' => 'پی چوری',
+'searchbutton' => 'پی جوری',
+'go' => 'رو',
+'searcharticle' => 'رو',
+'history' => 'ويرگار بلگه',
+'history_short' => 'ويرگار',
+'updatedmarker' => 'د آخرین دیئن مه روزآمد کو',
+'printableversion' => 'نسقه چاپ بيئنی',
+'permalink' => 'چسب ون هميشئی',
+'print' => 'چاپ كردن',
+'view' => 'ديئن',
+'edit' => 'ويرايشت',
+'create' => 'راس كردن',
+'editthispage' => 'ويرايشت ای بلگه',
+'create-this-page' => 'راس كردن ای بلگه',
+'delete' => 'حذف كردن',
+'deletethispage' => 'ای بلگه نه حذف بكيد',
+'undeletethispage' => 'ای بلگه نه حذف نكيد',
+'undelete_short' => 'پاک نکو {{جمی:$1|یه گل ویرایشت|$1 ویرایشتیا}}',
+'protect' => 'حمايت بكيد',
+'protect_change' => 'آلشت بكيد',
+'protectthispage' => 'ای بلگه نه حفاظت بكيد',
+'unprotect' => 'حمايت آلشت بكيد',
+'unprotectthispage' => 'حفاظت دی بلگه نه آلشت بكيد',
+'newpage' => 'بلگه نو',
+'talkpage' => 'دباره ای بلگه قصه بكيد',
+'talkpagelinktext' => 'وت و واچ',
+'specialpage' => 'بلگه ويجه',
+'personaltools' => 'اوزاريا شصقی',
+'postcomment' => 'بشه تازه',
+'articlepage' => 'ديئن محتوا بلگه',
+'talk' => 'گپ',
+'views' => 'ديئنيا',
+'toolbox' => 'اوزاريا',
+'userpage' => 'ديئن بلگه كارور',
+'projectpage' => 'ديئن بلگه پروجه',
+'imagepage' => 'ديئن بلگه فايل',
+'mediawikipage' => 'ديئن بلگه پيغوم',
+'templatepage' => 'ديئن بلگه قالو',
+'viewhelppage' => 'ديئن بلگه هومياری',
+'categorypage' => 'ديئن بلگه دسه بنی',
+'viewtalkpage' => 'ديئن چك چنه يا',
+'otherlanguages' => 'د زونيا هنی',
+'redirectedfrom' => '(ورگشتن د$1)',
+'redirectpagesub' => 'بلگه دوباره ورگشتن',
+'lastmodifiedat' => 'ای بلگه تازه ايا وضع آلشت بيه د $1, د $2.',
+'viewcount' => 'ای بلگه قاول دسترسی بيه {{PLURAL:$1|once|$1 times}}.',
+'protectedpage' => 'بلگه حفاظت بيه',
+'jumpto' => 'پئرستن د',
+'jumptonavigation' => 'ناوگشتن',
+'jumptosearch' => 'پی جوری',
+'pool-errorunknown' => 'خطا ناشناس',
+
+# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
+'aboutsite' => 'دباره {{SITENAME}}',
+'aboutpage' => 'پروجه:دباره',
+'copyrightpage' => '{{ns:پروجه}}:کپی رایت',
+'currentevents' => 'پيشومدل تازه باو',
+'currentevents-url' => 'پروجه:پيشومدل تازه باو',
+'disclaimers' => 'منكرون',
+'disclaimerpage' => 'پروجه:منكر بيئن كاروريا',
+'edithelp' => 'هومياری سی ويرايشت',
+'helppage' => 'هومياری:محتوا',
+'mainpage' => 'سرآسونه',
+'mainpage-description' => 'سرآسونه',
+'policy-url' => 'پروجه:خط و مش',
+'portal' => 'تلگه جمی',
+'portal-url' => 'پروجه:تلگه جمی',
+'privacy' => 'رهبرد رازداری',
+'privacypage' => 'پروجه: خط مشی راز واداشتن',
+
+'badaccess' => 'خطا :اجازه بئیر',
+'badaccess-group0' => 'شما اجازه انجوم کاری که حاستیت نارین',
+
+'versionrequired' => 'یه نسقه د نیازمنیا ویکی رسانه
+$1',
+
+'ok' => 'خوئه',
+'retrievedfrom' => 'بازيافته د"$1"',
+'youhavenewmessages' => 'شما داريت $1($2)',
+'youhavenewmessagesmanyusers' => 'شما $1 د خيلی كاروريا داريت ($2).',
+'newmessagesdifflinkplural' => 'آخر {{PLURAL:$1|change|changes}}',
+'youhavenewmessagesmulti' => 'شما یه گل پیغوم تازه د $1 داریتو',
+'editsection' => 'ويرايشت',
+'editold' => 'ويرايشت',
+'viewsourceold' => 'سرچشمه نه بوينيت',
+'editlink' => 'ويرايشت',
+'viewsourcelink' => 'سرچشمه نه بوينيت',
+'editsectionhint' => 'ويرايشت يه بشق:$1',
+'toc' => 'محتوايا',
+'showtoc' => 'نشو دائن',
+'hidetoc' => 'قام كردن',
+'collapsible-collapse' => 'جم كردن',
+'collapsible-expand' => 'وا كردن',
+'thisisdeleted' => 'دیئن یا ورگنين $1?',
+'viewdeleted' => 'دیئن$1?',
+'feedlinks' => 'غذا دهنه:',
+'feed-invalid' => 'نوع مشترک بین خورحو نامعتور',
+'site-rss-feed' => 'خورخو RSS سی $1',
+'site-atom-feed' => 'خور حون Atom سی $1',
+'page-rss-feed' => 'خورخو RSS سی «$1»',
+'page-atom-feed' => 'خور حون Atom سی $1',
+'red-link-title' => '$1(بلگه وجود ناره)',
+'sort-descending' => 'كم بيئن منظم',
+'sort-ascending' => 'زياد بيئن منظم',
+
+# Short words for each namespace, by default used in the namespace tab in monobook
+'nstab-main' => 'بلگه',
+'nstab-user' => 'بلگه كارور',
+'nstab-media' => 'بلگه رسانه',
+'nstab-special' => 'بلگيا ويجه',
+'nstab-project' => 'بلگه پروجه',
+'nstab-image' => 'فاين',
+'nstab-mediawiki' => 'پيغوم',
+'nstab-template' => 'قالو',
+'nstab-help' => 'بلگه هومياری',
+'nstab-category' => 'دسه',
+
+# Main script and global functions
+'nosuchaction' => 'چنو كاری وجود ناره',
+'nosuchspecialpage' => 'چنو بلگه خاصی وجود ناره',
+
+# General errors
+'error' => 'خطا',
+'databaseerror' => 'خطا د جاگه دونسمنيا',
+'databaseerror-text' => 'یه خطا جست کردن د پایگا داده پیش اوما.یه ممکنه یه در کار ونن د نرم اوزار پیش بیاره',
+'databaseerror-textcl' => 'خطاجست گرتن پايگاه دونسمنيا پيشومد كرده',
+'databaseerror-query' => 'نوم گشتن: $1',
+'databaseerror-function' => 'تابع:$1',
+'databaseerror-error' => 'خطا: $1',
+'laggedslavemode' => 'زنهار:بلگه شايت شومل روزامديا تازه باو نبوئه',
+'readonly' => 'جاگه دونسمنيا بسه بيه',
+'missing-article' => 'پاگا داده نتونه بلگه ای با پیدا بکه بجوره.که نومش $1 و $2 هئ.
+معمولند یه سی یه که فرخ ویرگار رئته دش بیه پاک بیه.',
+'missingarticle-rev' => '(دوواره ديئن#: $1)',
+'missingarticle-diff' => '(فرخ: $1، $2)',
+'internalerror' => 'خطا داخلی',
+'internalerror_info' => 'خطا داخلی:$1',
+'filecopyerror' => 'نبوئه فایل $1 د $2 کپی بوئه',
+'filerenameerror' => 'نبوئه فایل $1 د $2 نوم آلشت بوئه',
+'filedeleteerror' => 'نبوئه فایل $1 پاک بوئه',
+'filenotfound' => 'نتونیت فایل $1 پیدا بکید',
+'formerror' => 'خطا:نبوئه فرم وه مو بئيت',
+'cannotdelete-title' => 'نبوئه بلگه $1 حذف بو',
+'badtitle' => 'موضو گن',
+'badtitletext' => 'عنوان بلگه حاسته بیه معتور نی،یا  یه گل مئن زونی یا مئن ویکی عنوان غلطه.
+یه شایت شومل یکی با یا بیشتر کاراکتریا نبوئه سی ای موضوعیا استفاده بوئن',
+'viewsource' => 'سرچشمه نه بوينيت',
+'viewsource-title' => 'سرچشمه $1 بوينيت',
+'mycustomcssprotected' => 'شما حق ناریت ای بلگه سی اس اس نه ویرایشت بکید',
+'mycustomjsprotected' => 'شما حق ناریت ای بلگه جاوا اسکریپت نه ویرایشت بکید',
+'myprivateinfoprotected' => 'شما حق ناریت دونسمنیا خصوصی نه ویرایشت بکید',
+'mypreferencesprotected' => 'شما حق ناریت ویجگی یا هنی تونه ویرایشت بکید',
+'ns-specialprotected' => 'بلگیا ویجه نتونن ویرایشت بوئن',
+'exception-nologin' => 'نبوئه وارد بوئيد',
+
+# Virus scanner
+'virus-scanfailed' => 'زل گشتن شکست حرد',
+'virus-unknownscanner' => 'ويروس كش ناآشگار',
+
+# Login and logout pages
+'welcomeuser' => 'خوش اومايت،$1!',
+'yourname' => 'نوم كاروری:',
+'userlogin-yourname' => 'نوم كاروری',
+'userlogin-yourname-ph' => 'نوم كاروری تو نه وارد بكيد',
+'createacct-another-username-ph' => 'نوم كاروری ته وارد كو',
+'yourpassword' => 'پاسورد:',
+'userlogin-yourpassword' => 'رمز',
+'userlogin-yourpassword-ph' => 'رمز بزه',
+'createacct-yourpassword-ph' => 'رمزه بزه',
+'yourpasswordagain' => 'دوواره رمز بزه',
+'createacct-yourpasswordagain' => 'رمز محكم كو',
+'createacct-yourpasswordagain-ph' => 'دوواره رمز بزه',
+'remembermypassword' => 'اومائن وا مئن منه د ای مرورگر د ویر داشتو(سی بیشترین$1{{PLURAL:$1|day|days}})',
+'userlogin-remembermypassword' => 'منه مئن سيستم وادار',
+'userlogin-signwithsecure' => 'د وصل بيئن امن استفاده كو',
+'yourdomainname' => 'پوشگیر شما:',
+'password-change-forbidden' => 'شما نتونید پاسوردیانه د ای ویکی آلشت بکید',
+'login' => 'اومائن',
+'nav-login-createaccount' => ' اومائن د سيستم/راس كردن حساو',
+'loginprompt' => 'شما وا کوکیانه سی اومائن د {{SITENAME}} کوکیانه فعال بکید.',
+'userlogin' => ' اومائن د سيستم/راس كردن حساو',
+'userloginnocreate' => 'اومائن',
+'logout' => 'رئتن',
+'userlogout' => 'د سيستم دراومائن',
+'notloggedin' => 'نبوئه وارد بوئيد',
+'userlogin-noaccount' => 'یه گل حساو ناریت؟',
+'userlogin-joinproject' => 'وصل بوييت {{SITENAME}}',
+'nologin' => 'حساو كاروری ناريت؟$1',
+'nologinlink' => 'يه گل حساو راست بكيد',
+'createaccount' => 'حساو راست بكيد',
+'gotaccount' => 'ایسنی حساو کاروری داریتو؟$1',
+'gotaccountlink' => 'اومائن',
+'userlogin-resetlink' => 'جزییات وامین اومائن تونه د ویر بردیته',
+'userlogin-resetpassword-link' => 'هنی رمز وارد بكيد',
+'helplogin-url' => 'هومياری:د حالت اومائن د سيستم',
+'userlogin-createanother' => 'يه گل حساوهنی راست بكيد',
+'createacct-join' => 'دونسمنيا دباره خوتونه د هار وارد بكيد',
+'createacct-another-join' => 'دونسمنیا یه گل حساو د هار وارد بکید',
+'createacct-emailrequired' => 'نشونی ايميل',
+'createacct-emailoptional' => 'نشونی ايميل',
+'createacct-email-ph' => 'نوم نشون ايميلتونه وارد بكيت',
+'createacct-another-email-ph' => 'يه گل ايميل وارد بكيت',
+'createacct-realname' => 'نوم راستكی(مژبوری نيئ)',
+'createaccountreason' => 'دليل',
+'createacct-reason' => 'دليل',
+'createacct-reason-ph' => 'سی چی شما داريتو يه گل حساو هنی راس می كيد',
+'createacct-captcha' => 'وارسی امنيت دار بين',
+'createacct-imgcaptcha-ph' => 'متنی نه كه د وارو ميئنيت وارد بكيد',
+'createacct-submit' => 'حساو خوتونه راس بكيد',
+'createacct-another-submit' => 'يه گل حساوهنی راست بكيد',
+'createacct-benefit-heading' => '{{نوم مالگه}} وه دس خلکی چی شما راس بیه.',
+'createacct-benefit-body1' => '{{جمی:$1|ویرایشت|ویرایشتا}}',
+'createacct-benefit-body2' => '{{جمی:$1|بلگه|بلگیا}}',
+'badretype' => 'پاسوردی که شما دئیته مطاوقت ناره',
+'userexists' => 'کارور نوم که وارد بیه د ایسه استفاده بوئه.
+لطف بکید یه گل نوم هنی انتخاو بکید',
+'loginerror' => 'خطا اومائن د سيستم',
+'createacct-error' => 'خطا راس كردن حساو',
+'createaccounterror' => 'نبوئه حساو راس بكيد:$1',
+'noname' => 'شما یه گل نوم کاروری خو ناریت',
+'loginsuccesstitle' => 'اومائن د سيستم موفق بی',
+'loginsuccess' => 'شما ایسه وارد بیته {{SITENAME}} د دعنوان "$1".\'',
+'nosuchusershort' => 'چنو کاروری وا ای نوم $1 نی ئیش.
+نیسنن تونه دوواره نئری بکیتو',
+'nouserspecified' => 'شما باید یه نوم کارور اختصاص بئیتو',
+'login-userblocked' => 'کارور قلف بیه.وامین اومائن اجازه نی ئن',
+'wrongpassword' => 'پاسورد غلط وارد بیه.
+هنی تلاش بکید',
+'wrongpasswordempty' => 'پاسوردی که دئیت حالیه.د نؤ تلاش بکیت',
+'passwordtooshort' => 'پاسورد با حداقل  {{PLURAL:$1|1 character|$1 characters}}          با',
+'password-name-match' => 'پاسوردتو با د نوم کاروریتو فرخ داشتوه',
+'password-login-forbidden' => 'وه کار گرتن ای پاسوردو نوم کاروری ممنو بیه.',
+'mailmypassword' => 'رمز هنی نه ايميل بكيد',
+'passwordremindertitle' => 'پاسورد موقت تازه سی {{SITENAME}}',
+'noemail' => 'هیچ نشونی ایمیلی سی کارور $1 ضفط نبیه.',
+'noemailcreate' => 'شما باید یه نشونی نومه معتور فراهم بکید',
+'mailerror' => 'خطا داره کل موئه:$1',
+'emailconfirmlink' => 'نشونی ايملتو نه محكم بكيد',
+'emaildisabled' => 'ای مالگه نتونه ایمیل بفرسنه',
+'accountcreated' => 'حساو راس بی',
+'createaccount-title' => 'حساو راس کرده سی  {{SITENAME}}',
+'usernamehasherror' => 'نوم کاربری نتونه شومل نیسه یا هش بوئه',
+'login-abort-generic' => 'اومائن وامین تو شکست حرد-شکست حرده',
+'loginlanguagelabel' => 'زون:$1',
+
+# Email sending
+'php-mail-error-unknown' => "خطا ناشناس مئن تاوع  PHP's mail()",
+'user-mail-no-addy' => 'سی کل کردن ایمیل بی نشونه ایمیل صورت گرته',
+
+# Change password dialog
+'resetpass' => 'پاسورد نه آلشت بكيت',
+'resetpass_header' => 'پاسورد حساوتونه آلشت بکید',
+'oldpassword' => 'پاسورد قدیمی:',
+'newpassword' => 'پاسورد تازه:',
+'retypenew' => 'رمز تازه نه دوواره بنیسید:',
+'resetpass_submit' => 'پاسور بنیت و وامین بیایت',
+'changepassword-success' => 'پاسورد شما وا موفقیت آلشت بی',
+'resetpass_forbidden' => 'پاسوردیا نتونن آلشت بوئن',
+'resetpass-submit-loggedin' => 'پاسورد نه آلشت بكيت',
+'resetpass-submit-cancel' => 'رد كردن',
+'resetpass-temp-password' => 'رمز موقت:',
+
+# Special:PasswordReset
+'passwordreset' => 'د نۈ وارد كردن رمز',
+'passwordreset-legend' => 'د نۈ وارد كردن رمز',
+'passwordreset-username' => 'نوم كاروری:',
+'passwordreset-domain' => 'پوشگیر',
+'passwordreset-capture' => 'ایمیل نتیجه نه بوینیتو؟',
+'passwordreset-email' => 'نشونی ايميل',
+'passwordreset-emailsent' => 'پاسورد هنی سی ایمیل کل بیه.',
+
+# Special:ChangeEmail
+'changeemail' => 'ایمیل تو نه آلشت بکید',
+'changeemail-header' => 'ایمیل حساوتونه آلشت بکید',
+'changeemail-oldemail' => 'نشونی ایمیل تازه باو:',
+'changeemail-newemail' => 'نشونی ایمیل تازه',
+'changeemail-none' => '(هيش كوم)',
+'changeemail-password' => 'شما {{SITENAME}} پاسورد:',
+'changeemail-submit' => 'آلشت کردن ایمیل',
+'changeemail-cancel' => 'رد كردن',
+
+# Edit page toolbar
+'bold_sample' => 'متن توپر بيه',
+'bold_tip' => 'متن توپر بيه',
+'italic_sample' => 'نوشته كج كوله',
+'italic_tip' => 'نوشته كج كوله',
+'link_sample' => 'عنوان لينك',
+'link_tip' => 'لینک مئن ون',
+'extlink_sample' => 'http://www.example.com نوم ديس ون',
+'extlink_tip' => 'هوم پیوند خارجی(د ویر داشتو)',
+'headline_sample' => 'سرخط نوشته',
+'headline_tip' => 'قدم 2 خط سر ون',
+'nowiki_sample' => 'د ایچه یه گل متن بی شلک وارد بکید',
+'nowiki_tip' => 'شلک ویکی نه ندید بگر',
+'image_tip' => 'فایل محاط بيه',
+'media_tip' => 'فایل هوم پیوند',
+'sig_tip' => 'امضا شما و برچسو وخت',
+'hr_tip' => 'خط افق ونه(سوا سوا دش استفاده کو)',
+
+# Edit pages
+'summary' => 'چكسته',
+'minoredit' => 'يه ويرايشت كؤچكيه',
+'watchthis' => 'ديئن ای بلگه',
+'savearticle' => 'بلگه ضبط بوئه',
+'preview' => 'پيش سيل',
+'showpreview' => 'پيش نمائش نشون بيئه',
+'showlivepreview' => 'پیش سیل زنه',
+'showdiff' => 'آلشتيانه نشون بيئه',
+'anoneditwarning' => 'زنهار شما وامین نیومایته.
+نشونی آی پی تو د ویرگار ویرایشت ای بلگه ضفط بوئه',
+'missingcommenttext' => 'لطفن د ایچه نظر بیئتو',
+'summary-preview' => 'چکسته پیش سیل:',
+'blockedtitle' => 'كارور قلف بيه',
+'blockednoreason' => 'هیژ دلیلی دئه نبیه',
+'whitelistedittext' => 'شما باید $1 سی ویرایشت بلگیا',
+'nosuchsectiontitle' => 'نبوئه بشخ پیدا بوئه',
+'loginreqtitle' => 'وامین اومائن لازمه',
+'loginreqlink' => 'اومائن',
+'accmailtitle' => 'پاسورد کل بی',
+'newarticle' => 'تازه',
+'newarticletext' => 'شما وادما هوم پیوندی هئیت که وجود ناره.
+سی راس کردن بلگه.شرو د نیسنن مئن جعوه هاری بکید(سیل[[{{MediaWiki:Helppage}}|]] سی دونسمنی بیشتر بکید).
+ار شما سی اشتوا کردن هایئن ایچه، دگمه وادما رئتن مرورگر تونه بپورنیت.',
+'noarticletext' => 'د تازه یا د ای بلگه متن نی.
+شما تونید د[[Special:Search/{{PAGENAME}}|search for this page title]] بگردید د ای بلگه یا د بلگیا هنی یا<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}   د هنی پی جوری بوئه  logs]</span>   
+   [{{fullurl:{{FULLPAGENAME}}|action=edit}} یای ای بلگه نه ویرایشت بکیدpage]</span>.',
+'noarticletext-nopermission' => 'د تازه یا د ای بلگه متن نی.
+شما تونید د[[Special:Search/{{PAGENAME}}|search for this page title]] بگردید د ای بلگه یا د بلگیا هنی یا<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}   د هنی پی جوری بوئه  logs]</span>      اما شما حق ناریتو ای بلگه نه راس بکیت',
+'updated' => '(تازه بيه)',
+'note' => "'''نيسنن:'''",
+'previewnote' => 'فقط ای پیش سیل د ویرتو با.
+آلشتیاتو هنی ذخیره نبیه.',
+'continue-editing' => 'رو د راساگه ویرایشت',
+'editing' => 'د حالت ويرايشت$1',
+'creating' => 'راس كردن $1',
+'editingsection' => 'د حال ویرایشت$1(بشخ)',
+'editingcomment' => 'د حال ویرایشت$1(بشخ تازه)',
+'yourtext' => 'متن شما',
+'yourdiff' => 'فرخيا',
+'templatesused' => '{{جمی:$1|قالو|قالویا}}د ای بلگه استفاده بیه:',
+'template-protected' => '(حمايت بيه)',
+'template-semiprotected' => '(نيم-حفاظت بيه)',
+'hiddencategories' => 'ای بلگه يه اندوم د{{PLURAL:$1|1 hidden category|$1 hidden categories}}: هئ',
+'permissionserrors' => 'خطا اجازه دئین',
+'permissionserrorstext-withaction' => 'شما سی $2 اجازه ناریت
+سی دمال کردن{{PLURAL:$1|reason|reasons}}:',
+'recreate-moveddeleted-warn' => "'''زنهار شما بلگه ای که وادما پاک بیه هنی راس کردیته'''
+شما باید دونسه بایت که آیا هنی سی نها گرتن ویرایشت ای بلگه خوئه.
+پاک بیئن و جمشت سی ای بلگه سی راحتی تو فراهم بیه:",
+'moveddeleted-notice' => 'ای بلگه پاک بیه.
+پاک بین و جمشت ای بلگه سی سرچشمه دئین فراهم بیه',
+'edit-conflict' => 'مخالفت نه ویرایشت بکید',
+'postedit-confirmation' => 'ویرایشتتو ذخیره بی',
+'defaultmessagetext' => 'متن پیغوم پیش فرض',
+
+# Content models
+'content-model-wikitext' => 'ويكی متن',
+'content-model-text' => 'متن ساده',
+'content-model-javascript' => 'جاوا اسكريپت',
+'content-model-css' => 'سی اس اس',
+
+# Parser/template warnings
+'post-expand-template-inclusion-warning' => 'زنئار قالو شومل انازه ای یه که فره گپه.پاره ای د قالویا نه د بر نگره',
+'post-expand-template-inclusion-category' => 'بلگیا شومل قالوی ین که انازش د حد اومائه وه در',
+'post-expand-template-argument-warning' => 'زنهار ای بلگه شومل حداقل یه قالو سی چک چنه یه که انازه فره گپه.
+گپسنیا پاک بینه.',
+'post-expand-template-argument-category' => 'بلگه شومل قالو چک چنیا د بین رئته',
+
+# History pages
+'viewpagelogs' => 'سی ای بلگه بوینتو.',
+'currentrev' => 'آخرین دوواره دیئن',
+'currentrev-asof' => 'آخرين دووار ديئن چی $1',
+'revisionasof' => 'دوواره ديئن $1',
+'revision-info' => 'دوواره سیل بیه چی $1 وا $2',
+'previousrevision' => 'اصلاح دمايی',
+'nextrevision' => 'تازه ترن دوبار دیئن',
+'currentrevisionlink' => 'آخرین دوواره دیئن',
+'cur' => 'تازه باو',
+'next' => 'نيایی',
+'last' => 'دمايی',
+'page_first' => 'اولی',
+'page_last' => 'آخر',
+'history-fieldset-title' => 'ویرگار مرور ون',
+'history-show-deleted' => 'فقط پاك بيه',
+'histfirst' => 'قديمي تري',
+'histlast' => 'تازه تري',
+'historyempty' => '(حالی)',
+
+# Revision feed
+'history-feed-title' => 'ویرگار دوواره دیئن',
+'history-feed-item-nocomment' => '$1 د
+$2',
+
+# Revision deletion
+'rev-delundel' => 'آلشت وضئيت ديئن',
+'rev-showdeleted' => 'نشو دائن',
+'revdelete-show-file-submit' => 'هری',
+'revdelete-hide-comment' => 'چکسه نه ویرایشت بکید',
+'revdelete-radio-same' => 'آلشت نکید',
+'revdelete-radio-set' => 'قام بیه',
+'revdelete-radio-unset' => 'دیینی',
+'revdelete-log' => 'دلیل:',
+'revdel-restore' => 'آلشت وضئيت ديئن',
+'revdel-restore-deleted' => 'پاك كردن مراجعيا',
+'revdel-restore-visible' => 'مراجعات ديئنی',
+'pagehist' => 'ويرگار بلگه',
+'deletedhist' => 'ویرگار پاک بیه',
+'revdelete-otherreason' => 'دلیل هنی:',
+'revdelete-reasonotherlist' => 'دلیل هنی',
+'revdelete-edit-reasonlist' => 'دلیلیا پاک کردنه نه ویرایشت بکید',
+
+# History merging
+'mergehistory-from' => 'بلگه سرچشمه:',
+'mergehistory-into' => 'بلگه مقصد:',
+'mergehistory-reason' => 'دليل:',
+
+# Merge log
+'revertmerge' => 'بی لوئه',
+
+# Diffs
+'history-title' => 'دوواره دیئن ویرگار$1',
+'lineno' => 'خط $1:',
+'compareselectedversions' => 'دوبار دیئنیایی که انتخاو بینه مقایسه بکیتو',
+'editundo' => 'رد كردن',
+'diff-empty' => '(بی فرق)',
+'diff-multi' => '({{جمی:$1|یه گل دوواره دیئن مینجایی|$1مینجا دوواره دیئنیا}} وا {{جمی:$2|یه کارور|$2 کاروریا}} نشو دئه نی)',
+
+# Search results
+'searchresults' => 'نتيجه يا پی جوری',
+'searchresults-title' => 'نتيجه يا پی جوری سی "$1"',
+'searchsubtitleinvalid' => 'شما پی جوریت سی',
+'titlematches' => 'عنوان بلگه مطاوقت داره',
+'prevn' => 'وادما {{PLURAL:$1|$1}}',
+'nextn' => 'نيايی {{PLURAL:$1|$1}}',
+'prevn-title' => 'پيشتر $1 {{PLURAL:$1|نتيجه|نتيجيا}}',
+'nextn-title' => 'نيايی $1 {{PLURAL:$1|نتيجه|نتيجيا}}',
+'shown-title' => 'نشون دائن $1 {{PLURAL:$1|نتيجه|نتيجه}} سی همه بلگه',
+'viewprevnext' => 'ديئن ($1 {{int:pipe-separator}} $2) ($3)',
+'searchmenu-legend' => 'گزينه يا هنی پی جوری',
+'searchmenu-exists' => "'''ایچه بلگه ای هئ وه نوم\"[[:\$1]]\" که ها د ای ویکی'''",
+'searchmenu-new' => "'''ای بلگه نه راس كو \"[[:\$1]]\" د ای  ويكي!'''",
+'searchprofile-articles' => 'بلگيا محتوا',
+'searchprofile-project' => 'بلگيا هومياری پروجه',
+'searchprofile-images' => 'رسانيا جمی',
+'searchprofile-everything' => 'همه چی',
+'searchprofile-advanced' => 'پيشرفته',
+'searchprofile-articles-tooltip' => 'بگرد مئن $1',
+'searchprofile-project-tooltip' => 'بگرد مئن $1',
+'searchprofile-images-tooltip' => 'بگرد سی فايليا',
+'searchprofile-everything-tooltip' => 'همه محتوا نه پی جوری كو (شاملا بلگيا چك چنه)',
+'searchprofile-advanced-tooltip' => 'نوم جايا نوم ديار بگرد',
+'search-result-size' => '$1 ({{PLURAL:$2|بی واچه يل|واچه تكی|واچه يل|$2 واچه يل|$2 واچه}})',
+'search-result-category-size' => '{{جمی:$1|1 اندوم|$1 اندومیا}} ({{جمی:$2|1 زیردسه|$2 زیردسه یا}}, {{جمی:$3|1 فایل|$3 فایلیا}})',
+'search-redirect' => '(ورگشتن $1)',
+'search-section' => '(بشق $1)',
+'search-suggest' => 'منظورت يه بی:$1',
+'search-interwiki-more' => '(بیشتر)',
+'search-relatedarticle' => 'مرتوط',
+'searchrelated' => 'مرتوط',
+'searchall' => 'همه',
+'showingresultsheader' => "{{PLURAL:$5|نتيجه '''$1''' د'''$3'''|نتيجه يا '''$1 - $2''' د'''$3'''}} سيli'''$4'''",
+'search-nonefound' => 'هیژ نتیجه یی سی پی جست تو مطاوقت نکرده',
+'powersearch' => 'پی جوری پیشبرده',
+'powersearch-legend' => 'پی جوری پیشبرده',
+'powersearch-field' => 'پی جوری سی',
+'powersearch-togglelabel' => 'چك كردن:',
+'powersearch-toggleall' => 'همه',
+'powersearch-togglenone' => 'هيش كوم',
+'search-external' => 'پی جوری د در',
+
+# Preferences page
+'preferences' => 'خصوصيات هنی',
+'mypreferences' => 'خصوصيات هنی',
+'prefs-edits' => 'شماره ویرایشتا:',
+'changepassword' => 'پاسورد نه آلشت بكيت',
+'prefs-skin' => 'پوست',
+'skin-preview' => 'پیش سیل',
+'prefs-datetime' => 'وخت و زمون',
+'prefs-user-pages' => 'بلگیا كارور',
+'prefs-personal' => 'پروفایل کارور',
+'prefs-rc' => 'آلشتیا تازه باو',
+'prefs-watchlist' => 'سیل برگ',
+'prefs-misc' => 'شيوسن',
+'prefs-resetpass' => 'پاسورد نه آلشت بكيت',
+'prefs-changeemail' => 'نشونی ایمیل تو نه آلشت بکید',
+'saveprefs' => 'ذخيره كردن',
+'prefs-editing' => 'د حالت ويرايشت',
+'rows' => 'رديفيا:',
+'columns' => 'ستينا:',
+'searchresultshead' => 'پی جوری',
+'stub-threshold-disabled' => 'د كار ونن',
+'timezonelegend' => 'وخت راساگه',
+'localtime' => 'وخت ولاتی:',
+'timezoneuseserverdefault' => 'وخت راساگه',
+'timezoneoffset' => 'آفست:',
+'servertime' => 'وخت سرور:',
+'timezoneregion-africa' => 'افرقا',
+'timezoneregion-america' => 'امركا',
+'timezoneregion-antarctica' => 'قطو هار ونه',
+'timezoneregion-arctic' => 'قطو شمال',
+'timezoneregion-asia' => 'آسيا',
+'timezoneregion-atlantic' => 'جهون آو آتلانتیک',
+'timezoneregion-australia' => 'استراليا',
+'timezoneregion-europe' => 'اوروپا',
+'timezoneregion-indian' => 'جهوناو هند',
+'timezoneregion-pacific' => 'جهوناو آروم',
+'prefs-searchoptions' => 'پی جوری',
+'prefs-namespaces' => 'نوم جایا',
+'default' => 'پيش فرض',
+'prefs-files' => 'فايلا',
+'youremail' => 'ايميل:',
+'yourrealname' => 'نوم راستكی:',
+'yourlanguage' => 'زون:',
+'yournick' => 'امضا تازه:',
+'email' => 'پیومک برقی',
+'prefs-help-email' => 'نشونی ایمیل اختیاری هئ.اما سی بازجست پاسورد دش نیاز بوئه.شما باید پاسوردتونه د ویر بوریت',
+'prefs-help-email-others' => 'شما می تونید سی پیوند گرتن تو وا نهایین ایمیل مئن یه هوم پیوند د بلگه کاروری یا بلگه چک چنه تو انتخاو بکید.
+نشونی ایمیلتو وختی که کاروریا هنی وا تو پیوند می گرن دیار نی.',
+'prefs-editor' => 'ويرايشتگر',
+'prefs-preview' => 'پیش سیل',
+'prefs-diffs' => 'فرخیا',
+
+# User rights
+'userrights-user-editname' => 'نوم كاروری ته وارد كو',
+'editusergroup' => 'ویرایشت گرویا کاروری',
+'userrights-editusergroup' => 'ویرایشت گرویا کاروری',
+'saveusergroups' => 'ذخیره کرد گرویا کاروری',
+'userrights-groupsmember' => 'اندوم:',
+'userrights-reason' => 'دليل:',
+
+# Groups
+'group' => 'گرو',
+'group-user' => 'کاروریا',
+'group-autoconfirmed' => 'کاروریا خودوادار',
+'group-bot' => 'بتیا',
+'group-sysop' => 'مدیریا',
+'group-bureaucrat' => 'بروکراتیا',
+'group-all' => '(همه)',
+
+# Rights
+'right-read' => 'حنن بلگیا',
+'right-edit' => 'ویرایشت بلگیا',
+
+# Special:Log/newusers
+'newuserlogpage' => 'راس بیه وا کارور',
+
+# Associated actions - in the sentence "You do not have permission to X"
+'action-read' => 'ای بلگه نه بحون',
+'action-edit' => 'ای بلگه نه ويرايشت بكيد',
+'action-createpage' => 'راس کردن بلگیا',
+'action-move' => 'لی بلگه جا وه جا کو',
+'action-delete' => 'ای بلگه نه پاک کو',
+'action-deleterevision' => 'ای بازدئین پاک کو',
+'action-undelete' => 'ای بلگه نه پاک نکو',
+'action-sendemail' => 'ایمیلیانه کل کو',
+
+# Recent changes
+'nchanges' => '$1 {{جمی:$1|آلشت|آلشتیا}}',
+'enhancedrc-history' => 'ويرگار',
+'recentchanges' => 'تغيريا تازه',
+'recentchanges-legend' => 'گزينه يا آلشتيا تازه',
+'recentchanges-feed-description' => 'دو بیشتر آلشتیا تازباو نه د ویکی که ها د هوال حون پیگری کو.',
+'recentchanges-label-newpage' => 'ای ويرايشت يه بلگه تازه راس كرده',
+'recentchanges-label-minor' => 'يه ويرايشت كؤچكيه',
+'recentchanges-label-bot' => 'ای ويرايشت نه يه بوت انجوم ديئه',
+'recentchanges-label-unpatrolled' => 'ای ويرايشت هنی تيه واداشت نبيه',
+'rcnote' => "د هار{{جمی:$1|هئ'''1''' آلشت|آخری هئ ن '''$1'''آلشتیا}}د آخر{{جمی:$2|رو|'''$2''' روزیا}}, چی $5, $4.",
+'rcnotefrom' => 'د هار آلشتیا د $2 هیئن(د بال د $1 نشون دئه بیه)',
+'rclistfrom' => 'آلشتیا تازه ایی که وا $1 شرو بیه نشونش بئه',
+'rcshowhideminor' => 'ويرايشتيا کؤچک $1',
+'rcshowhidebots' => '$1 رواتيا یا بوتيا',
+'rcshowhideliu' => '$1 کارورياداخل بيه',
+'rcshowhideanons' => '$1 کاروريا ناشناس',
+'rcshowhidepatr' => '$1 ویرایشتیا تیه پرس بیه',
+'rcshowhidemine' => 'ويرايشتيا مه$1',
+'rclinks' => 'آخرین آلشتیا $1 نشو بیه د اخرین روزیا $2',
+'diff' => 'فرخ',
+'hist' => 'ويرگار',
+'hide' => 'قام كردن',
+'show' => 'نشون دائن',
+'minoreditletter' => 'م',
+'newpageletter' => 'ن',
+'boteditletter' => 'ب',
+'rc_categories_any' => 'هرکوم',
+'rc-enhanced-expand' => 'جزيات نشون بيئه',
+'rc-enhanced-hide' => 'جزياته قام كو',
+
+# Recent changes linked
+'recentchangeslinked' => 'تغيريا مرتبط',
+'recentchangeslinked-toolbox' => 'تغيريا مرتبط',
+'recentchangeslinked-title' => 'آلشتيا مرتوط وا $1',
+'recentchangeslinked-summary' => 'ای نوم گه تازه د بلگیایی که وا بلگیا ویجه هوم پیوند بینه آلشت بیه(یا سی اندومیا دسه بنی بیه)
+بلگیا یی که هان [[Special:Watchlist|your watchlist]]و گپ بینه',
+'recentchangeslinked-page' => 'نوم بلگه:',
+'recentchangeslinked-to' => 'آلشتیایی که د بلگه یا هوم پیوند بینه وه جا بلگه دئیه بیه نشو بیه',
+
+# Upload
+'upload' => 'بلم گير كردن فايلا',
+'uploadlogpage' => 'سوارکرد',
+'filename' => 'نوم فایل',
+'filedesc' => 'چكسته',
+'fileuploadsummary' => 'چکسه',
+'filesource' => 'سرچشمه:',
+'uploadedimage' => 'سوارکرد"[[$1]]"',
+'upload-source' => 'سرچشمه فایل',
+
+# img_auth script messages
+'img-auth-accessdenied' => 'دسرسی منع بی',
+
+'license' => 'ليانس دار بيئن',
+'license-header' => 'د شكل ليسانس دار بيئن',
+
+# Special:ListFiles
+'imgfile' => 'فايل',
+'listfiles_thumb' => 'بن کلکی',
+'listfiles_date' => 'تاريخ',
+'listfiles_name' => 'نوم',
+'listfiles_user' => 'كارور',
+'listfiles_size' => 'انازه',
+'listfiles_count' => 'نسقیا',
+'listfiles-latestversion' => 'نسقه تازه',
+'listfiles-latestversion-yes' => 'هری',
+'listfiles-latestversion-no' => 'نه',
+
+# File description page
+'file-anchor-link' => 'فايل',
+'filehist' => 'ويرگار فايل',
+'filehist-help' => 'ری  ويرگاريا بپورنيت تا نسقه مرتوط بونيت.',
+'filehist-deleteall' => 'همه نه پاک کو',
+'filehist-deleteone' => 'پاك كردن',
+'filehist-revert' => 'ورگنین',
+'filehist-current' => 'تازه باو',
+'filehist-datetime' => 'ويرگار/وخت',
+'filehist-thumb' => 'عسگ كؤچك بيه',
+'filehist-thumbtext' => 'كؤچك كردن سی  نسقه چی $1',
+'filehist-user' => 'كارور',
+'filehist-dimensions' => 'بعديا',
+'filehist-filesize' => 'انازه فایل',
+'filehist-comment' => 'نظر',
+'imagelinks' => 'استفاده د فايل',
+'linkstoimage' => 'دمال بيه {{PLURAL:$1|ديس ونيا بلگه|$1 ديس ون بلگيا}} دای فایل:',
+'nolinkstoimage' => 'ایچه هیژ بلگه ای سی هوم پیوند بیئن وا ای فایل نی',
+'sharedupload-desc-here' => 'فایلی که د $1 شایت د مئن پروجیا هنی استفاده بیه.
+توضی دباره[$2 file description page] د هار نشو دئئه بیه',
+
+# File deletion
+'filedelete-comment' => 'دليل:',
+'filedelete-submit' => 'پاك كردن',
+
+# MIME search
+'download' => 'گرتن',
+
+# Unused templates
+'unusedtemplateswlh' => 'هوم پیوندیا هنی',
+
+# Random page
+'randompage' => 'بلگه بختكی',
+
+# Random page in category
+'randomincategory-selectcategory-submit' => 'رو',
+
+# Statistics
+'statistics' => 'آماريا',
+'statistics-pages' => 'بلگیا',
+'statistics-users-active' => 'کاروریا کارکو',
+
+'pageswithprop-submit' => 'رو',
+
+'brokenredirects-edit' => 'ویرایشت',
+'brokenredirects-delete' => 'پاك كردن',
+
+'withoutinterwiki-legend' => 'پیشون',
+'withoutinterwiki-submit' => 'نشون دائن',
+
+# Miscellaneous special pages
+'nbytes' => '$1{{PLURAL:$1|كلی|بايت|بايت}}',
+'nmembers' => '$1 {{PLURAL:$1|اندوم|اندوميا}}',
+'prefixindex' => 'همه بلگيا وا پيشون',
+'usercreated' => '{{جنسیت:$3|راس بیه}}د $1 at $2',
+'newpages' => 'بلگيا نو',
+'move' => 'جاوه جا بوئيت',
+'pager-newer-n' => '{{جمی:$1|وانها تر 1وانها تر $1}}',
+'pager-older-n' => '{{جمی:$1|گپسالتر 1|گپسالتر $1}}',
+
+# Book sources
+'booksources' => 'سرچشمه يل كتاو',
+'booksources-search-legend' => 'پی جوری سی سرچشمه یا کتاو',
+'booksources-go' => 'رو',
+
+# Special:AllPages
+'allpages' => 'همه بلگيا',
+'alphaindexline' => '$1 د
+$2',
+'allarticles' => 'همه بلگيا',
+'allpagessubmit' => 'رو',
+
+# Special:Categories
+'categories' => 'دسه يا',
+
+# Special:LinkSearch
+'linksearch-line' => '$1 داره د $2 هوم پیوند بوئه',
+
+# Special:ListGroupRights
+'listgrouprights-members' => '(نوم گه اندومیا)',
+
+# Email user
+'emailuser' => 'ای كارور نه ايميل كو',
+
+# Watchlist
+'watchlist' => 'سیل برگ',
+'mywatchlist' => 'سیل برگ',
+'watchlistfor2' => 'سي $1 $2',
+'watch' => 'سيل كردن',
+'unwatch' => 'ديه نبيه',
+'watchlist-details' => '{{جمی:$1|$1 بلگه|$1 بلگیا}} د سیل برگتو هیش بلگه قسه کردن نی .',
+'wlshowlast' => 'آخرین$1 ساعتیا $2و روزیا $3 نشو بیئه',
+'watchlist-options' => 'گزینیا سیل برگ',
+
+# Delete
+'actioncomplete' => 'عملكرد كامل بيه',
+'actionfailed' => 'عملكرد شكست حرده',
+'dellogpage' => 'لاگ پاك كردن',
+
+# Rollback
+'rollbacklink' => 'ورگشتن',
+
+# Protect
+'protectlogpage' => 'حفاظت کردن',
+'protectedarticle' => 'حفاظت بيه [[$1]]',
+
+# Undelete
+'undeletelink' => 'بوين/دوواره آماده با',
+'undeleteviewlink' => 'ديئن',
+
+# Namespace form on various pages
+'namespace' => 'نوم جا:',
+'invert' => 'انتخاو برعسك بوئه',
+'blanknamespace' => 'اصلی',
+
+# Contributions
+'contributions' => '{{جنس:$1|کارور}} هومیاریا',
+'contributions-title' => 'هومياري كارور سي $1',
+'mycontris' => 'هومياری',
+'contribsub2' => 'سي {{جنسيت:$3|$1}} ($2)',
+'uctop' => '(تازه باو)',
+'month' => 'د ما(یا زیتر)',
+'year' => 'د سال',
+
+'sp-contributions-newbies' => 'فقط هومیاری یایی که د حساو تازه بیه نشون بئه',
+'sp-contributions-blocklog' => 'قلف',
+'sp-contributions-uploads' => 'سواركرديا',
+'sp-contributions-talk' => 'چك چنه',
+'sp-contributions-search' => 'سی هومیاریا پی جور با',
+'sp-contributions-username' => 'نوم نشون آی پی يا نوم كاروری:',
+'sp-contributions-toponly' => 'فقط ویرایشتیایی که جزئه آخرین دوواره دیئن هئین نشو بیه',
+'sp-contributions-submit' => 'پی جوری',
+
+# What links here
+'whatlinkshere' => 'كؤم ديس ونيا هان ايچه',
+'whatlinkshere-title' => 'بلگه ای که د $1 هوم پیوند بیه',
+'whatlinkshere-page' => 'بلگه',
+'linkshere' => "بلگیا نهایی د '''[[:$1]]''' هوم پیوند بیه",
+'nolinkshere' => "هیژ بگله ای د  '''[[:$1]]''' هوم پیوند نبیه",
+'isredirect' => 'بلگه دوباره ورگشتن',
+'istemplate' => 'نشونی دئن',
+'isimage' => 'فایل هوم پیوند',
+'whatlinkshere-prev' => '{{جمی:$1|دمایی|دمایی $1}}',
+'whatlinkshere-next' => '{{جمی:$1|نهایی|نهایی $1}}',
+'whatlinkshere-links' => 'هوم پیوندیا',
+'whatlinkshere-hideredirs' => '$1 دوواره د نشونی ورگشتن',
+'whatlinkshere-hidetrans' => '$ا چن نتیجه ای',
+'whatlinkshere-hidelinks' => 'هوم پیوندیا $1',
+'whatlinkshere-hideimages' => 'فایل هوم پیوندیا $1',
+'whatlinkshere-filters' => 'فيلتريا',
+
+# Block/unblock
+'ipboptions' => '2 ساعتیا:2 ساعت,1 رو:1 رو,3 روزا:3 رو,1 هفته:1 هفته,2 هفته یا:2 هفته,1 ما:1 ما,3 ما:3 میا,6 ما:6 مایا,1 سال:1سال,حد ناره:حد ناره',
+'ipblocklist' => 'كاروريا منع بيه',
+'blocklink' => 'بسته بوئه',
+'unblocklink' => 'بی قطی',
+'change-blocklink' => 'اجازه نديئن سی  آلشت',
+'contribslink' => 'هومكاری',
+'blocklogpage' => 'قلف',
+'blocklogentry' => ' [[$1]] وا یه گل وخت تموم بیئن $2 و $3  قلف بیه',
+'block-log-flags-nocreate' => 'حساو راس کردن عاجز بیه.',
+
+# Move page
+'movelogpage' => 'جاوه جا کردن',
+'revertmove' => 'لرستن',
+
+# Export
+'export' => 'وه صحرا ديئن بلگيا',
+
+# Namespace 8 related
+'allmessagesname' => 'نوم',
+'allmessagesdefault' => 'سفارشت متنی پيش فرض',
+
+# Thumbnails
+'thumbnail-more' => 'گپ كردن',
+'thumbnail_error' => 'خطا د راس بیئن بن کلئکی:$1',
+
+# Tooltip help for the actions
+'tooltip-pt-userpage' => 'بلگه كارورتو',
+'tooltip-pt-mytalk' => 'بلگه قسه كردن شما',
+'tooltip-pt-preferences' => 'اولويتيا شما',
+'tooltip-pt-watchlist' => 'نوم نوشت د بلگه يايی كه شما آلشتاشونه پيگئری  ميكيد',
+'tooltip-pt-mycontris' => 'يه گل د هومياريا شما',
+'tooltip-pt-login' => 'توصيه بو كه وارد بوئين، اما مجبوری ني',
+'tooltip-pt-logout' => 'د سيستم دراومائن',
+'tooltip-ca-talk' => 'قسه دباره محتوا بلگه',
+'tooltip-ca-edit' => 'شما تونيد ای  بلگه نه ويرايشت بكيد. لطف بكيد د دگمه پيش ديئن پيش د ذخيره كردن استفاده بكيد',
+'tooltip-ca-addsection' => 'بشخ تازه نه شرو كو',
+'tooltip-ca-viewsource' => 'ای بلگه حفاظت بيه.
+شما تونيت سرچمه ش بئوينيت',
+'tooltip-ca-history' => 'دوواره ديئن ای بلگه',
+'tooltip-ca-protect' => 'ای بلگه نه حفاظت بكيد',
+'tooltip-ca-delete' => 'ای بلگه نه حذف بكيد',
+'tooltip-ca-move' => 'ای بگله نه جا وه جا كو',
+'tooltip-ca-watch' => 'اضاف کردن ای بلگه وه نوم نوشت پیگئریاتو',
+'tooltip-ca-unwatch' => 'ورداشتن ای بلگه وه نوم نوشت پیگئریاتو',
+'tooltip-search' => 'پی جوری {{SITENAME}}',
+'tooltip-search-go' => 'رؤ د بلگه ای که یه نوم راستکی ها مینش الوت ار دش بوئه',
+'tooltip-search-fulltext' => 'بلگيانه سی چنو متنی بگرد',
+'tooltip-p-logo' => 'سرآسونه نه بونيت',
+'tooltip-n-mainpage' => 'سرآسونه نه بونيت',
+'tooltip-n-mainpage-description' => 'ديئن سرآسونه',
+'tooltip-n-portal' => 'دباره پروجه،ايسا ترين(تونيت) چی بكيد، كجه چيانه بجورين',
+'tooltip-n-currentevents' => 'ساوند دونسمنديايی كه هان د پيشومدل تازه باو پيدا كو',
+'tooltip-n-recentchanges' => 'يه نوم جاوند سی تغيرا تازه مئن ويكی',
+'tooltip-n-randompage' => 'سوار كرد بلگه بختكی',
+'tooltip-n-help' => 'جاگه سی فهمسن',
+'tooltip-t-whatlinkshere' => 'سيائه تمؤم بلگيایی كه ايچه چسب ون دارن',
+'tooltip-t-recentchangeslinked' => 'تغيريا تازه باو مئن بلگيايي كه د ای بلگه چسب وند بيئنه',
+'tooltip-feed-atom' => 'تغذيه كؤچك سی ای بلگه',
+'tooltip-t-contributions' => 'یه نوم گه د هومیاریا ای کارور',
+'tooltip-t-emailuser' => 'سی ای كارور ايميل كل كو',
+'tooltip-t-upload' => 'بلم گير كردن فايلا',
+'tooltip-t-specialpages' => 'سيائه تمؤم بلگيا خاص',
+'tooltip-t-print' => 'نسقه چاپ بيئنی سی ای بلگه',
+'tooltip-t-permalink' => 'چسب ون هميشئی د دوواره بينی ای بلگه',
+'tooltip-ca-nstab-main' => 'ديئن محتوا بلگه',
+'tooltip-ca-nstab-user' => 'ديئن بلگه كارور',
+'tooltip-ca-nstab-special' => 'اي بلگه ويجه يه، شما نتونيت خود اي بلگه نه ويرايشت بكيد',
+'tooltip-ca-nstab-project' => 'ديئن بلگه پروجه',
+'tooltip-ca-nstab-image' => 'ديئن بلگه فايل',
+'tooltip-ca-nstab-template' => 'ديئن قالو',
+'tooltip-ca-nstab-category' => 'ديئن بلگه دسه بنی',
+'tooltip-minoredit' => 'یه نه د عنوان حیرده ویرایشت ثوت کو',
+'tooltip-save' => 'آلشتياتونه ذخيره بكيد',
+'tooltip-preview' => 'پیش سیل آلشتیاتو،لطفن پیش د ذخیره دش استفاده بکیتو',
+'tooltip-diff' => 'آلشتیا نه که شما د ای متن راس کردیته نشو بیئه',
+'tooltip-compareselectedversions' => 'فرخیا مینجا دو تا د دو بار دیئن ای بلگه نه بوینیت',
+'tooltip-watch' => 'ای بلگه نه د سیل برگتو اضاف بکید',
+'tooltip-rollback' => '"ورگشتن" لرستن د حالت اول  سی ای بلگه  که سی  يه كه هومياری  نيايی اصلاح بيه وا يه پورنسن',
+'tooltip-undo' => 'انجوم نگرتن ای ویرایشت ورگن و همه فرمیا ویرایشت تانه که حالت پیش سیل واکو.یه اجازه میئه سی اضاف کردن یه دلیل د چکسته.',
+'tooltip-summary' => 'يه چكسته كؤچك وارد بكيد',
+
+# Browsing diffs
+'previousdiff' => '← ويرايشت كۈهنه تر',
+'nextdiff' => 'ويرايشت تازه تر',
+
+# Media information
+'file-info-size' => '$1 × $2 پیکسل, انازه فایل: $3, MIME نوع: $4',
+'file-nohires' => 'عسك ون بالاتري دش ني',
+'svg-long-desc' => 'اس وی جی فايل.نومنا $1 $2 پيكسل',
+'show-big-image' => 'تموم رخ ون',
+
+# Bad image list
+'bad_image_list' => 'دونسمنديانه وه ای شلگ وارد بكيت:
+
+فقط سرخط يایی که وا * شرو بوئن د وير گرته بوئن. اولی چسب ون مئن هر سرخط، باید چسب ونی وه یک عسگ گن با.
+چسب ونيا نيایی د همو سرخط، وه عنوان چيا استثنادار د وير گرته بوئن',
+
+# Metadata
+'metadata' => 'داديا  فره گپ',
+'metadata-help' => 'ای فایل شومل دونسمنیا هنی یه.شایت د دیربین رقم ون یا اسکنری که سی راس کردنشو استفاده بیه،وه ایچه اضاف بیه',
+'metadata-fields' => 'رشته یا گپ دونسمنیا که د ای پیغوم نوم ون بینه شومل بلگه عسگ ن که وختی که جدول گپ دونسمنیا وا بوئه نشون دئیه بوئن.
+چی یا هنی سی یه که پیش فرضن قام بوئن.
+*راست کو
+*مدل
+*دم وخت اصل
+*وخت آشگار
+*اف ان شماره
+*ایزو نرخ من سرعت
+*فوکالنس
+*هنرمن
+*کپی رایت
+*حالت جی پی اس 
+*جی پی اس گپ حالت
+*جی پی اس همه حالت',
+
+# External editor support
+'edit-externally' => 'ای فایل سی ویرایشت وه در دیئن کاربردش استفاده بکید',
+'edit-externally-help' => '(بوینیت [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)',
+
+# 'all' in various places, this might be different for inflected languages
+'watchlistall2' => 'همه شو',
+'namespacesall' => 'همه شو',
+'monthsall' => 'همه',
+
+# Watchlist editing tools
+'watchlisttools-view' => 'آلشتیا مرتوط نه بوینیت',
+'watchlisttools-edit' => 'سیل برگ بوینیتو و ویرایشت بکید',
+'watchlisttools-raw' => 'سیل برگ نه ردیفی ویرایشت کو',
+
+# Core parser functions
+'duplicate-defaultsort' => 'زنهار کلیت پیش فرض جور بیه $2 تازه ای یا کلید پیش فرض جوربیه $1 رد بیه.',
+
+# Special:SpecialPages
+'specialpages' => 'بلگيا ويجه',
+
+# External image whitelist
+'external_image_whitelist' => 'یه خط نه ول بکید چی وه<pre>',
+
+# Special:Tags
+'tag-filter' => 'فيلتر [[Special:Tags|Tag]]:',
+
+);
index c29b9dc..f0b02fb 100644 (file)
@@ -63,7 +63,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Seniausi_puslapiai' ),
        'Blankpage'                 => array( 'Tuščias_puslapis' ),
        'Block'                     => array( 'Blokuoti_IP' ),
-       'Blockme'                   => array( 'Užblokuoti_mane' ),
        'Booksources'               => array( 'Knygų_šaltiniai' ),
        'BrokenRedirects'           => array( 'Peradresavimai_į_niekur' ),
        'Categories'                => array( 'Kategorijos' ),
@@ -73,7 +72,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Sukurti_paskyrą' ),
        'Deadendpages'              => array( 'Puslapiai-aklavietės' ),
        'DeletedContributions'      => array( 'Ištrintas_indėlis' ),
-       'Disambiguations'           => array( 'Nukreipiamieji' ),
        'DoubleRedirects'           => array( 'Dvigubi_peradesavimai' ),
        'Emailuser'                 => array( 'Rašyti_laišką' ),
        'Export'                    => array( 'Eksportas' ),
@@ -458,8 +456,6 @@ $1',
 'ok' => 'Gerai',
 'retrievedfrom' => 'Gauta iš „$1“',
 'youhavenewmessages' => 'Jūs turite $1 ($2).',
-'newmessageslink' => 'naujų žinučių',
-'newmessagesdifflink' => 'paskutinis pakeitimas',
 'youhavenewmessagesfromusers' => 'Jūs gavote $1 nuo {{PLURAL:$3|kito vartotojo|$3 vartotojų}} ($2).',
 'youhavenewmessagesmanyusers' => 'Jūs turite $1 iš daugelio vartotojų ( $2 ) .',
 'newmessageslinkplural' => '{{PLURAL:$1|naują žinutę|naujų žinučių}}',
@@ -1264,8 +1260,6 @@ Prašome patikrinti sąrašus.',
 'preferences' => 'Nustatymai',
 'mypreferences' => 'Nustatymai',
 'prefs-edits' => 'Keitimų skaičius:',
-'prefsnologin' => 'Neprisijungęs',
-'prefsnologintext' => 'Jums reikia būti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prisijungusiam]</span>, kad galėtumėte keisti savo nustatymus.',
 'changepassword' => 'Pakeisti slaptažodį',
 'prefs-skin' => 'Išvaizda',
 'skin-preview' => 'Peržiūra',
@@ -1552,6 +1546,7 @@ teisės",
 'recentchanges-label-minor' => 'Tai smulkus pakeitimas',
 'recentchanges-label-bot' => 'Šį keitimą atliko automatinė programa',
 'recentchanges-label-unpatrolled' => 'Šis keitimas dar nebuvo patikrintas',
+'recentchanges-legend-newpage' => '$1 - naujas puslapis',
 'rcnote' => "Žemiau yra {{PLURAL:$1|'''1''' pakeitimas|paskutiniai '''$1''' pakeitimai|paskutinių '''$1''' pakeitimų}} per {{PLURAL:$2|dieną|paskutiniąsias '''$2''' dienas|paskutiniųjų '''$2''' dienų}} skaičiuojant nuo $5, $4.",
 'rcnotefrom' => "Žemiau yra pakeitimai pradedant '''$2''' (rodoma iki '''$1''' pakeitimų).",
 'rclistfrom' => 'Rodyti naujus pakeitimus pradedant $1',
@@ -2766,7 +2761,7 @@ Pastaruoju atveju, jūs taip pat galite naudoti nuorodą, pvz. [[{{#Special:Expo
 'allmessagesdefault' => 'Pradinis tekstas',
 'allmessagescurrent' => 'Dabartinis tekstas',
 'allmessagestext' => 'Čia pateikiamas sisteminių pranešimų sąrašas, esančių MediaWiki vardų srityje.
-Aplankykite [//www.mediawiki.org/wiki/Localisation „MediaWiki“ lokaliziciją] ir [//translatewiki.net „translatewiki.net“], jei norite prisidėti prie bendrojo „MediaWiki“ lokalizavimo.',
+Aplankykite [https://www.mediawiki.org/wiki/Localisation „MediaWiki“ lokaliziciją] ir [//translatewiki.net „translatewiki.net“], jei norite prisidėti prie bendrojo „MediaWiki“ lokalizavimo.',
 'allmessagesnotsupportedDB' => "Šis puslapis nepalaikomas, nes nuostata '''\$wgUseDatabaseMessages''' yra išjungtas.",
 'allmessages-filter-legend' => 'Filtras',
 'allmessages-filter' => 'Filtruoti pagal būseną:',
@@ -2957,6 +2952,8 @@ Leidžia pridėti atmetimo priežastį komentaruose',
 'spam_reverting' => 'Atkuriama į ankstesnę versiją, neturinčios nuorodų į $1',
 'spam_blanking' => 'Visos versijos turėjo nuorodų į $1, išvaloma',
 'spam_deleting' => 'Visos versijos turėjo nuorodų į $1, ištrinama',
+'simpleantispam-label' => "Anti-spam patikra.
+'''NE'''pildykite!",
 
 # Info page
 'pageinfo-title' => '„$1“ informacija',
@@ -3520,7 +3517,7 @@ Visos kitos nuorodos toje pačioje eilutėje yra laikomos išimtimis, t. y. pusl
 
 # External editor support
 'edit-externally' => 'Atverti išoriniame redaktoriuje',
-'edit-externally-help' => '(Norėdami gauti daugiau informacijos, žiūrėkite [//www.mediawiki.org/wiki/Manual:External_editors diegimo instrukcijas])',
+'edit-externally-help' => '(Norėdami gauti daugiau informacijos, žiūrėkite [https://www.mediawiki.org/wiki/Manual:External_editors diegimo instrukcijas])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'visus',
@@ -3708,7 +3705,7 @@ Jūs taip pat galite [[Special:EditWatchlist|naudoti standartinį redaktorių]].
 'version-hook-subscribedby' => 'Užsakyta',
 'version-version' => '(Versija $1)',
 'version-license' => 'Licencija',
-'version-poweredby-credits' => "Šis projektas naudoja '''[//www.mediawiki.org/ MediaWiki]''', autorystės teisės © 2001-$1 $2.",
+'version-poweredby-credits' => "Šis projektas naudoja '''[https://www.mediawiki.org/ MediaWiki]''', autorystės teisės © 2001-$1 $2.",
 'version-poweredby-others' => 'kiti',
 'version-credits-summary' => 'Už indėlį kuriant [[Special:Version|MediaWiki]] dėkojame',
 'version-license-info' => 'MediaWiki yra nemokama programinė įranga; galite ją platinti ir/arba modifikuoti pagal GNU General Public License, kurią publikuoja Free Software Foundation; taikoma 2-oji licenzijos versija arba (Jūsų pasirinkimu) bet kuri vėlesnė versija. 
@@ -3747,8 +3744,7 @@ Jūs turėjote gauti [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General Public Licens
 
 # Special:SpecialPages
 'specialpages' => 'Specialieji puslapiai',
-'specialpages-note' => '----
- * įprastą specialius puslapius.
+'specialpages-note' => ' * įprastą specialius puslapius.
  * <span class="mw-specialpagerestricted">tik specialius puslapius.</span>
  * <span class="mw-specialpagecached">Talpyklinių specialius puslapius (gali būti pasenusius).</span>',
 'specialpages-group-maintenance' => 'Sistemos palaikymo pranešimai',
@@ -3940,4 +3936,10 @@ Kitu atveju, galite naudotis žemiau esančia paprastesne forma. Jūsų komentar
 'duration-centuries' => '$1 {{PLURAL:$1|amžius|amžiai|amžių}}',
 'duration-millennia' => '$1 {{PLURAL:$1|tūkstantmetis|tūkstantmečiai|tūkstantmečių}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Rezultatas',
+'expand_templates_ok' => 'Gerai',
+'expand_templates_remove_comments' => 'Pašalinti komentarus',
+'expand_templates_preview' => 'Peržiūra',
+
 );
index 1b4b7f5..9640eee 100644 (file)
@@ -105,8 +105,6 @@ $messages = array(
 'category-article-count' => '{{PLURAL:$2|Itymā kategorejā ir vīn dūtuo puslopa.|{{PLURAL:$1|Paruodeita $1 puslopa|Paruodeitys $1 puslopys}} nu $2.}}',
 'listingcontinuesabbrev' => '(tuoļuojums)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Aproksts',
 'article' => 'Rakstīņs',
 'newwindow' => '(atdareišona jaunuo puslopā)',
@@ -207,8 +205,6 @@ $messages = array(
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Atdabuot nu "$1"',
 'youhavenewmessages' => 'Tu dabuoji $1 ($2).',
-'newmessageslink' => 'jaunus viestejumus',
-'newmessagesdifflink' => 'pādejā pataise',
 'editsection' => 'pataiseit',
 'editold' => 'pataiseit',
 'editlink' => 'pataiseit',
@@ -867,7 +863,7 @@ Puorejī lauki, piec nūklusiejuma, byus nūglobuoti.
 
 # External editor support
 'edit-externally' => 'Izmaineit itū failu ar uoreju programu',
-'edit-externally-help' => '(Verīs [//www.mediawiki.org/wiki/Manual:External_editors instrukcijas] Mediawiki.org, kab dabuotu vaira informacejis).',
+'edit-externally-help' => '(Verīs [https://www.mediawiki.org/wiki/Manual:External_editors instrukcijas] Mediawiki.org, kab dabuotu vaira informacejis).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'vysys',
index d68ae6c..a860c3b 100644 (file)
@@ -272,8 +272,6 @@ $1',
 'ok' => 'Aw le',
 'retrievedfrom' => '"$1" aṭanga lâk chhuah',
 'youhavenewmessages' => '($2) $1 i nei.',
-'newmessageslink' => 'thudawn thar',
-'newmessagesdifflink' => 'tihdanglam thar',
 'youhavenewmessagesfromusers' => 'Hmangtu dang {{PLURAL:$3|pakhat|$3}} hnên aṭang $1 i nei ($2)',
 'youhavenewmessagesmanyusers' => 'Hmangtu dang tamtak hnên aṭang $1 i nei nual ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|thudawn thar}}',
@@ -770,8 +768,6 @@ Google hmangin i lo zawng hrih thei ang.
 'preferences' => 'Duhdàn',
 'mypreferences' => 'Duhthlanna',
 'prefs-edits' => 'Siamţhat zât',
-'prefsnologin' => 'I la lût lo',
-'prefsnologintext' => 'Hmangtu duhdàn siam tùrin i <span class="plainlinks"> [{{fullurl:{{#Special:UserLogin}}|returnto=$1}} inziah luh] </span> a ngai.',
 'changepassword' => 'Thurûk thlâkna',
 'prefs-skin' => 'Vun',
 'skin-preview' => 'Enchhinna',
@@ -1858,7 +1854,7 @@ A bak zawng chu thuhrûk sa vek a ni ang.
 
 # External editor support
 'edit-externally' => 'Pawnlam hmanraw hmanga tihdanglamna',
-'edit-externally-help' => '(Hriat chian lehzualnan [//www.mediawiki.org/wiki/Manual:External_editors bundàn kaihhruaina phek] hi en rawh)',
+'edit-externally-help' => '(Hriat chian lehzualnan [https://www.mediawiki.org/wiki/Manual:External_editors bundàn kaihhruaina phek] hi en rawh)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'a vaiin',
index 87965a9..f3e2af9 100644 (file)
@@ -324,8 +324,6 @@ $1',
 'ok' => 'Labi',
 'retrievedfrom' => 'Saturs iegūts no "$1"',
 'youhavenewmessages' => 'Tev ir $1 (skatīt $2).',
-'newmessageslink' => 'jauns vēstījums',
-'newmessagesdifflink' => 'pēdējā izmaiņa',
 'newmessageslinkplural' => '{{PLURAL:$1|jauns vēstījums|jauni vēstījumi}}',
 'newmessagesdifflinkplural' => '{{PLURAL:$1|pēdējā izmaiņa|pēdējās izmaiņas}}',
 'youhavenewmessagesmulti' => 'Tev ir jauns ziņojums: $1',
@@ -1026,8 +1024,6 @@ Pagaidām vari meklēt, izmantojot Google vai Yahoo.
 'preferences' => 'Izvēles',
 'mypreferences' => 'Izvēles',
 'prefs-edits' => 'Izmaiņu skaits:',
-'prefsnologin' => 'Neesi iegājis',
-'prefsnologintext' => 'Tev jābūt <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} iegājušam]</span>, lai mainītu lietotāja izvēles.',
 'changepassword' => 'Mainīt paroli',
 'prefs-skin' => 'Apdare',
 'skin-preview' => 'Priekšskats',
@@ -1058,11 +1054,15 @@ Pagaidām vari meklēt, izmantojot Google vai Yahoo.
 'columns' => 'Simbolu skaits rindiņā:',
 'searchresultshead' => 'Meklēšana',
 'resultsperpage' => 'Lappusē parādāmo rezultātu skaits',
+'stub-threshold' => 'Slieksnis <a href="#" class="stub">aizmetņa saites</a> formatēšanai (baiti):',
 'stub-threshold-disabled' => 'Atslēgts',
-'recentchangesdays' => 'Dienu skaits, kuru rādīt pēdējajās izmaiņās:',
+'recentchangesdays' => 'Dienu skaits, kuru rādīt pēdējās izmaiņās:',
 'recentchangesdays-max' => 'Ne vairāk kā $1 {{PLURAL:$1|diena|dienas}}',
 'recentchangescount' => 'Izmaiņu skaits, kuru rāda pēc noklusējuma:',
 'prefs-help-recentchangescount' => 'Šis parametrs attiecas uz pēdējo izmaiņu un hronoloģijas lapām, kā arī uz sistēmas žurnāliem',
+'prefs-help-watchlist-token2' => 'Šī ir slepena atslēga tavam uzraugāmo lapu sarakstam.
+Ikvienam, kas to zinās, būs iespēja apskatīt tavu uzraugāmo lapu sarakstu, tāpēc nedalies ar to.
+[[Special:ResetTokens|Spied šeit, lai to atjaunotu]].',
 'savedprefs' => 'Jūsu izvēles ir saglabātas.',
 'timezonelegend' => 'Laika josla:',
 'localtime' => 'Vietējais laiks:',
@@ -1084,7 +1084,7 @@ Pagaidām vari meklēt, izmantojot Google vai Yahoo.
 'allowemail' => 'Atļaut saņemt e-pastus no citiem lietotājiem',
 'prefs-searchoptions' => 'Meklēšana',
 'prefs-namespaces' => 'Vārdtelpas',
-'defaultns' => 'Meklēt šajās palīglapās pēc noklusējuma:',
+'defaultns' => 'Meklēt šajās vārdtelpās pēc noklusējuma:',
 'default' => 'pēc noklusējuma',
 'prefs-files' => 'Attēli',
 'prefs-custom-css' => 'Personīgais CSS',
@@ -1108,13 +1108,12 @@ Tam ir jābūt īsākam par  $1 {{PLURAL:$1|simbolu|simboliem}}.',
 'gender-unknown' => 'Es nevēlos norādīt',
 'gender-male' => 'Viņš labo viki lapas',
 'gender-female' => 'Viņa labo viki lapas',
-'prefs-help-gender' => 'Dzimums nav obligāti jānorāda (šo parametru programmatūra izmanto, lai ģenerētu paziņojumus, kas atkarīgi no lietotāja dzimuma).
-Norādītā parametra vērtība būs publiski pieejama.',
+'prefs-help-gender' => 'Dzimums nav obligāti jānorāda (šo parametru programmatūra izmanto, lai ģenerētu paziņojumus, kas atkarīgi no lietotāja dzimuma). Šī informācija būs publiski pieejama.',
 'email' => 'E-pasts',
 'prefs-help-realname' => 'Īstais vārds nav obligāti jānorāda.
 Ja tu izvēlies to norādīt, tas tiks izmantots, lai identificētu tavu darbu (ieguldījumu {{grammar:lokatīvs|{{SITENAME}}}}).',
 'prefs-help-email' => 'E-pasta adrese nav obligāta, bet ir nepieciešama nozaudētas paroles atjaunošanai.',
-'prefs-help-email-others' => 'Jus ari variet izvelties ka citi jus var kontaktēt uz jusu lietotajā sarunas lapu, neatklājot jus identitāti.',
+'prefs-help-email-others' => 'Tu arī vari izvēlēties, ka citi var sazināties ar tevi ar saites tavā lietotāja lapā vai lietotāja diskusijas lapā palīdzību. Citiem lietotājiem netiek atklāta tava e-pasta adrese, kad viņi sazinās ar tevi.',
 'prefs-help-email-required' => 'E-pasta adrese ir obligāta.',
 'prefs-info' => 'Pamatinformācija',
 'prefs-i18n' => 'Internacionalizācija',
@@ -1124,14 +1123,15 @@ Ja tu izvēlies to norādīt, tas tiks izmantots, lai identificētu tavu darbu (
 'prefs-advancedediting' => 'Vispārīgi uzstādījumi',
 'prefs-editor' => 'Redaktors',
 'prefs-preview' => 'Priekšskatījums',
-'prefs-advancedrc' => 'Papildus uzstādījumi',
-'prefs-advancedrendering' => 'Papildus uzstādījumi',
-'prefs-advancedsearchoptions' => 'Papildus uzstādījumi',
-'prefs-advancedwatchlist' => 'Papildus uzstādījumi',
+'prefs-advancedrc' => 'Papildu uzstādījumi',
+'prefs-advancedrendering' => 'Papildu uzstādījumi',
+'prefs-advancedsearchoptions' => 'Papildu uzstādījumi',
+'prefs-advancedwatchlist' => 'Papildu uzstādījumi',
 'prefs-displayrc' => 'Pamatuzstādījumi',
 'prefs-displaysearchoptions' => 'Pamatuzstādījumi',
 'prefs-displaywatchlist' => 'Pamatuzstādījumi',
 'prefs-diffs' => 'Izmaiņas',
+'prefs-help-prefershttps' => 'Šie uzstādījumi stāsies spēkā nākamajā pievienošanās reizē.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'E-pasta adrese šķiet derīga',
@@ -1292,6 +1292,7 @@ Ja tu izvēlies to norādīt, tas tiks izmantots, lai identificētu tavu darbu (
 'recentchanges-label-minor' => 'Šī ir maznozīmīga izmaiņa',
 'recentchanges-label-bot' => 'Šī ir bota veikta izmaiņa',
 'recentchanges-label-unpatrolled' => 'Šis labojums vēl nav pārbaudīts',
+'recentchanges-legend-newpage' => '$1 - jauna lapa',
 'rcnote' => 'Šobrīd ir {{PLURAL:$1|redzama pēdējā <strong>$1</strong> izmaiņa, kas izdarīta|redzamas pēdējās <strong>$1</strong> izmaiņas, kas izdarītas}} {{PLURAL:$2|pēdējā|pēdējās}} <strong>$2</strong> {{PLURAL:$2|dienā|dienās}} (līdz $4, $5).',
 'rcnotefrom' => "Šobrīd redzamas izmaiņas kopš '''$2''' (parādītas ne vairāk par '''$1''').",
 'rclistfrom' => 'Parādīt jaunas izmaiņas kopš $1',
@@ -2353,7 +2354,7 @@ Pirmajā gadījumā var arī lietot šādu metodi, piem., [[{{#Special:Export}}/
 'allmessagesdefault' => 'Noklusētais ziņojuma teksts',
 'allmessagescurrent' => 'Pašreizējais teksts',
 'allmessagestext' => "Šajā lapā ir visu \"'''MediaWiki:'''\" lapās atrodamo sistēmas paziņojumu uzskaitījums.
-Šos paziņojumus var izmainīt tikai admini. Izmainot tos šeit, tie tiks izmainīti tikai šajā mediawiki instalācijā. Lai tos izmainītu visām pārējām, apskatieties [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net].",
+Šos paziņojumus var izmainīt tikai admini. Izmainot tos šeit, tie tiks izmainīti tikai šajā mediawiki instalācijā. Lai tos izmainītu visām pārējām, apskatieties [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net].",
 'allmessagesnotsupportedDB' => "Šī lapa nedarbojas, tāpēc, ka '''wgUseDatabaseMessages''' nedarbojas.",
 'allmessages-filter-legend' => 'Filtrs',
 'allmessages-filter' => 'Filtrēt pēc izmainīšanas statusa:',
@@ -2515,6 +2516,8 @@ To visticamāk izraisīja ārēja saite uz melnajā sarakstā esošu interneta v
 'spamprotectionmatch' => 'Spama filtram radās iebildumi pret šo tekstu: $1',
 'spambot_username' => 'MediaWiki surogātpasta tīrīšana',
 'spam_reverting' => 'Atjauno iepriekšējo versiju, kas nesatur saiti uz $1',
+'simpleantispam-label' => "Pretspama pārbaude. 
+ '''NEAIZPILDĪT!'''",
 
 # Info page
 'pageinfo-title' => 'Informācija par "$1"',
@@ -2930,7 +2933,7 @@ Pārējie lauki, pēc noklusējuma, būs paslēpti.
 
 # External editor support
 'edit-externally' => 'Izmainīt šo failu ar ārēju programmu',
-'edit-externally-help' => '(Skat. [//www.mediawiki.org/wiki/Manual:External_editors instrukcijas] Mediawiki.org, lai iegūtu vairāk informācijas).',
+'edit-externally-help' => '(Skat. [https://www.mediawiki.org/wiki/Manual:External_editors instrukcijas] Mediawiki.org, lai iegūtu vairāk informācijas).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'visas',
@@ -3073,7 +3076,7 @@ Var arī lietot [[Special:EditWatchlist|standarta izmainīšanas lapu]].',
 'version-hook-name' => 'Aizķeres nosaukums',
 'version-version' => '(Versija $1)',
 'version-license' => 'Licence',
-'version-poweredby-credits' => "Šis viki darbojas ar '''[//www.mediawiki.org/ MediaWiki]''' programmatūru, autortiesības © 2001-$1 $2.",
+'version-poweredby-credits' => "Šis viki darbojas ar '''[https://www.mediawiki.org/ MediaWiki]''' programmatūru, autortiesības © 2001-$1 $2.",
 'version-poweredby-others' => 'citi',
 'version-poweredby-translators' => 'translatewiki.net tulkotāji',
 'version-credits-summary' => 'Mēs vēlētos izteikt atzinību šīm personām par viņu ieguldījumu [[Special:Version|MediaWiki]].',
@@ -3100,8 +3103,7 @@ Var arī lietot [[Special:EditWatchlist|standarta izmainīšanas lapu]].',
 
 # Special:SpecialPages
 'specialpages' => 'Īpašās lapas',
-'specialpages-note' => '----
-* Normālas īpašās lapas.
+'specialpages-note' => '* Normālas īpašās lapas.
 * <span class="mw-specialpagerestricted">Ierobežotas pieejas īpašās lapas.</span>
 * <span class="mw-specialpagecached">Iekešotās īpašās lapas.</span>',
 'specialpages-group-maintenance' => 'Uzturēšanas atskaites',
@@ -3198,7 +3200,7 @@ Var arī lietot [[Special:EditWatchlist|standarta izmainīšanas lapu]].',
 'logentry-newusers-newusers' => 'Lietotāja konts $1 tika {{GENDER:$2|izveidots}}',
 'logentry-newusers-create' => 'Lietotāja konts $1 tika {{GENDER:$2|izveidots}}',
 'logentry-newusers-create2' => '$1 {{GENDER:$2|izveidoja}} lietotāja kontu $3',
-'logentry-newusers-autocreate' => 'Konts $1 tika {GENDER:$2|izveidots}} automātiski',
+'logentry-newusers-autocreate' => 'Lietotaja konts $1 tika {{GENDER:$2|izveidots}} automātiski',
 'rightsnone' => '(nav)',
 
 # Feedback
@@ -3239,4 +3241,9 @@ Var arī lietot [[Special:EditWatchlist|standarta izmainīšanas lapu]].',
 'limitreport-templateargumentsize' => 'Veidnes argumenta izmērs',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|baits|baiti}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Rezultāts',
+'expand_templates_ok' => 'Labi',
+'expand_templates_preview' => 'Pirmskats',
+
 );
index c57b0a5..625229e 100644 (file)
@@ -34,7 +34,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( '增簿' ),
        'Deadendpages'              => array( '此無路也' ),
        'DeletedContributions'      => array( '已刪之積' ),
-       'Disambiguations'           => array( '釋義' ),
        'DoubleRedirects'           => array( '窮渡' ),
        'EditWatchlist'             => array( '治哨站' ),
        'Emailuser'                 => array( '遺書' ),
@@ -423,8 +422,6 @@ $1',
 'ok' => '可',
 'retrievedfrom' => '取自"$1"',
 'youhavenewmessages' => '有$1書至子書房也。($2)',
-'newmessageslink' => '新訊',
-'newmessagesdifflink' => '變更',
 'youhavenewmessagesfromusers' => '子有 $1 自 {{PLURAL:$3|一簿戶也|$3 簿戶也}} ($2)。',
 'youhavenewmessagesmanyusers' => '子有 $1 自多簿戶 ( $2 )',
 'newmessageslinkplural' => '{{PLURAL:$1|一新訊息|新訊息}}',
@@ -1094,8 +1091,6 @@ $1",
 'preferences' => '簿註',
 'mypreferences' => '簿註',
 'prefs-edits' => '數計:',
-'prefsnologin' => '未登簿',
-'prefsnologintext' => '註記須<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登簿]</span>。',
 'changepassword' => '易符節',
 'prefs-skin' => '面版',
 'skin-preview' => '草覽',
@@ -1360,6 +1355,7 @@ $1",
 'recentchanges-label-minor' => '此乃細纂',
 'recentchanges-label-bot' => '此乃機纂',
 'recentchanges-label-unpatrolled' => '是纂未巡',
+'recentchanges-legend-newpage' => '$1 - 新頁',
 'rcnote' => "下為自$4$5起,'''$2'''日內'''$1'''近易也。",
 'rcnotefrom' => "下為自'''$2'''至'''$1'''之易也。",
 'rclistfrom' => '自$1起之易也',
@@ -2327,7 +2323,7 @@ $1',
 'allmessagesdefault' => '慣話文',
 'allmessagescurrent' => '今話文',
 'allmessagestext' => '此列MediaWiki官話。
-如貢正宗MediaWiki本地化,[//www.mediawiki.org/wiki/Localisation MediaWiki本地化]與[//translatewiki.net translatewiki.net]閱之。',
+如貢正宗MediaWiki本地化,[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]與[//translatewiki.net translatewiki.net]閱之。',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages'''閉庫,'''無纂也。",
 'allmessages-filter-legend' => '濾',
 'allmessages-filter' => '以易濾:',
@@ -2637,7 +2633,7 @@ $1',
 
 # External editor support
 'edit-externally' => '以外部程式修此文',
-'edit-externally-help' => '(請閱[//www.mediawiki.org/wiki/Manual:External_editors 安裝指引]以知詳情)',
+'edit-externally-help' => '(請閱[https://www.mediawiki.org/wiki/Manual:External_editors 安裝指引]以知詳情)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全',
@@ -2789,7 +2785,7 @@ $5
 'version-hook-subscribedby' => '用於',
 'version-version' => '(版 $1)',
 'version-license' => '牌',
-'version-poweredby-credits' => "此 Wiki 以 '''[//www.mediawiki.org/ MediaWiki]''' 之驅,權 © 2001-$1 $2。",
+'version-poweredby-credits' => "此 Wiki 以 '''[https://www.mediawiki.org/ MediaWiki]''' 之驅,權 © 2001-$1 $2。",
 'version-poweredby-others' => '其他',
 'version-license-info' => 'MediaWiki乃自由軟件;爾依自由軟件基金會之GNU通用公共授權之款,就此本程序再發佈及/或修;依之二版(自選之)或後之。
 
@@ -2812,8 +2808,7 @@ MediaWiki乃為用之發,無擔之責也;亦無售目之默擔也。參GNU
 
 # Special:SpecialPages
 'specialpages' => '特查',
-'specialpages-note' => '----
-* 準特查。
+'specialpages-note' => '* 準特查。
 * <strong class="mw-specialpagerestricted">限特查。</strong>',
 'specialpages-group-maintenance' => '護報',
 'specialpages-group-other' => '它之奇頁',
index 70e2146..50aeb3f 100644 (file)
@@ -286,8 +286,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'प्राप्ति स्थल "$1"',
 'youhavenewmessages' => 'अहाँ लग अछि $1 ($2).',
-'newmessageslink' => 'नव संदेश सभ',
-'newmessagesdifflink' => 'अन्तिम परिवर्तन',
 'youhavenewmessagesmulti' => '$1 पर अहाँ लेल नव सन्देश अछि',
 'editsection' => 'संपादन करू',
 'editold' => 'सम्पादित करू',
@@ -1022,8 +1020,6 @@ $3 द्वारा देल कारण अछि ''$2''",
 'preferences' => 'विकल्प',
 'mypreferences' => 'खासमखास',
 'prefs-edits' => 'सम्पादनक संख्या',
-'prefsnologin' => 'सम्प्रवेशित नै',
-'prefsnologintext' => 'अहाँ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logged in]</span> प्रयोक्ता विकल्प निर्धारण लेल प्रयोग करू।',
 'changepassword' => 'कूटशब्द बदलू',
 'prefs-skin' => 'रूप',
 'skin-preview' => 'पूर्वावलोकन',
@@ -2456,7 +2452,7 @@ $1 एकर प्रतिबन्धक कारण अछि : "$2"',
 'allmessagesdefault' => 'पूर्वनिर्धारित संदेश पाठ',
 'allmessagescurrent' => 'अखुनका संदेश पाठ',
 'allmessagestext' => 'ई मीडियाविकी नामस्थानमे उपलब्ध संस्थागत संदेशक सूची छी।
-कृपा कऽ देखू [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] आ [//translatewiki.net translatewiki.net] जँ अहाँ मीडियाविकीक स्थानिकीकरणक मूलक अनुवादमे योगदान करए चाहै छी।',
+कृपा कऽ देखू [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] आ [//translatewiki.net translatewiki.net] जँ अहाँ मीडियाविकीक स्थानिकीकरणक मूलक अनुवादमे योगदान करए चाहै छी।',
 'allmessagesnotsupportedDB' => "ई पन्ना प्रयोगमे नै आनल जा सकैए कारण '''\$wgUseDatabaseMessages''' अशक्त कएल अछि।",
 'allmessages-filter-legend' => 'चलनी',
 'allmessages-filter' => 'अपन हिसाबे अनुकूलित कऽ छाँटू:',
@@ -3147,7 +3143,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => 'ऐ फाइलकेँ बाहरी अनुप्रयोगसँ हटाउ',
-'edit-externally-help' => '(देखू [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] विषेष जानकारी लेल)',
+'edit-externally-help' => '(देखू [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] विषेष जानकारी लेल)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'सभ',
@@ -3333,7 +3329,7 @@ $5
 'version-hook-subscribedby' => 'ई सदस्यता लेलनि',
 'version-version' => '(संस्करण $1)',
 'version-license' => 'अधिकार',
-'version-poweredby-credits' => "ई विकी चालित अछि '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2",
+'version-poweredby-credits' => "ई विकी चालित अछि '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2",
 'version-poweredby-others' => 'आन',
 'version-license-info' => 'मीडियाविकी एकटा मंगनीक तंत्रांश अछि; अहाँ एकरा बाँटि सकै छी आ/ वा संशोधित कऽ सकै छीगी.एन.यू. सामान्य जन लाइसेन्सक अन्तर्गत जेना फ्री सॉफ्टवेयर फाउन्डेशन एकरा प्रकाशित केने अछि; चाहे तँ लाइसेन्सक संस्करण २, वा (अहाँक विकल्पपर) कोनो बादक दोसर संस्करणक अन्तर्गत।
 
@@ -3357,8 +3353,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'विशेष पन्ना',
-'specialpages-note' => '----
-* सामान्य विशिष्ट पन्ना।
+'specialpages-note' => '* सामान्य विशिष्ट पन्ना।
 * <span class="mw-specialpagerestricted">प्रतिबंधित विशिष्ट पन्ना।</span>
 * <span class="mw-specialpagecached">उपस्मृतिक विशिष्ट पन्ना (पुरान भऽ सकैए)।</span>',
 'specialpages-group-maintenance' => 'सुस्थापन प्रतिवेदन',
index d128bd8..93b6549 100644 (file)
@@ -289,8 +289,6 @@ Deleng [[Special:Version|kaca versi]].',
 'ok' => 'OK',
 'retrievedfrom' => 'Ditampa sekang "$1"',
 'youhavenewmessages' => 'Rika duwe $1 ($2).',
-'newmessageslink' => 'pesen anyar',
-'newmessagesdifflink' => 'owahan keri dhewek',
 'youhavenewmessagesfromusers' => 'Rika nduwe $1 sekang {{PLURAL:$3|panganggo liya|$3 panganggo}} ($2).',
 'youhavenewmessagesmanyusers' => 'Rika nduwe $1 sekang akeh panganggo ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|pesen anyar|pesen anyar}}',
@@ -978,8 +976,6 @@ Ningen Rika kudu eling nek indeks Google kanggo {{SITENAME}} bisa baen isine anu
 'preferences' => 'Preferensi',
 'mypreferences' => 'Preferensi',
 'prefs-edits' => 'Jumlah suntingan:',
-'prefsnologin' => 'Durung mlebu log',
-'prefsnologintext' => 'Rika kudu <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}}| mlebu log disit]</span> kanggo ngowahi préferènsine Rika.',
 'changepassword' => 'Ganti tembung sandhi',
 'prefs-skin' => 'Kulit',
 'skin-preview' => 'Pratayang',
@@ -1821,7 +1817,7 @@ Sing liyane bakal diumpetna sacara ''default''.
 
 # External editor support
 'edit-externally' => 'Sunting berkas kiye nganggo aplikasi jaba',
-'edit-externally-help' => '(Deleng [//www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] kanggo informasi sabanjuré)',
+'edit-externally-help' => '(Deleng [https://www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] kanggo informasi sabanjuré)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kabèh',
index 746a2e1..5913c44 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'КунардоньЛопат' ),
        'Blankpage'                 => array( 'ШаваЛопа' ),
        'Block'                     => array( 'СёлгомаIP' ),
-       'Blockme'                   => array( 'Сёлгомак' ),
        'Booksources'               => array( 'КинигаЛисьмот' ),
        'BrokenRedirects'           => array( 'СиньтьфШашфтфксне' ),
        'Categories'                => array( 'Категориет' ),
@@ -69,7 +68,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Сёрматфтомс' ),
        'Deadendpages'              => array( 'ПеньЛопат' ),
        'DeletedContributions'      => array( 'НардафПутксне' ),
-       'Disambiguations'           => array( 'Лама Смусть' ),
        'DoubleRedirects'           => array( 'КафонзафШашфтфксне' ),
        'Emailuser'                 => array( 'АдресТиись' ),
        'Export'                    => array( 'Вимс' ),
@@ -398,8 +396,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => '"$1"ста сявф',
 'youhavenewmessages' => 'Тонь ули $1 ($2).',
-'newmessageslink' => 'Од сёрмат',
-'newmessagesdifflink' => 'мекольце полафтома',
 'youhavenewmessagesfromusers' => 'Тонь $1 {{PLURAL:$3|тага фкя тиить эзда|$3 тиихнень эзда}} ($2).',
 'youhavenewmessagesmanyusers' => 'Тонь $1 лама тиихнень эзда ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|од сёрма|од сёрмат}}',
@@ -1026,8 +1022,6 @@ $3 макссь туфталсь - ''$2''",
 'preferences' => 'Арафнематне',
 'mypreferences' => 'Монь латцемане',
 'prefs-edits' => 'Петнематнень лувсна:',
-'prefsnologin' => 'Апак сувак',
-'prefsnologintext' => 'Тондейть эряви <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} сувамс]</span> тонь арафнематнень латцеманкса.',
 'changepassword' => 'Сувама валть полафтомс',
 'prefs-skin' => 'Ванфонь латцема',
 'skin-preview' => 'Васень няфтема',
@@ -2148,7 +2142,7 @@ $1',
 'allmessagesdefault' => 'Апак полафтт текст',
 'allmessagescurrent' => 'Тяниень текст',
 'allmessagestext' => 'Тя MediaWiki-са васьфневи системонь пачфтематнень лувомась.
-Эняльттяма, сувак [//www.mediawiki.org/wiki/Localisation MediaWiki Локализациес] ди [//translatewiki.net translatewiki.net-с] кда тонь мяльце тиемс эсь путксце марстонь MediaWiki локализациес.',
+Эняльттяма, сувак [https://www.mediawiki.org/wiki/Localisation MediaWiki Локализациес] ди [//translatewiki.net translatewiki.net-с] кда тонь мяльце тиемс эсь путксце марстонь MediaWiki локализациес.',
 'allmessagesnotsupportedDB' => "Тя лопас аш кода кунцемс сяс мес '''\$wgUseDatabaseMessages'''лоткафоль.",
 'allmessages-language' => 'Кяль:',
 'allmessages-filter-submit' => 'Ётамс',
@@ -2647,7 +2641,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Петнемс тя файлть ушеширень програмонь вельде',
-'edit-externally-help' => '(Ванк [//www.mediawiki.org/wiki/Manual:External_editors арафнемань вятемовалсь] сяда лама содаманкса)',
+'edit-externally-help' => '(Ванк [https://www.mediawiki.org/wiki/Manual:External_editors арафнемань вятемовалсь] сяда лама содаманкса)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'сембе',
@@ -2805,8 +2799,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Башка лопат',
-'specialpages-note' => '----
-* Кърдань башка лопат.
+'specialpages-note' => '* Кърдань башка лопат.
 * <strong class="mw-specialpagerestricted">Кардаф башка лопат.</strong>',
 'specialpages-group-maintenance' => 'Латцема лувоматне',
 'specialpages-group-other' => 'Иля башка тевонь лопатне',
index a5ae666..7f0486f 100644 (file)
@@ -130,7 +130,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Pejy_antitra' ),
        'Blankpage'                 => array( 'Pejy_fotsy' ),
        'Block'                     => array( 'Hanakana' ),
-       'Blockme'                   => array( 'Sakano_ahy' ),
        'Booksources'               => array( 'Boky_loharano' ),
        'BrokenRedirects'           => array( 'Fihodinana_tapaka' ),
        'Categories'                => array( 'Sokajy' ),
@@ -141,7 +140,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Hamorona_kaonty' ),
        'Deadendpages'              => array( 'Pejy_tsy_misy_rohy' ),
        'DeletedContributions'      => array( 'Fandraisan\'anjara_voafafa' ),
-       'Disambiguations'           => array( 'Pejy_mitovy_anarana' ),
        'DoubleRedirects'           => array( 'Fihodinana_miroa' ),
        'EditWatchlist'             => array( 'Hanova_ny_pejy_arahana' ),
        'Emailuser'                 => array( 'Handefa_imailaka' ),
@@ -492,8 +490,6 @@ Mitaky version $1-n'i MediaWiki",
 'pagetitle' => '$1 - {{SITENAME}}',
 'retrievedfrom' => 'Hita tao amin\'ny "$1"',
 'youhavenewmessages' => 'Manana $1 ($2).',
-'newmessageslink' => 'hafatra vaovao',
-'newmessagesdifflink' => 'fanovana farany',
 'youhavenewmessagesfromusers' => "Manana $1 avy amin'ny mpikambana {{PLURAL:$3|hafa|$3}} ($2).",
 'youhavenewmessagesmanyusers' => "Manana $1 avy amin'ny mpikambana maro ($2).",
 'newmessageslinkplural' => '{{PLURAL:$1|hafatra iray|hafatra maro}}',
@@ -680,6 +676,7 @@ Mila manaiky cookies ianao raha te hiditra amin'ny {{SITENAME}}.",
 'userlogin-resetpassword-link' => 'Hamerina ny tenimiafinao',
 'helplogin-url' => 'Help:Fidirana',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Fanoroana mikasika ny fidirana]]',
+'userlogin-createanother' => 'Hamorona kaonty hafa',
 'createacct-join' => 'Atsofohy eo ambany ny fampahalalana momba anao.',
 'createacct-another-join' => "Atsofohy eo ambany ny fampahalalana vaovaon'ny kaonty",
 'createacct-emailrequired' => 'Adiresy mailaka :',
@@ -1342,8 +1339,6 @@ ihany no miseho amin'ny vokatry ny karoka).",
 'preferences' => 'Ny momba anao',
 'mypreferences' => 'Safidy',
 'prefs-edits' => 'isa ny fanovàna :',
-'prefsnologin' => 'Tsy tafiditra',
-'prefsnologintext' => 'Mila <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} misoratra ary tafiditra]</span> amin\'ny kaontinao ianao vao afaka manova ny safidinao.',
 'changepassword' => 'Hanova tenimiafina',
 'prefs-skin' => 'Endrika',
 'skin-preview' => 'Tsipalotra',
@@ -1638,6 +1633,7 @@ Tsy haseho ny adiresy imailakao rehefa manoratra any aminao ny mpikambana hafa."
 'recentchanges-label-minor' => 'Kely fotsiny ity fanovana ity',
 'recentchanges-label-bot' => "Nataon'ny rôbô ity fanovana ity.",
 'recentchanges-label-unpatrolled' => 'Ity fanovana ity dia mbola tsy voamarina',
+'recentchanges-legend-newpage' => '$1 - pejy vaovao',
 'rcnote' => "!Ity ny {{PLURAL:$1|fanovàna farany|fanovàna farany}} $1 natao nandritra ny <b>$2</b> andro, hatramin'ny $4 tamin'ny ora faha $5.",
 'rcnotefrom' => "Ity eto ambany ity ny lisitry ny vao niova manomboka ny <b>$2</b> (hatramin'ny <b>$1</b> no miseho).",
 'rclistfrom' => 'Asehoy izay vao niova manomboka ny $1',
@@ -1915,6 +1911,7 @@ Rehefa sivanin'ny mpikambana iray izy ity, ny rakitra izay ahitana santiôna vao
 'listfiles_size' => 'Habe',
 'listfiles_description' => 'Visavisa',
 'listfiles_count' => 'Version',
+'listfiles-latestversion' => 'Filaza ankehitriny',
 'listfiles-latestversion-yes' => 'Eny',
 'listfiles-latestversion-no' => 'Tsia',
 
@@ -1941,8 +1938,12 @@ Rehefa sivanin'ny mpikambana iray izy ity, ny rakitra izay ahitana santiôna vao
 'morelinkstoimage' => "Hijery [[Special:WhatLinksHere/$1|rohy fanampiny]] makany amin'io rakitra io.",
 'linkstoimage-redirect' => '$1 (fihodinana) $2',
 'sharedupload' => "Mety ho rakitra itambarana amin'ny tetikasa hafa ny rakitra $1.",
+'sharedupload-desc-there' => "Avy amin'i $1 ity rakitr aity ary mety ampiasaina any amin'ny tetikasa hafa.
+Jereo [$2 ny pejy famisavisana ilay rakitra] ho an'ny fampahalalana fanampiny.",
 'sharedupload-desc-here' => "Avy amin'i $1 io rakitra io ary mety ampiasain'ny tetikasa hafa.
 Aseho eo ambany ny [$2 famisavisana ilay rakitra].",
+'sharedupload-desc-edit' => "Avy amin'i $1 ity rakitra ity ka mety ampiasaina any amina tetikasa hafa.
+Mety tia hanova ny famisavisany ianao any amin'ny [$2 pejy famisavisana rakitra] any.",
 'filepage-nofile' => 'Tsy nahitana rakitra mitondra io anarana io.',
 'filepage-nofile-link' => 'Tsy misy rakitra mitondra io anarana io, fa afaka [$1 mampiditra azy ianao].',
 'uploadnewversion-linktext' => "Andefa version vaovao n'ity rakitra ity",
@@ -2379,7 +2380,7 @@ ataovy am-pitandremana ity tao ity.",
 Efa nataon'i [[User:$3|$3]] ([[User talk:$3|dinika]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) ny fanovana farany.",
 'editcomment' => "Toy izao no fanamarihana momba io fanovana io: \"''\$1''\".",
 'revertpage' => "Voafafa ny fanovana ny [[Special:Contributions/$2|$2]] ([[User talk:$2|Dinika]]); voaverina amin'ny votoatiny teo aloha nataon'i [[User:$1|$1]]",
-'revertpage-nouser' => "Manala ny fanovana (nataon'ny anaram-pikambana nesorina), miverina any amin'ny santiona farany nataon'i  [[User:$1|$1]]",
+'revertpage-nouser' => "Manala ny fanovana (nataom-pikambana voaafina), miverina any amin'ny filaza faran'i  [[User:$1|$1]]",
 'rollback-success' => "Fanalàna ny fanovana nataon'i $1 ;
 miverina any amin'ny santiôna farany nataon'i $2.",
 
@@ -2398,7 +2399,7 @@ Ho ann'y fanazavana fanampiny, jereo [[Special:ProtectedPages|ny lisitry ny pejy
 'unprotectedarticle' => "nanala ny fiarovana an'i « [[$1]] »",
 'movedarticleprotection' => 'nanova ny safidim-piarovana : « [[$2]] » lasa « [[$1]] »',
 'protect-title' => "Hanova ny lentam-piarovana ho an'i « $1 »",
-'protect-title-notallowed' => "Hijery ny lentam-piarovana ho an'i «[[$1]]»",
+'protect-title-notallowed' => "Hijery ny lentam-piarovana ho an'i «$1»",
 'prot_1movedto2' => '[[$1]] voaova anarana ho [[$2]]',
 'protect-badnamespace-title' => 'Anaran-tsehatra tsy azo arovana',
 'protect-badnamespace-text' => "Tsy afaka arovana ny pejy ao amin'io anaran-tsehatra io.",
@@ -2821,7 +2822,7 @@ Etsy amin'ny toerana farany dia afaka mampiasa rohy ihany koa ianao, ohatra [[{{
 'allmessagesdefault' => 'Dikan-teny tany am-boalohany',
 'allmessagescurrent' => 'Dikan-teny miasa ankehitriny',
 'allmessagestext' => "Ity dia lisitry ny hafatra hita ao amin'ny anaran-tsehatra MediaWiki.
-Andana vangio ny [//www.mediawiki.org/wiki/Localisation Fandikana an'i Mediawiki] ary [//translatewiki.net/ translatewiki.net] raha tia handray anjara amin'ny fandikana an'i Mediawiki amin'ny ankapobeny.",
+Andana vangio ny [https://www.mediawiki.org/wiki/Localisation Fandikana an'i Mediawiki] ary [//translatewiki.net/ translatewiki.net] raha tia handray anjara amin'ny fandikana an'i Mediawiki amin'ny ankapobeny.",
 'allmessagesnotsupportedDB' => "Tsy mbola mandeha ny '''{{ns:special}}:Allmessages''' satria tsy mandeha koa ny '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Tantavanina',
 'allmessages-filter' => 'Hanasivana araka ny satam-panovana :',
@@ -2903,6 +2904,9 @@ Avereno fanindroany.',
 # JavaScriptTest
 'javascripttest' => 'Fanandramana JavaScript',
 'javascripttest-title' => 'Mandefa fanandramana $1',
+'javascripttest-pagetext-skins' => 'Mifidia skin hanaovana ny fanandramana:',
+'javascripttest-qunit-intro' => "Jereo ny [$1 fanoroana mikasika ny andrana] eo amin'i mediawiki.org.",
+'javascripttest-qunit-heading' => "Tohin'andrana QUnit an'i Javascript eo amin'i MediaWiki",
 
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'Ny pejinao',
@@ -2922,7 +2926,7 @@ Ampesao ny topi-maso aloha no mihatiry.",
 'tooltip-ca-viewsource' => 'Voaaro ilay pejy. Fa afaka itanao ny voatotiny.',
 'tooltip-ca-history' => "Ny revision natao tamin'ity pejy ity",
 'tooltip-ca-protect' => 'Arovy ity pejy ity',
-'tooltip-ca-unprotect' => "Hanala ny fiarovan'ity pejy ity",
+'tooltip-ca-unprotect' => "Hanova ny lentam-piarovan'ity pejy ity",
 'tooltip-ca-delete' => 'Fafao ity pejy ity',
 'tooltip-ca-undelete' => "Hamerina ny fanovana natao tamin'ity pejy ity talohan'ny famafany",
 'tooltip-ca-move' => 'Ovay anarana ilay pejy',
@@ -2989,7 +2993,8 @@ Mamerina ny version taloha io asa io ary afaka manometraka ny antony anatin'ny a
 'othercontribs' => "Mifototra amin'ny asan'i $1.",
 'others' => 'hafa',
 'siteusers' => '{{SITENAME}} mpikambana $1 miisa $2{{PLURAL:}}',
-'anonusers' => "Ny mpikambana tsy nisoratra anarana $1 ao amin'i {{SITENAME}}",
+'anonusers' => "Ny mpikambana tsy nisoratra anarana $1 ao amin'i {{SITENAME}}{{PLURAL:$2}}",
+'creditspage' => "Fisaorana ho an'ny pejy",
 
 # Spam protection
 'spamprotectiontitle' => "Sivana mpiaro amin'ny spam",
@@ -3009,11 +3014,12 @@ Mamerina ny version taloha io asa io ary afaka manometraka ny antony anatin'ny a
 'pageinfo-length' => 'Halavam-pejy (oktety)',
 'pageinfo-article-id' => 'Laharam-pejy',
 'pageinfo-language' => "Tenin'ny votoatiny",
-'pageinfo-robot-policy' => "Satan'ny motera fikarohana",
-'pageinfo-robot-index' => 'Azo tondroina',
+'pageinfo-robot-policy' => "Fanondroana ataon'ny rôbô",
+'pageinfo-robot-index' => 'Azo atao',
 'pageinfo-robot-noindex' => 'Tsy azo tondroina',
 'pageinfo-views' => "Isan'ny jery",
 'pageinfo-watchers' => "Isan'ny mpandray anjara manaraka",
+'pageinfo-few-watchers' => 'Mpanaraka latsaky ny $1{{PLURAL:}}',
 'pageinfo-redirects-name' => "Fihodinana manketo amin'ity pejy ity",
 'pageinfo-subpages-name' => "Zana-pejin'ity pejy ity",
 'pageinfo-firstuser' => 'Mpamorona ilay pejy',
@@ -3051,6 +3057,7 @@ Mamerina ny version taloha io asa io ary afaka manometraka ny antony anatin'ny a
 'markedaspatrollederrortext' => 'Tsy maintsy misafidy santiôna iray ianao mba hahafahanao manamarika azy ho voamarina.',
 'markedaspatrollederror-noautopatrol' => 'Tsy azonao marihana ho voamarina ny fanovanao.',
 'markedaspatrollednotify' => "Voamarika ho hita ny fanovana natao tamin'i $1.",
+'markedaspatrollederrornotify' => 'Tsy nahamarika azy ho voaara-maso.',
 
 # Patrol log
 'patrol-log-page' => "Laogin'ny fanovana voamarina",
@@ -3221,7 +3228,12 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 'exif-gpsdestlatitude' => 'Laharam-pehintany tanjona',
 'exif-gpsareainformation' => 'Anaram-paritra GPS',
 'exif-gpsdatestamp' => 'Daty GPS',
+'exif-worldregioncreated' => 'Faritany nangalana ity ilay sary',
 'exif-countrycreated' => 'Firenena nangalana ilay sary',
+'exif-countrycodecreated' => 'Kaontim-pirenena nangalana ilay sary',
+'exif-provinceorstatecreated' => 'Faritany nangalana ilay sary',
+'exif-citycreated' => 'Tanàna nangalana ilay sary',
+'exif-sublocationcreated' => 'Fari-tanàna nangalana ilay sary',
 'exif-worldregiondest' => 'Faritany aseho',
 'exif-countrydest' => 'Firenena aseho',
 'exif-countrycodedest' => 'Kaodim-pirenena aseho',
@@ -3242,6 +3254,7 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 'exif-contact' => 'Fampahalalana mikasika ny fifandraisana',
 'exif-writer' => 'Mpanoratra',
 'exif-languagecode' => 'Fiteny',
+'exif-iimversion' => 'filaza IIM',
 'exif-iimcategory' => 'Sokajy',
 'exif-iimsupplementalcategory' => 'Sokajy fanampiny',
 'exif-datetimeexpires' => 'Asa ampiasaina aoriany',
@@ -3265,9 +3278,15 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 'exif-attributionurl' => "Rehefa mampiasa ity asa ity dia asio rohy mankany amin'i",
 'exif-preferredattributionname' => 'Rehefa mampiasa ilay asa, isaory',
 'exif-pngfilecomment' => "Famoahan-kevitra momban'ilay rakitra PNG",
+'exif-disclaimer' => 'Fampitanremana',
 'exif-contentwarning' => 'Fampitandremana mikasika ny votoatiny',
 'exif-giffilecomment' => 'Famoahan-kevitry ny rakirta GIF',
 'exif-intellectualgenre' => 'Karazan-javatra',
+'exif-subjectnewscode' => "Kaodin'ny lohahevitra",
+'exif-event' => 'Zava-mitranga azo sary',
+'exif-organisationinimage' => 'Fikambanana azo sary',
+'exif-personinimage' => 'Olona azo sary',
+'exif-originalimageheight' => "Haambon-tsary talohan'ny nanovana azy",
 
 'exif-copyrighted-true' => "Iharan'ny zom-pamorona",
 'exif-copyrighted-false' => "Toetran'ny zom-pamorona tsy voafaritra",
@@ -3275,10 +3294,20 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 'exif-unknowndate' => 'Daty tsy fantatra',
 
 'exif-orientation-1' => 'Tsotra',
+'exif-orientation-3' => 'Ahodina 180°',
+'exif-orientation-4' => 'Navadika ambony ambany',
+'exif-orientation-5' => 'Navadika 90° miankavia ary navadika ambony ambany',
+'exif-orientation-6' => 'Navadika 90° miankavia',
+'exif-orientation-7' => 'Navadika 90° miankavanana ary navadika ambony ambany',
+'exif-orientation-8' => 'Navadika 90° miankavanana',
+
+'exif-planarconfiguration-2' => 'Data misaraka',
 
 'exif-componentsconfiguration-0' => 'tsy nahitana',
 
 'exif-exposureprogram-0' => 'Tsy nolazaina',
+'exif-exposureprogram-1' => 'Natao tanana',
+'exif-exposureprogram-2' => 'Fandaharana ara-dalàna',
 
 'exif-subjectdistance-value' => '$1 metatra',
 
@@ -3295,8 +3324,16 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 'exif-lightsource-9' => "Toetr'andro mazava",
 'exif-lightsource-10' => "Toetr'andro mandrahona",
 'exif-lightsource-11' => 'Haloka',
+'exif-lightsource-17' => 'Jiro manara-penitra A',
+'exif-lightsource-18' => 'Jiro manara-penitra B',
+'exif-lightsource-19' => 'Jiro manara-penitra C',
+'exif-lightsource-24' => "Tangistenina ISO an'ny studio",
+'exif-lightsource-255' => 'Loharanon-kazavana hafa',
 
 # Flash modes
+'exif-flash-fired-0' => 'Tsy nirehitra ny flash',
+'exif-flash-fired-1' => 'Nirehitra ny flash',
+'exif-flash-return-0' => 'Tsy misy stirôbôskôpy mamerina lefa fahitana',
 'exif-flash-mode-3' => 'Toetra aotômatika',
 
 'exif-focalplaneresolutionunit-2' => 'Posy',
@@ -3328,7 +3365,7 @@ Tokony sary tsy misy na sary tsy izy ny rohy voalohany anaty andalana iray .
 
 # External editor support
 'edit-externally' => "Ovao amin'ny alalan'ny fampiasana fitaovana ivelan'ity Wiki ity io rakitra io",
-'edit-externally-help' => "jereo any amin'[//www.mediawiki.org/wiki/Manual:External_editors ny torolalana] ny fanazavana fanampiny,.",
+'edit-externally-help' => "jereo any amin'[https://www.mediawiki.org/wiki/Manual:External_editors ny torolalana] ny fanazavana fanampiny,.",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'rehetra',
@@ -3389,6 +3426,11 @@ Azafady hamafiso fa tena irinao averina hoforonina tokoa ity lahatsoratra ity.",
 'confirm_purge_button' => 'Eka',
 'confirm-purge-top' => "Fafana ve ny cache-n'ity pejy ity?",
 
+# action=watch/unwatch
+'confirm-watch-top' => 'Hanaraka ity pejy ity?',
+'confirm-unwatch-button' => 'OK',
+'confirm-unwatch-top' => "Hanala ity pejy ity amin'ny lisitry ny pejy arahinao?",
+
 # Multipage image navigation
 'imgmultipageprev' => '← pejy nialoha',
 'imgmultipagenext' => 'pejy manaraka →',
@@ -3403,6 +3445,7 @@ Azafady hamafiso fa tena irinao averina hoforonina tokoa ity lahatsoratra ity.",
 'table_pager_first' => 'Pejy voalohany',
 'table_pager_last' => 'Pejy farany',
 'table_pager_limit' => 'Haneho zavatra $1 isaky ny pejy',
+'table_pager_limit_label' => 'Valiny isam-pejy:',
 'table_pager_limit_submit' => 'Hitsidika',
 'table_pager_empty' => 'Tsy nahitana valiny',
 
@@ -3429,7 +3472,11 @@ Andramo ny topi-maso tsotra',
 'watchlistedit-noitems' => 'Tsy misy lohateny ny lisitrao.',
 'watchlistedit-normal-title' => 'Hanova ny lisitra ny pejy arahako maso',
 'watchlistedit-normal-legend' => "Hanala lohateny ao amin'ny lisitra",
+'watchlistedit-normal-explain' => "Aseho eo ambany ny lohateny ao amin'ny lisitry ny pejy arahanao.
+Tsindrio ny boaty eo akaikiny ary tsindrio  « {{int:Watchlistedit-normal-submit}} ».
+Azonao atao ihany koa ny [[Special:EditWatchlist/raw|manova ilay lisitra amin'ny akorany]].",
 'watchlistedit-normal-submit' => 'Hanala ireo lohateny nosafidiana ireo',
+'watchlistedit-normal-done' => "Afaka tamin'ny lisitry ny pejy arahanao ny lohateny $1{{PLURAL:}}",
 'watchlistedit-raw-title' => "Hanova ny lisitra ny pejy arahako maso amin'ny fomba akorany",
 'watchlistedit-raw-legend' => "Fanovana ilay lisitry ny pejy arahina maso amin'ny fomba akorany",
 'watchlistedit-raw-titles' => 'Lohateny :',
@@ -3454,6 +3501,7 @@ Andramo ny topi-maso tsotra',
 'version-hook-subscribedby' => "Nalefan'i",
 'version-version' => '(Santiôna $1)',
 'version-license' => 'Lisansy',
+'version-poweredby-others' => 'hafa',
 'version-software' => 'Rindrankahy voapetraka',
 'version-software-product' => 'Vokatra',
 'version-software-version' => 'Santiôna',
index 5952fe5..1c504f3 100644 (file)
@@ -230,7 +230,7 @@ $messages = array(
 'errorpagetitle' => 'Йоҥылыш',
 'returnto' => '$1 деке пӧртылаш.',
 'tagline' => '{{SITENAME}} гыч',
-'help' => 'Ð\9fолÑ\88Ñ\8bк',
+'help' => 'Ð\9fолÑ\8bÑ\88',
 'search' => 'Кычалмаш',
 'searchbutton' => 'Кычалаш',
 'go' => 'Куснаш',
@@ -262,7 +262,7 @@ $messages = array(
 'userpage' => 'Пайдаланышын лаштыкым ончалаш',
 'imagepage' => 'Файлын лаштыкым ончалаш',
 'templatepage' => 'Ямдылыкын лаштыкым ончалаш',
-'viewhelppage' => 'Ð\9fолÑ\88Ñ\8bк лаштыкым ончалаш',
+'viewhelppage' => 'Ð\9fолÑ\8bÑ\88 лаштыкым ончалаш',
 'categorypage' => 'Категорийын лаштыкым ончалаш',
 'viewtalkpage' => 'Ончалаш каҥашымашым',
 'otherlanguages' => 'Вес йылме дене',
@@ -298,8 +298,6 @@ $messages = array(
 'ok' => 'Йӧра',
 'retrievedfrom' => 'Налме вер — "$1"',
 'youhavenewmessages' => 'Тендан $1 уло ($2).',
-'newmessageslink' => 'У серыш',
-'newmessagesdifflink' => 'пытартыш тӧрлатымаш',
 'editsection' => 'тӧрлаташ',
 'editold' => 'тӧрлаташ',
 'viewsourceold' => 'тӱҥалтыш текстым ончалаш',
@@ -333,6 +331,7 @@ $messages = array(
 
 # General errors
 'error' => 'Йоҥылыш',
+'databaseerror-error' => 'Йоҥылыш: $1',
 'missing-article' => 'Тыгай текст дене возымо лаштык базыште муалтын огыл, "$1" $2.
 
 Кунам тый тоштемше кылвер почеш шӧрымӧ вашталтымаш лаштыкыш (але эртымгорно лаштыкыш) куснет, тыге лийын кертеш.
@@ -355,24 +354,30 @@ $messages = array(
 'virus-unknownscanner' => 'палыдыме антивирус:',
 
 # Login and logout pages
+'welcomeuser' => 'Пагален ӱжына, $1!',
 'yourname' => 'Пайдаланышын лӱмжӧ:',
 'yourpassword' => 'Шолыпмут:',
+'createacct-yourpassword-ph' => 'Шолыпмутым пурто',
 'yourpasswordagain' => 'Шолыпмутым угыч пуртымаш:',
+'createacct-yourpasswordagain' => 'Шолыпмутым пеҥгыдемде',
+'createacct-yourpasswordagain-ph' => 'Шолыпмутым угыч пурто',
 'remembermypassword' => 'Тиде компьютерыште мыйым шарнаш (эн шуко $1 {{PLURAL:$1|кечылан|кечылан}})',
 'yourdomainname' => 'Тендан домен:',
-'login' => 'Шке денет палымым ыште',
+'login' => 'Шке денет палдаре',
 'nav-login-createaccount' => 'Пураш/Регистрацийым эрте',
-'loginprompt' => '{{SITENAME}} Ñ\82Ñ\8bй Ð´ÐµÐ½ÐµÑ\82 Ð¿Ð°Ð»Ñ\8bме Ð»Ð¸Ð¹Ð¼Ð°Ñ\88лан, cookies Ñ\87ӱкÑ\82алÑ\82Ñ\8bн Ñ\83лÑ\88аÑ\88.',
-'userlogin' => 'Шке Ð´ÐµÐ½ÐµÑ\82 Ð¿Ð°Ð»Ñ\8bмÑ\8bм Ñ\8bÑ\88Ñ\82е/РегиÑ\81Ñ\82Ñ\80аÑ\86ийÑ\8bм Ñ\8dÑ\80Ñ\82е',
+'loginprompt' => '{{SITENAME}} Ñ\88ке Ð´ÐµÐ½ÐµÑ\82 Ð¿Ð°Ð»Ð´Ð°Ñ\80Ñ\8bме Ð´ÐµÑ\87 Ð¾Ð½Ñ\87Ñ\8bÑ\87 ÐºÐ¾Ð¼Ð¿Ñ\8cÑ\8eÑ\82еÑ\80Ñ\8bÑ\88Ñ\82еÑ\82 Â«cookies»-Ñ\8bм Ñ\87ӱкÑ\82Ñ\8bман.',
+'userlogin' => 'Ð\9fÑ\83Ñ\80аÑ\88/РегиÑ\81Ñ\82Ñ\80аÑ\86ийÑ\8bм Ñ\8dÑ\80Ñ\82аÑ\88',
 'logout' => 'Лекташ',
 'userlogout' => 'Лекташ',
 'nologin' => "Тый регистрацийым эше эртен отыл? '''$1'''.",
 'nologinlink' => 'Регистрацийым эрте',
 'createaccount' => 'Регистрацийым эрте',
 'gotaccount' => "Тый регистрацийым эртенат? '''$1'''.",
-'gotaccountlink' => 'Шке денет палымым ыште',
+'gotaccountlink' => 'Шке денет палдаре',
 'userlogin-resetlink' => 'Лӱмдам але шолыпмутдам монденда?',
+'userlogin-resetpassword-link' => 'Шолыпмутым монденат?',
 'createaccountmail' => 'Кӱчык жаплан чокым ыштыме шолыпмутым мылам e-mail дене колташ',
+'createacct-benefit-heading' => '{{SITENAME}} тендан гаяк еҥ-влак дене ыштен шындалтын.',
 'nosuchuser' => '"$1" лӱман пайдаланыше уке.
 Пайдаланышын лӱмыштӧ йӱкпале-влакын кугытшо тӱрыс лийшаш.
 Лӱмым чын возымым терге але [[Special:UserLogin/signup|регистрацийым эрте]].',
@@ -647,6 +652,7 @@ $messages = array(
 'recentchanges-label-minor' => 'Тиде изи тӧрлатымаш',
 'recentchanges-label-bot' => 'Тиде тӧрлатымашым бот ыштен',
 'recentchanges-label-unpatrolled' => 'Тиде тӧрлатымашым нигӧ терген огыл',
+'recentchanges-legend-newpage' => '$1 - у лаштык',
 'rcnote' => "Ӱлнӧ {{PLURAL:$1|'''1'''|'''$1'''}} вашталтыш пытартыш {{PLURAL:$2||'''$2'''}} кечылан, $5-лан, $4-лан.",
 'rcnotefrom' => "Ниже перечислены изменения с '''$2''' (не более '''$1''').",
 'rclistfrom' => '$1 гыч тӱҥалын у вашталтымашым ончыкташ',
@@ -997,7 +1003,7 @@ $messages = array(
 'tooltip-pt-preferences' => 'Мыйын келыштарымашем',
 'tooltip-pt-watchlist' => 'Мыйын эскерыме лаштык-влак лӱмер',
 'tooltip-pt-mycontris' => 'Тыйын пашатым эскерыме лаштык',
-'tooltip-pt-login' => 'Шке Ð´ÐµÐ½ÐµÑ\82 Ð¿Ð°Ð»Ñ\8bмÑ\8bм Ñ\8bÑ\88Ñ\82еÑ\82 Ð³Ñ\8bн Ñ\81айÑ\80ак Ð»Ð¸ÐµÑ\88; Ñ\82акÑ\88Ñ\8bм Ñ\82идÑ\8bм Ñ\8bÑ\88Ñ\82Ñ\8bдеаÑ\82 ÐºÐµÑ\80Ñ\82аÑ\82.',
+'tooltip-pt-login' => 'ТÑ\8bÑ\88Ñ\82е Ñ\80егиÑ\81Ñ\82Ñ\80аÑ\86ийÑ\8bм Ñ\8dÑ\80Ñ\82ен ÐºÐµÑ\80Ñ\82аÑ\82. Ð ÐµÐ³Ð¸Ñ\81Ñ\82Ñ\80аÑ\86ий Ð´ÐµÑ\87 Ð¿Ð¾Ñ\81нааÑ\82 Ð¿Ð°Ñ\88ам Ñ\8bÑ\88Ñ\82аÑ\88 Ð»Ð¸ÐµÑ\88.',
 'tooltip-pt-logout' => 'Системе гыч лекташ',
 'tooltip-ca-talk' => 'Лаштыкыште возымым каҥашаш',
 'tooltip-ca-edit' => 'Тый тиде лаштыкым тӧрлатен кертат. Лаштыкым аралыме деч ончыч тудым тергаш ит мондо.',
@@ -1020,7 +1026,7 @@ $messages = array(
 'tooltip-n-currentevents' => 'Мо лийме нерген нерген пытартыш увер',
 'tooltip-n-recentchanges' => 'Пытартыш вашталтымаш лӱмер',
 'tooltip-n-randompage' => 'Лаштыкым чокым ойыраш',
-'tooltip-n-help' => 'Ð\92икипедийÑ\8bм ÐºÑ\83Ñ\87Ñ\8bлÑ\82мо Ð´Ð° Ñ\82Ó§Ñ\80лаÑ\82Ñ\8bме Ñ\88оÑ\82Ñ\8bÑ\88Ñ\82о Ð¿Ð¾Ð»Ñ\88Ñ\8bк.',
+'tooltip-n-help' => 'Ð\92икипедийÑ\8bм ÐºÑ\83Ñ\87Ñ\8bлÑ\82мо Ð´Ð° Ñ\82Ó§Ñ\80лаÑ\82Ñ\8bме Ñ\88оÑ\82Ñ\8bÑ\88Ñ\82о Ð¿Ð¾Ð»Ñ\8bÑ\88.',
 'tooltip-t-whatlinkshere' => 'Тышке кондышо лаштык-влакын лӱмерышт',
 'tooltip-t-recentchangeslinked' => 'Тиде лаштык дене кылдалтше пытартыш тӧрлатымаш-влак',
 'tooltip-feed-rss' => 'Тиде лаштыклан RSS-кыл',
@@ -1094,7 +1100,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'Файлым ӧрдыж программыште тӧрлаташ',
-'edit-externally-help' => '(Сайрак палашлан ончал [//www.mediawiki.org/wiki/Manual:External_editors шындымаш нерген туныктымашым])',
+'edit-externally-help' => '(Сайрак палашлан ончал [https://www.mediawiki.org/wiki/Manual:External_editors шындымаш нерген туныктымашым])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'чыла',
@@ -1151,4 +1157,8 @@ $messages = array(
 
 #Размещайте фрагменты регулярных выражений над этой строчкой. Оставьте эту строчку такой, как она есть.</pre>',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Йӧра',
+'expand_templates_preview' => 'Ончылгоч ончымаш',
+
 );
index 1354166..ef2f2de 100644 (file)
@@ -21,7 +21,7 @@ $fallback = 'id';
 $namespaceNames = array(
        NS_MEDIA            => 'Media',
        NS_SPECIAL          => 'Istimewa',
-       NS_TALK             => 'Maota',
+       NS_TALK             => 'Rundiang',
        NS_USER             => 'Pangguno',
        NS_USER_TALK        => 'Rundiang_Pangguno',
        NS_PROJECT_TALK     => 'Rundiang_$1',
@@ -53,41 +53,43 @@ $namespaceAliases = array(
        'Pembicaraan_Bantuan'   => NS_HELP_TALK,
        'Kategori'              => NS_CATEGORY,
        'Pembicaraan_Kategori'  => NS_CATEGORY_TALK,
+
+       'Maota'                 => NS_TALK,
 );
 
 $specialPageAliases = array(
        'Activeusers'               => array( 'PanggunoAktip', 'Pangguno_aktip' ),
-       'Allmessages'               => array( 'PasanSistim', 'Pasan_sistem' ),
+       'Allmessages'               => array( 'PasanSistim', 'Pasan_sistim' ),
        'Allpages'                  => array( 'DaptaLaman', 'Dapta_laman' ),
        'Ancientpages'              => array( 'LamanLamo', 'Laman_lamo' ),
        'Badtitle'                  => array( 'JudulBuruak', 'Judul_indak_rancak' ),
        'Blankpage'                 => array( 'LamanKosong', 'Laman_kosong' ),
-       'Block'                     => array( 'Blokir', 'IPkanaiBlok', 'PanggunoTablokir' ),
-       'Blockme'                   => array( 'BlokDen', 'BlokirAmbo' ),
+       'Block'                     => array( 'Sakek', 'IPkanaiSakek', 'PanggunoTasakek' ),
        'Booksources'               => array( 'SumberBuku', 'Sumber_buku' ),
        'BrokenRedirects'           => array( 'PangaliahanRusak', 'Pangaliahan_rusak' ),
        'Categories'                => array( 'Kategori' ),
        'ChangeEmail'               => array( 'GantiSurel', 'Ganti_surel' ),
-       'ChangePassword'            => array( 'GantiSandi', 'TukaSandi', 'TukaKatoSandi' ),
+       'ChangePassword'            => array( 'GantiSandi', 'TukaKatoSandi' ),
        'ComparePages'              => array( 'BandiangkanLaman', 'Bandiangkan_laman' ),
        'Confirmemail'              => array( 'PastikanSurel', 'Pastikan_surel' ),
-       'Contributions'             => array( 'SuntiangPangguno', 'Suntiangan_pangguno' ),
+       'Contributions'             => array( 'SuntiangPangguno', 'Jariah' ),
        'CreateAccount'             => array( 'BuekAkun', 'Buek_akun' ),
        'Deadendpages'              => array( 'LamanBuntu', 'Laman_buntu' ),
        'DeletedContributions'      => array( 'SuntiangDihapuih', 'Suntiangan_kanai_hapuih' ),
-       'Disambiguations'           => array( 'SamoArti', 'Samo_arti' ),
-       'EditWatchlist'             => array( 'SuntiangDaptaPantau', 'Suntiang_dapta_pantau' ),
+       'DoubleRedirects'           => array( 'PangaliahanGanda', 'Pangaliahan_ganda' ),
+       'EditWatchlist'             => array( 'SuntiangPantauan', 'Suntiang_pantauan' ),
        'Emailuser'                 => array( 'SurelPangguno', 'Surel_pangguno' ),
        'Export'                    => array( 'Ekspor' ),
-       'Fewestrevisions'           => array( 'ParubahanTasaketek', 'Parubahan_tasaketek' ),
+       'Fewestrevisions'           => array( 'ParubahanTasangenek', 'Parubahan_tasangenek' ),
        'FileDuplicateSearch'       => array( 'CariBerkasDuplikat', 'Cari_berkas_duplikat' ),
        'Filepath'                  => array( 'LokasiBerkas', 'Lokasi_berkas' ),
        'Import'                    => array( 'Impor' ),
-       'Invalidateemail'           => array( 'BatalSurel', 'Batalkan_surel' ),
+       'Invalidateemail'           => array( 'BatalSurel', 'Batalan_surel' ),
        'JavaScriptTest'            => array( 'TesSkripJava', 'Tes_skrip_Java' ),
-       'BlockList'                 => array( 'DaptaBlokir', 'Dapta_pemblokiran', 'Dapta_IP_diblok' ),
-       'LinkSearch'                => array( 'CariTautan', 'Cari_tautan' ),
-       'Listadmins'                => array( 'DaptaPanguruih' ),
+       'BlockList'                 => array( 'DaptaSakek', 'Dapta_pemblokiran', 'Dapta_IP_disakek' ),
+       'LinkSearch'                => array( 'CariPautan', 'Cari_pautan' ),
+       'Listadmins'                => array( 'DaptaPanguruih', 'Dapta_panguruih' ),
+       'Listbots'                  => array( 'DaptaBot' ),
        'Listfiles'                 => array( 'DaptaBerkas', 'DaptaGamba' ),
        'Listgrouprights'           => array( 'DaptaHakKalompok', 'HakKalompokPangguno' ),
        'Listredirects'             => array( 'DaptaPangaliahan', 'Dapta_pangaliahan' ),
@@ -106,9 +108,58 @@ $specialPageAliases = array(
        'Mostlinkedtemplates'       => array( 'TemplatTautanTabanyak', 'TemplatAcokDipakai' ),
        'Mostrevisions'             => array( 'ParubahanTabanyak' ),
        'Movepage'                  => array( 'PindahLaman', 'Pindahkan_laman' ),
-       'Mycontributions'           => array( 'SuntianganAmbo', 'Suntiangan_ambo' ),
-       'Mypage'                    => array( 'LamanDenai', 'Laman_denai' ),
-       'Mytalk'                    => array( 'DiskusiAmbo' ),
+       'Mycontributions'           => array( 'JariahDenai', 'Jariah_Ambo' ),
+       'Mypage'                    => array( 'LamanDenai', 'Laman_Ambo' ),
+       'Mytalk'                    => array( 'RundiangDenai', 'Laman_rundiang__Ambo' ),
+       'Myuploads'                 => array( 'DenaiMuek', 'Nan_Ambo_muek' ),
+       'Newimages'                 => array( 'BerkasBaru', 'Berkas_baru' ),
+       'Newpages'                  => array( 'LamanBaru', 'Laman_baru' ),
+       'PagesWithProp'             => array( 'LamanJoProperti', 'Laman_jo_properti' ),
+       'PasswordReset'             => array( 'TukaSandi', 'Tuka_baliak_sandi' ),
+       'PermanentLink'             => array( 'PautanPamanen', 'Pautan_pamanen' ),
+       'Popularpages'              => array( 'LamanPopuler', 'Laman_populer' ),
+       'Preferences'               => array( 'Rujuakan' ),
+       'Prefixindex'               => array( 'DaptaAwalan' ),
+       'Protectedpages'            => array( 'LamanTalinduang', 'Laman_nan_dilinduang' ),
+       'Protectedtitles'           => array( 'JudulTalinduang' ),
+       'Randompage'                => array( 'LamanSumbarang' ),
+       'Randomredirect'            => array( 'PangaliahanSumbarang' ),
+       'Recentchanges'             => array( 'ParubahanBaru' ),
+       'Recentchangeslinked'       => array( 'ParubahanTakaik' ),
+       'Redirect'                  => array( 'Pangaliahan' ),
+       'Revisiondelete'            => array( 'HapuihRevisi' ),
+       'Search'                    => array( 'Cari', 'Pancarian' ),
+       'Shortpages'                => array( 'LamanPendek' ),
+       'Specialpages'              => array( 'LamanIstimewa' ),
+       'Unblock'                   => array( 'PambatalanSakek' ),
+       'Uncategorizedcategories'   => array( 'KategoriIndakTakategori' ),
+       'Uncategorizedimages'       => array( 'BerkasIndakTakategori' ),
+       'Uncategorizedpages'        => array( 'LamanIndakTakategori' ),
+       'Uncategorizedtemplates'    => array( 'TemplatIndakTakategori' ),
+       'Undelete'                  => array( 'BatalHapuih' ),
+       'Unlockdb'                  => array( 'BukakKunciBD' ),
+       'Unusedcategories'          => array( 'KategoriKosong' ),
+       'Unusedimages'              => array( 'BerkasIndakTapakai' ),
+       'Unusedtemplates'           => array( 'TemplatIndakTapakai' ),
+       'Unwatchedpages'            => array( 'LamanIndakTapantau' ),
+       'Upload'                    => array( 'Muek' ),
+       'Userlogin'                 => array( 'MasuakLog' ),
+       'Userlogout'                => array( 'KaluaLog' ),
+       'Userrights'                => array( 'HakPangguno' ),
+       'Wantedcategories'          => array( 'KategoriNanParalu' ),
+       'Wantedfiles'               => array( 'BerkasNanParalu' ),
+       'Wantedpages'               => array( 'LamanNanParalu' ),
+       'Wantedtemplates'           => array( 'TemplatNanParalu' ),
+       'Watchlist'                 => array( 'Pantauan' ),
+       'Whatlinkshere'             => array( 'PautanBaliak' ),
+       'Withoutinterwiki'          => array( 'InterwikiIndakAdo' ),
+);
+
+$magicWords = array(
+       'redirect'                  => array( '0', '#ALIAH', '#ALIH', '#REDIRECT' ),
+       'pagesincategory_all'       => array( '0', 'sado', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'laman', 'pages' ),
+       'pagesincategory_files'     => array( '0', 'berkas', 'files' ),
 );
 
 $messages = array(
@@ -386,8 +437,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Didapek dari "$1"',
 'youhavenewmessages' => 'Sanak punyo $1 ($2).',
-'newmessageslink' => 'pasan baru',
-'newmessagesdifflink' => 'parubahan tarakhia',
 'youhavenewmessagesfromusers' => 'Sanak mandapek $1 dari {{PLURAL:$3|$3 pangguno}} ($2)',
 'youhavenewmessagesmanyusers' => 'Sanak mandapek $1 dari banyak pangguno ($2)',
 'newmessageslinkplural' => '{{PLURAL:$1|pasan baru}}',
@@ -1157,8 +1206,6 @@ Ingek indeks Google untuak {{SITENAME}} mungkin lah kadaluarsa.',
 'preferences' => 'Pangaturan',
 'mypreferences' => 'Pangaturan',
 'prefs-edits' => 'Jumlah suntiangan:',
-'prefsnologin' => 'Alun masuak log',
-'prefsnologintext' => 'Sanak musti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} masuak log]</span> untuak mengeset pangaturan.',
 'changepassword' => 'Tuka kato sandi',
 'prefs-skin' => 'Kulik',
 'skin-preview' => 'Caliak',
@@ -2253,6 +2300,8 @@ Sanak hanyo buliah mancaliak sumbernyo sajo',
 # Spam protection
 'spam_blanking' => 'Sado revisi nan ado pautan ka $1, kosong',
 'spam_deleting' => 'Sado revisi nan ado pautan ka $1, dihapuih',
+'simpleantispam-label' => "Pamarisoan anti-spam.
+Masukan ko '''DILARANG'''!",
 
 # Info page
 'pageinfo-title' => 'Informasi untuak "$1"',
@@ -2468,7 +2517,7 @@ Nan lainnyo akan tasuruak sacaro baku.
 
 # External editor support
 'edit-externally' => 'Suntiang berkas ko jo aplikasi lua',
-'edit-externally-help' => '(Caliak [//www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] untuak informasi lanjuiknyo)',
+'edit-externally-help' => '(Caliak [https://www.mediawiki.org/wiki/Manual:External_editors instruksi pangaturan] untuak informasi lanjuiknyo)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kasadonyo',
@@ -2526,7 +2575,7 @@ Sanak dapek juo [[Special:EditWatchlist|manggunoan panyuntiang standarnyo]].',
 'version-other' => 'Lain-lain',
 'version-version' => '(Versi $1)',
 'version-license' => 'Lisensi',
-'version-poweredby-credits' => "Wiki ko didukuang jo '''[//www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki ko didukuang jo '''[https://www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
 'version-poweredby-others' => 'lainnyo',
 'version-credits-summary' => 'Kami nio mangakui urang-urang ko ateh kontribusinyo pado [[Special:Version|MediaWiki]].',
 'version-license-info' => 'MediaWiki adolah parangkaik lunak bebas; Sanak dapek mandistribusian dan/atau mamodfikasinyo jo syaraik Lisensi Publik Umum GNU nan dikaluaan dek Free Software Foundation; versi 2 atau nan tabaru.
@@ -2549,8 +2598,7 @@ Sanak mustilah alah manarimo [{{SERVER}}{{SCRIPTPATH}}/COPYING salinan Lisensi P
 
 # Special:SpecialPages
 'specialpages' => 'Laman istimewa',
-'specialpages-note' => '----
-* Laman istimewa normal.
+'specialpages-note' => '* Laman istimewa normal.
 * <span class="mw-specialpagerestricted">Laman istimewa talarang.</span>
 * <span class="mw-specialpagecached">Laman istimewa tasinggah (mungkin usang).</span>',
 'specialpages-group-maintenance' => 'Laporan pamaliharoan',
@@ -2648,4 +2696,13 @@ Sanak mustilah alah manarimo [{{SERVER}}{{SCRIPTPATH}}/COPYING salinan Lisensi P
 # Image rotation
 'rotate-comment' => 'Gambar diputa $1 {{PLURAL:$1|darajaik}} saarah jarum jam',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Pangambangan templat',
+'expand_templates_input' => 'Teks masuakan:',
+'expand_templates_output' => 'Hasil',
+'expand_templates_xml_output' => 'Hasil XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Hapuih komentar',
+'expand_templates_preview' => 'Pratonton',
+
 );
index fabf597..4eb3ca2 100644 (file)
@@ -95,12 +95,12 @@ $dateFormats = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'АктивниКорисници' ),
        'Allmessages'               => array( 'СитеПораки' ),
+       'AllMyUploads'              => array( 'СитеМоиПодигања' ),
        'Allpages'                  => array( 'СитеСтраници' ),
        'Ancientpages'              => array( 'НајстариСтраници' ),
        'Badtitle'                  => array( 'Лошнаслов' ),
        'Blankpage'                 => array( 'ПразнаСтраница' ),
        'Block'                     => array( 'Блокирање', 'БлокIP', 'БлокирајКорисник' ),
-       'Blockme'                   => array( 'БлокирајМе' ),
        'Booksources'               => array( 'ПечатенИзвор' ),
        'BrokenRedirects'           => array( 'ПрекинатиПренасочувања' ),
        'Categories'                => array( 'Категории' ),
@@ -112,10 +112,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'СоздајКорисничкаСметка' ),
        'Deadendpages'              => array( 'ЌорсокакСтраници' ),
        'DeletedContributions'      => array( 'ИзбришаниПридонеси' ),
-       'Disambiguations'           => array( 'Појаснувања' ),
        'DoubleRedirects'           => array( 'ДвојниПренасочувања' ),
        'EditWatchlist'             => array( 'УредиНабљудувања' ),
        'Emailuser'                 => array( 'Пиши_е-пошта_на_корисникот' ),
+       'ExpandTemplates'           => array( 'ПрошириШаблони' ),
        'Export'                    => array( 'Извоз' ),
        'Fewestrevisions'           => array( 'НајмалкуРевизии' ),
        'FileDuplicateSearch'       => array( 'ПребарувањеДупликатПодатотека' ),
@@ -156,14 +156,16 @@ $specialPageAliases = array(
        'PermanentLink'             => array( 'ПостојанаВрска' ),
        'Popularpages'              => array( 'ПопуларниСтраници' ),
        'Preferences'               => array( 'Нагодувања' ),
-       'Prefixindex'               => array( 'Ð\98ндекÑ\81Ð\9dаÐ\9fÑ\80еÑ\84икÑ\81и' ),
+       'Prefixindex'               => array( 'Ð\98ндекÑ\81Ð\9dаÐ\9fÑ\80еÑ\82Ñ\81Ñ\82авки' ),
        'Protectedpages'            => array( 'ЗаштитениСтраници' ),
        'Protectedtitles'           => array( 'ЗаштитениНаслови' ),
        'Randompage'                => array( 'Случајна', 'СлучајнаСтраница' ),
+       'RandomInCategory'          => array( 'СлучајнаВоКатегорија' ),
        'Randomredirect'            => array( 'СлучајноПренасочување' ),
        'Recentchanges'             => array( 'СкорешниПромени' ),
        'Recentchangeslinked'       => array( 'ПоврзаниПромени' ),
        'Redirect'                  => array( 'Пренасочување' ),
+       'ResetTokens'               => array( 'ВратиОдновоЗнаци' ),
        'Revisiondelete'            => array( 'БришењеРевизија' ),
        'Search'                    => array( 'Барај' ),
        'Shortpages'                => array( 'КраткиСтраници' ),
@@ -254,6 +256,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'центар', 'ц', 'center', 'centre' ),
        'img_framed'                => array( '1', 'рамка', 'ворамка', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'безрамка', 'frameless' ),
+       'img_lang'                  => array( '1', 'јаз=$1', 'lang=$1' ),
        'img_page'                  => array( '1', 'страница=$1', 'страница_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'исправено', 'исправено=$1', 'исправено_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'граничник', 'граница', 'border' ),
@@ -293,6 +296,7 @@ $magicWords = array(
        'revisionyear'              => array( '1', 'ГОДИНАНАРЕВИЗИЈА', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', 'ВРЕМЕНАРЕВИЗИЈА', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'КОРИСНИКНАНАРЕВИЗИЈА', 'REVISIONUSER' ),
+       'revisionsize'              => array( '1', 'ГОЛЕМИНАНАРЕВИЗИЈА', 'REVISIONSIZE' ),
        'plural'                    => array( '0', 'МНОЖИНА:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'ПОЛНАURL:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'ПОЛНАURLE:', 'FULLURLE:' ),
@@ -489,8 +493,6 @@ $messages = array(
 'noindex-category' => 'Неиндексирани страници',
 'broken-file-category' => 'Страници со прекинати врски до податотеки',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'За {{SITENAME}}',
 'article' => 'Статија',
 'newwindow' => '(се отвора во нов прозорец)',
@@ -628,12 +630,10 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Преземено од „$1“',
 'youhavenewmessages' => 'Имате $1 ($2).',
-'newmessageslink' => 'нови пораки',
-'newmessagesdifflink' => 'скорешна промена',
 'youhavenewmessagesfromusers' => 'Имате $1 од {{PLURAL:$3|еден корисник|$3 корисници}} ($2).',
 'youhavenewmessagesmanyusers' => 'Имате $1 од многу корисници ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|нова порака|нови пораки}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|последна промена|последни промени}}',
+'newmessageslinkplural' => '{{PLURAL:$1|нова порака|999=нови пораки}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|последна промена|999=последни промени}}',
 'youhavenewmessagesmulti' => 'Имате нови пораки на $1',
 'editsection' => 'уреди',
 'editold' => 'уреди',
@@ -766,7 +766,8 @@ $2',
 'invalidtitle-knownnamespace' => 'Неважечки наслов со именски простор „$2“ и текст „$3“',
 'invalidtitle-unknownnamespace' => 'Неважечки наслов со именски простор бр. $1 и текст „$2“',
 'exception-nologin' => 'Не сте најавени',
-'exception-nologin-text' => 'Оваа страница или постапка бара да сте најавени на викито.',
+'exception-nologin-text' => '[[Special:Userlogin|Најавете се]] за да добиете пристап до страницата или дејството.',
+'exception-nologin-text-manual' => 'Треба да сте $1 за да имате пристап до страницата или дејството.',
 
 # Virus scanner
 'virus-badscanner' => "Лоша поставка: непознат проверувач на вируси: ''$1''",
@@ -813,7 +814,7 @@ $2',
 'gotaccount' => "Веќе имате корисничка сметка? '''$1'''.",
 'gotaccountlink' => 'Најавете се',
 'userlogin-resetlink' => 'Си ги заборавивте податоците за најава?',
-'userlogin-resetpassword-link' => 'Смени Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°',
+'userlogin-resetpassword-link' => 'Ð\88а Ð·Ð°Ð±Ð¾Ñ\80авивÑ\82е Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°Ñ\82а?',
 'helplogin-url' => 'Help:Најава',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Помош со најавата]]',
 'userlogin-loggedin' => 'Веќе сте најавени како {{GENDER:$1|$1}}.
@@ -889,7 +890,7 @@ $2',
 'mailerror' => 'Грешка при испраќање на е-поштата: $1',
 'acct_creation_throttle_hit' => 'Корисници на ова вики користејќи ја вашата IP-адреса создале {{PLURAL:$1|1 корисничка сметка|$1 кориснички сметки}} во последниве денови, при што е достигнат максималниот број на кориснички сметки предвиден и овозможен за овој период.
 Како резултат на ова, посетителите кои ја користат оваа IP-адреса во моментов нема да можат да создаваат нови сметки.',
-'emailauthenticated' => 'Ð\92аÑ\88аÑ\82а Ðµ-поÑ\88Ñ\82енÑ\81ка Ð°Ð´Ñ\80еÑ\81а Ðµ Ð¿Ð¾Ñ\82вÑ\80дена Ð½Ð° $2 Ð²Ð¾ $3 Ñ\87.',
+'emailauthenticated' => 'Вашата е-пошта адреса е потврдена на $2 во $3 ч.',
 'emailnotauthenticated' => 'Вашата е-поштенска адреса сè уште не е потврдена.
 Нема да биде испратена е-пошта во ниту еден од следниве случаи.',
 'noemailprefs' => 'Наведете е-поштенска адреса за да функционираат следниве својства.',
@@ -1336,19 +1337,20 @@ $2
 'revdelete-text' => "'''Избришаните измени и настани сѐ уште ќе се појавуваат во историјата на страницата и дневниците, но делови од нивната содржина ќе бидат недостапни за јавноста.'''
 Други администратори на {{SITENAME}} сѐ уште ќе имаат пристап до скриената содржина и ќе можат да ја вратат преку истиот посредник, освен ако не се поставени дополнителни ограничувања.",
 'revdelete-confirm' => 'Потврдете дека сакате да го направите ова, дека ги сфаќате последиците, и дека тоа го правите во согласност со [[{{MediaWiki:Policy-url}}|правилата]].',
-'revdelete-suppress-text' => "Ограничувањето '''се користи''' само во следниве случаи:
+'revdelete-suppress-text' => "Притајувањето се користи '''само''' во следниве случаи:
+* Потенцијално клеветнички информации
 * Несоодветни лични информации
-*: ''домашни адреси и телефонски броеви, матични броеви, и.т.н.''",
+*: ''домашни адреси и телефонски броеви, матични броеви и тн.''",
 'revdelete-legend' => 'Постави ограничувања за видливост',
-'revdelete-hide-text' => 'СкÑ\80иÑ\98 Ð³Ð¾ Ñ\82екÑ\81Ñ\82от на ревизијата',
+'revdelete-hide-text' => 'ТекÑ\81т на ревизијата',
 'revdelete-hide-image' => 'Скриј содржина на податотека',
 'revdelete-hide-name' => 'Скриј го дејството и неговата одредница',
-'revdelete-hide-comment' => 'СкÑ\80иÑ\98 Ð³Ð¾ Ð¾Ð¿Ð¸Ñ\81оÑ\82 на уредувањето',
-'revdelete-hide-user' => 'СкÑ\80иÑ\98 ÐºÐ¾Ñ\80иÑ\81ниÑ\87ко Ð¸Ð¼Ðµ/IP-адÑ\80еÑ\81а Ð½Ð° Ð°Ð²Ñ\82оÑ\80от',
+'revdelete-hide-comment' => 'Ð\9eпиÑ\81 на уредувањето',
+'revdelete-hide-user' => 'Ð\9aоÑ\80иÑ\81ниÑ\87ко Ð¸Ð¼Ðµ/IP-адÑ\80еÑ\81а Ð½Ð° Ñ\83Ñ\80едникот',
 'revdelete-hide-restricted' => 'Постави ограничувања и за администратори на ист начин како и за останатите',
 'revdelete-radio-same' => '(не менувај)',
-'revdelete-radio-set' => 'Ð\94а',
-'revdelete-radio-unset' => 'Ð\9dе',
+'revdelete-radio-set' => 'СкÑ\80иена',
+'revdelete-radio-unset' => 'Ð\92идлива',
 'revdelete-suppress' => 'Притајувај податоци и од администраторите',
 'revdelete-unsuppress' => 'Отстрани ограничувања на обновени ревизии',
 'revdelete-log' => 'Причина:',
@@ -1503,8 +1505,7 @@ $1",
 'preferences' => 'Нагодувања',
 'mypreferences' => 'нагодувања',
 'prefs-edits' => 'Број на уредувања:',
-'prefsnologin' => 'Не сте најавени',
-'prefsnologintext' => 'Мора да бидете <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} најавени]</span> за да ги менувате вашите кориснички нагодувања.',
+'prefsnologintext2' => 'Треба да сте $1 за да можете да ги поставувате корисничките нагодувања.',
 'changepassword' => 'Смени лозинка',
 'prefs-skin' => 'Руво',
 'skin-preview' => 'Преглед',
@@ -1805,6 +1806,9 @@ $1",
 'recentchanges-label-minor' => 'Ова е ситна промена',
 'recentchanges-label-bot' => 'Ова уредување е направено од бот',
 'recentchanges-label-unpatrolled' => 'Ова уредување сè уште не е испатролирано',
+'recentchanges-label-plusminus' => 'Промена на големината на страницата во бајти',
+'recentchanges-legend-newpage' => '(погл. и [[Special:NewPages|списокот на нови страници]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Подолу {{PLURAL:$1|е прикажана '''1''' промена|се прикажани последните '''$1''' промени}} {{PLURAL:$2|за денес|во последниве '''$2''' дена}}, заклучно со $5, $4.",
 'rcnotefrom' => 'Подолу се промените од <b>$2</b> (се прикажуваат до <b>$1</b>).',
 'rclistfrom' => 'Прикажи нови промени почнувајќи од $1',
@@ -2549,7 +2553,7 @@ $NEWPAGE
 е-пошта: $PAGEEDITOR_EMAIL
 вики: $PAGEEDITOR_WIKI
 
\9fовеÑ\9cе Ð½ÐµÐ¼Ð° Ð´Ð° Ð´Ð¾Ð±Ð¸Ð²Ð°Ñ\82е Ð¸Ð·Ð²ÐµÑ\81Ñ\82Ñ\83ваÑ\9aа Ð²Ð¾ Ñ\81лÑ\83Ñ\87аÑ\98 Ð½Ð° Ð´Ñ\80Ñ\83ги Ð¿Ð¾Ð½Ð°Ñ\82амоÑ\88ни Ð¿Ñ\80омени, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ð½Ðµ Ñ\98а Ð¿Ð¾Ñ\81еÑ\82иÑ\82е Ð¾Ð²Ð°Ð° Ñ\81Ñ\82Ñ\80аниÑ\86а.
\9fовеÑ\9cе Ð½ÐµÐ¼Ð° Ð´Ð° Ð´Ð¾Ð±Ð¸Ð²Ð°Ñ\82е Ð¸Ð·Ð²ÐµÑ\81Ñ\82Ñ\83ваÑ\9aа Ð²Ð¾ Ñ\81лÑ\83Ñ\87аÑ\98 Ð½Ð° Ð´Ñ\80Ñ\83ги Ð¿Ð¾Ð½Ð°Ñ\82амоÑ\88ни Ð°ÐºÑ\82ивноÑ\81Ñ\82и, Ð¾Ñ\81вен Ð°ÐºÐ¾ Ð½Ðµ Ñ\98а Ð¿Ð¾Ñ\81еÑ\82иÑ\82е Ð¾Ð²Ð°Ð° Ñ\81Ñ\82Ñ\80аниÑ\86а Ð´Ð¾Ð´ÐµÐºÐ° Ñ\81Ñ\82е Ð½Ð°Ñ\98авени.
 Можете и да ги поништите ознаките за известување за сите набљудувани страници на вашиот список на набљудувања.
 
 Известителниот систем на {{SITENAME}}
@@ -3081,7 +3085,7 @@ $1',
 'allmessagesdefault' => 'Текст по основно',
 'allmessagescurrent' => 'Сегашен текст',
 'allmessagestext' => 'Ова е список на системските пораки расположиви за именскиот простор „МедијаВики“.
-Одете на [//www.mediawiki.org/wiki/Localisation Локализација на МедијаВики] и [//translatewiki.net translatewiki.net] ако сакате да придонесете кон општата локализација на МедијаВики.',
+Одете на [https://www.mediawiki.org/wiki/Localisation Локализација на МедијаВики] и [//translatewiki.net translatewiki.net] ако сакате да придонесете кон општата локализација на МедијаВики.',
 'allmessagesnotsupportedDB' => "Оваа страница не може да се користи бидејќи '''\$wgUseDatabaseMessages''' е исклучено.",
 'allmessages-filter-legend' => 'Филтер',
 'allmessages-filter' => 'Филтрирај по состојба на прилагодувањето:',
@@ -3246,7 +3250,7 @@ $2',
 'tooltip-undo' => '„Откажи“ го поништува ова уредување и ве носи на уредувањето во режим на преглед. Дава можност за наведување на причина во описот.',
 'tooltip-preferences-save' => 'Зачувај',
 'tooltip-summary' => 'Внесете краток опис',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Тука поставениот CSS ќе се применува врз сите рува */',
@@ -3296,6 +3300,8 @@ $2',
 'spam_reverting' => 'Враќам на последната верзија што не содржи врска до $1',
 'spam_blanking' => 'Сите ревизии содржеа врски до $1. Чистам',
 'spam_deleting' => 'Сите ревизии содржеа врски до $1. Бришам',
+'simpleantispam-label' => "Проверка против спам.
+'''НЕ''' пополнувајте го ова!",
 
 # Info page
 'pageinfo-title' => 'Информации за „$1“',
@@ -3309,6 +3315,7 @@ $2',
 'pageinfo-length' => 'Должина на страницата (во бајти)',
 'pageinfo-article-id' => 'Назнака на страницата',
 'pageinfo-language' => 'Јазик на содржината на страницата',
+'pageinfo-content-model' => 'Модел на содржината на страницата',
 'pageinfo-robot-policy' => 'Индексирање со роботи',
 'pageinfo-robot-index' => 'Дозволено',
 'pageinfo-robot-noindex' => 'Недозволено',
@@ -3397,7 +3404,7 @@ $1',
 'svg-long-desc' => 'SVG податотека, номинално $1 × $2 пиксели, големина: $3',
 'svg-long-desc-animated' => 'Анимирана SVG-податотека, номинално: $1 × $2 пиксели, големина: $3',
 'svg-long-error' => 'Неважечка SVG-податотека: $1',
-'show-big-image' => 'Ð\92иÑ\81Ñ\82инÑ\81ка Ð³Ð¾Ð»ÐµÐ¼Ð¸Ð½а',
+'show-big-image' => 'Ð\98звоÑ\80на Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82ека',
 'show-big-image-preview' => 'Големина на овој преглед: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Друга резолуција|Други резолуции}}: $1.',
 'show-big-image-size' => '$1 × $2 пиксели',
@@ -3929,7 +3936,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => 'Уреди ја податотеката со надворешен програм',
-'edit-externally-help' => '(Видете [//www.mediawiki.org/wiki/Manual:External_editors повеќе напатствија] за нагодувањето).',
+'edit-externally-help' => '(Видете [https://www.mediawiki.org/wiki/Manual:External_editors повеќе напатствија] за нагодувањето).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'сите',
@@ -4035,6 +4042,7 @@ $5
 
 # Separators for various lists, etc.
 'percent' => '$1&#160;%',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '&larr; претходна страница',
@@ -4205,7 +4213,7 @@ $5
 'version-version' => '(Верзија $1)',
 'version-svn-revision' => '(рев. $2)',
 'version-license' => 'Лиценца',
-'version-poweredby-credits' => "Ова вики работи на '''[//www.mediawiki.org/ МедијаВики]''', авторски права © 2001-$1 $2.",
+'version-poweredby-credits' => "Ова вики работи на '''[https://www.mediawiki.org/ МедијаВики]''', авторски права © 2001-$1 $2.",
 'version-poweredby-others' => 'други',
 'version-poweredby-translators' => 'преведувачи на translatewiki.net',
 'version-credits-summary' => 'Би сакале да им се заблагодариме на следниве лица за нивните придонеси кон [[Special:Version|МедијаВики]].',
@@ -4226,7 +4234,7 @@ $5
 # Special:Redirect
 'redirect' => 'Пренасочување по податотека, корисник или назнака на ревизија',
 'redirect-legend' => 'Пренасочување кон податотека или страница',
-'redirect-summary' => 'Оваа специјална страница пренасочува кон податотека (се задава името), страница (се задава назнаката на ревизијата) или корисничка странца (се задава бројчената назнака на корисникот).',
+'redirect-summary' => 'Оваа специјална страница пренасочува кон податотека (се задава името), страница (се задава назнаката на ревизијата) или корисничка странца (се задава бројчената назнака на корисникот). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Оди',
 'redirect-lookup' => 'Пребарај:',
 'redirect-value' => 'Вредност:',
@@ -4248,10 +4256,9 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Специјални страници',
-'specialpages-note' => '----
-* Нормални специјални страници.
-* <span class="mw-specialpagerestricted">Ограничени специјални страници.</span>
-* <span class="mw-specialpagecached">Кеширани специјални страници (може да се застарени).</span>',
+'specialpages-note-top' => 'Легенда',
+'specialpages-note' => '* Нормални специјални страници.
+* <span class="mw-specialpagerestricted">Ограничени специјални страници.</span>',
 'specialpages-group-maintenance' => 'Извештаи за одржување',
 'specialpages-group-other' => 'Други специјални страници',
 'specialpages-group-login' => 'Најава / регистрација',
@@ -4463,4 +4470,21 @@ $5
 'limitreport-expansiondepth' => 'Најголема длабочина на проширувањето',
 'limitreport-expensivefunctioncount' => 'Бр. на сложени парсерски функции',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Прошири шаблони',
+'expand_templates_intro' => 'Оваа специјална страница зема еден текст и рекурзивно ги проширува сите шаблони во него.
+Исто така проширува и парсерски функции како
+<code><nowiki>{{</nowiki>#language:…}}</code> и променливи како
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Всушност, го проширува сето она што стои во двојни аглести загради.',
+'expand_templates_title' => 'Наслов на контекстот, за {{FULLPAGENAME}} и тн.:',
+'expand_templates_input' => 'Влезен текст:',
+'expand_templates_output' => 'Извод',
+'expand_templates_xml_output' => 'XML излез',
+'expand_templates_ok' => 'ОК',
+'expand_templates_remove_comments' => 'Отстрани коментари',
+'expand_templates_remove_nowiki' => 'Притаи <nowiki> ознаки во резултатот',
+'expand_templates_generate_xml' => 'Прикажи XML дрво на парсирање',
+'expand_templates_preview' => 'Преглед',
+
 );
index d7f57b1..d44532c 100644 (file)
@@ -8,6 +8,7 @@
  * @file
  *
  * @author Abhishek Jacob
+ * @author Akhilan
  * @author Anoopan
  * @author Chrisportelli
  * @author Deepugn
@@ -85,12 +86,12 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'സജീവ_ഉപയോക്താക്കൾ' ),
        'Allmessages'               => array( 'സർവ്വസന്ദേശങ്ങൾ' ),
+       'AllMyUploads'              => array( 'എന്റെയെല്ലാഅപ്‌ലോഡുകളും', 'എന്റെയെല്ലാപ്രമാണങ്ങളും' ),
        'Allpages'                  => array( 'എല്ലാതാളുകളും' ),
        'Ancientpages'              => array( 'പുരാതന_താളുകൾ' ),
        'Badtitle'                  => array( 'മോശംതലക്കെട്ട്' ),
        'Blankpage'                 => array( 'ശൂന്യതാൾ' ),
        'Block'                     => array( 'തടയുക', 'ഐ.പി.തടയുക', 'ഉപയോക്തൃതടയൽ' ),
-       'Blockme'                   => array( 'എന്നെതടയുക' ),
        'Booksources'               => array( 'പുസ്തകസ്രോതസ്സുകൾ' ),
        'BrokenRedirects'           => array( 'പൊട്ടിയതിരിച്ചുവിടലുകൾ' ),
        'Categories'                => array( 'വർഗ്ഗങ്ങൾ' ),
@@ -102,10 +103,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'അംഗത്വമെടുക്കൽ' ),
        'Deadendpages'              => array( 'അന്ത്യസ്ഥാനത്തുള്ള_താളുകൾ' ),
        'DeletedContributions'      => array( 'മായ്ച്ച_സേവനങ്ങൾ' ),
-       'Disambiguations'           => array( 'വിവക്ഷിതങ്ങൾ' ),
        'DoubleRedirects'           => array( 'ഇരട്ടത്തിരിച്ചുവിടലുകൾ' ),
        'EditWatchlist'             => array( 'ശ്രദ്ധിക്കുന്നവയുടെപട്ടികതിരുത്തുക' ),
        'Emailuser'                 => array( 'ഉപയോക്തൃഇമെയിൽ' ),
+       'ExpandTemplates'           => array( 'ഫലകങ്ങൾ_വികസിപ്പിക്കുക' ),
        'Export'                    => array( 'കയറ്റുമതി' ),
        'Fewestrevisions'           => array( 'കുറഞ്ഞ_പുനരവലോകനങ്ങൾ' ),
        'FileDuplicateSearch'       => array( 'പ്രമാണത്തിന്റെ_അപരനുള്ള_തിരച്ചിൽ' ),
@@ -150,9 +151,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'സംരക്ഷിത_താളുകൾ' ),
        'Protectedtitles'           => array( 'സംരക്ഷിത_ശീർഷകങ്ങൾ' ),
        'Randompage'                => array( 'ക്രമരഹിതം', 'ക്രമരഹിതതാൾ' ),
+       'RandomInCategory'          => array( 'വർഗ്ഗത്തിൽനിന്ന്ക്രമരഹിതം' ),
        'Randomredirect'            => array( 'ക്രമരഹിതതിരിച്ചുവിടലുകൾ' ),
        'Recentchanges'             => array( 'സമീപകാലമാറ്റങ്ങൾ' ),
        'Recentchangeslinked'       => array( 'ബന്ധപ്പെട്ട_മാറ്റങ്ങൾ' ),
+       'Redirect'                  => array( 'തിരിച്ചുവിടൽ' ),
+       'ResetTokens'               => array( 'ചീട്ട്പുനഃസജ്ജീകരിക്കുക' ),
        'Revisiondelete'            => array( 'നാൾപ്പതിപ്പ്_മായ്ക്കൽ' ),
        'Search'                    => array( 'അന്വേഷണം' ),
        'Shortpages'                => array( 'ചെറിയ_താളുകൾ' ),
@@ -234,6 +238,8 @@ $magicWords = array(
        'fullpagenamee'             => array( '1', 'താളിന്റെമുഴുവൻപേര്സമഗ്രം', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', 'അനുബന്ധതാളിന്റെപേര്‌', 'SUBPAGENAME' ),
        'subpagenamee'              => array( '1', 'അനുബന്ധതാളിന്റെപേര്സമഗ്രം', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'മൂലതാളിന്റെപേര്', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'മൂലതാളിന്റെപേര്‌സമഗ്രം', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'അടിസ്ഥാനതാളിന്റെപേര്‌', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'അടിസ്ഥാനതാളിന്റെപേര്‌സമഗ്രം', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'സംവാദതാളിന്റെപേര്‌', 'TALKPAGENAME' ),
@@ -253,6 +259,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'നടുവിൽ', 'നടുക്ക്‌', 'center', 'centre' ),
        'img_framed'                => array( '1', 'ചട്ടം', 'ചട്ടത്തിൽ', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'ചട്ടരഹിതം', 'frameless' ),
+       'img_lang'                  => array( '1', 'ഭാഷ=$1', 'lang=$1' ),
        'img_page'                  => array( '1', 'താൾ=$1', 'താൾ_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'നേരേകുത്തനെ', 'നേരേകുത്തനെ=$1', 'നേരേകുത്തനെ_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'അതിർവര', 'border' ),
@@ -267,8 +274,10 @@ $magicWords = array(
        'img_link'                  => array( '1', 'കണ്ണി=$1', 'link=$1' ),
        'img_alt'                   => array( '1', 'പകരം=$1', 'alt=$1' ),
        'img_class'                 => array( '1', 'ശ്രേണി=$1', 'class=$1' ),
+       'int'                       => array( '0', 'സമ്പർക്കം:', 'INT:' ),
        'sitename'                  => array( '1', 'സൈറ്റിന്റെപേര്', 'SITENAME' ),
        'ns'                        => array( '0', 'നാമേ:', 'NS:' ),
+       'nse'                       => array( '0', 'നാമേസ:', 'NSE:' ),
        'localurl'                  => array( '0', 'ലോക്കൽയുആർഎൽ:', 'LOCALURL:' ),
        'localurle'                 => array( '0', 'ലോക്കൽയുആർഎൽഇ:', 'LOCALURLE:' ),
        'articlepath'               => array( '0', 'ലേഖനപഥം', 'ARTICLEPATH' ),
@@ -295,12 +304,16 @@ $magicWords = array(
        'revisionuser'              => array( '1', 'അവസാനംതിരുത്തിയയാൾ', 'REVISIONUSER' ),
        'plural'                    => array( '0', 'ബഹുവചനം:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'പൂർണ്ണവിലാസം:', 'FULLURL:' ),
+       'fullurle'                  => array( '0', 'പൂർണ്ണവിലാസംസമഗ്രം:', 'FULLURLE:' ),
+       'canonicalurl'              => array( '0', 'കാനോനിക്കൽവിലാസം:', 'CANONICALURL:' ),
+       'canonicalurle'             => array( '0', 'കാനോനിക്കൽവിലാസംസമഗ്രം:', 'CANONICALURLE:' ),
        'raw'                       => array( '0', 'അസംസ്കൃതം:', 'RAW:' ),
        'displaytitle'              => array( '1', 'ശീർഷകംപ്രദർശിപ്പിക്കുക', 'തലക്കെട്ട്പ്രദർശിപ്പിക്കുക', 'DISPLAYTITLE' ),
        'rawsuffix'                 => array( '1', 'വ', 'R' ),
        'newsectionlink'            => array( '1', '__പുതിയവിഭാഗംകണ്ണി__', '__പുതിയഖണ്ഡിക്കണ്ണി__', '__NEWSECTIONLINK__' ),
        'nonewsectionlink'          => array( '1', '__പുതിയവിഭാഗംകണ്ണിവേണ്ട__', '__പുതിയഖണ്ഡിക്കണ്ണിവേണ്ട__', '__NONEWSECTIONLINK__' ),
        'currentversion'            => array( '1', 'ഈപതിപ്പ്', 'CURRENTVERSION' ),
+       'urlencode'                 => array( '0', 'വിലാസഗൂഢീകരണം:', 'URLENCODE:' ),
        'currenttimestamp'          => array( '1', 'സമയമുദ്ര', 'CURRENTTIMESTAMP' ),
        'localtimestamp'            => array( '1', 'പ്രാദേശികസമയമുദ്ര', 'LOCALTIMESTAMP' ),
        'directionmark'             => array( '1', 'ദിശാസൂചിക', 'DIRECTIONMARK', 'DIRMARK' ),
@@ -558,7 +571,7 @@ $messages = array(
 'articlepage' => 'ലേഖനം കാണുക',
 'talk' => 'സംവാദം',
 'views' => 'ദർശനീയത',
-'toolbox' => 'പണിസà´\9eàµ\8dà´\9aà´¿',
+'toolbox' => 'à´\89à´ªà´\95à´°à´£à´\99àµ\8dà´\99ൾ',
 'userpage' => 'ഉപയോക്താവിന്റെ താൾ കാണുക',
 'projectpage' => 'പദ്ധതി താൾ കാണുക',
 'imagepage' => 'പ്രമാണ താൾ കാണുക',
@@ -614,12 +627,10 @@ $1',
 'ok' => 'ശരി',
 'retrievedfrom' => '"$1" എന്ന താളിൽനിന്നു ശേഖരിച്ചത്',
 'youhavenewmessages' => 'താങ്കൾക്ക് $1 ഉണ്ട് ($2).',
-'newmessageslink' => 'പുതിയ സന്ദേശങ്ങൾ',
-'newmessagesdifflink' => 'അവസാന മാറ്റം',
 'youhavenewmessagesfromusers' => 'താങ്കൾക്ക് {{PLURAL:$3|ഒരു ഉപയോക്താവ്|$3 ഉപയോക്താക്കൾ}} $1 ചേർത്തിട്ടുണ്ട് ($2).',
 'youhavenewmessagesmanyusers' => 'താങ്കൾക്ക് പലർ $1 ചേർത്തിട്ടുണ്ട് ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|à´ªàµ\81തിയ à´¸à´¨àµ\8dà´¦àµ\87à´¶à´\82|പുതിയ സന്ദേശങ്ങൾ}}',
-'newmessagesdifflinkplural' => 'അവസാന {{PLURAL:$1|മാറ്റം|മാറ്റങ്ങൾ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|à´ªàµ\81തിയ à´\92à´°àµ\81 à´¸à´¨àµ\8dà´¦àµ\87à´¶à´\82|999=പുതിയ സന്ദേശങ്ങൾ}}',
+'newmessagesdifflinkplural' => 'അവസാന {{PLURAL:$1|മാറ്റം|999=മാറ്റങ്ങൾ}}',
 'youhavenewmessagesmulti' => 'താങ്കൾക്ക് $1 താളിൽ പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്',
 'editsection' => 'തിരുത്തുക',
 'editold' => 'തിരുത്തുക',
@@ -749,7 +760,8 @@ $2',
 'invalidtitle-knownnamespace' => 'നാമമേഖല "$2", എഴുത്ത് "$3" എന്നിവ ഉപയോഗിച്ചുള്ള അസാധുവായ തലക്കെട്ട്',
 'invalidtitle-unknownnamespace' => 'അപരിചിതമായ നാമമേഖലാ സംഖ്യ $1, എഴുത്ത് "$2" എന്നിവ ഉപയോഗിച്ചുള്ള അസാധുവായ തലക്കെട്ട്',
 'exception-nologin' => 'ലോഗിൻ ചെയ്തിട്ടില്ല',
-'exception-nologin-text' => 'ഈ വിക്കിയിൽ ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ലഭ്യമാകാൻ താങ്കൾ ലോഗിൻ ചെയ്തിരിക്കേണ്ടതാണ്.',
+'exception-nologin-text' => 'ഈ വിക്കിയിൽ ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ലഭ്യമാകാൻ ദയവായി [[Special:Userlogin|പ്രവേശിക്കുക]].',
+'exception-nologin-text-manual' => 'ഈ താൾ അല്ലെങ്കിൽ പ്രവൃത്തി ഉപയോഗിക്കാൻ ദയവായി $1.',
 
 # Virus scanner
 'virus-badscanner' => "തെറ്റായ ക്രമീകരണങ്ങൾ: അപരിചിതമായ വൈറസ് തിരച്ചിൽ ഉപാധി :  ''$1''",
@@ -759,7 +771,7 @@ $2',
 # Login and logout pages
 'logouttext' => "'''താങ്കൾ ഇപ്പോൾ {{SITENAME}} സംരംഭത്തിൽനിന്നും ലോഗൗട്ട് ചെയ്തിരിക്കുന്നു'''
 
-താà´\99àµ\8dà´\95ൾ à´µàµ\86à´¬àµ\8d à´¬àµ\8dà´°àµ\8cസറിന്റെ ക്യാഷെ ശൂന്യമാക്കിയിട്ടില്ലെങ്കിൽ ചില താളുകളിൽ താങ്കൾ ലോഗിൻ ചെയ്തിരിക്കുന്നതായി കാണിക്കാൻ സാധ്യതയുണ്ട്.",
+താà´\99àµ\8dà´\95ൾ à´µàµ\86à´¬àµ\8d à´¬àµ\8dà´°àµ\97സറിന്റെ ക്യാഷെ ശൂന്യമാക്കിയിട്ടില്ലെങ്കിൽ ചില താളുകളിൽ താങ്കൾ ലോഗിൻ ചെയ്തിരിക്കുന്നതായി കാണിക്കാൻ സാധ്യതയുണ്ട്.",
 'welcomeuser' => 'സ്വാഗതം, $1!',
 'welcomecreation-msg' => 'താങ്കളുടെ അംഗത്വം സൃഷ്ടിക്കപ്പെട്ടിരിക്കുന്നു.
 താങ്കളുടെ [[Special:Preferences|{{SITENAME}} ക്രമീകരണങ്ങളിൽ]] മാറ്റം വരുത്താൻ മറക്കരുത്.',
@@ -796,7 +808,7 @@ $2',
 'gotaccount' => "താങ്കൾക്ക് അംഗത്വമുണ്ടോ? '''$1'''.",
 'gotaccountlink' => 'പ്രവേശിക്കുക',
 'userlogin-resetlink' => 'താങ്കളുടെ ലോഗിൻ വിവരങ്ങൾ മറന്നു പോയോ?',
-'userlogin-resetpassword-link' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 à´°à´¹à´¸àµ\8dയവാà´\95àµ\8dà´\95àµ\8d à´ªàµ\81à´¨à´\83à´¸à´\9càµ\8dà´\9càµ\80à´\95à´°à´¿à´\95àµ\8dà´\95àµ\81à´\95',
+'userlogin-resetpassword-link' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 à´°à´¹à´¸àµ\8dയവാà´\95àµ\8dà´\95àµ\8d à´®à´±à´¨àµ\8dà´¨àµ\8b?',
 'helplogin-url' => 'Help:പ്രവേശനം',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|പ്രവേശന സഹായം]]',
 'userlogin-loggedin' => 'താങ്കൾ ഇപ്പോൾ തന്നെ {{GENDER:$1|$1}} ആയി പ്രവേശിച്ചിരിക്കുന്നു.
@@ -855,13 +867,13 @@ $2',
 'noemailcreate' => 'താങ്കൾ സാധുവായ ഇമെയിൽ വിലാസം നൽകേണ്ടതാണ്',
 'passwordsent' => '‘$1” എന്ന അംഗത്വത്തിനായി രജിസ്റ്റർ ചെയ്യപ്പെട്ടിട്ടുള്ള ഇമെയിൽ വിലാസത്തിലേക്ക് ഒരു പുതിയ രഹസ്യവാക്ക് അയച്ചിട്ടുണ്ട്. അത് ലഭിച്ചശേഷം ദയവായി ലോഗിൻ ചെയ്യുക.',
 'blocked-mailpassword' => 'താങ്കളുടെ ഐ.പി. വിലാസത്തെ ഈ വിക്കി തിരുത്തുന്നതിൽ നിന്നു തടഞ്ഞിട്ടുള്ളതാണ്‌. അതിനാൽ രഹസ്യവാക്ക് വീണ്ടെടുക്കുവാനുള്ള സജ്ജീകരണം ഉപയോഗിക്കുന്നതിനു താങ്കൾക്ക് അവകാശമില്ല.',
-'eauthentsent' => 'താà´\99àµ\8dà´\95ൾ à´µà´¿à´\95àµ\8dà´\95ിയിൽ à´\95àµ\8dà´°à´®àµ\80à´\95à´°à´¿à´\9aàµ\8dà´\9aà´¿à´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´¤àµ\8dതിലàµ\87à´\95àµ\8dà´\95àµ\8d à´¸àµ\8dഥിരàµ\80à´\95രണതàµ\8dതിനായി à´\92à´°àµ\81 à´®àµ\86യിൽ à´\85à´¯à´\9aàµ\8dà´\9aà´¿à´\9fàµ\8dà´\9fàµ\81à´£àµ\8dà´\9fàµ\8d. à´\87വിà´\9fàµ\86 à´¨à´¿à´¨àµ\8dà´¨àµ\8d à´\86 à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´¤àµ\8dതിലàµ\87à´\95àµ\8dà´\95àµ\8d à´®à´±àµ\8dà´±àµ\8aà´°àµ\81 à´®àµ\86യിൽ à´\95àµ\82à´\9fà´¿ à´\85à´¯à´\95àµ\8dà´\95àµ\81à´¨àµ\8dനതിനàµ\81 à´®àµ\81ൻപായി, à´\85à´\82à´\97à´¤àµ\8dà´µà´\82 à´¤à´¾à´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\87à´¤àµ\81 à´¤à´¨àµ\8dà´¨àµ\86 à´\8eà´¨àµ\8dà´¨àµ\81 à´\89റപàµ\8dà´ªàµ\81 à´µà´°àµ\81à´¤àµ\8dà´¤àµ\81à´¨àµ\8dനതിനായി, à´\87à´ªàµ\8dà´ªàµ\8bൾ à´\85à´¯à´\9aàµ\8dà´\9aà´¿à´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ മെയിലിലെ നിർദ്ദേശങ്ങൾ താങ്കൾ പാലിക്കേണ്ടതാണ്.',
+'eauthentsent' => 'താà´\99àµ\8dà´\95ൾ à´¨àµ½à´\95ിയിà´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´¤àµ\8dതിലàµ\87à´\95àµ\8dà´\95àµ\8d à´¸àµ\8dഥിരàµ\80à´\95രണതàµ\8dതിനായി à´\92à´°àµ\81 à´\87à´®àµ\86യിൽ à´\85à´¯à´\9aàµ\8dà´\9aà´¿à´\9fàµ\8dà´\9fàµ\81à´£àµ\8dà´\9fàµ\8d. à´\86 à´µà´¿à´²à´¾à´¸à´¤àµ\8dതിലàµ\87à´\95àµ\8dà´\95àµ\8d à´®à´±àµ\8dà´±àµ\8aà´°àµ\81 à´\87à´®àµ\86യിൽ à´\85à´¯à´\95àµ\8dà´\95àµ\81à´¨àµ\8dനതിനàµ\81 à´®àµ\81ൻപായി, à´\85à´\82à´\97à´¤àµ\8dà´µà´\82 à´¤à´¾à´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\87à´¤àµ\81 à´¤à´¨àµ\8dà´¨àµ\86 à´\8eà´¨àµ\8dà´¨àµ\81 à´\89റപàµ\8dà´ªàµ\81 à´µà´°àµ\81à´¤àµ\8dà´¤àµ\81à´¨àµ\8dനതിനàµ\8d, à´\87à´ªàµ\8dà´ªàµ\8bൾ à´\85à´¯à´\9aàµ\8dà´\9aà´¿à´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ à´\87മെയിലിലെ നിർദ്ദേശങ്ങൾ താങ്കൾ പാലിക്കേണ്ടതാണ്.',
 'throttled-mailpassword' => 'കഴിഞ്ഞ {{PLURAL:$1|മണിക്കൂറിനുള്ളിൽ |$1 മണിക്കൂറുകൾക്കുള്ളിൽ}} രഹസ്യവാക്ക് പുനർസജ്ജീകരിക്കാനുള്ള ഒരു ഇമെയിൽ അയച്ചിട്ടുണ്ട്. ദുരുപയോഗം ഒഴിവാക്കാൻ {{PLURAL:$1|ഒരു മണിക്കൂറിനുള്ളിൽ |$1 മണിക്കൂറുകൾക്കുള്ളിൽ}} രഹസ്യവാക്ക് പുനർസജ്ജീകരിക്കാനുള്ള ഒരു ഇമെയിൽ മാത്രമേ അയയ്ക്കുകയുള്ളു.',
 'mailerror' => 'മെയിൽ അയയ്ക്കുന്നതിൽ പിഴവ്: $1',
 'acct_creation_throttle_hit' => 'കഴിഞ്ഞ ഒരു ദിവസത്തിനുള്ളിൽ താങ്കളുടെ ഐ.പി. വിലാസത്തിൽ നിന്നുമുള്ള സന്ദർശകർ {{PLURAL:$1|1 അംഗത്വം|$1 അംഗത്വങ്ങൾ}} എടുത്തിട്ടുണ്ട്, പ്രസ്താവിത സമയത്തിനുള്ളിൽ എടുക്കാവുന്ന ഏറ്റവും കൂടിയ പരിധിയാണിത്.
 അതിന്റെ ഫലമായി, ഈ ഐ.പി.യിൽ നിന്നുള്ള സന്ദർശകർക്ക് ഇപ്പോൾ കൂടുതൽ അംഗത്വമെടുക്കാൻ കഴിയുന്നതല്ല.',
-'emailauthenticated' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´\82 $2, $3-à´¨àµ\8d à´¸à´¾à´§àµ\81à´¤ à´¤àµ\86ളിയിച്ചതാണ്.',
-'emailnotauthenticated' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´¤àµ\8dതിനàµ\8dà´±àµ\86 à´¸à´¾à´§àµ\81à´¤ à´\87à´¤àµ\81വരàµ\86 à´¸àµ\8dഥിരàµ\80à´\95à´°à´¿à´\95àµ\8dà´\95à´ªàµ\8dà´ªàµ\86à´\9fàµ\8dà´\9fà´¿à´\9fàµ\8dà´\9fà´¿à´²àµ\8dà´². à´¸à´¾à´§àµ\81à´¤ à´¤àµ\86ളിയിà´\95àµ\8dà´\95àµ\81à´¨àµ\8dനതàµ\81വരàµ\86 à´¤à´¾à´´àµ\86à´ªàµ\8dപറയàµ\81à´¨àµ\8dനവയàµ\8dà´\95àµ\8dà´\95àµ\8aà´¨àµ\8dà´¨àµ\81à´\82 à´¤à´¾à´\99àµ\8dà´\95ൾà´\95àµ\8dà´\95àµ\8d à´\87à´®àµ\86യിൽ à´\85à´¯à´\95àµ\8dà´\95àµ\81à´µാൻ സാദ്ധ്യമല്ല.',
+'emailauthenticated' => 'താà´\99àµ\8dà´\95ൾ à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´\82 $2, $3-à´¨àµ\8d à´¸àµ\8dഥിരàµ\80à´\95à´°ിച്ചതാണ്.',
+'emailnotauthenticated' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 à´\87à´®àµ\86യിൽ à´µà´¿à´²à´¾à´¸à´\82 à´\87à´¤àµ\81വരàµ\86 à´¸àµ\8dഥിരàµ\80à´\95à´°à´¿à´\95àµ\8dà´\95à´ªàµ\8dà´ªàµ\86à´\9fàµ\8dà´\9fà´¿à´\9fàµ\8dà´\9fà´¿à´²àµ\8dà´². à´¤à´¾à´´àµ\86à´ªàµ\8dപറയàµ\81à´¨àµ\8dനവയàµ\8dà´\95àµ\8dà´\95àµ\8d à´\87à´®àµ\86യിലàµ\81à´\95ൾ à´\85യയàµ\8dà´\95àµ\8dà´\95ാൻ സാദ്ധ്യമല്ല.',
 'noemailprefs' => 'ഈ ക്രമീകരണങ്ങൾ പ്രവർത്തിക്കുവാൻ സാധുവായ ഒരു ഇമെയിൽ വിലാസം ഉൾപ്പെടുത്തുക.',
 'emailconfirmlink' => 'താങ്കളുടെ ഇമെയിൽ വിലാസം സ്ഥിരീകരിക്കുക',
 'invalidemailaddress' => 'ഇമെയിൽ വിലാസം സാധുവായ രൂപത്തിൽ അല്ലാത്തതിനാൽ സ്വീകാര്യമല്ല.
@@ -1285,15 +1297,15 @@ $3 അതിനു കാണിച്ചിരിക്കുന്ന കാര
 * അനുയോജ്യമല്ലാത്ത വ്യക്തി വിവരങ്ങൾ
 *: ''വീട്ടുവിലാസങ്ങൾ, ടെലിഫോൺ നമ്പറുകൾ, സാമൂഹിക സുരക്ഷാ നമ്പരുകൾ, തുടങ്ങിയവ.''",
 'revdelete-legend' => 'നാൾപ്പതിപ്പിന്റെ ദർശനീയത സജ്ജീകരിക്കുക',
-'revdelete-hide-text' => 'മാറàµ\8dà´±à´\82 à´µà´¨àµ\8dà´¨ à´\8eà´´àµ\81à´¤àµ\8dà´¤àµ\8d à´®à´±à´¯àµ\8dà´\95àµ\8dà´\95àµ\81à´\95',
+'revdelete-hide-text' => 'നാൾപàµ\8dപതിപàµ\8dപിലàµ\86 à´\8eà´´àµ\81à´¤àµ\8dà´¤àµ\8d',
 'revdelete-hide-image' => 'പ്രമാണത്തിന്റെ ഉള്ളടക്കം മറയ്ക്കുക',
 'revdelete-hide-name' => 'പ്രവൃത്തിയും ലക്ഷ്യവും മറയ്ക്കുക',
-'revdelete-hide-comment' => 'തിരàµ\81à´¤àµ\8dതലിനàµ\8dà´±àµ\86 à´\85à´­à´¿à´ªàµ\8dരായà´\82 à´®à´±à´¯àµ\8dà´\95àµ\8dà´\95àµ\81à´\95',
-'revdelete-hide-user' => 'തിരുത്തുന്ന ആളുടെ ഉപയോക്തൃനാമം/ഐ.പി. വിലാസം മറയ്ക്കുക',
+'revdelete-hide-comment' => 'തിരàµ\81à´¤àµ\8dതലിനàµ\8dà´±àµ\86 à´\9aàµ\81à´°àµ\81à´\95àµ\8dà´\95à´\82',
+'revdelete-hide-user' => 'തിരുത്തുന്ന ആളുടെ ഉപയോക്തൃനാമം/ഐ.പി. വിലാസം',
 'revdelete-hide-restricted' => 'വിവരങ്ങളുടെ നിയന്ത്രണം മറ്റുള്ളവരെ പോലെ കാര്യനിർവാഹകർക്കും ബാധകമാക്കുക',
 'revdelete-radio-same' => '(മാറ്റം വരുത്തരുത്)',
-'revdelete-radio-set' => 'à´µàµ\87à´£à´\82',
-'revdelete-radio-unset' => 'à´µàµ\87à´£àµ\8dà´\9f',
+'revdelete-radio-set' => 'മറയàµ\8dà´\95àµ\8dà´\95à´ªàµ\8dà´ªàµ\86à´\9fàµ\8dà´\9fà´µ',
+'revdelete-radio-unset' => 'à´\95ാണാവàµ\81à´¨àµ\8dനവ',
 'revdelete-suppress' => 'സിസോപ്പുകളിൽ നിന്നും മറ്റുള്ളവരിൽ നിന്നും ഈ ഡാറ്റാ മറച്ചു വെക്കുക',
 'revdelete-unsuppress' => 'പുനഃസ്ഥാപിച്ച പതിപ്പുകളിലുള്ള നിയന്ത്രണങ്ങൾ ഒഴിവാക്കുക',
 'revdelete-log' => 'കാരണം:',
@@ -1447,8 +1459,7 @@ $1",
 'preferences' => 'ക്രമീകരണങ്ങൾ',
 'mypreferences' => 'ക്രമീകരണങ്ങൾ',
 'prefs-edits' => 'ആകെ തിരുത്തുകൾ:',
-'prefsnologin' => 'ലോഗിൻ ചെയ്തിട്ടില്ല',
-'prefsnologintext' => 'ഉപയോക്തൃക്രമീകരണങ്ങൾ മാറ്റാൻ താങ്കൾ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ലോഗിൻ]</span> ചെയ്തിരിക്കണം.',
+'prefsnologintext2' => 'താങ്കളുടെ ഉപയോക്തൃക്രമീകരണങ്ങൾ സജ്ജീകരിക്കാൻ ദയവായി $1.',
 'changepassword' => 'രഹസ്യവാക്ക് മാറ്റുക',
 'prefs-skin' => 'ദൃശ്യരൂപം',
 'skin-preview' => 'എങ്ങനെയുണ്ടെന്നു കാണുക',
@@ -1507,7 +1518,7 @@ $1",
 'timezoneregion-indian' => 'ഇന്ത്യൻ മഹാസമുദ്രം',
 'timezoneregion-pacific' => 'ശാന്തസമുദ്രം',
 'allowemail' => 'എനിക്ക് എഴുത്തയക്കാൻ മറ്റുള്ളവരെ അനുവദിക്കുക',
-'prefs-searchoptions' => 'തിരയàµ\81à´\95',
+'prefs-searchoptions' => 'തിരà´\9aàµ\8dà´\9aിൽ',
 'prefs-namespaces' => 'നാമമേഖലകൾ',
 'defaultns' => 'അല്ലെങ്കിൽ ഈ നാമമേഖലകളിൽ തിരയുക:',
 'default' => 'സ്വതേ',
@@ -1746,8 +1757,10 @@ $1",
 'recentchanges-feed-description' => 'ഈ ഫീഡ് ഉപയോഗിച്ച് വിക്കിയിലെ പുതിയ മാറ്റങ്ങൾ നിരീക്ഷിക്കുക.',
 'recentchanges-label-newpage' => 'ഒരു പുതിയ താൾ സൃഷ്ടിച്ചിരിക്കുന്നു',
 'recentchanges-label-minor' => 'ഇതൊരു ചെറിയ തിരുത്താണ്',
-'recentchanges-label-bot' => 'à´\87à´¤àµ\8aà´°àµ\81 à´¯à´¨àµ\8dà´¤àµ\8dà´°à´\82 à´¨à´\9fà´¤àµ\8dതിയ തിരുത്താണ്',
+'recentchanges-label-bot' => 'à´\87à´¤àµ\8d à´¯à´¨àµ\8dà´¤àµ\8dà´°à´\82 à´\9aàµ\86à´¯àµ\8dà´¤ തിരുത്താണ്',
 'recentchanges-label-unpatrolled' => 'ഇതുവരെ റോന്തു ചുറ്റപ്പെടാത്ത ഒരു തിരുത്താണിത്',
+'recentchanges-label-plusminus' => 'താളിന്റെ വലിപ്പം ഇത്രയും ബൈറ്റുകൾ മാറിയിരിക്കുന്നു',
+'recentchanges-legend-newpage' => '([[Special:NewPages|പുതിയ താളുകളുടെ പട്ടികയും]] കാണുക)',
 'rcnote' => "കഴിഞ്ഞ {{PLURAL:$2|ദിവസം|'''$2''' ദിവസങ്ങൾക്കുള്ളിൽ}} സംഭവിച്ച, {{PLURAL:$1|'''1''' തിരുത്തൽ|'''$1''' തിരുത്തലുകൾ}} താഴെക്കാണാം. ശേഖരിച്ച സമയം: $4, $5.",
 'rcnotefrom' => '<b>$2</b> മുതലുള്ള മാറ്റങ്ങൾ (<b>$1</b> എണ്ണം വരെ കാണാം).',
 'rclistfrom' => '$1 മുതലുള്ള മാറ്റങ്ങൾ പ്രദർശിപ്പിക്കുക',
@@ -2169,6 +2182,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization കാണുക.',
 
 'pageswithprop' => 'താളിന്റെ സവിശേഷതകളുള്ള താളുകൾ',
 'pageswithprop-legend' => 'ഒരു താൾ സവിശേഷതയുള്ള താളുകൾ',
+'pageswithprop-prop' => 'ഗുണം:',
 'pageswithprop-submit' => 'പോകൂ',
 
 'doubleredirects' => 'ഇരട്ട തിരിച്ചുവിടലുകൾ',
@@ -2466,8 +2480,9 @@ $NEWPAGE
 മെയിൽ: $PAGEEDITOR_EMAIL
 വിക്കി: $PAGEEDITOR_WIKI
 
-താങ്കൾ ഈ താൾ സന്ദർശിക്കുന്നില്ലങ്കിൽ മറ്റ് അറിയിപ്പുകൾ ഒന്നുമുണ്ടാകുന്നതല്ല. ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക സന്ദർശിച്ചും ഉൾപ്പെട്ട താളുകളിലെ അറിയിപ്പ് മുദ്രകൾ താങ്കൾക്ക് പുനഃക്രമീകരിക്കാവുന്നതാണ്‌.
-             താങ്കളുടെ {{SITENAME}} സുഹൃദ് അറിയിപ്പ് സജ്ജീകരണം
+താങ്കൾ ലോഗിൻ ചെയ്ത് ഈ താൾ സന്ദർശിക്കുന്നില്ലങ്കിൽ മറ്റ് അറിയിപ്പുകൾ ഒന്നുമുണ്ടാകുന്നതല്ല. ശ്രദ്ധിക്കുന്ന താളുകളുടെ പട്ടിക സന്ദർശിച്ചും ഉൾപ്പെട്ട താളുകളിലെ അറിയിപ്പ് മുദ്രകൾ താങ്കൾക്ക് പുനഃക്രമീകരിക്കാവുന്നതാണ്‌.
+
+താങ്കളുടെ {{SITENAME}} സുഹൃദ് അറിയിപ്പ് സജ്ജീകരണം
 
 --
 ഇമെയിൽ അറിയിപ്പ് സജ്ജീകരണങ്ങളിൽ മാറ്റംവരുത്താൻ, സന്ദർശിക്കുക
@@ -2981,7 +2996,7 @@ $1',
 'allmessagesdefault' => 'സ്വതേയുള്ള ഉള്ളടക്കം',
 'allmessagescurrent' => 'നിലവിലുള്ള ഉള്ളടക്കം',
 'allmessagestext' => 'ഇത് മീഡിയവിക്കി നാമമേഖലയിൽ ലഭ്യമായ വ്യവസ്ഥാസന്ദേശങ്ങളുടെ ഒരു പട്ടിക ആണ്‌.
-പ്രാമാണികമായ വിധത്തിൽ മീഡിയവിക്കിയുടെ പ്രാദേശീകരണം താങ്കൾ ഉദ്ദേശിക്കുന്നുവെങ്കിൽ ദയവായി [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net] എന്നീ താളുകൾ സന്ദർശിക്കുക.',
+പ്രാമാണികമായ വിധത്തിൽ മീഡിയവിക്കിയുടെ പ്രാദേശീകരണം താങ്കൾ ഉദ്ദേശിക്കുന്നുവെങ്കിൽ ദയവായി [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation], [//translatewiki.net translatewiki.net] എന്നീ താളുകൾ സന്ദർശിക്കുക.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' ബന്ധിച്ചിരിക്കുന്നതു കാരണം ഈ താൾ ഉപയോഗിക്കുവാൻ സാദ്ധ്യമല്ല.",
 'allmessages-filter-legend' => 'അരിപ്പ',
 'allmessages-filter' => 'പുനഃക്രമീകരിച്ച ക്രമത്തിൽ തിരഞ്ഞുവെയ്ക്കുക:',
@@ -3190,6 +3205,8 @@ $1',
 'spam_reverting' => '$1 എന്നതിലേയ്ക്കുള്ള കണ്ണികളില്ലാത്ത അവസാന നാൾപ്പതിപ്പിലേയ്ക്ക് മുൻപ്രാപനം ചെയ്യുന്നു',
 'spam_blanking' => '$1 എന്നതിലേയ്ക്ക് കണ്ണികളുള്ള എല്ലാ നാൾപ്പതിപ്പുകളും ശൂന്യമാക്കുന്നു',
 'spam_deleting' => '$1 എന്നതിലേയ്ക്ക് കണ്ണികളുള്ള എല്ലാ നാൾപ്പതിപ്പുകളും മായ്ക്കുന്നു',
+'simpleantispam-label' => "പാഴെഴുത്ത് വിരുദ്ധ പരിശോധന.
+ഇത് '''പൂരിപ്പിക്കരുത്'''!",
 
 # Info page
 'pageinfo-title' => '"$1" എന്ന താളിന്റെ വിവരങ്ങൾ',
@@ -3203,6 +3220,7 @@ $1',
 'pageinfo-length' => 'താളിന്റെ നീളം (ബൈറ്റിൽ)',
 'pageinfo-article-id' => 'താളിന്റെ ഐ.ഡി.',
 'pageinfo-language' => 'താളിന്റെ ഉള്ളടക്കത്തിന്റെ ഭാഷ',
+'pageinfo-content-model' => 'താളിന്റെ ഉള്ളടക്ക രീതി',
 'pageinfo-robot-policy' => 'റോബോട്ടുകളുടെ സൂചികാവത്കരണം',
 'pageinfo-robot-index' => 'അനുവദിച്ചിരിക്കുന്നു',
 'pageinfo-robot-noindex' => 'അനുവദിച്ചിട്ടില്ല',
@@ -3288,7 +3306,7 @@ $1',
 'svg-long-desc' => 'എസ്.വി.ജി. പ്രമാണം, നാമമാത്രമായ $1 × $2 പിക്സലുകൾ, പ്രമാണത്തിന്റെ വലിപ്പം: $3',
 'svg-long-desc-animated' => 'ചലിക്കുന്ന എസ്.വി.ജി. പ്രമാണം, നാമമാത്രമായ $1 × $2 പിക്സലുകൾ, പ്രമാണത്തിന്റെ വലിപ്പം: $3',
 'svg-long-error' => 'അസാധുവായ എസ്.വി.ജി. പ്രമാണം: $1',
-'show-big-image' => 'à´ªàµ\82ർണàµ\8dà´£ à´±àµ\86സലàµ\82ഷൻ',
+'show-big-image' => 'à´ªàµ\82ർണàµ\8dà´£ à´µà´²à´¿à´ªàµ\8dà´ªà´\82',
 'show-big-image-preview' => 'ഈ പ്രിവ്യൂവിന്റെ വലിപ്പം: $1.',
 'show-big-image-other' => 'കൂടുതൽ {{PLURAL:$2|റെസലൂഷൻ}}: $1.',
 'show-big-image-size' => '$1 × $2 പിക്സലുകൾ',
@@ -3752,7 +3770,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ഈ പ്രമാണം ഒരു ബാഹ്യ ആപ്ലിക്കേഷൻ ഉപയോഗിച്ച് തിരുത്തുക',
-'edit-externally-help' => '(കൂടുതൽ വിവരത്തിനു //www.mediawiki.org/wiki/Manual:External_editors കാണുക)',
+'edit-externally-help' => '(കൂടുതൽ വിവരത്തിനു [https://www.mediawiki.org/wiki/Manual:External_editors സജ്ജമാക്കൽ നിർദ്ദേശങ്ങൾ] കാണുക)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'എല്ലാം',
@@ -3761,7 +3779,7 @@ $1',
 'limitall' => 'എല്ലാം',
 
 # Email address confirmation
-'confirmemail' => 'ഇ-മെയിൽ വിലാസം സ്ഥിരീകരിക്കൽ',
+'confirmemail' => 'ഇമെയിൽ വിലാസം സ്ഥിരീകരിക്കൽ',
 'confirmemail_noemail' => '[[Special:Preferences|താങ്കളുടെ ക്രമീകരണങ്ങളുടെ കൂടെ]] സാധുവായൊരു ഇ-മെയിൽ വിലാസം സജ്ജീകരിച്ചിട്ടില്ല.',
 'confirmemail_text' => '{{SITENAME}} സം‌രംഭത്തിൽ ഇ-മെയിൽ സൗകര്യം ഉപയോഗിക്കണമെങ്കിൽ താങ്കൾ താങ്കളുടെ ഇ-മെയിൽ വിലാസത്തിന്റെ സാധുത തെളിയിച്ചിരിക്കണം. താങ്കളുടെ ഇ-മെയിൽ വിലാസത്തിലേക്ക് സ്ഥിരീകരണ മെയിൽ അയക്കുവാൻ താഴെയുള്ള ബട്ടൺ അമർത്തുക. താങ്കൾക്ക് അയക്കുന്ന ഇ-മെയിലിൽ ഒരു സ്ഥിരീകരണ കോഡ് ഉണ്ട്. ആ കോഡിൽ അമർത്തിയാൽ താങ്കളുടെ വിലാസത്തിന്റെ സാധുത തെളിയിക്കപ്പെടും.',
 'confirmemail_pending' => 'താങ്കളുടെ അംഗത്വം ഈ അടുത്ത് ഉണ്ടാക്കിയതാണെങ്കിൽ,  ഒരു സ്ഥിരീകരണ കോഡ് താങ്കൾക്ക് ഇ-മെയിൽ ചെയ്തിട്ടുണ്ട്.  പുതിയ സ്ഥിരീകരണ കോഡ് ആവശ്യപ്പെടാൻ ശ്രമിക്കുന്നതിനു മുൻപ് ആദ്യത്തെ സ്ഥിരീകരണ കോഡിനായി കുറച്ച് സമയം കാത്തിരിക്കൂ.',
@@ -3941,7 +3959,7 @@ $5
 'version-hook-subscribedby' => 'വരിക്കാരനായത്',
 'version-version' => '(പതിപ്പ് $1)',
 'version-license' => 'അനുമതി',
-'version-poweredby-credits' => "ഈ വിക്കി പ്രവർത്തിക്കാൻ '''[//www.mediawiki.org/ മീഡിയവിക്കി]''' ഉപയോഗിക്കുന്നു. പകർപ്പവകാശം © 2001-$1 $2.",
+'version-poweredby-credits' => "ഈ വിക്കി പ്രവർത്തിക്കാൻ '''[https://www.mediawiki.org/ മീഡിയവിക്കി]''' ഉപയോഗിക്കുന്നു. പകർപ്പവകാശം © 2001-$1 $2.",
 'version-poweredby-others' => 'മറ്റുള്ളവർ',
 'version-poweredby-translators' => 'പരിഭാഷാവിക്കിയിലെ പരിഭാഷകർ',
 'version-credits-summary' => '[[Special:Version|മീഡിയവിക്കിയ്ക്ക്]] നൽകിയ സംഭാവനകളുടെ പേരിൽ താഴെക്കൊടുക്കുന്നവർക്ക് ഞങ്ങൾ നന്ദി പറയുന്നു.',
@@ -3962,7 +3980,7 @@ $5
 # Special:Redirect
 'redirect' => 'പ്രമാണത്താൽ, ഉപയോക്താവിനാൽ അഥവാ നാൾപ്പതിപ്പ് ഐ.ഡി. ചെയ്യുന്ന തിരിച്ചുവിടൽ',
 'redirect-legend' => 'ഒരു പ്രമാണത്തിലോട്ടോ താളിലോട്ടോ ഉള്ള തിരിച്ചുവിടൽ',
-'redirect-summary' => 'ഈ പ്രത്യേക താൾ ഒരു പ്രമാണത്തിലേയ്ക്കോ (പ്രമാണത്തിന്റെ പേര് തന്നിട്ടുണ്ട്), ഒരു താളിലേയ്ക്കോ (നാൾപ്പതിപ്പിന്റെ ഐഡി തന്നിട്ടുണ്ട്), അല്ലെങ്കിൽ ഒരു ഉപയോക്തൃതാളിലേയ്ക്കോ (ഉപയോക്താവിന്റെ സംഖ്യാ ഐ.ഡി. തന്നിട്ടുണ്ട്) തിരിച്ചുവിടുന്നു.',
+'redirect-summary' => 'ഈ പ്രത്യേക താൾ ഒരു പ്രമാണത്തിലേയ്ക്കോ (പ്രമാണത്തിന്റെ പേര് തന്നിട്ടുണ്ട്), ഒരു താളിലേയ്ക്കോ (നാൾപ്പതിപ്പിന്റെ ഐഡി തന്നിട്ടുണ്ട്), അല്ലെങ്കിൽ ഒരു ഉപയോക്തൃതാളിലേയ്ക്കോ (ഉപയോക്താവിന്റെ സംഖ്യാ ഐ.ഡി. തന്നിട്ടുണ്ട്) തിരിച്ചുവിടുന്നു. ഉപയോഗം Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], അല്ലെങ്കിൽ [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'പോകൂ',
 'redirect-lookup' => 'തേടുക:',
 'redirect-value' => 'വില:',
@@ -3984,10 +4002,9 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'പ്രത്യേക താളുകൾ',
-'specialpages-note' => '----
-* പൊതുവേ ഉപയോഗിക്കുന്ന പ്രത്യേക താളുകൾ.
-* <strong class="mw-specialpagerestricted">ഉപയോഗം പരിമിതപ്പെടുത്തിയിരിക്കുന്ന പ്രത്യേക താളുകൾ.</strong>
-* <span class="mw-specialpagecached">പ്രാദേശികമായി സംഭരിച്ചുപയോഗിക്കുന്ന പ്രത്യേക താളുകൾ.</span>',
+'specialpages-note-top' => 'സൂചന',
+'specialpages-note' => '* പൊതുവേ ഉപയോഗിക്കുന്ന പ്രത്യേക താളുകൾ.
+* <span class="mw-specialpagerestricted">ഉപയോഗം പരിമിതപ്പെടുത്തിയിരിക്കുന്ന പ്രത്യേക താളുകൾ.</span>',
 'specialpages-group-maintenance' => 'പരിചരണം ആവശ്യമായവ',
 'specialpages-group-other' => 'മറ്റു പ്രത്യേക താളുകൾ',
 'specialpages-group-login' => 'പ്രവേശിക്കുക / അംഗത്വമെടുക്കുക',
@@ -4200,4 +4217,20 @@ $5
 'limitreport-expansiondepth' => 'വികസിപ്പിക്കാനാവുന്ന ഉയർന്ന പരിധി',
 'limitreport-expensivefunctioncount' => 'വ്യയമേറിയ പാഴ്സർ ഫങ്ഷൻ എണ്ണം',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'ഫലകങ്ങൾ വികസിപ്പിക്കുക',
+'expand_templates_intro' => 'ഈ പ്രത്യേക താൾ, ചില എഴുത്തുകൾ എടുത്ത് എല്ലാ ഫലകങ്ങളും പുനരാവർത്തിത സ്വഭാവത്തോടെ വികസിപ്പിക്കുന്നു.
+<code><nowiki>{{</nowiki>#എങ്കിൽ:…}}</code> തുടങ്ങിയ പാഴ്‌സർ ഫങ്ഷനുകളും
+<code><nowiki>{{</nowiki>ഈദിവസം}}</code> തുടങ്ങിയ ചരങ്ങളും, ഈ താൾ വികസിപ്പിക്കുന്നുണ്ട്.
+ചുരുക്കിപറഞ്ഞാൽ ഇരട്ട കോഷ്ഠകങ്ങളിലുള്ള എന്തിനേയും വികസിപ്പിക്കുന്നു.',
+'expand_templates_title' => '{{FULLPAGENAME}} മുതലായവ എടുക്കാനായി ഉള്ളടക്കത്തിന്റെ തലക്കെട്ട്:',
+'expand_templates_input' => 'ഇൻപുട്ട് ടെക്സ്റ്റ്:',
+'expand_templates_output' => 'ഫലം',
+'expand_templates_xml_output' => 'എക്സ്.എം.എൽ. ഔട്ട്പുട്ട്',
+'expand_templates_ok' => 'ശരി',
+'expand_templates_remove_comments' => 'അഭിപ്രായങ്ങൾ ഒഴിവാക്കുക',
+'expand_templates_remove_nowiki' => 'ഫലങ്ങളിലെ <nowiki> റ്റാഗുകൾ ഒതുക്കുക',
+'expand_templates_generate_xml' => 'എക്സ്.എം.എൽ. പാഴ്‌സർ ട്രീ പ്രദർശിപ്പിക്കുക',
+'expand_templates_preview' => 'എങ്ങനെയുണ്ടെന്നു കാണുക',
+
 );
index 04734d6..b664b15 100644 (file)
@@ -11,7 +11,9 @@
  * @author E.shijir
  * @author Kaganer
  * @author Meno25
+ * @author MongolWiki
  * @author Wisdom
+ * @author Zorigt
  * @author לערי ריינהארט
  */
 
@@ -147,18 +149,30 @@ $messages = array(
 'oct' => '10-р сар',
 'nov' => '11-р сар',
 'dec' => '12-р сар',
+'january-date' => 'Нэгдүгээр сарын $1',
+'february-date' => 'Хоёрдугаар сарын $1',
+'march-date' => 'Гуравдугаар сарын $1',
+'april-date' => 'Дөрөвдүгээр сарын $1',
+'may-date' => 'Тавдугаар сарын $1',
+'june-date' => 'Зургаадугаар сарын $1',
+'july-date' => 'Долоодугаар сарын $1',
+'august-date' => 'Наймдугаар сарын $1',
+'september-date' => 'Есдүгээр сарын $1',
+'october-date' => 'Аравдугаар сарын $1',
+'november-date' => 'Арван нэгдүгээр сарын $1',
+'december-date' => 'Арван хоёрдугаар сарын $1',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|Ангилал|Ангиллууд}}',
-'category_header' => '"$1" Ð°Ð½Ð³Ð¸Ð»Ð°Ð» Ð´Ð°Ñ\85Ñ\8c Ñ\85Ñ\83Ñ\83дÑ\81Ñ\83Ñ\83д',
-'subcategories' => 'Ð\94Ñ\8dд Ð°Ð½Ð³Ð¸Ð»Ð»Ñ\83Ñ\83д',
-'category-media-header' => '"$1" Ð°Ð½Ð³Ð¸Ð»Ð°Ð» Ð´Ð°Ñ\85Ñ\8c Ð¼ÐµÐ´Ð¸Ð° Ñ\84айлÑ\83Ñ\83д',
+'pagecategories' => '{{PLURAL:$1|Анги|Ангилал}}',
+'category_header' => '"$1" Ð°Ð½Ð³Ð¸Ð¹Ð½ Ð±Ò¯Ñ\80Ñ\8dлдÑ\8dÑ\85үүн',
+'subcategories' => 'Ð\90нгийн Ð±Ò¯Ð»Ñ\8dг',
+'category-media-header' => '"$1" Ð°Ð½Ð³Ð¸Ð¹Ð½ Ñ\84айл',
 'category-empty' => "''Одоогийн байдлаар энэ ангилалд хуудас, медиа файл байхгүй байна.''",
 'hidden-categories' => '{{PLURAL:$1|Нуугдсан ангилал|Нуугдсан ангиллууд}}',
 'hidden-category-category' => 'Нуугдсан ангиллууд',
-'category-subcat-count' => '{{PLURAL:$2|Энэ ангилалд дараах дэд ангилал л байна.|Энэ ангилалд нийт $2-с $1 дэд ангилал байна.}}',
+'category-subcat-count' => '{{PLURAL:$2|Энэ ангилалд дараах дэд ангилал л байна.|Энэ анги дотроо $2 анги, бүлэгтэй. Үүнээс $1 доор харагдаж байна.}}',
 'category-subcat-count-limited' => 'Энэ ангилалд {{PLURAL:$1| дэд ангилал|$1-н дэд ангилалууд}} байна.',
-'category-article-count' => '{{PLURAL:$2|Энэ ангилалд дараах хуудас л байна.|Энэ ангилалд нийт $2-с дараах $1 хуудас байна.}}',
+'category-article-count' => '{{PLURAL:$2|Энд нэг хуудас байна.|Энд $2 хуудас байна. Үүнээс $1 доор харагдаж байна.}}',
 'category-article-count-limited' => 'Энэ ангилалд дараах {{PLURAL:$1|хуудас|$1 хуудаснууд}} байна.',
 'category-file-count' => '{{PLURAL:$2|Энэ ангилалд дараах файл л байна.|Энэ ангилалд нийт $2-с дараах $1 файл байна.}}',
 'category-file-count-limited' => 'Энэ ангилалд дараах {{PLURAL:$1|файл|$1 файлнууд}} байна.',
@@ -172,6 +186,7 @@ $messages = array(
 'newwindow' => '(шинэ цонх нээгдэнэ)',
 'cancel' => 'Цуцлах',
 'moredotdotdot' => 'Дэлгэрэнгүй...',
+'morenotlisted' => 'Энэ жагсаалт нь бүрэн биш.',
 'mypage' => 'Хэрэглэгчийн хуудас',
 'mytalk' => 'Миний хэлэлцүүлэг',
 'anontalk' => 'Энэ IP-н яриа',
@@ -273,7 +288,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}}-н тухай',
 'aboutpage' => 'Project:Тухай',
-'copyright' => 'Ð\90гÑ\83Ñ\83лгÑ\8bг $1-н Ñ\85Ñ\83вÑ\8cд хэрэглэх боломжтой.',
+'copyright' => 'ТÑ\83Ñ\81гайлÑ\81ан Ñ\82айлбаÑ\80 Ð±Ð°Ð¹Ñ\85гүй Ð±Ð¾Ð» Ñ\8dнÑ\8d Ð°Ð³Ñ\83Ñ\83лгÑ\8bг $1 Ð»Ð¸Ñ\86ензийн Ð´Ð°Ð³Ñ\83Ñ\83 хэрэглэх боломжтой.',
 'copyrightpage' => '{{ns:project}}:Зохиогчийн эрх',
 'currentevents' => 'Сүүлийн үеийн мэдээ',
 'currentevents-url' => 'Project:Сүүлийн үеийн мэдээ',
@@ -300,12 +315,10 @@ $1',
 'pagetitle' => '$1 - {{SITENAME}}',
 'retrievedfrom' => '"$1" хуудаснаас авсан',
 'youhavenewmessages' => 'Таньд $1 ($2) байна.',
-'newmessageslink' => 'шинэ мессеж',
-'newmessagesdifflink' => 'сүүлийн өөрчлөлт',
 'youhavenewmessagesfromusers' => 'Танд {{PLURAL:$3|өөр нэгэн хэрэглэгчээс |$3 хэрэглэгчээс}} $1 ирсэн байна ($2).',
 'youhavenewmessagesmanyusers' => 'Танд ($2) олон хэрэглэгчидээс $1.',
-'newmessageslinkplural' => '{{PLURAL:$1|нэг шинэ меммеж| шинэ мессеж}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|сүүлд хийсэн өөрчлөлт|сүүлд хийсэн өөрчлөлт}}',
+'newmessageslinkplural' => '{{PLURAL:$1|шинэ зурвас}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|сүүлд хийгдсэн өөрчлөлт}}',
 'youhavenewmessagesmulti' => 'Таньд $1 дээр шинэ мессеж ирсэн байна',
 'editsection' => 'засварлах',
 'editold' => 'засварлах',
@@ -343,7 +356,7 @@ $1',
 'nstab-mediawiki' => 'Мэдэгдэл',
 'nstab-template' => 'Загвар',
 'nstab-help' => 'Тусламж',
-'nstab-category' => 'Ангилал',
+'nstab-category' => 'Анги',
 
 # Main script and global functions
 'nosuchaction' => 'Тийм үйлдэл байхгүй байна',
@@ -424,7 +437,7 @@ $2',
 'invalidtitle-knownnamespace' => 'Гарчигийг "$2" namespace, "$3" бичвэртэй буруу оруулсан байна',
 'invalidtitle-unknownnamespace' => '$1 гэсэн үл мэдэгдэх неймспайсын дугаар, "$2" бичвэртэй буруу гарчиг байна.',
 'exception-nologin' => 'Та хэрэглэгчийн нэрээр нэвтрээгүй байна.',
-'exception-nologin-text' => 'Уг Ñ\85Ñ\83Ñ\83даÑ\81, Ò¯Ð¹Ð»Ð´Ð»Ð¸Ð¹Ð³ Ñ\85ийÑ\85Ñ\8dд Ñ\82а Ð²Ð¸ÐºÐ¸Ñ\80Ñ\83Ñ\83 Ñ\85олбогдÑ\81он Ð±Ð°Ð¹Ñ\85 Ñ\88ааÑ\80длагаÑ\82ай.',
+'exception-nologin-text' => 'ЭнÑ\8d Ñ\85Ñ\83Ñ\83дÑ\81анд Ñ\85андаÑ\85, Ñ\8dÑ\81вÑ\8dл Ñ\83г Ò¯Ð¹Ð»Ð´Ð»Ð¸Ð¹Ð³ Ñ\85ийÑ\85ийн Ñ\82Ñ\83лд [[Special:Userlogin|нÑ\8dвÑ\82Ñ\8dÑ\80нÑ\8d]] Ò¯Ò¯.',
 
 # Virus scanner
 'virus-badscanner' => "Буруу тохиргоо: үл мэдэгдэх вирус илрүүлэгч программ: ''$1''",
@@ -440,8 +453,16 @@ $2',
 'welcomecreation-msg' => 'Таны бүртгэл хийгдсэн байна.
 Та өөрийн [[Special:Preferences|{{SITENAME}}-н тохиргоогоо]]  өөрчлөхөө бүү мартаарай.',
 'yourname' => 'Хэрэглэгчийн нэр:',
+'userlogin-yourname' => 'Хэрэглэгчийн нэр',
+'userlogin-yourname-ph' => 'Хэрэглэгчийн нэрээ оруулна уу',
+'createacct-another-username-ph' => 'Хэрэглэгчийн нэрээ оруулна уу',
 'yourpassword' => 'Нууц үг:',
+'userlogin-yourpassword' => 'Нууц үг',
+'userlogin-yourpassword-ph' => 'Нууц үгээ оруулна уу',
+'createacct-yourpassword-ph' => 'Нууц үгээ оруулна уу',
 'yourpasswordagain' => 'Нууц үгээ дахин оруулах:',
+'createacct-yourpasswordagain' => 'Нууц үгээ баталгаажуулна уу',
+'createacct-yourpasswordagain-ph' => 'Нууц үгээ дахиж оруулна уу',
 'remembermypassword' => 'Энэ компьютер дээрх миний нэвтрэлтийг сана (хамгийн дээд талдаа $1 {{PLURAL:$1|өдрийн|өдрийн}} туршид)',
 'yourdomainname' => 'Таны домэйн:',
 'password-change-forbidden' => 'Та энэ вики дээрх нууц үгээ сольж болохгүй.',
@@ -454,14 +475,29 @@ $2',
 'logout' => 'Гарах',
 'userlogout' => 'Гарах',
 'notloggedin' => 'Нэвтрээгүй байна',
+'userlogin-joinproject' => '{{SITENAME}}-д бүртгүүлэх',
 'nologin' => "Бүртгэлгүй юу? '''$1'''.",
 'nologinlink' => 'Бүртгүүлэх',
 'createaccount' => 'Бүртгүүлэх',
 'gotaccount' => "Та бүртгэлтэй юу? '''$1'''",
 'gotaccountlink' => 'Нэвтрэх',
 'userlogin-resetlink' => 'Нэвтрэх мэдээллээ мартаа юу?',
+'userlogin-resetpassword-link' => 'Нууц үгээ мартсан уу?',
+'helplogin-url' => 'Help:Нэвтрэх',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Нэвтрэхэд тусламж]]',
+'userlogin-loggedin' => 'Та {{GENDER:$1|$1}} нэрээр нэвтэрсэн байна.
+Өөр нэрээр нэвтрэх бол доорх маягтыг ашиглана уу.',
+'userlogin-createanother' => 'Өөр бүртгэл үүсгэх',
+'createacct-join' => 'Мэдээллээ оруулна уу.',
+'createacct-another-join' => 'Шинэ бүртгэлийн мэдээллээ оруулна уу.',
 'createaccountmail' => 'Мэйлээр илгээх',
+'createacct-realname' => 'Жинхэнэ нэр (хоосон орхиж болно)',
 'createaccountreason' => 'Шалтгаан:',
+'createacct-reason' => 'Шалтгаан',
+'createacct-reason-ph' => 'Өөр бүртгэл үүсгэх шалтгаан',
+'createacct-benefit-heading' => '{{SITENAME}}-г тан шиг хүмүүс хийж байна.',
+'createacct-benefit-body1' => '{{PLURAL:$1|засвар}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|хуудас}}',
 'badretype' => 'Таны оруулсан хоёр нууц үг таарахгүй байна.',
 'userexists' => 'Хэрэглэгчийн нэр ашиглагдаж байна.
 Өөр нэрээр нэвтэрнэ үү.',
@@ -491,7 +527,7 @@ $2',
 Хамгийн багадаа {{PLURAL:$1|1 үсэгтэй|$1 үсэгтэй}} байх ёстой.',
 'password-name-match' => 'Таны нууц үг хэрэглэгчийн нэрнээс ялгаатай байх ёстой.',
 'password-login-forbidden' => 'Ийм хэрэглэгчийн, нууц үгээр нэвтрэхийг хориглож байна.',
-'mailmypassword' => 'Ð\9cÑ\8dйл Ñ\85аÑ\8fгааÑ\80 Ñ\88инÑ\8d Ð½Ñ\83Ñ\83Ñ\86 Ò¯Ð³Ð¸Ð¹Ð³ Ð¸Ð»Ð³Ñ\8dÑ\8d',
+'mailmypassword' => 'Ð\9dÑ\83Ñ\83Ñ\86 Ò¯Ð³Ñ\8dÑ\8d Ñ\81Ñ\8dÑ\80гÑ\8dÑ\8dÑ\85',
 'passwordremindertitle' => '{{SITENAME}}-д нэвтрэх түр зуурын шинэ нууц үг',
 'passwordremindertext' => 'Хэн нэгэн (магадгүй та, $1 гэх IP хаягаас) {{SITENAME}} ($4) хуудсанд нэвтрэх шинэ нууц үг явуулах хүсэлтийг тавьсан байна. "$3" гэсэн түр хугацаанд хэрэглэж болох нууц үгийг хэрэглэгч "$2"-д олгов.
 Хэрэв та ингэхийг хүссэн бол нэвтэрч ороод шинэ нууц үгээ сонгоно уу.
@@ -856,8 +892,8 @@ $3-н тодорхойлсон шалтгаан нь ''$2''",
 (сүүлчийн) = өмнөх засвартай харьцуулах, Б = бага зэргийн засвар',
 'history-fieldset-title' => 'Түүх сөхөе',
 'history-show-deleted' => 'Зөвхөн устгагдсаныг',
-'histfirst' => 'Эхний',
-'histlast' => 'Сүүлийн',
+'histfirst' => 'хамгийн эхэнд',
+'histlast' => 'хамгийн шинэ',
 'historysize' => '($1 байт)',
 'historyempty' => '(хоосон байна)',
 
@@ -1081,8 +1117,6 @@ $1",
 'preferences' => 'Хэрэглэгчийн тохиргоо',
 'mypreferences' => 'Миний тохиргоо',
 'prefs-edits' => 'Засваруудын тоо:',
-'prefsnologin' => 'Нэвтрээгүй байна',
-'prefsnologintext' => 'Та хэрэглэгчийн тохиргоогоо тохируулахын тулд <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} нэвтэрсэн байх]</span> ёстой.',
 'changepassword' => 'Нууц үгээ солих',
 'prefs-skin' => 'Арьс',
 'skin-preview' => 'Урьдчилж харах',
@@ -1356,6 +1390,7 @@ $1 тэмдэгтээс богино байх ёстой.',
 'recentchanges-label-minor' => 'Энэ нь бага зэргийн засвар байна',
 'recentchanges-label-bot' => 'Энэ засварыг бот гүйцэтгэсэн байна',
 'recentchanges-label-unpatrolled' => 'Энэ засварыг одоогийн байдлаар манаагүй байна',
+'recentchanges-legend-newpage' => '([[Special:NewPages|Шинэ хуудсуудын жагсаалтыг]] бас үзнэ үү.',
 'rcnote' => "Доорх нь $5, $4-ий байдлаарх сүүлийн '''$2''' өдрийн турших '''$1''' засвар юм.",
 'rcnotefrom' => "Доорх нь '''$2'''-с хойших өөрчлөлтүүд ('''$1''' хүртэлхийг харуулав) юм.",
 'rclistfrom' => '$1-с хойших шинэ засваруудыг үзүүлэх',
@@ -1649,6 +1684,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'listfiles_search_for' => 'Зургийн нэрээр хайх:',
 'imgfile' => 'файл',
 'listfiles' => 'Файлын жагсаалт',
+'listfiles_thumb' => 'товч агуулга',
 'listfiles_date' => 'Огноо',
 'listfiles_name' => 'Нэр',
 'listfiles_user' => 'Хэрэглэгч',
@@ -1789,7 +1825,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 
 # Miscellaneous special pages
 'nbytes' => '$1 байт',
-'ncategories' => '$1 ангилал',
+'ncategories' => '$1 анги',
 'nlinks' => '$1 линк',
 'nmembers' => '$1 гишүүн',
 'nrevisions' => '$1 засвар',
@@ -1797,12 +1833,12 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'nimagelinks' => '$1 {{PLURAL:$1|хуудсанд|хуудсанд}} ашигласан',
 'specialpage-empty' => 'Энэ мэдүүлэгт үр дүн гарсангүй.',
 'lonelypages' => 'Өнчин хуудсууд',
-'lonelypagestext' => 'Энэ хуудсууд {{SITENAME}}-дахь бусад хуудсуудтай холбогдоогүй эсвэл заагаас хэтэрсэн байна.',
+'lonelypagestext' => 'Энэ хуудсууд {{SITENAME}}-дахь бусад хуудастай холбогдоогүй эсвэл заагаас хэтэрсэн байна.',
 'uncategorizedpages' => 'Ангилагдаагүй хуудсууд',
-'uncategorizedcategories' => 'Ангилагдаагүй ангиллууд',
+'uncategorizedcategories' => 'Ангилагдаагүй анги',
 'uncategorizedimages' => 'Ангилагдаагүй зургууд',
 'uncategorizedtemplates' => 'Ангилагдаагүй загварууд',
-'unusedcategories' => 'Ð\90Ñ\88иглагдаагүй Ð°Ð½Ð³Ð¸Ð»Ð»Ñ\83Ñ\83д',
+'unusedcategories' => 'ХооÑ\81он Ð°Ð½Ð³Ð¸',
 'unusedimages' => 'Ашиглагдаагүй файлууд',
 'popularpages' => 'Эрэлттэй хуудсууд',
 'wantedcategories' => 'Хэрэгцээт ангиллууд',
@@ -1889,11 +1925,11 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'cachedspecial-refresh-now' => 'Саяханы хуудсыг харах',
 
 # Special:Categories
-'categories' => 'Ангиллууд',
+'categories' => 'Анги',
 'categoriespagetext' => 'Дараах {{PLURAL:$1|ангилалд|ангиллуудад}} хуудас эсвэл медиа файл агуулагдаж байна.
 [[Special:UnusedCategories|Хэрэглэгдэхгүй байгаа]] ангиллуудыг энд харуулсангүй.
 [[Special:WantedCategories|Хэрэгтэй ангиллууд]] гэдгийг харна уу.',
-'categoriesfrom' => 'Хамгийн Ñ\8dÑ\85Ñ\8dлж Ñ\85аÑ\80Ñ\83Ñ\83лаÑ\85 ангилал:',
+'categoriesfrom' => 'ЭÑ\85ний ангилал:',
 'special-categories-sort-count' => 'тоогоор ялгах',
 'special-categories-sort-abc' => 'үсгийн дарааллаар ялгах',
 
@@ -2243,7 +2279,7 @@ $1',
 'mycontris' => 'Оруулсан хувь нэмэр',
 'contribsub2' => 'Хэрэглэгч: $1 ($2)',
 'nocontribs' => 'Энэ шалгуурт тохирох өөрчилсөн зүйлүүд олдсонгүй.',
-'uctop' => 'ï¼\88дÑ\8dÑ\8dд)',
+'uctop' => 'ï¼\88одооÑ\85)',
 'month' => 'Дараах сараас (өмнөх засварууд нь ч орно):',
 'year' => 'Дараах жилээс (өмнөх засварууд нь ч орно):',
 
@@ -2538,7 +2574,7 @@ $1',
 'allmessagesdefault' => 'Анхны',
 'allmessagescurrent' => 'Одоогийн',
 'allmessagestext' => 'Энэ бол МедиаВики дахь системийн мэдэгдлүүдийн жагсаалт юм.
-МедиаВикиг орчуулах тухай мэдээллийг [//www.mediawiki.org/wiki/Localisation МедиаВикигийн орчуулга], мөн [//translatewiki.net translatewiki.net]-с авна уу.',
+МедиаВикиг орчуулах тухай мэдээллийг [https://www.mediawiki.org/wiki/Localisation МедиаВикигийн орчуулга], мөн [//translatewiki.net translatewiki.net]-с авна уу.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' нь унтарсан байгаа тул '''Special:Allmessages'''-г хэрэглэж болохгүй.",
 'allmessages-filter-legend' => 'Шүүлтүүр',
 'allmessages-filter' => 'Өөрийн болгосон байдлаар нь шүүх:',
@@ -2781,7 +2817,7 @@ $1',
 'file-nohires' => 'Илүү чанартай хувилбар байхгүй байна.',
 'svg-long-desc' => 'SVG файл, $1 × $2 пиксэл, файлын хэмжээ: $3',
 'svg-long-error' => '$1 : Буруу SVG файл',
-'show-big-image' => 'Хамгийн Ñ\81айн Ñ\87анаÑ\80Ñ\82ай Ñ\85Ñ\83вилбаÑ\80',
+'show-big-image' => 'ЭÑ\85 Ñ\84айл',
 'show-big-image-preview' => 'Үзлэгийн хэмжээ : $1',
 'show-big-image-other' => 'Бусад {{PLURAL:$2|зургын нягтрал|зургын нягтрал}}: $1.',
 'show-big-image-size' => '$1 × $2 пиксел',
@@ -2974,7 +3010,7 @@ $1',
 'exif-writer' => 'Бичсэн',
 'exif-languagecode' => 'Хэл',
 'exif-iimversion' => 'IIM хувилбар',
-'exif-iimcategory' => 'Ангилал',
+'exif-iimcategory' => 'Анги',
 'exif-datetimeexpires' => 'түүний дараа бүү хэрэглэ',
 'exif-datetimereleased' => 'Гарсан өдөр',
 'exif-originaltransmissionref' => '',
@@ -3158,7 +3194,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Гадны программыг ашиглан энэ файлыг засварлах',
-'edit-externally-help' => '(Нэмэлт мэдээллийг [//www.mediawiki.org/wiki/Manual:External_editors тохируулгын зааврын] хуудаснаас харна уу)',
+'edit-externally-help' => '(Нэмэлт мэдээллийг [https://www.mediawiki.org/wiki/Manual:External_editors тохируулгын зааврын] хуудаснаас харна уу)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'бүгдийг',
@@ -3326,7 +3362,7 @@ $5
 'version-hook-subscribedby' => 'Захиалсан:',
 'version-version' => '(Хувилбар $1)',
 'version-license' => 'Лиценз',
-'version-poweredby-credits' => "Энэхүү викиг '''[//www.mediawiki.org/ MediaWiki]''' програмаар ажиллуулдаг, зохиогчийн эрх © 2001-$1 $2.",
+'version-poweredby-credits' => "Энэхүү викиг '''[https://www.mediawiki.org/ MediaWiki]''' програмаар ажиллуулдаг, зохиогчийн эрх © 2001-$1 $2.",
 'version-poweredby-others' => 'бусад',
 'version-software' => 'Суулгасан программ',
 'version-software-product' => 'Бүтээгдэхүүн',
@@ -3345,8 +3381,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Тусгай хуудсууд',
-'specialpages-note' => '----
-* Ердийн тусгай хуудсууд.
+'specialpages-note' => '* Ердийн тусгай хуудсууд.
 * <strong class="mw-specialpagerestricted">Хориотой тусгай хуудсууд.</strong>',
 'specialpages-group-maintenance' => 'Засвар үйлчилгээний тайлангууд',
 'specialpages-group-other' => 'Бусад тусгай хуудсууд',
@@ -3456,4 +3491,9 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|зуун|зуун}}',
 'duration-millennia' => '$1 {{PLURAL:$1|мянган|мянган}}',
 
+# Special:ExpandTemplates
+'expand_templates_input' => 'Оруулах бичиг:',
+'expand_templates_output' => 'Үр дүн',
+'expand_templates_remove_comments' => 'Товч агуулгыг авч хаях',
+
 );
index b59092b..c89a976 100644 (file)
@@ -81,7 +81,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'जुनी_पाने' ),
        'Blankpage'                 => array( 'कोरे_पान' ),
        'Block'                     => array( 'प्रतिबंध', 'अंकपत्ता_प्रतिबंध', 'सदस्य_प्रतिबंध' ),
-       'Blockme'                   => array( 'मला_प्रतिबंध_करा' ),
        'Booksources'               => array( 'पुस्तक_स्रोत' ),
        'BrokenRedirects'           => array( 'चुकीची_पुनर्निर्देशने' ),
        'Categories'                => array( 'वर्ग' ),
@@ -93,9 +92,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'सदस्य_नोंद' ),
        'Deadendpages'              => array( 'टोकाची_पाने' ),
        'DeletedContributions'      => array( 'वगळलेली_योगदाने' ),
-       'Disambiguations'           => array( 'निःसंदिग्धीकरण' ),
        'DoubleRedirects'           => array( 'दुहेरी_पुनर्निर्देशने' ),
        'Emailuser'                 => array( 'विपत्र_वापरकर्ता' ),
+       'ExpandTemplates'           => array( 'साचेविस्तारकरा' ),
        'Export'                    => array( 'निर्यात' ),
        'Fewestrevisions'           => array( 'कमीत_कमी_आवर्तने' ),
        'FileDuplicateSearch'       => array( 'दुहेरी_संचिका_शोध' ),
@@ -173,7 +172,7 @@ $magicWords = array(
        'nogallery'                 => array( '0', '__प्रदर्शननको__', '__NOGALLERY__' ),
        'forcetoc'                  => array( '0', '__अनुक्रमणिकाहवीच__', '__FORCETOC__' ),
        'toc'                       => array( '0', '__अनुक्रमणिका__', '__TOC__' ),
-       'noeditsection'             => array( '0', '__असंपादनक्षम__', '__NOEDITSECTION__' ),
+       'noeditsection'             => array( '0', '__विभाà¤\97à¤\85सà¤\82पादनà¤\95à¥\8dषम__', '__NOEDITSECTION__' ),
        'currentmonth'              => array( '1', 'सद्यमहिना', 'सद्यमहिना२', 'CURRENTMONTH', 'CURRENTMONTH2' ),
        'currentmonth1'             => array( '1', 'सद्यमहिना१', 'CURRENTMONTH1' ),
        'currentmonthname'          => array( '1', 'सद्यमहिनानाव', 'CURRENTMONTHNAME' ),
@@ -207,6 +206,7 @@ $magicWords = array(
        'pagenamee'                 => array( '1', 'लेखानावव', 'PAGENAMEE' ),
        'namespace'                 => array( '1', 'नामविश्व', 'NAMESPACE' ),
        'namespacee'                => array( '1', 'नामविश्वा', 'नामविश्वाचे', 'NAMESPACEE' ),
+       'namespacenumber'           => array( '1', 'नामविश्वक्रमांक', 'NAMESPACENUMBER' ),
        'talkspace'                 => array( '1', 'चर्चाविश्व', 'TALKSPACE' ),
        'talkspacee'                => array( '1', 'चर्चाविश्वा', 'चर्चाविश्वाचे', 'TALKSPACEE' ),
        'subjectspace'              => array( '1', 'विषयविश्व', 'लेखविश्व', 'SUBJECTSPACE', 'ARTICLESPACE' ),
@@ -233,8 +233,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'मध्यवर्ती', 'center', 'centre' ),
        'img_framed'                => array( '1', 'चौकट', 'फ़्रेम', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'विनाचौकट', 'विनाफ़्रेम', 'frameless' ),
-       'img_page'                  => array( '1', 'पान=$1', 'पान $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'उभा', 'उभा=$1', 'उभा $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'पान=$1', 'पान_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'उभा', 'उभा=$1', 'उभा_$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'सीमा', 'border' ),
        'img_baseline'              => array( '1', 'तळरेषा', 'आधाररेषा', 'baseline' ),
        'img_sub'                   => array( '1', 'अधो', 'sub' ),
@@ -304,6 +304,11 @@ $magicWords = array(
        'staticredirect'            => array( '1', '__अविचलपुर्ननिर्देश__', '__STATICREDIRECT__' ),
        'protectionlevel'           => array( '1', 'सुरक्षास्तर', 'PROTECTIONLEVEL' ),
        'formatdate'                => array( '0', 'दिनांकनपद्धती', 'formatdate', 'dateformat' ),
+       'url_wiki'                  => array( '0', 'विकि', 'WIKI' ),
+       'pagesincategory_all'       => array( '0', 'सर्व', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'पाने', 'pages' ),
+       'pagesincategory_subcats'   => array( '0', 'उपवर्ग', 'subcats' ),
+       'pagesincategory_files'     => array( '0', 'संचिका', 'files' ),
 );
 
 $digitTransformTable = array(
@@ -563,7 +568,7 @@ $messages = array(
 $1',
 'pool-timeout' => 'ताळ्यासाठी वाट पाहण्याची वेळ संपली',
 'pool-queuefull' => 'सर्व्हरवर ताण आहे.',
-'pool-errorunknown' => 'à¤\85परिà¤\9aित à¤¤à¥\8dरà¥\82टी',
+'pool-errorunknown' => 'à¤\85परिà¤\9aित à¤¤à¥\8dरà¥\81टी',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}}बद्दल',
@@ -593,13 +598,11 @@ $1',
 
 'ok' => 'ठीक',
 'retrievedfrom' => '"$1" पासून हुडकले',
-'youhavenewmessages' => 'तुमच्यासाठी $1 ($2) आहे.',
-'newmessageslink' => 'नवीन संदेश',
-'newmessagesdifflink' => 'ताजा बदल',
-'youhavenewmessagesfromusers' => 'आपलेपाशी  $1च्या पासून  {{PLURAL:$3|वेगळे सदस्य|$3 सदस्य}}($2)आहेत.',
-'youhavenewmessagesmanyusers' => ' आपलेपाशी ($2) सदस्यांपासून $1 आहेत.',
-'newmessageslinkplural' => '{{PLURAL:$1|a new message|नविन संदेश}}',
-'newmessagesdifflinkplural' => 'मागिल {{PLURAL:$1|बदल}}',
+'youhavenewmessages' => 'तुमच्यासाठी $1 आहे. ($2)',
+'youhavenewmessagesfromusers' => 'तुमच्यासाठी {{PLURAL:$3|इतर सदस्याकडून|$3 सदस्यांकडून}} $1 आहेत. ($2)',
+'youhavenewmessagesmanyusers' => 'तुमच्यासाठी बऱ्याच सदस्यांकडून $1 आहेत. ($2)',
+'newmessageslinkplural' => '{{PLURAL:$1|नवीन संदेश|नवीन संदेश}}',
+'newmessagesdifflinkplural' => 'मागील {{PLURAL:$1|बदल}}',
 'youhavenewmessagesmulti' => '$1 वर तुमच्यासाठी नवीन संदेश आहेत.',
 'editsection' => 'संपादन',
 'editold' => 'संपादन',
@@ -612,13 +615,13 @@ $1',
 'hidetoc' => 'लपवा',
 'collapsible-collapse' => 'निपात करा',
 'collapsible-expand' => 'विस्तार',
-'thisisdeleted' => '$1à¤\9aà¥\87 à¤\85वलà¥\8bà¤\95न à¤\95िà¤\82वा à¤ªà¥\82नर्स्थापन करायचे ?',
+'thisisdeleted' => '$1à¤\9aà¥\87 à¤\85वलà¥\8bà¤\95न à¤\95िà¤\82वा à¤ªà¥\81नर्स्थापन करायचे ?',
 'viewdeleted' => ' $1चे अवलोकन करायचे?',
 'restorelink' => '{{PLURAL:$1|एक वगळलेले संपादन|$1 वगळलेली संपादने}}',
-'feedlinks' => 'पà¥\8dरदाय (Feed):',
+'feedlinks' => 'रसद (Feed) :',
 'feed-invalid' => 'अयोग्य रसद नोंदणी (Invalid subscription feed type).',
-'feed-unavailable' => 'सिà¤\82डà¥\80à¤\95à¥\87शन à¤«à¥\80ड उपलब्ध नाहीत',
-'site-rss-feed' => '$1 à¤\86रà¤\8fसà¤\8fस à¤«à¥\80ड',
+'feed-unavailable' => 'सिà¤\82डà¥\80à¤\95à¥\87शन à¤°à¤¸à¤¦ उपलब्ध नाहीत',
+'site-rss-feed' => '$1 à¤\86रà¤\8fसà¤\8fस à¤°à¤¸à¤¦',
 'site-atom-feed' => '$1 ऍटम रसद (Atom Feed)',
 'page-rss-feed' => '"$1" आर.एस.एस.रसद (RSS Feed)',
 'page-atom-feed' => '"$1" ऍटम रसद (Atom Feed)',
@@ -801,8 +804,8 @@ $2',
 'createacct-benefit-body1' => '{{PLURAL:$1|edit|संपादने}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|लेख}}',
 'createacct-benefit-body3' => 'अलीकडील {{PLURAL:$1|योगदानकर्ता|योगदानकर्ते}}',
-'badretype' => 'à¤\86पण à¤\9fाà¤\95लà¥\87ला à¤ªà¤°à¤µà¤²à¥\80à¤\9aा à¤¶à¤¬à¥\8dद à¤\9cà¥\81ळत à¤¨à¤¾à¤¹à¥\80.',
-'userexists' => 'à¤\86पण टाकलेले सदस्यनाम पूर्वीच वापरात आहे.
+'badretype' => 'तà¥\81मà¥\8dहà¥\80 à¤\9fाà¤\95लà¥\87लà¥\87 à¤ªà¤°à¤µà¤²à¥\80à¤\9aà¥\87 à¤¶à¤¬à¥\8dद à¤\9cà¥\81ळत à¤¨à¤¾à¤¹à¥\80त.',
+'userexists' => 'तà¥\81मà¥\8dहà¥\80 टाकलेले सदस्यनाम पूर्वीच वापरात आहे.
 कृपया वेगळे सदस्यनाम निवडा.',
 'loginerror' => 'सनोंद-प्रवेशात चूक झाली आहे',
 'createacct-error' => 'खाते तयार करण्यात चुकी',
@@ -1278,15 +1281,15 @@ $1",
 'deletedhist' => 'वगळलेला इतिहास',
 'revdelete-hide-current' => '$1 मधील $2 या वेळचे आवर्तन लपविण्यात त्रूटी : ते सद्य पुनरावर्तन आहे.
 ते लपवता येत नाही.',
-'revdelete-show-no-access' => '$2, $1 à¤\9aà¥\80 à¤µà¤¸à¥\8dतà¥\82 दाखवताना अडचण: ती "प्रतिबंधित" खूण असलेली आहे.
+'revdelete-show-no-access' => '$2, $1 à¤\9aà¥\80 à¤¬à¤¾à¤¬ दाखवताना अडचण: ती "प्रतिबंधित" खूण असलेली आहे.
 तुम्ही तिच्यापर्यंत पोचू शकत नाही.',
-'revdelete-modify-no-access' => '$2, $1 à¤\9aà¥\80 à¤µà¤¸à¥\8dतà¥\82 संपादताना अडचण: ती "प्रतिबंधित" खूण असलेली आहे.
+'revdelete-modify-no-access' => '$2, $1 à¤\9aà¥\80 à¤¬à¤¾à¤¬ संपादताना अडचण: ती "प्रतिबंधित" खूण असलेली आहे.
 तुम्ही तिच्यापर्यंत पोचू शकत नाही.',
-'revdelete-modify-missing' => 'वसà¥\8dतà¥\82 क्र. $1 ला संपादताना त्रुटी: ती माहितीकोषात नाही!',
-'revdelete-no-change' => "'''सà¥\82à¤\9aना:''' $2, $1 à¤\9aà¥\8dया à¤µà¤¸à¥\8dतà¥\82ने अगोदरच दृश्यता रुपरेषा मागितल्या आहेत.",
-'revdelete-concurrent-change' => '$2, $1 à¤\9aà¥\80 à¤µà¤¸à¥\8dतà¥\82 à¤¸à¤\82पादताना à¤\9aà¥\82à¤\95: à¤¤à¥\81मà¥\8dहà¥\80 à¤¤à¤¿à¤²à¤¾ à¤¸à¤\82पादताना à¤¦à¥\81सऱà¥\8dया à¤µà¥\8dयà¤\95à¥\8dतिनà¥\87 à¤µà¤¸à¥\8dतà¥\82स à¤¸à¤\82पादले असावे.
+'revdelete-modify-missing' => 'बाब क्र. $1 ला संपादताना त्रुटी: ती माहितीकोषात नाही!',
+'revdelete-no-change' => "'''सà¥\82à¤\9aना:''' $2, $1 à¤\9aà¥\8dया à¤¬à¤¾à¤¬à¥\80ने अगोदरच दृश्यता रुपरेषा मागितल्या आहेत.",
+'revdelete-concurrent-change' => '$2, $1 à¤\9aà¥\80 à¤¬à¤¾à¤¬ à¤¸à¤\82पादताना à¤\9aà¥\82à¤\95: à¤¤à¥\81मà¥\8dहà¥\80 à¤¤à¤¿à¤²à¤¾ à¤¸à¤\82पादताना à¤¦à¥\81सऱà¥\8dया à¤µà¥\8dयà¤\95à¥\8dतिनà¥\87  à¤¬à¤¾à¤¬à¥\80स à¤¸à¤\82पादिले असावे.
 कृपया याद्या तपासा.',
-'revdelete-only-restricted' => '$2, $1 à¤\9aà¥\80 à¤µà¤¸à¥\8dतà¥\82 à¤²à¤ªà¤µà¤¤à¤¾à¤¨à¤¾ à¤\9aà¥\82à¤\95: à¤¤à¥\81मà¥\8dहà¥\80 à¤\87तर à¤¦à¥\83शà¥\8dयता à¤ªà¤°à¥\8dयायाà¤\82ना à¤¨à¤¿à¤µà¤¡à¤²à¥\8dयाशिवाय à¤ªà¥\8dरà¤\9aालà¤\95ाà¤\82पासà¥\82न à¤µà¤¸à¥\8dतà¥\82 लपवू शकत नाही.',
+'revdelete-only-restricted' => '$2, $1 à¤\9aà¥\80 à¤¬à¤¾à¤¬ à¤²à¤ªà¤µà¤¤à¤¾à¤¨à¤¾ à¤\9aà¥\82à¤\95: à¤¤à¥\81मà¥\8dहà¥\80 à¤\87तर à¤¦à¥\83शà¥\8dयता à¤ªà¤°à¥\8dयायाà¤\82ना à¤¨à¤¿à¤µà¤¡à¤²à¥\8dयाशिवाय à¤ªà¥\8dरà¤\9aालà¤\95ाà¤\82पासà¥\82न à¤¬à¤¾à¤¬ लपवू शकत नाही.',
 'revdelete-reason-dropdown' => '* वगळण्याची सामान्य कारणे
 ** प्रताधिकार उल्लंघन
 ** अयोग्य टिप्पणी किंवा व्यक्तिगत माहिती
@@ -1368,7 +1371,7 @@ $1",
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|या उपसर्गानिशी असलेली पाने न्याहाळा]]',
 'searchprofile-articles' => 'आशय-पाने',
 'searchprofile-project' => 'साहाय्य व प्रकल्प पाने',
-'searchprofile-images' => 'मलà¥\8dà¤\9fिमà¥\80डिया',
+'searchprofile-images' => 'बहà¥\81माधà¥\8dयमà¥\87',
 'searchprofile-everything' => 'सगळे',
 'searchprofile-advanced' => 'प्रगत',
 'searchprofile-articles-tooltip' => '$1 मध्ये शोधा',
@@ -1378,11 +1381,11 @@ $1",
 'searchprofile-advanced-tooltip' => 'निवडलेल्या नामविश्वांमध्ये शोधा:',
 'search-result-size' => '$1 ({{PLURAL:$2|१ शब्द|$2 शब्द}})',
 'search-result-category-size' => '{{PLURAL:$1|१ सदस्य|$1 सदस्य}} ({{PLURAL:$2|१ उपवर्ग|$2 उपवर्ग}}, {{PLURAL:$3|1 संचिका|$3 संचिका}})',
-'search-result-score' => 'à¤\9cà¥\81ळणà¥\80: $1%',
+'search-result-score' => 'à¤\85नà¥\8dवरà¥\8dथà¤\95ता: $1%',
 'search-redirect' => '(पुनर्निर्देशन $1)',
 'search-section' => '(विभाग $1)',
 'search-suggest' => 'तुम्हाला हेच म्हणायचे का: $1',
-'search-interwiki-caption' => 'à¤\87तर प्रकल्प',
+'search-interwiki-caption' => 'सह प्रकल्प',
 'search-interwiki-default' => '$1चे निकाल:',
 'search-interwiki-more' => '(आणखी)',
 'search-relatedarticle' => 'जवळील',
@@ -1408,11 +1411,9 @@ $1",
 'search-error' => 'शोध घेतांना घडलेली त्रूटी:$1',
 
 # Preferences page
-'preferences' => 'माà¤\9dà¥\8dया à¤ªà¤¸à¤\82तà¥\80',
+'preferences' => 'पसà¤\82तà¥\80à¤\95à¥\8dरम',
 'mypreferences' => 'पसंतीक्रम',
 'prefs-edits' => 'संपादनांची संख्या:',
-'prefsnologin' => 'प्रवेश केलेला नाही',
-'prefsnologintext' => 'तुम्हाला सदस्य पसंती बदलण्यासाठी <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} प्रवेश]</span> करावा लागेल.',
 'changepassword' => 'परवलीचा शब्द बदला',
 'prefs-skin' => 'त्वचा',
 'skin-preview' => 'झलक',
@@ -1423,13 +1424,13 @@ $1",
 'prefs-user-pages' => 'सदस्य पान',
 'prefs-personal' => 'सदस्य व्यक्तिरेखा',
 'prefs-rc' => 'अलीकडील बदल',
-'prefs-watchlist' => 'नितà¥\8dय à¤ªà¤¹à¤¾à¤£à¥\8dयाà¤\9aà¥\80 सूची',
-'prefs-watchlist-days' => 'पहाऱà¥\8dयाà¤\9aà¥\8dया सूचीमध्ये दिसणाऱ्या दिवसांची संख्या:',
+'prefs-watchlist' => 'निरà¥\80à¤\95à¥\8dषणसूची',
+'prefs-watchlist-days' => 'निरà¥\80à¤\95à¥\8dषणसूचीमध्ये दिसणाऱ्या दिवसांची संख्या:',
 'prefs-watchlist-days-max' => 'जास्तीत जास्त $1 {{PLURAL:$1|दिवस|दिवस}}',
-'prefs-watchlist-edits' => 'वाढà¥\80व à¤ªà¤¹à¤¾à¤±à¥\8dयाà¤\9aà¥\8dया सूचीमध्ये दिसणाऱ्या संपादनांची संख्या:',
+'prefs-watchlist-edits' => 'वाढà¥\80व à¤¨à¤¿à¤°à¥\80à¤\95à¥\8dषणसूचीमध्ये दिसणाऱ्या संपादनांची संख्या:',
 'prefs-watchlist-edits-max' => 'अधिकतम अंक:  १०००.',
-'prefs-watchlist-token' => 'पहाऱà¥\8dयाà¤\9aà¥\8dया सूचीचा बिल्ला:',
-'prefs-misc' => 'à¤\87तर',
+'prefs-watchlist-token' => 'निरà¥\80à¤\95à¥\8dषणसूचीचा बिल्ला:',
+'prefs-misc' => 'à¤\95िरà¤\95à¥\8bळ',
 'prefs-resetpass' => 'परवलीचा शब्द बदला.',
 'prefs-changeemail' => 'विपत्रपत्ता बदला',
 'prefs-setemail' => 'तुमचा ई-मेल पत्ता लिहा.',
@@ -1446,9 +1447,9 @@ $1",
 'stub-threshold' => '<a href="#" class="stub">अंकुरीत दुव्यांच्या</a> रचनेची नांदी (बाईट्स):',
 'stub-threshold-disabled' => 'अक्षम केले',
 'recentchangesdays' => 'अलीकडील बदल मधील दाखवावयाचे दिवस:',
-'recentchangesdays-max' => 'जास्तीतजास्त $1 {{PLURAL:$1|दिवस|दिवस}}',
-'recentchangescount' => 'à¤\85लà¥\80à¤\95डà¥\80ल à¤¬à¤¦à¤², à¤\87तिहास à¤µ à¤¨à¥\8bà¤\82द à¤ªà¤¾à¤¨à¤¾à¤\82मधà¥\8dयà¥\87 à¤¦à¤¾à¤\96वायाच्या संपादनांची संख्या:',
-'prefs-help-recentchangescount' => 'यात à¤¨à¥\81à¤\95तà¥\87à¤\9a à¤\9dालà¥\87लà¥\87 à¤¬à¤¦à¤², à¤ªà¤¾à¤¨à¤¾à¤\82à¤\9aà¥\87 à¤\87तिहास à¤µ à¤¯à¤¾à¤¦à¥\8dया या गोष्टी असतात.',
+'recentchangesdays-max' => 'जास्तीतजास्त $1 {{PLURAL:$1|दिवस}}',
+'recentchangescount' => 'à¤\85विà¤\9aलरितà¥\8dया à¤¦à¤¾à¤\96वावयाच्या संपादनांची संख्या:',
+'prefs-help-recentchangescount' => 'यात à¤¨à¥\81à¤\95तà¥\87à¤\9a à¤\9dालà¥\87लà¥\87 à¤¬à¤¦à¤², à¤ªà¤¾à¤¨à¤¾à¤\82à¤\9aà¥\87 à¤\87तिहास à¤µ à¤¨à¥\8bà¤\82दà¥\80 या गोष्टी असतात.',
 'prefs-help-watchlist-token2' => "ही आपल्या निरिक्षणसूचीच्या 'वेब फिड'ची गुप्त चाबी आहे.ज्या कोणास त्याची माहिती होईल तो आपली निरिक्षणसूची बघू शकेल,म्हणुन कोणास यात सहभागी करून घेउ नका.[[Special:ResetTokens|पुनर्स्थापनाची आपणास गरज असल्यास येथे टिचकी द्या]].",
 'savedprefs' => 'तुमच्या पसंती जतन केल्या आहेत.',
 'timezonelegend' => 'वेळक्षेत्र',
@@ -1477,7 +1478,7 @@ $1",
 'prefs-custom-css' => 'सीएसएस पद्धत बदला',
 'prefs-custom-js' => 'जावास्क्रिप्ट पद्धत बदला',
 'prefs-common-css-js' => 'मिळून वापरलेले सर्व त्वचांसाठींचे सीएसएस / जावास्क्रिप्ट:',
-'prefs-reset-intro' => 'à¤\86पन à¤¦à¥\8dदà¥\80लà¥\87लà¥\87 à¤¸à¤°à¥\8dव à¤ªà¥\8dरà¥\80फà¥\8dरà¥\8dनà¥\8dसà¥\87सà¥\8d à¤µà¤ªà¤°à¥\8dनà¥\8dयासथि à¤¤à¥\81मà¥\8dहà¥\80 à¤¹à¥\87 à¤ªà¥\87à¤\9cà¥\8d à¤µà¤¾à¤ªरू शकता.',
+'prefs-reset-intro' => 'à¤\86पण à¤¯à¤¾ à¤ªà¤¾à¤¨à¤¾à¤\9aा à¤µà¤¾à¤ªà¤°, à¤¯à¤¾ à¤¸à¤\82à¤\95à¥\87तसà¥\8dथळà¤\9aà¥\8dया à¤\85विà¤\9aलनà¥\81सार, à¤\86पला à¤ªà¤¸à¤\82तà¥\80à¤\95à¥\8dरम à¤ªà¥\81नरà¥\8dसà¥\8dथापनà¥\87साठà¥\80 à¤\95रू शकता.',
 'prefs-emailconfirm-label' => 'विपत्र निश्चितीकरण:',
 'youremail' => 'विपत्र:',
 'username' => '{{GENDER:$1|सदस्यनाम}}:',
@@ -1506,7 +1507,7 @@ $1",
 'prefs-info' => 'मूलभूत माहिती',
 'prefs-i18n' => 'आंतरराष्ट्रीयीकरण',
 'prefs-signature' => 'स्वाक्षरी',
-'prefs-dateformat' => 'तारà¥\80à¤\96 à¤°à¤\9aना',
+'prefs-dateformat' => 'दिनाà¤\82à¤\95 à¤ªà¥\8dरारà¥\81पण',
 'prefs-timeoffset' => 'वेळ बरोबरी',
 'prefs-advancedediting' => 'सर्वसामान्य पर्याय',
 'prefs-editor' => 'संपादक',
@@ -1593,7 +1594,7 @@ $1",
 'right-upload_by_url' => 'एखाद्या URL वरील संचिकेचे अपभारण करा',
 'right-purge' => 'एखाद्या पानाची सय रिकामी करा',
 'right-autoconfirmed' => 'आयपी आधारित दर-मर्यादेचा प्रभाव पडु देऊ नका.',
-'right-bot' => 'सà¥\8dवयà¤\82à¤\9aलित à¤\95ारà¥\8dयाप्रमाणे वागणूक मिळवा',
+'right-bot' => 'सà¥\8dवयà¤\82à¤\9aलित à¤ªà¥\8dरणालà¥\80प्रमाणे वागणूक मिळवा',
 'right-nominornewtalk' => 'चर्चा पृष्ठावर छोटी संपादने जी नवीन चर्चा दर्शवितात ती नकोत',
 'right-apihighlimits' => 'API पृच्छांमध्ये उच्चतर मर्यादा वापरा',
 'right-writeapi' => 'लेखन एपीआय चा उपयोग',
@@ -1616,7 +1617,7 @@ $1",
 'right-protect' => 'सुरक्षा पातळी बदलवा व निपात-प्रतिबंधित पानांचे संपादन करा',
 'right-editprotected' => ' "{{int:protect-level-sysop}}"म्हणून नमुद केलेली सुरक्षित पाने संपादा',
 'right-editsemiprotected' => '"{{int:protect-level-autoconfirmed}}" म्हणून नमुद केलेली सुरक्षित पाने संपादा',
-'right-editinterface' => 'सदस्य पसंती बदला',
+'right-editinterface' => 'सदस्य पसंतीक्रम बदला',
 'right-editusercssjs' => 'इतर सदस्यांच्या CSS व JS संचिका संपादित करा',
 'right-editusercss' => 'इतर सदस्यांच्या CSS संचिका संपादित करा',
 'right-edituserjs' => 'इतर सदस्यांच्या JS संचिका संपादित करा',
@@ -1706,6 +1707,7 @@ $1",
 'recentchanges-label-minor' => 'हे एक किरकोळ संपादन आहे',
 'recentchanges-label-bot' => 'हे संपादन एका सांगकाम्याकडून केले गेले आहे',
 'recentchanges-label-unpatrolled' => 'हे संपादन अजून तपासल्या गेले नाही',
+'recentchanges-legend-newpage' => '$1 - नवीन पान',
 'rcnote' => "खाली $4, $5 पर्यंतचे गेल्या {{PLURAL:$2|'''१''' दिवसातील|'''$2''' दिवसांतील}} {{PLURAL:$1|शेवटचा '''1''' बदल|शेवटचे '''$1''' बदल}} दिलेले आहेत.",
 'rcnotefrom' => "खाली <b>$2</b> पासूनचे ('''$1''' पर्यंत) बदल दाखविले आहेत.",
 'rclistfrom' => '$1 नंतर केले गेलेले बदल दाखवा.',
@@ -3099,6 +3101,8 @@ $1',
 'spam_reverting' => '$1शी दुवे नसलेल्या गेल्या आवर्तनाकडे परत उलटवत आहे',
 'spam_blanking' => '$1शी दुवे असलेली सर्व आवर्तने,रिक्त केली जात आहेत',
 'spam_deleting' => 'यातील सर्व आवृत्त्यांचे $1शी दुवे आहेत.गाळत आहे',
+'simpleantispam-label' => "चिखलणी विरोधक तपासणी.
+हे भरू '''नका'''!",
 
 # Info page
 'pageinfo-title' => '"$1" च्याबद्दल माहिती',
@@ -3668,7 +3672,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'बाहेरील संगणक प्रणाली वापरून ही संचिका संपादित करा.',
-'edit-externally-help' => 'अधिक माहितीसाठी  [//www.mediawiki.org/wiki/Manual:External_editors स्थापन करण्याच्या सूचना] येथे पहा.',
+'edit-externally-help' => 'अधिक माहितीसाठी  [https://www.mediawiki.org/wiki/Manual:External_editors स्थापन करण्याच्या सूचना] येथे पहा.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'सर्व',
@@ -3844,7 +3848,7 @@ $5
 'version-hook-subscribedby' => 'वर्गणीदार',
 'version-version' => '(आवृत्ती $1)',
 'version-license' => 'परवाना',
-'version-poweredby-credits' => "हा विकी '''[//www.mediawiki.org/ मीडियाविकी]'''द्वारे संचालित आहे, प्रताधिकारित © २००१-$1 $2.",
+'version-poweredby-credits' => "हा विकी '''[https://www.mediawiki.org/ मीडियाविकी]'''द्वारे संचालित आहे, प्रताधिकारित © २००१-$1 $2.",
 'version-poweredby-others' => 'इतर',
 'version-poweredby-translators' => 'ट्रांसलेटविकि.नेट वरील भाषांतरकार',
 'version-credits-summary' => 'आम्ही खालील व्यक्तींना, [[Special:Version|मिडियाविकि]]वर त्यांनी दिलेल्या योगदानामुळे, मान्यता देऊ ईच्छितो.',
@@ -4088,4 +4092,20 @@ $5
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|बाइट|बाइट्स}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|बाइट|बाइट्स}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'साचे वाढवा',
+'expand_templates_intro' => 'हे पान काही मजकूर घेऊन त्यातिल सर्व साचे वाढविते. तसेच हे पान पार्सर फंक्शन्स जसे की
+<nowiki>{{</nowiki>#language:...}}, व बदलणार्‍या किमती (variables) जसे की
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;म्हणजेच दोन ब्रेसेसमधील सर्व मजकूर वाढविते.
+मीडियाविकिमधून पार्सर स्टेज मागवून हे केले जाते.',
+'expand_templates_title' => '{{FULLPAGENAME}} वगैरे करीता, कन्टेक्स्ट शीर्षक:',
+'expand_templates_input' => 'इनपुट मजकूर:',
+'expand_templates_output' => 'निकाल',
+'expand_templates_xml_output' => 'XML चे आऊटपुट',
+'expand_templates_ok' => 'ठिक आहे',
+'expand_templates_remove_comments' => 'शेरा हटवा',
+'expand_templates_remove_nowiki' => 'निकालात <nowiki>खूणपतका दाखवू नका',
+'expand_templates_generate_xml' => 'XML चा पार्स (parse) वृक्ष दाखवा',
+'expand_templates_preview' => 'झलक',
+
 );
index b1aa125..817ddd3 100644 (file)
@@ -111,7 +111,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Laman_lapuk' ),
        'Blankpage'                 => array( 'Laman_kosong' ),
        'Block'                     => array( 'Sekat_IP' ),
-       'Blockme'                   => array( 'Sekat_saya' ),
        'Booksources'               => array( 'Sumber_buku' ),
        'BrokenRedirects'           => array( 'Lencongan_rosak', 'Pelencongan_rosak' ),
        'Categories'                => array( 'Kategori' ),
@@ -123,9 +122,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Buka_akaun' ),
        'Deadendpages'              => array( 'Laman_buntu' ),
        'DeletedContributions'      => array( 'Sumbangan_dihapuskan' ),
-       'Disambiguations'           => array( 'Penyahtaksaan', 'Nyahkekaburan' ),
        'DoubleRedirects'           => array( 'Lencongan_berganda', 'Pelencongan_berganda' ),
        'Emailuser'                 => array( 'E-mel_pengguna' ),
+       'ExpandTemplates'           => array( 'Kembangkan_templat' ),
        'Export'                    => array( 'Eksport' ),
        'Fewestrevisions'           => array( 'Semakan_tersikit' ),
        'FileDuplicateSearch'       => array( 'Cari_fail_berganda' ),
@@ -338,8 +337,6 @@ $messages = array(
 'noindex-category' => 'Laman tak diindeks',
 'broken-file-category' => 'Laman yang ada pautan fail yang terputus',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Perihal',
 'article' => 'Laman kandungan',
 'newwindow' => '(dibuka di tetingkap baru)',
@@ -476,8 +473,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Diambil daripada "$1"',
 'youhavenewmessages' => 'Anda mempunyai $1 ($2).',
-'newmessageslink' => 'pesanan baru',
-'newmessagesdifflink' => 'perubahan terakhir',
 'youhavenewmessagesfromusers' => 'Anda menerima $1 daripada {{PLURAL:$3|seorang|$3 orang}} pengguna lain ($2).',
 'youhavenewmessagesmanyusers' => 'Anda menerima $1 daripada ramai pengguna ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|pesanan|pesanan-pesanan}} baru',
@@ -1316,8 +1311,6 @@ Cuba berikan awalan ''all:'' untuk mencari semua kandungan (termasuk laman perbi
 'preferences' => 'Keutamaan',
 'mypreferences' => 'Keutamaan',
 'prefs-edits' => 'Jumlah suntingan:',
-'prefsnologin' => 'Belum log masuk',
-'prefsnologintext' => 'Anda hendaklah <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} log masuk]</span> terlebih dahulu untuk menetapkan keutamaan.',
 'changepassword' => 'Tukar kata laluan',
 'prefs-skin' => 'Rupa',
 'skin-preview' => 'Pralihat',
@@ -1615,6 +1608,7 @@ Tindakan ini tidak boleh dibatalkan.',
 'recentchanges-label-minor' => 'Ini ialah suntingan kecil',
 'recentchanges-label-bot' => 'Suntingan ini dilakukan oleh bot',
 'recentchanges-label-unpatrolled' => 'Suntingan ini belum dirondai',
+'recentchanges-legend-newpage' => '$1 - laman baru',
 'rcnote' => "Yang berikut ialah '''$1''' perubahan terakhir sejak '''$2''' hari yang lalu sehingga $5, $4.",
 'rcnotefrom' => 'Yang berikut ialah semua perubahan sejak <b>$2</b> (sehingga <b>$1</b>).',
 'rclistfrom' => 'Papar perubahan sejak $1',
@@ -2858,7 +2852,7 @@ Dalam pilihan kedua tadi, anda juga boleh menggunakan pautan, umpamanya [[{{#Spe
 'allmessagesdefault' => 'Teks mesej asal',
 'allmessagescurrent' => 'Teks pesanan semasa',
 'allmessagestext' => 'Ini ialah senarai pesanan sistem yang terdapat dalam ruang nama MediaWiki.
-Sila lawat [//www.mediawiki.org/wiki/Localisation Penyetempatan MediaWiki] dan [//translatewiki.net translatewiki.net] sekiranya anda mahu menyumbang dalam menyetempatkan dan menterjemah perisian MediaWiki.',
+Sila lawat [https://www.mediawiki.org/wiki/Localisation Penyetempatan MediaWiki] dan [//translatewiki.net translatewiki.net] sekiranya anda mahu menyumbang dalam menyetempatkan dan menterjemah perisian MediaWiki.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' tidak boleh digunakan kerana '''\$wgUseDatabaseMessages''' dipadamkan.",
 'allmessages-filter-legend' => 'Penapisan',
 'allmessages-filter' => 'Tapis berdasarkan keadaan penempahan:',
@@ -3050,6 +3044,7 @@ Simpan dalam komputer anda dan muat naiknya di sini.',
 'spam_reverting' => 'Membalikkan kepada versi terakhir yang tidak mengandungi pautan ke $1',
 'spam_blanking' => 'Mengosongkan semua semakan yang mengandungi pautan ke $1',
 'spam_deleting' => 'Menghapuskan semua semakan yang mengandungi pautan ke $1',
+'simpleantispam-label' => "Pemeriksaan anti-spam. '''JANGAN''' isi ruangan ini!",
 
 # Info page
 'pageinfo-title' => 'Maklumat untuk "$1"',
@@ -3619,7 +3614,7 @@ Ruangan-ruangan yang lain pula akan disembunyikan pada asali.
 
 # External editor support
 'edit-externally' => 'Sunting fail ini menggunakan perisian luar',
-'edit-externally-help' => '(Lihat [//www.mediawiki.org/wiki/Manual:External_editors arahan pemasangan] untuk maklumat lanjut)',
+'edit-externally-help' => '(Lihat [https://www.mediawiki.org/wiki/Manual:External_editors arahan pemasangan] untuk maklumat lanjut)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'semua',
@@ -3810,7 +3805,7 @@ Anda juga boleh [[Special:EditWatchlist|menggunakan penyunting piawai]].',
 'version-hook-subscribedby' => 'Dilanggan oleh',
 'version-version' => '(Versi $1)',
 'version-license' => 'Lesen',
-'version-poweredby-credits' => "Wiki ini dikuasakan oleh '''[//www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki ini dikuasakan oleh '''[https://www.mediawiki.org/ MediaWiki]''', hak cipta © 2001-$1 $2.",
 'version-poweredby-others' => 'penyumbang-penyumbang lain',
 'version-poweredby-translators' => 'para penterjemah translatewiki.net',
 'version-credits-summary' => 'Kami ingin mengucapkan sekalung budi kepada mereka yang berikut atas sumbangan mereka keada [[Special:Version|MediaWiki]].',
@@ -3853,8 +3848,7 @@ Anda patut telah menerima [{{SERVER}}{{SCRIPTPATH}}/COPYING sebuah salinan bagi
 
 # Special:SpecialPages
 'specialpages' => 'Laman khas',
-'specialpages-note' => '----
-* Laman khas biasa.
+'specialpages-note' => '* Laman khas biasa.
 * <span class="mw-specialpagerestricted">Laman khas terhad.</span>
 * <span class="mw-specialpagecached">Laman khas tercache (mungkin lapuk).</span>',
 'specialpages-group-maintenance' => 'Laporan penyenggaraan',
@@ -4066,4 +4060,21 @@ Ataupun, anda boleh menggunakan borang yang mudah di bawah. Ulasan anda akan dic
 'limitreport-expansiondepth' => 'Kedalaman peluasan terjauh',
 'limitreport-expensivefunctioncount' => 'Kiraan fungsi penghurai muatan tinggi',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Kembangkan templat',
+'expand_templates_intro' => 'Halaman khas ini mengambil teks dan mengembangkan semua templat di dalamnya secara rekursif.
+Ia juga mengembangkan fungsi-fungsi penghurai seperti
+<code><nowiki>{{</nowiki>#language:…}}</code>, dan pembolehubah-pembolehubah seperti
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Sebenarnya, ia mengembangkan segalanya dalam tanda kurung panah berganda.',
+'expand_templates_title' => 'Tajuk konteks, untuk {{FULLPAGENAME}} dan sebagainya:',
+'expand_templates_input' => 'Teks input:',
+'expand_templates_output' => 'Hasil',
+'expand_templates_xml_output' => 'Output XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Buang ulasan',
+'expand_templates_remove_nowiki' => 'Sekat tag <nowiki> dalam hasil',
+'expand_templates_generate_xml' => 'Papar pepohon hurai XML',
+'expand_templates_preview' => 'Pralihat',
+
 );
index 6bec1c6..b8d1705 100644 (file)
@@ -56,7 +56,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'TitluĦażin' ),
        'Blankpage'                 => array( 'PaġnaVojta' ),
        'Block'                     => array( 'BlokkaIP' ),
-       'Blockme'                   => array( 'Imblukkani' ),
        'Booksources'               => array( 'SorsiKotba' ),
        'BrokenRedirects'           => array( 'RindirizziMiksura' ),
        'Categories'                => array( 'Kategoriji' ),
@@ -67,9 +66,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'OħloqKont' ),
        'Deadendpages'              => array( 'PaġniWieqfa' ),
        'DeletedContributions'      => array( 'KontribuzzjonijietImħassra' ),
-       'Disambiguations'           => array( 'Diżambigwazzjoni' ),
        'DoubleRedirects'           => array( 'RindirizziDoppji' ),
        'Emailuser'                 => array( 'IbgħatUtent' ),
+       'ExpandTemplates'           => array( 'EspandiMudelli' ),
        'Export'                    => array( 'Esporta' ),
        'Fewestrevisions'           => array( 'L-InqasReviżjonijiet' ),
        'FileDuplicateSearch'       => array( 'FittexFajlDuplikat' ),
@@ -271,6 +270,8 @@ $magicWords = array(
        'formatdate'                => array( '0', 'formatdata', 'dataformat', 'formatdate', 'dateformat' ),
 );
 
+$linkPrefixCharset = 'A-\\x{10ffff}';
+
 $messages = array(
 # User preference toggles
 'tog-underline' => 'Ħoloq sottolinjati:',
@@ -411,8 +412,6 @@ $messages = array(
 'noindex-category' => 'Paġni mhux indiċizzati',
 'broken-file-category' => "Paġni b'ħoloq lejn fajls miksura",
 
-'linkprefix' => '/^(.*?)([a-żA-Ż\\x80-\\xff]+)$/sD',
-
 'about' => 'Dwar',
 'article' => 'artiklu',
 'newwindow' => "(tinfetaħ f'tieqa ġdida)",
@@ -546,8 +545,6 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Miġjub minn "$1"',
 'youhavenewmessages' => 'Għandek $1 ($2).',
-'newmessageslink' => 'messaġġi ġodda',
-'newmessagesdifflink' => 'l-aħħar bidla',
 'youhavenewmessagesmanyusers' => 'Għandek $1 mingħand ħafna utenti ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|messaġġ ġdid|messaġġi ġodda}}',
 'newmessagesdifflinkplural' => 'l-aħħar {{PLURAL:$1|bidla|bidliet}}',
@@ -1318,8 +1315,6 @@ Innota però li l-werreja tal-kontenut ta' {{SITENAME}} f'dawn is-siti, jistgħu
 'preferences' => 'Preferenzi',
 'mypreferences' => 'Preferenzi',
 'prefs-edits' => "Numru ta' modifiki:",
-'prefsnologin' => 'Għadek ma dħaltx ġewwa',
-'prefsnologintext' => 'Sabiex tkun tista\' tippersonalizza l-preferenzi huwa neċessarju li tidħol fil-<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kont]</span>.',
 'changepassword' => 'Ibdel il-password',
 'prefs-skin' => 'Aspett grafiku (skin)',
 'skin-preview' => 'dehra proviżorja',
@@ -1591,6 +1586,7 @@ Innota però li l-werreja tal-kontenut ta' {{SITENAME}} f'dawn is-siti, jistgħu
 'recentchanges-label-minor' => 'Din hi modifika minuri',
 'recentchanges-label-bot' => 'Din il-modifika ġiet effettwata minn bot',
 'recentchanges-label-unpatrolled' => 'Din il-modifika għadha ma ġietx verifikata',
+'recentchanges-legend-newpage' => '$1 - paġna ġdida',
 'rcnote' => "Hawn taħt {{PLURAL:$1|tinsab l-aktar modifika riċenti|jinsabu l-'''$1''' modifiki riċenti}} għas-sit fl-aħħar {{PLURAL:$2|24 siegħa|'''$2''' ġranet}}, id-dati ġew aġġornati fil-$5 ta' $4.",
 'rcnotefrom' => "Ħawn taħt jinsabu l-modifiki minn '''$2''' (sa '''$1''').",
 'rclistfrom' => 'Uri l-modifiki ġodda jibdew minn $1',
@@ -3466,7 +3462,7 @@ Oħrajn jiġu moħbija kif inhu definit oriġinarjament.
 
 # External editor support
 'edit-externally' => "Immodifika dan il-fajl b'użu ta' applikazzjoni esterna",
-'edit-externally-help' => '(Għal aktar informazzjoni ara l-[//www.mediawiki.org/wiki/Manual:External_editors istruzzjonijiet])',
+'edit-externally-help' => '(Għal aktar informazzjoni ara l-[https://www.mediawiki.org/wiki/Manual:External_editors istruzzjonijiet])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kollha',
@@ -3666,7 +3662,7 @@ Inti tista' wkoll tuża' l-[[Special:EditWatchlist|editur bl-interfaċċa standa
 'version-hook-subscribedby' => 'Reġistrat minn',
 'version-version' => '(Verżjoni $1)',
 'version-license' => 'Liċenzja',
-'version-poweredby-credits' => "Din il-wiki hija operata minn '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Din il-wiki hija operata minn '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'oħrajn',
 'version-license-info' => "MediaWiki huwa softwer b'xejn; inti tista' tqassmu mill-ġdid u/jew timmodifikah taħt it-termini tal-GNU General Public License, kif ippubblikata mill-Free Software Foundation; jew it-2 verżjoni tal-Liċenzja, jew (skont l-għażla tiegħek) kwalunkwe verżjoni suċċessiva.
 
@@ -3842,4 +3838,21 @@ Flimkien ma' dan il-programm suppost kellek tirċievi [{{SERVER}}{{SCRIPTPATH}}/
 'duration-centuries' => '$1 {{PLURAL:$1|seklu|sekli}}',
 'duration-millennia' => '$1 {{PLURAL:$1|millennju|millennji}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espandi l-mudelli',
+'expand_templates_intro' => "!Din il-paġna speċjali tieħu test u tkabbar il-mudelli kollha preżenti.
+Barra minn hekk, din tikkalkola r-riżultat tal-funzjonijiet ''parser'' bħal
+<code><nowiki>{{</nowiki>#language:…}}</code>, u varjabbli bħal
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Fil-fatt, din tespandi kważi dak kollu bejn żewġ parentesi.",
+'expand_templates_title' => 'Kuntest (għal {{FULLPAGENAME}} etċ.):',
+'expand_templates_input' => "Test ta' ''input'':",
+'expand_templates_output' => 'Riżultat',
+'expand_templates_xml_output' => "Riżultat f'format XML",
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Neħħi l-kummenti',
+'expand_templates_remove_nowiki' => "Ħassar it-''tags'' <nowiki> fir-riżultat",
+'expand_templates_generate_xml' => 'Uri siġra sintattika XML',
+'expand_templates_preview' => 'Dehra proviżorja',
+
 );
index 3fe13d1..a7a7ce7 100644 (file)
@@ -246,7 +246,7 @@ $messages = array(
 'articlepage' => 'Ber páigina de cuntenido',
 'talk' => 'Çcusson',
 'views' => 'Besitas',
-'toolbox' => 'Caixa de Ferramientas',
+'toolbox' => 'Ferramientas',
 'userpage' => 'Ber páigina de outelizador',
 'imagepage' => 'Ber páigina de fexeiro',
 'mediawikipage' => 'Ber páigina de mensaiges',
@@ -288,8 +288,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Sacado an "$1"',
 'youhavenewmessages' => 'Tu tenes $1 ($2).',
-'newmessageslink' => 'nuobas mensaiges',
-'newmessagesdifflink' => 'redadeira altaraçon',
 'youhavenewmessagesmulti' => 'Tenes nuobas mensaiges an $1',
 'editsection' => 'eiditar',
 'editold' => 'eiditar',
@@ -653,6 +651,7 @@ Causo l çponiblizes, este será outelizado pa te dar crédito pul tou trabalho.
 'recentchanges' => 'Redadeiras altaraçones',
 'recentchanges-legend' => 'Oupçones de las redadeiras altaraçones',
 'recentchanges-feed-description' => 'Acumpanha las redadeiras altaraçones de l biqui por esta semiente.',
+'recentchanges-legend-newpage' => '$1 - nuoba páigina',
 'rcnote' => "A seguir {{PLURAL:$1|stá listada '''ua''' altaraçon feita|stan '''$1''' altaraçones feitas}} {{PLURAL:$2|ne l redadeiro die|ne ls redadeiros '''$2''' dies}}, a partir de las $5 de $4.",
 'rcnotefrom' => 'Alteraçones feitas zde <b>$2</b> (amostradas até <b>$1</b>).',
 'rclistfrom' => 'Amostrar las noubas altaraçones a partir de $1',
@@ -1153,7 +1152,7 @@ Causo l fexeiro tenga sido demudado a partir de l sou stado oureginal, alguns de
 
 # External editor support
 'edit-externally' => 'Eiditar este fexeiro outelizando ua aplicaçon sterna',
-'edit-externally-help' => '(Bei las [//www.mediawiki.org/wiki/Manual:External_editors anstruçones de anstalaçon] pa mais anformaçon).',
+'edit-externally-help' => '(Bei las [https://www.mediawiki.org/wiki/Manual:External_editors anstruçones de anstalaçon] pa mais anformaçon).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todas',
index 4edacf7..a5c791a 100644 (file)
@@ -186,11 +186,11 @@ $messages = array(
 'hidden-categories' => '{{PLURAL:$1|ဝှက်ထားသော ကဏ္ဍ|ဝှက်ထားသော ကဏ္ဍများ}}',
 'hidden-category-category' => 'ဝှက်ထားသော ကဏ္ဍများ',
 'category-subcat-count' => '{{PLURAL:$2|ဤကဏ္ဍတွင် အောက်ပါ ကဏ္ဍခွဲသာ ရှိသည်။ |ဤကဏ္ဍတွင် စုစုပေါင်း $2 ခု အနက်မှ အောက်ပါ {{PLURAL:$1|ကဏ္ဍခွဲ|ကဏ္ဍခွဲ $1 ခု}} ရှိသည်။}}',
-'category-subcat-count-limited' => 'ဤကဏ္ဍတွင် အောက်ပါ {PLURAL:$1|ကဏ္ဍခွဲ|$1 ကဏ္ဍခွဲများ}} ရှိသည်။',
+'category-subcat-count-limited' => 'ဤကဏ္ဍတွင် အောက်ပါ {{PLURAL:$1|ကဏ္ဍခွဲ|$1 ကဏ္ဍခွဲများ}} ရှိသည်။',
 'category-article-count' => '{{PLURAL:$2|ဤကဏ္ဍတွင် အောက်ပါစာမျက်နှာသာ ရှိသည်။|စုစုပေါင်း $2 အနက်မှ အောက်ပါ {{PLURAL:$1|စာမျက်နှာသည်|စာမျက်နှာ $1 ခုသည်}} ဤကဏ္ဍတွင် ရှိသည်။}}',
 'category-article-count-limited' => 'အောက်ပါ{{PLURAL:$1|စာမျက်နှာ|$1 စာမျက်နှာများ}} သည် လက်ရှိကဏ္ဍတွင် ရှိသည်။',
 'category-file-count' => '{{PLURAL:$2|ဤကဏ္ဍတွင် အောက်ပါဖိုင်သာ ရှိသည်။|စုစုပေါင်း $2 အနက်မှ အောက်ပါ {{PLURAL:$1|ဖိုင် သည်|ဖိုင် $1 ခုသည်}} ဤကဏ္ဍတွင် ရှိသည်။}}',
-'category-file-count-limited' => 'အောက်ပါ {PLURAL:$1|စာမျက်နှာ|$1 စာမျက်နှာများ}} သည် လက်ရှိစာမျက်နှာတွင် ရှိသည်။',
+'category-file-count-limited' => 'အောက်ပါ {{PLURAL:$1|စာမျက်နှာ|$1 စာမျက်နှာများ}} သည် လက်ရှိစာမျက်နှာတွင် ရှိသည်။',
 'listingcontinuesabbrev' => 'ပံ့ပိုး',
 'index-category' => 'အက္ခရာစဉ် စာမျက်နှာများ',
 'noindex-category' => 'အက္ခရာစဉ် စာမျက်နှာများမရှိ',
@@ -325,8 +325,6 @@ $1',
 'ok' => 'အိုကေ',
 'retrievedfrom' => '"$1" မှ ရယူရန်',
 'youhavenewmessages' => 'သင့်တွင် $1 ($2) ရှိသည်။',
-'newmessageslink' => 'မက်ဆေ့ အသစ်',
-'newmessagesdifflink' => 'နောက်ဆုံးအပြောင်းအလဲ',
 'youhavenewmessagesmulti' => '$1 မှာ မက်ဆေ့အသစ်များ ရှိသည်',
 'editsection' => 'ပြင်​ဆင်​ရန်​',
 'editold' => 'ပြင်​ဆင်​ရန်​',
@@ -735,7 +733,6 @@ Try prefixing your query with ''all:'' to search all content (including talk pag
 'preferences' => '​ရွေး​ချယ်​စ​ရာ​များ​',
 'mypreferences' => '​ရွေး​ချယ်​စ​ရာ​များ​',
 'prefs-edits' => 'တည်းဖြတ်မှုအရေအတွက် -',
-'prefsnologin' => 'logged in ဝင်မထားပါ',
 'changepassword' => 'စကားဝှက် ပြောင်းရန်',
 'prefs-skin' => 'အသွင်အပြင်',
 'skin-preview' => 'နမူနာ',
@@ -1783,7 +1780,7 @@ Your e-mail address is not revealed when other users contact you.
 
 # External editor support
 'edit-externally' => 'ပြင်ပ application တစ်ခုခုကိုသုံး၍ ဤဖိုင်ကို ပြင်ရန်',
-'edit-externally-help' => '(နောက်ထပ်သတင်းအချက်အလက်များအတွက်[//www.mediawiki.org/wiki/Manual:External_editors တပ်ဆင်မှု လမ်းညွှန်များ] ကို ကြည့်ရန်)',
+'edit-externally-help' => '(နောက်ထပ်သတင်းအချက်အလက်များအတွက်[https://www.mediawiki.org/wiki/Manual:External_editors တပ်ဆင်မှု လမ်းညွှန်များ] ကို ကြည့်ရန်)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'အားလုံး',
index e24ad45..4cffa42 100644 (file)
@@ -49,7 +49,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'ТюштяПингеньЛопат' ),
        'Blankpage'                 => array( 'ЧавоЛопа' ),
        'Block'                     => array( 'СаймасСаемсIP' ),
-       'Blockme'                   => array( 'СаймасСаемизь' ),
        'Booksources'               => array( 'КнигаЛисьмапрят' ),
        'BrokenRedirects'           => array( 'СинденьЛиявНевтемат' ),
        'Categories'                => array( 'Категорият' ),
@@ -58,6 +57,7 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ТеемсШкамсСовамоТарка' ),
        'Deadendpages'              => array( 'ЛисемаСюлмавомаПевтемеЛопат' ),
        'DoubleRedirects'           => array( 'КавтоньКирданьЛиявНевтемат' ),
+       'ExpandTemplates'           => array( 'ПоладомсЛопаПарцунт' ),
        'Export'                    => array( 'Экспортировамс' ),
        'Fewestrevisions'           => array( 'ВесемедеАламокстьЛиякстомтозь' ),
        'Filepath'                  => array( 'ФайланьКи' ),
@@ -152,7 +152,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'куншкасо', 'центр', 'center', 'centre' ),
        'img_framed'                => array( '1', 'кундсо', 'обрамить', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'кундовтомо', 'безрамки', 'frameless' ),
-       'img_page'                  => array( '1', 'лопа=$1', 'лопа $1', 'страница=$1', 'страница $1', 'страница $1', 'page=$1', 'page $1' ),
+       'img_page'                  => array( '1', 'лопа=$1', 'лопа_$1', 'страница=$1', 'страница_$1', 'страница $1', 'page=$1', 'page $1' ),
        'img_top'                   => array( '1', 'верькс', 'сверху', 'top' ),
        'img_text_top'              => array( '1', 'текст-верькс', 'текст-сверху', 'text-top' ),
        'img_middle'                => array( '1', 'куншка', 'посередине', 'middle' ),
@@ -193,13 +193,13 @@ $messages = array(
 'tog-hidepatrolled' => 'Кекшемс лувонь кирдиень витнеметнень-петнематнень чыяконь полавтнематнестэ',
 'tog-newpageshidepatrolled' => 'Кекшемс лувонь кирдиень ванстома лопатнень од лопань керьксэнть эйстэ',
 'tog-extendwatchlist' => 'Келейгавтомс сёрмадовксонь мельга ваномань сёрмалевксэнть невтевест весе полавтнематне, аволь ансяк чыеньсетне.',
-'tog-usenewrc' => 'Ð\9fÑ\83Ñ\80намÑ\81 Ð»Ð¸Ñ\8fкÑ\81Ñ\82омÑ\82омаÑ\82 Ð»Ð¾Ð¿Ð°Ð½Ñ\8c ÐºÐ¾Ñ\80Ñ\8fÑ\81 ÐºÑ\83Ñ\80онÑ\8c-кÑ\83Ñ\80онÑ\8c Ñ\87иенÑ\8c Ð¿Ð¾Ð»Ð°Ð²Ñ\82немаÑ\82неÑ\81Ñ\8d-ванома Ð»ÐµÐ¼Ñ\80иÑ\81Ñ\8cмеÑ\82неÑ\81Ñ\8d  (веÑ\88и JavaScript)',
-'tog-numberheadings' => 'Сёрмадовкс коняксос кадык сынсь ловома валтнэ путовить',
-'tog-showtoolbar' => 'Ð\9aедÑ\8cÑ\91нкÑ\81 Ð»Ð°Ð·Ð½Ñ\8dнÑ\82Ñ\8c Ð½ÐµÐ²Ñ\82емÑ\81 Ñ\81Ñ\91Ñ\80мадома Ñ\88каÑ\81Ñ\82о (JavaScript)',
-'tog-editondblclick' => 'Кавксть лепштязь совамс сёрмадовксонь витнеме-петнеме (JavaScript)',
+'tog-usenewrc' => 'Ð\9fÑ\83Ñ\80намÑ\81 Ð»Ð¸Ñ\8fкÑ\81Ñ\82омÑ\82омаÑ\82 Ð»Ð¾Ð¿Ð°Ð½Ñ\8c ÐºÐ¾Ñ\80Ñ\8fÑ\81 ÐºÑ\83Ñ\80онÑ\8c-кÑ\83Ñ\80онÑ\8c Ñ\87иенÑ\8c Ð¿Ð¾Ð»Ð°Ð²Ñ\82немаÑ\82неÑ\81Ñ\82Ñ\8d-ванома Ð»ÐµÐ¼Ñ\80иÑ\81Ñ\8cмеÑ\82неÑ\81Ñ\82Ñ\8d',
+'tog-numberheadings' => 'Сёрмадовксконяксос кадык сынсь ловома валтнэ путовить',
+'tog-showtoolbar' => 'Ð\9dевÑ\82емÑ\81 ÐºÐµÐ´Ñ\8cÑ\91нкÑ\81лазнÑ\8dнÑ\82Ñ\8c Ñ\81Ñ\91Ñ\80мадома Ñ\88каÑ\81Ñ\82о',
+'tog-editondblclick' => 'Кавксть лепштязь совамс сёрмадовксонь витнеме-петнеме',
 'tog-editsection' => 'Невтемс сюлмавома пенть «витемс» эрьва секциянтень-пельксэнтень',
-'tog-editsectiononrightclick' => 'Витнемс секциятнень-пелькстнэнь, лепштямс сёрмадовксонть лемензэ лангс чэерень витьёнсе повнэсэ  (JavaScript)',
-'tog-showtoc' => 'Невтемс сёрмадовкс потмокс (лопатненень, конатнесэ 3-до ламо сёрмадовкст)',
+'tog-editsectiononrightclick' => 'Витнемс секциятнень-пелькстнэнь, лепштямс сёрмадовксонть лемензэ лангс чеерень витьёнсе повнесэ',
+'tog-showtoc' => 'Невтемс сёрмадовкспотмокс (лопатненень, конатнесэ 3-до ламо сёрмадовкст)',
 'tog-rememberpassword' => 'Ледстемс совамо валом те бравзерсэнть (сех кувать $1 {{PLURAL:$1|чи|чить}})',
 'tog-watchcreations' => 'Совавтомс ванома лемрисьмезэнь монь теевть лопатнень ды сень, мезе йовкстан',
 'tog-watchdefault' => 'Совавтомс монь витевть лопатнень ванома лемрисьмезэнь',
@@ -216,7 +216,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Невтемс зяро теицятнеде, конат аравтызь лопанть эсест ванома лемрисьментень',
 'tog-oldsig' => 'Уликс кедьпутовксось:',
 'tog-fancysig' => 'Лемпутовксось прок викитекст (сонсь теевиця сюлмавома певтеме)',
-'tog-uselivepreview' => 'Максомс эряй васнянь невтевкс (JavaScript) (Варчамонь)',
+'tog-uselivepreview' => 'Максомс эриця васнянь невтевкс (варчамонь сон)',
 'tog-forceeditsummary' => 'Невтик монень, мезе сёрмадомс витнемадо-петнемадо ёвтамонь вальминентень',
 'tog-watchlisthideown' => 'Кекшить монь теевть витневкстнэнь ванома лемрисьменть эйстэ',
 'tog-watchlisthidebots' => 'Кекшить бот витневкстнэнь-петневкстнэнь ванома лемрисьсенть эйстэ',
@@ -290,6 +290,18 @@ $messages = array(
 'oct' => 'Ожо',
 'nov' => 'Сун',
 'dec' => 'Аца',
+'january-date' => 'Якшамков $1',
+'february-date' => 'Даволков $1',
+'march-date' => 'Эйзюрков $1',
+'april-date' => 'Чадыков $1',
+'may-date' => 'Панжиков $1',
+'june-date' => 'Аштемков $1',
+'july-date' => 'Медьков $1',
+'august-date' => 'Умарьков $1',
+'september-date' => 'Таштамков $1',
+'october-date' => 'Ожоков $1',
+'november-date' => 'Сундерьков $1',
+'december-date' => 'Ацамков $1',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Категория|Категорият}}',
@@ -315,6 +327,7 @@ $messages = array(
 'newwindow' => '(панжови од вальмасо)',
 'cancel' => 'Саемс мекев',
 'moredotdotdot' => 'Седе ламо...',
+'morenotlisted' => 'Те лемрисьмесь апак прядо.',
 'mypage' => 'Монь лопам',
 'mytalk' => 'Кортнемам',
 'anontalk' => 'Кортамс те IP-нть марто',
@@ -368,7 +381,9 @@ $messages = array(
 'create-this-page' => 'Теик-шкик те лопанть',
 'delete' => 'Нардамс',
 'deletethispage' => 'Нардамс те лопанть',
+'undeletethispage' => 'Вельмевтемс мекев те лопанть',
 'undelete_short' => 'Велявтомс нардазенть {{PLURAL:$1|вейке витнема-петнема|$1 витнемат-петнемат}}',
+'viewdeleted_short' => 'Ваномс {{PLURAL:$1|нардазь вейке витнема-петнема|нардазь $1 витнемат-петнемат}}',
 'protect' => 'Аравтомс прянь ванстомас',
 'protect_change' => 'полавтомс',
 'protectthispage' => 'Аравтомс те лопанть ванстомас',
@@ -383,7 +398,7 @@ $messages = array(
 'articlepage' => 'Ваномс потмокслопанть',
 'talk' => 'Кортнеме',
 'views' => 'Ваномкат',
-'toolbox' => 'Кедьёнкс парго',
+'toolbox' => 'Кедьёнкст',
 'userpage' => 'Ваномонзо кирдицянть лопанзо',
 'projectpage' => 'Ваномонзо проектенть лопанть',
 'imagepage' => 'Ваномс файлань лопанть',
@@ -400,13 +415,18 @@ $messages = array(
 'protectedpage' => 'Те лопась ванстомасо',
 'jumpto' => 'Тёкадемс тей:',
 'jumptonavigation' => 'Новигациясь-лездамось',
-'jumptosearch' => 'вешнэме',
+'jumptosearch' => 'вешнеме',
+'view-pool-error' => 'Кежеть иляст са, сервертнень виест а сатыть ней.
+Пекень пек ламо теицят стараить ваномс те лопанть.
+Учокая аламос, мейле одов варчасак тезэнь совамонть.
+$1',
+'pool-queuefull' => 'Процесспулось пешксе',
 'pool-errorunknown' => 'Апак содань ильведькс',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}} ланга',
 'aboutpage' => 'Project:Эстэдензэ',
-'copyright' => '$1-сто муят мезе тесэ.',
+'copyright' => '$1-сто муят мезе тесэ, бути лиякс апак ёвта.',
 'copyrightpage' => '{{ns:project}}:Ломанень видечинзэ',
 'currentevents' => 'Мезе ней моли',
 'currentevents-url' => 'Project:Мезе ней моли',
@@ -414,16 +434,17 @@ $messages = array(
 'disclaimerpage' => 'Project:Видечинь прякс кортнема',
 'edithelp' => 'Витнемань-петнемань лезкс',
 'helppage' => 'Help:Лопась мезе кирди',
-'mainpage' => 'Ð\9fÑ\80Ñ\8fкÑ\81лопа',
-'mainpage-description' => 'Ð\9fÑ\80Ñ\8fкÑ\81лопа',
+'mainpage' => 'Ð\9fÑ\80Ñ\8fвÑ\82лопа',
+'mainpage-description' => 'Ð\9fÑ\80Ñ\8fвÑ\82лопа',
 'policy-url' => 'Project:Политика',
 'portal' => 'Велень-сядонь вальма',
-'portal-url' => 'Project:Ð\92ейÑ\82Ñ\8cÑ\81Ñ\8dнÑ\8c Ð²Ð°Ð»Ñ\8cма',
+'portal-url' => 'Project:Вейсэнь вальма',
 'privacy' => 'Салавачинь политикась',
 'privacypage' => 'Project:Салавачинь политикась',
 
 'badaccess' => 'Меревемань асатыкс',
 'badaccess-group0' => 'Тонеть а мерить теемс мезе вешить.',
+'badaccess-groups' => 'Тевтеемась, конань вешить, тееви ансяк «$1» {{PLURAL:$2|куронь|куротнень}} теицятненень.',
 
 'versionrequired' => 'МедияВикинь $1 версиясь эряви',
 'versionrequiredtext' => 'МедияВикинь $1 версиясь эряви те лопанть тевс нолдамга.
@@ -432,8 +453,6 @@ $messages = array(
 'ok' => 'Маштови',
 'retrievedfrom' => 'Лисмапрясь "$1"-сто',
 'youhavenewmessages' => 'Тонеть сась $1 ($2).',
-'newmessageslink' => 'Од пачтямнэть',
-'newmessagesdifflink' => 'меельсе полавтома',
 'youhavenewmessagesmulti' => 'Од сёрминеть учить эйсэть $1-со',
 'editsection' => 'витнеме-петнеме',
 'editold' => 'витнеме-петнеме',
@@ -478,6 +497,7 @@ $messages = array(
 # General errors
 'error' => 'Ильведькс',
 'databaseerror' => 'Датабазань ильведькс',
+'databaseerror-error' => 'Ильведькс: $1',
 'laggedslavemode' => 'Ванок: Кизды, лопасонть материалось таштомсь.',
 'readonly' => 'Датабазась панжома экшсэ',
 'enterlockreason' => 'Сёрмадт мейс сёлгамс эряви, ды ёвтак, зярдо таго арьсят панжови',
@@ -523,9 +543,18 @@ $messages = array(
 # Login and logout pages
 'welcomeuser' => 'Совак, $1, инеськеть!',
 'yourname' => 'Теицянь лем:',
+'userlogin-yourname' => 'Совамовал',
+'userlogin-yourname-ph' => 'Совавтык совамовалот',
 'yourpassword' => 'Салава валот:',
+'userlogin-yourpassword' => 'салававал',
+'userlogin-yourpassword-ph' => 'Совавтык салававалот',
+'createacct-yourpassword-ph' => 'Совавтык салававал',
 'yourpasswordagain' => 'Омбоцеде сёрмадык кирдицянь леметь:',
+'createacct-yourpasswordagain' => 'Кемекстык салававалонть',
+'createacct-yourpasswordagain-ph' => 'Совавтык салававалонть одов',
 'remembermypassword' => 'Ледстемс совамом те бравзерсэнть (сех кувать $1 {{PLURAL:$1|чи|чить}})',
+'userlogin-remembermypassword' => 'Кирдемизь совавтозекс',
+'userlogin-signwithsecure' => 'Нолдак тевс ванстозь сюлмавкс',
 'yourdomainname' => 'Эсеть доменэть:',
 'password-change-forbidden' => 'Те викисэнть а полавтсак салававалот.',
 'login' => 'Совамо',
@@ -536,14 +565,23 @@ $messages = array(
 'logout' => 'Лисеме',
 'userlogout' => 'Лисеме',
 'notloggedin' => 'Апак соваво',
+'userlogin-noaccount' => 'Совамотаркат арась?',
+'userlogin-joinproject' => 'Совак «{{SITENAME}}» сайтэнь теицякс',
 'nologin' => "Совамотаркат арась? '''$1'''.",
 'nologinlink' => 'Тейть совамотарка',
 'createaccount' => 'Теемс теицянь од лопа',
 'gotaccount' => "Совамотаркат ули? '''$1'''.",
 'gotaccountlink' => 'Совамс',
 'userlogin-resetlink' => 'Совамо эрявикстнэнь стувтыть?',
-'createaccountmail' => 'Тейть кодамо понгсь салавань вал, кучик сонзэ ало максозь е-сёрмапаргонтень',
+'userlogin-resetpassword-link' => 'Салававалот стувтовсь?',
+'userlogin-createanother' => 'Шкак од совамотарка',
+'createaccountmail' => 'Тейть кодамо понгсь салававал, кучик сонзэ ало максозь е-сёрмапаргонтень',
 'createaccountreason' => 'Тувталось:',
+'createacct-reason' => 'Тувтал',
+'createacct-submit' => 'Шкик совамотаркат',
+'createacct-another-submit' => 'Шкак од совамотарка',
+'createacct-benefit-heading' => '«{{SITENAME}}» сайтэнть теизь тонь кондямо ломанть.',
+'createacct-benefit-body2' => '{{PLURAL:$1|лопа|лопат}}',
 'badretype' => 'Сёрмадыть салава валот кавксть: сынь аволь вейкеть.',
 'userexists' => 'Те лемесь уш саезь.
 Арсека эстеть лия, инеськеть.',
@@ -579,14 +617,14 @@ $messages = array(
 'noemailcreate' => 'Эряви максомс е-сёрмапарго, конась маштови',
 'passwordsent' => '$1 -нь е-сёрмань адресэнтень кучозь од совамо вал.<br />
 Инеськеть, кодак валось пачкоди, совака одов.',
-'eauthentsent' => 'Электрононь адресэзэть кучозь кемекстамонь е-сёрмине.<br /> Сонзэ эйсэ сёрмадозь мезе кода теемс. Ансяк седе мейле, зярдо невтик, адресэсь алкукс эсеть, карматано кучомо лия сёрмат.',
+'eauthentsent' => 'Электрононь сёрмапаргозот кучозь кемекстамонь е-сёрмине.<br /> Сонзэ эйсэ сёрмадозь мезе кода теемс. Ансяк седе мейле, зярдо невтик, сёрмапаргось алкукс эсеть, карматано кучомо лия сёрмат.',
 'mailerror' => 'Е-сёрма кучомсто ильведькс: $1',
 'acct_creation_throttle_hit' => 'Те викисэ тонь IP адресстэть совасть теицят, конат теисть {{PLURAL:$1|1 сёрмадовкс|$1 сёрмадовкст}} меельсе чынть перть, седе ламо полавтомат а мерить теемс истя зняронь шкань перть.
 Тень кисэ, те   IP адресэнть коряс седе тов а маштови теемс-шкамс од сёрмадовкст, зярс.',
-'emailauthenticated' => 'Е-сёрма паргот кемекстазель $2 чыстэ $3 цяссто.',
+'emailauthenticated' => 'Е-сёрмапаргот кемекстазель $2 чистэ $3 цяссто.',
 'emailconfirmlink' => 'Кемекстык е-сёрмапаргот',
 'accountcreated' => 'Совамо таркась теезь',
-'accountcreatedtext' => '$1-нь совицянь таркась теевсь-шкавсь.',
+'accountcreatedtext' => '[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|кортнема]]) совицянь таркась теевсь-шкавсь.',
 'loginlanguagelabel' => 'Кель: $1',
 
 # Email sending
@@ -600,7 +638,7 @@ $messages = array(
 'newpassword' => 'Од совамо валот:',
 'retypenew' => 'Сёрмадык омбоцеде совамо валот:',
 'resetpass_submit' => 'Тештик совамо валот ды совак',
-'changepassword-success' => 'Совамо валот полавтовсь теть! Совавтыть эйсэть системас...',
+'changepassword-success' => 'Совамовалот полавтовсь!',
 'resetpass_forbidden' => 'Совамо валтнэ а полавтовить',
 'resetpass-submit-loggedin' => 'Полавтомс совамо валот',
 'resetpass-submit-cancel' => 'Саемс мекев',
@@ -678,9 +716,9 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'loginreqlink' => 'совамс',
 'loginreqpagetext' => 'Лия лопань ванномга, эряви $1.',
 'accmailtitle' => 'Салавань вал кучозь.',
-'accmailtext' => "Кода понгсь теезь совамо вал [[User talk:$1|$1]]-нь туртов кучозь $2 адресэнтень.
+'accmailtext' => "Кода понгсь теезь совамовал [[User talk:$1|$1]]-нь туртов кучозь $2 сёрмапаргонтень.
 
-Те од совамо таркас совамо валось полавтови ''[[Special:ChangePassword|совамо валонь полавтома]]'' лопас совамодо мейле.",
+Те од совамо таркас совамовалось полавтови ''[[Special:ChangePassword|совамовалонь полавтома]]'' лопас совамодо мейле.",
 'newarticle' => '(Од)',
 'newarticletext' => "Молить налтке мельга сёрмадовксос, конась апак тее.
 Ули мелеть теемс сёрмадовкс, сёрмадт валт ало паргос (вант [[{{MediaWiki:Helppage}}|help page]] тесэ лездамо информация).
@@ -762,8 +800,8 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 Чарькодевтемат: (молиц.) = редямось молиця версиястонть; (и. молиц.) = редямось икеле молиця версиястонть; '''а''' = аволь седе ламо лиякстомтома.",
 'history-fieldset-title' => 'Ваномс лопанть юронзо-путовксонзо',
 'history-show-deleted' => 'Ансяк нардазь',
-'histfirst' => 'Ð\92аÑ\81енÑ\86е',
-'histlast' => 'Ð\9cеелÑ\8cÑ\81е',
+'histfirst' => 'веÑ\81емеде Ñ\83монÑ\8c',
+'histlast' => 'Ð\9cеелÑ\8cÑ\86е',
 'historysize' => '({{PLURAL:$1|1 байт|$1 байтт}})',
 'historyempty' => '(чаво)',
 
@@ -868,7 +906,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'search-interwiki-default' => '$1 савкс:',
 'search-interwiki-more' => '(седе ламо)',
 'search-relatedarticle' => 'Малавикс',
-'mwsuggest-disable' => 'Лоткавтомс "AJAX" превспутыенть',
+'mwsuggest-disable' => 'Лоткавтомс вешнемань превспутыенть',
 'searcheverything-enable' => 'Вешнемс весе лем потмотнестэ',
 'searchrelated' => 'малавикс',
 'searchall' => 'весе',
@@ -889,8 +927,6 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'preferences' => 'Аравтомат',
 'mypreferences' => 'Аравтомат',
 'prefs-edits' => 'Зяроксть витнезь-петнезь:',
-'prefsnologin' => 'Эзить сова',
-'prefsnologintext' => 'Эряви <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} совамс]</span> аравтоматнень ладсемга.',
 'changepassword' => 'Салавань валонь полавтома',
 'prefs-skin' => 'Неемань ладсема',
 'skin-preview' => 'Васнянь неевтезэ',
@@ -951,9 +987,9 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'badsiglength' => 'Кедень путомат пек кувака.
 Эйсэнзэ иляст уле $1 -до ламо {{PLURAL:$1|тешкст|тешкст}}.',
 'yourgender' => 'Сыметь (цёрань-тейтерень):',
-'gender-unknown' => 'апак Ð½ÐµÐ²Ñ\82е',
-'gender-male' => 'цёрань сыме',
-'gender-female' => 'Ð\90ванÑ\8c Ñ\81Ñ\8bме',
+'gender-unknown' => 'Ð\90 Ð¼ÐµÑ\80евлинÑ\8c',
+'gender-male' => 'Сон витни-петни викилопатнесэ',
+'gender-female' => 'Сон Ð²Ð¸Ñ\82ни-пеÑ\82ни Ð²Ð¸ÐºÐ¸Ð»Ð¾Ð¿Ð°Ñ\82неÑ\81Ñ\8d',
 'email' => 'Е-сёрма',
 'prefs-help-realname' => 'Алкуксонь леметь (арась мелеть, иляк путо): путсак, ды сон карми неявомо не таркатнесэ, косо тон тев теят.',
 'prefs-help-email' => 'Е-сёрмапаргот а эряви тешкстамс. Сон карми эрявомо ансяк салававалонь одов пачтямсто ёмавтындерясак неень салавань валот.',
@@ -1055,8 +1091,8 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'action-undelete' => 'вельмевтемс мекев те лопанть',
 'action-suppressionlog' => 'ваномс те теицянть тевнеде сёрмадовкс',
 'action-block' => 'кардамс те совицянть витнемадо-петнемадо',
-'action-import' => 'совавтомс те лопанть лия Викистэ',
-'action-importupload' => 'совавтомс те лопанть файлань йовкстамо юртсто',
+'action-import' => 'совавтомс тезэнь лопат лия Викистэ',
+'action-importupload' => 'совавтомс тезэнь лопат файлань путома юртсто',
 'action-mergehistory' => 'вейтьсэндямс те лопанть юронзо-путовксонзо',
 'action-userrights' => 'витнемс-петнемс совицянь весе видечитнень',
 'action-userrights-interwiki' => 'витнемс-петнемс лия викитнесэ теицянь видечитнень',
@@ -1072,6 +1108,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'recentchanges-label-minor' => 'Те а покшкэ витнемась-петнемась',
 'recentchanges-label-bot' => 'Те витнеманть-петнеманть теизе кона-кона бот',
 'recentchanges-label-unpatrolled' => '',
+'recentchanges-legend-newpage' => '(вантаять [[Special:NewPages|од лопань лемрисьме]])',
 'rcnote' => "$5, $4 шканть коряс муят алдо {{PLURAL:$1|Меельсе '''1''' лиякстомтоманть|Меельсе '''$1''' лиякстомтоматнень}}  меельсе {{PLURAL:$2|чинть|'''$2''' читнень}} шкасто.",
 'rcnotefrom' => "Ало невтезь  '''$2''' лиякстомтомасто саезь ('''$1''' видс).",
 'rclistfrom' => 'Невтемс од витьнематнень $1-нть эйстэ саезь.',
@@ -1091,7 +1128,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'boteditletter' => 'б',
 'rc_categories_any' => 'Кодамо илязо уле',
 'newsectionsummary' => '/* $1 */ од пелькс',
-'rc-enhanced-expand' => 'Невтемс седе ламо тень ланга (JavaScript эряви)',
+'rc-enhanced-expand' => 'Невтемс седе ламо тень ланга',
 'rc-enhanced-hide' => 'Кекшемс келейстэ ёвтазенть',
 'rc-old-title' => 'васня сёрмадозель «$1» лем марто',
 
@@ -1425,7 +1462,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'emailsenttext' => 'Е-сёрмасо пачтямнэть кучовсь.',
 
 # Watchlist
-'watchlist' => 'Ð\9cезе Ð¼ÐµÐ»Ñ\8cга Ð¼Ð¾Ð½ Ð²Ð°Ð½Ñ\81Ñ\82нÑ\8fн',
+'watchlist' => 'Ð\92анома Ð»ÐµÐ¼Ñ\80иÑ\81Ñ\8cме',
 'mywatchlist' => 'Мезе мельга мон ванстнян',
 'watchlistfor2' => '$1-нь туртов $2',
 'nowatchlist' => 'Ванома керьксэзэть мезеяк апак путо.',
@@ -1859,7 +1896,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'file-info-size' => '$1 × $2 пиксельть, файлонть-путовксонть сталмозо: $3, MIME типезе: $4',
 'file-nohires' => 'Арась версия покш разрешения марто.',
 'svg-long-desc' => 'SVG файла, $1 × $2 пиксельть, файланть покшолмазо: $3',
-'show-big-image' => 'Ð\9fеÑ\88кÑ\81е Ñ\82еевкÑ\81еÑ\81Ñ\8c',
+'show-big-image' => 'Ð\92аÑ\81енÑ\8c Ñ\84айла',
 'file-info-gif-looped' => 'кирьксэс аравтозь',
 'file-info-png-looped' => 'кирьксэс аравтозь',
 
@@ -2081,7 +2118,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 
 # External editor support
 'edit-externally' => 'Витнемс-петнемс те файланть, тевс нолдазь ушо ёнксонь программанть',
-'edit-externally-help' => '(Вант [//www.mediawiki.org/wiki/Manual:External_editors аравтома инструкциятнень] седе ламо информациянть кис.)',
+'edit-externally-help' => '(Вант [https://www.mediawiki.org/wiki/Manual:External_editors аравтома инструкциятнень] седе ламо информациянть кис.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'весе',
@@ -2175,7 +2212,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'specialpages-group-highuse' => 'Пек тевс нолдазь лопат',
 'specialpages-group-pages' => 'Лопа керькст',
 'specialpages-group-pagetools' => 'Лопань кедьёнкст',
-'specialpages-group-wiki' => 'Викинь дата ды кедьйонкст',
+'specialpages-group-wiki' => 'Викинь дата ды кедьёнкст',
 'specialpages-group-redirects' => 'Башка тевень лопатнень ютавтома лия таркас',
 'specialpages-group-spam' => 'Шукш пачтнематнеде кедьёнкст',
 
@@ -2231,4 +2268,7 @@ IP-тешкстэть — $3, саймас совавтоманть ID-сь —
 'duration-centuries' => '$1 {{PLURAL:$1|пинге|пингеть}}',
 'duration-millennia' => '$1 {{PLURAL:$1|тёжтьие|тёжтьиеть}}',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'Васнянь неевтезэ',
+
 );
index c903256..13b8baf 100644 (file)
@@ -378,8 +378,6 @@ $2، $1',
 'ok' => 'خا',
 'retrievedfrom' => '"$1" جه بیته بیّه',
 'youhavenewmessages' => 'شما اتا $1 دانّی ($2).',
-'newmessageslink' => 'ترنه پیغوم‌ئون',
-'newmessagesdifflink' => 'پایانی دچی‌یه',
 'youhavenewmessagesfromusers' => 'شِما {{PLURAL:$3| کارور دیگه| $3  کارور}} $1 دارنی ($2).',
 'youhavenewmessagesmanyusers' => 'شما ات‌سری کارور جه $1 دارنی ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ترنه پیغوم|ترنه پیغوم}}',
@@ -668,7 +666,6 @@ $2، $1',
 # Preferences page
 'mypreferences' => 'مه خاستنی‌ئون',
 'prefs-edits' => 'تعداد دچی‌یه‌ئون:',
-'prefsnologin' => 'سیستم دله نمویی',
 'prefs-rc' => 'تازه دگاردسته‌ئون',
 'youremail' => 'شه مه Email:',
 'username' => 'کاروری نوم:',
index a9224e7..1ab8959 100644 (file)
@@ -302,8 +302,6 @@ $messages = array(
 'ok' => 'Nopan iti',
 'retrievedfrom' => 'Ōquīzqui ītech  "$1"',
 'youhavenewmessages' => 'Tiquimpiya $1 ($2).',
-'newmessageslink' => 'yancuīc tlahcuilōltzintli',
-'newmessagesdifflink' => 'achto tlapatlaliztli',
 'youhavenewmessagesmulti' => 'Tiquimpiya yancuīc tlahcuilōlli īpan $1',
 'editsection' => 'ticpatlāz',
 'editold' => 'ticpatlāz',
@@ -630,7 +628,6 @@ Hueliz ōmopolo huiqui nozo ōmozacac.
 'preferences' => 'Tlaēlēhuiliztli',
 'mypreferences' => 'Notlaēlēhuiliz',
 'prefs-edits' => 'Tlapatlaliztli tlapōhualli:',
-'prefsnologin' => 'Ahmo ōtimocalac',
 'changepassword' => 'Ticpatlāz motlahtōlichtacāyo',
 'skin-preview' => 'Xiquitta quemeh yez',
 'datedefault' => 'Ayāc tlanequiliztli',
@@ -1471,8 +1468,7 @@ Niman tihuelīti [[Special:UserLogin|timocalaqui]] auh ticpactiāz huiquitica.',
 
 # Special:SpecialPages
 'specialpages' => 'Nònkuâkìskàtlaìxtlapaltìn',
-'specialpages-note' => '----
-* Yeliztli nōncuahquīzqui āmatl.
+'specialpages-note' => '* Yeliztli nōncuahquīzqui āmatl.
 * <span class="mw-specialpagerestricted">Tlaquīxtīlli nōncuahquīzqui āmatl.</span>
 * <span class="mw-specialpagecached">Tlatlātīlli nōncuahquīzqui āmatl (aocmo monemitīa).</span>',
 'specialpages-group-other' => 'Oksẻki nònkuâkìskàtlaìxtlapaltìn',
@@ -1508,4 +1504,8 @@ Niman tihuelīti [[Special:UserLogin|timocalaqui]] auh ticpactiāz huiquitica.',
 'api-error-uploaddisabled' => 'Sèuhtok in êkawilistli ìpan inìn wiki.',
 'api-error-verification-error' => 'Inìn èwalli welis îtlakauhtok, noso âmò kualli motzòwîtok.',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Cualli',
+'expand_templates_preview' => 'Xiquitta achtochīhualiztli',
+
 );
index a9eba0c..cddc1d9 100644 (file)
@@ -12,6 +12,8 @@
  * @author Kaihsu
  */
 
+$fallback = 'cdo, zh-hant';
+
 $datePreferences = array(
        'default',
        'ISO 8601',
@@ -208,7 +210,7 @@ $messages = array(
 'create-this-page' => 'Khai-sí siá chit ia̍h',
 'delete' => 'Thâi',
 'deletethispage' => 'Thâi chit ia̍h',
-'undelete_short' => 'Kiù {{PLURAL:$1|$1|$1} ê siu-kái',
+'undelete_short' => 'Kiù {{PLURAL:$1|$1|$1}} ê siu-kái',
 'viewdeleted_short' => 'Khoàⁿ {{PLURAL:$1|chi̍t-ê thâi tiàu--ê pian-chi̍p|$1 ê thâi tiàu--ê pian-chi̍p}}',
 'protect' => 'Pó-hō·',
 'protect_change' => 'kái-piàn',
@@ -281,8 +283,6 @@ Chhiáⁿ khoàⁿ [[Special:Version|pán-pún ia̍h]].',
 'ok' => 'Hó ah',
 'retrievedfrom' => 'Lâi-goân: "$1"',
 'youhavenewmessages' => 'Lí ū $1 ($2).',
-'newmessageslink' => 'sin sìn-sit',
-'newmessagesdifflink' => 'chêng 2 ê siu-tēng-pún ê diff',
 'youhavenewmessagesmulti' => 'Lí tī $1 ū sin sìn-sit',
 'editsection' => 'siu-kái',
 'editold' => 'siu-kái',
@@ -600,8 +600,6 @@ Lí ê kái-piàn tī ē-kha ê bûn-jī-keh. Lí su-iàu chiōng lí chò ê k
 # Preferences page
 'preferences' => 'Siat-tēng',
 'mypreferences' => 'Góa ê siat-tēng',
-'prefsnologin' => 'Bô teng-ji̍p',
-'prefsnologintext' => 'Lí it-tēng ài [[Special:UserLogin|teng-ji̍p]] chiah ē-tàng chhiâu iōng-chiá ê siat-tēng.',
 'changepassword' => 'Oāⁿ bi̍t-bé',
 'prefs-skin' => 'Phôe',
 'skin-preview' => 'Chhì khoàⁿ',
@@ -1169,4 +1167,10 @@ Chit tiuⁿ phoe ê khak-jīn-bé ē chū-tōng tī $4 kòe-kî.',
 # Special:SpecialPages
 'specialpages' => 'Te̍k-sû-ia̍h',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Khok-chhiong pang-bô͘',
+'expand_templates_input' => 'Su-ji̍p bûn-jī:',
+'expand_templates_output' => 'Kiat-kó:',
+'expand_templates_remove_comments' => 'Comments the̍h tiāu',
+
 );
index 042cd49..db67e15 100644 (file)
@@ -269,8 +269,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Estratto \'e "$1"',
 'youhavenewmessages' => 'Haje $1 ($2).',
-'newmessageslink' => "nove 'mmasciàte",
-'newmessagesdifflink' => "differenze cu 'a revisione precedente",
 'youhavenewmessagesmulti' => 'Tiene nuove mmasciate $1',
 'editsection' => 'càgna',
 'editold' => 'càgna',
@@ -785,7 +783,7 @@ Also see [[Special:WantedCategories|wanted categories]].",
 'exif-subjectdistancerange-0' => 'Scanusciuta',
 
 # External editor support
-'edit-externally-help' => "Pe piglià cchiù nfromma veré 'e [//www.mediawiki.org/wiki/Manual:External_editors struzione] ('n ngrese)",
+'edit-externally-help' => "Pe piglià cchiù nfromma veré 'e [https://www.mediawiki.org/wiki/Manual:External_editors struzione] ('n ngrese)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tutte',
index 1df949a..03bf9e1 100644 (file)
@@ -104,7 +104,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Ugyldig_tittel' ),
        'Blankpage'                 => array( 'Blank_side' ),
        'Block'                     => array( 'Blokker', 'Blokker_IP', 'Blokker_bruker' ),
-       'Blockme'                   => array( 'Blokker_meg' ),
        'Booksources'               => array( 'Bokkilder' ),
        'BrokenRedirects'           => array( 'Ødelagte_omdirigeringer' ),
        'Categories'                => array( 'Kategorier' ),
@@ -116,10 +115,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Opprett_konto' ),
        'Deadendpages'              => array( 'Blindveisider' ),
        'DeletedContributions'      => array( 'Slettede_bidrag' ),
-       'Disambiguations'           => array( 'Pekere' ),
        'DoubleRedirects'           => array( 'Doble_omdirigeringer' ),
        'EditWatchlist'             => array( 'Rediger_overvåkningsliste' ),
        'Emailuser'                 => array( 'E-post' ),
+       'ExpandTemplates'           => array( 'Utvid_maler' ),
        'Export'                    => array( 'Eksporter' ),
        'Fewestrevisions'           => array( 'Færrest_revisjoner' ),
        'FileDuplicateSearch'       => array( 'Filduplikatsøk' ),
@@ -161,6 +160,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Beskyttede_sider' ),
        'Protectedtitles'           => array( 'Beskyttede_titler' ),
        'Randompage'                => array( 'Tilfeldig', 'Tilfeldig_side' ),
+       'RandomInCategory'          => array( 'Tilfeldig_fra_kategori' ),
        'Randomredirect'            => array( 'Tilfeldig_omdirigering' ),
        'Recentchanges'             => array( 'Siste_endringer' ),
        'Recentchangeslinked'       => array( 'Relaterte_endringer' ),
@@ -324,12 +324,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Skjul patruljerte redigeringer i siste endringer',
 'tog-newpageshidepatrolled' => 'Skjul patruljerte sider fra listen over nye sider',
 'tog-extendwatchlist' => 'Utvid overvåkningslisten til å vise alle endringer, ikke bare de siste',
-'tog-usenewrc' => 'Grupper endringer i siste endringer og overvåkingslistte (krever JavaScript)',
+'tog-usenewrc' => 'Gruppeendringer per side i siste endringer samt overvåkingsliste',
 'tog-numberheadings' => 'Autonummerer overskrifter',
-'tog-showtoolbar' => 'Vis verktøylinje (krever JavaScript)',
-'tog-editondblclick' => 'Rediger sider ved å dobbeltklikke (krever JavaScript)',
+'tog-showtoolbar' => 'Vis verktøylinje',
+'tog-editondblclick' => 'Rediger sider ved å dobbeltklikke',
 'tog-editsection' => 'Rediger avsnitt ved hjelp av [rediger]-lenke',
-'tog-editsectiononrightclick' => 'Rediger avsnitt ved å høyreklikke på avsnittsoverskrift (JavaScript)',
+'tog-editsectiononrightclick' => 'Rediger avsnitt ved å høyreklikke på avsnittsoverskrift',
 'tog-showtoc' => 'Vis innholdsfortegnelse (for sider med flere enn tre avsnitt)',
 'tog-rememberpassword' => 'Husk meg i denne nettleseren (i høyst $1 {{PLURAL:$1|dag|dager}})',
 'tog-watchcreations' => 'Legg til sider jeg oppretter og filer jeg laster opp i min overvåkingsliste',
@@ -347,7 +347,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Vis antall brukere som overvåker',
 'tog-oldsig' => 'Nåværende signatur:',
 'tog-fancysig' => 'Behandle signaturen som wikitekst (uten automatisk lenke)',
-'tog-uselivepreview' => 'Bruk levende forhåndsvisning (eksperimentell JavaScript)',
+'tog-uselivepreview' => 'Bruk levende forhåndsvisning (eksperimentelt)',
 'tog-forceeditsummary' => 'Advar meg når jeg ikke gir noen redigeringsforklaring',
 'tog-watchlisthideown' => 'Skjul mine endringer fra overvåkningslisten',
 'tog-watchlisthidebots' => 'Skjul robotendringer fra overvåkningslisten',
@@ -564,7 +564,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Om {{SITENAME}}',
 'aboutpage' => 'Project:Om',
-'copyright' => 'Innholdet er tilgjengelig under $1.',
+'copyright' => 'Innholdet er tilgjengelig under $1 med mindre annet er spesifikt angitt.',
 'copyrightpage' => '{{ns:project}}:Opphavsrett',
 'currentevents' => 'Aktuelt',
 'currentevents-url' => 'Project:Aktuelt',
@@ -590,8 +590,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Hentet fra «$1»',
 'youhavenewmessages' => 'Du har $1 ($2).',
-'newmessageslink' => 'nye meldinger',
-'newmessagesdifflink' => 'siste endring',
 'youhavenewmessagesfromusers' => 'Du har $1 fra {{PLURAL:$3|en annen bruker| $3 brukere}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du har $1 fra mange brukere ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|en ny melding|nye meldinger}}',
@@ -827,13 +825,13 @@ og fortsette å bruke det gamle passordet.',
 'passwordsent' => 'Et nytt passord har blitt sendt til e-postadressen registrert for «$1».
 Logg inn når du har mottatt det nye passordet.',
 'blocked-mailpassword' => 'IP-adressen din er blokkert fra å redigere, og for å forhindre misbruk kan du heller ikke bruke funksjonen som gir deg nytt passord.',
-'eauthentsent' => 'En bekreftelsesmelding ble sendt til gitte e-postadresse. Før andre e-poster kan sendes til kontoen må du følge instruksjonene i e-posten for å bekrefte at kontoen faktisk er din.',
+'eauthentsent' => 'En bekreftelsesmelding ble sendt til oppgitt e-postadresse. Før andre e-poster kan sendes til kontoen må du følge instruksjonene i e-posten for å bekrefte at kontoen faktisk er din.',
 'throttled-mailpassword' => 'En passordtilbakestillingsepost har allerede blitt sendt for mindre enn {{PLURAL:$1|en time|$1 timer}} siden.
 For å forhindre misbruk kan kun én passordtilbakestillingsepost sendes per {{PLURAL:$1|time|$1 timer}}.',
 'mailerror' => 'Feil under sending av e-post: $1',
 'acct_creation_throttle_hit' => 'Gjester med samme IP-adresse som deg har opprettet {{PLURAL:$1|én konto|$1 kontoer}} det siste døgnet, og det er ikke tillatt å opprette flere.
 Som et resultat kan det ikke opprettes flere kontoer fra denne IP-adressen.',
-'emailauthenticated' => 'Din e-postadresse ble bekreftet $2 $3.',
+'emailauthenticated' => 'Din e-postadresse ble bekreftet den $2 kl. $3.',
 'emailnotauthenticated' => 'Din e-postadresse er ikke bekreftet. Du vil ikke kunne motta e-post for noen av følgende egenskaper.',
 'noemailprefs' => 'Oppgi en e-postadresse for at disse funksjonene skal fungere.',
 'emailconfirmlink' => 'Bekreft e-postadressen din.',
@@ -881,7 +879,7 @@ Du kan ha allerede byttet passordet, eller bedt om et nytt midlertidig passord.'
 'resetpass-abort-generic' => 'Endring av passord har blitt avbrutt av en utvidelse.',
 
 # Special:PasswordReset
-'passwordreset' => 'Passordresetting',
+'passwordreset' => 'Tilbakestilling av passord',
 'passwordreset-text-one' => 'Fyll ut skjemaet for å tilbakestille passordet',
 'passwordreset-text-many' => '{{PLURAL:$1|Fyll inn et av datafeltene for å tilbakestille passordet ditt.}}',
 'passwordreset-legend' => 'Nullstill passord',
@@ -1278,7 +1276,7 @@ Andre administratorer på {{SITENAME}} vil fortsatt kunne se det skjulte innhold
 'revdelete-hide-image' => 'Skjul filinnhold',
 'revdelete-hide-name' => 'Skjul handling og mål',
 'revdelete-hide-comment' => 'Skjul redigeringsforklaring',
-'revdelete-hide-user' => 'Skjul bidragsyters brukernavn eller IP',
+'revdelete-hide-user' => 'Skjul bidragsyters brukernavn eller IP-adresse',
 'revdelete-hide-restricted' => 'La disse begrensningene gjelde for administratorer også',
 'revdelete-radio-same' => '(ikke endre)',
 'revdelete-radio-set' => 'Ja',
@@ -1436,8 +1434,6 @@ For å søke i alle, bruk prefikset ''all:'' (inkluderer diskusjonssider, maler,
 'preferences' => 'Innstillinger',
 'mypreferences' => 'Innstillinger',
 'prefs-edits' => 'Antall redigeringer:',
-'prefsnologin' => 'Ikke logget inn',
-'prefsnologintext' => 'Du må være <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logget inn]</span> for å endre brukerinnstillingene.',
 'changepassword' => 'Endre passord',
 'prefs-skin' => 'Utseende',
 'skin-preview' => 'Forhåndsvisning',
@@ -1462,7 +1458,7 @@ For å søke i alle, bruk prefikset ''all:'' (inkluderer diskusjonssider, maler,
 'prefs-rendering' => 'Utseende',
 'saveprefs' => 'Lagre',
 'resetprefs' => 'Tilbakestill ulagrede endringer',
-'restoreprefs' => 'Tilbakestill til standardinnstillinger overalt',
+'restoreprefs' => 'Tilbakestill alt til standardinnstillinger',
 'prefs-editing' => 'Redigering',
 'rows' => 'Rader:',
 'columns' => 'Kolonner',
@@ -1708,8 +1704,8 @@ Informasjonen vil være offentlig.',
 'action-block' => 'blokkere denne brukeren fra å redigere',
 'action-protect' => 'endre denne sidens beskyttelsesnivåer',
 'action-rollback' => 'raskt tilbakestille endringene til den siste brukeren som redigerte en bestemt side',
-'action-import' => 'importere denne siden fra en annen wiki',
-'action-importupload' => 'importere denne siden fra en opplastet fil',
+'action-import' => 'importere sider fra en annen wiki',
+'action-importupload' => 'importere sider fra en filopplasting',
 'action-patrol' => 'merke andre brukeres redigeringer som patruljert',
 'action-autopatrol' => 'merke redigeringene dine som patruljert',
 'action-unwatchedpages' => 'vise listen over uovervåkede sider',
@@ -1736,6 +1732,7 @@ Informasjonen vil være offentlig.',
 'recentchanges-label-minor' => 'Dette er en mindre endring',
 'recentchanges-label-bot' => 'Denne redigeringen ble gjort av en bot',
 'recentchanges-label-unpatrolled' => 'Denne redigeringen har ikke blitt patruljert ennå',
+'recentchanges-legend-newpage' => '$1 – ny side',
 'rcnote' => "Nedenfor vises {{PLURAL:$1|'''1''' endring|de siste '''$1''' endringene}} fra {{PLURAL:$2|det siste døgnet|de siste '''$2''' døgnene}}, per $5 $4.",
 'rcnotefrom' => "Nedenfor er endringene siden '''$2''' (opp til '''$1''' vises).",
 'rclistfrom' => 'Vis nye endringer med start fra $1',
@@ -1743,7 +1740,7 @@ Informasjonen vil være offentlig.',
 'rcshowhidebots' => '$1 roboter',
 'rcshowhideliu' => '$1 innloggede brukere',
 'rcshowhideanons' => '$1 anonyme brukere',
-'rcshowhidepatr' => '$1 godkjente endringer',
+'rcshowhidepatr' => '$1 patruljerte endringer',
 'rcshowhidemine' => '$1 mine endringer',
 'rclinks' => 'Vis siste $1 endringer i de siste $2 dagene<br />$3',
 'diff' => 'diff',
@@ -1758,7 +1755,7 @@ Informasjonen vil være offentlig.',
 'rc_categories_any' => 'Alle',
 'rc-change-size-new' => '$1 {{PLURAL:$1|byte}} etter endring',
 'newsectionsummary' => '/* $1 */ ny seksjon',
-'rc-enhanced-expand' => 'Vis detaljer (krever JavaScript)',
+'rc-enhanced-expand' => 'Vis detaljer',
 'rc-enhanced-hide' => 'Skjul detaljer',
 'rc-old-title' => 'opprinnelig opprettet som «$1»',
 
@@ -2502,9 +2499,11 @@ Se $2 for en oversikt over de siste slettingene.',
 'deleteotherreason' => 'Annen/utdypende grunn:',
 'deletereasonotherlist' => 'Annen grunn',
 'deletereason-dropdown' => '* Vanlige grunner for sletting
-** På forfatters forespørsel
+** Spam
+** Vandalisme
 ** Opphavsrettsbrudd
-** Vandalisme',
+** På forfatters forespørsel 
+** Råtten omdirigering',
 'delete-edit-reasonlist' => 'Rediger begrunnelser for sletting',
 'delete-toobig' => 'Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Muligheten til å slette slike sider er begrenset for å unngå utilsiktet forstyrring av {{SITENAME}}.',
 'delete-warning-toobig' => 'Denne siden har en stor redigeringshistorikk, med over {{PLURAL:$1|$1&nbsp;revisjon|$1&nbsp;revisjoner}}. Sletting av denne siden kan forstyrre databasen til {{SITENAME}}; vær varsom.',
@@ -3164,6 +3163,8 @@ Dette er sannsynligvis forårsaket av en lenke til et svartelistet eksternt nett
 'spam_reverting' => 'Tilbakestiller til siste versjon uten lenke til $1',
 'spam_blanking' => 'Alle revisjoner inneholdt lenke til $1, tømmer siden',
 'spam_deleting' => 'Sletter alle revisjoner med lenker til $1',
+'simpleantispam-label' => "Antispamsjekk.
+'''IKKE''' fyll inn dette feltet!",
 
 # Info page
 'pageinfo-title' => 'Informasjon om «$1»',
@@ -3217,20 +3218,20 @@ Dette er sannsynligvis forårsaket av en lenke til et svartelistet eksternt nett
 'skinname-modern' => 'Moderne',
 
 # Patrolling
-'markaspatrolleddiff' => 'Godkjenn endringen',
-'markaspatrolledtext' => 'Godkjenn denne siden',
-'markedaspatrolled' => 'Merket som godkjent',
-'markedaspatrolledtext' => 'Den valgte revisjonen av [[:$1]] har blitt markert som patruljert.',
+'markaspatrolleddiff' => 'Merk som patruljert',
+'markaspatrolledtext' => 'Merk denne siden som patruljert',
+'markedaspatrolled' => 'Merket som patruljert',
+'markedaspatrolledtext' => 'Den valgte revisjonen av [[:$1]] har blitt merket som patruljert.',
 'rcpatroldisabled' => 'Siste endringer-patruljering er slått av',
 'rcpatroldisabledtext' => 'Siste endringer-patruljeringsfunksjonen er slått av.',
-'markedaspatrollederror' => 'Kan ikke merke som godkjent',
-'markedaspatrollederrortext' => 'Du må spesifisere en versjon å merke som godkjent.',
-'markedaspatrollederror-noautopatrol' => 'Du kan ikke merke dine egne endringer som godkjente.',
+'markedaspatrollederror' => 'Kunne ikke merke som patruljert',
+'markedaspatrollederrortext' => 'Du må spesifisere en versjon å merke som patruljert.',
+'markedaspatrollederror-noautopatrol' => 'Du har ikke lov å merke dine egne endringer som patruljerte.',
 'markedaspatrollednotify' => 'Denne endringen av $1 har blitt patruljert.',
 'markedaspatrollederrornotify' => 'Patruljering feilet.',
 
 # Patrol log
-'patrol-log-page' => 'Godkjenningslogg',
+'patrol-log-page' => 'Patruljeringslogg',
 'patrol-log-header' => 'Dette er en logg over patruljerte sideversjoner.',
 'log-show-hide-patrol' => '$1 patruljeringslogg',
 
@@ -3733,7 +3734,7 @@ Rotert 90° mot klokka og vridd vertikalt',
 
 # External editor support
 'edit-externally' => 'Rediger denne filen med et eksternt program',
-'edit-externally-help' => '(Se [//www.mediawiki.org/wiki/Manual:External_editors oppsettsinstruksjonene] for mer informasjon)',
+'edit-externally-help' => '(Se [https://www.mediawiki.org/wiki/Manual:External_editors oppsettsinstruksjonene] for mer informasjon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
@@ -3936,7 +3937,7 @@ Du kan også [[Special:EditWatchlist|bruke standardverktøyet]].',
 'version-hook-subscribedby' => 'Brukes av',
 'version-version' => '(versjon $1)',
 'version-license' => 'Lisens',
-'version-poweredby-credits' => "Denne wikien er drevet av '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Denne wikien er drevet av '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'andre',
 'version-poweredby-translators' => 'translatewiki.net-oversettere',
 'version-credits-summary' => 'Vi ønsker å takke følgende personer for deres bidrag til [[Special:Version|MediaWiki]].',
@@ -3977,8 +3978,7 @@ Du skal ha mottatt [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopi av GNU General Publ
 
 # Special:SpecialPages
 'specialpages' => 'Spesialsider',
-'specialpages-note' => '----
-* Normale spesialsider.
+'specialpages-note' => '* Normale spesialsider.
 * <span class="mw-specialpagerestricted">Spesialsider med begrenset tilgang.</span>
 * <span class="mw-specialpagecached">Spesialsider som oppdateres periodisk (kan være foreldede).</span>',
 'specialpages-group-maintenance' => 'Vedlikeholdsrapporter',
@@ -4188,4 +4188,21 @@ Om det ikke er tilfellet, kan du bruke det enkle skjemaet som du finner under. K
 'limitreport-expansiondepth' => 'Største ekspansjonsdybde',
 'limitreport-expensivefunctioncount' => 'Antall kostbare parserfunksjoner',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Utvid maler',
+'expand_templates_intro' => 'Denne spesialsiden tar tekst og utvider rekusivt alle maler brukt i teksten. 
+Den utvider også alle parserfunksjoner som 
+<code><nowiki>{{</nowiki>#language:…}}</code>, og variabler som 
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Faktisk utvider den det meste innkapslet i doble krøllparenteser.',
+'expand_templates_title' => 'Konteksttittel, for {{FULLPAGENAME}}, etc.:',
+'expand_templates_input' => 'Skriv inn tekst:',
+'expand_templates_output' => 'Resultat',
+'expand_templates_xml_output' => 'XML-resultat',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Fjern kommentarer',
+'expand_templates_remove_nowiki' => 'Ikke vis <nowiki>-merkelapper i resultatet',
+'expand_templates_generate_xml' => 'Vis parsetre som XML',
+'expand_templates_preview' => 'Forhåndsvisning',
+
 );
index 2159551..17732af 100644 (file)
@@ -138,7 +138,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Ole Sieden' ),
        'Blankpage'                 => array( 'Leddige Sied' ),
        'Block'                     => array( 'Blocken' ),
-       'Blockme'                   => array( 'Proxy-Sparr' ),
        'Booksources'               => array( 'ISBN-Söök' ),
        'BrokenRedirects'           => array( 'Kaputte Redirects' ),
        'Categories'                => array( 'Kategorien' ),
@@ -147,7 +146,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Bidrääg' ),
        'CreateAccount'             => array( 'Brukerkonto anleggen' ),
        'Deadendpages'              => array( 'Sackstraatsieden' ),
-       'Disambiguations'           => array( 'Mehrdüdige Begrepen' ),
        'DoubleRedirects'           => array( 'Dubbelte Redirects' ),
        'Emailuser'                 => array( 'E-Mail an Bruker' ),
        'Export'                    => array( 'Exporteren' ),
@@ -473,8 +471,6 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Vun „$1“',
 'youhavenewmessages' => 'Du hest $1 ($2).',
-'newmessageslink' => 'Ne’e Narichten',
-'newmessagesdifflink' => 'Ünnerscheed to vörher',
 'youhavenewmessagesmulti' => 'Du hest ne’e Narichten op $1',
 'editsection' => 'ännern',
 'editold' => 'ännern',
@@ -1118,8 +1114,6 @@ de aver nich jümmer den aktuellsten Stand weerspegelt.<p>',
 'preferences' => 'Instellen',
 'mypreferences' => 'För mi Instellen',
 'prefs-edits' => 'Wo faken du in dit Wiki Sieden ännert hest:',
-'prefsnologin' => 'Nich anmellt',
-'prefsnologintext' => 'Du musst <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} anmellt]</span> wesen, dat du dien Instellen ännern kannst.',
 'changepassword' => 'Passwoort ännern',
 'prefs-skin' => 'Utsehn vun de Steed',
 'skin-preview' => 'Vörschau',
@@ -2477,6 +2471,7 @@ All Transwiki-Import-Akschonen staht later ok in dat [[Special:Log/import|Import
 'spambot_username' => 'MediaWiki Spam-Oprümen',
 'spam_reverting' => 'Trüchdreiht na de letzte Version ahn Lenken na $1.',
 'spam_blanking' => 'All Versionen harrn Lenken na $1, rein maakt.',
+'simpleantispam-label' => "Antispam-Kuntrull. Hier '''nix''' indragen!",
 
 # Info page
 'pageinfo-title' => 'Informatschoon för "$1"',
@@ -2858,7 +2853,7 @@ Wiedere warrt standardmatig nich anwiest:
 
 # External editor support
 'edit-externally' => 'Änner disse Datei mit en extern Programm',
-'edit-externally-help' => '(Lees de [//www.mediawiki.org/wiki/Manual:External_editors Installatschoonshelp] wenn du dor mehr to weten wullt)',
+'edit-externally-help' => '(Lees de [https://www.mediawiki.org/wiki/Manual:External_editors Installatschoonshelp] wenn du dor mehr to weten wullt)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
@@ -3002,7 +2997,7 @@ Du kannst ok de [[Special:EditWatchlist|normale Sied to’n Ännern]] bruken.',
 'version-hook-subscribedby' => 'Opropen vun',
 'version-version' => '(Version $1)',
 'version-license' => 'Lizenz',
-'version-poweredby-credits' => "Dit Wiki bruukt '''[//www.mediawiki.org/ MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Dit Wiki bruukt '''[https://www.mediawiki.org/ MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'annere',
 'version-software' => 'Installeerte Software',
 'version-software-product' => 'Produkt',
@@ -3021,8 +3016,7 @@ Du kannst ok de [[Special:EditWatchlist|normale Sied to’n Ännern]] bruken.',
 
 # Special:SpecialPages
 'specialpages' => 'Sünnerliche Sieden',
-'specialpages-note' => '----
-* Normale Spezialsieden
+'specialpages-note' => '* Normale Spezialsieden
 * <strong class="mw-specialpagerestricted">Spezialsieden för Brukers mit mehr Rechten</strong>',
 'specialpages-group-maintenance' => 'Pleeglisten',
 'specialpages-group-other' => 'Annere Spezialsieden',
@@ -3104,4 +3098,20 @@ Du kannst ok de [[Special:EditWatchlist|normale Sied to’n Ännern]] bruken.',
 'revdelete-unrestricted' => 'Inschränkungen för Administraters rutnahmen',
 'rightsnone' => '(kene)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Vörlagen oplösen',
+'expand_templates_intro' => 'Mit disse Spezialsied köönt Vörlagen in ingeven Text in Wikitext ümwannelt warrn.
+Ok Parserfunkschonen so as
+<nowiki>{{</nowiki>#language:…}}, un Variabeln so as
+<nowiki>{{</nowiki>CURRENTDAY}} warrt ümwannelt. Also so temlich allens, wat twischen swiefte Klammern steit.
+Dorto warrt de nödigen Parser-Phasen in MediaWiki direkt opropen.',
+'expand_templates_title' => 'Kontexttitel, för {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Inputtext:',
+'expand_templates_output' => 'Resultat',
+'expand_templates_xml_output' => 'XML-Utgaav',
+'expand_templates_ok' => 'Los',
+'expand_templates_remove_comments' => 'Kommentaren rutnehmen',
+'expand_templates_generate_xml' => 'XML-Parser-Boom wiesen',
+'expand_templates_preview' => 'Vörschau',
+
 );
index 707bcb3..f8fc34a 100644 (file)
@@ -75,13 +75,14 @@ $bookstoreList = array(
 
 #!!# Translation <b>HLEERSTE:</b> is used more than once for <a href="#mw-sp-magic-lcfirst">lcfirst</a> and <a href="#mw-sp-magic-ucfirst">ucfirst</a>.
 $magicWords = array(
-       'redirect'                  => array( '0', '#DEURVERWIEZING', '#DOORVERWIJZING', '#REDIRECT' ),
+       'redirect'                  => array( '0', '#DEURVERWIEZING', '#DUURVERWIEZING', '#DOORVERWIJZING', '#REDIRECT' ),
        'notoc'                     => array( '0', '__GIENONDERWARPEN__', '__GEENINHOUD__', '__NOTOC__' ),
-       'nogallery'                 => array( '0', '__GIENGALLERIEJE__', '__GEEN_GALERIJ__', '__NOGALLERY__' ),
-       'forcetoc'                  => array( '0', '__FORSEERONDERWARPEN__', '__INHOUD_DWINGEN__', '__FORCEERINHOUD__', '__FORCETOC__' ),
+       'nogallery'                 => array( '0', '__GIENGALLERIEJE__', '__GIENGALDERIEJE__', '__GEEN_GALERIJ__', '__NOGALLERY__' ),
+       'forcetoc'                  => array( '0', '__FORSEERONDERWARPEN_', '__INHOUD_DWINGEN__', '__FORCEERINHOUD__', '__FORCETOC__' ),
        'toc'                       => array( '0', '__ONDERWARPEN__', '__INHOUD__', '__TOC__' ),
        'noeditsection'             => array( '0', '__GIENBEWARKSEKSIE__', '__NIETBEWERKBARESECTIE__', '__NOEDITSECTION__' ),
-       'currentmonth'              => array( '1', 'DISSEMAOND', 'HUIDIGEMAAND', 'HUIDIGEMAAND2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'currentmonth'              => array( '1', 'DISSEMAOND', 'DISSEMAOND2', 'HUIDIGEMAAND', 'HUIDIGEMAAND2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'currentmonth1'             => array( '1', 'DISSEMAOND1', 'HUIDIGEMAAND1', 'CURRENTMONTH1' ),
        'currentmonthname'          => array( '1', 'DISSEMAONDNAAM', 'HUIDIGEMAANDNAAM', 'CURRENTMONTHNAME' ),
        'currentmonthnamegen'       => array( '1', 'DISSEMAONDGEN', 'HUIDIGEMAANDGEN', 'CURRENTMONTHNAMEGEN' ),
        'currentmonthabbrev'        => array( '1', 'DISSEMAONDAOFK', 'HUIDIGEMAANDAFK', 'CURRENTMONTHABBREV' ),
@@ -102,35 +103,38 @@ $magicWords = array(
        'localyear'                 => array( '1', 'LOKAALJAOR', 'PLAATSELIJKJAAR', 'LOKAALJAAR', 'LOCALYEAR' ),
        'localtime'                 => array( '1', 'LOKALETIED', 'PLAATSELIJKETIJD', 'LOKALETIJD', 'LOCALTIME' ),
        'localhour'                 => array( '1', 'LOKAALURE', 'PLAATSELIJKUUR', 'LOKAALUUR', 'LOCALHOUR' ),
-       'numberofpages'             => array( '1', 'ANTALPAGINAS', 'ANTALPAGINA\'S', 'ANTALPAGINA’S', 'AANTALPAGINAS', 'AANTALPAGINA\'S', 'AANTALPAGINA’S', 'NUMBEROFPAGES' ),
+       'numberofpages'             => array( '1', 'ANTALZIEJEN', 'AANTALPAGINAS', 'AANTALPAGINA\'S', 'AANTALPAGINA’S', 'NUMBEROFPAGES' ),
        'numberofarticles'          => array( '1', 'ANTALARTIKELS', 'AANTALARTIKELEN', 'NUMBEROFARTICLES' ),
        'numberoffiles'             => array( '1', 'ANTALBESTANDEN', 'AANTALBESTANDEN', 'NUMBEROFFILES' ),
        'numberofusers'             => array( '1', 'ANTALGEBRUKERS', 'AANTALGEBRUIKERS', 'NUMBEROFUSERS' ),
        'numberofactiveusers'       => array( '1', 'ANTALAKTIEVEGEBRUKERS', 'AANTALACTIEVEGEBRUIKERS', 'ACTIEVEGEBRUIKERS', 'NUMBEROFACTIVEUSERS' ),
        'numberofedits'             => array( '1', 'ANTALBEWARKINGEN', 'AANTALBEWERKINGEN', 'NUMBEROFEDITS' ),
        'numberofviews'             => array( '1', 'ANTALKERENBEKEKEN', 'AANTALKERENBEKEKEN', 'NUMBEROFVIEWS' ),
-       'pagename'                  => array( '1', 'PAGINANAAM', 'PAGENAME' ),
-       'pagenamee'                 => array( '1', 'PAGINANAAME', 'PAGENAMEE' ),
+       'pagename'                  => array( '1', 'ZIEDNAAM', 'PAGINANAAM', 'PAGENAME' ),
+       'pagenamee'                 => array( '1', 'ZIEDNAAME', 'PAGINANAAME', 'PAGENAMEE' ),
        'namespace'                 => array( '1', 'NAAMRUUMTE', 'NAAMRUIMTE', 'NAMESPACE' ),
        'namespacee'                => array( '1', 'NAAMRUUMTEE', 'NAAMRUIMTEE', 'NAMESPACEE' ),
+       'namespacenumber'           => array( '1', 'NAAMRUUMTENUMMER', 'NAAMRUIMTENUMMER', 'NAMESPACENUMBER' ),
        'talkspace'                 => array( '1', 'OVERLEGRUUMTE', 'OVERLEGRUIMTE', 'TALKSPACE' ),
        'talkspacee'                => array( '1', 'OVERLEGRUUMTEE', 'OVERLEGRUIMTEE', 'TALKSPACEE' ),
        'subjectspace'              => array( '1', 'ONDERWARPRUUMTE', 'ARTIKELRUUMTE', 'ONDERWERPRUIMTE', 'ARTIKELRUIMTE', 'SUBJECTSPACE', 'ARTICLESPACE' ),
        'subjectspacee'             => array( '1', 'ONDERWARPRUUMTEE', 'ARTIKELRUUMTEE', 'ONDERWERPRUIMTEE', 'ARTIKELRUIMTEE', 'SUBJECTSPACEE', 'ARTICLESPACEE' ),
-       'fullpagename'              => array( '1', 'HELEPAGINANAAM', 'VOLLEDIGEPAGINANAAM', 'FULLPAGENAME' ),
-       'fullpagenamee'             => array( '1', 'HELEPAGINANAAME', 'VOLLEDIGEPAGINANAAME', 'FULLPAGENAMEE' ),
-       'subpagename'               => array( '1', 'DEELPAGINANAAM', 'SUBPAGENAME' ),
-       'subpagenamee'              => array( '1', 'DEELPAGINANAAME', 'SUBPAGENAMEE' ),
+       'fullpagename'              => array( '1', 'HELEZIEDNAAM', 'VOLLEDIGEPAGINANAAM', 'FULLPAGENAME' ),
+       'fullpagenamee'             => array( '1', 'HELEZIEDNAAME', 'VOLLEDIGEPAGINANAAME', 'FULLPAGENAMEE' ),
+       'subpagename'               => array( '1', 'DEELZIEDNAAM', 'DEELPAGINANAAM', 'SUBPAGENAME' ),
+       'subpagenamee'              => array( '1', 'DEELZIEDNAAME', 'DEELPAGINANAAME', 'SUBPAGENAMEE' ),
+       'rootpagename'              => array( '1', 'ROOTZIEDNAAM', 'ROOTPAGINANAAM', 'ROOTPAGENAME' ),
+       'rootpagenamee'             => array( '1', 'ROOTZIEDNAAME', 'ROOTPAGINANAAME', 'ROOTPAGENAMEE' ),
        'basepagename'              => array( '1', 'BAOSISPAGINANAAM', 'BASISPAGINANAAM', 'BASEPAGENAME' ),
        'basepagenamee'             => array( '1', 'BAOSISPAGINANAAME', 'BASISPAGINANAAME', 'BASEPAGENAMEE' ),
        'talkpagename'              => array( '1', 'OVERLEGPAGINANAAM', 'TALKPAGENAME' ),
        'talkpagenamee'             => array( '1', 'OVERLEGPAGINANAAME', 'TALKPAGENAMEE' ),
-       'subjectpagename'           => array( '1', 'ONDERWARPPAGINANAAM', 'ARTIKELPAGINANAAM', 'ONDERWERPPAGINANAAM', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
-       'subjectpagenamee'          => array( '1', 'ONDERWARPPAGINANAAME', 'ARTIKELPAGINANAAME', 'ONDERWERPPAGINANAAME', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
+       'subjectpagename'           => array( '1', 'ONDERWARPZIEDNAAM', 'ARTIKELZIEDNAAM', 'ONDERWERPPAGINANAAM', 'ARTIKELPAGINANAAM', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
+       'subjectpagenamee'          => array( '1', 'ONDERWARZIEDNAAME', 'ARTIKELZIEDNAAME', 'ONDERWERPPAGINANAAME', 'ARTIKELPAGINANAAME', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ),
        'msg'                       => array( '0', 'BERICHT:', 'MSG:' ),
        'subst'                     => array( '0', 'VERVANG:', 'VERV:', 'SUBST:' ),
        'msgnw'                     => array( '0', 'BERICHTNW', 'MSGNW:' ),
-       'img_thumbnail'             => array( '1', 'miniatuur', 'duumnegel', 'doemnaegel', 'thumbnail', 'thumb' ),
+       'img_thumbnail'             => array( '1', 'duum', 'doem', 'miniatuur', 'mini', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'miniatuur=$1', 'duumnegel=$1', 'doemnaegel=$1', 'thumbnail=$1', 'thumb=$1' ),
        'img_right'                 => array( '1', 'rechts', 'right' ),
        'img_left'                  => array( '1', 'links', 'left' ),
@@ -138,7 +142,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'esentreerd', 'gecentreerd', 'center', 'centre' ),
        'img_framed'                => array( '1', 'umraand', 'omkaderd', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'kaoderloos', 'kaderloos', 'frameless' ),
-       'img_page'                  => array( '1', 'pagina=$1', 'pagina_$1', 'pagina $1', 'page=$1', 'page $1' ),
+       'img_page'                  => array( '1', 'zied=$1', 'zied_$1', 'pagina=$1', 'pagina $1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'rechtop', 'rechtop=$1', 'rechtop$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'raand', 'rand', 'border' ),
        'img_baseline'              => array( '1', 'grondliende', 'grondlijn', 'baseline' ),
@@ -147,7 +151,7 @@ $magicWords = array(
        'img_middle'                => array( '1', 'midden', 'middle' ),
        'img_bottom'                => array( '1', 'benejen', 'beneden', 'bottom' ),
        'img_text_bottom'           => array( '1', 'tekste-benejen', 'tekst-beneden', 'text-bottom' ),
-       'img_link'                  => array( '1', 'verwiezing=$1', 'verwijzing=$1', 'koppeling=$1', 'link=$1' ),
+       'img_link'                  => array( '1', 'verwiezing=$1', 'koppeling=$1', 'verwijzing=$1', 'link=$1' ),
        'sitename'                  => array( '1', 'WEBSTEENAAM', 'SITENAAM', 'SITENAME' ),
        'ns'                        => array( '0', 'NR:', 'NS:' ),
        'localurl'                  => array( '0', 'LOKALEURL', 'LOCALURL:' ),
@@ -157,30 +161,32 @@ $magicWords = array(
        'stylepath'                 => array( '0', 'STIELPAD', 'STIJLPAD', 'STYLEPATH' ),
        'grammar'                   => array( '0', 'GRAMMATIKA:', 'GRAMMATICA:', 'GRAMMAR:' ),
        'gender'                    => array( '0', 'GESLACHTE:', 'GESLACHT:', 'GENDER:' ),
-       'notitleconvert'            => array( '0', '__GIENTITELKONVERSIE__', '__GIENTC__', '__GEENTITELCONVERSIE__', '__GEENTC__', '__GEENPAGINANAAMCONVERSIE__', '__NOTITLECONVERT__', '__NOTC__' ),
-       'nocontentconvert'          => array( '0', '__GIENINHOUDKONVERSIE__', '__GIENIC__', '__GEENINHOUDCONVERSIE__', '__GEENIC__', '__NOCONTENTCONVERT__', '__NOCC__' ),
+       'notitleconvert'            => array( '0', '__GIENTITELKONVERSIE__', '__GIENTK__', '__GEENPAGINANAAMCONVERSIE__', '__GEENTITELCONVERSIE__', '__GEENTC__', '__NOTITLECONVERT__', '__NOTC__' ),
+       'nocontentconvert'          => array( '0', '__GIENINHOUDKONVERSIE__', '__GIENIK__', '__GEENINHOUDCONVERSIE__', '__GEENIC__', '__NOCONTENTCONVERT__', '__NOCC__' ),
        'currentweek'               => array( '1', 'DISSEWEKE', 'HUIDIGEWEEK', 'CURRENTWEEK' ),
        'currentdow'                => array( '1', 'DISSEDVDW', 'HUIDIGEDVDW', 'CURRENTDOW' ),
        'localweek'                 => array( '1', 'LOKALEWEKE', 'PLAATSELIJKEWEEK', 'LOKALEWEEK', 'LOCALWEEK' ),
        'localdow'                  => array( '1', 'LOKALEDVDW', 'PLAATSELIJKEDVDW', 'LOCALDOW' ),
-       'revisionid'                => array( '1', 'REVISIEID', 'REVISIE-ID', 'VERSIEID', 'REVISIONID' ),
-       'revisionday'               => array( '1', 'REVISIEDAG', 'VERSIEDAG', 'REVISIONDAY' ),
-       'revisionday2'              => array( '1', 'REVISIEDAG2', 'VERSIEDAG2', 'REVISIONDAY2' ),
-       'revisionmonth'             => array( '1', 'REVISIEMAOND', 'VERSIEMAAND', 'REVISIONMONTH' ),
-       'revisionyear'              => array( '1', 'REVISIEJAOR', 'VERSIEJAAR', 'REVISIONYEAR' ),
-       'revisiontimestamp'         => array( '1', 'REVISIETIEDSTEMPEL', 'VERSIETIJD', 'REVISIONTIMESTAMP' ),
+       'revisionid'                => array( '1', 'VERSIEID', 'REVISIONID' ),
+       'revisionday'               => array( '1', 'VERSIEDAG', 'REVISIONDAY' ),
+       'revisionday2'              => array( '1', 'VERSIEDAG2', 'REVISIONDAY2' ),
+       'revisionmonth'             => array( '1', 'VERSIEMAOND', 'VERSIEMAAND', 'REVISIONMONTH' ),
+       'revisionmonth1'            => array( '1', 'VERSIEMAOND1', 'VERSIEMAAND1', 'REVISIONMONTH1' ),
+       'revisionyear'              => array( '1', 'VERSIEJAOR', 'VERSIEJAAR', 'REVISIONYEAR' ),
+       'revisiontimestamp'         => array( '1', 'VERSIETIEDSTEMPEL', 'VERSIETIJD', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'VERSIEGEBRUKER', 'VERSIEGEBRUIKER', 'REVISIONUSER' ),
        'plural'                    => array( '0', 'MEERVOUD:', 'PLURAL:' ),
-       'fullurl'                   => array( '0', 'HELEURL', 'VOLLEDIGEURL', 'VOLLEDIGEURL:', 'FULLURL:' ),
-       'fullurle'                  => array( '0', 'HELEURLE', 'VOLLEDIGEURLE', 'VOLLEDIGEURLE:', 'FULLURLE:' ),
+       'fullurl'                   => array( '0', 'HELEURL', 'VOLLEDIGEURL:', 'FULLURL:' ),
+       'fullurle'                  => array( '0', 'HELEURLE', 'VOLLEDIGEURLE:', 'FULLURLE:' ),
        'lcfirst'                   => array( '0', 'KLEERSTE:', 'LCFIRST:' ),
        'ucfirst'                   => array( '0', 'GLEERSTE:', 'HLEERSTE:', 'UCFIRST:' ),
        'lc'                        => array( '0', 'KL:', 'LC:' ),
        'uc'                        => array( '0', 'HL:', 'UC:' ),
        'raw'                       => array( '0', 'RAUW:', 'RUW:', 'RAW:' ),
-       'displaytitle'              => array( '1', 'TEUNTITEL', 'TOONTITEL', 'TITELTONEN', 'WEERGEGEVENTITEL', 'DISPLAYTITLE' ),
-       'newsectionlink'            => array( '1', '__NIEJESECTIEVERWIEZING__', '__NIEUWESECTIELINK__', '__NIEUWESECTIEKOPPELING__', '__NEWSECTIONLINK__' ),
-       'nonewsectionlink'          => array( '1', '__GIENNIEJKOPJENVERWIEZING__', '__GEENNIEUWKOPJEVERWIJZING__', '__GEENNIEUWESECTIELINK__', '__GEENNIEUWKOPJEKOPPELING__', '__NONEWSECTIONLINK__' ),
+       'displaytitle'              => array( '1', 'TEUNTITEL', 'WEERGEGEVENTITEL', 'TOONTITEL', 'DISPLAYTITLE' ),
+       'nocommafysuffix'           => array( '0', 'GIENSCHEIDINGSTEKEN', 'GEENSCHEIDINGSTEKEN', 'NOSEP' ),
+       'newsectionlink'            => array( '1', '__NIEJESEKSIEVERWIEZING__', '__NIEUWESECTIELINK__', '__NIEUWESECTIEKOPPELING__', '__NEWSECTIONLINK__' ),
+       'nonewsectionlink'          => array( '1', '__GIENNIEJKOPJENVERWIEZING__', '__GEENNIEUWKOPJEKOPPELING__', '__GEENNIEUWESECTIELINK__', '__GEENNIEUWKOPJEVERWIJZING__', '__NONEWSECTIONLINK__' ),
        'currentversion'            => array( '1', 'DISSEVERSIE', 'HUIDIGEVERSIE', 'CURRENTVERSION' ),
        'urlencode'                 => array( '0', 'URLKODEREN', 'URLCODEREN', 'CODEERURL', 'URLENCODE:' ),
        'anchorencode'              => array( '0', 'ANKERKODEREN', 'ANKERCODEREN', 'CODEERANKER', 'ANCHORENCODE' ),
@@ -189,7 +195,7 @@ $magicWords = array(
        'directionmark'             => array( '1', 'RICHTINGMARKERING', 'RICHTINGSMARKERING', 'DIRECTIONMARK', 'DIRMARK' ),
        'language'                  => array( '0', '#TAAL:', '#LANGUAGE:' ),
        'contentlanguage'           => array( '1', 'INHOUDSTAAL', 'INHOUDTAAL', 'CONTENTLANGUAGE', 'CONTENTLANG' ),
-       'pagesinnamespace'          => array( '1', 'PAGINASINNAAMRUUMTE', 'PAGINA’SINNAAMRUUMTE', 'PAGINA\'SINNAAMRUUMTE', 'PAGINASINNAAMRUIMTE', 'PAGINA’SINNAAMRUIMTE', 'PAGINA\'SINNAAMRUIMTE', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
+       'pagesinnamespace'          => array( '1', 'ZIEJENINNAAMRUUMTE', 'PAGINASINNAAMRUIMTE', 'PAGINA’SINNAAMRUIMTE', 'PAGINA\'SINNAAMRUIMTE', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
        'numberofadmins'            => array( '1', 'ANTALBEHEERDERS', 'AANTALBEHEERDERS', 'AANTALADMINS', 'NUMBEROFADMINS' ),
        'formatnum'                 => array( '0', 'FORMATTEERNUM', 'NUMFORMATTEREN', 'FORMATNUM' ),
        'padleft'                   => array( '0', 'LINKSOPVULLEN', 'PADLEFT' ),
@@ -199,36 +205,43 @@ $magicWords = array(
        'filepath'                  => array( '0', 'BESTAANDSPAD:', 'BESTANDSPAD:', 'FILEPATH:' ),
        'tag'                       => array( '0', 'etiket', 'label', 'tag' ),
        'hiddencat'                 => array( '1', '__VERBÖRGENKAT__', '__VERBORGENCAT__', '__HIDDENCAT__' ),
-       'pagesincategory'           => array( '1', 'PAGINASINKATEGORIE', 'PAGINASINKAT', 'PAGINASINCATEGORIE', 'PAGINASINCAT', 'PAGESINCATEGORY', 'PAGESINCAT' ),
-       'pagesize'                  => array( '1', 'PAGINAGROOTTE', 'PAGESIZE' ),
+       'pagesincategory'           => array( '1', 'ZIEJENINKATEGORIE', 'PAGINASINCATEGORIE', 'PAGINASINCAT', 'PAGESINCATEGORY', 'PAGESINCAT' ),
+       'pagesize'                  => array( '1', 'ZIEDGROOTTE', 'PAGINAGROOTTE', 'PAGESIZE' ),
        'noindex'                   => array( '1', '__GIENINDEX__', '__GEENINDEX__', '__NOINDEX__' ),
        'numberingroup'             => array( '1', 'ANTALINGROEP', 'AANTALINGROEP', 'NUMBERINGROUP', 'NUMINGROUP' ),
        'staticredirect'            => array( '1', '__STAOTIESEDEURVERWIEZING__', '__STATISCHEDOORVERWIJZING__', '__STATISCHEREDIRECT__', '__STATICREDIRECT__' ),
        'protectionlevel'           => array( '1', 'BEVEILIGINGSNIVO', 'BEVEILIGINGSNIVEAU', 'PROTECTIONLEVEL' ),
        'formatdate'                => array( '0', 'daotumopmaak', 'datumopmaak', 'formatdate', 'dateformat' ),
        'url_query'                 => array( '0', 'ZEUKOPDRACHTE', 'ZOEKOPDRACHT', 'QUERY' ),
+       'defaultsort_noerror'       => array( '0', 'gienfout', 'geenfout', 'noerror' ),
+       'pagesincategory_pages'     => array( '0', 'ziejen', 'paginas', 'pages' ),
+       'pagesincategory_subcats'   => array( '0', 'onderkategorieen', 'ondercategorieen', 'subcats' ),
+       'pagesincategory_files'     => array( '0', 'bestaanden', 'bestanden', 'files' ),
 );
 
 $specialPageAliases = array(
        'Activeusers'               => array( 'Aktieve_gebrukers' ),
        'Allmessages'               => array( 'Alle_systeemteksten' ),
-       'Allpages'                  => array( 'Alle_pagina\'s' ),
-       'Ancientpages'              => array( 'Oudste_pagina\'s' ),
-       'Blankpage'                 => array( 'Lege_pagina' ),
-       'Block'                     => array( 'Blokkeer_IP' ),
-       'Blockme'                   => array( 'Blokkeer_mien' ),
+       'Allpages'                  => array( 'Alle_ziejen' ),
+       'Ancientpages'              => array( 'Oudste_ziejen' ),
+       'Badtitle'                  => array( 'Verkeerde_ziednaam' ),
+       'Blankpage'                 => array( 'Lege_zied' ),
+       'Block'                     => array( 'Blokkeren' ),
        'Booksources'               => array( 'Boekinformasie' ),
        'BrokenRedirects'           => array( 'Ebreuken_deurverwiezingen' ),
        'Categories'                => array( 'Kategorieën' ),
+       'ChangeEmail'               => array( 'Netpost_wiezigen' ),
        'ChangePassword'            => array( 'Wachtwoord_wiezigen' ),
+       'ComparePages'              => array( 'Ziejen_vergelieken' ),
        'Confirmemail'              => array( 'Netpost_bevestigen' ),
        'Contributions'             => array( 'Biedragen' ),
        'CreateAccount'             => array( 'Gebruker_anmaken' ),
        'Deadendpages'              => array( 'Gien_verwiezingen' ),
        'DeletedContributions'      => array( 'Vort-edaone_gebrukersbiedragen' ),
-       'Disambiguations'           => array( 'Deurverwiespagina\'s' ),
        'DoubleRedirects'           => array( 'Dubbele_deurverwiezingen' ),
+       'EditWatchlist'             => array( 'Volglieste_bewarken' ),
        'Emailuser'                 => array( 'Bericht_sturen' ),
+       'ExpandTemplates'           => array( 'Mallen_substitueren' ),
        'Export'                    => array( 'Uutvoeren' ),
        'Fewestrevisions'           => array( 'Minste_bewarkingen' ),
        'FileDuplicateSearch'       => array( 'Dubbele_bestaanden_zeuken' ),
@@ -245,50 +258,53 @@ $specialPageAliases = array(
        'Listusers'                 => array( 'Gebrukerslieste' ),
        'Lockdb'                    => array( 'Databanke_blokkeren' ),
        'Log'                       => array( 'Logboeken' ),
-       'Lonelypages'               => array( 'Weespagina\'s' ),
+       'Lonelypages'               => array( 'Weesziejen' ),
        'Longpages'                 => array( 'Lange_artikels' ),
        'MergeHistory'              => array( 'Geschiedenisse_bie_mekaar_doon' ),
        'MIMEsearch'                => array( 'MIME-zeuken' ),
        'Mostcategories'            => array( 'Meeste_kategorieën' ),
        'Mostimages'                => array( 'Meestgebruukten_bestaanden' ),
-       'Mostlinked'                => array( 'Meest_naor_verwezen_pagina\'s' ),
+       'Mostinterwikis'            => array( 'Meeste_interwikiverwiezingen' ),
+       'Mostlinked'                => array( 'Meest_naor_verwezen_ziejen' ),
        'Mostlinkedcategories'      => array( 'Meestgebruukten_kategorieën' ),
        'Mostlinkedtemplates'       => array( 'Meestgebruken_mallen' ),
        'Mostrevisions'             => array( 'Meeste_bewarkingen' ),
-       'Movepage'                  => array( 'Herneum_pagina' ),
+       'Movepage'                  => array( 'Zied_herneumen' ),
        'Mycontributions'           => array( 'Mien_biedragen' ),
-       'Mypage'                    => array( 'Mien_gebrukerspagina' ),
+       'Mypage'                    => array( 'Mien_gebrukerszied' ),
        'Mytalk'                    => array( 'Mien_overleg' ),
-       'Myuploads'                 => array( 'Mien_in-elaojen_bestanen' ),
+       'Myuploads'                 => array( 'Mien_in-elaojen_bestaanden' ),
        'Newimages'                 => array( 'Nieje_bestaanden' ),
-       'Newpages'                  => array( 'Nieje_pagina\'s' ),
+       'Newpages'                  => array( 'Nieje_ziejen' ),
+       'PagesWithProp'             => array( 'Ziejen_mit_eigenschap' ),
        'PasswordReset'             => array( 'Wachtwoord_opniej_instellen' ),
        'PermanentLink'             => array( 'Vaste_verwiezing' ),
-       'Popularpages'              => array( 'Populaire_artikels' ),
+       'Popularpages'              => array( 'Populaere_artikels' ),
        'Preferences'               => array( 'Veurkeuren' ),
        'Prefixindex'               => array( 'Veurvoegselindex' ),
-       'Protectedpages'            => array( 'Beveiligden_pagina\'s' ),
+       'Protectedpages'            => array( 'Beveiligden_ziejen' ),
        'Protectedtitles'           => array( 'Beveiligden_titels' ),
-       'Randompage'                => array( 'Zo_mer_n_artikel' ),
-       'Randomredirect'            => array( 'Zo_mer_n_deurverwiezing' ),
+       'Randompage'                => array( 'Netzelde_welk_artikel' ),
+       'Randomredirect'            => array( 'Netzelde_welke_deurverwiezing' ),
        'Recentchanges'             => array( 'Leste_wiezigingen' ),
-       'Recentchangeslinked'       => array( 'Volg_verwiezingen' ),
+       'Recentchangeslinked'       => array( 'Leste_wiezigingen_ekoppeld' ),
+       'Redirect'                  => array( 'Deurverwiezen' ),
        'Revisiondelete'            => array( 'Versie_vortdoon' ),
        'Search'                    => array( 'Zeuken' ),
        'Shortpages'                => array( 'Korte_artikels' ),
-       'Specialpages'              => array( 'Spesiale_pagina\'s' ),
+       'Specialpages'              => array( 'Spesiale_ziejen' ),
        'Statistics'                => array( 'Staotistieken' ),
        'Tags'                      => array( 'Etiketten' ),
        'Uncategorizedcategories'   => array( 'Kategorieën_zonder_kategorie' ),
        'Uncategorizedimages'       => array( 'Bestaanden_zonder_kategorie' ),
-       'Uncategorizedpages'        => array( 'Pagina\'s_zonder_kategorie' ),
+       'Uncategorizedpages'        => array( 'Ziejen_zonder_kategorie' ),
        'Uncategorizedtemplates'    => array( 'Mallen_zonder_kategorie' ),
        'Undelete'                  => array( 'Weerummeplaotsen' ),
        'Unlockdb'                  => array( 'Databanke_vriegeven' ),
        'Unusedcategories'          => array( 'Ongebruukten_kategorieën' ),
        'Unusedimages'              => array( 'Ongebruukten_bestaanden' ),
        'Unusedtemplates'           => array( 'Ongebruukten_mallen' ),
-       'Unwatchedpages'            => array( 'Niet-evolgden_pagina\'s' ),
+       'Unwatchedpages'            => array( 'Niet-evolgden_ziejen' ),
        'Upload'                    => array( 'Bestaanden_opsturen' ),
        'UploadStash'               => array( 'Bestaandenstallige' ),
        'Userlogin'                 => array( 'Anmelden' ),
@@ -297,10 +313,10 @@ $specialPageAliases = array(
        'Version'                   => array( 'Versie' ),
        'Wantedcategories'          => array( 'Gewunste_kategorieën' ),
        'Wantedfiles'               => array( 'Gewunste_bestaanden' ),
-       'Wantedpages'               => array( 'Gewunste_pagina\'s' ),
+       'Wantedpages'               => array( 'Gewunste_ziejen' ),
        'Wantedtemplates'           => array( 'Gewunste_mallen' ),
        'Watchlist'                 => array( 'Volglieste' ),
-       'Whatlinkshere'             => array( 'Verwiezingen_naor_disse_pagina' ),
+       'Whatlinkshere'             => array( 'Verwiezingen_naor_disse_zied' ),
        'Withoutinterwiki'          => array( 'Gien_interwiki' ),
 );
 
@@ -581,8 +597,6 @@ $1",
 'ok' => 'Best',
 'retrievedfrom' => 'Van "$1"',
 'youhavenewmessages' => 'Je hebben $1 ($2).',
-'newmessageslink' => 'nieje berichten',
-'newmessagesdifflink' => 'verschil mit de veurige versie',
 '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|nieje berichten}}',
@@ -759,7 +773,7 @@ Vergeet niet joew [[Special:Preferences|veurkeuren veur {{SITENAME}}]] an te pas
 'gotaccount' => "Stao'j al in-eschreven? '''$1'''.",
 'gotaccountlink' => 'Anmelden',
 'userlogin-resetlink' => "Bi'j de anmeldgegevens kwiet?",
-'userlogin-resetpassword-link' => 'Joew wachtwoord opniej instellen',
+'userlogin-resetpassword-link' => 'Joew wachtwoord vergeten?',
 'helplogin-url' => 'Help:Anmelden',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hulpe bie t anmelden]]',
 'userlogin-loggedin' => 'Je bin al an-emeld as {{GENDER:$1|$1}}.
@@ -827,7 +841,7 @@ en blief joew bestaonde wachtwoord gebruken.',
 'noemailcreate' => 'Je mutten n geldig netpostadres opgeven',
 'passwordsent' => 'Der is n niej wachtwoord verstuurd naor t netpostadres van gebruker "$1". Meld an, a\'j t wachtwoord ontvangen.',
 'blocked-mailpassword' => "Dit IP-adres is eblokkeerd. Dit betekent da'j niet bewarken kunnen en dat {{SITENAME}} joew wachtwoord niet weerummehaolen kan, dit wörden edaon um misbruuk tegen te gaon.",
-'eauthentsent' => "Der is n bevestigingsberich naor t op-egeven netpostadres verstuurd. Veurdat der veerdere berichten naor dit netpostadres verstuurd kunnen wörden, mu'j de instruksies volgen in t toe-esturen berich, um te bevestigen da'j joe eigen daodwarkelik an-emeld hebben.",
+'eauthentsent' => "Der is n bevestigingsbericht naor t op-egeven netpostadres verstuurd. Veurdat der veerdere berichten naor dit netpostadres verstuurd kunnen wörden, mu'j de instruksies volgen in t toe-estuurden bericht, um te bevestigen da'j joew eigen daodwarkelik an-emeld hebben.",
 'throttled-mailpassword' => 'In {{PLURAL:$1|t veurbieje ure|de veurbieje $1 uren}} is der al n wachtwoordherinnering estuurd.
 Um misbruuk te veurkoemen wörden der mer één wachtwoordherinnering per {{PLURAL:$1|ure|$1 uren}} verstuurd.',
 'mailerror' => 'Fout bie t versturen van bericht: $1',
@@ -1262,15 +1276,15 @@ Beheerders van {{SITENAME}} kunnen de verbörgen inhoud bekieken en t weerummepl
 * Ongepassen persoonlike informasie
 *: ''adressen en tillefoonnummers, burgerservicenummers, en gao zo mer deur.''",
 'revdelete-legend' => 'Stel versiebeparkingen in:',
-'revdelete-hide-text' => 'Verbarg de bewarken tekste',
+'revdelete-hide-text' => 'Versietekste',
 'revdelete-hide-image' => 'Verbarg bestaandsinhoud',
 'revdelete-hide-name' => 'Verbarg logboekaksie',
-'revdelete-hide-comment' => 'Verbarg bewarkingssamenvatting',
-'revdelete-hide-user' => 'Verbarg gebrukersnamen en IP-adressen van aandere luui.',
+'revdelete-hide-comment' => 'Bewarkingssamenvatting',
+'revdelete-hide-user' => 'Gebrukersnaam/IP-adres van disse gebruker',
 'revdelete-hide-restricted' => 'Gegevens veur beheerders en aander volk onderdrokken',
 'revdelete-radio-same' => '(niet wiezigen)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nee',
+'revdelete-radio-set' => 'Zichtbaor',
+'revdelete-radio-unset' => 'Verbörgen',
 'revdelete-suppress' => 'Gegevens veur beheerders en aander volk onderdrokken',
 'revdelete-unsuppress' => 'Beparkingen veur weerummezetten versies vortdoon',
 'revdelete-log' => 'Reden:',
@@ -1423,8 +1437,6 @@ Waorschienlik ku'j der meer gegevens over vienen in t [{{fullurl:{{#Special:Log}
 'preferences' => 'Veurkeuren',
 'mypreferences' => 'Mien veurkeuren',
 'prefs-edits' => 'Antal bewarkingen:',
-'prefsnologin' => 'Niet an-meld',
-'prefsnologintext' => 'Je mutten <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} an-emeld]</span> ween um joew veurkeuren in te kunnen stellen.',
 'changepassword' => 'Wachtwoord wiezigen',
 'prefs-skin' => '{{SITENAME}}-uterlik',
 'skin-preview' => 'bekieken',
@@ -1724,6 +1736,7 @@ Disse informasie is zichtbaor veur aandere gebrukers.',
 'recentchanges-label-minor' => 'Dit is n kleine wieziging',
 'recentchanges-label-bot' => 'Disse bewarking is uutevoerd deur n bot',
 'recentchanges-label-unpatrolled' => 'Disse bewarking is nog niet nao-ekeken',
+'recentchanges-legend-newpage' => '$1 - nieje pagina',
 'rcnote' => "Hieronder {{PLURAL:$1|steet de leste bewarking|staon de leste '''$1''' bewarkingen}} van de aofgeleupen {{PLURAL:$2|dag|'''$2''' dagen}} (per: $5, $4).",
 'rcnotefrom' => 'Dit bin de wiezigingen sinds <b>$2</b> (maximum van <b>$1</b> wiezigingen).',
 'rclistfrom' => 'Bekiek wiezigingen vanaof $1',
@@ -2483,10 +2496,12 @@ Bevestig hieronder dat dit inderdaod de bedoeling is, da'j de gevolgen begriepen
 'deletecomment' => 'Reden:',
 'deleteotherreason' => 'Aandere/extra reden:',
 'deletereasonotherlist' => 'Aandere reden',
-'deletereason-dropdown' => '*Redens veur t vortdoon van ziejen
+'deletereason-dropdown' => '* Redens veur t vortdoon van ziejen
+** Spam
+** Vandalisme
+** Schending van auteursrechten
 ** Op verzeuk van de auteur
-** Schending van auteursrecht
-** Vandalisme',
+** Ebreuken deurverwiezing',
 'delete-edit-reasonlist' => 'Redens veur t vortdoon bewarken',
 'delete-toobig' => 'Disse zied hef n lange bewarkingsgeschiedenisse, meer as $1 {{PLURAL:$1|versie|versies}}.
 t Vortdoon van dit soort ziejen is mit rechten bepark um t per ongelok versteuren van de warking van {{SITENAME}} te veurkoemen.',
@@ -2951,7 +2966,7 @@ A'j dat leste doon willen dan ku'j oek n verwiezing gebruken, bieveurbeeld [[{{#
 'allmessagesdefault' => 'Standardtekste',
 'allmessagescurrent' => 'De leste versie',
 'allmessagestext' => "Hieronder steet n lieste mit alle systeemteksten in de MediaWiki-naamruumte.
-Kiek oek effen bie [//www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] a'j biedragen willen an de algemene vertaling veur MediaWiki.",
+Kiek oek effen bie [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisasie] en [//translatewiki.net translatewiki.net] a'j biedragen willen an de algemene vertaling veur MediaWiki.",
 'allmessagesnotsupportedDB' => "Disse zied kan niet gebruukt wörden umdat '''\$wgUseDatabaseMessages''' uutezet is.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filtreer op wiezigingen:',
@@ -3117,7 +3132,7 @@ De tiedelike map is niet anwezig.',
 Iej könt in de bewearkingssamenvatting n reden opgeven.',
 'tooltip-preferences-save' => 'Vuurkeuren opsloan',
 'tooltip-summary' => 'Voer ne korte samenvatting in',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Metadata
 'notacceptable' => 'De wikiserver kan de gegevens niet leveren in n vorm die joew kliënt kan lezen.',
@@ -3143,6 +3158,8 @@ Meestentieds kömp dit deur n uutgaonde verwiezing die op de zwarte lieste steet
 'spam_reverting' => 'Bezig mit t weerummezetten naor de leste versie die gien verwiezing hef naor $1',
 'spam_blanking' => 'Alle wiezigingen mit n verwiezing naor $1 wörden vortehaold',
 'spam_deleting' => 'In alle versies staon verwiezingen naor $1. Zied vortedaon',
+'simpleantispam-label' => "Antispamkontraole.
+Hier '''NIKS''' invullen!",
 
 # Info page
 'pageinfo-title' => 'Informasie over "$1"',
@@ -3156,6 +3173,7 @@ Meestentieds kömp dit deur n uutgaonde verwiezing die op de zwarte lieste steet
 'pageinfo-length' => 'Ziedlengte (in bytes)',
 'pageinfo-article-id' => 'Zied-ID',
 'pageinfo-language' => 'Taal veur de zied',
+'pageinfo-content-model' => 'Ziedinhoudsmodel',
 'pageinfo-robot-policy' => 'Indexering deur bots',
 'pageinfo-robot-index' => 'Toe-estaon',
 'pageinfo-robot-noindex' => 'Niet toe-estaon',
@@ -3708,7 +3726,7 @@ Aandere velden wörden verbörgen.
 
 # External editor support
 'edit-externally' => 'Wiezig dit bestaand mit n extern programma',
-'edit-externally-help' => '(Zie de [//www.mediawiki.org/wiki/Manual:External_editors installasie-instruksies] veur meer informasie)',
+'edit-externally-help' => '(Zie de [https://www.mediawiki.org/wiki/Manual:External_editors installasie-instruksies] veur meer informasie)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alles',
@@ -3797,6 +3815,9 @@ De bevestigingskode zal verlopen op $4.',
 'confirm-unwatch-button' => 'Oké',
 'confirm-unwatch-top' => 'Disse zied van joew volglieste aofhaolen?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '&larr; veurige',
 'imgmultipagenext' => 'volgende &rarr;',
@@ -3888,7 +3909,7 @@ Je kunnen oek [[Special:EditWatchlist|t standardbewarkingsscharm gebruken]].',
 'version-hook-subscribedby' => 'In-eschreven deur',
 'version-version' => '(Versie $1)',
 'version-license' => 'Lisensie',
-'version-poweredby-credits' => "Disse wiki wörden an-estuurd deur '''[//www.mediawiki.org/ MediaWiki]''', auteursrecht © 2001-$1 $2.",
+'version-poweredby-credits' => "Disse wiki wörden an-estuurd deur '''[https://www.mediawiki.org/ MediaWiki]''', auteursrecht © 2001-$1 $2.",
 'version-poweredby-others' => 'aanderen',
 'version-poweredby-translators' => 'vertalers van translatewiki.net',
 'version-credits-summary' => 'Wulen erkennen grege de volgende personen veur der biedrage an [[Special:Version|MediaWiki]].',
@@ -3907,7 +3928,7 @@ Samen mit dit programma heur je n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van de
 # Special:Redirect
 'redirect' => 'Deurverwiezen op bestaandsnaam, gebrukersnummer of versienummer',
 'redirect-legend' => 'Deurverwiezen naor n bestaand of zied',
-'redirect-summary' => 'Disse spesiale zied verwis deur naor n bestaand (as n bestaandsnaam op-egeven wörden), n zied (as n versienummer op-egeven wörden) of n gebrukerszied (as t gebrukersnummer op-egeven wörden).',
+'redirect-summary' => 'Disse spesiale zied verwis deur naor n bestaand (as de bestaandsnaam op-egeven wörden), n zied (as n versienummer op-egeven wörden) of n gebrukerszied (as t gebrukersnummer op-egeven wörden). Gebruuk: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], of [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Zeuk',
 'redirect-lookup' => 'Opzeuken:',
 'redirect-value' => 'Weerde:',
@@ -3929,8 +3950,7 @@ Samen mit dit programma heur je n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van de
 
 # Special:SpecialPages
 'specialpages' => 'Spesiale ziejen',
-'specialpages-note' => '----
-* Normale spesiale ziejen.
+'specialpages-note' => '* Normale spesiale ziejen.
 * <strong class="mw-specialpagerestricted">Beparkt toegankelike spesiale ziejen.</strong>
 * <span class="mw-specialpagecached">Spesiale ziejen mit allinnig gegevens uut t tussengeheugen (kunnen verouwerd ween).</span>',
 'specialpages-group-maintenance' => 'Onderhoudsliesten',
@@ -3944,7 +3964,7 @@ Samen mit dit programma heur je n [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van de
 'specialpages-group-pagetools' => 'Ziedhulpmiddels',
 'specialpages-group-wiki' => 'Gegevens en hulpmiddels',
 'specialpages-group-redirects' => 'Deurverwiezende spesiale ziejen',
-'specialpages-group-spam' => 'Hulpmiddels tegen ongewunste bewarkingen',
+'specialpages-group-spam' => 'Spam-hulpmiddels',
 
 # Special:BlankPage
 'blankpage' => 'Lege zied',
@@ -4145,4 +4165,17 @@ Aanders ku\'j oek t eenvoudige formulier hieronder gebruken. Joew kommentaar zal
 'limitreport-expansiondepth' => 'Hoogste uutbreidingsdiepte',
 'limitreport-expensivefunctioncount' => 'Antal kostbaore parserfunksies',
 
+# Special:ExpandTemplates
+'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_output' => 'Resultaot',
+'expand_templates_xml_output' => 'XML-uutvoer',
+'expand_templates_ok' => 'Oké',
+'expand_templates_remove_comments' => 'Opmarking vorthaolen',
+'expand_templates_remove_nowiki' => 'Etiketten <nowiki> in resultaot onderdrokken',
+'expand_templates_generate_xml' => 'XML-parserboom bekieken',
+'expand_templates_preview' => 'Naokieken',
+
 );
index 6abbfda..a998926 100644 (file)
@@ -193,8 +193,6 @@ $messages = array(
 'noindex-category' => 'क्रमांकन नगरिएका पृष्ठहरु',
 'broken-file-category' => 'टुटेको फाइल लिंकसितको पृष्ठ',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'बारेमा',
 'article' => 'सामाग्री पृष्ठ',
 'newwindow' => '(नयाँ विन्डोमा खुल्छ)',
@@ -333,8 +331,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => ' "$1" बाट निकालिएको',
 'youhavenewmessages' => 'तपाईंको लागि ($2) मा  $1 छ ।',
-'newmessageslink' => 'नयाँ सन्देशहरू',
-'newmessagesdifflink' => 'आखिरी परिवर्तन',
 'youhavenewmessagesfromusers' => 'तपाईंको लागि  {{PLURAL:$3|प्रयोगकर्ता|$3 प्रयोगकर्ताहरु}} ($2) बाट $1',
 'youhavenewmessagesmanyusers' => 'तपाईँलाई धेरै प्रयोगकर्ताहरू($2) बाट $1 छ ।',
 'newmessageslinkplural' => '{{PLURAL:$1|नयाँ सन्देश|नयाँ सन्देशहरू}}',
@@ -851,6 +847,11 @@ $2
 'edit-already-exists' => 'नयाँ पृष्ठ बनाउन सकिएन ।
 यो पहिले देखि नै रहेको छ।',
 
+# Content models
+'content-model-wikitext' => 'विकिपाठ',
+'content-model-text' => 'साधारण पाठ',
+'content-model-javascript' => 'जाभास्क्रिप्ट',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''चेतावनी:''' यस पृष्टका अति धेरै संख्याका महँगा पार्सर फंक्सन कल्स (expensive parser function calls)  छन्।
 यसमा $2 भन्दा कम {{PLURAL:$2|कल|कल्स}} हुनुपर्छ,  यहाँ {{PLURAL:$1|अहिले $1 कल छ|अहिले $1 कल्स छ्न्}}.",
@@ -954,10 +955,10 @@ $2
 'revdelete-selected' => "'''[[:$1]]को {{PLURAL:$2|छानिएको संस्करण|छानिएका संस्करणहरु}}  :'''",
 'logdelete-selected' => "'''{{PLURAL:$1|छानिएको लग घटना|छानिएका लग घटनाहरु}}:'''",
 'revdelete-legend' => 'दृष्टि बन्देज मिलाउने',
-'revdelete-hide-text' => 'पुनरावलोकन पाठ लुकाउने',
+'revdelete-hide-text' => 'पुनरावलोकन पाठ',
 'revdelete-hide-image' => 'फाइल कमेन्ट लुकाउने',
 'revdelete-hide-name' => 'कार्य र गन्तब्य लुकाउने',
-'revdelete-hide-comment' => 'सम्पादन टिप्पणी लुकाउने',
+'revdelete-hide-comment' => 'सम्पादन टिप्पणी',
 'revdelete-hide-user' => 'सम्पादकको प्रयोगकर्ता नाम/IP लुकाउने',
 'revdelete-hide-restricted' => 'प्रवन्धक वा अरुबाट डेटा कम लिने',
 'revdelete-radio-same' => '(परिवर्तन नगर्नुहोस्)',
@@ -1108,8 +1109,6 @@ $1",
 'preferences' => 'रोजाईहरू',
 'mypreferences' => 'प्राथमिकताहरु',
 'prefs-edits' => 'सम्पादन संख्या:',
-'prefsnologin' => 'प्रवेश (लग ईन) नगरिएको',
-'prefsnologintext' => 'प्रयोगकर्ता अभिरूचि निर्धारण गर्न <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ]</span>तपाईंले प्रवेश गरेको हुनुपर्छ।',
 'changepassword' => 'पासवर्ड परिवर्तन गर्नुहोस्',
 'prefs-skin' => 'काँचुली',
 'skin-preview' => 'पूर्वावलोकन',
@@ -1117,6 +1116,7 @@ $1",
 'prefs-beta' => 'बिटा गुणहरु',
 'prefs-datetime' => 'मिति र समय',
 'prefs-labs' => 'प्रयोगशाला गुणहरु',
+'prefs-user-pages' => 'प्रयोगकर्ता पृष्ठहरू',
 'prefs-personal' => 'प्रयोगकर्ताको विवरण',
 'prefs-rc' => 'नयाँ परिवर्तनहरु',
 'prefs-watchlist' => 'अवलोकन पृष्ठ',
@@ -1209,6 +1209,8 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'prefs-dateformat' => 'मिति ढाँचा',
 'prefs-timeoffset' => 'समय अफसेट',
 'prefs-advancedediting' => 'सामान्य विकल्पहरू',
+'prefs-editor' => 'सम्पादक',
+'prefs-preview' => 'पूर्वावलोकन',
 'prefs-advancedrc' => 'उन्नत विकल्पहरू',
 'prefs-advancedrendering' => 'उन्नत विकल्पहरु',
 'prefs-advancedsearchoptions' => 'उन्नत विकल्पहरू',
@@ -1216,6 +1218,7 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'prefs-displayrc' => 'प्रदर्शन विकल्पहरू',
 'prefs-displaysearchoptions' => 'प्रदर्शन विकल्पहरू',
 'prefs-displaywatchlist' => 'प्रदर्शन विकल्पहरू',
+'prefs-tokenwatchlist' => 'टोकन',
 'prefs-diffs' => 'diffs(भिन्नता)',
 
 # User preference: email validation using jQuery
@@ -1374,6 +1377,7 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|परिवर्तन|परिवर्तनहरु}}',
+'enhancedrc-history' => 'इतिहास',
 'recentchanges' => 'नयाँ परिवर्तनहरु',
 'recentchanges-legend' => 'हालैको परिवर्तन विकल्पहरु',
 'recentchanges-summary' => 'विकिका भर्खरका परिवर्तनहरुलाई यस पृष्ठमा पहिल्याउने',
@@ -1382,6 +1386,7 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'recentchanges-label-minor' => 'यो साधारण सम्पादन हो',
 'recentchanges-label-bot' => 'यो सम्पादन बोट द्वारा गरिएको थियो',
 'recentchanges-label-unpatrolled' => 'यो सम्पादन अहिले सम्म पट्रोल गरिएको छैन',
+'recentchanges-legend-newpage' => '$1 - नयाँ पृष्ठ',
 'rcnote' => "तल पछिल्ला {{PLURAL:$2|day|'''$2''' दिनहरु}} मा  $5, $4 सम्म भएका {{PLURAL:$1|is '''1''' change|पछिल्ला '''$1''' परिवर्तनहरु}} देखाइएको छ ।",
 'rcnotefrom' => "'''$2''' देखिका परिवर्तनहरु तल ('''$1''' सम्मका देखाइन्छ)।",
 'rclistfrom' => '$1 देखिका नयाँ परिवर्तनहरू देखाउनु',
@@ -1589,6 +1594,8 @@ $1',
 'listfiles_size' => 'आकार',
 'listfiles_description' => 'वर्णन',
 'listfiles_count' => 'संस्करणहरु',
+'listfiles-latestversion-yes' => 'हो',
+'listfiles-latestversion-no' => 'हैन',
 
 # File description page
 'file-anchor-link' => 'फाईल',
@@ -1903,7 +1910,7 @@ $1',
 'notanarticle' => 'सामाग्री सहितको पेज हैन',
 'notvisiblerev' => 'पूर्वावलोकन हटाइयो',
 'watchlist-details' => 'तपाईको निगरानी सूचीमा रहेका{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठहरु}}वार्तालापमा पृष्ठमा गनिएका छैनन् ।',
-'wlheader-enotif' => 'ईमेलद्वारा जानकारी गराउने तरिका सक्रिय गरियो ।',
+'wlheader-enotif' => 'ईमेल जानकारी सक्रिय गरियो ।',
 'wlheader-showupdated' => "तपाइले पछिल्लो पल्ट भ्रमण गरेपछि परिवर्तन भएका पृष्ठहरूलाई '''गाढा''' गरेर देखाइएको छ ।",
 'watchmethod-recent' => 'निगरानी सुचीमा रहेका पृष्ठमा गरिएका सम्पादनहरु जाँच्दै',
 'watchmethod-list' => 'सम्पदान गरिएका निगरानी सुचीमा रहेका पृष्ठहरुको सम्पादन जाँच्दै',
@@ -2401,7 +2408,7 @@ $1को बन्देजको कारण : "$2" हो',
 'allmessagesdefault' => 'डिफल्ट सन्देश पाठ',
 'allmessagescurrent' => 'वर्तमान सन्देश पाठ',
 'allmessagestext' => 'यो मीडियाविकि नेमस्पेसमा पाइने सिस्टम सन्देशहरूको सूची हो।
-यदि तपाईं व्यापक मीडिया विकि स्थानीयकरणमा योगदान गर्न चाहनुहुन्छ भनें कृपया [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation]मा र [//translatewiki.net translatewiki.net]मा जानुहोस्।',
+यदि तपाईं व्यापक मीडिया विकि स्थानीयकरणमा योगदान गर्न चाहनुहुन्छ भनें कृपया [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation]मा र [//translatewiki.net translatewiki.net]मा जानुहोस्।',
 'allmessages-filter-legend' => 'फिल्टर',
 'allmessages-filter-unmodified' => 'असंशोधित',
 'allmessages-filter-all' => 'सबै',
@@ -3067,7 +3074,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'यो फाइललाई बाह्य अनुप्रयोग प्रयोग गरेर सम्पादन गर्ने',
-'edit-externally-help' => '(थप जानकारीको लागि [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] मा हेर्नुहोस् )',
+'edit-externally-help' => '(थप जानकारीको लागि [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] मा हेर्नुहोस् )',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'सबै',
@@ -3318,7 +3325,7 @@ $5
 'version-version' => '(संस्करण $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'इजाजतपत्र',
-'version-poweredby-credits' => "यो विकी '''[//www.mediawiki.org/ मिडियाविकि]''' द्वारा सशक्तिकरण गरिएको छ, copyright © सन् २००१-$1 $2.",
+'version-poweredby-credits' => "यो विकी '''[https://www.mediawiki.org/ मिडियाविकि]''' द्वारा सशक्तिकरण गरिएको छ, copyright © सन् २००१-$1 $2.",
 'version-poweredby-others' => 'अन्य',
 'version-software' => 'स्थापना गरिएको सफ्टवेयर',
 'version-software-product' => 'उत्पादन',
@@ -3337,8 +3344,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'विशेष पृष्ठ',
-'specialpages-note' => '----
-* साधारण विशेष पृष्ठहरु।
+'specialpages-note' => '* साधारण विशेष पृष्ठहरु।
 * <span class="mw-specialpagerestricted">निषेधित विशेष पृष्ठहरु।</span>
 * <span class="mw-specialpagecached">क्याश गरिएका विशेष पृष्ठहरु (अध्यावधिक नहुन सक्छ)।</span>',
 'specialpages-group-maintenance' => 'मर्मत प्रतिवेदनहरु',
index ae86c2f..908187f 100644 (file)
  * @author AvatarTeam
  * @author B4bol4t
  * @author Basvb
+ * @author Breghtje
  * @author DasRakel
  * @author Effeietsanders
  * @author Erwin
  * @author Erwin85
  * @author Extended by Hendrik Maryns <hendrik.maryns@uni-tuebingen.de>, March 2007.
+ * @author Flightmare
  * @author Fryed-peach
  * @author Galwaygirl
  * @author Geitost
@@ -176,7 +178,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'gecentreerd', 'center', 'centre' ),
        'img_framed'                => array( '1', 'omkaderd', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'kaderloos', 'frameless' ),
-       'img_page'                  => array( '1', 'pagina=$1', 'pagina $1', 'page=$1', 'page $1' ),
+       'img_lang'                  => array( '1', 'taal=$1', 'lang=$1' ),
+       'img_page'                  => array( '1', 'pagina=$1', 'pagina_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'rechtop', 'rechtop=$1', 'rechtop$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'rand', 'border' ),
        'img_baseline'              => array( '1', 'grondlijn', 'baseline' ),
@@ -186,6 +189,7 @@ $magicWords = array(
        'img_bottom'                => array( '1', 'beneden', 'bottom' ),
        'img_text_bottom'           => array( '1', 'tekst-beneden', 'text-bottom' ),
        'img_link'                  => array( '1', 'koppeling=$1', 'verwijzing=$1', 'link=$1' ),
+       'img_class'                 => array( '1', 'klasse=$1', 'class=$1' ),
        'sitename'                  => array( '1', 'SITENAAM', 'SITENAME' ),
        'ns'                        => array( '0', 'NR:', 'NS:' ),
        'nse'                       => array( '0', 'NRE:', 'NSE:' ),
@@ -212,6 +216,7 @@ $magicWords = array(
        'revisionyear'              => array( '1', 'VERSIEJAAR', 'REVISIONYEAR' ),
        'revisiontimestamp'         => array( '1', 'VERSIETIJD', 'REVISIONTIMESTAMP' ),
        'revisionuser'              => array( '1', 'VERSIEGEBRUIKER', 'REVISIONUSER' ),
+       'revisionsize'              => array( '1', 'VERSIEGROOTTE', 'REVISIONSIZE' ),
        'plural'                    => array( '0', 'MEERVOUD:', 'PLURAL:' ),
        'fullurl'                   => array( '0', 'VOLLEDIGEURL:', 'FULLURL:' ),
        'fullurle'                  => array( '0', 'VOLLEDIGEURLE:', 'FULLURLE:' ),
@@ -266,12 +271,12 @@ $magicWords = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'ActieveGebruikers' ),
        'Allmessages'               => array( 'AlleBerichten', 'Systeemberichten' ),
+       'AllMyUploads'              => array( 'AlMijnUploads' ),
        'Allpages'                  => array( 'AllePaginas', 'AllePagina’s', 'AllePagina\'s' ),
        'Ancientpages'              => array( 'OudstePaginas', 'OudstePagina’s', 'OudstePagina\'s' ),
        'Badtitle'                  => array( 'OnjuistePaginanaam' ),
        'Blankpage'                 => array( 'LegePagina' ),
        'Block'                     => array( 'Blokkeren', 'IPblokkeren', 'BlokkeerIP', 'BlokkeerIp' ),
-       'Blockme'                   => array( 'BlokkeerMij', 'MijBlokkeren' ),
        'Booksources'               => array( 'Boekbronnen', 'Boekinformatie' ),
        'BrokenRedirects'           => array( 'GebrokenDoorverwijzingen' ),
        'Categories'                => array( 'Categorieën' ),
@@ -283,10 +288,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'GebruikerAanmaken' ),
        'Deadendpages'              => array( 'VerwijslozePaginas', 'VerwijslozePagina’s', 'VerwijslozePagina\'s' ),
        'DeletedContributions'      => array( 'VerwijderdeBijdragen' ),
-       'Disambiguations'           => array( 'Doorverwijzingen' ),
        'DoubleRedirects'           => array( 'DubbeleDoorverwijzingen' ),
        'EditWatchlist'             => array( 'VolglijstBewerken' ),
        'Emailuser'                 => array( 'GebruikerE-mailen', 'E-mailGebruiker' ),
+       'ExpandTemplates'           => array( 'SjablonenSubstitueren' ),
        'Export'                    => array( 'Exporteren' ),
        'Fewestrevisions'           => array( 'MinsteVersies', 'MinsteHerzieningen', 'MinsteRevisies' ),
        'FileDuplicateSearch'       => array( 'BestandsduplicatenZoeken' ),
@@ -330,10 +335,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'BeveiligdePaginas', 'BeveiligdePagina\'s', 'BeschermdePaginas', 'BeschermdePagina’s', 'BeschermdePagina\'s' ),
        'Protectedtitles'           => array( 'BeveiligdeTitels', 'BeschermdeTitels' ),
        'Randompage'                => array( 'Willekeurig', 'WillekeurigePagina' ),
+       'RandomInCategory'          => array( 'WillekeurigeUitCategorie' ),
        'Randomredirect'            => array( 'WillekeurigeDoorverwijzing' ),
        'Recentchanges'             => array( 'RecenteWijzigingen' ),
        'Recentchangeslinked'       => array( 'RecenteWijzigingenGelinkt', 'VerwanteWijzigingen' ),
        'Redirect'                  => array( 'Doorverwijzen' ),
+       'ResetTokens'               => array( 'TokensOpnieuwInstellen' ),
        'Revisiondelete'            => array( 'VersieVerwijderen', 'HerzieningVerwijderen', 'RevisieVerwijderen' ),
        'Search'                    => array( 'Zoeken' ),
        'Shortpages'                => array( 'KortePaginas', 'KortePagina’s', 'KortePagina\'s' ),
@@ -644,12 +651,10 @@ Meer informatie is beschikbaar op de pagina [[Special:Version|softwareversie]].'
 'ok' => 'OK',
 'retrievedfrom' => 'Overgenomen van "$1"',
 'youhavenewmessages' => 'U hebt $1 ($2).',
-'newmessageslink' => 'nieuwe berichten',
-'newmessagesdifflink' => 'laatste wijziging',
 'youhavenewmessagesfromusers' => 'U heeft $1 van {{PLURAL:$3|een andere gebruiker|$3 gebruikers}} ($2).',
 'youhavenewmessagesmanyusers' => 'U heeft $1 van een groot aantal gebruikers ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|een nieuw bericht|nieuwe berichten}}',
-'newmessagesdifflinkplural' => 'laatste {{PLURAL:$1|wijziging|wijzigingen}}',
+'newmessageslinkplural' => '{{PLURAL:$1|een nieuw bericht|999=nieuwe berichten}}',
+'newmessagesdifflinkplural' => 'laatste {{PLURAL:$1|wijziging|999=wijzigingen}}',
 'youhavenewmessagesmulti' => 'U hebt nieuwe berichten op $1',
 'editsection' => 'bewerken',
 'editold' => 'bewerken',
@@ -783,7 +788,8 @@ De opgegeven reden is "\'\'$3\'\'".',
 'invalidtitle-knownnamespace' => 'Ongeldige titel met naamruimte "$2" en tekst "$3"',
 'invalidtitle-unknownnamespace' => 'Ongeldige titel met onbekend naamruimtenummer $1 en tekst "$2"',
 'exception-nologin' => 'Niet aangemeld',
-'exception-nologin-text' => 'Om deze pagina te bekijken of deze handeling uit te kunnen voeren moet u aangemeld zijn bij deze wiki.',
+'exception-nologin-text' => '[[Special:Userlogin|Meld u aan]] om deze pagina te bekijken of deze handeling uit te voeren.',
+'exception-nologin-text-manual' => 'U moet $1 om deze pagina te kunnen bekijken of de handeling uit te voeren.',
 
 # Virus scanner
 'virus-badscanner' => "Onjuiste configuratie: onbekende virusscanner: ''$1''.",
@@ -822,7 +828,7 @@ Vergeet niet uw [[Special:Preferences|voorkeuren voor {{SITENAME}}]] aan te pass
 'logout' => 'Afmelden',
 'userlogout' => 'Afmelden',
 'notloggedin' => 'Niet aangemeld',
-'userlogin-noaccount' => 'Hebt u geen geregistreerde gebruiker?',
+'userlogin-noaccount' => 'Hebt u geen account?',
 'userlogin-joinproject' => 'Word lid van {{SITENAME}}',
 'nologin' => 'Nog geen gebruikersnaam? $1.',
 'nologinlink' => 'Registreren',
@@ -830,7 +836,7 @@ Vergeet niet uw [[Special:Preferences|voorkeuren voor {{SITENAME}}]] aan te pass
 'gotaccount' => 'Hebt u al een gebruikersnaam? $1.',
 'gotaccountlink' => 'Aanmelden',
 'userlogin-resetlink' => 'Bent u uw aanmeldgegevens vergeten?',
-'userlogin-resetpassword-link' => 'Uw wachtwoord opnieuw instellen',
+'userlogin-resetpassword-link' => 'Wachtwoord vergeten?',
 'helplogin-url' => 'Help:Aanmelden',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hulp bij aanmelden]]',
 'userlogin-loggedin' => 'U bent al aangemeld als {{GENDER:$1|$1}}.
@@ -915,7 +921,7 @@ Om misbruik te voorkomen wordt er slechts één wachtwoordherinnering per {{PLUR
 Daarom kunt u vanaf uw IP-adres op dit moment geen nieuwe gebruikers registreren.',
 'emailauthenticated' => 'Uw e-mailadres is bevestigd op $2 om $3.',
 'emailnotauthenticated' => 'Uw e-mailadres is niet bevestigd.
-U ontvangt geen e-mail voor de onderstaande functies.',
+De volgende functies verzenden nog geen e-mail.',
 'noemailprefs' => 'Geef een e-mailadres op in uw voorkeuren om deze functies te gebruiken.',
 'emailconfirmlink' => 'Bevestig uw e-mailadres',
 'invalidemailaddress' => 'Het e-mailadres is niet aanvaard, omdat het een ongeldige opmaak heeft.
@@ -1212,7 +1218,7 @@ U kunt reeds bestaande pagina's wijzigen of u kunt [[Special:UserLogin|zich aanm
 'sectioneditnotsupported-text' => 'Het is op deze pagina niet mogelijk om paragrafen te bewerken.',
 'permissionserrors' => 'Fouten in rechten',
 'permissionserrorstext' => 'U hebt geen rechten om dit te doen om de volgende {{PLURAL:$1|reden|redenen}}:',
-'permissionserrorstext-withaction' => 'U hebt geen rechten om $2 om de volgende {{PLURAL:$1|reden|redenen}}:',
+'permissionserrorstext-withaction' => 'U hebt geen rechten om $2, {{PLURAL:$1|want}}:',
 'recreate-moveddeleted-warn' => "'''Waarschuwing: u bent bezig met het aanmaken van een pagina die in het verleden verwijderd is.'''
 
 Overweeg of het terecht is dat u verder werkt aan deze pagina.
@@ -1358,19 +1364,20 @@ U kunt deze verschillen bekijken. Er kunnen details te vinden zijn in het [{{ful
 'revdelete-text' => "'''Verwijderde bewerkingen zijn zichtbaar in de geschiedenis en logboeken, maar delen van de inhoud zijn niet langer publiek toegankelijk.'''
 Andere beheerders van {{SITENAME}} kunnen de verborgen inhoud benaderen en de verwijdering ongedaan maken met behulp van dit formulier, tenzij er aanvullende beperkingen gelden die zijn ingesteld door de systeembeheerder.",
 'revdelete-confirm' => 'Bevestig dat u dit wilde doen, dat u de consequenties begrijpt en dat u dit doet in overeenstemming met het geldende [[{{MediaWiki:Policy-url}}|beleid]].',
-'revdelete-suppress-text' => "Versies verbergen dient '''alleen''' gebruikt te worden in de volgende gevallen:
-* Ongepaste persoonlijke informatie
-*: ''woonadres, telefoonnummers, Burger Service Nummers, enzovoort.''",
+'revdelete-suppress-text' => "Gebruik versies verbergen '''alleen''' in de volgende gevallen:
+* Mogelijk smadelijke informatie;
+* Ongepaste persoonlijke gegevens, zoals:
+*: ''adres, telefoonnummers, Burger Service Nummers, enzovoort.''",
 'revdelete-legend' => 'Zichtbaarheidsbeperkingen instellen',
-'revdelete-hide-text' => 'Bewerkte tekst verbergen',
+'revdelete-hide-text' => 'Versietekst',
 'revdelete-hide-image' => 'Bestandsinhoud verbergen',
 'revdelete-hide-name' => 'Handeling en doel verbergen',
-'revdelete-hide-comment' => 'Bewerkingssamenvatting verbergen',
-'revdelete-hide-user' => 'Gebruikersnaam/IP-adres van de gebruiker verbergen',
+'revdelete-hide-comment' => 'Bewerkingssamenvatting',
+'revdelete-hide-user' => 'Gebruikersnaam of IP-adres van de gebruiker',
 'revdelete-hide-restricted' => 'Deze beperkingen ook op beheerders toepassen',
 'revdelete-radio-same' => '(niet wijzigen)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nee',
+'revdelete-radio-set' => 'Verborgen',
+'revdelete-radio-unset' => 'Zichtbaar',
 'revdelete-suppress' => 'Gegevens voor zowel beheerders als anderen onderdrukken',
 'revdelete-unsuppress' => 'Beperkingen op teruggeplaatste wijzigingen verwijderen',
 'revdelete-log' => 'Reden:',
@@ -1531,8 +1538,7 @@ De gegevens over {{SITENAME}} zijn mogelijk niet bijgewerkt.',
 'preferences' => 'Voorkeuren',
 'mypreferences' => 'Voorkeuren',
 'prefs-edits' => 'Aantal bewerkingen:',
-'prefsnologin' => 'Niet aangemeld',
-'prefsnologintext' => 'U moet <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} aangemeld]</span> zijn om uw voorkeuren te kunnen instellen.',
+'prefsnologintext2' => 'U moet $1 om voorkeuren in te stellen.',
 'changepassword' => 'Wachtwoord wijzigen',
 'prefs-skin' => 'Vormgeving',
 'skin-preview' => 'Voorvertoning',
@@ -1725,7 +1731,7 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'right-bot' => 'Behandeld worden als een geautomatiseerd proces',
 'right-nominornewtalk' => "Kleine bewerkingen aan een overlegpagina leiden niet tot een melding 'nieuwe berichten'",
 'right-apihighlimits' => 'Hogere limieten in API-zoekopdrachten gebruiken',
-'right-writeapi' => 'Bewerken via de API',
+'right-writeapi' => 'Via de API bewerkingen uitvoeren',
 'right-delete' => "Pagina's verwijderen",
 'right-bigdelete' => "Pagina's met een grote geschiedenis verwijderen",
 'right-deletelogentry' => 'Specifieke logboekregels verwijderen en terugplaatsen',
@@ -1756,7 +1762,7 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'right-viewmyprivateinfo' => 'Uw eigen privégegevens bekijken (bijvoorbeeld e-mailadres, echte naam)',
 'right-editmyprivateinfo' => 'Uw eigen privégegevens bewerken (bijvoorbeeld e-mailadres, echte naam)',
 'right-editmyoptions' => 'Uw eigen voorkeuren bewerken',
-'right-rollback' => 'Snel de laatste bewerking(en) van een gebruiker van een pagina terugdraaien',
+'right-rollback' => 'De bewerkingen van de laatste gebruiker die een pagina heeft bewerkt snel terugdraaien',
 'right-markbotedits' => 'Teruggedraaide bewerkingen markeren als botbewerkingen',
 'right-noratelimit' => 'Tijdsafhankelijke beperkingen negeren',
 'right-import' => "Pagina's uit andere wiki's importeren",
@@ -1796,7 +1802,7 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'action-reupload' => 'dit bestaande bestand te overschrijven',
 'action-reupload-shared' => 'dit bestand te uploaden, terwijl er al een bestand met dezelfde naam in de gedeelde mediadatabank staat',
 'action-upload_by_url' => 'dit bestand vanaf een URL te uploaden',
-'action-writeapi' => 'via de API te bewerken',
+'action-writeapi' => 'via de API bewerkingen uit te voeren',
 'action-delete' => 'deze pagina te verwijderen',
 'action-deleterevision' => 'deze versie te verwijderen',
 'action-deletedhistory' => 'de verwijderde versies van deze pagina te bekijken',
@@ -1806,7 +1812,7 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'action-suppressionlog' => 'dit beschermde logboek te bekijken',
 'action-block' => 'deze gebruiker een bewerkingsblokkade op te leggen',
 'action-protect' => 'het beveiligingsniveau van deze pagina aan te passen',
-'action-rollback' => 'bewerkingen van de laatste gebruiker die een pagina heeft bewerkt snel terugdraaien',
+'action-rollback' => 'de bewerkingen van de laatste gebruiker die een pagina heeft bewerkt snel terug te draaien',
 'action-import' => "pagina's te importeren van een andere wiki",
 'action-importupload' => "pagina's te importeren uit een bestandsupload",
 'action-patrol' => 'bewerkingen van anderen als gecontroleerd te markeren',
@@ -1831,10 +1837,13 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'recentchanges-summary' => 'Op deze pagina kunt u de recentste wijzigingen in deze wiki bekijken.',
 'recentchanges-noresult' => 'Er zijn in deze periode geen wijzigingen gemaakt die aan de criteria voldoen.',
 'recentchanges-feed-description' => 'Met deze feed kunt u de recentste wijzigingen in deze wiki bekijken.',
-'recentchanges-label-newpage' => 'Met deze bewerking is een nieuwe pagina aangemaakt',
+'recentchanges-label-newpage' => 'Met deze bewerking is een nieuwe pagina aangemaakt.',
 'recentchanges-label-minor' => 'Dit is een kleine bewerking',
 'recentchanges-label-bot' => 'Deze bewerking is uitgevoerd door een bot',
 'recentchanges-label-unpatrolled' => 'Deze bewerking is nog niet gecontroleerd',
+'recentchanges-label-plusminus' => 'Deze paginagrootte is met dit aantal bytes gewijzigd',
+'recentchanges-legend-newpage' => "Zie ook de [[Special:NewPages|Lijst met nieuwe pagina's]].",
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Hieronder {{PLURAL:$1|staat de laatste bewerking|staan de laatste '''$1''' bewerkingen}} in de laatste {{PLURAL:$2|dag|'''$2''' dagen}}, op $4 om $5.",
 'rcnotefrom' => "Wijzigingen sinds '''$2''' (met een maximum van '''$1''' wijzigingen).",
 'rclistfrom' => 'Wijzigingen bekijken vanaf $1',
@@ -2587,7 +2596,7 @@ Contactgegevens van de auteur:
 E-mailadres: $PAGEEDITOR_EMAIL
 Wiki: $PAGEEDITOR_WIKI
 
-Tenzij u deze pagina bezoekt, komen er geen verdere berichten. Op uw volglijst kunt u voor alle gevolgde pagina\'s de waarschuwingsinstellingen opschonen.
+Tenzij u deze pagina bezoekt, komen er geen verdere berichten. Als u bent aangemeld, kunt u op uw volglijst voor alle gevolgde pagina\'s de waarschuwingsinstellingen opschonen.
 
 Groet van uw {{SITENAME}}-waarschuwingssysteem.
 
@@ -3119,7 +3128,7 @@ In het laatste geval kunt u ook een koppeling gebruiken, bijvoorbeeld [[{{#Speci
 'allmessagesdefault' => 'Standaardinhoud',
 'allmessagescurrent' => 'Huidige inhoud',
 'allmessagestext' => 'Hieronder staan de systeemberichten uit de MediaWiki-naamruimte.
-Ga naar [//www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] als u wilt bijdragen aan de algemene vertaling voor MediaWiki.',
+Ga naar [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokalisatie] en [//translatewiki.net translatewiki.net] als u wilt bijdragen aan de algemene vertaling voor MediaWiki.',
 'allmessagesnotsupportedDB' => "Deze pagina kan niet worden gebruikt, omdat '''\$wgUseDatabaseMessages''' is uitgeschakeld.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filteren op aangepast:',
@@ -3285,7 +3294,7 @@ U kunt wel de broncode bekijken.',
 'tooltip-undo' => 'Met "ongedaan maken" draait u deze bewerking terug en komt in het bewerkingsvenster. U kunt in de bewerkingssamenvatting een reden opgeven.',
 'tooltip-preferences-save' => 'Voorkeuren opslaan',
 'tooltip-summary' => 'Voer een korte samenvatting in',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/** CSS die hier wordt geplaatst heeft invloed op alle skins */',
@@ -3335,6 +3344,8 @@ Meestal wordt dit door een externe koppeling op een zwarte lijst veroorzaakt.',
 'spam_reverting' => 'Teruggedraaid naar de laatste versie die geen koppeling bevat naar $1',
 'spam_blanking' => 'Alle versies bevatten een koppeling naar $1. Pagina leeggemaakt',
 'spam_deleting' => 'Alle versies bevatten koppelingen naar $1. Pagina verwijderd',
+'simpleantispam-label' => "Antispamcontrole.
+Vul dit veld '''NIET''' in!",
 
 # Info page
 'pageinfo-title' => 'Informatie over "$1"',
@@ -3348,6 +3359,7 @@ Meestal wordt dit door een externe koppeling op een zwarte lijst veroorzaakt.',
 'pageinfo-length' => 'Paginalengte (in bytes)',
 'pageinfo-article-id' => 'Paginanummer',
 'pageinfo-language' => 'Taal voor de pagina',
+'pageinfo-content-model' => 'Paginainhoudmodel',
 'pageinfo-robot-policy' => 'Indexering door robots',
 'pageinfo-robot-index' => 'Toegestaan',
 'pageinfo-robot-noindex' => 'Niet toegestaan',
@@ -3434,7 +3446,7 @@ $1',
 'svg-long-desc' => 'SVG-bestand, nominaal $1 × $2 pixels, bestandsgrootte: $3',
 'svg-long-desc-animated' => 'Bewegend SVG-bestand, nominaal $1 × $2 pixels, bestandsgrootte: $3',
 'svg-long-error' => 'Ongeldig SVG-bestand: $1',
-'show-big-image' => 'Volledige resolutie',
+'show-big-image' => 'Oorspronkelijk bestand',
 'show-big-image-preview' => 'Grootte van deze voorvertoning: $1.',
 'show-big-image-other' => 'Andere {{PLURAL:$2|resolutie|resoluties}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3474,13 +3486,13 @@ $1',
 'hours-ago' => '$1 {{PLURAL:$1|uur}} geleden',
 'minutes-ago' => '$1 {{PLURAL:$1|minuut|minuten}} geleden',
 'seconds-ago' => '$1 {{PLURAL:$1|seconde|seconden}} geleden',
-'monday-at' => 'Maandag om $1',
-'tuesday-at' => 'Dinsdag om $1',
-'wednesday-at' => 'Woensdag om $1',
-'thursday-at' => 'Donderdag om $1',
-'friday-at' => 'Vrijdag om $1',
-'saturday-at' => 'Zaterdag om $1',
-'sunday-at' => 'Zondag om $1',
+'monday-at' => 'maandag om $1',
+'tuesday-at' => 'dinsdag om $1',
+'wednesday-at' => 'woensdag om $1',
+'thursday-at' => 'donderdag om $1',
+'friday-at' => 'vrijdag om $1',
+'saturday-at' => 'zaterdag om $1',
+'sunday-at' => 'zondag om $1',
 'yesterday-at' => 'Gisteren om $1',
 
 # Bad image list
@@ -3903,7 +3915,7 @@ Andere velden worden verborgen.
 
 # External editor support
 'edit-externally' => 'Dit bestand in een extern programma bewerken',
-'edit-externally-help' => '(zie de [//www.mediawiki.org/wiki/Manual:External_editors handleiding voor instellingen] voor meer informatie)',
+'edit-externally-help' => '(zie de [https://www.mediawiki.org/wiki/Manual:External_editors handleiding voor instellingen] voor meer informatie)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alles',
@@ -4001,6 +4013,9 @@ Bevestig dat u de pagina opnieuw wilt aanmaken.',
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Deze pagina verwijderen uit uw volglijst?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '← vorige pagina',
 'imgmultipagenext' => 'volgende pagina →',
@@ -4106,7 +4121,7 @@ U kunt ook [[Special:EditWatchlist|het standaard bewerkingsscherm gebruiken]].',
 'version-hook-subscribedby' => 'Geabonneerd door',
 'version-version' => '(Versie $1)',
 'version-license' => 'Licentie',
-'version-poweredby-credits' => "Deze wiki wordt aangedreven door '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Deze wiki wordt aangedreven door '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'anderen',
 'version-poweredby-translators' => 'translatewiki.net-vertalers',
 'version-credits-summary' => 'We erkennen graag de volgende personen voor hun bijdrage aan [[Special:Version|MediaWiki]].',
@@ -4127,7 +4142,7 @@ Samen met dit programma hoort u een [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van
 # Special:Redirect
 'redirect' => 'Doorverwijzen op bestandsnaam, gebruikersnummer of versienummer',
 'redirect-legend' => 'Doorverwijzen naar een bestand of pagina',
-'redirect-summary' => 'Deze speciale pagina verwijst door naar een bestand (als een bestandsnaam wordt opgegeven), een pagina (als een versienummer wordt opgegeven) of een gebruikerspagina (als een gebruikersnummer wordt opgegeven).',
+'redirect-summary' => 'Deze speciale pagina verwijst door naar een bestand (als een bestandsnaam wordt opgegeven), een pagina (als een versienummer wordt opgegeven) of een gebruikerspagina (als een gebruikersnummer wordt opgegeven). Gebruik: [[{{#Special:Redirect}}/file/Voorbeeld.jpg]], [[{{#Special:Redirect}}/revision/328429]] of [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'OK',
 'redirect-lookup' => 'Opzoeken:',
 'redirect-value' => 'Waarde:',
@@ -4149,10 +4164,9 @@ Samen met dit programma hoort u een [{{SERVER}}{{SCRIPTPATH}}/COPYING kopie van
 
 # Special:SpecialPages
 'specialpages' => "Speciale pagina's",
-'specialpages-note' => '----
-* Normale speciale pagina\'s
-* <strong class="mw-specialpagerestricted">Beperkt toegankelijke speciale pagina\'s</strong>
-* <span class="mw-specialpagecached">Speciale pagina\'s met alleen gegevens uit de cache (mogelijk verouderd)</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Normale speciale pagina\'s
+* <span class="mw-specialpagerestricted">Beperkt toegankelijke speciale pagina\'s</span>',
 'specialpages-group-maintenance' => 'Onderhoudsrapporten',
 'specialpages-group-other' => "Overige speciale pagina's",
 'specialpages-group-login' => 'Aanmelden / registreren',
@@ -4365,4 +4379,21 @@ Anders kunt u ook het eenvoudige formulier hieronder gebruiken. Uw reactie wordt
 'limitreport-expansiondepth' => 'Hoogste uitbreidingsdiepte',
 'limitreport-expensivefunctioncount' => 'Aantal kostbare parserfuncties',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Sjablonen substitueren',
+'expand_templates_intro' => 'Deze speciale pagina leest de opgegeven tekst in en substitueert recursief alle sjablonen in de tekst.
+Het substitueert ook alle parserfuncties zoals
+<code><nowiki>{{</nowiki>#language:…}}</code> en
+variabelen als <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Vrijwel alle tekst tussen dubbele accolades wordt gesubstitueerd.',
+'expand_templates_title' => 'Contexttitel, voor {{FULLPAGENAME}}, enzovoort:',
+'expand_templates_input' => 'Invoertekst:',
+'expand_templates_output' => 'Resultaat',
+'expand_templates_xml_output' => 'XML-uitvoer',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Opmerkingen verwijderen',
+'expand_templates_remove_nowiki' => 'Tags <nowiki> in resultaat onderdrukken',
+'expand_templates_generate_xml' => 'XML-parserboom bekijken',
+'expand_templates_preview' => 'Voorvertoning',
+
 );
index 38d0da7..d9498da 100644 (file)
@@ -217,23 +217,23 @@ $namespaceNames = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Verksame_brukarar', 'Aktive_brukarar' ),
        'Allmessages'               => array( 'Alle_systemmeldingar' ),
+       'AllMyUploads'              => array( 'Alle_opplastingane_mine' ),
        'Allpages'                  => array( 'Alle_sider' ),
        'Ancientpages'              => array( 'Gamle_sider' ),
        'Badtitle'                  => array( 'Dårleg_tittel' ),
        'Blankpage'                 => array( 'Tom_side' ),
        'Block'                     => array( 'Blokker' ),
-       'Blockme'                   => array( 'Blokker_meg' ),
        'Booksources'               => array( 'Bokkjelder' ),
        'BrokenRedirects'           => array( 'Blindvegsomdirigeringar' ),
        'Categories'                => array( 'Kategoriar' ),
        'ChangeEmail'               => array( 'Endra_e-post', 'Endre_e-post' ),
        'ChangePassword'            => array( 'Nullstill_passord' ),
+       'ComparePages'              => array( 'Samanlikna_sider', 'Samanlikne_sider', 'Samanlikn_sider' ),
        'Confirmemail'              => array( 'Stadfest_e-postadresse' ),
        'Contributions'             => array( 'Bidrag' ),
        'CreateAccount'             => array( 'Opprett_konto' ),
        'Deadendpages'              => array( 'Blindvegsider' ),
        'DeletedContributions'      => array( 'Sletta_brukarbidrag' ),
-       'Disambiguations'           => array( 'Fleirtydingssider' ),
        'DoubleRedirects'           => array( 'Doble_omdirigeringar' ),
        'EditWatchlist'             => array( 'Endra_overvakingsliste', 'Endre_overvakingsliste' ),
        'Emailuser'                 => array( 'E-post' ),
@@ -243,8 +243,9 @@ $specialPageAliases = array(
        'Filepath'                  => array( 'Filstig', 'Filsti' ),
        'Import'                    => array( 'Importer' ),
        'Invalidateemail'           => array( 'Gjer_e-post_ugyldig' ),
+       'JavaScriptTest'            => array( 'Utrøyning_av_JavaScript', 'JavaScript-test' ),
        'BlockList'                 => array( 'Blokkeringsliste' ),
-       'LinkSearch'                => array( 'Lenkjesøk' ),
+       'LinkSearch'                => array( 'Lenkjesøk', 'Lenkesøk' ),
        'Listadmins'                => array( 'Administratorliste', 'Administratorar' ),
        'Listbots'                  => array( 'Bottliste', 'Bottar', 'Robotliste', 'Robotar' ),
        'Listfiles'                 => array( 'Filliste' ),
@@ -259,6 +260,7 @@ $specialPageAliases = array(
        'MIMEsearch'                => array( 'MIME-søk' ),
        'Mostcategories'            => array( 'Flest_kategoriar' ),
        'Mostimages'                => array( 'Mest_brukte_filer' ),
+       'Mostinterwikis'            => array( 'Flest_interwikilenkjer', 'Mest_interwiki' ),
        'Mostlinked'                => array( 'Mest_lenka_sider', 'Mest_lenkja_sider' ),
        'Mostlinkedcategories'      => array( 'Mest_brukte_kategoriar' ),
        'Mostlinkedtemplates'       => array( 'Mest_brukte_malar' ),
@@ -326,10 +328,10 @@ $messages = array(
 'tog-extendwatchlist' => 'Utvid overvakingslista til å vise alle endringane, ikkje berre dei siste',
 'tog-usenewrc' => 'Grupper endringar etter side i siste endringane og på overvakingslista mi (krev JavaScript)',
 'tog-numberheadings' => 'Vis nummererte overskrifter',
-'tog-showtoolbar' => 'Vis endringsknappar (JavaScript)',
-'tog-editondblclick' => 'Endre sider med dobbeltklikk (JavaScript)',
+'tog-showtoolbar' => 'Vis endringsverktøyline',
+'tog-editondblclick' => 'Endre sider med dobbeltklikk',
 'tog-editsection' => 'Endre avsnitt ved hjelp av [endre]-lenkje',
-'tog-editsectiononrightclick' => 'Endre avsnitt ved å høgreklikke på avsnittsoverskrift (JavaScript)',
+'tog-editsectiononrightclick' => 'Endre avsnitt ved å høgreklikke på avsnittsoverskrifter',
 'tog-showtoc' => 'Vis innhaldsliste (for sider med meir enn tre bolkar)',
 'tog-rememberpassword' => 'Hugs innlogginga mi med denne nettlesaren (for høgst {{PLURAL:$1|éin dag|$1 dagar}})',
 'tog-watchcreations' => 'Legg til sidene eg opprettar og filene eg lastar opp på overvakingslista mi',
@@ -347,7 +349,7 @@ $messages = array(
 'tog-shownumberswatching' => 'Vis kor mange som overvakar sida',
 'tog-oldsig' => 'Noverande signatur:',
 'tog-fancysig' => 'Handsam signaturar som wikitekst (utan automatisk lenking)',
-'tog-uselivepreview' => 'Bruk levande førehandsvising (eksperimentelt JavaScript)',
+'tog-uselivepreview' => 'Bruk levande førehandsvising (eksperimentelt)',
 'tog-forceeditsummary' => 'Spør meg når eg ikkje har skrive noko i endringssamandraget',
 'tog-watchlisthideown' => 'Gøym endringane mine i overvakingslista',
 'tog-watchlisthidebots' => 'Gøym endringar gjorde av robotar i overvakingslista',
@@ -457,8 +459,6 @@ $messages = array(
 'noindex-category' => 'Ikkje-indekserte sider',
 'broken-file-category' => 'Sider med brotne fillenkjer',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Om',
 'article' => 'Innhaldsside',
 'newwindow' => '(vert opna i eit nytt vindauge)',
@@ -593,8 +593,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Henta frå «$1»',
 'youhavenewmessages' => 'Du har $1 ($2).',
-'newmessageslink' => 'nye meldingar',
-'newmessagesdifflink' => 'sjå skilnad',
 'youhavenewmessagesfromusers' => 'Du har $1 frå {{PLURAL:$3|ein annan brukar| $3 brukarar}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du har $1 frå mange brukarar ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ei ny melding|nye meldingar}}',
@@ -765,7 +763,7 @@ Gløym ikkje å endra [[Special:Preferences|innstillingane dine for {{SITENAME}}
 'gotaccount' => "Har du ein brukarkonto? '''$1'''.",
 'gotaccountlink' => 'Logg inn',
 'userlogin-resetlink' => 'Har du gløymd påloggingsopplysingane dine?',
-'userlogin-resetpassword-link' => 'Attendestill passordet ditt',
+'userlogin-resetpassword-link' => 'Gløymt passordet ditt?',
 'helplogin-url' => 'Help:Innlogging',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hjelp med innlogging]]',
 'createacct-join' => 'Skriv inn informasjonen din under.',
@@ -1014,9 +1012,9 @@ Det siste elementet i blokkeringsloggen er oppgjeve nedanfor:',
 * '''Internet Explorer:''' Haldt nede ''Ctrl'' medan du klikkar ''Oppdater'', eller trykk ''Ctrl-F5.''
 * '''Opera:''' Tøm mellomlageret i ''Verktøy → Innstillingar''.",
 'usercssyoucanpreview' => "'''Tips:''' Bruk «{{int:showpreview}}»-knappen for å teste den nye CSS- eller JavaScript-koden din før du lagrar.",
-'userjsyoucanpreview' => "''Tips:''' Bruk «{{int:showpreview}}»-knappen for å teste den nye CSS- eller JavaScript-koden din før du lagrar.",
+'userjsyoucanpreview' => "'''Tips:''' Bruk «{{int:showpreview}}»-knappen for å teste den nye CSS- eller JavaScript-koden din før du lagrar.",
 'usercsspreview' => "'''Hugs at dette berre er ei førehandsvising av din eigen CSS og at han ikkje er lagra enno!'''",
-'userjspreview' => "'''Hugs at du berre testar ditt eige JavaScript, det har ikkje vorte lagra enno!!'''",
+'userjspreview' => "'''Hugs at du berre testar eller førehandsviser brukar-JavaScript-et ditt. Det har ikkje vorte lagra enno!'''",
 'sitecsspreview' => "'''Hugs at du berre førehandsviser dette stilarket. '''
 '''Det er ikkje lagra enno!'''",
 'sitejspreview' => "'''Hugs at du berre førehandsviser denne JavaScript-koden.'''
@@ -1035,7 +1033,7 @@ Endringane dine er ikkje lagra enno!",
 
 '''Dersom dette er eit heilt vanleg forsøk på endring, prøv ein gong til. Dersom det framleis ikkje går, prøv å logge deg ut og inn att.'''",
 'token_suffix_mismatch' => "'''Endringa di vart avvist fordi klienten/nettlesaren din lagar teiknfeil i teksten. Dette vart gjort for å hindre øydelegging av teksten på sida. Slikt kan av og til hende når ein brukar feilprogrammerte og vevbaserte anonyme proxytenester.'''",
-'edit_form_incomplete' => 'Delar av redigeringsskjemaet nådde ikkje fram til tenaren; dobbelsjekk at redigeringa er korrekt, og prøv om att.',
+'edit_form_incomplete' => 'Delar av endringsskjemaet nådde ikkje fram til tenaren; dobbelsjekk at endringa er korrekt og prøv om att.',
 'editing' => 'Endrar $1',
 'creating' => 'Opprettar $1',
 'editingsection' => 'Endrar $1 (bolk)',
@@ -1097,7 +1095,7 @@ Sletteloggen for sida finn du her:",
 'edit-gone-missing' => 'Kunne ikkje oppdatere sida.
 Det ser ut til at ho er sletta.',
 'edit-conflict' => 'Endringskonflikt.',
-'edit-no-change' => 'Redigeringa di vart ignorert fordi det ikkje vart gjort endringar i teksten.',
+'edit-no-change' => 'Endringa di vart ignorert fordi det ikkje vart gjort endringar i teksten.',
 'postedit-confirmation' => 'Endringa di vart lagra.',
 'edit-already-exists' => 'Kunne ikkje opprette ny side fordi ho alt eksisterer.',
 'defaultmessagetext' => 'Standard meldingstekst',
@@ -1136,7 +1134,8 @@ Desse parameterane har vorte utelatne.',
 'converter-manual-rule-error' => 'Det vart oppdaga ein feil i ein manuell språkkonverteringsregel',
 
 # "Undo" feature
-'undo-success' => 'Endringa kan attenderullast. Ver venleg og sjå over skilnadene nedanfor for å vere sikker på at du vil attenderulle. Deretter kan du lagre attenderullinga.',
+'undo-success' => 'Endringa kan angrast.
+Sjå på samanlikninga under for å stadfesta at dette er det du ynskjer å gjera. Deretter kan du lagra desse endringane for å fullføra angringa.',
 'undo-failure' => 'Endringa kunne ikkje attenderullast grunna konflikt med endringar som er gjorde i mellomtida.',
 'undo-norev' => 'Endringa kunne ikkje fjernast fordi han ikkje finst eller vart sletta',
 'undo-summary' => 'Rullar attende versjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])',
@@ -1223,7 +1222,8 @@ Du kan sjå skilnaden; detaljar finst i [{{fullurl:{{#Special:Log}}/suppcess|pag
 'revdelete-text' => "Sletta versjonar og oppføringar vert framleis synlege i sidehistorikken og loggane, men delar av innhaldet deira vert ikkje lenger offentleggjort.'''
 Andre administratorar på {{SITENAME}} kan framleis sjå det gøymde innhaldet og attopprette det, med mindre fleire avgrensingar vert lagde inn av sideoperatørane.",
 'revdelete-confirm' => 'Stadfest at du ynskjer å gjera dette, at du skjønar konsekvensane, og at du gjer det i samsvar med [[{{MediaWiki:Policy-url}}|retningslinene]].',
-'revdelete-suppress-text' => "Løyning av sideversjonar bør '''berre''' verta nytta i dei fylgjande tilfella:
+'revdelete-suppress-text' => "Løyning av sideversjonar bør '''berre''' nyttast i desse tilfella:
+* Mogeleg ærekrenkjande informasjon
 * Upassanda personleg informasjon
 *: ''heimeadresser og -telefonnummer,  personnummer, osb.''",
 'revdelete-legend' => 'Vel avgrensing for synlegdom',
@@ -1234,8 +1234,8 @@ Andre administratorar på {{SITENAME}} kan framleis sjå det gøymde innhaldet o
 'revdelete-hide-user' => 'Gøym brukarnamn/IP-adresse',
 'revdelete-hide-restricted' => 'Løyn data frå administratorar slik som med andre brukarar',
 'revdelete-radio-same' => '(ikkje endra)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nei',
+'revdelete-radio-set' => 'Løynd',
+'revdelete-radio-unset' => 'Synleg',
 'revdelete-suppress' => 'Fjern informasjon frå administratorar også',
 'revdelete-unsuppress' => 'Fjern avgrensingane på dei attoppretta versjonane',
 'revdelete-log' => 'Årsak:',
@@ -1301,7 +1301,7 @@ Pass på at den nye sida også har innhald frå den innfletta sida.',
 'mergehistory-reason' => 'Årsak:',
 
 # Merge log
-'mergelog' => 'Flettingslogg',
+'mergelog' => 'Flettelogg',
 'pagemerge-logentry' => 'fletta [[$1]] til [[$2]] (versjonar fram til $3)',
 'revertmerge' => 'Fjern fletting',
 'mergelogpagetext' => 'Nedanfor finn du ei liste over dei siste flettingane av ein sidehistorikk til ein annan.',
@@ -1392,8 +1392,6 @@ Ver merksam på at registra deira kan vera utdaterte.',
 'preferences' => 'Innstillingar',
 'mypreferences' => 'Innstillingar',
 'prefs-edits' => 'Tal på endringar:',
-'prefsnologin' => 'Ikkje innlogga',
-'prefsnologintext' => 'Du må vere <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} logga inn]</span> for å endre brukarinnstillingane.',
 'changepassword' => 'Skift passord',
 'prefs-skin' => 'Drakt',
 'skin-preview' => 'førehandsvis',
@@ -1418,7 +1416,7 @@ Ver merksam på at registra deira kan vera utdaterte.',
 'prefs-rendering' => 'Utsjånad',
 'saveprefs' => 'Lagre',
 'resetprefs' => 'Rull attende',
-'restoreprefs' => 'Hent attende alle standardinnstillingane',
+'restoreprefs' => 'Hent attende alle standardinnstillingane (i alle bolkane)',
 'prefs-editing' => 'Endring',
 'rows' => 'Rekkjer',
 'columns' => 'Kolonnar',
@@ -1524,7 +1522,7 @@ Denne informasjonen vil vera offentleg.',
 'userrights-no-interwiki' => 'Du har ikkje tilgang til å endre brukartilgangar på andre wikiar.',
 'userrights-nodatabase' => 'Databasen $1 finst ikkje eller er ikkje lokal.',
 'userrights-nologin' => 'Du må [[Special:UserLogin|logge inn]] med ein administrator- og/eller byråkratkonto for å endre brukartilgangar.',
-'userrights-notallowed' => 'Kontoen din har ikkje løyve til å leggja til eller fjerna brukarrettar.',
+'userrights-notallowed' => 'Du har ikkje løyve til å leggja til eller fjerna brukarrettar.',
 'userrights-changeable-col' => 'Grupper du kan endre',
 'userrights-unchangeable-col' => 'Grupper du ikkje kan endre',
 
@@ -1676,6 +1674,7 @@ Denne informasjonen vil vera offentleg.',
 'recentchanges-label-minor' => 'Endringa er småplukk',
 'recentchanges-label-bot' => 'Denne endringa vart gjort av ein bot',
 'recentchanges-label-unpatrolled' => 'Endringa er ikkje patruljert enno',
+'recentchanges-legend-newpage' => '$1 – ny side',
 'rcnote' => "Nedanfor er {{PLURAL:$1|den siste endringa gjord|dei siste '''$1''' endringane gjorde}} {{PLURAL:$2|den siste dagen|dei siste '''$2''' dagane}}, for $4, kl. $5.",
 'rcnotefrom' => "Nedanfor vert opp til '''$1''' endringar sidan  ''' $2''' viste.",
 'rclistfrom' => 'Vis nye endringar sidan $1',
@@ -1698,7 +1697,7 @@ Denne informasjonen vil vera offentleg.',
 'rc_categories_any' => 'Alle',
 'rc-change-size-new' => '$1 {{PLURAL:$1|byte}} etter endringa',
 'newsectionsummary' => '/* $1 */ ny bolk',
-'rc-enhanced-expand' => 'Vis detaljar (krev JavaScript)',
+'rc-enhanced-expand' => 'Vis detaljar',
 'rc-enhanced-hide' => 'Skjul detaljar',
 'rc-old-title' => 'opphavleg oppretta som «$1»',
 
@@ -2058,7 +2057,7 @@ Du vil kan henda endra skildringa på [$2 filskildringssida] hennar der.',
 
 # Random page
 'randompage' => 'Tilfeldig side',
-'randompage-nopages' => 'Det finst ingen sider i {{PLURAL:$2|det fylgjande namneromet|dei fylgjande namneroma}}: $1.',
+'randompage-nopages' => 'Det finst ingen sider i {{PLURAL:$2|dette namnerommet|desse namneromma}}: $1.',
 
 # Random redirect
 'randomredirect' => 'Tilfeldig omdirigering',
@@ -2167,9 +2166,9 @@ Du vil kan henda endra skildringa på [$2 filskildringssida] hennar der.',
 'ancientpages' => 'Eldste sider',
 'move' => 'Flytt',
 'movethispage' => 'Flytt denne sida',
-'unusedimagestext' => 'Dei fylgjande filene finst, men vert ikkje nytta på noka side.
+'unusedimagestext' => 'Desse filene finst, men vert ikkje nytta på noka side.
 Merk at andre internettsider kan ha direkte lenkjer til filer, og difor kan filene vera nytta aktivt trass i at dei er lista opp her.',
-'unusedcategoriestext' => 'Dei følgjande kategorisidene er oppretta, sjølv om ingen artikkel eller kategori brukar dei.',
+'unusedcategoriestext' => 'Desse kategorisidene er oppretta, sjølv om ingen artikkel eller kategori brukar dei.',
 'notargettitle' => 'Inkje mål',
 'notargettext' => 'Du har ikkje spesifisert noka målside eller nokon brukar å bruke denne funksjonen på.',
 'nopagetitle' => 'Målsida finst ikkje',
@@ -2570,7 +2569,7 @@ $1',
 'contributions' => '{{GENDER:$1|Brukarbidrag}}',
 'contributions-title' => 'Bidrag av $1',
 'mycontris' => 'Bidrag',
-'contribsub2' => 'For $1 ($2)',
+'contribsub2' => 'For {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Det vart ikkje funne nokon endringar gjorde av denne brukaren.',
 'uctop' => '(gjeldande)',
 'month' => 'Månad:',
@@ -2708,7 +2707,7 @@ IP-adresser som blir automatisk blokkerte er ikkje lista her. Sjå [[Special:Blo
 'block-log-flags-noemail' => 'sending av e-post blokkert',
 'block-log-flags-nousertalk' => 'kan ikkje endre eiga diskusjonsside',
 'block-log-flags-angry-autoblock' => 'utvida autoblokkering aktivert',
-'block-log-flags-hiddenname' => 'brukarnamn gøymt',
+'block-log-flags-hiddenname' => 'brukarnamn løynt',
 'range_block_disabled' => 'Funksjonen for blokkering av IP-adresse-seriar er inaktivert på tenaren.',
 'ipb_expiry_invalid' => 'Ugyldig opphørstid.',
 'ipb_expiry_temp' => 'For å skjule brukarnamnet må blokkeringa vere permanent.',
@@ -2866,7 +2865,7 @@ Dersom du berre vil ha noverande versjon, kan du også bruke ei lenkje, til døm
 'allmessagesdefault' => 'Standardtekst',
 'allmessagescurrent' => 'Gjeldande meldingstekst',
 'allmessagestext' => 'Dette er ei liste over systemmeldingar i MediaWiki-namnerommet.
-Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] om du ynskjer å bidra til den generelle omsetjinga av MediaWiki.',
+Vitja [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//translatewiki.net translatewiki.net] om du ynskjer å bidra til den generelle omsetjinga av MediaWiki.',
 'allmessagesnotsupportedDB' => "Denne sida kan ein ikkje bruka fordi «'''\$wgUseDatabaseMessages'''» er slått av.",
 'allmessages-filter-legend' => 'Filtrer',
 'allmessages-filter' => 'Filtrer etter tilpassingsgrad:',
@@ -3060,6 +3059,8 @@ Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//trans
 'spam_reverting' => 'Attenderullar til siste versjon utan lenkje til $1',
 'spam_blanking' => 'Alle versjonar inneheldt lenkje til $1, tømmer sida',
 'spam_deleting' => 'Alle versjonane inneheldt lenkjer til $1, slettar.',
+'simpleantispam-label' => "Antispam-kontroll.
+'''IKKJE''' fyll ut dette feltet!",
 
 # Info page
 'pageinfo-title' => 'Informasjon om «$1»',
@@ -3073,13 +3074,13 @@ Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//trans
 'pageinfo-length' => 'Sidelengd (i byte)',
 'pageinfo-article-id' => 'Side-ID',
 'pageinfo-language' => 'Sideinnhaldsspråk',
-'pageinfo-robot-policy' => 'Søkjemotorstode',
-'pageinfo-robot-index' => 'Kan indekserast',
-'pageinfo-robot-noindex' => 'Kan ikkje indekserast',
+'pageinfo-robot-policy' => 'Botindeksering',
+'pageinfo-robot-index' => 'Tillate',
+'pageinfo-robot-noindex' => 'Ikkje tillate',
 'pageinfo-views' => 'Tal på visningar',
 'pageinfo-watchers' => 'Tal på overvakarar av sida',
 'pageinfo-few-watchers' => 'Færre enn $1 {{PLURAL:$1|som overvakar}}',
-'pageinfo-redirects-name' => 'Omdirigeringar til sida',
+'pageinfo-redirects-name' => 'Tal på omdirigeringar til sida',
 'pageinfo-subpages-name' => 'Undersider av sida',
 'pageinfo-subpages-value' => '$1 ({{PLURAL:$2|éi omdirigering|$2 omdirigeringar}}; {{PLURAL:$3|éi ikkje-omdirigering|$3 ikkje-omdirigeringar}})',
 'pageinfo-firstuser' => 'Sideopprettar',
@@ -3122,7 +3123,7 @@ Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//trans
 'markedaspatrollederror' => 'Kan ikkje merke sida som patruljert',
 'markedaspatrollederrortext' => 'Du må markere ein versjon for å kunne godkjenne.',
 'markedaspatrollederror-noautopatrol' => 'Ein har ikkje høve til å merkje sine eigne endringar som godkjende.',
-'markedaspatrollednotify' => 'Denne endringa på $1 vart merkt som patruljert.',
+'markedaspatrollednotify' => 'Endringa på $1 vart merkt som patruljert.',
 'markedaspatrollederrornotify' => 'Det gjekk ikkje å merkja endringa som patruljert.',
 
 # Patrol log
@@ -3157,7 +3158,7 @@ $1',
 'svg-long-desc' => 'SVG-fil, standardoppløysing: $1 × $2 pikslar, filstorleik: $3',
 'svg-long-desc-animated' => 'Animert SVG-fil, standardoppløysing $1 × $2 pikslar, filstorleik: $3',
 'svg-long-error' => 'Ugild SVG-fil: $1',
-'show-big-image' => 'Full oppløysing',
+'show-big-image' => 'Opphavleg fil',
 'show-big-image-preview' => 'Storleik på førehandsvising: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Anna oppløysing|Andre oppløysingar}}: $1.',
 'show-big-image-size' => '$1 × $2 pikslar',
@@ -3419,7 +3420,7 @@ Andre er gøymde som standard.
 'exif-compression-4' => 'CCITT Gruppe 4 faks-koding',
 
 'exif-copyrighted-true' => 'Verna av opphavsrett',
-'exif-copyrighted-false' => 'Ikkje verna av opphavsrett',
+'exif-copyrighted-false' => 'Opphavsrettsstode er ikkje oppgjeven',
 
 'exif-unknowndate' => 'Ukjend dato',
 
@@ -3625,7 +3626,7 @@ Andre er gøymde som standard.
 
 # External editor support
 'edit-externally' => 'Endre denne fila med eit eksternt program',
-'edit-externally-help' => '(Sjå [//www.mediawiki.org/wiki/Manual:External_editors oppsettsinstruksjonane] for meir informasjon)',
+'edit-externally-help' => '(Sjå [https://www.mediawiki.org/wiki/Manual:External_editors oppsettsinstruksjonane] for meir informasjon)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
@@ -3805,7 +3806,7 @@ Du kan òg [[Special:EditWatchlist|nytte standardverktøyet]].',
 'version-hook-subscribedby' => 'Brukt av',
 'version-version' => '(versjon $1)',
 'version-license' => 'Lisens',
-'version-poweredby-credits' => "Denne wikien er driven av '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Denne wikien er driven av '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'andre',
 'version-poweredby-translators' => 'translatewiki.net-omsetjarar',
 'version-credits-summary' => 'Me ynskjer godskriva desse personane for tilskotet deira til [[Special:Version|MediaWiki]].',
@@ -3846,8 +3847,7 @@ Du skal ha motteke [{{SERVER}}{{SCRIPTPATH}}/COPYING ein kopi av GNU General Pub
 
 # Special:SpecialPages
 'specialpages' => 'Spesialsider',
-'specialpages-note' => '----
-* Vanlege spesialsider.
+'specialpages-note' => '* Vanlege spesialsider.
 * <span class="mw-specialpagerestricted">Spesialsider med avgrensa tilgang.</span>',
 'specialpages-group-maintenance' => 'Vedlikehaldsrapportar',
 'specialpages-group-other' => 'Andre spesialsider',
@@ -3912,7 +3912,7 @@ Du skal ha motteke [{{SERVER}}{{SCRIPTPATH}}/COPYING ein kopi av GNU General Pub
 'dberr-info' => '(Kan ikkje kontakta databasetenaren: $1)',
 'dberr-usegoogle' => 'Du kan søkja gjennom Google i mellomtida.',
 'dberr-outofdate' => 'Merk at versjonane deira av innhaldet vårt kan vera forelda.',
-'dberr-cachederror' => 'Fylgjande er ein mellomlagra kopi av den etterspurde sida, og er, kan henda, ikkje den siste versjonen av ho.',
+'dberr-cachederror' => 'Dette er ein mellomlagra kopi av den etterspurde sida og er mogelegvis ikkje den gjeldande versjonen av henne.',
 
 # HTML forms
 'htmlform-invalid-input' => 'Det finst problem med innskrivinga di',
@@ -3947,7 +3947,7 @@ Du skal ha motteke [{{SERVER}}{{SCRIPTPATH}}/COPYING ein kopi av GNU General Pub
 'logentry-suppress-revision-legacy' => '$1 {{GENDER:$2|endra}} i løyndom synlegdomen til versjonar på sida $3',
 'revdelete-content-hid' => 'innhald løynt',
 'revdelete-summary-hid' => 'endringsamandrag løynt',
-'revdelete-uname-hid' => 'brukarnamn gøymt',
+'revdelete-uname-hid' => 'brukarnamn løynt',
 'revdelete-content-unhid' => 'innhald gjort synleg',
 'revdelete-summary-unhid' => 'endringssamandrag gjort synleg',
 'revdelete-uname-unhid' => 'brukarnamn gjort synleg',
@@ -4057,4 +4057,21 @@ Om ikkje kan du nytta det enkle skjemaet under. Merknaden din vert lagd til på
 'limitreport-expansiondepth' => 'Største utvidingsdjupna',
 'limitreport-expensivefunctioncount' => 'Tal på dyre analysefunksjonar',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Utvid malar',
+'expand_templates_intro' => 'Denne sida tek ein tekst og utvider alle malar som er bruka i teksten.
+Ho utvider òg alle funksjonar som
+<nowiki>{{</nowiki>#language:…}}, og variablar som
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash; bortimot alt som står i dobbelte klammeparentesar.
+Dette gjer ho ved å kalla dei relevante parsersetega frå MediaWiki sjølv.',
+'expand_templates_title' => 'Konteksttittel, for {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Inntekst:',
+'expand_templates_output' => 'Resultat',
+'expand_templates_xml_output' => 'XML-resultat',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Fjern kommentarar',
+'expand_templates_remove_nowiki' => 'Ikkje vis <nowiki>-merke i resultatet',
+'expand_templates_generate_xml' => 'Vis parsertre som XML',
+'expand_templates_preview' => 'Førehandsvising',
+
 );
index 99cea76..c2edf96 100644 (file)
@@ -253,8 +253,6 @@ $messages = array(
 
 'retrievedfrom' => 'Le tšwa go "$1"',
 'youhavenewmessages' => 'O na le $1 ($2).',
-'newmessageslink' => 'ya melaetša ye mefsa',
-'newmessagesdifflink' => 'phetogo ya mafelelo',
 'newmessagesdifflinkplural' => 'l{{PLURAL:$1|Phetogo tša|Diphetogo ya}}go feta',
 'youhavenewmessagesmulti' => 'O nale melaetša ye mefsa go $1',
 'editsection' => 'lokiša',
@@ -596,7 +594,6 @@ Leka go fetleka ka go ngwala ''all:'' go fetleka mateng ka moka, goba o šumiše
 'preferences' => 'Dikgatlhegelo',
 'mypreferences' => 'Dikgatlhegelo tša ka',
 'prefs-edits' => 'Palo ya diphetogo:',
-'prefsnologin' => 'Ga wa tsena',
 'changepassword' => 'Fetola ditlhaka-tša-siphiri',
 'skin-preview' => 'Ponopele',
 'prefs-datetime' => 'Tšatšikgwedi le nako',
@@ -1214,7 +1211,7 @@ letlakala la seswantšho ge tafola ya metadata e bulwa. Tše dingwe tša di ''fi
 
 # External editor support
 'edit-externally' => 'Fetola faele ye o šumiša thulusi ya ka ntle',
-'edit-externally-help' => '(Lebelela [//www.mediawiki.org/wiki/Manual:External_editors Taelo ya go thoma] go humana sedi)',
+'edit-externally-help' => '(Lebelela [https://www.mediawiki.org/wiki/Manual:External_editors Taelo ya go thoma] go humana sedi)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ka moka',
@@ -1272,4 +1269,7 @@ letlakala la seswantšho ge tafola ya metadata e bulwa. Tše dingwe tša di ''fi
 # Special:Tags
 'tag-filter' => '[[Special:Tags|Tag]] "filter":',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Phetho',
+
 );
index 34503b0..ca9df6d 100644 (file)
@@ -64,7 +64,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Paginas_ancianas' ),
        'Blankpage'                 => array( 'Pagina_blanca', 'PaginaBlanca' ),
        'Block'                     => array( 'Blocar', 'Blocatge' ),
-       'Blockme'                   => array( 'Blocatz_me', 'Blocatz-me' ),
        'Booksources'               => array( 'Obratge_de_referéncia', 'Obratges_de_referéncia' ),
        'BrokenRedirects'           => array( 'Redireccions_copadas', 'RedireccionsCopadas' ),
        'Categories'                => array( 'Categorias' ),
@@ -74,7 +73,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Crear_un_compte', 'CrearUnCompte', 'CrearCompte' ),
        'Deadendpages'              => array( 'Paginas_sul_camin_d\'enlòc' ),
        'DeletedContributions'      => array( 'Contribucions_escafadas', 'ContribucionsEscafadas' ),
-       'Disambiguations'           => array( 'Omonimia', 'Omonimias', 'Paginas_d\'omonimia' ),
        'DoubleRedirects'           => array( 'Redireccions_doblas', 'RedireccionsDoblas' ),
        'Emailuser'                 => array( 'Corrièr_electronic', 'Email', 'Emèl', 'Emèil' ),
        'Export'                    => array( 'Exportar', 'Exportacion' ),
@@ -314,7 +312,7 @@ $messages = array(
 'tog-minordefault' => 'Considerar mas modificacions coma menoras per defaut',
 'tog-previewontop' => 'Far veire la previsualizacion al dessús de la zòna de modificacion',
 'tog-previewonfirst' => 'Far veire la previsualizacion al moment de la primièra edicion',
-'tog-nocache' => "Desactivar l'amagatal de paginas",
+'tog-nocache' => "Desactivar l'escondedor de las paginas pel navigador",
 'tog-enotifwatchlistpages' => 'M’avertir per corrièr electronic quand una pagina o un fichièr de ma lista de seguiment es modificat',
 'tog-enotifusertalkpages' => 'M’avertir per corrièr electronic en cas de modificacion de ma pagina de discussion',
 'tog-enotifminoredits' => 'M’avertir per corrièr electronic quitament en cas de modificacions menoras de las paginas o dels fichièrs',
@@ -510,7 +508,7 @@ $messages = array(
 'articlepage' => "Vejatz l'article",
 'talk' => 'Discussion',
 'views' => 'Afichatges',
-'toolbox' => "Bóstia d'aisinas",
+'toolbox' => 'Aisinas',
 'userpage' => "Pagina d'utilizaire",
 'projectpage' => 'Pagina meta',
 'imagepage' => 'Veire la pagina del fichièr',
@@ -540,7 +538,7 @@ $1",
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'A prepaus de {{SITENAME}}',
 'aboutpage' => 'Project:A prepaus',
-'copyright' => 'Lo contengut es disponible segon los tèrmes de la licéncia $1.',
+'copyright' => 'Lo contengut es disponible jos licéncia $1 levat mencion contrària.',
 'copyrightpage' => '{{ns:project}}:Copyright',
 'currentevents' => 'Actualitats',
 'currentevents-url' => 'Project:Actualitats',
@@ -566,8 +564,6 @@ $1",
 'ok' => "D'acòrdi",
 'retrievedfrom' => 'Recuperada de « $1 »',
 'youhavenewmessages' => 'Avètz $1 ($2).',
-'newmessageslink' => 'de messatges novèls',
-'newmessagesdifflink' => 'darrièr cambiament',
 'youhavenewmessagesfromusers' => "Avètz $1 {{PLURAL:$3|d'un autre utilizaire|de $3 autres utilizaires}} ($2).",
 'youhavenewmessagesmanyusers' => 'Avètz $1 de fòrça utilizaires ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|un novèl messatge|de novèls messatges}}',
@@ -623,6 +619,8 @@ Una lista de las paginas especialas pòt èsser trobada sus [[Special:SpecialPag
 # General errors
 'error' => 'Error',
 'databaseerror' => 'Error de la banca de donadas',
+'databaseerror-text' => "Una error de requèsta de banca de donadas s'es producha. Aquò pòt provenir d'un bug dins lo logicial.",
+'databaseerror-textcl' => "Una error de requèsta de banca de donadas s'es produsida.",
 'databaseerror-query' => 'Requèsta : $1',
 'databaseerror-function' => 'Foncion : $1',
 'databaseerror-error' => 'Error : $1',
@@ -696,7 +694,8 @@ L'administrator que l'a varrolhat a provesit aqueste motiu : « $3 ».",
 'invalidtitle-knownnamespace' => "Títol invalid amb l'espaci de noms « $2 » e l'intitulat « $3 »",
 'invalidtitle-unknownnamespace' => "Títol invalid amb lo numèro d'espaci de noms $1 e l'intitulat « $2 » desconeguts",
 'exception-nologin' => 'Pas connectat',
-'exception-nologin-text' => "Aquesta pagina o aquesta accion necessita d'èsser connectada sus aqueste wiki.",
+'exception-nologin-text' => '[[Special:Userlogin|Connectatz-vos]] per poder accedir a aquesta pagina o aquesta accion.',
+'exception-nologin-text-manual' => '$1 per poder accedir a aquesta pagina o aquesta accion.',
 
 # Virus scanner
 'virus-badscanner' => "Marrida configuracion : escaner de virús desconegut : ''$1''",
@@ -743,9 +742,12 @@ Doblidetz pas de modificar [[Special:Preferences|vòstras preferéncias per {{SI
 'gotaccount' => "Ja avètz un compte ? '''$1'''.",
 'gotaccountlink' => 'Identificatz-vos',
 'userlogin-resetlink' => 'Avètz doblidat vòstres detalhs de connexion ?',
-'userlogin-resetpassword-link' => 'Reïnicializar lo senhal',
+'userlogin-resetpassword-link' => 'Senhal doblidat ?',
 'helplogin-url' => 'Help:Connexion',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ajuda a la connexion]]',
+'userlogin-loggedin' => 'Sètz ja connectat en tant que {{GENDER:$1|$1}}.
+Utilizatz lo formulari çaijós per vos connectar amb un autre utilizaire.',
+'userlogin-createanother' => 'Crear un autre compte',
 'createacct-join' => 'Entratz vòstras informacions çaijós.',
 'createacct-another-join' => 'Picar las informacions del novèl compte çaijós.',
 'createacct-emailrequired' => 'Adreça electronica',
@@ -806,13 +808,13 @@ podètz ignorar aqueste messatge e contunhar d'utilizar vòstre senhal ancian.",
 Identificatz-vos tre que l'aurètz recebut.",
 'blocked-mailpassword' => 'Vòstra adreça IP es blocada en edicion, la foncion de rapèl del senhal es doncas desactivada per evitar los abuses.',
 'eauthentsent' => 'Un corrièr de confirmacion es estat mandat a l’adreça indicada.
-Abans qu’un autre corrièr sià mandat a aqueste compte, vos caldrà seguir las instruccions donadas dins lo messatge per confirmar que sètz plan lo titular.',
+Abans qu’un autre corrièr sià mandat a aqueste compte, vos caldrà seguir las instruccions donadas dins lo messatge per confirmar que lo compte es plan vòstre.',
 'throttled-mailpassword' => 'Un corrièr electronic de reïnicializacion de vòstre senhal es ja estat mandat durant {{PLURAL:$1|la darrièra ora|las $1 darrièras oras}}. Per evitar los abuses, un sol corrièr de reïnicializacion de vòstre senhal serà pas mandat per {{PLURAL:$1|ora|interval de $1 oras}}.',
 'mailerror' => 'Error en mandant lo corrièr electronic : $1',
 'acct_creation_throttle_hit' => "De visitors d'aqueste wiki qu'utilizan vòstra adreça IP an creat $1 {{PLURAL:$1|compte|comptes}} lo jorn darrièr, aquò es lo limit maximum autorizat pendent aqueste periòde.
 Atal los visitors qu'utilizan aquesta adreça IP pòdon pas crear mai de compte novèl pel moment.",
-'emailauthenticated' => 'Vòstra adreça de corrièr electronic es estada autentificada lo $2 a $3.',
-'emailnotauthenticated' => 'Vòstra adreça de corrièr electronic es <strong>pas encara autentificada</strong>. Cap corrièr serà pas mandat per caduna de las foncions seguentas.',
+'emailauthenticated' => 'Vòstra adreça de corrièr electronic es estada confirmada lo $2 a $3.',
+'emailnotauthenticated' => 'Vòstra adreça de corrièr electronic es pas encara confirmada. Cap de corrièr serà pas mandat per caduna de las foncions seguentas.',
 'noemailprefs' => "Cap d'adreça electronica es pas estada indicada, las foncions seguentas seràn pas disponiblas.",
 'emailconfirmlink' => 'Confirmatz vòstra adreça de corrièr electronic',
 'invalidemailaddress' => "Aquesta adreça de corrièr electronic pòt pas èsser acceptada perque sembla qu'a un format incorrècte.
@@ -1227,18 +1229,19 @@ Podètz veire aquesta diff ; i pòt aver mai de detalhs dins lo [{{fullurl:{{#Sp
 D’autres administrators sus {{SITENAME}} poiràn totjorn accedir al contengut amagat e lo restablir tornamai a travèrs d'aquesta meteissa interfàcia, a mens qu’una restriccion suplementària siá mesa en plaça pels operators del site.",
 'revdelete-confirm' => "Confirmatz que volètz efectuar aquesta accion, que ne comprenètz las consequéncias, e qu'o fasètz en acòrd amb [[{{MediaWiki:Policy-url}}|las règlas]].",
 'revdelete-suppress-text' => "La supression deu èsser utilizada '''sonque''' dins los cases seguents :
+* Informacions potencialament difamatòrias
 * Informacions personalas inapropriadas
 *: ''adreça, numèro de telefòn, numèro de seguretat sociala, ...''",
 'revdelete-legend' => 'Metre en plaça de restriccions de version :',
-'revdelete-hide-text' => 'Amagar lo tèxte de la version',
+'revdelete-hide-text' => 'Tèxte de la revision',
 'revdelete-hide-image' => 'Amagar lo contengut del fichièr',
 'revdelete-hide-name' => 'Amagar l’accion e la cibla',
-'revdelete-hide-comment' => 'Amagar lo comentari de modificacion',
-'revdelete-hide-user' => 'Amagar lo pseudonim o l’adreça IP del contributor.',
+'revdelete-hide-comment' => 'Modificar lo resumit',
+'revdelete-hide-user' => 'Nom d’utilizaire/Adreça IP de l’editor',
 'revdelete-hide-restricted' => 'Suprimir aquestas donadas als administrators e mai als autres',
 'revdelete-radio-same' => '(cambiar pas)',
-'revdelete-radio-set' => 'Òc',
-'revdelete-radio-unset' => 'Non',
+'revdelete-radio-set' => 'Amagat',
+'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => 'Suprimir las donadas dels administrators e tanben dels autres utilizaires',
 'revdelete-unsuppress' => 'Levar las restriccions sus las versions restablidas',
 'revdelete-log' => 'Motiu :',
@@ -1394,8 +1397,7 @@ Atencion, lor indexacion de contengut {{SITENAME}} benlèu es pas a jorn.',
 'preferences' => 'Preferéncias',
 'mypreferences' => 'Preferéncias',
 'prefs-edits' => 'Nombre d’edicions :',
-'prefsnologin' => 'Vos sètz pas identificat(ada)',
-'prefsnologintext' => 'Vos cal èsser <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} connectat(ada)]</span> per modificar vòstras preferéncias d’utilizaire.',
+'prefsnologintext2' => "$1 per definir las preferéncias d'utilizaire.",
 'changepassword' => 'Modificacion del senhal',
 'prefs-skin' => 'Aparéncia',
 'skin-preview' => 'Previsualizar',
@@ -1432,6 +1434,9 @@ Atencion, lor indexacion de contengut {{SITENAME}} benlèu es pas a jorn.',
 'recentchangesdays-max' => '(maximum $1 {{PLURAL:$1|jorn|jorns}})',
 'recentchangescount' => "Nombre de modificacions d'afichar per defaut :",
 'prefs-help-recentchangescount' => 'Aquò inclutz las modificacions recentas, las paginas d’istorics e los jornals.',
+'prefs-help-watchlist-token2' => 'Aquí la clau secreta del flux Web de vòstra lista de seguiment.
+Tota persona que la coneis poirà legir vòstra lista de seguiment, doncas, la comuniquetz pas.
+[[Special:ResetTokens|Clicatz aicí se la vos cal reïnicializar]].',
 'savedprefs' => 'Las preferéncias son estadas salvadas.',
 'timezonelegend' => 'Fus orari :',
 'localtime' => 'Ora locala :',
@@ -1505,6 +1510,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'prefs-displaywatchlist' => "Opcions d'afichatge",
 'prefs-tokenwatchlist' => 'Geton',
 'prefs-diffs' => 'Diferéncias',
+'prefs-help-prefershttps' => 'Aquesta preferéncia serà efectiva al moment de vòstra connexion que ven.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => "L'adreça electronica sembla bona",
@@ -1531,6 +1537,8 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'userrights-notallowed' => "Avètz pas la permission d'apondre o suprimir de dreches d'utilizaire.",
 'userrights-changeable-col' => 'Los gropes que podètz cambiar',
 'userrights-unchangeable-col' => 'Los gropes que podètz pas cambiar',
+'userrights-conflict' => "Conflicte de modificacion de dreches d'utilizaire ! Relegissètz e confirmatz vòstras modificacions.",
+'userrights-removed-self' => 'Avètz suprimit vòstres pròpris dreches corrèctament. Del còp, podètz pas mai accedir a aquela pagina.',
 
 # Groups
 'group' => 'Grop :',
@@ -1605,6 +1613,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'right-editmyusercss' => 'Modificar vòstres pròpris fichièrs CSS utilizaire',
 'right-editmyuserjs' => 'Modificar vòstres pròpris fichièrs JavaScript utilizaire',
 'right-viewmywatchlist' => 'Afichar vòstra pròpria lista de seguiment',
+'right-editmywatchlist' => 'Modificar vòstra pròpria lista de seguiment. Remarcatz que certanas accions apondràn encara de paginas sens aqueste drech.',
 'right-viewmyprivateinfo' => 'Veire vòstras donadas personalas (exemple adreça, nom vertadièr)',
 'right-editmyprivateinfo' => 'Modificar vòstras donadas personalas (exemple adreça, nom vertadièr)',
 'right-editmyoptions' => 'Modificar vòstras preferéncias',
@@ -1659,8 +1668,8 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'action-block' => 'blocar aqueste utilizaire a l’edicion',
 'action-protect' => 'modificar los nivèls de proteccion per aquesta pagina',
 'action-rollback' => "anullar rapidament las modificacions del darrièr utilizaire qu'a modificat una pagina donada",
-'action-import' => 'importar aquesta pagina a partir d’un autre wiki',
-'action-importupload' => 'importar aquesta pagina e partir de l’impòrt d’un fichièr',
+'action-import' => 'importar de paginas dempuèi un autre wiki',
+'action-importupload' => 'importar de paginas dempuèi un fichièr telecargat',
 'action-patrol' => 'marcar la modificacion dels autres coma patrolhada',
 'action-autopatrol' => 'aver vòstra modificacion marcada coma patrolhada',
 'action-unwatchedpages' => 'veire la lista de las paginas pas susvelhadas',
@@ -1681,11 +1690,13 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'recentchanges' => 'Darrièrs cambiaments',
 'recentchanges-legend' => 'Opcions dels darrièrs cambiaments',
 'recentchanges-summary' => 'Vaquí sus aquesta pagina, los darrièrs cambiaments de {{SITENAME}}.',
+'recentchanges-noresult' => 'Pas cap de modificacion que correspond a aqueles critèris sul periòde indicat.',
 'recentchanges-feed-description' => "Seguissètz los darrièrs cambiaments d'aqueste wiki dins un flux.",
 'recentchanges-label-newpage' => 'Aquesta modificacion a creat una pagina novèla',
 'recentchanges-label-minor' => 'Aqueste cambiament es menor',
 'recentchanges-label-bot' => 'Aqueste cambiament es estat efectuat per un bòt.',
 'recentchanges-label-unpatrolled' => 'Aqueste cambiament es pas estat verificat encara.',
+'recentchanges-legend-newpage' => '$1 - pagina novèla',
 'rcnote' => 'Vaquí {{PLURAL:$1|lo darrièr cambiament|los $1 darrièrs cambiaments}} dempuèi {{PLURAL:$2|lo darrièr jorn|los <b>$2</b> darrièrs jorns}}, determinat{{PLURAL:$1||s}} lo $4, a $5.',
 'rcnotefrom' => "Vaquí los cambiaments efectuats dempuèi lo '''$2''' ('''$1''' al maximum).",
 'rclistfrom' => 'Afichar las modificacions novèlas dempuèi lo $1.',
@@ -1766,8 +1777,8 @@ Vejatz la [[Special:NewFiles|galariá dels imatges novèls]] per una presentacio
 'filetype-bad-ie-mime' => 'Lo fichièr pòt pas èsser importat perque serià detectat coma « $1 » per Internet Explorer, tipe de fichièr interdich perque potencialament dangierós.',
 'filetype-unwanted-type' => "«.$1»''' es un format de fichièr pas desirat.
 {{PLURAL:$3|Lo tipe de fichièr preconizat es|Los tipes de fichièrs preconizats son}} $2.",
-'filetype-banned-type' => "''' « .$1 » '''{{PLURAL:$4|est pas un tipe de fichièr autorizat|son pas de tipes de fichièrs autorizats}}. 
-{{PLURAL:$3|lo tipe de fichièr autorizat es |los tipes de fichièrs autorizats son}} $2.",
+'filetype-banned-type' => "''' « .$1 » '''{{PLURAL:$4|es pas un tipe de fichièr autorizat|son pas de tipes de fichièrs autorizats}}. 
+{{PLURAL:$3|Lo tipe de fichièr autorizat es|Los tipes de fichièrs autorizats son}} $2.",
 'filetype-missing' => "Lo fichièr a pas cap d'extension (coma « .jpg » per exemple).",
 'empty-file' => "Lo fichièr qu'avètz somés èra void.",
 'file-too-large' => "Lo fichièr qu'avètz somés èra tròp grand.",
@@ -2092,6 +2103,7 @@ Doblidetz pas de verificar se i a pas d’autre ligam cap als modèls abans de l
 'statistics-edits' => 'Modificacions de paginas dempuèi que {{SITENAME}} foguèt installat',
 'statistics-edits-average' => 'Modificacions mejanas per pagina',
 'statistics-views-total' => 'Visitas totalas',
+'statistics-views-total-desc' => 'Las vistas de las paginas non existentas e de las paginas especialas son pas inclusas',
 'statistics-views-peredit' => 'Visitas per modificacions',
 'statistics-users' => '[[Special:ListUsers|Utilizaires]] enregistrats',
 'statistics-users-active' => 'Utilizaires actius',
@@ -2100,6 +2112,7 @@ Doblidetz pas de verificar se i a pas d’autre ligam cap als modèls abans de l
 
 'pageswithprop' => 'Paginas amb una proprietat de pagina',
 'pageswithprop-legend' => 'Paginas amb una proprietat de pagina',
+'pageswithprop-text' => "Aquesta pagina fa la lista de las paginas qu'utilizan una proprietat de pagina particulara.",
 'pageswithprop-prop' => 'Nom de la proprietat :',
 'pageswithprop-submit' => 'Anar',
 'pageswithprop-prophidden-long' => 'valor de proprietat de tèxte long amagada ($1)',
@@ -2175,6 +2188,7 @@ Las entradas <del>barradas</del> son estadas resolgudas.',
 'listusers' => 'Lista dels participants',
 'listusers-editsonly' => "Far veire sonque los utilizaires qu'an al mens una contribucion",
 'listusers-creationsort' => 'Triar per data de creacion',
+'listusers-desc' => 'Triar en òrdre descendent',
 'usereditcount' => '$1 {{PLURAL:$1|cambiament|cambiaments}}',
 'usercreated' => '{{GENDER:$3|Creat}} lo $1 a $2',
 'newpages' => 'Paginas novèlas',
@@ -2192,6 +2206,7 @@ Notatz que d’autres sites pòdon aver un ligam dirècte cap a un fichièr, e d
 'pager-newer-n' => '{{PLURAL:$1|1 mai recenta|$1 mai recentas}}',
 'pager-older-n' => '{{PLURAL:$1|1 mai anciana|$1 mai ancianas}}',
 'suppress' => 'Supervisor',
+'querypage-disabled' => 'Aquesta pagina especiala es desactivada per de rasons de performàncias.',
 
 # Book sources
 'booksources' => 'Obratges de referéncia',
@@ -2365,6 +2380,7 @@ per modificar vòstra lista de seguiment.',
 # Displayed when you click the "watch" button and it is in the process of watching
 'watching' => 'Seguit...',
 'unwatching' => 'Fin del seguit...',
+'watcherrortext' => "Una error s'es producha al moment de la modificacion dels paramètres de vòstra lista de seguiment per « $1 ».",
 
 'enotif_mailer' => 'Sistèma d’expedicion de notificacion de {{SITENAME}}',
 'enotif_reset' => 'Marcar totas las paginas coma visitadas',
@@ -2435,10 +2451,12 @@ Vejatz $2 per una lista de las supressions recentas.',
 'deletecomment' => 'Motiu :',
 'deleteotherreason' => 'Motius suplementaris o autres :',
 'deletereasonotherlist' => 'Autre motiu',
-'deletereason-dropdown' => "*Motius de supression mai corrents
-** Demanda de l'autor
-** Violacion dels dreches d'autor
-** Vandalisme",
+'deletereason-dropdown' => '* Motius de supression los mai corrents
+** Corrièrs indesirables
+** Vandalisme
+** Violacion dels dreches d’autor
+** Demanda de l’autor
+** Redireccion copada',
 'delete-edit-reasonlist' => 'Modifica los motius de la supression',
 'delete-toobig' => "Aquesta pagina dispausa d'un istoric important, depassant {{PLURAL:$1|revision|revisions}}.
 La supression de talas paginas es estada limitada per evitar de perturbacions accidentalas de {{SITENAME}}.",
@@ -2460,7 +2478,7 @@ qualqu’un mai ja a modificat o revocat la pagina.
 La darrièra modificacion es estada efectuada per [[User:$3|$3]] ([[User talk:$3|Discutir]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
 'editcomment' => "Lo resumit de la modificacion èra : « ''$1'' ».",
 'revertpage' => 'Anullacion de las modificacions de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]]) cap a la darrièra version de [[User:$1|$1]]',
-'revertpage-nouser' => 'Revocacion de las modificacions per un d’utilizaire amagat a la darrièra version per [[User:$1|$1]]',
+'revertpage-nouser' => 'Revocacion de las modificacions per un utilizaire amagat a la darrièra version per {{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'Anullacion de las modificacions de $1 ; retorn a la version de $2.',
 
 # Edit tokens
@@ -2481,6 +2499,7 @@ Consultatz la [[Special:ProtectedPages|lista de las paginas protegidas]] per la
 'protect-title-notallowed' => 'Veire lo nivèl de proteccion de « $1 »',
 'prot_1movedto2' => 'a renomenat [[$1]] en [[$2]]',
 'protect-badnamespace-title' => 'Espaci de noms pas protegible',
+'protect-badnamespace-text' => 'Las paginas dins aqueste espaci de noms pòdon pas èsser protegidas.',
 'protect-norestrictiontypes-title' => 'Pagina pas protegibla',
 'protect-legend' => 'Confirmar la proteccion',
 'protectcomment' => 'Rason :',
@@ -2593,7 +2612,7 @@ $1",
 'contributions' => "Contribucions de l'{{GENDER:$1|utilizaire|utilizaira}}",
 'contributions-title' => 'Lista de las contribucions de l’utilizaire $1',
 'mycontris' => 'Contribucions',
-'contribsub2' => 'Lista de las contribucions de $1 ($2). Las paginas que son estadas escafadas son pas afichadas.',
+'contribsub2' => 'Per {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Cap de modificacion correspondenta a aquestes critèris es pas estada trobada.',
 'uctop' => '(actual)',
 'month' => 'A partir del mes (e precedents) :',
@@ -2658,6 +2677,7 @@ Donatz çaijós un motiu precís (per exemple en citant las paginas que son esta
 ** Temptativa d’intimidacion o agarriment
 ** Abús d’utilizacion de comptes multiples
 ** Nom d’utilizaire inacceptable, injuriós o difamant',
+'ipb-hardblock' => 'Empachar los utilizaires connectats de modificar en utilizant aquesta adreça IP',
 'ipbcreateaccount' => 'Empachar la creacion de compte',
 'ipbemailban' => 'Empachar l’utilizaire de mandar de corrièrs electronics',
 'ipbenableautoblock' => 'Blocar automaticament las adreças IP utilizadas per aqueste utilizaire',
@@ -2668,6 +2688,7 @@ Donatz çaijós un motiu precís (per exemple en citant las paginas que son esta
 'ipbotherreason' => 'Motiu diferent o suplementari',
 'ipbhidename' => 'Amagar lo nom d’utilizaire de las modificacions e de las listas',
 'ipbwatchuser' => "Seguir las paginas d'utilizaire e de discussion d'aqueste utilizaire",
+'ipb-disableusertalk' => "Empachar l'utilizaire de modificar sa pagina de discussion pendent lo blocatge",
 'ipb-change-block' => 'Tornar blocar aqueste utilizaire amb aquestes paramètres',
 'ipb-confirm' => 'Confirmar lo blocatge',
 'badipaddress' => "L'adreça IP es incorrècta",
@@ -2842,6 +2863,7 @@ Lo volètz suprimir per permetre lo cambiament de nom ?',
 'immobile-source-page' => 'Aquesta pagina se pòt pas tornar nomenar.',
 'immobile-target-page' => 'Es pas possible de desplaçar la pagina cap a aqueste títol.',
 'imagenocrossnamespace' => 'Pòt pas desplaçar un imatge cap a un espaci de nomenatge que siá pas un imatge.',
+'nonfile-cannot-move-to-file' => "Impossible de renomenar quicòm mai qu'un fichièr cap a l'espaci de noms fichièr.",
 'imagetypemismatch' => "L'extension novèla d'aqueste fichièr reconeis pas aqueste format.",
 'imageinvalidfilename' => 'Lo nom del fichièr cibla es incorrècte',
 'fix-double-redirects' => 'Metre a jorn las redireccions que puntant cap al títol ancian',
@@ -2864,6 +2886,7 @@ Dins aqueste darrièr cas, podètz tanben utilizar un ligam, coma [[{{#Special:E
 'exportcuronly' => 'Exportar unicament la version correnta sens l’istoric complet',
 'exportnohistory' => "----
 '''Nòta :''' l’exportacion completa de l’istoric de las paginas amb l’ajuda d'aqueste formulari es estada desactivada per de rasons de performàncias.",
+'exportlistauthors' => 'Inclure una lista completa dels contributors per cada pagina',
 'export-submit' => 'Exportar',
 'export-addcattext' => 'Apondre las paginas de la categoria :',
 'export-addcat' => 'Apondre',
@@ -2879,7 +2902,7 @@ Dins aqueste darrièr cas, podètz tanben utilizar un ligam, coma [[{{#Special:E
 'allmessagesdefault' => 'Messatge per defaut',
 'allmessagescurrent' => 'Messatge actual',
 'allmessagestext' => 'Aquò es la lista de totes los messatges disponibles dins l’espaci MediaWiki.
-Visitatz la [//www.mediawiki.org/wiki/Localisation Localizacion MediaWiki] e [//translatewiki.net translatewiki.net] se desiratz contribuir a la localizacion MediaWiki generica.',
+Visitatz la [https://www.mediawiki.org/wiki/Localisation Localizacion MediaWiki] e [//translatewiki.net translatewiki.net] se desiratz contribuir a la localizacion MediaWiki generica.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' es pas disponible perque '''\$wgUseDatabaseMessages''' es desactivat.",
 'allmessages-filter-legend' => 'Filtre',
 'allmessages-filter' => 'Filtrar per estat de modificacion :',
@@ -2898,6 +2921,8 @@ Visitatz la [//www.mediawiki.org/wiki/Localisation Localizacion MediaWiki] e [//
 $2",
 'djvu_page_error' => 'Pagina DjVu fòra limits',
 'djvu_no_xml' => "Impossible d’obténer l'XML pel fichièr DjVu",
+'thumbnail-temp-create' => 'Impossible de crear lo fichièr de vinheta temporari',
+'thumbnail-dest-create' => "Impossible d'enregistrar la vinheta sus la destinacion",
 'thumbnail_invalid_params' => 'Paramètres de la miniatura invalids',
 'thumbnail_dest_directory' => 'Impossible de crear lo repertòri de destinacion',
 'thumbnail_image-type' => 'Tipe d’imatge pas suportat',
@@ -2943,7 +2968,11 @@ Salvatz-lo sus vòstre disc dur puèi importatz-lo aicí.",
 'import-upload' => "Impòrt d'un fichier XML",
 'import-token-mismatch' => 'Pèrda de las donadas de sesilha. Tornatz ensajar.',
 'import-invalid-interwiki' => "Impossible d'importar dempuèi lo wiki especificat.",
+'import-error-edit' => 'La pagina « $1 » es pas estada importada perque sètz pas autorizat a la modificar.',
+'import-error-create' => 'La pagina « $1 » es pas estada importada perque sètz pas autorizat a la crear.',
+'import-error-invalid' => 'Pagina « $1 » es pas importada perque son nom es pas valid.',
 'import-options-wrong' => '{{PLURAL:$2|Marrida opcion|Marridas opcions}} : <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'La pagina raiç provesida es un títol invalid.',
 
 # Import log
 'importlogpage' => 'Istoric de las importacions de paginas',
@@ -2956,6 +2985,7 @@ Salvatz-lo sus vòstre disc dur puèi importatz-lo aicí.",
 # JavaScriptTest
 'javascripttest' => 'Tèst de JavaScript',
 'javascripttest-title' => 'Execucion dels tèsts $1',
+'javascripttest-pagetext-noframework' => "Aquesta pagina es reservada per l'execucion dels tèsts JavaScript.",
 'javascripttest-pagetext-unknownframework' => 'Estructura « $1 » desconeguda.',
 'javascripttest-pagetext-frameworks' => 'Causissètz una de las estructuras de tèst seguentas : $1',
 'javascripttest-pagetext-skins' => 'Causissètz un abilhatge amb lo qual cal aviar los tèsts :',
@@ -3070,6 +3100,8 @@ Aquò es probablament causat per un ligam sus lista negra que punta cap a un sit
 'spam_reverting' => 'Restabliment de la darrièra version que conten pas de ligam cap a $1',
 'spam_blanking' => 'Totas las versions que contenon de ligams cap a $1 son blanquidas',
 'spam_deleting' => 'Totas las versions contenonián de ligams cap a $1, supression',
+'simpleantispam-label' => "Verificacion antispam.
+Inscriviscatz '''PAS RES''' dedins !",
 
 # Info page
 'pageinfo-title' => 'Informacions per « $1 »',
@@ -3082,6 +3114,7 @@ Aquò es probablament causat per un ligam sus lista negra que punta cap a un sit
 'pageinfo-length' => 'Talha de la pagina (en octets)',
 'pageinfo-article-id' => 'Numèro de la pagina',
 'pageinfo-language' => 'Lenga del contengut de la pagina',
+'pageinfo-content-model' => 'Modèl de contengut de la pagina',
 'pageinfo-robot-policy' => 'Indexacion per robòts',
 'pageinfo-robot-index' => 'Autorizada',
 'pageinfo-robot-noindex' => 'Interdicha',
@@ -3166,7 +3199,7 @@ Se l'executatz, vòstre sistèma pòt èsser compromés.",
 'svg-long-desc' => 'Fichièr SVG, resolucion de $1 × $2 pixèls, talha : $3',
 'svg-long-desc-animated' => 'Fichièr SVG animat, talha $1 x $2 pixèls, talha del fichièr : $3',
 'svg-long-error' => 'Fichièr SVG invalid : $1',
-'show-big-image' => 'Imatge en resolucion mai nauta',
+'show-big-image' => "Fichièr d'origina",
 'show-big-image-preview' => "Talha d'aqueste apercebut : $1.",
 'show-big-image-other' => '{{PLURAL:$2|Autra resolucion|Autras resolucions}} : $1.',
 'show-big-image-size' => '$1 × $2 pixèls',
@@ -3636,7 +3669,7 @@ Los autres ligams sus la meteissa linha son considerats coma d'excepcions, per e
 
 # External editor support
 'edit-externally' => 'Modificar aqueste fichièr en utilizant una aplicacion extèrna',
-'edit-externally-help' => "(Consultatz [//www.mediawiki.org/wiki/Manual:External_editors/oc las instruccions d'installacion] per mai d’entresenhas)",
+'edit-externally-help' => "(Consultatz [https://www.mediawiki.org/wiki/Manual:External_editors/oc las instruccions d'installacion] per mai d’entresenhas)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tot',
@@ -3732,6 +3765,7 @@ Confirmatz que desiratz tornar crear aqueste article.",
 
 # Separators for various lists, etc.
 'colon-separator' => '&nbsp;:&#32;',
+'quotation-marks' => '« $1 »',
 
 # Multipage image navigation
 'imgmultipageprev' => '← pagina precedenta',
@@ -3821,7 +3855,7 @@ Ensajatz la previsualizacion normala.',
 'version-hook-subscribedby' => 'Definit per',
 'version-version' => '(Version $1)',
 'version-license' => 'Licéncia',
-'version-poweredby-credits' => "Aqueste wiki fonciona gràcias a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Aqueste wiki fonciona gràcias a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'autres',
 'version-poweredby-translators' => 'traductors de translatewiki.net',
 'version-software' => 'Logicial installat',
@@ -3855,8 +3889,7 @@ Ensajatz la previsualizacion normala.',
 
 # Special:SpecialPages
 'specialpages' => 'Paginas especialas',
-'specialpages-note' => '----
-* Paginas especialas normalas.
+'specialpages-note' => '* Paginas especialas normalas.
 * <span class="mw-specialpagerestricted">Paginas especialas restrenchas.</span>
 * <span class="mw-specialpagecached">Paginas especialas solament en escondedor (poirián èsser obsolètas).</span>',
 'specialpages-group-maintenance' => 'Rapòrts de mantenença',
@@ -3896,7 +3929,10 @@ Ensajatz la previsualizacion normala.',
 'tags-tag' => 'Nom de la balisa',
 'tags-display-header' => 'Aparéncia dins las listas de modificacions',
 'tags-description-header' => 'Descripcion completa de la balisa',
+'tags-active-header' => 'Actiu ?',
 'tags-hitcount-header' => 'Modificacions balisadas',
+'tags-active-yes' => 'Òc',
+'tags-active-no' => 'Non',
 'tags-edit' => 'modificar',
 'tags-hitcount' => '$1 {{PLURAL:$1|cambiament|cambiaments}}',
 
@@ -3917,6 +3953,7 @@ Ensajatz la previsualizacion normala.',
 'dberr-problems' => 'O planhèm ! Aqueste site rencontra de dificultats tecnicas.',
 'dberr-again' => "Ensajatz d'esperar qualques minutas e tornatz cargar.",
 'dberr-info' => '(Se pòt pas connectar al servidor de la banca de donadas : $1)',
+'dberr-info-hidden' => '(Connexion al servidor de la banca de donadas impossibla)',
 'dberr-usegoogle' => 'Podètz ensajar de cercar amb Google pendent aqueste temps.',
 'dberr-outofdate' => 'Notatz que lors indèxes de nòstre contengut pòdon èsser depassats.',
 'dberr-cachederror' => 'Aquò es una còpia amagada de la pagina demandada e pòt èsser depassada.',
@@ -3985,7 +4022,9 @@ Ensajatz la previsualizacion normala.',
 'feedback-error1' => "Error : Resultat de l'IPA pas reconegut",
 'feedback-error2' => 'Error : la modificacion a fracassat',
 'feedback-error3' => "Error : pas cap de responsa de l'API",
+'feedback-thanks' => 'Mercé ! Vòstre comentari es estat publicat sus la pagina "[$2 $1]".',
 'feedback-close' => 'Fach',
+'feedback-bugcheck' => "Remirable ! Verificatz simplament qu'es pas un dels [$1 bugs ja coneguts].",
 'feedback-bugnew' => 'Ai verificat. Senhalar un bug novèl',
 
 # Search suggestions
@@ -3996,6 +4035,8 @@ Ensajatz la previsualizacion normala.',
 'api-error-badaccess-groups' => 'Sètz pas autorizat a cargar de fichièrs sus aqueste wiki.',
 'api-error-badtoken' => 'Error intèrna : marrit « geton ».',
 'api-error-copyuploaddisabled' => 'Los cargaments via URL son desactivats sus aqueste servidor.',
+'api-error-duplicate' => "I a ja {{PLURAL:$1|[$2 un autre fichièr present]|[$2 d'autres fichièrs presents]}} sul site amb lo meteis contengut.",
+'api-error-duplicate-archive' => "I aviá ja {{PLURAL:$1|[$2 un autre fichièr present]|[$2 d'autres fichièrs presents]}} sul site amb lo meteis contengut, mas {{PLURAL:$1|es estat suprimit|son estats suprimits}}.",
 'api-error-duplicate-archive-popup-title' => 'Duplicar {{PLURAL:$1|lo fichièr|los fichièrs}} que {{PLURAL:$1|ja es estat suprimit|je son estats suprimits}}',
 'api-error-duplicate-popup-title' => '{{PLURAL:$1|fichièr|fichièrs}} en doble',
 'api-error-empty-file' => "Lo fichièr qu'avètz somés èra void.",
@@ -4005,16 +4046,31 @@ Ensajatz la previsualizacion normala.',
 'api-error-file-too-large' => "Lo fichièr qu'avètz somés èra tròp grand.",
 'api-error-filename-tooshort' => 'Lo nom del fichièr es tròp cort.',
 'api-error-filetype-banned' => 'Aqueste tipe de fichièr es interdich',
+'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|es pas un tipe de fichièr autorizat|son pas de tipes de fichièrs autorizats}}. 
+{{PLURAL:$3|Lo tipe de fichièr autorizat es|Los tipes de fichièrs autorizats son}} $2.',
 'api-error-filetype-missing' => "L'extension del fichièr es mancanta.",
 'api-error-hookaborted' => "La modificacion qu'avètz ensajat de realizar es estada anullada per una extension.",
+'api-error-http' => 'Error intèrna : se pòt pas connectar al servidor.',
 'api-error-illegal-filename' => 'Lo nom del fichièr es pas autorizat.',
+'api-error-internal-error' => "Error intèrna : Quicòm s'es mal passat al moment del tractament de vòstre impòrt sul wiki.",
+'api-error-invalid-file-key' => "Error intèrna : cap de fichièr pas trobat dins l'emmagazinatge temporari.",
+'api-error-missingparam' => 'Error intèrna : Manca de paramètres dins la requèsta.',
+'api-error-missingresult' => 'Error intèrna : Avèm pas pogut determinar se la còpia aviá capitat.',
+'api-error-mustbeloggedin' => 'Vos cal èsser connectat per telecargar de fichièrs.',
+'api-error-mustbeposted' => 'Error intèrna : aquesta requèsta necessita lo metòde HTTP POST.',
 'api-error-nomodule' => 'Error intèrna : cap de modul de versament pas definit.',
 'api-error-ok-but-empty' => 'Error intèrna : Lo servidor a pas respondut.',
+'api-error-overwrite' => 'Espotir un fichièr existent es pas autorizat.',
+'api-error-stashfailed' => 'Error intèrna : lo servidor a pas pogut enregistrar lo fichièr temporari.',
+'api-error-publishfailed' => 'Error intèrna: Lo servidor a pas pogut publicar lo fichièr temporari.',
+'api-error-timeout' => 'Lo servidor a pas respondut dins lo relambi pervist.',
 'api-error-unclassified' => "Una error desconeguda s'es producha.",
 'api-error-unknown-code' => 'Error desconeguda : « $1 »',
+'api-error-unknown-error' => 'Error intèrna : Quicòm a mal virat al moment del mandadís de vòstre fichièr.',
 'api-error-unknown-warning' => 'Avertiment desconegut : $1',
 'api-error-unknownerror' => 'Error desconeguda : « $1 »',
 'api-error-uploaddisabled' => 'Lo cargament es desactivat sus aqueste wiki.',
+'api-error-verification-error' => 'Aqueste fichièr pòt èsser corromput, o son extension es incorrècta.',
 
 # Durations
 'duration-seconds' => '$1 segonda{{PLURAL:$1||s}}',
@@ -4039,10 +4095,23 @@ Ensajatz la previsualizacion normala.',
 'limitreport-ppvisitednodes' => 'Nombre de nosèls de preprocessor visitats',
 'limitreport-ppgeneratednodes' => 'Nombre de nosèls de preprocessor generats',
 'limitreport-postexpandincludesize' => 'Talha d’inclusion aprèp espandiment',
-'limitreport-postexpandincludesize-value' => '$1/$2 octets',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|octet|octets}}',
 'limitreport-templateargumentsize' => 'Talha de l’argument del modèl',
-'limitreport-templateargumentsize-value' => '$1/$2 octets',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|octet|octets}}',
 'limitreport-expansiondepth' => 'Mai granda prigondor d’espandiment',
 'limitreport-expensivefunctioncount' => 'Nombre de foncions d’analisi costosas',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espandiment dels modèls',
+'expand_templates_intro' => 'Aquesta pagina permet de testar l’espandiment de modèls, que son desvolopats recursivament. Las foncions e las variablas predefinidas, coma <nowiki>{{</nowiki>#language:...}} e <nowiki>{{</nowiki>CURRENTDAY}} tanben son desvolopadas.',
+'expand_templates_title' => 'Títol de l’article, util per exemple se lo modèl utiliza {{FULLPAGENAME}} :',
+'expand_templates_input' => 'Picatz vòstre tèxte aicí :',
+'expand_templates_output' => 'Visualizatz lo resultat :',
+'expand_templates_xml_output' => 'Sortida XML',
+'expand_templates_ok' => "D'acòrdi",
+'expand_templates_remove_comments' => 'Suprimir los comentaris.',
+'expand_templates_remove_nowiki' => 'Suprimís los marcadors <nowiki> dins lo resultat',
+'expand_templates_generate_xml' => "Veire l'arborescéncia XML",
+'expand_templates_preview' => 'Previsualizacion',
+
 );
index 6ab6ef9..652c970 100644 (file)
@@ -83,7 +83,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'ଖରାପନାମ' ),
        'Blankpage'                 => array( 'ଖାଲିପୃଷ୍ଠା' ),
        'Block'                     => array( 'ଅଟକାଇବେ', 'ଆଇପିଅଟକାଇବେ', 'ସଭ୍ୟଅଟକାଇବେ' ),
-       'Blockme'                   => array( 'ମୋତେଅଟକାଇବେ' ),
        'Booksources'               => array( 'ବହିସ୍ରୋତ' ),
        'BrokenRedirects'           => array( 'ଭଙ୍ଗାଲେଉଟାଣି' ),
        'Categories'                => array( 'ଶ୍ରେଣୀ' ),
@@ -95,7 +94,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ଖାତାଖୋଲିବେ' ),
        'Deadendpages'              => array( 'ଆଗକୁରାହାନଥିବାପୃଷ୍ଠା' ),
        'DeletedContributions'      => array( 'ହଟାଇଦିଆଯାଇଥିବାଅବଦାନ' ),
-       'Disambiguations'           => array( 'ବହୁବିକଳ୍ପୀ' ),
        'DoubleRedirects'           => array( 'ଦୁଇଥରଲେଉଟାଣି' ),
        'EditWatchlist'             => array( 'ଧ୍ୟାନସୂଚୀବଦଳାଇବେ' ),
        'Emailuser'                 => array( 'ସଭ୍ୟଙ୍କୁମେଲକରିବେ' ),
@@ -530,8 +528,6 @@ $1',
 'ok' => 'ଠିକ ଅଛି',
 'retrievedfrom' => '"$1" ରୁ ଅଣାଯାଇଅଛି',
 'youhavenewmessages' => 'ଆପଣଙ୍କ ପାଇଁ $1 ($2)।',
-'newmessageslink' => 'ନୂଆ ମେସେଜ',
-'newmessagesdifflink' => 'ଶେଷ ବଦଳ',
 'youhavenewmessagesfromusers' => 'ଆପଣଙ୍କର {{PLURAL:$3|another user|$3 users}} ($2)ରୁ $1 ଅଛି ।',
 'youhavenewmessagesmanyusers' => 'ଆପଣଙ୍କର ବହୁତ ବ୍ୟବହାରକାରୀ($2)ମାନଙ୍କଠାରୁ $1 ଅଛି ।',
 'newmessageslinkplural' => '{{PLURAL:$1|ଏକ ନୂଆ ସନ୍ଦେଶ|ନୂଆ ସନ୍ଦେଶ}}',
@@ -1372,8 +1368,6 @@ $1",
 'preferences' => 'ପସନ୍ଦ',
 'mypreferences' => 'ପସନ୍ଦ',
 'prefs-edits' => 'ସମ୍ପାଦନା ସଂଖ୍ୟା:',
-'prefsnologin' => 'ଲଗ‌‌ ଇନ କରିନାହାନ୍ତି',
-'prefsnologintext' => 'ବ୍ୟବହାରକାରୀଙ୍କ ପସନ୍ଦସବୁ ବଦଳାଇବା ପାଇଁ ଆପଣଙ୍କୁ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ଲଗ ଇନ]</span> କରିବାକୁ ପଡ଼ିବ ।',
 'changepassword' => 'ପାସୱର୍ଡ଼ ବଦଳାନ୍ତୁ',
 'prefs-skin' => 'ବହିରାବରଣ',
 'skin-preview' => 'ସାଇତା ଆଗରୁ ଦେଖଣା',
@@ -2890,7 +2884,7 @@ MediaWiki ବ୍ୟବହାର କରି [[Special:Import|ପୃଷ୍ଠା 
 'allmessagesdefault' => 'ଆପେଆପେ ଚିଠିରେ ରହିବା କଥା',
 'allmessagescurrent' => 'ଏବେକର ସନ୍ଦେଶ ଲେଖା',
 'allmessagestext' => 'ଏଥିରେ ମିଡ଼ିଆଉଇକି ନେମସ୍ପେସରେ ଥିବା ସିଷ୍ଟମ ସନ୍ଦେଶର ଏକ ତାଲିକା ଦିଆଗଲା ।
-ଯଦି ଆପଣ ମୂଳ ଦୟାକରି ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣରେ ଭାଗ ନେବା ପାଇଁ ଚାହାନ୍ତି ତେବେ [//www.mediawiki.org/wiki/Localisation ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣ] ଓ [//translatewiki.net translatewiki.net] ଦେଖନ୍ତୁ ।',
+ଯଦି ଆପଣ ମୂଳ ଦୟାକରି ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣରେ ଭାଗ ନେବା ପାଇଁ ଚାହାନ୍ତି ତେବେ [https://www.mediawiki.org/wiki/Localisation ମିଡ଼ିଆଉଇକି ଆଞ୍ଚଳିକୀକରଣ] ଓ [//translatewiki.net translatewiki.net] ଦେଖନ୍ତୁ ।',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' ଅଚଳ କରାଯାଇଥିବାରୁ ଏହି ପୃଷ୍ଠାଟି ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ ।",
 'allmessages-filter-legend' => 'ଛାଣିବା',
 'allmessages-filter' => 'ଆପଣା ପସନ୍ଦରେ ଛାଣିବେ:',
@@ -3080,6 +3074,8 @@ MediaWiki ବ୍ୟବହାର କରି [[Special:Import|ପୃଷ୍ଠା 
 'spam_reverting' => '$1 ସହ ଯୋଡ଼ା ନଥିବା ଶେଷ ସଂସ୍କରଣକୁ ଲେଉଟାଇ ଦେଉଅଛୁଁ',
 'spam_blanking' => '$1 ସହ ଯୋଡ଼ାଥିବା ସବୁଯାକ ସଂସ୍କରଣ ଖାଲି କରିଦିଆଗଲା',
 'spam_deleting' => '$1 ସହ ଯୋଡ଼ାଥିବା ସବୁଯାକ ସଂସ୍କରଣ ଖାଲି କରିଦିଆଗଲା',
+'simpleantispam-label' => "ସ୍ପାମ-ବିରୋଧି ପରଖ ।
+ଏହାକୁ ଭରନ୍ତୁ '''ନାହିଁ''' !",
 
 # Info page
 'pageinfo-title' => '"$1"ର ବିବରଣୀ',
@@ -3631,7 +3627,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'ଏକ ବାହାର ଆପ୍ଲିକେସନ ବ୍ୟବହାର କରି ଏହି ଫାଇଲଟିକୁ ବଦଳାଇବା',
-'edit-externally-help' => '(ଆହୁରି ବି [//www.mediawiki.org/wiki/Manual:External_editors ସଜାଡିବା ନିର୍ଦେଶ] ଦେଖନ୍ତୁ)',
+'edit-externally-help' => '(ଆହୁରି ବି [https://www.mediawiki.org/wiki/Manual:External_editors ସଜାଡିବା ନିର୍ଦେଶ] ଦେଖନ୍ତୁ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ସବୁ',
@@ -3815,7 +3811,7 @@ $5
 'version-hook-subscribedby' => 'କାହା ଦେଇ ମଗାଯାଇଛି',
 'version-version' => '(ଭାଗ $1)',
 'version-license' => 'ଲାଇସେନ୍ସ',
-'version-poweredby-credits' => "ଏହି ଉଇକିଟି '''[//www.mediawiki.org/ ମିଡ଼ିଆଉଇକି]''' ଦେଇ ପରିଚାଳିତ, ସତ୍ଵାଧିକାର © ୨୦୦୧-$1 $2 ।",
+'version-poweredby-credits' => "ଏହି ଉଇକିଟି '''[https://www.mediawiki.org/ ମିଡ଼ିଆଉଇକି]''' ଦେଇ ପରିଚାଳିତ, ସତ୍ଵାଧିକାର © ୨୦୦୧-$1 $2 ।",
 'version-poweredby-others' => 'ବାକିସବୁ',
 'version-credits-summary' => 'ଆମେ ଏହି ଲୋକମାନଙ୍କୁ [[Special:Version|MediaWiki]]ରେ ସେମାନକର ଅବଦାନ ପାଇଁ ଚିହ୍ନିବାକୁ ଚାହୁଁଛୁ ।',
 'version-license-info' => 'MediaWiki ଏକ ମାଗଣା ସଫ୍ଟୱାର; ଆପଣ ଏହାକୁ ପୁନବଣ୍ଟନ କରିପାରିବେ ବା GNU ଜେନେରାଲ ପବ୍ଲିକ ଲାଇସେନ୍ସ ଅଧିନରେ ବଦଳାଇପାରିବେ ଯାହା ଫ୍ରି ସଫ୍ଟୱାର ଫାଉଣ୍ଡେସନ ଦେଇ ପ୍ରକାଶିତ ହୋଇଥିବ।
@@ -3843,8 +3839,7 @@ MediaWiki ଉପଯୋଗୀ ହେବା ଲକ୍ଷରେ ବଣ୍ଟାଯ
 
 # Special:SpecialPages
 'specialpages' => 'ବିଶେଷ ପୃଷ୍ଠା',
-'specialpages-note' => '----
-* ସାଧାରଣ ବିଶେଷ ପୃଷ୍ଠାମାନ ।
+'specialpages-note' => '* ସାଧାରଣ ବିଶେଷ ପୃଷ୍ଠାମାନ ।
 * <span class="mw-specialpagerestricted">କିଳାଯାଇଥିବା ବିଶେଷ ପୃଷ୍ଠାମାନ ।</span>',
 'specialpages-group-maintenance' => 'ରକ୍ଷଣାବେକ୍ଷଣା ବିବରଣୀ',
 'specialpages-group-other' => 'ବାକି ବିଶେଷ ପୃଷ୍ଠା',
@@ -4035,4 +4030,11 @@ MediaWiki ଉପଯୋଗୀ ହେବା ଲକ୍ଷରେ ବଣ୍ଟାଯ
 'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
 'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
 
+# Special:ExpandTemplates
+'expand_templates_input' => 'ଇନପୁଟ ବିଷୟ:',
+'expand_templates_output' => 'ପରିଣାମ',
+'expand_templates_ok' => 'ଠିକ ଅଛି',
+'expand_templates_remove_comments' => 'ମତାମତ ହଟାନ୍ତୁ',
+'expand_templates_preview' => 'ଦେଖଣା',
+
 );
index c14f4d6..a418993 100644 (file)
@@ -59,7 +59,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Æвзæрном' ),
        'Blankpage'                 => array( 'АфтидФарс' ),
        'Block'                     => array( 'Блок' ),
-       'Blockme'                   => array( 'НыблокМæКæн' ),
        'Booksources'               => array( 'ЧингуытыРавзæрæнтæ' ),
        'BrokenRedirects'           => array( 'ЦъæлРарвыстытæ' ),
        'Categories'                => array( 'Категоритæ' ),
@@ -71,7 +70,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'АккаунтСкæнын' ),
        'Deadendpages'              => array( 'ХæдбарФæрстæ' ),
        'DeletedContributions'      => array( 'ХафтБавæрд' ),
-       'Disambiguations'           => array( 'Бирæнысаниуæгджынтæ' ),
        'DoubleRedirects'           => array( 'ДывæрÆрвыстытæ' ),
        'EditWatchlist'             => array( 'ЦæстдардИвын' ),
        'Emailuser'                 => array( 'АрхайæгмæEmail' ),
@@ -447,8 +445,6 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Ист æрцыд {{grammar:ablative|"$1"}}',
 'youhavenewmessages' => 'Райстай $1 ($2).',
-'newmessageslink' => 'ног фыстæгтæ',
-'newmessagesdifflink' => 'фæстаг ивд',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Æндæр архайæгæй|$3 архайæгæй}} дæм $1 æрцыд ($2).',
 'youhavenewmessagesmanyusers' => 'Бирæ архайæгæй дæм $1 æрцыдис ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ног фыстæг|ног фыстæджытæ}}',
@@ -1073,7 +1069,6 @@ ASCII нысæнттæм чи нæ хауы, уыдон ивыны бынаты
 'preferences' => 'Уагæвæрдтæ',
 'mypreferences' => 'Уагæвæрдтæ',
 'prefs-edits' => 'Ивдтыты нымæц:',
-'prefsnologin' => 'Системæйы нæ дæ',
 'changepassword' => 'Пароль ивæн',
 'prefs-skin' => 'Цъар',
 'skin-preview' => 'Разæркаст',
@@ -1724,7 +1719,7 @@ $3',
 
 # External editor support
 'edit-externally' => 'Ивын ацы файл æддаг программæйæ',
-'edit-externally-help' => '(Кæс [//www.mediawiki.org/wiki/Manual:External_editors сывæрыны уагæвæрдтæ] фылдæр базонынæн)',
+'edit-externally-help' => '(Кæс [https://www.mediawiki.org/wiki/Manual:External_editors сывæрыны уагæвæрдтæ] фылдæр базонынæн)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'иууылдæр',
@@ -1789,7 +1784,7 @@ $3',
 'version-other' => 'Æндæр',
 'version-version' => '(Фæлтæр $1)',
 'version-license' => 'Лицензи',
-'version-poweredby-credits' => "Ацы викийæн тых радта '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ацы викийæн тых радта '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'æндæртæ',
 'version-software-version' => 'Верси',
 
@@ -1868,4 +1863,8 @@ $3',
 'duration-centuries' => '$1 {{PLURAL:$1|æнус|æнусы}}',
 'duration-millennia' => '$1 {{PLURAL:$1|мин аз|мин азы}}',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Афтæ уæд!',
+'expand_templates_preview' => 'Разæркаст',
+
 );
index c3b48e1..77f6c7b 100644 (file)
@@ -14,6 +14,7 @@
  * @author Babanwalia
  * @author Gman124
  * @author Guglani
+ * @author Jimidar
  * @author Kaganer
  * @author Raj Singh
  * @author Saurabh123
@@ -30,8 +31,8 @@ $namespaceNames = array(
        NS_MEDIA            => 'ਮੀਡੀਆ',
        NS_SPECIAL          => 'ਖ਼ਾਸ',
        NS_TALK             => 'ਗੱਲ-ਬਾਤ',
-       NS_USER             => 'ਵਰਤà©\8cਂਕਾਰ',
-       NS_USER_TALK        => 'ਵਰਤà©\8cਂਕਾਰ_ਗੱਲ-ਬਾਤ',
+       NS_USER             => 'ਵਰਤà©\8bਂਕਾਰ',
+       NS_USER_TALK        => 'ਵਰਤà©\8bਂਕਾਰ_ਗੱਲ-ਬਾਤ',
        NS_PROJECT_TALK     => '$1_ਗੱਲ-ਬਾਤ',
        NS_FILE             => 'ਤਸਵੀਰ',
        NS_FILE_TALK        => 'ਤਸਵੀਰ_ਗੱਲ-ਬਾਤ',
@@ -50,6 +51,8 @@ $namespaceAliases = array(
        'ਚਰਚਾ' => NS_TALK,
        'ਮੈਂਬਰ' => NS_USER,
        'ਮੈਂਬਰ_ਚਰਚਾ' => NS_USER_TALK,
+       'ਵਰਤੌਂਕਾਰ' => NS_USER,
+       'ਵਰਤੌਂਕਾਰ_ਗੱਲ-ਬਾਤ' => NS_USER_TALK,
        '$1_ਚਰਚਾ' => NS_PROJECT_TALK,
        'ਤਸਵੀਰ_ਚਰਚਾ' => NS_FILE_TALK,
        'ਮੀਡੀਆਵਿਕਿ' => NS_MEDIAWIKI,
@@ -63,24 +66,22 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'ਸਰਗਰਮ_ਵਰਤੋਂਕਾਰ' ),
        'Allmessages'               => array( 'ਸਾਰੇ_ਸਨੇਹੇ' ),
-       'Allpages'                  => array( 'ਸਾਰà©\87_ਪੰਨੇ' ),
-       'Ancientpages'              => array( 'ਪà©\81ਰਾਣà©\87_ਪੰਨੇ' ),
+       'Allpages'                  => array( 'ਸਾਰà©\87_ਸਫ਼ੇ' ),
+       'Ancientpages'              => array( 'ਪà©\81ਰਾਣà©\87_ਸਫ਼ੇ' ),
        'Badtitle'                  => array( 'ਖ਼ਰਾਬ_ਸਿਰਲੇਖ' ),
-       'Blankpage'                 => array( 'à¨\96਼ਾਲà©\80_ਪੰਨਾ' ),
+       'Blankpage'                 => array( 'à¨\96਼ਾਲà©\80_ਸਫ਼ਾ' ),
        'Block'                     => array( 'ਪਾਬੰਦੀ_ਲਾਓ', 'IP_’ਤੇ_ਪਾਬੰਦੀ_ਲਾਓ', 'ਵਰਤੋਂਕਾਰ_’ਤੇ_ਪਾਬੰਦੀ_ਲਾਓ' ),
-       'Blockme'                   => array( 'ਮੇਰੇ_’ਤੇ_ਪਾਬੰਦੀ_ਲਾਓ' ),
        'Booksources'               => array( 'ਕਿਤਾਬ_ਸਰੋਤ' ),
        'BrokenRedirects'           => array( 'ਟੁੱਟੇ_ਰੀਡਿਰੈਕਟ' ),
        'Categories'                => array( 'ਸ਼੍ਰੇਣੀਆਂ' ),
        'ChangeEmail'               => array( 'ਈ-ਮੇਲ_ਬਦਲੋ' ),
        'ChangePassword'            => array( 'ਪਾਸਵਰਡ_ਬਦਲੋ', 'ਪਾਸਵਰਡ_ਰੀਸੈੱਟ_ਕਰੋ' ),
-       'ComparePages'              => array( 'ਪੰਨਿਆਂ_ਦੀ_ਤੁਲਨਾ_ਕਰੋ' ),
+       'ComparePages'              => array( 'ਸਫ਼ਿਆਂ_ਦੀ_ਤੁਲਨਾ_ਕਰੋ' ),
        'Confirmemail'              => array( 'ਈ-ਮੇਲ_ਤਸਦੀਕ_ਕਰੋ' ),
        'Contributions'             => array( 'ਯੋਗਦਾਨ' ),
        'CreateAccount'             => array( 'ਖਾਤਾ_ਬਣਾਓ' ),
-       'Deadendpages'              => array( 'ਬੰਦ_ਪੰਨੇ' ),
+       'Deadendpages'              => array( 'ਬੰਦ_ਸਫ਼ੇ' ),
        'DeletedContributions'      => array( 'ਮਿਟਾਏ_ਯੋਗਦਾਨ' ),
-       'Disambiguations'           => array( 'ਗੁੰਝਲਖੋਲ੍ਹ' ),
        'DoubleRedirects'           => array( 'ਦੂਹਰੇ_ਰੀਡਿਰੈਕਟ' ),
        'EditWatchlist'             => array( 'ਨਿਗਰਾਨੀ-ਲਿਸਟ_ਸੋਧੋ' ),
        'Emailuser'                 => array( 'ਵਰਤੋਂਕਾਰ_ਨੂੰ_ਈ-ਮੇਲ_ਕਰੋ' ),
@@ -91,62 +92,62 @@ $specialPageAliases = array(
        'Import'                    => array( 'ਆਯਾਤ' ),
        'Invalidateemail'           => array( 'ਗਲਤ_ਈ-ਮੇਲ_ਪਤਾ' ),
        'JavaScriptTest'            => array( 'ਜਾਵਾਸਕ੍ਰਿਪਟ_ਪਰਖ' ),
-       'BlockList'                 => array( 'ਪਾਬੰਦà©\80à¨\86à¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
+       'BlockList'                 => array( 'ਪਾਬੰਦà©\80à¨\86à¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
        'LinkSearch'                => array( 'ਲਿੰਕ_ਖੋਜੋ' ),
-       'Listadmins'                => array( 'ਪà©\8dਰਬੰਧà¨\95ਾà¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
-       'Listbots'                  => array( 'ਬà©\8bà¨\9fਾà¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
-       'Listfiles'                 => array( 'ਫ਼ਾà¨\88ਲਾà¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
-       'Listgrouprights'           => array( 'ਵਰਤੋਂਕਾਰ_ਹੱਕ_ਸੂਚੀ' ),
-       'Listredirects'             => array( 'ਰà©\80ਡਿਰà©\88à¨\95à¨\9fਾà¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
-       'Listusers'                 => array( 'ਵਰਤà©\8bà¨\82à¨\95ਾਰਾà¨\82_ਦà©\80_ਸà©\82à¨\9aà©\80' ),
+       'Listadmins'                => array( 'ਪà©\8dਰਬੰਧà¨\95ਾà¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
+       'Listbots'                  => array( 'ਬà©\8bà¨\9fਾà¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
+       'Listfiles'                 => array( 'ਫ਼ਾà¨\88ਲਾà¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
+       'Listgrouprights'           => array( 'ਵਰਤੋਂਕਾਰ_ਹੱਕਾਂ_ਦੀ_ਲਿਸਟ' ),
+       'Listredirects'             => array( 'ਰà©\80ਡਿਰà©\88à¨\95à¨\9fਾà¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
+       'Listusers'                 => array( 'ਵਰਤà©\8bà¨\82à¨\95ਾਰਾà¨\82_ਦà©\80_ਲਿਸà¨\9f' ),
        'Lockdb'                    => array( 'ਡੈਟਾਬੇਸ_’ਤੇ_ਤਾਲਾ_ਲਗਾਓ' ),
        'Log'                       => array( 'ਚਿੱਠਾ', 'ਚਿੱਠੇ' ),
-       'Lonelypages'               => array( 'à¨\87à¨\95ੱਲà©\87_ਪੰਨੇ' ),
-       'Longpages'                 => array( 'ਲੰਬà©\87_ਪੰਨੇ' ),
+       'Lonelypages'               => array( 'à¨\87à¨\95ੱਲà©\87_ਸਫ਼ੇ' ),
+       'Longpages'                 => array( 'ਲੰਬà©\87_ਸਫ਼ੇ' ),
        'MergeHistory'              => array( 'ਰਲਾਉਣ_ਦਾ_ਅਤੀਤ' ),
        'MIMEsearch'                => array( 'MIME_ਖੋਜੋ' ),
        'Mostcategories'            => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਸ਼੍ਰੇਣੀਆਂ' ),
        'Mostimages'                => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਜੁੜੀਆਂ_ਫ਼ਾਈਲਾਂ' ),
        'Mostinterwikis'            => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਇੰਟਰਵਿਕੀ' ),
-       'Mostlinked'                => array( 'ਸਭ_ਤà©\8bà¨\82_ਵੱਧ_à¨\9cà©\81à©\9cà©\87_ਪੰਨੇ' ),
+       'Mostlinked'                => array( 'ਸਭ_ਤà©\8bà¨\82_ਵੱਧ_à¨\9cà©\81à©\9cà©\87_ਸਫ਼ੇ' ),
        'Mostlinkedcategories'      => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਜੁੜੀਆਂ_ਸ਼੍ਰੇਣੀਆਂ' ),
        'Mostlinkedtemplates'       => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਜੁੜੇ_ਫਰਮੇ' ),
        'Mostrevisions'             => array( 'ਸਭ_ਤੋਂ_ਵੱਧ_ਰੀਵਿਜ਼ਨ' ),
        'Movepage'                  => array( 'ਸਿਰਲੇਖ_ਬਦਲੋ' ),
        'Mycontributions'           => array( 'ਮੇਰੇ_ਯੋਗਦਾਨ' ),
-       'Mypage'                    => array( 'ਮà©\87ਰਾ_ਪੰਨਾ' ),
+       'Mypage'                    => array( 'ਮà©\87ਰਾ_ਸਫ਼ਾ' ),
        'Mytalk'                    => array( 'ਮੇਰੀ_ਚਰਚਾ' ),
        'Myuploads'                 => array( 'ਮੇਰੇ_ਅੱਪਲੋਡ' ),
        'Newimages'                 => array( 'ਨਵੀਆਂ_ਫ਼ਾਈਲਾਂ' ),
-       'Newpages'                  => array( 'ਨਵà©\87à¨\82_ਪੰਨੇ' ),
+       'Newpages'                  => array( 'ਨਵà©\87à¨\82_ਸਫ਼ੇ' ),
        'PasswordReset'             => array( 'ਪਾਸਵਰਡ_ਰੀਸੈੱਟ' ),
        'PermanentLink'             => array( 'ਪੱਕਾ_ਲਿੰਕ' ),
-       'Popularpages'              => array( 'ਮਸ਼ਹà©\82ਰ_ਪੰਨੇ' ),
+       'Popularpages'              => array( 'ਮਸ਼ਹà©\82ਰ_ਸਫ਼ੇ' ),
        'Preferences'               => array( 'ਪਸੰਦਾਂ' ),
        'Prefixindex'               => array( 'ਅਗੇਤਰ_ਤਤਕਰਾ' ),
-       'Protectedpages'            => array( 'ਸà©\81ਰੱà¨\96ਿà¨\85ਤ_ਪੰਨੇ' ),
+       'Protectedpages'            => array( 'ਸà©\81ਰੱà¨\96ਿà¨\85ਤ_ਸਫ਼ੇ' ),
        'Protectedtitles'           => array( 'ਸੁਰੱਖਿਅਤ_ਸਿਰਲੇਖ' ),
-       'Randompage'                => array( 'ਰਲਵਾà¨\82_ਪੰਨਾ' ),
+       'Randompage'                => array( 'ਰਲਵਾà¨\82_ਸਫ਼ਾ' ),
        'Randomredirect'            => array( 'ਸੁਰੱਖਿਅਤ_ਰੀਡਿਰੈਕਟ' ),
-       'Recentchanges'             => array( 'ਹਾਲ_\'ਚ_ਹੋਈਆਂ_ਤਬਦੀਲੀਆਂ' ),
+       'Recentchanges'             => array( 'ਹਾਲੀਆ_ਤਬਦੀਲੀਆਂ' ),
        'Recentchangeslinked'       => array( 'ਜੁੜੀਆਂ_ਤਾਜ਼ਾ_ਤਬਦੀਲੀਆਂ' ),
-       'Revisiondelete'            => array( 'ਰੀਵਿਜਨ_ਮਿਟਾਓ' ),
+       'Revisiondelete'            => array( 'ਰà©\80ਵਿà¨\9c਼ਨ_ਮਿà¨\9fਾà¨\93' ),
        'Search'                    => array( 'ਖੋਜੋ' ),
-       'Shortpages'                => array( 'à¨\9bà©\8bà¨\9fà©\87_ਪੰਨੇ' ),
-       'Specialpages'              => array( 'à¨\96਼ਾਸ_ਪੰਨੇ' ),
+       'Shortpages'                => array( 'à¨\9bà©\8bà¨\9fà©\87_ਸਫ਼ੇ' ),
+       'Specialpages'              => array( 'à¨\96਼ਾਸ_ਸਫ਼ੇ' ),
        'Statistics'                => array( 'ਅੰਕੜੇ' ),
        'Tags'                      => array( 'ਟੈਗ' ),
        'Unblock'                   => array( 'ਪਾਬੰਦੀ_ਹਟਾਓ' ),
        'Uncategorizedcategories'   => array( 'ਸ਼੍ਰੇਣੀਹੀਣ_ਸ਼੍ਰੇਣੀਆਂ' ),
        'Uncategorizedimages'       => array( 'ਸ਼੍ਰੇਣੀਹੀਣ_ਫ਼ਾਈਲਾਂ' ),
-       'Uncategorizedpages'        => array( 'ਸ਼à©\8dਰà©\87ਣà©\80ਹà©\80ਣ_ਪੰਨੇ' ),
+       'Uncategorizedpages'        => array( 'ਸ਼à©\8dਰà©\87ਣà©\80ਹà©\80ਣ_ਸਫ਼ੇ' ),
        'Uncategorizedtemplates'    => array( 'ਸ਼੍ਰੇਣੀਹੀਣ_ਫਰਮੇ' ),
        'Undelete'                  => array( 'ਅਣ-ਹਟਾਓਣ' ),
        'Unlockdb'                  => array( 'ਡੈਟਾਬੇਸ_ਖੋਲ੍ਹੋ' ),
        'Unusedcategories'          => array( 'ਅਣਵਰਤੀਆਂ_ਸ਼੍ਰੇਣੀਆਂ' ),
        'Unusedimages'              => array( 'ਅਣਵਰਤੀਆਂ_ਫ਼ਾਈਲਾਂ' ),
        'Unusedtemplates'           => array( 'ਅਣਵਰਤੇ_ਫਰਮੇ' ),
-       'Unwatchedpages'            => array( 'ਬà©\87-ਨਿà¨\97ਰਾਨ_ਪੰਨੇ' ),
+       'Unwatchedpages'            => array( 'ਬà©\87-ਨਿà¨\97ਰਾਨ_ਸਫ਼ੇ' ),
        'Upload'                    => array( 'ਅੱਪਲੋਡ' ),
        'Userlogin'                 => array( 'ਵਰਤੋਂਕਾਰ_ਲਾਗਇਨ' ),
        'Userlogout'                => array( 'ਵਰਤੋਂਕਾਰ_ਲਾਗਆਊਟ' ),
@@ -154,10 +155,10 @@ $specialPageAliases = array(
        'Version'                   => array( 'ਰੂਪ' ),
        'Wantedcategories'          => array( 'ਚਾਹੀਦੀਆਂ_ਸ਼੍ਰੇਣੀਆਂ' ),
        'Wantedfiles'               => array( 'ਚਾਹੀਦੀਆਂ_ਫ਼ਾਈਲਾਂ' ),
-       'Wantedpages'               => array( 'à¨\9aਾਹà©\80ਦà©\87_ਪੰਨੇ', 'ਟੁੱਟੇ_ਜੋੜ' ),
+       'Wantedpages'               => array( 'à¨\9aਾਹà©\80ਦà©\87_ਸਫ਼ੇ', 'ਟੁੱਟੇ_ਜੋੜ' ),
        'Wantedtemplates'           => array( 'ਚਾਹੀਦੇ_ਫਰਮੇ' ),
        'Watchlist'                 => array( 'ਨਿਗਰਾਨੀ-ਲਿਸਟ' ),
-       'Whatlinkshere'             => array( 'à¨\95ਿਹà©\9cà©\87_ਪੰਨੇ_ਇੱਥੇ_ਜੋੜਦੇ_ਹਨ' ),
+       'Whatlinkshere'             => array( 'à¨\95ਿਹà©\9cà©\87_ਸਫ਼ੇ_ਇੱਥੇ_ਜੋੜਦੇ_ਹਨ' ),
        'Withoutinterwiki'          => array( 'ਬਿਨਾਂ_ਇੰਟਰਵਿਕੀਆਂ_ਵਾਲੇ' ),
 );
 
@@ -460,8 +461,6 @@ $1',
 'ok' => 'ਠੀਕ ਹੈ',
 'retrievedfrom' => '"$1" ਤੋਂ ਲਿਆ',
 'youhavenewmessages' => 'ਤੁਹਾਡੇ ਲਈ $1। ($2)',
-'newmessageslink' => 'ਨਵੇਂ ਸੁਨੇਹੇ',
-'newmessagesdifflink' => 'ਆਖ਼ਰੀ ਤਬਦੀਲੀ',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|ਇੱਕ ਵਰਤੋਂਕਾਰ|$3 ਵਰਤੋਂਕਾਰਾਂ}} ਵੱਲੋਂ ਤੁਹਾਨੂੰ $1 ($2)।',
 'youhavenewmessagesmanyusers' => 'ਕਈ ਯੂਜ਼ਰ ਵੱਲੋਂ ਤੁਹਾਨੂੰ $1 ($2)।',
 'newmessageslinkplural' => '{{PLURAL:$1|ਇੱਕ ਨਵਾਂ ਸੁਨੇਹਾ|ਨਵੇਂ ਸੁਨੇਹੇ}} {{PLURAL:$1|ਹੈ|ਹਨ}}',
@@ -516,6 +515,7 @@ $1',
 # General errors
 'error' => 'ਗ਼ਲਤੀ',
 'databaseerror' => 'ਡਾਟਾਬੇਸ ਗਲਤੀ',
+'databaseerror-error' => 'ਦੋਸ਼: $1',
 'laggedslavemode' => "'''ਖ਼ਬਰਦਾਰ:''' ਹੋ ਸਕਦਾ ਹੈ ਸਫ਼ੇ ਵਿਚ ਤਾਜ਼ਾ ਤਬਦੀਲੀਆਂ ਸ਼ਾਮਲ ਨਾ ਹੋਣ।",
 'readonly' => 'ਡਾਟਾਬੇਸ ਨੂੰ ਤਾਲ਼ਾ ਲੱਗਿਆ ਹੋਇਆ ਹੈ',
 'enterlockreason' => 'ਤਾਲਾ-ਬੰਦੀ ਲਈ ਕਾਰਨ ਦਾਖ਼ਲ ਕਰੋ, ਨਾਲ਼ ਹੀ ਤਾਲਾ-ਬੰਦੀ ਦੇ ਰਿਲੀਜ਼ ਹੋਣ ਦਾ ਅੰਦਾਜ਼ਨ ਵਕਤ',
@@ -630,9 +630,10 @@ $2',
 'gotaccount' => 'ਖਾਤਾ ਪਹਿਲਾਂ ਹੀ ਹੈ? $1',
 'gotaccountlink' => 'ਲਾਗਇਨ',
 'userlogin-resetlink' => 'ਆਪਣੀ ਲਾਗਇਨ ਜਾਣਕਾਰੀ ਭੁੱਲ ਗਏ ਹੋ?',
-'userlogin-resetpassword-link' => 'à¨\86ਪਣਾ à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨«à©\87ਰ à¨¬à¨£à¨¾à¨\93',
+'userlogin-resetpassword-link' => 'à¨\86ਪਣਾ à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨­à©\81ੱਲ à¨\97à¨\8f à¨¹à©\8b?',
 'helplogin-url' => 'Help: ਲਾਗਇਨ ਕਰਨਾ',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|ਲਾਗਇਨ ਹੋਣ ਲਈ ਮੱਦਦ]]',
+'userlogin-createanother' => 'ਹੋਰ ਖਾਤਾ ਬਣਾਓ',
 'createacct-join' => 'ਆਪਣੀ ਜਾਣਕਾਰੀ ਹੇਠਾਂ ਦਿਉ।',
 'createacct-another-join' => 'ਆਪਣੇ ਅਕਾਊਂਟ ਦੀ ਜਾਣਕਾਰੀ ਹੇਠਾਂ ਦਿਉ।',
 'createacct-emailrequired' => 'ਈਮੇਲ ਪਤਾ',
@@ -695,11 +696,11 @@ $2',
 'acct_creation_throttle_hit' => 'ਤੁਹਾਡਾ IP ਪਤਾ ਵਰਤ ਕੇ ਆਉਣ ਵਾਲ਼ਿਆਂ ਨੇ ਆਖ਼ਰੀ ਦਿਨਾਂ ਵਿਚ ਇਸ ਵਿਕੀ ’ਤੇ {{PLURAL:$1|੧ ਖਾਤਾ ਬਣਾਇਆ ਹੈ|$1 ਖਾਤੇ ਬਣਾਏ ਹਨ}} ਜੋ ਕਿ, ਹਾਲ ਦੀ ਘੜੀ, ਖਾਤੇ ਬਣਾਉਣ ਦੀ ਆਖ਼ਰੀ ਹੱਦ ਹੈ।
 ਨਤੀਜੇ ਵਜੋਂ ਇਸ IP ਪਤੇ ਨੂੰ ਵਰਤਣ ਵਾਲ਼ੇ ਫ਼ਿਲਹਾਲ ਹੋਰ ਖਾਤੇ ਨਹੀਂ ਬਣਾ ਸਕਦੇ।',
 'emailauthenticated' => 'ਤੁਹਾਡਾ ਈ-ਮੇਲ ਪਤਾ $2 ਨੂੰ $3 ’ਤੇ ਤਸਦੀਕ ਕੀਤਾ ਗਿਆ।',
-'emailnotauthenticated' => 'ਤà©\81ਹਾਡਾ à¨\88ਮà©\87ਲ à¨ªà¨¤à¨¾ à¨¹à¨¾à¨²à©\87 à¨¤à¨¸à¨\95ਦà©\80à¨\95 à¨¨à¨¹à©\80à¨\82 à¨¹à©\8bà¨\87à¨\86। à¨¹à©\87ਠ à¨¦à¨¿à©±à¨¤à©\87 à¨«à©\80à¨\9aਰਾà¨\82 à¨²à¨\88 à¨\95à©\8bà¨\88 à¨µà©\80 à¨\88ਮà©\87ਲ à¨¨à¨¹à©\80à¨\82 à¨­à©\87à¨\9cà©\80 à¨\9cਾਵà©\87à¨\97à©\80।',
+'emailnotauthenticated' => 'ਤੁਹਾਡਾ ਈਮੇਲ ਪਤਾ ਹਾਲੇ ਤਸਦੀਕ ਨਹੀਂ ਹੋਇਆ। ਹੇਠ ਦਿੱਤੇ ਫੀਚਰਾਂ ਲਈ ਕੋਈ ਵੀ ਈਮੇਲ ਨਹੀਂ ਭੇਜੀ ਜਾਵੇਗੀ।',
 'noemailprefs' => 'ਇਹਨਾਂ ਸਹੂਲਤਾਂ ਦੀ ਵਰਤੋਂ ਲਈ ਆਪਣੀਆਂ ਪਸੰਦਾਂ ਵਿਚ ਇਕ ਈ-ਮੇਲ ਪਤਾ ਦਿਓ।',
 'emailconfirmlink' => 'ਆਪਣਾ ਈਮੇਲ ਪਤਾ ਤਸਦੀਕ ਕਰਾਓ',
-'invalidemailaddress' => 'ਈ-ਮੇਲ ਪਤਾ ਕਬੂਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਕਿਉਂਕਿ ਇਹ ਸਹੀ ਅੰਦਾਜ਼ ਵਿਚ ਲਿਖਿਆ ਨਹੀਂ ਜਾਪਦਾ ਹੈ।
-ਸਹà©\80 à¨\85ੰਦਾà¨\9c਼ à¨µà¨¿à¨\9a à¨¦à¨¿à¨\93 ਜਾਂ ਇਹ ਖ਼ਾਨਾ ਖ਼ਾਲੀ ਛੱਡ ਦਿਓ।',
+'invalidemailaddress' => 'ਈਮੇਲ ਪਤਾ ਕਬੂਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਕਿਉਂਕਿ ਇਹ ਸਹੀ ਅੰਦਾਜ਼ ਵਿਚ ਲਿਖਿਆ ਨਹੀਂ ਜਾਪਦਾ ਹੈ।
+ਸਹà©\80 à¨\85ੰਦਾà¨\9c਼ à¨µà¨¿à¨\9a à¨²à¨¿à¨\96à©\8b ਜਾਂ ਇਹ ਖ਼ਾਨਾ ਖ਼ਾਲੀ ਛੱਡ ਦਿਓ।',
 'cannotchangeemail' => 'ਇਸ ਵਿਕੀ ਤੇ ਈ-ਮੇਲ ਪਤੇ ਬਦਲੇ ਨਹੀਂ ਜਾ ਸਕਦੇ।',
 'emaildisabled' => 'ਇਹ ਸਾਈਟ ਈ-ਮੇਲਾਂ ਨਹੀਂ ਭੇਜ ਸਕਦੀ।',
 'accountcreated' => 'ਖਾਤਾ ਬਣਾਇਆ',
@@ -711,10 +712,12 @@ $2',
 ਜੇ ਇਹ ਖਾਤਾ ਗ਼ਲਤੀ ਨਾਲ਼ ਬਣ ਗਿਆ ਹੈ ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੁਨੇਹੇ ਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰ ਸਕਦੇ ਹੋ।',
 'usernamehasherror' => 'ਵਰਤੋਂਕਾਰ ਦੇ ਨਾਂ ਵਿਚ ਹੈਸ਼ ਅੱਖਰ ਨਹੀਂ ਹੋ ਸਕਦੇ',
 'login-throttled' => 'ਤੁਸੀਂ ਬਹੁਤ ਸਾਰੀਆਂ ਤਾਜ਼ਾ ਲਾਗਇਨ ਕੋਸ਼ਿਸ਼ਾਂ ਕੀਤੀਆਂ ਹਨ।
-ਫà©\87ਰ à¨\95à©\8bਸ਼ਿਸ਼ à¨\95ਰਨ à¨¤à©\8bà¨\82 à¨ªà¨¹à¨¿à¨²à¨¾à¨\82 à¨¥à©\8bà©\9cà©\8dਹà©\80 ਉਡੀਕ ਕਰੋ ਜੀ।',
+ਮà©\81à©\9c à¨\95à©\8bਸ਼ਿਸ਼ à¨\95ਰਨ à¨¤à©\8bà¨\82 à¨ªà¨¹à¨¿à¨²à¨¾à¨\82 $1 ਉਡੀਕ ਕਰੋ ਜੀ।',
 'login-abort-generic' => 'ਤੁਹਾਡਾ ਦਾਖ਼ਲਾ ਨਾਕਾਮ ਸੀ - ਅਧੂਰਾ ਛੱਡਿਆ',
 'loginlanguagelabel' => 'ਭਾਸ਼ਾ: $1',
 'suspicious-userlogout' => 'ਤੁਹਾਡੀ ਵਿਦਾਇਗੀ ਦੀ ਬੇਨਤੀ ਨਕਾਰ ਦਿੱਤੀ ਗਈ ਕਿਉਂਕਿ ਲੱਗਦਾ ਹੈ ਕਿ ਇਹ ਕਿਸੇ ਟੁੱਟੇ ਹੋਏ ਬਰਾਊਜ਼ਰ ਜਾਂ ਕੈਸ਼ ਹੋਈ ਪ੍ਰਾਕਸੀ ਤੋਂ ਭੇਜੀ ਗਈ ਸੀ।',
+'createacct-another-realname-tip' => 'ਅਸਲੀ ਨਾਂ ਚੋਣਵਾਂ ਹੈ।
+ਜੇਕਰ ਤੁਸੀਂ ਇਹ ਦਿੱਤਾ ਹੈ ਤਾਂ ਤੁਹਾਡੇ ਕੰਮ ਵਾਸਤੇ ਗੁਣ ਦੇ ਤੌਰ ਉੱਤੇ ਵਰਤਿਆ ਜਾਵੇਗਾ।',
 
 # Email sending
 'php-mail-error-unknown' => 'PHP ਦੇ ਮੇਲ() ਕਰਜ ਵਿੱਚ ਅਣਜਾਣ ਦੋਸ਼',
@@ -779,6 +782,9 @@ $2
 
 # Special:ResetTokens
 'resettokens' => 'ਟੋਕਨ ਮੁੜ-ਸੈੱਟ ਕਰੋ',
+'resettokens-tokens' => 'ਟੋਕਨ:',
+'resettokens-token-label' => '$1 (ਚਾਲੂ ਮੁੱਲ: $2)',
+'resettokens-resetbutton' => 'ਚੁਣੇ ਹੋਏ ਟੋਕਨ ਮੁੜ ਸੈੱਟ ਕਰੋ',
 
 # Edit page toolbar
 'bold_sample' => 'ਗੂੜੀ ਲਿਖਤ',
@@ -941,7 +947,7 @@ $1 ਲੁਕਵੀਆਂ ਸ਼੍ਰੇਣੀਆਂ}} ਦਾ ਮੈਂਬਰ 
 'post-expand-template-inclusion-category' => 'ਉਹ ਸਫ਼ੇ ਜਿੱਥੇ ਫਰਮੇ ਸ਼ਾਮਲ ਕਰਨ ਦਾ ਅਕਾਰ ਹੱਦੋਂ ਵੱਧ ਗਿਆ ਹੈ',
 'post-expand-template-argument-warning' => "'''ਚੇਤਾਵਨੀ:'''
 ਇਸ ਪੰਨੇ ਤੇ ਘੱਟੋ ਘੱਟ ਇੱਕ ਐਸੀ ਸਾਂਚਾ ਬਹਿਸ ਹੈ ਜਿਸ ਦਾ ਅਕਾਰ ਬਹੁਤ ਵੱਡਾ ਹੈ। ਅਜਿਹੀਆਂ ਬਹਿਸਾਂ ਨੂੰ ਛੱਡ ਦਿੱਤਾ ਗਿਆ ਹੈ।",
-'post-expand-template-argument-category' => 'à¨\90ਸà©\87 à¨ªà©°à¨¨à©\87 à¨\9cਿਨà©\8dਹਾà¨\82 à¨µà¨¿à©±à¨\9a à¨¸à¨¾à¨\82à¨\9aà©\87 à¨¦à©\87 à¨¸à¨\81à¨\98à¨\9fà¨\95 à¨\9bà©\81ੱà¨\9f à¨\97à¨\8f à¨¹à¨¨ ।',
+'post-expand-template-argument-category' => 'à¨\90ਸà©\87 à¨¸à¨«à¨¼à©\87 à¨\9cਿਨà©\8dਹਾà¨\82 à¨µà¨¿à©±à¨\9a à¨«à¨°à¨®à©\87 à¨¦à©\87 à¨\86ਰà¨\97à©\82ਮà©\88à¨\82à¨\9f à¨\9bà©\81ੱà¨\9f à¨\97à¨\8f à¨¹à¨¨।',
 'parser-template-loop-warning' => 'ਫਰਮੇ ਦਾ ਲੂਪ ਲੱਭਿਆ: [[$1]]',
 
 # "Undo" feature
@@ -1026,19 +1032,22 @@ page={{FULLPAGENAMEE}}}} ਜ਼ਬਤੀ ਦੇ ਚਿੱਠੇ] ਵਿਚ ਵ
 'revdelete-show-file-submit' => 'ਹਾਂ',
 'revdelete-selected' => "'''[[:$1]] {{PLURAL:$2|ਦੀ ਚੁਣੀ ਹੋਈ ਰੀਵਿਜ਼ਨ|ਦੀਆਂ ਚੁਣੀਆਂ ਹੋਈਆਂ ਰੀਵਿਜ਼ਨਾਂ}}:'''",
 'revdelete-legend' => 'ਵੇਖਣ ਪਾਬੰਦੀਆਂ ਸੈੱਟ ਕਰੋ:',
-'revdelete-hide-text' => 'ਰà©\80ਵਿà¨\9c਼ਨ à¨²à¨¿à¨\96ਤ à¨\93ਹਲà©\87',
+'revdelete-hide-text' => 'ਦà©\81ਹਰਾà¨\88 à¨²à¨¿à¨\96ਤ',
 'revdelete-hide-image' => 'ਫ਼ਾਈਲ ਸਮੱਗਰੀ ਓਹਲੇ',
 'revdelete-hide-name' => 'ਕਾਰਵਾਈ ਅਤੇ ਟਾਰਗੇਟ ਓਹਲੇ',
-'revdelete-hide-comment' => 'ਸੋਧ ਸਾਰ ਲੁਕਾਓ',
-'revdelete-hide-user' => 'ਸà©\8bਧਣ à¨µà¨¾à¨²à¨¼à©\87 à¨¦à¨¾ à¨®à©\88à¨\82ਬਰ-ਨਾà¨\82/IP à¨ªà¨¤à¨¾ à¨²à©\81à¨\95ਾà¨\93',
+'revdelete-hide-comment' => 'ਸੋਧ ਸਾਰ',
+'revdelete-hide-user' => 'ਸà©\8bਧਣ à¨µà¨¾à¨²à¨¼à©\87 à¨¦à¨¾ à¨µà¨°à¨¤à©\8bà¨\82à¨\95ਾਰà©\80 à¨¨à¨¾à¨\82/IP à¨ªà¨¤à¨¾',
 'revdelete-hide-restricted' => 'ਪ੍ਰਸ਼ਾਸਕਾਂ ਅਤੇ ਹੋਰਾਂ ਦੀ ਸਮੱਗਰੀ ਲੁਕਾਓ',
 'revdelete-radio-same' => '(ਨਾ ਬਦਲੋ)',
-'revdelete-radio-set' => 'ਹਾਂ',
-'revdelete-radio-unset' => 'ਨਹà©\80à¨\82',
+'revdelete-radio-set' => 'ਲà©\81à¨\95ਵਾਂ',
+'revdelete-radio-unset' => 'ਪਰà¨\97à¨\9f',
 'revdelete-suppress' => 'ਪ੍ਰਸ਼ਾਸਕਾਂ ਅਤੇ ਹੋਰਾਂ ਦੀ ਸਮੱਗਰੀ ਲੁਕਾਓ',
 'revdelete-unsuppress' => 'ਮੁੜ ਬਹਾਲ ਕੀਤੀਆਂ ਰੀਵਿਜ਼ਨਾਂ ਤੋਂ ਰੋਕਾਂ ਹਟਾਓ',
 'revdelete-log' => 'ਕਾਰਨ:',
 'revdelete-submit' => 'ਚੁਣੇ ਹੋਏ {{PLURAL:$1|ਸੁਧਾਰ|ਸੁਧਾਰਾਂ}} ਉੱਤੇ ਲਾਗੂ ਕਰੋ',
+'revdelete-success' => "'''ਦੁਹਰਾਈ ਦੀ ਪ੍ਰਤੱਖਤਾ ਅੱਪਡੇਟ ਕਰਨੀ ਸਫ਼ਲ ਹੋਈ।'''",
+'revdelete-failure' => "'''ਦੁਹਰਾਈ ਦੀ ਪ੍ਰਤੱਖਤਾ ਅੱਪਡੇਟ ਨਾ ਹੋ ਸਕੀ:'''
+$1",
 'logdelete-success' => "'''ਚਿੱਠੇ ਦੀ ਦਿੱਖ ਕਾਮਯਾਬੀ ਨਾਲ਼ ਸੈੱਟ ਕੀਤੀ।'''",
 'logdelete-failure' => "'''ਚਿੱਠੇ ਦੀ ਦਿੱਖ ਸੈੱਟ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ:''' $1",
 'revdel-restore' => 'ਦਿੱਖ ਬਦਲੋ',
@@ -1046,7 +1055,7 @@ page={{FULLPAGENAMEE}}}} ਜ਼ਬਤੀ ਦੇ ਚਿੱਠੇ] ਵਿਚ ਵ
 'revdel-restore-visible' => 'ਦਿਸਣਯੋਗ ਰੀਵੀਜਨ',
 'pagehist' => 'ਸਫ਼ਾ ਅਤੀਤ',
 'deletedhist' => 'ਹਟਾਇਆ ਗਿਆ ਅਤੀਤ',
-'revdelete-hide-current' => 'ਤਾਰੀਖ &2, $1 ਦੀ ਚੀਜ਼ ਲੁਕਾਉਣ ਵਿਚ ਗਲਤੀ: ਇਹ ਮੌਜੂਦਾ ਰੀਵਿਜ਼ਨ ਹੈ।
+'revdelete-hide-current' => 'ਤਾਰੀਖ $2, $1 ਦੀ ਚੀਜ਼ ਲੁਕਾਉਣ ਵਿਚ ਗ਼ਲਤੀ: ਇਹ ਮੌਜੂਦਾ ਦੁਹਰਾਈ ਹੈ।
 ਇਹ ਲੁਕਾਈ ਨਹੀਂ ਜਾ ਸਕਦੀ।',
 'revdelete-otherreason' => 'ਹੋਰ/ਵਾਧੂ ਕਾਰਨ:',
 'revdelete-reasonotherlist' => 'ਹੋਰ ਕਾਰਨ',
@@ -1089,6 +1098,7 @@ page={{FULLPAGENAMEE}}}} ਜ਼ਬਤੀ ਦੇ ਚਿੱਠੇ] ਵਿਚ ਵ
 'compareselectedversions' => 'ਚੁਣੇ ਵਰਜਨਾਂ ਦੀ ਤੁਲਨਾ',
 'showhideselectedversions' => 'ਚੁਣੇ ਰੀਵਿਜ਼ਨ ਵਖਾਓ/ਲੁਕਾਓ',
 'editundo' => 'ਰੱਦ ਕਰੋ',
+'diff-empty' => '(ਕੋਈ ਫ਼ਰਕ ਨਹੀਂ)',
 'diff-multi' => '({{PLURAL:$2|ਵਰਤੋਂਕਾਰ ਦੀ|$2 ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ}} {{PLURAL:$1|ਵਿਚਕਾਰਲੀ ਰੀਵਿਜਨ ਨਹੀਂ ਦਿਖਾਈ ਜਾ ਰਹੀ|ਵਿਚਕਾਰਲੀਆਂ $1 ਰੀਵਿਜਨਾਂ ਨਹੀਂ ਦਿਖਾਈਆਂ ਜਾ ਰਹੀਆਂ}})',
 
 # Search results
@@ -1097,6 +1107,7 @@ page={{FULLPAGENAMEE}}}} ਜ਼ਬਤੀ ਦੇ ਚਿੱਠੇ] ਵਿਚ ਵ
 'searchresulttext' => '{{SITENAME}} ਖੋਜ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ ਲਵੋ, ਵੇਖੋ [[{{MediaWiki:Helppage}}|{{int:help}}]].',
 'searchsubtitle' => 'ਤੁਸੀਂ \'\'\'[[:$1]]\'\'\' ਲਈ ਖੋਜ ਕੀਤੀ ([[Special:Prefixindex/$1|"$1" ਨਾਲ ਸ਼ੁਰੂ ਹੁੰਦੇ ਸਭ ਸਫ਼ੇ]]{{int:pipe-separator}}[[Special:WhatLinksHere/$1|"$1" ਨਾਲ ਲਿੰਕ ਹੋਏ ਸਭ ਸਫ਼ੇ]])',
 'searchsubtitleinvalid' => "ਤੁਸੀਂ'''$1''' ਲਈ ਖੋਜ ਕੀਤੀ।",
+'toomanymatches' => 'ਬਾਹਲੇ ਮੇਲ ਮਿਲੇ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਕੋਈ ਹੋਰ ਪੁੱਛ-ਗਿੱਛ ਵਰਤੋ',
 'titlematches' => 'ਆਰਟੀਕਲ ਟੈਕਸਟ ਮਿਲਦਾ',
 'notitlematches' => 'ਕੋਈ ਪੇਜ ਟਾਇਟਲ ਨਹੀਂ ਮਿਲਦਾ',
 'textmatches' => 'ਸਫ਼ੇ ਦੀ ਲਿਖਤ ਮੇਲ ਖਾਂਦੀ ਹੈ',
@@ -1156,8 +1167,6 @@ $3|'''1''' ਨਤੀਜਾ|'''$3''' ਨਤੀਜੇ}} ਵਖਾਓ।",
 'preferences' => 'ਪਸੰਦਾਂ',
 'mypreferences' => 'ਪਸੰਦਾਂ',
 'prefs-edits' => 'ਸੋਧਾਂ ਦੀ ਗਿਣਤੀ:',
-'prefsnologin' => 'ਦਾਖ਼ਲ ਨਹੀਂ ਹੋ',
-'prefsnologintext' => 'ਵਰਤੋਂਕਾਰ ਪਸੰਦਾਂ ਸੈੱਟ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ਲਾਗਇਨ]</span> ਕਰਨਾ ਪਵੇਗਾ।',
 'changepassword' => 'ਪਾਸਵਰਡ ਬਦਲੋ',
 'prefs-skin' => 'ਸਕਿਨ',
 'skin-preview' => 'ਝਲਕ',
@@ -1234,13 +1243,13 @@ $3|'''1''' ਨਤੀਜਾ|'''$3''' ਨਤੀਜੇ}} ਵਖਾਓ।",
 'badsig' => 'ਗ਼ਲਤ ਕੱਚੇ ਦਸਤਖ਼ਤ।
 HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'badsiglength' => 'ਦਸਤਖ਼ਤ ਬਹੁਤ ਲੰਬਾ ਹੋ ਗਿਆ ਹੈ। ਇਹ {{PLURAL:$1|ਅੱਖਰ|ਅੱਖਰਾਂ}} ਤੋਂ ਲੰਬਾ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ।',
-'yourgender' => 'ਲਿੰà¨\97:',
+'yourgender' => 'ਤà©\81ਸà©\80à¨\82 à¨\86ਪਣਾ à¨µà¨°à¨£à¨¨ à¨\95ਿਵà©\87à¨\82 à¨\95ਰਨਾ à¨ªà¨¸à©°à¨¦ à¨\95ਰà©\8bà¨\97à©\87?',
 'gender-unknown' => 'ਮੈਂ ਦੱਸਣਾ ਨਹੀਂ ਚਾਹੁੰਦਾ/ਚਾਹੁੰਦੀ',
 'gender-male' => 'ਉਹ ਵਿਕੀ ਸਫ਼ੇ ਸੋਧਦਾ ਹੈ',
 'gender-female' => 'ਉਹ ਵਿਕੀ ਸਫ਼ੇ ਸੋਧਦੀ ਹੈ',
 'email' => 'ਈਮੇਲ',
 'prefs-help-realname' => 'ਅਸਲੀ ਨਾਂ ਚੋਣਵਾਂ ਹੈ, ਅਤੇ ਜੇ ਤੁਸੀਂ ਇਹ ਦਿੱਤਾ ਹੈ ਤਾਂ ਤੁਹਾਡੇ ਕੰਮ ਵਾਸਤੇ ਗੁਣ ਦੇ ਤੌਰ ਉੱਤੇ ਵਰਤਿਆ ਜਾਵੇਗਾ।',
-'prefs-help-email' => 'ਤà©\81ਹਾਡà©\80 à¨®à¨°à¨\9cà©\80 à¨¹à©\88 à¨\88ਮà©\87ਲ à¨ªà¨¤à¨¾ à¨¦à¨¿à¨\93 à¨\9cਾà¨\82 à¨¨à¨¾ à¨¦à¨¿à¨\93 à¨ªà¨° à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨­à©\81ੱਲ à¨\9cਾਣ à¨¤à©\87 à¨¨à¨µà¨¾à¨\82 à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨¹à¨¾à¨¸à¨² à¨\95ਰਨ à¨²à¨\88 à¨\87ਹ à¨\9cਰੂਰੀ ਹੈ।',
+'prefs-help-email' => 'à¨\88ਮà©\87ਲ à¨ªà¨¤à¨¾ à¨¦à©\87ਣਾ à¨¤à©\81ਹਾਡà©\80 à¨®à¨°à¨\9c਼à©\80 à¨¹à©\88, à¨¦à¨¿à¨\93 à¨\9cਾà¨\82 à¨¨à¨¾ à¨¦à¨¿à¨\93 à¨ªà¨° à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨­à©\81ੱਲ à¨\9cਾਣ à¨¤à©\87 à¨¨à¨µà¨¾à¨\82 à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨¹à¨¾à¨¸à¨² à¨\95ਰਨ à¨²à¨\88 à¨\87ਹ à¨\9c਼ਰੂਰੀ ਹੈ।',
 'prefs-help-email-others' => 'ਤੁਸੀਂ ਇਹ ਵੀ ਚੁਣ ਸਕਦੇ ਹੋ ਕਿ ਤੁਹਾਡੇ ਵਰਤੋਂਕਾਰ ਜਾਂ ਚਰਚਾ ਪੰਨੇ ਤੋਂ ਹੋਰ ਵਰਤੋਂਕਾਰ ਤੁਹਾਨੂੰ ਈ-ਮੇਲ ਭੇਜ ਸਕਣ?
 ਜਦੋਂ ਹੋਰ ਵਰਤੋਂਕਾਰ ਤੁਹਾਨੂੰ ਈ-ਮੇਲ ਭੇਜਦੇ ਹਨ ਤਾਂ ਤੁਹਾਡਾ ਈ-ਮੇਲ ਪਤਾ ਜ਼ਾਹਰ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ।',
 'prefs-help-email-required' => 'ਈ-ਮੇਲ ਪਤਾ ਚਾਹੀਦਾ ਹੈ।',
@@ -1259,7 +1268,9 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'prefs-displayrc' => 'ਵੇਖਾਉਣ ਚੋਣਾਂ',
 'prefs-displaysearchoptions' => 'ਵੇਖਾਉਣ ਚੋਣਾਂ',
 'prefs-displaywatchlist' => 'ਵੇਖਾਉਣ ਚੋਣਾਂ',
+'prefs-tokenwatchlist' => 'ਟੋਕਨ',
 'prefs-diffs' => 'ਫ਼ਰਕ',
+'prefs-help-prefershttps' => 'ਇਹ ਪਸੰਦ ਤੁਹਾਡੇ ਅਗਲੇ ਦਾਖ਼ਲੇ ਤੋਂ ਚਾਲੂ ਹੋ ਜਾਵੇਗੀ।',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'ਈ-ਮੇਲ ਪਤਾ ਸਹੀ ਲਗਦਾ ਹੈ',
@@ -1296,6 +1307,7 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'group-bot-member' => 'ਬੌਟ',
 
 'grouppage-user' => '{{ns:project}}:ਵਰਤੋਂਕਾਰ',
+'grouppage-autoconfirmed' => '{{ns:project}}:ਸਵੈ-ਤਸਦੀਕੀ ਵਰਤੋਂਕਾਰ',
 'grouppage-bot' => '{{ns:project}}:ਬੌਟ',
 'grouppage-sysop' => '{{ns:project}}:ਪ੍ਰਸ਼ਾਸਕ',
 'grouppage-bureaucrat' => '{{ns:project}}:ਅਫ਼ਸਰ',
@@ -1386,6 +1398,8 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|ਤਬਦੀਲੀ|ਤਬਦੀਲੀਆਂ}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|ਆਖ਼ਰੀ ਫੇਰੀ ਤੋਂ ਲੈ ਕੇ}}',
+'enhancedrc-history' => 'ਅਤੀਤ',
 'recentchanges' => 'ਹਾਲ ’ਚ ਹੋਈਆਂ ਤਬਦੀਲੀਆਂ',
 'recentchanges-legend' => 'ਹਾਲ ਦੀਆਂ ਤਬਦੀਲੀਆਂ ਸਬੰਧੀ ਚੋਣਾਂ',
 'recentchanges-summary' => 'ਇਸ ਵਿਕੀ ’ਤੇ ਹੋਈਆਂ ਸਭ ਤੋਂ ਨਵੀਆਂ ਤਬਦੀਲੀਆਂ ਇਸ ਸਫ਼ੇ ’ਤੇ ਵੇਖੋ।',
@@ -1394,6 +1408,8 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'recentchanges-label-minor' => 'ਇਹ ਇੱਕ ਛੋਟੀ ਸੋਧ ਹੈ',
 'recentchanges-label-bot' => 'ਇਹ ਸੋਧ ਇੱਕ ਬੋਟ ਦੁਆਰਾ ਕੀਤੀ ਗਈ ਸੀ',
 'recentchanges-label-unpatrolled' => 'ਇਹ ਫੇਰ-ਬਦਲ ਹਾਲੇ ਵੇਖਿਆ ਨਹੀਂ ਗਿਆ',
+'recentchanges-legend-newpage' => '$1 - ਨਵਾਂ ਸਫ਼ਾ',
+'recentchanges-legend-plusminus' => "(''±੧੨੩'')",
 'rcnote' => "$4, $5 ਤੱਕ ਆਖਰੀ {{PLURAL:$2|ਦਿਨ|'''$2''' ਦਿਨਾਂ}} ਵਿੱਚ {{PLURAL:$1|'''1''' ਬਦਲੀ ਹੋਈ ਹੈ।|'''$1''' ਬਦਲੀਆਂ ਹੋਈਆਂ ਹਨ।}}",
 'rcnotefrom' => "'''$2''' ਤੱਕ ('''$1''' ਤੱਕ ਦਿੱਸਦੇ) ਬਦਲਾਵ ਹੇਠ ਦਿੱਤੀਆਂ ਹਨ।",
 'rclistfrom' => '$1 ਤੋਂ ਸ਼ੁਰੂ ਕਰਕੇ ਨਵੀਆਂ ਸੋਧਾਂ ਵਖਾਓ',
@@ -1513,6 +1529,7 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'uploadstash-refresh' => 'ਫ਼ਾਈਲਾਂ ਦੀ ਲਿਸਟ ਨੂੰ ਤਾਜ਼ਾ ਕਰੋ',
 
 # img_auth script messages
+'img-auth-accessdenied' => 'ਪਹੁੰਚ ਨਕਾਰੀ ਗਈ',
 'img-auth-nofile' => 'ਫ਼ਾਈਲ "$1" ਮੌਜੂਦ ਨਹੀਂ ਹੈ।',
 
 # Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
@@ -1538,6 +1555,8 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'listfiles_size' => 'ਆਕਾਰ',
 'listfiles_description' => 'ਵੇਰਵਾ',
 'listfiles_count' => 'ਵਰਜਨ',
+'listfiles-latestversion-yes' => 'ਹਾਂ',
+'listfiles-latestversion-no' => 'ਨਹੀਂ',
 
 # File description page
 'file-anchor-link' => 'ਫ਼ਾਈਲ',
@@ -1616,6 +1635,12 @@ HTML ਟੈਗ ਚੈੱਕ ਕਰੋ।',
 'randompage' => 'ਰਲ਼ਵਾਂ ਸਫ਼ਾ',
 'randompage-nopages' => '{{PLURAL:$2|ਇਸ ਥਾਂ-ਨਾਮ|ਇਹਨਾਂ ਥਾਂ-ਨਾਂਵਾ}} ਵਿਚ ਕੋਈ ਸਫ਼ਾ ਨਹੀਂ ਹੈ: $1।',
 
+# Random page in category
+'randomincategory' => 'ਸ਼੍ਰੇਣੀ ਵਿਚਲਾ ਰਲ਼ਵਾਂ ਸਫ਼ਾ',
+'randomincategory-invalidcategory' => '"$1" ਕੋਈ ਸਹੀ ਸ਼੍ਰੇਣੀ ਦਾ ਨਾਂ ਨਹੀਂ ਹੈ।',
+'randomincategory-nopages' => '[[:Category:$1|$1]] ਸ਼੍ਰੇਣੀ ਵਿਚ ਕੋਈ ਸਫ਼ਾ ਨਹੀਂ ਹੈ।',
+'randomincategory-selectcategory-submit' => 'ਜਾਓ',
+
 # Random redirect
 'randomredirect' => 'ਰਲ਼ਵਾਂ ਰੀਡਿਰੈਕਟ',
 
@@ -2290,7 +2315,7 @@ $1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆ
 'file-info-size' => '$1 × $2 ਪਿਕਸਲ, ਫ਼ਾਈਲ ਅਕਾਰ: $3, MIME ਕਿਸਮ: $4',
 'file-nohires' => 'ਇਸ ਤੋਂ ਵੱਡੀ ਤਸਵੀਰ ਮੌਜੂਦ ਨਹੀਂ ਹੈ।',
 'svg-long-desc' => 'SVG ਫ਼ਾਈਲ, ਆਮ ਤੌਰ ’ਤੇ $1 × $2 ਪਿਕਸਲ, ਫ਼ਾਈਲ ਦਾ ਅਕਾਰ: $3',
-'show-big-image' => 'ਪà©\82ਰਾ à¨°à©\88à¨\9cà©\8bਲà©\87ਸ਼ਨ',
+'show-big-image' => 'à¨\85ਸਲ à¨«à¨¾à¨\88ਲ',
 
 # Special:NewFiles
 'newimages' => 'ਨਵੀਆਂ ਫ਼ਾਈਲਾਂ ਦੀ ਗੈਲਰੀ',
@@ -2547,7 +2572,7 @@ $1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆ
 
 # External editor support
 'edit-externally' => 'ਬਾਹਰੀ ਐਪਲੀਕੇਸ਼ਨ ਵਰਤ ਕੇ ਇਸ ਫ਼ਾਈਲ ਨੂੰ ਸੋਧੋ',
-'edit-externally-help' => '(ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] ਵੇਖੋ)',
+'edit-externally-help' => '(ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] ਵੇਖੋ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ਸਭ',
@@ -2560,6 +2585,8 @@ $1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆ
 'confirmemail_send' => 'ਇੱਕ ਤਸਦੀਕੀ ਕੋਡ ਭੇਜੋ',
 'confirmemail_sent' => 'ਤਸਦੀਕੀ ਈਮੇਲ ਭੇਜੀ ਗਈ।',
 'confirmemail_invalid' => 'ਗਲਤ ਪੁਸ਼ਟੀ ਕੋਡ ਹੈ। ਕੋਡ ਦੀ ਮਿਆਦ ਪੁੱਗੀ ਹੋ ਸਕਦੀ ਹੈ।',
+'confirmemail_success' => 'ਤੁਹਾਡਾ ਈਮੇਲ ਪਤਾ ਤਸਦੀਕ ਹੋ ਚੁੱਕਾ ਹੈ।
+ਤੁਸੀਂ ਹੁਣ [[Special:UserLogin|ਲਾਗਇਨ]] ਕਰ ਕੇ ਵਿਕੀ ਦਾ ਮਜ਼ਾ ਸਕਦੇ ਹੋ।',
 'confirmemail_loggedin' => 'ਤੁਹਾਡਾ ਈ-ਮੇਲ ਪਤਾ ਹੁਣ ਤਸਦੀਕ ਹੋ ਚੁੱਕਾ ਹੈ।',
 'confirmemail_subject' => '{{SITENAME}} ਈ-ਮੇਲ ਪਤਾ ਤਸਦੀਕ',
 'confirmemail_invalidated' => 'ਈਮੇਲ ਪਤੇ ਦੀ ਤਸਦੀਕੀ ਰੱਦ ਕੀਤੀ ਗਈ',
@@ -2611,17 +2638,21 @@ $1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆ
 ਸਧਾਰਨ ਝਲਕ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।',
 
 # Watchlist editor
-'watchlistedit-noitems' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚ ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ ਹਨ।',
+'watchlistedit-numitems' => 'ਗੱਲ-ਬਾਤ ਸਫ਼ਿਆਂ ਤੋਂ ਬਿਨਾਂ, ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚ {{PLURAL:$1|1 ਸਿਰਲੇਖ ਹੈ|$1 ਸਿਰਲੇਖ ਹਨ}}।',
+'watchlistedit-noitems' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚ ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ ਹਨ।',
 'watchlistedit-normal-title' => 'ਨਿਗਰਾਨੀ-ਲਿਸਟ ਸੋਧੋ',
-'watchlistedit-normal-legend' => 'ਨਿà¨\97ਰਾਨà©\80-ਲਿਸà¨\9f à¨¤à©\8bà¨\82 à¨¸à¨¿à¨°à¨²à©\87à¨\96 ਹਟਾਓ',
+'watchlistedit-normal-legend' => 'ਸਿਰਲà©\87à¨\96ਾà¨\82 à¨¨à©\82à©° à¨¨à¨¿à¨\97ਰਾਨà©\80-ਲਿਸà¨\9f à¨µà¨¿à©±à¨\9aà©\8bà¨\82 ਹਟਾਓ',
 'watchlistedit-normal-submit' => 'ਸਿਰਲੇਖ ਹਟਾਓ',
+'watchlistedit-normal-done' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚੋਂ {{PLURAL:$1|1 ਸਿਰਲੇਖ ਹਟਾਇਆ ਗਿਆ|$1 ਸਿਰਲੇਖ ਹਟਾਏ ਗਏ}}:',
 'watchlistedit-raw-title' => 'ਕੱਚੀ ਨਿਗਰਾਨ-ਸੂਚੀ ਸੋਧੋ',
-'watchlistedit-raw-legend' => 'ਕੱਚੀ ਨਿਗਰਾਨ-ਸੂਚੀ ਸੋਧੋ',
+'watchlistedit-raw-legend' => 'ਕੱਚੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਸੋਧੋ',
+'watchlistedit-raw-explain' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿੱਚ ਮੌਜੂਦ ਸਫ਼ੇ ਹਟਾਏ ਜਾਂ ਹੋਰ ਜੋੜੇ ਜਾ ਸਕਦੇ ਹਨ। ਹਟਾਉਣ ਜਾਂ ਜੋੜਨ ਤੋਂ ਬਾਅਦ "{{int:Watchlistedit-raw-submit}}" ’ਤੇ ਕਲਿੱਕ ਕਰੋ।
+ਤੁਸੀਂ [[Special:EditWatchlist|ਮਿਆਰੀ ਐਡੀਟਰ]] ਵੀ ਵਰਤ ਸਕਦੇ ਹੋ।',
 'watchlistedit-raw-titles' => 'ਸਿਰਲੇਖ:',
 'watchlistedit-raw-submit' => 'ਨਿਗਰਾਨੀ-ਲਿਸਟ ਤਾਜ਼ੀ ਕਰੋ',
-'watchlistedit-raw-done' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨ-ਸੂਚੀ ਅੱਪਡੇਟ ਹੋ ਗਈ ਹੈ।',
-'watchlistedit-raw-added' => '{{PLURAL:$1|1 title was|$1 titles were}} ਸ਼ਾਮਲ:',
-'watchlistedit-raw-removed' => '{{PLURAL:$1|1 title was|$1 titles were}} ਹਟਾਓ:',
+'watchlistedit-raw-done' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਅੱਪਡੇਟ ਹੋ ਗਈ ਹੈ।',
+'watchlistedit-raw-added' => '{{PLURAL:$1|1 ਸਿਰਲੇਖ ਸ਼ਾਮਲ ਕੀਤਾ|$1 ਸਿਰਲੇਖ ਸ਼ਾਮਲ ਕੀਤੇ}}:',
+'watchlistedit-raw-removed' => '{{PLURAL:$1|1 ਸਿਰਲੇਖ ਹਟਾਇਆ|$1 ਸਿਰਲੇਖ ਹਟਾਏ}}:',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'ਸਬੰਧਤ ਤਬਦੀਲੀਆਂ ਵੇਖੋ',
@@ -2802,4 +2833,7 @@ $1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆ
 # Image rotation
 'rotate-comment' => 'ਤਸਵੀਰ ਨੂੰ ਘੜੀ ਦੇ ਰੁਖ ਵਿਚ $1 {{PLURAL:$1|ਡਿਗਰੀ|ਡਿਗਰੀਆਂ}} ਨਾਲ਼ ਘੁਮਾਇਆ ਗਿਆ',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'ਝਲਕ',
+
 );
index 0788b05..65685c7 100644 (file)
@@ -250,8 +250,6 @@ Pabusten ing pamanaliling dake kapamilatan [alilan] ning suglung',
 'ok' => 'Sigi',
 'retrievedfrom' => 'Mekua ya king "$1"',
 'youhavenewmessages' => 'Atin kang $1 ($2).',
-'newmessageslink' => 'bayung mensahi',
-'newmessagesdifflink' => 'tauling miyalilan',
 'youhavenewmessagesmulti' => 'Atin kang bayung mensahi king $1',
 'editsection' => 'mag-edit',
 'editold' => 'alilan',
@@ -785,8 +783,6 @@ Pakitandanan mung maliaring e no makapanaun deng karelang index king kalamnan ni
 'preferences' => 'Pinili',
 'mypreferences' => '↓Deng pinili ku',
 'prefs-edits' => 'Bilang da reng edit:',
-'prefsnologin' => 'ekamaka log',
-'prefsnologintext' => 'Kailangan kang [[Special:UserLogin|maka-login]] ba mong apagana deng pinili ning talagamit (user preferences).',
 'changepassword' => 'Alilan ya ing password',
 'prefs-skin' => 'Balat',
 'skin-preview' => 'I-preview',
@@ -2175,7 +2171,7 @@ Detang aliwa tambing (by default) lang makasalikut.
 
 # External editor support
 'edit-externally' => 'I-edit me ing simpan a ini kapamilatan ning aplikasiun o program a ibat king kilual.',
-'edit-externally-help' => '(Lon me ing [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] para king karagdagang informacion)',
+'edit-externally-help' => '(Lon me ing [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] para king karagdagang informacion)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'eganagana',
index a7a62e8..e66f8f7 100644 (file)
@@ -242,8 +242,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Érprind din  "$1"',
 'youhavenewmessages' => 'Os avez $1 ($2).',
-'newmessageslink' => 'nouvieus messaches',
-'newmessagesdifflink' => 'darin cangemint',
 'youhavenewmessagesmulti' => 'Os avez des nouvieus messaches su $1',
 'editsection' => 'éditer',
 'editold' => 'éditer',
@@ -1026,7 +1024,7 @@ Chés eutes cans is s'ront muchés pèr défeut.
 
 # External editor support
 'edit-externally' => "Éditer ch'fichié-lo aveuc eune éstérne aplicachon",
-'edit-externally-help' => '(Vir [//www.mediawiki.org/wiki/Manual:External_editors/fr chés instruccions d’installachon] pou pus d’informachons)',
+'edit-externally-help' => '(Vir [https://www.mediawiki.org/wiki/Manual:External_editors/fr chés instruccions d’installachon] pou pus d’informachons)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tertous',
@@ -1057,8 +1055,7 @@ Chés eutes cans is s'ront muchés pèr défeut.
 
 # Special:SpecialPages
 'specialpages' => 'Paches éspéchiales',
-'specialpages-note' => '----
-* Paches éspéchiales conformes.
+'specialpages-note' => '* Paches éspéchiales conformes.
 * <span class="mw-specialpagerestricted">Paches éspéchiales réstrintes.</span>
 * <span class="mw-specialpagecached">Paches éspéchiales seulemint in muche (pétète des viuseries).</span>',
 'specialpages-group-maintenance' => "Rapports d'maintenanche",
index 4d12a58..d5e0088 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Kaganer
  * @author Krinkle
+ * @author Shirayuki
  * @author Xqt
  * @author לערי ריינהארט
  */
@@ -232,8 +233,6 @@ Guck aa [[Special:Version|Versionsblatt]]',
 'ok' => 'OK',
 'retrievedfrom' => 'Vun „$1“',
 'youhavenewmessages' => 'Du hast $1 uff deinem $2.',
-'newmessageslink' => 'Neiichkeede',
-'newmessagesdifflink' => 'Gschwetz-Blatt',
 'youhavenewmessagesmulti' => 'Du hascht neie Comments: $1',
 'editsection' => 'Ennere',
 'editold' => 'Ennere',
@@ -498,6 +497,7 @@ Paesswatt fer nau: $2',
 'recentchanges' => 'Was mer letscht geduh henn',
 'recentchanges-label-minor' => 'Gleene Ennering',
 'recentchanges-label-bot' => 'Ennering vun em Waddefresser',
+'recentchanges-legend-newpage' => '$1 - neies Blatt',
 'rcshowhideminor' => 'Gleene Enneringe $1',
 'rcshowhidebots' => 'Bots $1',
 'rcshowhideanons' => 'IP-Yuuser $1',
@@ -1008,4 +1008,10 @@ Guck $2 fer e Lischt vun de letscht Leschunge.',
 # Search suggestions
 'searchsuggest-search' => 'Uffgucke',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'Result',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Anmaerrickinge lösche',
+'expand_templates_preview' => 'Aagucke',
+
 );
index 9d774d0..ab0b726 100644 (file)
@@ -267,8 +267,6 @@ $1',
 'ok' => 'Alla gud',
 'retrievedfrom' => 'Vun "$1"',
 'youhavenewmessages' => 'Du hoschd $1 ($2).',
-'newmessageslink' => 'naije Nochrischde',
-'newmessagesdifflink' => 'ledschdi Ännarung',
 'newmessagesdifflinkplural' => 'ledschdi {{PLURAL:$1|Ännarung|Ännarunge}}',
 'youhavenewmessagesmulti' => 'Do hoschd ä Nochrischd grischd: $1',
 'editsection' => 'beawaide',
@@ -1181,7 +1179,7 @@ Wonn die Dadai vaännad worre isch, donn konns soi, daß zusedzlischi Õgawe fa
 
 # External editor support
 'edit-externally' => 'Die Dadai midm õnnare Weagzaisch beawaide',
-'edit-externally-help' => '(Gugg uff [//www.mediawiki.org/wiki/Manual:External_editors Inschdallazionsõwaisunge] fa mea Auskinfd)',
+'edit-externally-help' => '(Gugg uff [https://www.mediawiki.org/wiki/Manual:External_editors Inschdallazionsõwaisunge] fa mea Auskinfd)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alle',
index 289e770..ee80c86 100644 (file)
@@ -130,7 +130,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Zły_tytuł' ),
        'Blankpage'                 => array( 'Pusta_strona' ),
        'Block'                     => array( 'Blokuj' ),
-       'Blockme'                   => array( 'Zablokuj_mnie' ),
        'Booksources'               => array( 'Książki' ),
        'BrokenRedirects'           => array( 'Zerwane_przekierowania' ),
        'Categories'                => array( 'Kategorie' ),
@@ -142,15 +141,16 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Utwórz_konto', 'Stwórz_konto' ),
        'Deadendpages'              => array( 'Bez_linków' ),
        'DeletedContributions'      => array( 'Usunięty_wkład' ),
-       'Disambiguations'           => array( 'Ujednoznacznienia' ),
        'DoubleRedirects'           => array( 'Podwójne_przekierowania' ),
        'EditWatchlist'             => array( 'Edytuj_obserwowane' ),
        'Emailuser'                 => array( 'E-mail' ),
+       'ExpandTemplates'           => array( 'Rozwijanie_szablonów' ),
        'Export'                    => array( 'Eksport' ),
        'Fewestrevisions'           => array( 'Najmniej_edycji' ),
        'FileDuplicateSearch'       => array( 'Szukaj_duplikatu_pliku' ),
        'Filepath'                  => array( 'Ścieżka_do_pliku' ),
        'Invalidateemail'           => array( 'Anuluj_e-mail' ),
+       'JavaScriptTest'            => array( 'Test_JavaScriptu' ),
        'BlockList'                 => array( 'Zablokowani' ),
        'LinkSearch'                => array( 'Wyszukiwarka_linków' ),
        'Listadmins'                => array( 'Administratorzy' ),
@@ -179,6 +179,7 @@ $specialPageAliases = array(
        'Myuploads'                 => array( 'Moje_pliki' ),
        'Newimages'                 => array( 'Nowe_pliki' ),
        'Newpages'                  => array( 'Nowe_strony' ),
+       'PagesWithProp'             => array( 'Strony_z_własnością' ),
        'PasswordReset'             => array( 'Wyczyść_hasło' ),
        'PermanentLink'             => array( 'Niezmienny_link' ),
        'Popularpages'              => array( 'Popularne_strony' ),
@@ -187,9 +188,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Zabezpieczone_strony' ),
        'Protectedtitles'           => array( 'Zabezpieczone_nazwy_stron' ),
        'Randompage'                => array( 'Losowa_strona', 'Losowa' ),
+       'RandomInCategory'          => array( 'Losowa_w_kategorii', 'Losowa_strona_w_kategorii' ),
        'Randomredirect'            => array( 'Losowe_przekierowanie' ),
        'Recentchanges'             => array( 'Ostatnie_zmiany', 'OZ' ),
        'Recentchangeslinked'       => array( 'Zmiany_w_linkowanych', 'Zmiany_w_linkujących' ),
+       'Redirect'                  => array( 'Przekieruj' ),
+       'ResetTokens'               => array( 'Resetuj_tokeny' ),
        'Revisiondelete'            => array( 'Usuń_wersję' ),
        'Search'                    => array( 'Szukaj' ),
        'Shortpages'                => array( 'Najkrótsze_strony' ),
@@ -584,12 +588,10 @@ $1',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Źródło „$1”',
 'youhavenewmessages' => 'Masz $1 ($2).',
-'newmessageslink' => 'nowe wiadomości',
-'newmessagesdifflink' => 'różnica z poprzednią wersją',
 'youhavenewmessagesfromusers' => 'Masz $1 od {{PLURAL:$3|innego użytkownika|$3 użytkowników}} ($2).',
 'youhavenewmessagesmanyusers' => 'Masz $1 od wielu użytkowników ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|jedną wiadomość|nowe wiadomości}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|ostatnia zmiana|ostatnie zmiany}}',
+'newmessageslinkplural' => '{{PLURAL:$1|jedną wiadomość|999=nowe wiadomości}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|ostatnia zmiana|999=ostatnie zmiany}}',
 'youhavenewmessagesmulti' => 'Masz nowe wiadomości na $1',
 'editsection' => 'edytuj',
 'editold' => 'edytuj',
@@ -719,7 +721,8 @@ Administrator blokujący go podał następujący powód "\'\'$3\'\'".',
 'invalidtitle-knownnamespace' => 'Nieprawidłowa nazwa w obszarze nazw "$2" o treści "$3"',
 'invalidtitle-unknownnamespace' => 'Nieprawidłowa nazwa z nieznaną liczbą przestrzeni nazw  $1  o treści "$2"',
 'exception-nologin' => 'Nie jesteś zalogowany/a',
-'exception-nologin-text' => 'Ta strona lub akcja wymaga bycia zalogowanym na tej wiki.',
+'exception-nologin-text' => 'Proszę [[Special:Userlogin|zaloguj się]] aby mieć dostęp do tej strony lub akcji.',
+'exception-nologin-text-manual' => 'Musisz $1 aby mieć dostęp do tej strony lub akcji.',
 
 # Virus scanner
 'virus-badscanner' => "Zła konfiguracja – nieznany skaner antywirusowy ''$1''",
@@ -769,6 +772,9 @@ Nie zapomnij dostosować [[Special:Preferences|preferencji]].',
 'userlogin-resetpassword-link' => 'Nie pamiętasz hasła?',
 'helplogin-url' => 'Help:Logowanie',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoc z logowaniem]]',
+'userlogin-loggedin' => 'Zalogowano jako {{GENDER:$1|$1}}.
+Użyj poniższego formularza, aby zalogować się jako inny użytkownik.',
+'userlogin-createanother' => 'Załóż nowe konto',
 'createacct-join' => 'Wpisz poniżej swoje dane.',
 'createacct-another-join' => 'Wprowadź szczegóły nowego konta poniżej.',
 'createacct-emailrequired' => 'Adres e‐mail',
@@ -900,7 +906,7 @@ Być może właśnie zmienił{{GENDER:|eś|aś|eś(‐aś)}} swoje hasło lub po
 'passwordreset-domain' => 'Domena',
 'passwordreset-capture' => 'Czy pokazywać treść wiadomości e‐mail?',
 'passwordreset-capture-help' => 'Jeśli zaznaczysz to pole, zobaczysz treść wiadomości e‐mail z tymczasowym hasłem, w tej samej formie w jakiej jest wysyłana do użytkownika.',
-'passwordreset-email' => 'Adres e‐mail',
+'passwordreset-email' => 'Adres e‐mail:',
 'passwordreset-emailtitle' => 'Dane konta w {{GRAMMAR:MS.lp|{{SITENAME}}}}',
 'passwordreset-emailtext-ip' => 'Ktoś (prawdopodobnie Ty, spod adresu IP $1) poprosił o zresetowanie twojego hasła w {{GRAMMAR:MS.lp{{SITENAME}}}} ($4). Z tym adresem e‐mailowym powiązane {{PLURAL:$3|jest konto użytkownika|są następujące konta użytkowników:}}
 
@@ -925,10 +931,10 @@ Tymczasowe hasło – $2',
 'changeemail-header' => 'Zmiana adresu e‐mail',
 'changeemail-text' => 'Wypełnij formularz, jeśli chcesz zmienić swój adres poczty elektronicznej. Będziesz musiał wprowadzić hasło, aby potwierdzić tę zmianę.',
 'changeemail-no-info' => 'Musisz być zalogowany, by uzyskać bezpośredni dostęp do tej strony.',
-'changeemail-oldemail' => 'Obecny adres e‐mail',
-'changeemail-newemail' => 'Nowy adres e-mail',
+'changeemail-oldemail' => 'Obecny adres e‐mail:',
+'changeemail-newemail' => 'Nowy adres e-mail:',
 'changeemail-none' => '(brak)',
-'changeemail-password' => 'Hasło {{SITENAME}}:',
+'changeemail-password' => 'Twoje hasło:',
 'changeemail-submit' => 'Zapisz nowy',
 'changeemail-cancel' => 'Anuluj',
 
@@ -1278,8 +1284,9 @@ wybrana wersja nie istnieje lub próbowano ukryć wersję bieżącą.',
 'logdelete-selected' => "'''Zaznaczone {{PLURAL:$1|zdarzenie|zdarzenia}} z rejestru:'''",
 'revdelete-text' => "'''Usunięte wersje i czynności będą nadal widoczne w historii strony i rejestrach, ale ich treść nie będzie publicznie dostępna.'''
 Inni administratorzy {{GRAMMAR:D.lp|{{SITENAME}}}} nadal będą mieć dostęp do ukrytych treści oraz będą mogli je odtworzyć używając standardowych mechanizmów, chyba że nałożono dodatkowe ograniczenia.",
-'revdelete-confirm' => 'Potwierdź, że chcesz to zrobić, rozumiesz konsekwencje oraz że robisz to zgodnie z [[{{MediaWiki:Policy-url}}|zasadami]].',
+'revdelete-confirm' => 'Potwierdź, że chcesz to zrobić zgodnie z [[{{MediaWiki:Policy-url}}|zasadami]] i że rozumiesz konsekwencje.',
 'revdelete-suppress-text' => "Ukrywanie powinno być używane '''wyłącznie''' w sytuacji:
+* Informacji, która może być zniesławieniem
 * Ujawnienie danych osobowych
 *: ''adres domowy, numer telefonu, numer PESEL itp''",
 'revdelete-legend' => 'Ustaw ograniczenia widoczności',
@@ -1290,8 +1297,8 @@ Inni administratorzy {{GRAMMAR:D.lp|{{SITENAME}}}} nadal będą mieć dostęp do
 'revdelete-hide-user' => 'Ukryj nazwę użytkownika/adres IP',
 'revdelete-hide-restricted' => 'Ukryj informacje przed administratorami tak samo jak przed innymi',
 'revdelete-radio-same' => '(bez zmian)',
-'revdelete-radio-set' => 'Tak',
-'revdelete-radio-unset' => 'Nie',
+'revdelete-radio-set' => 'Ukryty',
+'revdelete-radio-unset' => 'Widoczny',
 'revdelete-suppress' => 'Utajnij informacje przed administratorami, tak samo jak przed innymi',
 'revdelete-unsuppress' => 'Wyłącz utajnianie dla odtwarzanej historii zmian',
 'revdelete-log' => 'Powód',
@@ -1445,8 +1452,7 @@ Jednak informacje o treści {{GRAMMAR:D.lp|{{SITENAME}}}} mogą być w Google ni
 'preferences' => 'Preferencje',
 'mypreferences' => 'Preferencje',
 'prefs-edits' => 'Liczba edycji',
-'prefsnologin' => 'Nie jesteś zalogowany',
-'prefsnologintext' => 'Musisz się <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} zalogować]</span> przed zmianą swoich preferencji.',
+'prefsnologintext2' => 'Musisz $1 aby ustawić preferencje.',
 'changepassword' => 'Zmiana hasła',
 'prefs-skin' => 'Skórka',
 'skin-preview' => 'podgląd',
@@ -1744,6 +1750,8 @@ Jeśli zdecydujesz się je podać, zostaną użyte, by udokumentować Twoje auto
 'recentchanges-label-minor' => 'To jest drobna zmiana',
 'recentchanges-label-bot' => 'Ta edycja została wykonana przez bota',
 'recentchanges-label-unpatrolled' => 'Ta edycja nie została jeszcze sprawdzona',
+'recentchanges-label-plusminus' => 'Zmieniony rozmiar strony (liczba bajtów)',
+'recentchanges-legend-newpage' => '(zobacz też [[Special:NewPages|listę nowych stron]])',
 'rcnote' => "Poniżej {{PLURAL:$1|znajduje się '''1''' ostatnia zmiana wykonana|znajdują się ostatnie '''$1''' zmiany wykonane|znajduje się ostatnich '''$1''' zmian wykonanych}} w ciągu {{PLURAL:$2|ostatniego dnia|ostatnich '''$2''' dni}}, licząc od $5 dnia $4.",
 'rcnotefrom' => "Poniżej pokazano zmiany wykonane po '''$2''' (nie więcej niż '''$1''' pozycji).",
 'rclistfrom' => 'Pokaż nowe zmiany od $1',
@@ -2479,9 +2487,9 @@ Kontakt do autora:
 mail – $PAGEEDITOR_EMAIL
 wiki – $PAGEEDITOR_WIKI
 
-W przypadku kolejnych zmian nowe powiadomienia nie zostaną wysłane, dopóki nie odwiedzisz tej strony. Możesz także zresetować wszystkie flagi powiadomień na swojej liście stron obserwowanych.
+W przypadku kolejnych zmian nowe powiadomienia nie zostaną wysłane, dopóki nie odwiedzisz tej strony jako zalogowany. Możesz także zresetować wszystkie flagi powiadomień na swojej liście stron obserwowanych.
 
-       Wiadomość z systemu powiadomień {{GRAMMAR:D.lp|{{SITENAME}}}}
+Wiadomość z systemu powiadomień {{GRAMMAR:D.lp|{{SITENAME}}}}
 
 --
 W celu zmiany ustawień swojej listy obserwowanych odwiedź
@@ -3000,7 +3008,7 @@ Możesz również użyć linku, np. [[{{#Special:Export}}/{{MediaWiki:Mainpage}}
 'allmessagesdefault' => 'Tekst domyślny',
 'allmessagescurrent' => 'Tekst obecny',
 'allmessagestext' => 'Lista wszystkich komunikatów systemowych dostępnych w przestrzeni nazw MediaWiki.
-Odwiedź [//www.mediawiki.org/wiki/Localisation Tłumaczenie MediaWiki] oraz [//translatewiki.net translatewiki.net], jeśli chcesz uczestniczyć w tłumaczeniu oprogramowania MediaWiki.',
+Odwiedź [https://www.mediawiki.org/wiki/Localisation Tłumaczenie MediaWiki] oraz [//translatewiki.net translatewiki.net], jeśli chcesz uczestniczyć w tłumaczeniu oprogramowania MediaWiki.',
 'allmessagesnotsupportedDB' => "Ta strona nie może być użyta, ponieważ zmienna '''\$wgUseDatabaseMessages''' jest wyłączona.",
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter' => 'Filtrowanie według stanu modyfikacji:',
@@ -3164,6 +3172,7 @@ Brak katalogu dla plików tymczasowych.',
 Pozwala na wpisanie powodu w opisie zmian.',
 'tooltip-preferences-save' => 'Zapisz preferencje',
 'tooltip-summary' => 'Wpisz krótki opis',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* Umieszczony tutaj kod CSS zostanie zastosowany we wszystkich skórkach */',
@@ -3209,6 +3218,8 @@ Najprawdopodobniej zostało to spowodowane przez link do zewnętrznej strony int
 'spam_reverting' => 'Przywracanie ostatniej wersji nie zawierającej linków do $1',
 'spam_blanking' => 'Wszystkie wersje zawierały odnośniki do $1. Czyszczenie strony.',
 'spam_deleting' => 'Wszystkie wersje zawierały linki do $1, usuwam.',
+'simpleantispam-label' => "Filtr antyspamowy.
+'''NIE''' wpisuj tu nic!",
 
 # Info page
 'pageinfo-title' => 'Informacje o „$1“',
@@ -3222,6 +3233,7 @@ Najprawdopodobniej zostało to spowodowane przez link do zewnętrznej strony int
 'pageinfo-length' => 'Długość strony (w bajtach)',
 'pageinfo-article-id' => 'Identyfikator strony',
 'pageinfo-language' => 'Język zawartości strony',
+'pageinfo-content-model' => 'Model zawartości',
 'pageinfo-robot-policy' => 'Indeksowanie przez roboty',
 'pageinfo-robot-index' => 'Dozwolone',
 'pageinfo-robot-noindex' => 'Niedozwolone',
@@ -3308,7 +3320,7 @@ Jeśli go otworzysz, możesz zarazić swój system.",
 'svg-long-desc' => 'Plik SVG, nominalnie $1 × $2 pikseli, rozmiar pliku: $3',
 'svg-long-desc-animated' => 'Animowany plik SVG, nominalnie $1 × $2 pikseli, rozmiar pliku: $3',
 'svg-long-error' => 'Nieprawidłowy plik SVG:$1',
-'show-big-image' => 'Pełna rozdzielczość',
+'show-big-image' => 'Rozmiar pierwotny',
 'show-big-image-preview' => 'Rozmiar podglądu – $1.',
 'show-big-image-other' => '{{PLURAL:$2|Inna rozdzielczość|Inne rozdzielczości}}: $1.',
 'show-big-image-size' => '$1 x $2 pikseli',
@@ -3784,7 +3796,7 @@ Pozostałe pola zostaną domyślnie ukryte.
 
 # External editor support
 'edit-externally' => 'Edytuj plik, używając zewnętrznej aplikacji',
-'edit-externally-help' => '(Więcej informacji o używaniu [//www.mediawiki.org/wiki/Manual:External_editors zewnętrznych edytorów]).',
+'edit-externally-help' => '(Więcej informacji o używaniu [https://www.mediawiki.org/wiki/Manual:External_editors zewnętrznych edytorów]).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'wszystkie',
@@ -3889,6 +3901,7 @@ Czy na pewno chcesz ją ponownie utworzyć?",
 
 # Separators for various lists, etc.
 'percent' => '$1&#160;%',
+'quotation-marks' => '„$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← poprzednia strona',
@@ -4019,7 +4032,7 @@ Możesz także użyć [[Special:EditWatchlist|standardowego edytora obserwowanyc
 'version-hook-subscribedby' => 'Zapotrzebowany przez',
 'version-version' => '(Wersja $1)',
 'version-license' => 'Licencja',
-'version-poweredby-credits' => "Ta wiki korzysta z oprogramowania '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001‐$1 $2.",
+'version-poweredby-credits' => "Ta wiki korzysta z oprogramowania '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001‐$1 $2.",
 'version-poweredby-others' => 'inni',
 'version-poweredby-translators' => 'tłumacze translatewiki.net',
 'version-credits-summary' => 'Następujące osoby wniosły istotny wkład w rozwój oprogramowania [[Special:Version|MediaWiki]].',
@@ -4038,7 +4051,7 @@ Powinieneś otrzymać [{{SERVER}}{{SCRIPTPATH}}/COPYING kopię licencji GNU Gene
 # Special:Redirect
 'redirect' => 'Przekierowanie według pliku, użytkownika albo identyfikatora wersji',
 'redirect-legend' => 'Przekieruj do pliku lub strony',
-'redirect-summary' => 'Ta strona specjalna przekierowuje do pliku (wg nazwy pliku), do strony (wg numeru wersji) albo do strony użytkownika (wg liczbowego identyfikatora użytkownika)',
+'redirect-summary' => 'Ta strona specjalna przekierowuje do: pliku (o podanej nazwie), do strony (o podanym numerze wersji) albo do strony użytkownika (o podanym identyfikatorze numerycznym). Sposób użycia: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] albo [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Przejdź',
 'redirect-lookup' => 'Wyszukaj:',
 'redirect-value' => 'Wartość:',
@@ -4060,8 +4073,8 @@ Powinieneś otrzymać [{{SERVER}}{{SCRIPTPATH}}/COPYING kopię licencji GNU Gene
 
 # Special:SpecialPages
 'specialpages' => 'Strony specjalne',
-'specialpages-note' => '----
-* Normalne strony specjalne.
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Normalne strony specjalne.
 * <span class="mw-specialpagerestricted">Zastrzeżone strony specjalne.</span>',
 'specialpages-group-maintenance' => 'Raporty konserwacyjne',
 'specialpages-group-other' => 'Inne strony specjalne',
@@ -4096,7 +4109,7 @@ Powinieneś otrzymać [{{SERVER}}{{SCRIPTPATH}}/COPYING kopię licencji GNU Gene
 'tag-filter-submit' => 'Filtr',
 'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Znacznik|Znaczniki}}]]: $2)',
 'tags-title' => 'Znaczniki',
-'tags-intro' => 'Na tej stronie znajduje się lista wzorców tekstu, dla których oprogramowanie może oznaczyć edycje, dodatkowo wskazując ich znaczenie.',
+'tags-intro' => 'Na tej stronie znajduje się lista znaczników, którymi oprogramowanie może oznaczyć edycje, oraz ich opisów.',
 'tags-tag' => 'Nazwa znacznika',
 'tags-display-header' => 'Wystąpienia na listach zmian',
 'tags-description-header' => 'Pełny opis znaczenia',
@@ -4275,4 +4288,21 @@ W przeciwnym wypadku można użyć prostego formularza poniżej. Komentarz zosta
 'limitreport-expansiondepth' => 'Największa głębokość ekspansji',
 'limitreport-expensivefunctioncount' => 'Liczba wywołań kosztownych funkcji parsera',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Rozwijanie szablonów',
+'expand_templates_intro' => 'We wprowadzonym na tej stronie tekście źródłowym zostaną rozwinięte rekurencyjnie wszystkie szablony.
+Rozwinięte także zostaną funkcje parsera takie jak
+<code><nowiki>{{</nowiki>#language:…}}</code> i zmienne jak
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+W zasadzie rozwijane jest prawie wszystko w podwójnych nawiasach klamrowych.',
+'expand_templates_title' => 'Pozorny tytuł strony dla zmiennych takich jak {{FULLPAGENAME}}',
+'expand_templates_input' => 'Tekst wejściowy',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'wynik w formacie XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Usuń komentarze',
+'expand_templates_remove_nowiki' => 'Ukrywaj w wyniku znaczniki <nowiki>',
+'expand_templates_generate_xml' => 'Pokaż drzewo analizatora składni w formacie XML',
+'expand_templates_preview' => 'Podgląd',
+
 );
index c9bce10..54edd28 100644 (file)
@@ -316,12 +316,10 @@ $1",
 'ok' => 'Va bin',
 'retrievedfrom' => 'Pijàit da «$1»',
 'youhavenewmessages' => "A l'ha $1 ($2).",
-'newmessageslink' => 'ëd mëssagi neuv',
-'newmessagesdifflink' => 'ùltima modìfica',
 'youhavenewmessagesfromusers' => "A l'ha $1 da {{PLURAL:$3|n'autr utent|$3 utent}} ($2).",
 'youhavenewmessagesmanyusers' => "A l'ha $1 da vàire utent ($2).",
-'newmessageslinkplural' => '{{PLURAL:$1|un mëssagi neuv|$1 mëssagi neuv}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|ùltima modìfica|ùltime modìfiche}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un mëssagi neuv|999=dij mëssagi neuv}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|ùltima modìfica|999=ùltime modìfiche}}',
 'youhavenewmessagesmulti' => "A l'ha dij neuv mëssagi an $1",
 'editsection' => 'modifiché',
 'editold' => 'modifiché',
@@ -449,7 +447,8 @@ L'aministrator ch'a l'ha blocalo a l'ha lassà sta spiegassion: «$3».",
 'invalidtitle-knownnamespace' => "Tìtol ch'a va nen bin con lë spassi nominal «$2» e ël test «$3»",
 'invalidtitle-unknownnamespace' => 'Tìtol pa bon con nùmer dë spassi nominal $1 e test «$2» sconossù',
 'exception-nologin' => 'Nen rintrà ant ël sistema',
-'exception-nologin-text' => "Costa pàgina o assion a l'ha damanca ch'a sia rintrà an costa wiki.",
+'exception-nologin-text' => "Për piasì, [[Special:Userlogin|ch'a rintra ant ël sistema]] për podèj acede a costa pàgina o a costa assion.",
+'exception-nologin-text-manual' => "Për piasì, ch'a $1 për podèj acede a costa pàgina o costa assion.",
 
 # Virus scanner
 'virus-badscanner' => "Configurassion falà: antivìrus nen conossù: ''$1''",
@@ -496,7 +495,7 @@ Che a dësmentia pa ëd cambié ij [[Special:Preferences|sò gust për {{SITENAM
 'gotaccount' => 'Ha-lo già un sò cont? $1.',
 'gotaccountlink' => "Ch'a rintra ant ël sistema",
 'userlogin-resetlink' => "A l'ha dësmentià ij sò detaj për intré ant ël sistema?",
-'userlogin-resetpassword-link' => 'Riamposté la ciav',
+'userlogin-resetpassword-link' => 'Ciav dësmentià?',
 'helplogin-url' => 'Help:Conession',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Agiut con la conession]]',
 'userlogin-loggedin' => "A l'é già rintrà an ël sistema tanme {{GENDER:$1|$1}}.
@@ -548,7 +547,7 @@ Che a preuva torna, për piasì.",
 'passwordtooshort' => 'Le ciav a devo avèj almanch {{PLURAL:$1|1 caràter|$1 caràter}}.',
 'password-name-match' => 'Soa ciav a dev esse diferenta da sò stranòm.',
 'password-login-forbidden' => "L'usagi ëd së stranòm d'utent e ëd sa ciav a son ëstàit proibì.",
-'mailmypassword' => 'Mandeme na neuva ciav për pòsta eletrònica',
+'mailmypassword' => 'Riamposté la ciav',
 'passwordremindertitle' => 'Neuva ciav provisòria për {{SITENAME}}',
 'passwordremindertext' => "Cheidun (a l'é belfé che a sia stàit pròpe chiel, da 'nt l'adrëssa IP $1) a l'ha ciamà na neuva
 ciav për rintré ant ël sistema ëd {{SITENAME}} ($4).
@@ -569,8 +568,8 @@ Anans che qualsëssìa àutr messagi ëd pòsta a ven-a mandà a 's cont-sì, a
 'mailerror' => 'Eror ën mandand via un mëssagi ëd pòsta eletrònica: $1',
 'acct_creation_throttle_hit' => "Dij visitador ëd costa wiki, an dovrand soa adrëssa IP a l'han creà {{PLURAL:$1|1 cont|$1 cont}} ant l'ùltim di, che a l'é tut lòn che as peul fesse ant cost temp.
 Ëd conseguensa, ij visitador che a deuvro costa adrëssa IP a peulo pì nen fé dij cont al moment.",
-'emailauthenticated' => "Soa adrëssa ëd pòsta eletrònica a l'é stàita autenticà ël $2 a $3.",
-'emailnotauthenticated' => "Soa adrëssa ëd pòsta eletrònica a l'é pa ancó stàita autenticà.
+'emailauthenticated' => "Soa adrëssa ëd pòsta eletrònica a l'é stàita confirmà ël $2 a $3.",
+'emailnotauthenticated' => "Soa adrëssa ëd pòsta eletrònica a l'é pa ancó stàita confirmà.
 Për qualsëssìa ëd coste funsion a sarà mandà gnun mëssagi.",
 'noemailprefs' => "Che a specìfica n'adrëssa ëd pòsta eletrònica se a veul dovré coste funsion-sì.",
 'emailconfirmlink' => 'Che a conferma soa adrëssa ëd pòsta eletrònica',
@@ -620,7 +619,7 @@ Peul desse ch'a l'ha già cambià la ciav o a l'ha ciamà na neuva ciav provisò
 # Special:PasswordReset
 'passwordreset' => 'Ri-inissialisassion ëd la ciav',
 'passwordreset-text-one' => "Ch'a completa 's formolari për reimposté soa ciav.",
-'passwordreset-text-many' => "{{PLURAL:$1|Ch'a compila un dij camp për riamposté soa ciav.}}",
+'passwordreset-text-many' => "{{PLURAL:$1|Ch'a compila un dij camp për arsèive na ciav provisòria për pòsta eletrònica.}}",
 'passwordreset-legend' => 'Riampostassion ëd la ciav',
 'passwordreset-disabled' => "La reinissialisassion ëd le ciav a l'é stàita disabilità su sta wiki.",
 'passwordreset-emaildisabled' => 'Le fonsionalità ëd pòsta eletrònica a son ëstàite disativà su sta wiki.',
@@ -850,33 +849,33 @@ L'ùltima vos dël registr a l'é smonùa sì-sota për arferiment:",
 'nocreatetext' => "{{SITENAME}} a l'ha limità la possibilità ëd creé dle pàgine neuve.
 A peul torné andaré e modifiché na pàgina che a-i é già, ò pura [[Special:UserLogin|rintré ant ël sistema ò deurb-se un cont]].",
 'nocreate-loggedin' => "A l'ha pa ël përmess ëd creé dle pàgine neuve.",
-'sectioneditnotsupported-title' => "La modìfica dla session a l'é nen prevëdùa",
-'sectioneditnotsupported-text' => "La modìfica dla session a l'é nen prevëdùa an costa pàgina ëd modìfica.",
+'sectioneditnotsupported-title' => "La modìfica ëd session a l'é nen mantnùa",
+'sectioneditnotsupported-text' => "La modìfica ëd na session a l'é nen mantnùa për costa pàgina.",
 'permissionserrors' => 'Eror ant ij përmess',
-'permissionserrorstext' => "A l'ha pa ij përmess dont a fa da manca për {{PLURAL:$1|via che|via che}}:",
-'permissionserrorstext-withaction' => "It l'has nen ij përmess për $2, për {{PLURAL:$1|cost motiv|costi motiv}}:",
-'recreate-moveddeleted-warn' => "A l'é an camin ch'a crea torna na pàgina ch'a l'era stàita scancelà.'''
+'permissionserrorstext' => "A l'ha pa ij përmess dont a fa da manca për {{PLURAL:$1|via che}}:",
+'permissionserrorstext-withaction' => "A l'ha nen ij përmess për $2, për {{PLURAL:$1|cost motiv|costi motiv}}:",
+'recreate-moveddeleted-warn' => "'''Atension: a l'é an camin ch'a crea torna na pàgina ch'a l'era stàita scancelà.'''
 
 Ch'a varda d'esse sigur ch'a vala la pen-a ëd travajé an sna pàgina parèj.
 Për soa comodità i-j mostroma la lista djë scancelament ch'a toco sta pàgina-sì:",
 'moveddeleted-notice' => "Sta pàgina-sì a l'é stàita scancelà.
-Ël registr ëd le scancelassion e dij tramud a l'é arportà sota për arferiment.",
-'log-fulllog' => 'Varda tut ël registr',
+Ël registr ëd le scancelassion e dij tramud a l'é arportà sì-sota për arferiment.",
+'log-fulllog' => 'Vëdde tut ël registr',
 'edit-hook-aborted' => "Modìfica anulà da n'estension.
-A-i é pa gnun-e spiegassion.",
-'edit-gone-missing' => 'As peul nen modifiché la pàgina.
+A-i é pa  spiegassion.",
+'edit-gone-missing' => 'As peul nen agiornesse la pàgina.
 A smija che a sia stàita scancelà.',
-'edit-conflict' => "Conflit d'edission.",
-'edit-no-change' => "Toa modìfica a l'é stàita ignorà, përchè a l'é pa stàit fàit gnun cambiament al test.",
-'postedit-confirmation' => "Soa modìfica a l'é stàita salvà!",
-'edit-already-exists' => 'As peul nen creesse la pàgina.
-A esist già.',
+'edit-conflict' => 'Conflit ëd modìfiche.',
+'edit-no-change' => "Soa modìfica a l'é stàita ignorà, përchè gnun cambiament a l'é stàit fàit al test.",
+'postedit-confirmation' => "Soa modìfica a l'é stàita salvà.",
+'edit-already-exists' => "La neuva pàgina a l'ha nen podù creesse.
+A esist già.",
 'defaultmessagetext' => "Test che a-i sarìa se a-i fusso pa 'd modìfiche",
 'content-failed-to-parse' => "Faliment ëd l'anàlisi dël contnù ëd $2 për ël model $1: $3",
 'invalid-content-data' => 'Dat dël contnù pa bon',
 'content-not-allowed-here' => "Ël contnù «$1» a l'é nen autorisà an sla pàgina [[$2]]",
 'editwarning-warning' => "Chité sta pàgina-sì a peul feje perde tute le modìfiche ch'a l'ha fàit.
-S'a l'é rintrà ant ël sistema, a peul disabilité st'avis ant la session «Modìfiche» dij sò gust.",
+S'a l'é rintrà ant ël sistema, a peul disabilité st'avis ant la session «Modìfica» dij sò gust.",
 
 # Content models
 'content-model-wikitext' => 'test wiki',
@@ -885,21 +884,21 @@ S'a l'é rintrà ant ël sistema, a peul disabilité st'avis ant la session «Mo
 'content-model-css' => 'CSS',
 
 # Parser/template warnings
-'expensive-parserfunction-warning' => "'''Atension:''' Costa pàgina a l'ha tròpe ciamà costose a le fonsions ëd parser.
+'expensive-parserfunction-warning' => "'''Atension:''' Costa pàgina a l'ha tròpe ciamà costose a le fonsions d'anàlisi sintàtica.
 
-A dovrìa essnie men che {{PLURAL:$2|$2|$2}}, adess a-i na j'é {{PLURAL:$1|$1|$1}}.",
-'expensive-parserfunction-category' => 'Pàgine con tròpe ciamà costose a le fonsion parser',
-'post-expand-template-inclusion-warning' => "'''Atension:''' La dimension djë stamp anserì a l'é tròp gròssa.
+A dovrìa essnie men che {{PLURAL:$2|$2}}, adess a-i na j'é {{PLURAL:$1|$1}}.",
+'expensive-parserfunction-category' => "Pàgine con tròpe ciamà costose ëd fonsion ëd l'analisator sintàtich",
+'post-expand-template-inclusion-warning' => "'''Atension:''' La dimension dj'anseriment dë stamp a l'é tròp gròssa.
 Chèich stamp a saran nen anserì.",
-'post-expand-template-inclusion-category' => "Pàgine andoa la dimension djë stamp anserì a l'é tròpa",
+'post-expand-template-inclusion-category' => 'Pàgine con tròpe anclusion dë stamp',
 'post-expand-template-argument-warning' => "'''Atension:''' Costa pàgina a conten almanch un paràmeter dë stamp che a l'ha n'espansion tròp gròssa.
-Costi paràmeter a son stàit lassà fòra.",
-'post-expand-template-argument-category' => 'Pàgine contenente stamp con paràmeter mancant',
+Costi paràmeter a son stàit ignorà.",
+'post-expand-template-argument-category' => 'Pàgine contenente djë stamp con paràmeter mancant',
 'parser-template-loop-warning' => 'Trovà na liassa dlë stamp: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Passà ël lìmit ëd ricorsion dlë stamp ($1)',
-'language-converter-depth-warning' => 'Passà lìmit ëd profondità dël convertidor ëd lenghe ($1)',
-'node-count-exceeded-category' => "Pàgine anté che ël nùmer ëd grop a l'é sorpassà",
-'node-count-exceeded-warning' => "La pàgina a l'ha sorpassà ël nùmer ëd grop",
+'language-converter-depth-warning' => 'Lìmit ëd profondità dël convertidor ëd lenga sorpassà ($1)',
+'node-count-exceeded-category' => "Pàgine anté che ël nùmer ëd neu a l'é sorpassà",
+'node-count-exceeded-warning' => "La pàgina a l'ha sorpassà ël nùmer ëd neu",
 'expansion-depth-exceeded-category' => "Pàgine anté che la profondeur d'espansion a l'é sorpassà",
 'expansion-depth-exceeded-warning' => "La pàgina a l'ha sorpassà la profondità d'espansion",
 'parser-unstrip-loop-warning' => 'Trovà un sicl nen dësmontàbil',
@@ -999,19 +998,20 @@ Chiel a peul ancora s-ciairé costa diferensa; a peulo essje pì 'd detaj ant ë
 'revdelete-text' => "Le version scancelà e j'event a së s-ciaireran sempe ant la stòria dla pàgina e ant ij registr, ma sò test al pùblich a j'andrà pì nen.'''
 J'àutri aministrator dzora a {{SITENAME}} a saran ancó sempe bon a s-ciairé ël contnù stërmà e a podran disdëscancelelo andré con la midema antërfacia, sempe che a sia nen stàita butà na restrission adissional.",
 'revdelete-confirm' => "Për piasì, ch'a confema ch'a veul fé sòn, ch'as rend cont dle conseguense, e ch'a lo fa an acòrd con [[{{MediaWiki:Policy-url}}|le régole]].",
-'revdelete-suppress-text' => "La scancelassion a dovrìa '''mach''' esse dovrà për cost cas:
-* Anformassion përsonaj nen aproprià
+'revdelete-suppress-text' => "La scancelassion a dovrìa '''mach''' esse dovrà an costi cas:
+* Anformassion ch'a podrìo esse difamatòrie
+* Anformassion përsonaj inapropià
 *: ''adrësse ëd ca e nùmer ëd teléfon, còdes fiscaj, e via fòrt''",
 'revdelete-legend' => 'But-je coste limitassion-sì a le version scancelà:',
-'revdelete-hide-text' => 'Stërma ël test dla revision',
+'revdelete-hide-text' => 'Test dla revision',
 'revdelete-hide-image' => "Stërma ël contnù dl'archivi",
 'revdelete-hide-name' => 'Stërma assion e oget',
-'revdelete-hide-comment' => 'Stërma ël coment a la modìfica',
-'revdelete-hide-user' => "Stërma lë stranòm ò l'adrëssa IP dël contributor",
+'revdelete-hide-comment' => 'Resumé dla modìfica',
+'revdelete-hide-user' => "Stranòm/adrëssa IP dl'utent",
 'revdelete-hide-restricted' => "Stërmé j'anformassion a j'aministrator tan-me a j'àutri",
 'revdelete-radio-same' => '(cambia pa)',
-'revdelete-radio-set' => 'É!',
-'revdelete-radio-unset' => '',
+'revdelete-radio-set' => 'Stërmà',
+'revdelete-radio-unset' => 'Visìbil',
 'revdelete-suppress' => "Smon-je pa ij dat gnanca a j'aministrator",
 'revdelete-unsuppress' => "Gava le limitassion da 'nt le version ciapà andaré",
 'revdelete-log' => 'Rason:',
@@ -1166,8 +1166,7 @@ Ch'a preuva a gionté dnans a soa arserca ël prefiss ''all:'' për sërché an
 'preferences' => 'Mè gust',
 'mypreferences' => 'Gust',
 'prefs-edits' => 'Nùmer ëd modìfiche fàite:',
-'prefsnologin' => "A l'é ancó pa rintrà ant ël sistema",
-'prefsnologintext' => 'A deuv esse <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} intrà ant ël sistema]</span> për amposté ij sò gust.',
+'prefsnologintext2' => "Për piasì, ch'a $1 për definì ij gust d'utent.",
 'changepassword' => 'Cangé la ciav',
 'prefs-skin' => 'Facia',
 'skin-preview' => 'Preuva',
@@ -1469,6 +1468,9 @@ Costa anformassion a sarà pùblica.",
 'recentchanges-label-minor' => "Costa a l'é na modìfica cita",
 'recentchanges-label-bot' => "Sa modìfica a l'é stàita fàita da un trigomiro",
 'recentchanges-label-unpatrolled' => "Sta modìfica-sì a l'é pa ancó stàita verificà",
+'recentchanges-label-plusminus' => "La taja dla pàgina a l'é cangià d'un nùmer ëd bytes",
+'recentchanges-legend-newpage' => '(vëdde ëdcò [[Special:NewPages|lista dle pàgine neuve]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Ambelessì sota a-i {{PLURAL:$1|é '''1''' modìfica|son j'ùltime '''$1''' modìfiche}} ant j'ùltim {{PLURAL:$2|di|'''$2''' di}}, a parte da $5 dël $4.",
 'rcnotefrom' => ' Ambelessì sota a-i é la lista dle modìfiche da <b>$2</b> (fin-a a <b>$1</b>).',
 'rclistfrom' => 'Mostré le modìfiche a parte da $1',
@@ -2203,7 +2205,7 @@ Për contaté l\'editor:
 pòsta eletrònica: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-A-i sarà pì gnun-a notìfica ëd modìfiche se chiel a vìsita nen costa pàgina. Che as visa che a peul cangeje la configurassion dle notìfiche a le pàgine che as ten sot-euj ansima a soa lista dla ròba ch\'as ten sot-euj.
+A-i sarà pì gnun-a notìfica an cas d\'àutre atività se chiel a vìsita nen costa pàgina da colegà. Che as visa che a peul cangeje la configurassion dle notìfiche a le pàgine che as ten sot-euj ansima a soa lista dla ròba ch\'as ten sot-euj.
 
 Comunicassion dël sistema ëd notìfica da {{SITENAME}}
 
@@ -2726,7 +2728,7 @@ Se costa ùltima possibilità a fussa lòn che a-j serv, a podrìa ëdcò dovré
 'allmessagesdefault' => "Test che a-i sarìa se a-i fusso pa 'd modìfiche",
 'allmessagescurrent' => 'Test corent',
 'allmessagestext' => "Costa-sì a l'é na lista dij mëssagi ëd sistema disponìbij ant lë spassi nominal MediaWiki.
-Për piasì, ch'a vìsita la [//www.mediawiki.org/wiki/Localisation Localisassion ëd MediaWiki] e [//translatewiki.net translatewiki.net] se a veul contribuì a la localisassion general ëd MediaWiki.",
+Për piasì, ch'a vìsita la [https://www.mediawiki.org/wiki/Localisation Localisassion ëd MediaWiki] e [//translatewiki.net translatewiki.net] se a veul contribuì a la localisassion general ëd MediaWiki.",
 'allmessagesnotsupportedDB' => "Sta pàgina-sì a peul pa esse dovrà përchè '''\$wgUseDatabaseMessages''' a l'é stàit disabilità.",
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter' => 'Filtré për stat ëd përsonalisassion:',
@@ -2924,6 +2926,8 @@ Sòn a l'é motobin belfé che a sia rivà përchè a-i era n'anliura a un sit e
 'spam_reverting' => "Butà andaré a l'ùltima version che a l'avèissa pa andrinta dj'anliure a $1",
 'spam_blanking' => "Pàgina dësvujdà, che tute le version a l'avìo andrinta dj'anliure a $1",
 'spam_deleting' => 'Scancelà, dagià che tute le revision a contnisìo dle liure a $1',
+'simpleantispam-label' => "Contròl contra la rumenta.
+Compilé '''NEN''' sòn!",
 
 # Info page
 'pageinfo-title' => 'Anformassion për «$1»',
@@ -2937,6 +2941,7 @@ Sòn a l'é motobin belfé che a sia rivà përchè a-i era n'anliura a un sit e
 'pageinfo-length' => 'Longheur ëd la pàgina (an byte)',
 'pageinfo-article-id' => 'Identificativ ëd la pàgina',
 'pageinfo-language' => 'Lenga dël contnù dla pàgina',
+'pageinfo-content-model' => 'Model dël contnù ëd le pàgine',
 'pageinfo-robot-policy' => 'Indicisassion con robò',
 'pageinfo-robot-index' => 'Autorisà',
 'pageinfo-robot-noindex' => 'Vietà',
@@ -3017,7 +3022,7 @@ An fasend-lo marcé ansima a sò ordinator chiel a podrìa porteje ëd dann a s
 'svg-long-desc' => "archivi an forma SVG, amzure nominaj $1 × $2 pontin, amzura dl'archivi: $3",
 'svg-long-desc-animated' => "Archivi SVG animà, dimension $1 × $2 pontin, amzura dl'archivi: $3",
 'svg-long-error' => 'Archivi SVG nen bon: $1',
-'show-big-image' => 'Version a arzolussion pien-a',
+'show-big-image' => 'Archivi original',
 'show-big-image-preview' => 'Amzure dë sta preuva: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Àutra arzolussion|Àutre arzolussion}}: $1.',
 'show-big-image-size' => '$1 × $2 pontin',
@@ -3489,7 +3494,7 @@ J'àutri a saran stërmà coma stàndard.
 
 # External editor support
 'edit-externally' => "Modifiché st'archivi con un programa estern",
-'edit-externally-help' => "(Lese [//www.mediawiki.org/wiki/Manual:External_editors j'anstrussion d'anstalassion] për avèj pì d'anformassion)",
+'edit-externally-help' => "(Lese [https://www.mediawiki.org/wiki/Manual:External_editors j'anstrussion d'anstalassion] për avèj pì d'anformassion)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tute',
@@ -3590,6 +3595,9 @@ Për piasì, che an conferma che da bon a veul torna creélo.",
 'confirm-unwatch-button' => 'Va bin',
 'confirm-unwatch-top' => 'Gavé sta pàgina-sì da la lista dle ròbe che as ten-o sot euj?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '«$1»',
+
 # Multipage image navigation
 'imgmultipageprev' => '← pàgina andré',
 'imgmultipagenext' => 'pàgina anans →',
@@ -3695,7 +3703,7 @@ As peul ëdcò [[Special:EditWatchlist|dovré l'editor sòlit]].",
 'version-hook-subscribedby' => 'A son scrivusse',
 'version-version' => '(Version $1)',
 'version-license' => 'Licensa',
-'version-poweredby-credits' => "Costa wiki-sì a marcia mersì a '''[//www.mediawiki.org/ MediaWiki]''', licensa © 2001-$1 $2.",
+'version-poweredby-credits' => "Costa wiki-sì a marcia grassie a '''[https://www.mediawiki.org/ MediaWiki]''', licensa © 2001-$1 $2.",
 'version-poweredby-others' => 'àutri',
 'version-poweredby-translators' => 'tradutor ëd translatewiki.net',
 'version-credits-summary' => 'I tnoma a aringrassié le përson-e sì-dapress për soa contribussion a [[Special:Version|MediaWiki]].',
@@ -3715,7 +3723,7 @@ A dovrìa avèj arseivù [{{SERVER}}{{SCRIPTPATH}}/COPYING na còpia dla Licensa
 # Special:Redirect
 'redirect' => 'Ridirigiù da archivi, utent o ID ëd revision',
 'redirect-legend' => "Ridirige a n'archivi o na pàgina",
-'redirect-summary' => "Costa pàgina special a ponta a n'archivi (dàit un nòm d'archivi), na pàgina (dàita n'ID a la revision) o na pàgina d'utent (dàit n'identificativ numérich a l'utent).",
+'redirect-summary' => "Costa pàgina special a ponta a n'archivi (dàit ël nòm dl'archivi), na pàgina (dàita n'ID a la revision) o na pàgina d'utent (dàit n'identificativ numérich a l'utent). Usagi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Andé',
 'redirect-lookup' => 'Arserca:',
 'redirect-value' => 'Valor:',
@@ -3737,10 +3745,9 @@ A dovrìa avèj arseivù [{{SERVER}}{{SCRIPTPATH}}/COPYING na còpia dla Licensa
 
 # Special:SpecialPages
 'specialpages' => 'Pàgine Speciaj',
-'specialpages-note' => '----
-* Pàgine speciaj normaj.
-* <span class="mw-specialpagerestricted">Pàgine speciaj riservà.</span>
-* <span class="mw-specialpagecached">Pàgine speciaj mach an memòria local (a peulo esse veje).</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Pàgine speciaj normaj.
+* <span class="mw-specialpagerestricted">Pàgine speciaj riservà.</span>',
 'specialpages-group-maintenance' => 'Rapòrt ëd manutension',
 'specialpages-group-other' => 'Àutre pàgine speciaj',
 'specialpages-group-login' => 'Intré ant ël sistema / creé un cont',
@@ -3953,4 +3960,21 @@ Dësnò, a peul dovré ël formolari semplificà sì-sota. Sò coment a sarà gi
 'limitreport-expansiondepth' => "Pi granda përfondità d'espansion",
 'limitreport-expensivefunctioncount' => "Cont ëd le fonsion d'anàlisi care",
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Anàlisi djë stamp',
+'expand_templates_intro' => "Sta pàgina special-sì a pija dël test e a-i fa n'anàlisi arcorenta ëd tuti jë stamp ch'a l'ha andrinta.
+A l'analisa ëdcò le fonsion anterpretà coma
+<code><nowiki>{{</nowiki>#language:…}}</code>, e le variàbij coma
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+An efet, a espand praticament tut lòn ch'a-i é antrames dle grafe dobie.",
+'expand_templates_title' => 'Tìtol ëd contest për {{FULLPAGENAME}} e via fòrt:',
+'expand_templates_input' => 'Test da analisé:',
+'expand_templates_output' => 'Arzultà',
+'expand_templates_xml_output' => 'Output an XML',
+'expand_templates_ok' => 'Bin parèj',
+'expand_templates_remove_comments' => 'Gava via ij coment',
+'expand_templates_remove_nowiki' => "Gava ij tag <nowiki> ant l'arzultà",
+'expand_templates_generate_xml' => "Mosta l'erbo ëd parse XML",
+'expand_templates_preview' => 'Preuva',
+
 );
index 5af5a56..6dc3836 100644 (file)
@@ -276,8 +276,6 @@ $messages = array(
 'ok' => 'ٹھیک اے',
 'retrievedfrom' => '"$1" توں لیا',
 'youhavenewmessages' => 'تواڈے لئی $1 ($2).',
-'newmessageslink' => 'نواں سنیآ',
-'newmessagesdifflink' => 'آخری تبدیلی',
 'youhavenewmessagesmulti' => 'تھاڈے ل‏ی $1 تے نوں سنیعہ اے۔',
 'editsection' => 'لکھو',
 'editold' => 'لکھو',
@@ -1007,8 +1005,6 @@ $1",
 'preferences' => 'تانگاں',
 'mypreferences' => 'میریاں تانگاں',
 'prefs-edits' => 'تبدیلیاں دی گنتی:',
-'prefsnologin' => 'لاگ ان نئیں او',
-'prefsnologintext' => 'تسیں لازمی <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} لاگ ان]</span> ورتن تانگاں سیٹ کرنا.',
 'changepassword' => 'کنجی بدلو',
 'prefs-skin' => 'چھاڑ',
 'skin-preview' => 'کچا کم',
@@ -2478,7 +2474,7 @@ $1',
 'allmessagesdefault' => 'ڈیفالٹ لکھائی',
 'allmessagescurrent' => 'موجودہ لکھائی',
 'allmessagestext' => 'ایہ لسٹ اے پربندھ سنیعیاں دی  جیہڑے میڈیاوکی دی ناں تھاں تے ہیگے نیں۔
-مہربانی کرکے [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] تے [//translatewiki.net translatewiki.net] تے جاؤ۔
+مہربانی کرکے [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] تے [//translatewiki.net translatewiki.net] تے جاؤ۔
 اگر تسیں میڈیا وکی دے بولی وٹاندرے چ کم کرنا چاندے او۔',
 'allmessagesnotsupportedDB' => "اے صفہ نئیں ورتیا جاسکدا کیوں جے '''\$wgUseDatabaseMessages''' روک دتا گیا اے۔",
 'allmessages-filter-legend' => 'فلٹر',
@@ -2664,6 +2660,8 @@ $1',
 'spambot_username' => 'میڈیاوکی سپام سفائی',
 'spam_reverting' => 'آخری ریوین ول جیدے چ $1 دے جوڑ ناں ہون۔',
 'spam_blanking' => 'سارے ریوین جناں چ $1 نوں جوڑ نیں، طاف کیتا جاریا اے۔',
+'simpleantispam-label' => 'سپام روک پھاٹک
+ایدے تے ناں لکھو۔',
 
 # Info page
 'pageinfo-title' => '"$1" لئی جانکاری',
@@ -3160,7 +3158,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'بارلا سافٹ ویئر استعال کردے ہوۓ اے فائل لکھو',
-'edit-externally-help' => 'زیادہ معلومات آسطے اے [//www.mediawiki.org/wiki/Manual:External_editors] ویکھو۔',
+'edit-externally-help' => 'زیادہ معلومات آسطے اے [https://www.mediawiki.org/wiki/Manual:External_editors] ویکھو۔',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'سارے',
@@ -3343,7 +3341,7 @@ $5
 'version-hook-subscribedby' => 'جینے لئی',
 'version-version' => '(ورین $1)',
 'version-license' => 'لائیسنس',
-'version-poweredby-credits' => "ایس وکی نوں '''[//www.mediawiki.org/ میڈیاوکی]''', copyright © 2001-$1 $2. چلاندا اے۔",
+'version-poweredby-credits' => "ایس وکی نوں '''[https://www.mediawiki.org/ میڈیاوکی]''', copyright © 2001-$1 $2. چلاندا اے۔",
 'version-poweredby-others' => 'دوجے',
 'version-license-info' => 'میڈیاوکی اک مفت سوفٹویر اے؛ تسیں اینوں ونڈ سکدے اوہ تے گنو جنرل پبلک لسنس دیاں شرطاں تے جیہڑیاں فری سوفٹویر فاؤنڈیشن نے چھاپیاں نیں ایدے چ تبدیلی کرسکدے اوہ لسنس دے ورین 2 نال، یا اپنی مرضی نال کسے وی ہور ورین فیر بنن والے ورین نوں۔
 
@@ -3368,8 +3366,7 @@ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
 # Special:SpecialPages
 'specialpages' => 'خاص صفے',
-'specialpages-note' => '----
-* نارمل خاص صفے.
+'specialpages-note' => '* نارمل خاص صفے.
 * <span class="mw-specialpagerestricted">روکے گۓ خاص صفے.</span>
 * <span class="mw-specialpagecached">کاشے خاص صفے (پرانے ہوگۓ ہون).</span>',
 'specialpages-group-maintenance' => 'مرمت رپورٹ',
index ad44e5a..12dc82c 100644 (file)
@@ -260,8 +260,6 @@ $messages = array(
 'ok' => 'Εγέντον',
 'retrievedfrom' => 'Ασο "$1"',
 'youhavenewmessages' => 'Έχετε $1 ($2).',
-'newmessageslink' => 'καινούρεα μενέματα',
-'newmessagesdifflink' => 'υστερνόν αλλαγήν',
 'youhavenewmessagesmulti' => 'Έχετε καινούρεα μενέματα σο $1',
 'editsection' => 'άλλαξον',
 'editold' => 'άλλαξον',
@@ -1348,7 +1346,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => "Αλλαγήν τ' αρχείου με προγράμματα ασα εξ μερέα",
-'edit-externally-help' => '(Τερέστεν τα [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] και θα ευρίετε κι άλλα πληροφορίας)',
+'edit-externally-help' => '(Τερέστεν τα [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] και θα ευρίετε κι άλλα πληροφορίας)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ούλαι',
index ebbde80..d9db050 100644 (file)
@@ -251,8 +251,6 @@ Pāusai en kategōrijai "$1"',
 'ok' => 'Labbai',
 'retrievedfrom' => 'Aps: "$1"',
 'youhavenewmessages' => 'Tu turri $1 ($2)',
-'newmessageslink' => 'nāunans waīstins',
-'newmessagesdifflink' => 'Šlaitīntan ezze panzdaumai wersiōnin',
 'youhavenewmessagesmulti' => 'Tū turri nāunans waīstins ēn $1',
 'editsection' => 'redigīs',
 'editold' => 'redigīs',
@@ -827,7 +825,6 @@ Pamēnais, kāi tenēisan indicai mazzi ni būtwei aktuālin.',
 'preferences' => 'Pirminiskwas',
 'mypreferences' => 'Majjas pirminiskwas',
 'prefs-edits' => 'Kitawīdinsnan gīrbis:',
-'prefsnologin' => 'Ni assei engūbun',
 'changepassword' => 'Kitawīdinais kliptaswīrdan',
 'prefs-skin' => 'Prusna',
 'skin-preview' => 'Pirmādira',
@@ -1065,6 +1062,7 @@ Tū mazzi dīgi etrīnktun dātun kitēimans drāugautwei sen tin pra tērpautaj
 'recentchanges-label-minor' => 'Sta ast malks redigīsenis',
 'recentchanges-label-bot' => 'Sta ast redigīsenis segītan pra bōtan',
 'recentchanges-label-unpatrolled' => 'Šis redigīsenis ni ast dabber izbandātan',
+'recentchanges-legend-newpage' => '$1 - nāunan pāusan',
 'rcnote' => "Zemmais ast {{PLURAL:$1|'''1''' kitawīdinsna segīta|panzdaumas '''$1''' kitawīdinsnas segītas}} en panzdaumamans {{PLURAL:$2|dēinan|'''$2''' dēinans}}, gīrbawintei ezze $5, $4.",
 'rcnotefrom' => "Zemmais ast kitawīdisnas ezze '''$2''' (ērgi '''$1''' waidīntan).",
 'rclistfrom' => 'Waidinnais nāunans kitawīdinsnans pagaūnintei ezze $1',
@@ -1969,7 +1967,7 @@ Ni mazīngi praskajjintun pāusan en din subban.',
 'allmessagesdefault' => 'Auprestamins teksts',
 'allmessagescurrent' => 'Bigānts teksts',
 'allmessagestext' => 'Sta ast listi wisēisan waīstin preiēiminan en MediaWikis tītelin plattibin.
-Madli kāimalukeis [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] be [//translatewiki.net translatewiki.net] ik tu kwaitēi delīkan īmtun en MediaWikis prōgraminin tulkausnai.',
+Madli kāimalukeis [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] be [//translatewiki.net translatewiki.net] ik tu kwaitēi delīkan īmtun en MediaWikis prōgraminin tulkausnai.',
 'allmessagesnotsupportedDB' => "Šī pāusan ni mazzi būtwei tērpautan, beggi wariābli '''\$wgUseDatabaseMessages''' ast izklaūtan.",
 'allmessages-filter-legend' => 'Filtrīs',
 'allmessages-filter' => 'Filtrīs pa būsenin:',
@@ -2451,7 +2449,7 @@ Kitāi wīrst būwusis kliptan auprestaminai.
 
 # External editor support
 'edit-externally' => 'Redigīs šin pāusan tērpawintei izwinaīnan prōgraman',
-'edit-externally-help' => '(Skaitāis [//www.mediawiki.org/wiki/Manual:External_editors instrukciōnins], kāi gaūlai tūls infōrmaciōnins).',
+'edit-externally-help' => '(Skaitāis [https://www.mediawiki.org/wiki/Manual:External_editors instrukciōnins], kāi gaūlai tūls infōrmaciōnins).',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'wisāi',
@@ -2595,8 +2593,7 @@ Tu mazzi dīgi [[Special:EditWatchlist|tērpautun stāndardiskan editōran]].',
 
 # Special:SpecialPages
 'specialpages' => 'Speciālai pāusai',
-'specialpages-note' => '----
-* Nōrmalai speciālai pāusai.
+'specialpages-note' => '* Nōrmalai speciālai pāusai.
 * <strong class="mw-specialpagerestricted">Speciālai pāusai sen arāikintan preiēisenin.</strong>',
 'specialpages-group-maintenance' => 'Kōnserwaciōnis repōrtai',
 'specialpages-group-other' => 'Kitāi speciālai pāusai',
index 60bef83..0e61cd5 100644 (file)
@@ -375,7 +375,7 @@ $messages = array(
 'articlepage' => 'د مخ مېنځپانگه ښکاره کول',
 'talk' => 'خبرې اترې',
 'views' => 'کتنې',
-'toolbox' => 'اوزاربکس',
+'toolbox' => 'اوزارونه',
 'userpage' => 'د کارن پاڼه کتل',
 'projectpage' => 'د پروژې مخ کتل',
 'imagepage' => 'د دوتنې مخ کتل',
@@ -393,7 +393,7 @@ $messages = array(
 'jumpto' => 'ورټوپ کړه:',
 'jumptonavigation' => 'گرځښت',
 'jumptosearch' => 'پلټل',
-'view-pool-error' => 'اÙ\88بخÚ\9aÛ\8dØ\8c Ø¯Ù\85 Ú«ړۍ پالنگران د ډېر بارېدو ستونزې سره مخامخ شوي.
+'view-pool-error' => 'اÙ\88بخÚ\9aÛ\8dØ\8c Ø¯Ù\85 Ú¯ړۍ پالنگران د ډېر بارېدو ستونزې سره مخامخ شوي.
 ډېر زيات کارنان د همدې مخ د کتلو په هڅه کې دي.
 لطفاً د دې مخ د کتلو د بيا هڅې نه دمخه يو څو شېبې صبر وکړۍ.
 
@@ -431,12 +431,10 @@ $1',
 'ok' => 'ښه',
 'retrievedfrom' => '"$1" نه اخيستل شوی',
 'youhavenewmessages' => 'تاسې $1 لری  ($2).',
-'newmessageslink' => 'نوي پيغامونه',
-'newmessagesdifflink' => 'وروستی بدلون',
 'youhavenewmessagesfromusers' => 'تاسې د {{PLURAL:$3|يو بل کارن|$3 کارنانو}} لخوا $1 لرۍ ($2).',
 'youhavenewmessagesmanyusers' => 'تاسې د يو شمېر کارنانو لخوا $1 لرۍ ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|يو نوی پيغام|نوي پيغامونه}}',
-'newmessagesdifflinkplural' => 'وروستي {{PLURAL:$1|بدلون|بدلونونه}}',
+'newmessageslinkplural' => '{{PLURAL:$1|يو نوی پيغام|999=نوي پيغامونه}}',
+'newmessagesdifflinkplural' => 'تېر {{PLURAL:$1|بدلون|999=بدلونونه}}',
 'youhavenewmessagesmulti' => 'تاسې په $1 کې نوي پېغامونه لرۍ',
 'editsection' => 'سمول',
 'editold' => 'سمول',
@@ -593,7 +591,7 @@ $1',
 'createacct-emailoptional' => 'برېښليک پته (اختياري)',
 'createacct-email-ph' => 'برېښليک پته مو وټاپۍ',
 'createacct-another-email-ph' => 'برېښليک پته مو ورکړۍ',
-'createaccountmail' => 'يو لنډمهاله ناټاکلی پټنوم کارول او په لاندې ورکړل شوې برېښليک پته کې ورلېږل',
+'createaccountmail' => 'يو لنډمهاله ناټاکلی پټنوم کارول او ځانگړې شوې برېښليک پتې ته ورلېږل',
 'createacct-realname' => 'آر نوم (اختياري)',
 'createaccountreason' => 'سبب:',
 'createacct-reason' => 'سبب',
@@ -652,8 +650,8 @@ $1',
 'mailerror' => 'د برېښليک د لېږلو ستونزه: $1',
 'acct_creation_throttle_hit' => 'د همدې ويکي کارنانو په وروستيو ورځو کې ستاسې د IP پتې په کارولو سره {{PLURAL:$1|1 گڼون|$1 گڼونونه}} جوړ کړي، چې دا په همدې مودې کې د گڼونونو د جوړولو تر ټولو ډېر شمېر دی چې اجازه يې ورکړ شوې.
 نو په همدې خاطر د اوس لپاره د همدې IP پتې کارنان نه شي کولای چې نور گڼونونه جوړ کړي.',
-'emailauthenticated' => 'ستاسÛ\90 Ø¨Ø±Û\90Ú\9aÙ\84Ù\8aÚ© Ù¾ØªÙ\87 Ù¾Ù\87 $2 Ù\86Û\90Ù¼Ù\87 Ù¾Ù\87 $3 Ø¨Ø¬Ù\88 Ø¯ Ù\85Ù\86Ù\84Ù\88 Ù\88Ú\93 Ù\88گرÚ\81Û\90دÙ\87.',
-'emailnotauthenticated' => 'Ù\84ا ØªØ± Ø§Ù\88سÙ\87 Ø³ØªØ§Ø³Û\90 Ø¨Ø±Û\90Ú\9aÙ\84Ù\8aÚ© Ù¾ØªÙ\87 Ø¯ Ù\85Ù\86Ù\84Ù\88 Ù\88Ú\93 Ù\86Ù\87 Ø¯Ù\87 Ú«Ø±Ú\81Û\90دÙ\84Û\90. Ø¯ Ù\84اÙ\86دÛ\90 Ú\81اÙ\86Ú«ړتياو لپاره به تاسې ته هېڅ کوم برېښليک و نه لېږل شي.',
+'emailauthenticated' => 'ستاسې برېښليک پته په $2 په $3 بجو د منلو وړ وگرځېده.',
+'emailnotauthenticated' => 'Ù\84ا ØªØ± Ø§Ù\88سÙ\87 Ø³ØªØ§Ø³Û\90 Ø¨Ø±Û\90Ú\9aÙ\84Ù\8aÚ© Ù¾ØªÙ\87 Ø¯ Ù\85Ù\86Ù\84Ù\88 Ù\88Ú\93 Ù\86Ù\87 Ø¯Ù\87 Ú¯Ø±Ú\81Û\90دÙ\84Û\90. Ø¯ Ù\84اÙ\86دÛ\90 Ú\81اÙ\86Ú¯ړتياو لپاره به تاسې ته هېڅ کوم برېښليک و نه لېږل شي.',
 'noemailprefs' => 'ددې لپاره چې دا کړنې کار وکړي نو تاسو يو برېښليک وټاکۍ.',
 'emailconfirmlink' => 'د خپل د برېښليک پتې پخلی وکړی',
 'invalidemailaddress' => 'دا برېښليک پته نه منل کېږي، دا ځکه چې دا پته يوه ناکره بڼه لري.
@@ -669,7 +667,7 @@ $1',
 که چېرته دا کړنه په تېروتنه کې شوی وي نو تاسې کولای شی چې دا پيغام بابېزه وگڼۍ.',
 'usernamehasherror' => 'کارن-نوم نشي کېدلای چې کرښکې لوښې ولري',
 'login-throttled' => 'تاسې څو واره هڅه کړې چې غونډال ته ورننوځۍ.
-لطفاً د بيا هڅې نه مخکې يو څو شېبې تم شۍ.',
+لطفاً د بيا هڅې نه مخکې $1 شېبې تم شۍ.',
 'login-abort-generic' => 'غونډال کې مو ننوتل نابريالی شو - ناڅاپي بند شو',
 'loginlanguagelabel' => 'ژبه: $1',
 
@@ -683,8 +681,7 @@ $1',
 'newpassword' => 'نوی پټنوم:',
 'retypenew' => 'نوی پټنوم بيا وليکه:',
 'resetpass_submit' => 'پټنوم مو وټاکۍ او بيا غونډال ته ورننوځۍ',
-'changepassword-success' => 'ستاسې پټنوم په برياليتوب سره بدل شو!
-اوس غونډال کې د ورننوتلو په حال کې يو ...',
+'changepassword-success' => 'ستاسې پټنوم په برياليتوب سره بدل شو!',
 'resetpass_forbidden' => 'پټنومونه مو نه شي بدلېدلای',
 'resetpass-no-info' => 'دې مخ ته د لاسرسي لپاره بايد غونډال کې ورننوځۍ.',
 'resetpass-submit-loggedin' => 'پټنوم بدلول',
@@ -709,6 +706,7 @@ $1',
 # Special:ChangeEmail
 'changeemail' => 'برېښليک پته بدلول',
 'changeemail-header' => 'د گڼون برېښليک پته بدلول',
+'changeemail-text' => 'د برېښليک پتې بدلولو لپاره مو همدا فورمه ډکه کړۍ. د دې بدلون د تاييد لپاره بايد پټنوم مو ورکړۍ.',
 'changeemail-no-info' => 'دې مخ ته د لاسرسي لپاره بايد غونډال کې ورننوځۍ.',
 'changeemail-oldemail' => 'اوسنۍ برېښليک پته:',
 'changeemail-newemail' => 'نوې برېښليک پته:',
@@ -932,14 +930,14 @@ $1',
 'revdelete-show-file-submit' => 'هو',
 'revdelete-selected' => "'''د [[:$1]] {{PLURAL:$2|ټاکلې بڼه|ټاکلې بڼې}}:'''",
 'revdelete-legend' => 'د ښکارېدنې محدوديتونه ټاکل',
-'revdelete-hide-text' => 'د مخکتنې متن پټول',
+'revdelete-hide-text' => 'د مخکتنې متن',
 'revdelete-hide-image' => 'د دوتنې مېنځپانگه پټول',
 'revdelete-hide-name' => 'کړنه او موخه پټول',
-'revdelete-hide-comment' => 'د سمون لنډيز پټول',
-'revdelete-hide-user' => 'د سمونگر کارن-نوم/آی پي پته پټول',
+'revdelete-hide-comment' => 'د سمون لنډيز',
+'revdelete-hide-user' => 'د سمونگر کارن-نوم/آی پي پته',
 'revdelete-radio-same' => '(مه بدلوه)',
-'revdelete-radio-set' => 'Ù\87Ù\88',
-'revdelete-radio-unset' => 'نه',
+'revdelete-radio-set' => 'پټ',
+'revdelete-radio-unset' => 'ښکاره',
 'revdelete-log' => 'سبب:',
 'revdel-restore' => 'ښکارېدنه بدلول',
 'revdel-restore-deleted' => 'ړنګې شوې بڼې',
@@ -1042,8 +1040,6 @@ $1',
 'preferences' => 'غوره توبونه',
 'mypreferences' => 'غوره توبونه',
 'prefs-edits' => 'د سمونو شمېر:',
-'prefsnologin' => 'غونډال کې نه ياست ننوتي',
-'prefsnologintext' => 'د دې لپاره چې خپل غوره توبونه مو وټاکی، نو پکار ده چې لومړی تاسو غونډال کې <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ننوځی]</span>.',
 'changepassword' => 'پټنوم بدلول',
 'prefs-skin' => 'پوښۍ',
 'skin-preview' => 'مخکتنه',
@@ -1066,7 +1062,7 @@ $1',
 'prefs-rendering' => 'ښکارېدنه',
 'saveprefs' => 'خوندي کول',
 'resetprefs' => 'بيا سمول',
-'restoreprefs' => 'ټولې تلواليزې امستنې پرځای کول',
+'restoreprefs' => 'ټولې تلواليزې امستنې پرځای کول (په ټولو برخو کې)',
 'prefs-editing' => 'سمېدنې کې دی',
 'rows' => 'ليکې:',
 'columns' => 'ستنې:',
@@ -1115,7 +1111,7 @@ $1',
 'yournick' => 'کورنی نوم:',
 'badsiglength' => 'ستاسو لاسليک ډېر اوږد دی.
 بايد چې لاسليک مو له $1 {{PLURAL:$1|توري|تورو}} نه لږ وي.',
-'yourgender' => 'جنس:',
+'yourgender' => 'څنگه غواړۍ ځان څرگند کړۍ؟',
 'gender-unknown' => 'ناڅرگنده',
 'gender-male' => 'نارينه',
 'gender-female' => 'ښځينه',
@@ -1151,9 +1147,11 @@ $1',
 'userrights-lookup-user' => 'کارن ډلې سمبالول',
 'userrights-user-editname' => 'يو کارن نوم وليکۍ:',
 'editusergroup' => 'کارن ډلې سمول',
+'editinguser' => "د '''[[کارن:$1|$1]]''' کارن رښتې بدلول $2",
 'userrights-editusergroup' => 'کارن ډلې سمول',
 'saveusergroups' => 'کارن ډلې خوندي کول',
 'userrights-groupsmember' => 'غړی د:',
+'userrights-groupsmember-auto' => 'ضمني غړی د:',
 'userrights-groups-help' => 'تاسې هغه ډلې چې همدا کارن يې غړی دی بدلولی شی:
 * يو په نښه شوی بکس د دې مانا لري چې کارن د هغې ډلې غړيتوب لري.
 * يو نانښه شوی بکس د دې مانا لري چې کارن د هغې ډلې غړيتوب نلري.
@@ -1263,6 +1261,7 @@ $1',
 'recentchanges-label-minor' => 'دا يوه وړه سمونه ده',
 'recentchanges-label-bot' => 'دغه سمون د يو روباټ لخوا ترسره شوی',
 'recentchanges-label-unpatrolled' => 'دغه سمون تر اوسه پورې نه دی څارل شوی',
+'recentchanges-legend-newpage' => '(دا هم وگورۍ [[Special:NewPages|د نويو مخونو لړليک]])',
 'rcnote' => "دلته لاندې {{PLURAL:$1|وروستی '''1''' بدلون دی|وروستي '''$1''' بدلونونه دي}} چې په  {{PLURAL:$2| يوې ورځ|'''$2''' ورځو}} کې تر $4 نېټې او $5 بجو پېښ شوي.",
 'rcnotefrom' => "په همدې ځای کې لاندې هغه بدلونونه دي چې د '''$2''' نه راپدېخوا پېښ شوي (تر '''$1''' پورې ښکاره شوي).",
 'rclistfrom' => 'هغه نوي بدلونونه ښکاره کول چې له $1 نه پيلېږي',
@@ -1403,6 +1402,7 @@ $1',
 'upload_source_file' => '(ستاسو په کمپيوټر کې يوه دوتنه)',
 
 # Special:ListFiles
+'listfiles-summary' => 'همدا ځانگړی مخ ټولې پورته شوې دوتنې ښکاره کوي.',
 'listfiles_search_for' => 'د انځور د نوم لټون:',
 'imgfile' => 'دوتنه',
 'listfiles' => 'د دوتنو لړليک',
@@ -1413,6 +1413,8 @@ $1',
 'listfiles_size' => 'کچه (بايټونه)',
 'listfiles_description' => 'څرگندونه',
 'listfiles_count' => 'بڼې',
+'listfiles-latestversion-yes' => 'هو',
+'listfiles-latestversion-no' => 'نه',
 
 # File description page
 'file-anchor-link' => 'دوتنه',
@@ -1483,6 +1485,10 @@ $1',
 'randompage' => 'ناټاکلی مخ',
 'randompage-nopages' => 'په لانديني {{PLURAL:$2|نوم-تشيال|نوم-تشيالونو}} کې هېڅ کوم مخ نشته: $1.',
 
+# Random page in category
+'randomincategory-selectcategory' => 'يو ناټاکلی مخ له وېشنيزې موندل: $1 $2.',
+'randomincategory-selectcategory-submit' => 'ورځه',
+
 # Random redirect
 'randomredirect' => 'ناټاکلی ورگرځېدنه',
 
@@ -1563,6 +1569,7 @@ $1',
 'listusers' => 'کارن لړليک',
 'listusers-editsonly' => 'يوازې هغه کارنان چې سمونونه يې کړي ښکاره کول',
 'listusers-creationsort' => 'د جوړېدو د نېټې له مخې اوډل',
+'listusers-desc' => 'مخښکته اوډل',
 'usereditcount' => '{{PLURAL:$1|سمون|سمونونه}}',
 'usercreated' => 'په $1 نېټه په $2 بجو {{GENDER:$3|جوړ شو}}',
 'newpages' => 'نوي مخونه',
@@ -1684,10 +1691,10 @@ $1',
 'emailsubject' => 'سکالو:',
 'emailmessage' => 'پيغام:',
 'emailsend' => 'لېږل',
-'emailccme' => 'زÙ\85ا Ø¯ Ù¾Ù\8aغاÙ\85 Ù\8aÙ\88Ù\87 Ø¨Û\90Ù\84Ú«ه دې ماته هم برېښليک شي.',
+'emailccme' => 'زÙ\85ا Ø¯ Ù¾Ù\8aغاÙ\85 Ù\8aÙ\88Ù\87 Ø¨Û\90Ù\84Ú¯ه دې ماته هم برېښليک شي.',
 'emailccsubject' => '$1 ته ستاسو د پيغام لمېسه: $2',
 'emailsent' => 'برېښليک مو ولېږل شو',
-'emailsenttext' => 'ستاسو برېښليکي پيغام ولېږل شو.',
+'emailsenttext' => 'ستاسې برېښليکي پيغام ولېږل شو.',
 'emailuserfooter' => 'دا برېښليک د $1 لخوا $2 ته د {{SITENAME}} په وېبځي کې د "کارن ته برېښليک لېږل" د کړنې په مرسته لېږل شوی.',
 
 # User Messenger
@@ -1713,7 +1720,7 @@ $1',
 'unwatchthispage' => 'څارنې په ټپه درول',
 'notanarticle' => 'يو منځپانګيز مخ نه دی',
 'watchlist-details' => 'ستاسې کتنلړ کې {{PLURAL:$1|$1 مخ دی|$1 مخونه دي}}، د خبرو اترو مخونه مو پکې نه دي شمېرلي.',
-'wlheader-enotif' => 'د Ø¨Ø±Û\90Ú\9aÙ\84Ù\8aÚ© Ù\84Ù\87 Ù\84ارÛ\90 Ø®Ø¨Ø±Ù\88Ù\84 Ú\86ارÙ\86 Ø´Ù\88Û\8c.*',
+'wlheader-enotif' => 'برÛ\90Ú\9aÙ\84Ù\8aÚ© Ø®Ø¨Ø±Ù\88Ù\86Ù\87 Ú\86ارÙ\86Ù\87 Ø´Ù\88Û\90.',
 'wlheader-showupdated' => "هغه مخونه چې وروستی ځل ستاسو د کتلو نه وروسته بدلون موندلی په '''روڼ''' ليک نښه شوي.",
 'watchlistcontains' => 'ستاسې کتنلړ $1 {{PLURAL:$1|مخ|مخونه}} لري.',
 'iteminvalidname' => "د '$1' توکي سره ستونزه، ناسم نوم ...",
@@ -2092,7 +2099,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'allmessagesdefault' => 'تلواليزه پيغام متن',
 'allmessagescurrent' => 'اوسنی پيغام متن',
 'allmessagestext' => 'دا د مېډياويکي په نوم-تشيال کې د غونډال د پيغامونو لړليک دی.
-که چېرته تاسې د ميډياويکي په ځايتابه کې ونډې ترسره کول غواړۍ نو لطفاً [//www.mediawiki.org/wiki/Localisation د ميډياويکي ځايتابه] او [//translatewiki.net translatewiki.net] څخه ليدنه وکړۍ.',
+که چېرته تاسې د ميډياويکي په ځايتابه کې ونډې ترسره کول غواړۍ نو لطفاً [https://www.mediawiki.org/wiki/Localisation د ميډياويکي ځايتابه] او [//translatewiki.net translatewiki.net] څخه ليدنه وکړۍ.',
 'allmessagesnotsupportedDB' => "'''Special:Allmessages''' ترېنه کار نه اخيستل کېږي ځکه چې '''\$wgUseDatabaseMessages''' مړ دی.",
 'allmessages-filter-legend' => 'چاڼگر',
 'allmessages-filter-unmodified' => 'نابدلېدلي',
@@ -2327,10 +2334,10 @@ $1',
 'exif-copyright' => 'د رښتو خاوند',
 'exif-colorspace' => 'رنگ تشيال',
 'exif-pixelydimension' => 'د انځور سور',
-'exif-pixelxdimension' => 'د Ø§Ù\86Ú\81Ù\88ر Ø¬Ú«والی',
+'exif-pixelxdimension' => 'د Ø§Ù\86Ú\81Ù\88ر Ø¬Ú¯والی',
 'exif-usercomment' => 'د کارن تبصرې',
 'exif-relatedsoundfile' => 'اړونده غږيزه دوتنه',
-'exif-datetimedigitized' => 'د Ú«ڼياليز کېدنې وخت او نېټه',
+'exif-datetimedigitized' => 'د Ú¯ڼياليز کېدنې وخت او نېټه',
 'exif-fnumber' => 'F شمېره',
 'exif-lightsource' => 'د رڼا سرچينه',
 'exif-flash' => 'فلش',
@@ -2484,7 +2491,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'د باندنيو پروګرامونو په کارولو سره دا دوتنه سمول',
-'edit-externally-help' => 'د نورو مالوماتو لپاره [//www.mediawiki.org/wiki/Manual:External_editors د امستنو لارښوونې] وگورۍ.',
+'edit-externally-help' => 'د نورو مالوماتو لپاره [https://www.mediawiki.org/wiki/Manual:External_editors د امستنو لارښوونې] وگورۍ.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ټول',
@@ -2562,7 +2569,7 @@ $5
 # Size units
 'size-bytes' => '$1 بايټ',
 'size-kilobytes' => '$1 کيلوبايټ',
-'size-megabytes' => '$1 Ù\85Û\90Ú«ابايټ',
+'size-megabytes' => '$1 Ù\85Û\90Ú¯ابايټ',
 'size-gigabytes' => '$1 ګېګابايټ',
 'size-terabytes' => '$1 ټېرابايټ',
 'size-petabytes' => '$1 پېبي بايټ',
@@ -2643,7 +2650,7 @@ $5
 'version-other' => 'بل',
 'version-version' => '(بڼه $1)',
 'version-license' => 'منښتليک',
-'version-poweredby-credits' => "دا ويکي د '''[//www.mediawiki.org/ مېډياويکي]''' په سېک چلېږي، ټولې رښتې خوندي دي © 2001-$1 $2.",
+'version-poweredby-credits' => "دا ويکي د '''[https://www.mediawiki.org/ مېډياويکي]''' په سېک چلېږي، ټولې رښتې خوندي دي © 2001-$1 $2.",
 'version-poweredby-others' => 'نور',
 'version-license-info' => 'مېډياويکي يو وړيا ساوتری دی؛ تاسې يې په ډاډه زړه د GNU د ټولگړو کارېدنو د منښتليک چې د وړيا ساوتريو د بنسټ له مخې خپور شوی، خپرولی او/يا بدلولی شی؛ د منښتليک ۲ بڼه او يا (ستاسې د خوښې) هر يوه وروستۍ بڼه.
 
@@ -2665,8 +2672,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'ځانگړي مخونه',
-'specialpages-note' => '----
-* نورماله ځانگړي مخونه.
+'specialpages-note' => '* نورماله ځانگړي مخونه.
 * <strong class="mw-specialpagerestricted">محدوده ځانگړي مخونه.</strong>
 * <span class="mw-specialpagecached">رانيولي ځانگړي مخونه (کېدای شي منسوخ شوی وي).</span>',
 'specialpages-group-maintenance' => 'د څارنې راپورونه',
@@ -2780,4 +2786,11 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|پېړۍ|پېړۍ}}',
 'duration-millennia' => '$1 {{PLURAL:$1|زرمه|زرمې}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'کينډۍ غځول',
+'expand_templates_input' => 'ځايونکی متن:',
+'expand_templates_output' => 'پايله',
+'expand_templates_ok' => 'ښه',
+'expand_templates_preview' => 'مخکتنه',
+
 );
index 9a6ff9e..82575c6 100644 (file)
@@ -57,6 +57,7 @@
  * @author Teles
  * @author Urhixidur
  * @author Villate
+ * @author Vitorvicentevalente
  * @author Waldir
  * @author Yves Marques Junqueira
  * @author לערי ריינהארט
@@ -117,7 +118,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Título_inválido' ),
        'Blankpage'                 => array( 'Página_em_branco' ),
        'Block'                     => array( 'Bloquear', 'Bloquear_IP', 'Bloquear_utilizador', 'Bloquear_usuário' ),
-       'Blockme'                   => array( 'Bloquear-me', 'Auto-bloqueio' ),
        'Booksources'               => array( 'Fontes_de_livros' ),
        'BrokenRedirects'           => array( 'Redireccionamentos_quebrados', 'Redirecionamentos_quebrados' ),
        'Categories'                => array( 'Categorias' ),
@@ -128,10 +128,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Criar_conta' ),
        'Deadendpages'              => array( 'Páginas_sem_saída', 'Artigos_sem_saída' ),
        'DeletedContributions'      => array( 'Contribuições_eliminadas', 'Edições_eliminadas' ),
-       'Disambiguations'           => array( 'Desambiguações', 'Páginas_de_desambiguação', 'Desambiguar' ),
        'DoubleRedirects'           => array( 'Redireccionamentos_duplos', 'Redirecionamentos_duplos' ),
        'EditWatchlist'             => array( 'Editar_lista_de_páginas_vigiadas' ),
        'Emailuser'                 => array( 'Contactar_utilizador', 'Contactar_usuário', 'Contatar_usuário' ),
+       'ExpandTemplates'           => array( 'Expandir_predefinições' ),
        'Export'                    => array( 'Exportar' ),
        'Fewestrevisions'           => array( 'Páginas_com_menos_edições', 'Artigos_com_menos_edições', 'Artigos_menos_editados' ),
        'FileDuplicateSearch'       => array( 'Busca_de_ficheiros_duplicados', 'Busca_de_arquivos_duplicados' ),
@@ -192,8 +192,8 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'Predefinições_não_utilizadas', 'Predefinições_sem_uso' ),
        'Unwatchedpages'            => array( 'Páginas_não_vigiadas', 'Páginas_não-vigiadas', 'Artigos_não-vigiados', 'Artigos_não_vigiados' ),
        'Upload'                    => array( 'Carregar_imagem', 'Carregar_ficheiro', 'Carregar_arquivo', 'Enviar' ),
-       'Userlogin'                 => array( 'Entrar', 'Login' ),
-       'Userlogout'                => array( 'Sair', 'Logout' ),
+       'Userlogin'                 => array( 'Entrar' ),
+       'Userlogout'                => array( 'Sair' ),
        'Userrights'                => array( 'Privilégios', 'Direitos', 'Estatutos' ),
        'Version'                   => array( 'Versão', 'Sobre' ),
        'Wantedcategories'          => array( 'Categorias_pedidas', 'Categorias_em_falta', 'Categorias_inexistentes' ),
@@ -265,8 +265,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'centro', 'center', 'centre' ),
        'img_framed'                => array( '1', 'commoldura', 'comborda', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'semmoldura', 'semborda', 'frameless' ),
-       'img_page'                  => array( '1', 'página=$1', 'página $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'superiordireito', 'superiordireito=$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'página=$1', 'página_$1', 'página $1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'superiordireito', 'superiordireito=$1', 'superiordireito_$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'borda', 'border' ),
        'img_baseline'              => array( '1', 'linhadebase', 'baseline' ),
        'img_top'                   => array( '1', 'acima', 'top' ),
@@ -594,12 +594,10 @@ Consulte a página da [[Special:Version|versão do sistema]].',
 'ok' => 'OK',
 'retrievedfrom' => 'Obtida de "$1"',
 'youhavenewmessages' => 'Tem $1 ($2).',
-'newmessageslink' => 'mensagens novas',
-'newmessagesdifflink' => 'comparar com a penúltima revisão',
 'youhavenewmessagesfromusers' => 'Tem $1 de {{PLURAL:$3|outro utilizador|$3 utilizadores}} ($2).',
 'youhavenewmessagesmanyusers' => 'Tem $1 de muitos utilizadores ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|uma mensagem nova|mensagens novas}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|última alteração|últimas alterações}}',
+'newmessageslinkplural' => '{{PLURAL:$1|uma mensagem nova|999=mensagens novas}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|última alteração|999=últimas alterações}}',
 'youhavenewmessagesmulti' => 'Tem mensagens novas em $1',
 'editsection' => 'editar',
 'editold' => 'editar',
@@ -655,6 +653,7 @@ Encontra uma lista das páginas especiais válidas em [[Special:SpecialPages|{{i
 Isto pode indicar um defeito no programa.',
 'databaseerror-textcl' => 'Ocorreu um erro na consulta à base de dados.',
 'databaseerror-query' => 'Consulta:$1',
+'databaseerror-function' => 'Função: $1',
 'databaseerror-error' => 'Erro: $1',
 'laggedslavemode' => "'''Aviso:''' A página pode não conter as atualizações mais recentes.",
 'readonly' => 'Base de dados bloqueada (limitada a leituras)',
@@ -727,7 +726,8 @@ O administrador que efetuou o bloqueio deu a seguinte explicação: "$3".',
 'invalidtitle-knownnamespace' => 'Título inválido com o espaço nominal "$2" e texto "$3"',
 'invalidtitle-unknownnamespace' => 'Título inválido com número de espaço nominal $1 desconhecido e texto "$2"',
 'exception-nologin' => 'Não está autenticado',
-'exception-nologin-text' => 'Esta página ou operação requer que esteja autenticado nesta wiki.',
+'exception-nologin-text' => 'Por favor, [[Special:Userlogin|entre]] para poder acessar esta página ou acção.',
+'exception-nologin-text-manual' => 'Por favor  $1  para poder aceder a esta página ou acção.',
 
 # Virus scanner
 'virus-badscanner' => "Má configuração: antivírus desconhecido: ''$1''",
@@ -774,7 +774,7 @@ Não se esqueça de personalizar as suas [[Special:Preferences|preferências]].'
 'gotaccount' => "Já possui uma conta? '''$1'''.",
 'gotaccountlink' => 'Autentique-se',
 'userlogin-resetlink' => 'Esqueceu-se do seu nome de utilizador ou da palavra-chave?',
-'userlogin-resetpassword-link' => 'Recuperar palavra-chave',
+'userlogin-resetpassword-link' => 'Esqueceu a sua palavra-chave?',
 'helplogin-url' => 'Help:Autenticação',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ajuda a fazer login]]',
 'userlogin-loggedin' => 'Já está {{GENDER:$1|autenticado|autenticada|autenticado}} com o nome $1.
@@ -848,9 +848,9 @@ Para prevenir abusos, só um email de recuperação de palavra-chave pode ser en
 'mailerror' => 'Erro ao enviar correio: $1',
 'acct_creation_throttle_hit' => 'Visitantes desta wiki com o seu endereço IP criaram $1 {{PLURAL:$1|conta|contas}} no último dia, o que é o máximo permitido neste período de tempo.
 Em resultado, visitantes com este endereço IP não podem criar mais nenhuma conta neste momento.',
-'emailauthenticated' => 'O seu endereço de correio electrónico foi autenticado a $2 às $3.',
-'emailnotauthenticated' => 'O seu endereço de correio electrónico ainda não foi autenticado.
-Não serão enviados correios de nenhuma das seguintes funcionalidades.',
+'emailauthenticated' => 'O seu endereço de correio electrónico foi confirmado a $2, às $3.',
+'emailnotauthenticated' => 'O seu endereço de correio electrónico ainda não foi confirmado.
+Não serão enviados emails de nenhuma das seguintes funcionalidades.',
 'noemailprefs' => 'Especifique um endereço de correio eletrónico nas suas preferências para ativar estas funcionalidades.',
 'emailconfirmlink' => 'Confirme o seu endereço de correio electrónico',
 'invalidemailaddress' => 'O endereço de correio eletrónico não pode ser aceite porque parece ter um formato inválido.
@@ -1299,17 +1299,17 @@ Outros administradores da {{SITENAME}} continuarão a poder aceder ao conteúdo
 'revdelete-suppress-text' => "A supressão '''só''' deverá ser usada nos seguintes casos:
 * Informação potencialmente caluniosa, difamatória ou injuriosa
 * Informação pessoal imprópria
-*: ''endereços de domicílio e números de telefone, números da segurança social, etc''",
+*: ''endereços de domicílio e números de telefone, números de identificação nacional, etc''",
 'revdelete-legend' => 'Definir restrições de visibilidade',
-'revdelete-hide-text' => 'Ocultar texto da edição',
+'revdelete-hide-text' => 'Revisão do texto',
 'revdelete-hide-image' => 'Ocultar conteúdo do ficheiro',
 'revdelete-hide-name' => 'Ocultar operação e destino',
-'revdelete-hide-comment' => 'Ocultar resumo da edição',
-'revdelete-hide-user' => 'Ocultar nome de utilizador/IP',
+'revdelete-hide-comment' => 'Resumo da edição',
+'revdelete-hide-user' => 'Nome de utilizador/endereço de IP',
 'revdelete-hide-restricted' => 'Ocultar dados dos administradores e de todos os outros',
 'revdelete-radio-same' => '(manter)',
-'revdelete-radio-set' => 'Sim',
-'revdelete-radio-unset' => 'Não',
+'revdelete-radio-set' => 'Escondido',
+'revdelete-radio-unset' => 'Visível',
 'revdelete-suppress' => 'Ocultar dados dos administradores e de todos os outros',
 'revdelete-unsuppress' => 'Remover restrições das revisões restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1468,8 +1468,7 @@ Note, no entanto, que a indexação da {{SITENAME}} neste motor de busca pode es
 'preferences' => 'Preferências',
 'mypreferences' => 'Preferências',
 'prefs-edits' => 'Número de edições:',
-'prefsnologin' => 'Não autenticado',
-'prefsnologintext' => 'Precisa de estar <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} autenticado]</span> para definir as suas preferências.',
+'prefsnologintext2' => 'Por favor, precisa de $1 para definir as suas preferências.',
 'changepassword' => 'Alterar palavra-chave',
 'prefs-skin' => 'Tema',
 'skin-preview' => 'Antever tema',
@@ -1573,6 +1572,7 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'prefs-dateformat' => 'Formato de data',
 'prefs-timeoffset' => 'Desvio horário',
 'prefs-advancedediting' => 'Opções gerais',
+'prefs-editor' => 'Editor',
 'prefs-preview' => 'Antevisão',
 'prefs-advancedrc' => 'Opções avançadas',
 'prefs-advancedrendering' => 'Opções avançadas',
@@ -1583,6 +1583,7 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'prefs-displaywatchlist' => 'Opções de apresentação',
 'prefs-tokenwatchlist' => 'Chave',
 'prefs-diffs' => 'Diferenças',
+'prefs-help-prefershttps' => 'Esta preferência terá efeito no seu próximo início de sessão.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Parece válido',
@@ -1609,7 +1610,7 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'userrights-notallowed' => 'A sua conta não tem permissão para adicionar ou remover privilégios a utilizadores.',
 'userrights-changeable-col' => 'Grupos que pode alterar',
 'userrights-unchangeable-col' => 'Grupos que não pode alterar',
-'userrights-conflict' => 'Conflito com os privilégios dos utilizadores! Por favor, aplique as suas mudanças novamente.',
+'userrights-conflict' => 'Conflito entre alterações de privilégios de utilizador! Por favor, revise e confirme as suas mudanças.',
 'userrights-removed-self' => 'Você removeu com sucesso os seus privilégios. Como resultado disso, já não consegue aceder a esta página.',
 
 # Groups
@@ -1677,12 +1678,18 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'right-unblockself' => 'Desbloquearem-se a si próprios',
 'right-protect' => 'Mudar níveis de proteção e editar páginas protegidas em cascata',
 'right-editprotected' => 'Editar páginas protegidas como "{{int:protect-level-sysop}}"',
+'right-editsemiprotected' => 'Editar páginas protegidas como "{{int:protect-level-autoconfirmed}}"',
 'right-editinterface' => 'Editar a interface de utilizador',
 'right-editusercssjs' => 'Editar os ficheiros CSS e JS de outros utilizadores',
 'right-editusercss' => 'Editar os ficheiros CSS de outros utilizadores',
 'right-edituserjs' => 'Editar os ficheiros JS de outros utilizadores',
 'right-editmyusercss' => 'Editar os seus próprios ficheiros CSS de utilizador',
 'right-editmyuserjs' => 'Editar os seus próprios ficheiros JavaScript de utilizador',
+'right-viewmywatchlist' => 'Ver sua própria lista de páginas vigiadas',
+'right-editmywatchlist' => 'Editar sua própria lista de páginas vigiadas. Observe que algumas ações seguirão adicionando páginas, mesmo sem este direito.',
+'right-viewmyprivateinfo' => 'Ver os seus próprios dados privados (ex.: endereço de e-mail, nome real)',
+'right-editmyprivateinfo' => 'Editar os seus próprios dados privados (ex.: endereço de e-mail, nome real)',
+'right-editmyoptions' => 'Editar as suas próprias preferências',
 'right-rollback' => 'Reverter rapidamente as edições do último utilizador que editou uma página em particular',
 'right-markbotedits' => 'Marcar edições revertidas como edições de bot',
 'right-noratelimit' => 'Não ser afetado pelos limites de velocidade de operação',
@@ -1734,8 +1741,8 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'action-block' => 'impedir este utilizador de editar',
 'action-protect' => 'alterar os níveis de proteção desta página',
 'action-rollback' => 'reverter rapidamente as edições do último utilizador que editou uma dada página',
-'action-import' => 'importar esta página a partir de outra wiki',
-'action-importupload' => 'importar esta página a partir de um ficheiro xml',
+'action-import' => 'importar páginas a partir de outra wiki',
+'action-importupload' => 'importar páginas por meio do envio de um ficheiro',
 'action-patrol' => 'marcar as edições de outros utilizadores como patrulhadas',
 'action-autopatrol' => 'marcar como patrulhadas as suas próprias edições',
 'action-unwatchedpages' => 'ver a lista de páginas não-vigiadas',
@@ -1744,9 +1751,15 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'action-userrights-interwiki' => 'editar privilégios de utilizadores de outras wikis',
 'action-siteadmin' => 'bloquear ou desbloquear a base de dados',
 'action-sendemail' => 'enviar e-mails',
+'action-editmywatchlist' => 'Editar sua lista de páginas vigiadas',
+'action-viewmywatchlist' => 'Ver sua lista de páginas vigiadas',
+'action-viewmyprivateinfo' => 'Ver sua informação privada',
+'action-editmyprivateinfo' => 'Editar sua informação privada',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|alteração|alterações}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|desde a última visita}}',
+'enhancedrc-history' => 'histórico',
 'recentchanges' => 'Mudanças recentes',
 'recentchanges-legend' => 'Opções das mudanças recentes',
 'recentchanges-summary' => 'Acompanhe nesta página as mudanças mais recentes da wiki.',
@@ -1756,6 +1769,7 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'recentchanges-label-minor' => 'Esta é uma edição menor',
 'recentchanges-label-bot' => 'Esta edição foi feita por um robô',
 'recentchanges-label-unpatrolled' => 'Esta edição ainda não foi patrulhada',
+'recentchanges-legend-newpage' => '(ver também a [[Special:NewPages|lista de páginas novas]])',
 'rcnote' => "A seguir {{PLURAL:$1|está listada '''uma''' alteração ocorrida|estão listadas '''$1''' alterações ocorridas}} {{PLURAL:$2|no último dia|nos últimos '''$2''' dias}}, a partir das $5 de $4.",
 'rcnotefrom' => 'Abaixo estão as mudanças desde <b>$2</b> (mostradas até <b>$1</b>).',
 'rclistfrom' => 'Mostrar as novas mudanças a partir das $1',
@@ -2063,6 +2077,8 @@ Verifique se o endereço está correto e o site disponível, por favor.',
 'listfiles_description' => 'Descrição',
 'listfiles_count' => 'Versões',
 'listfiles-show-all' => 'Incluir versões antigas de imagens',
+'listfiles-latestversion' => 'Versão atual',
+'listfiles-latestversion-yes' => 'Sim',
 'listfiles-latestversion-no' => 'Não',
 
 # File description page
@@ -2160,6 +2176,7 @@ Talvez queira editar a descrição na [$2 página original de descrição do fic
 
 # Random page in category
 'randomincategory-nopages' => 'Não há páginas na categoria [[:Category:$1|$1]].',
+'randomincategory-selectcategory' => 'Obter página aleatória da categoria: $1 $2',
 'randomincategory-selectcategory-submit' => 'Ir',
 
 # Random redirect
@@ -2192,8 +2209,8 @@ Talvez queira editar a descrição na [$2 página original de descrição do fic
 'pageswithprop-text' => 'Esta página lista páginas que usam uma propriedade em particular.',
 'pageswithprop-prop' => 'Nome da propriedade:',
 'pageswithprop-submit' => 'Avançar',
-'pageswithprop-prophidden-long' => 'foi ocultado o valor da propriedade por ser um texto muito longo ($1 kilobytes)',
-'pageswithprop-prophidden-binary' => 'foi ocultado o valor da propriedade por ser binário ($1 kilobytes)',
+'pageswithprop-prophidden-long' => 'foi ocultado o valor da propriedade por ser um texto muito longo ($1)',
+'pageswithprop-prophidden-binary' => 'foi ocultado o valor da propriedade por ser binário ($1)',
 
 'doubleredirects' => 'Redirecionamentos duplos',
 'doubleredirectstext' => 'Esta página lista todas as páginas que redirecionam para outras páginas de redirecionamento.
@@ -2268,6 +2285,7 @@ Agora redirecciona para [[$2]].',
 'listusers' => 'Utilizadores',
 'listusers-editsonly' => 'Mostrar apenas utilizadores com edições',
 'listusers-creationsort' => 'Ordenar por data de criação',
+'listusers-desc' => 'Ordenar de forma decrescente',
 'usereditcount' => '$1 {{PLURAL:$1|edição|edições}}',
 'usercreated' => '{{GENDER:$3|Criado|Criada}} em $1 às $2',
 'newpages' => 'Páginas recentes',
@@ -2484,16 +2502,16 @@ $PAGEINTRO $NEWPAGE
 Resumo da edição: $PAGESUMMARY $PAGEMINOREDIT
 
 Contacte o editor:
-correio eletrónico: $PAGEEDITOR_EMAIL
+correio electrónico: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Até que visite esta página, não receberá mais notificações das alterações futuras.
-Pode também reativar as notificações para todas páginas na sua lista de páginas vigiadas.
+Até que visite novamente esta página com a sua conta ligada, não receberá mais notificações das alterações futuras.
+Pode também reactivar as notificações para todas páginas na sua lista de páginas vigiadas.
 
-             O seu sistema de notificação amigável da {{SITENAME}}
+O seu sistema de notificação amigável da {{SITENAME}}
 
 --
-Para alterar as suas preferências das notificações por correio eletrónico, visite
+Para alterar as suas preferências das notificações por correio electrónico, visite
 {{canonicalurl:{{#special:Preferences}}}}
 
 Para alterar as suas preferências das páginas vigiadas, visite
@@ -3008,7 +3026,7 @@ Se desejar, pode utilizar um link (por exemplo, [[{{#Special:Export}}/{{MediaWik
 'allmessagesdefault' => 'Texto padrão',
 'allmessagescurrent' => 'Texto atual',
 'allmessagestext' => 'Esta é a lista das mensagens de sistema disponíveis no espaço nominal MediaWiki.
-Se deseja colaborar na localização genérica do MediaWiki, visite [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e a [//translatewiki.net translatewiki.net].',
+Se deseja colaborar na localização genérica do MediaWiki, visite [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e a [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => "Esta página não pode ser utilizada, uma vez que '''\$wgUseDatabaseMessages''' foi desativado.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar pelo estado de personalização:',
@@ -3215,6 +3233,8 @@ Este bloqueio foi provavelmente causado por um link para um site externo que con
 'spam_reverting' => 'A reverter para a última revisão que não contém links para $1',
 'spam_blanking' => 'Todas as revisões continham links para $1; a esvaziar',
 'spam_deleting' => 'Todas as revisões continham links para $1; a eliminar',
+'simpleantispam-label' => "Verificação contra spam
+'''NÃO''' preencha isto!",
 
 # Info page
 'pageinfo-title' => 'Informações sobre "$1"',
@@ -3314,7 +3334,7 @@ Executá-lo poderá comprometer a segurança do seu sistema.",
 'svg-long-desc' => 'ficheiro SVG, de $1 × $2 pixels, tamanho: $3',
 'svg-long-desc-animated' => 'ficheiro SVG animado, de $1 × $2 pixels, tamanho: $3',
 'svg-long-error' => 'Ficheiro SVG inválido: $1',
-'show-big-image' => 'Resolução completa',
+'show-big-image' => 'Arquivo original',
 'show-big-image-preview' => 'Tamanho desta antevisão: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Outra resolução|Outras resoluções}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3781,7 +3801,7 @@ Caso o ficheiro tenha sido modificado a partir do seu estado original, alguns de
 
 # External editor support
 'edit-externally' => 'Editar este ficheiro utilizando uma aplicação externa',
-'edit-externally-help' => '(Consulte as [//www.mediawiki.org/wiki/Manual:External_editors instruções de instalação] para mais informações)',
+'edit-externally-help' => '(Consulte as [https://www.mediawiki.org/wiki/Manual:External_editors instruções de instalação] para mais informações)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todas',
@@ -3974,7 +3994,7 @@ Também pode [[Special:EditWatchlist|editar a lista da maneira convencional]].',
 'version-hook-subscribedby' => 'Subscrito por',
 'version-version' => '(Versão $1)',
 'version-license' => 'Licença',
-'version-poweredby-credits' => "Esta é uma wiki '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Esta é uma wiki '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'outros',
 'version-credits-summary' => 'Gostaríamos de reconhecer as seguintes pessoas pela sua contribuição para o [[Special:Version|MediaWiki]].',
 'version-license-info' => 'O MediaWiki é software livre; pode redistribuí-lo e/ou modificá-lo nos termos da licença GNU General Public License, tal como publicada pela Free Software Foundation; tanto a versão 2 da Licença, como (por opção sua) qualquer versão posterior.
@@ -3992,7 +4012,7 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 # Special:Redirect
 'redirect' => 'Redirecionar pelo ID do ficheiro, utilizador ou revisão',
 'redirect-legend' => 'Redirecionar para um ficheiro ou página',
-'redirect-summary' => 'Esta página especial redireciona a um ficheiro (dado o nome do ficheiro), a uma página (dado um ID de revisão) ou a uma página de utilizador (dado o ID do utilizador).',
+'redirect-summary' => 'Esta página especial redireciona a um ficheiro (dado o nome do ficheiro), a uma página (dado um ID de revisão) ou a uma página de utilizador (dado o ID do utilizador). Utilização: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] ou [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Ir',
 'redirect-lookup' => 'Pesquisa:',
 'redirect-value' => 'Valor:',
@@ -4014,8 +4034,8 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 
 # Special:SpecialPages
 'specialpages' => 'Páginas especiais',
-'specialpages-note' => '----
-* Páginas especiais normais.
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Páginas especiais normais.
 * <span class="mw-specialpagerestricted">Páginas especiais restritas.</span>',
 'specialpages-group-maintenance' => 'Relatórios de manutenção',
 'specialpages-group-other' => 'Outras páginas especiais',
@@ -4056,6 +4076,8 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 'tags-description-header' => 'Descrição completa do significado',
 'tags-active-header' => 'Ativa?',
 'tags-hitcount-header' => 'Modificações etiquetadas',
+'tags-active-yes' => 'Sim',
+'tags-active-no' => 'Não',
 'tags-edit' => 'editar',
 'tags-hitcount' => '$1 {{PLURAL:$1|modificação|modificações}}',
 
@@ -4076,6 +4098,7 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 'dberr-problems' => 'Desculpe! Este site está com dificuldades técnicas.',
 'dberr-again' => 'Experimente esperar alguns minutos e atualizar.',
 'dberr-info' => '(Não foi possível contactar o servidor da base de dados: $1)',
+'dberr-info-hidden' => '(Não foi possível contactar o servidor de base de dados)',
 'dberr-usegoogle' => 'Pode tentar pesquisar no Google entretanto.',
 'dberr-outofdate' => 'Note que os seus índices relativos ao nosso conteúdo podem estar desatualizados.',
 'dberr-cachederror' => 'A seguinte página é uma cópia em cache da página pedida e pode não estar atualizada.',
@@ -4212,9 +4235,28 @@ Caso contrário, pode facilmente usar o formulário abaixo. O seu comentário se
 'rotate-comment' => 'Imagem rodada em $1 {{PLURAL:$1|grau|graus}} no sentido dos ponteiros do relógio',
 
 # Limit report
+'limitreport-title' => 'Dados de perfis do analisador:',
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|segundo|segundos}}',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|segundo|segundos}}',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|byte|bytes}}',
 'limitreport-templateargumentsize' => 'Tamanho dos argumentos da predefinição',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|byte|bytes}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandir predefinições',
+'expand_templates_intro' => "Esta página especial recebe um texto e expande recursivamente todas as predefinições nele existentes.
+Também expande funções do analisador sintático ''(parser)'', tais como
+<nowiki>{{</nowiki>#language:...}}, e variáveis, tais como
+<nowiki>{{</nowiki>CURRENTDAY}}.
+De fato, expande tudo o que estiver entre chaves duplas.",
+'expand_templates_title' => 'Título de contexto para {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Texto a expandir:',
+'expand_templates_output' => 'Resultado',
+'expand_templates_xml_output' => 'Resultado XML',
+'expand_templates_ok' => 'Expandir',
+'expand_templates_remove_comments' => 'Remover comentários',
+'expand_templates_remove_nowiki' => "Suprimir ''tags'' <nowiki> no resultado",
+'expand_templates_generate_xml' => 'Mostrar a árvore de análise sintáctica do XML',
+'expand_templates_preview' => 'Antevisão do resultado',
+
 );
index d60517a..fb60915 100644 (file)
@@ -61,6 +61,7 @@
  * @author Sir Lestaty de Lioncourt
  * @author Teles
  * @author TheGabrielZaum
+ * @author Titoncio
  * @author Urhixidur
  * @author Vivaelcelta
  * @author Vuln
@@ -123,7 +124,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Título_inválido' ),
        'Blankpage'                 => array( 'Página_em_branco' ),
        'Block'                     => array( 'Bloquear', 'Bloquear_IP', 'Bloquear_utilizador', 'Bloquear_usuário' ),
-       'Blockme'                   => array( 'Bloquear-me', 'Auto-bloqueio' ),
        'Booksources'               => array( 'Fontes_de_livros' ),
        'BrokenRedirects'           => array( 'Redirecionamentos_quebrados' ),
        'Categories'                => array( 'Categorias' ),
@@ -134,7 +134,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Criar_conta' ),
        'Deadendpages'              => array( 'Páginas_sem_saída', 'Artigos_sem_saída' ),
        'DeletedContributions'      => array( 'Contribuições_eliminadas', 'Edições_eliminadas' ),
-       'Disambiguations'           => array( 'Páginas_de_desambiguação', 'Desambiguar', 'Desambiguações' ),
        'DoubleRedirects'           => array( 'Redirecionamentos_duplos' ),
        'EditWatchlist'             => array( 'Editar_lista_de_páginas_vigiadas' ),
        'Emailuser'                 => array( 'Contatar_usuário', 'Contactar_usuário', 'Contactar_utilizador' ),
@@ -198,8 +197,8 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'Predefinições_sem_uso', 'Predefinições_não_utilizadas' ),
        'Unwatchedpages'            => array( 'Páginas_não-vigiadas', 'Páginas_não_vigiadas', 'Artigos_não-vigiados', 'Artigos_não_vigiados' ),
        'Upload'                    => array( 'Carregar_arquivo', 'Carregar_imagem', 'Carregar_ficheiro', 'Enviar' ),
-       'Userlogin'                 => array( 'Autenticar-se', 'Entrar', 'Login' ),
-       'Userlogout'                => array( 'Sair', 'Logout' ),
+       'Userlogin'                 => array( 'Autenticar-se', 'Entrar' ),
+       'Userlogout'                => array( 'Sair' ),
        'Userrights'                => array( 'Privilégios', 'Direitos', 'Estatutos' ),
        'Version'                   => array( 'Versão', 'Sobre' ),
        'Wantedcategories'          => array( 'Categorias_pedidas', 'Categorias_em_falta', 'Categorias_inexistentes' ),
@@ -271,8 +270,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'centro', 'center', 'centre' ),
        'img_framed'                => array( '1', 'commoldura', 'comborda', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'semmoldura', 'semborda', 'frameless' ),
-       'img_page'                  => array( '1', 'página=$1', 'página $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'superiordireito', 'superiordireito=$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'página=$1', 'página_$1', 'página $1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'superiordireito', 'superiordireito=$1', 'superiordireito_$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'borda', 'border' ),
        'img_baseline'              => array( '1', 'linhadebase', 'baseline' ),
        'img_top'                   => array( '1', 'acima', 'top' ),
@@ -336,7 +335,7 @@ $messages = array(
 'tog-usenewrc' => 'Agrupar alterações por páginas nas mudanças recentes e nas páginas vigiadas',
 'tog-numberheadings' => 'Auto-numerar cabeçalhos',
 'tog-showtoolbar' => 'Mostrar barra de ferramentas de edição',
-'tog-editondblclick' => 'Editar páginas quando houver clique duplo (requer JavaScript)',
+'tog-editondblclick' => 'Editar páginas quando houver clique duplo',
 'tog-editsection' => 'Ativar a edição de seções com links [editar]',
 'tog-editsectiononrightclick' => 'Habilitar edição de seção por clique com o botão direito no título da seção (requer JavaScript)',
 'tog-showtoc' => 'Mostrar Tabela de Conteúdos (para páginas com mais de três cabeçalhos)',
@@ -601,8 +600,6 @@ Veja a [[Special:Version|página sobre a versão do sistema]].',
 'ok' => 'OK',
 'retrievedfrom' => 'Disponível em "$1"',
 'youhavenewmessages' => 'Você tem $1 ($2).',
-'newmessageslink' => 'novas mensagens',
-'newmessagesdifflink' => 'última alteração',
 'youhavenewmessagesfromusers' => 'Você tem $1 de {{PLURAL:$3|outro usuário|$3 usuários}} ($2)',
 'youhavenewmessagesmanyusers' => 'Você tem $1 de muitos usuários ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|uma mensagem nova|mensagens novas}}',
@@ -786,7 +783,7 @@ Não se esqueça de personalizar as suas [[Special:Preferences|preferências no
 'gotaccount' => "Já possui uma conta? '''$1'''.",
 'gotaccountlink' => 'Autenticar-se',
 'userlogin-resetlink' => 'Esqueceu-se do seu nome de usuário ou da senha?',
-'userlogin-resetpassword-link' => 'Troque sua senha',
+'userlogin-resetpassword-link' => 'Esqueceu sua senha?',
 'helplogin-url' => 'Help:Iniciar sessão',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ajuda para iniciar sessão]]',
 'userlogin-loggedin' => 'Você já está conectado como {{GENDER:$1|$1}}.
@@ -1299,12 +1296,12 @@ Outros administradores no {{SITENAME}} continuarão podendo acessar ao conteúdo
 'revdelete-hide-text' => 'Ocultar texto da edição',
 'revdelete-hide-image' => 'Ocultar conteúdos do arquivo',
 'revdelete-hide-name' => 'Ocultar ação e alvo',
-'revdelete-hide-comment' => 'Ocultar o sumário de edição',
-'revdelete-hide-user' => 'Ocultar nome de usuário/IP do editor',
+'revdelete-hide-comment' => 'Sumário de edição',
+'revdelete-hide-user' => 'Nome de usuário/endereço IP',
 'revdelete-hide-restricted' => 'Suprimir dados de administradores assim como de outros',
 'revdelete-radio-same' => '(não alterar)',
-'revdelete-radio-set' => 'Sim',
-'revdelete-radio-unset' => 'Não',
+'revdelete-radio-set' => 'Oculto',
+'revdelete-radio-unset' => 'Visível',
 'revdelete-suppress' => 'Suprimir dados de administradores, bem como de outros',
 'revdelete-unsuppress' => 'Remover restrições das edições restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1461,8 +1458,6 @@ Note que os índices do sistema de busca externo poderão conter referências de
 'preferences' => 'Preferências',
 'mypreferences' => 'Preferências',
 'prefs-edits' => 'Número de edições:',
-'prefsnologin' => 'Não autenticado',
-'prefsnologintext' => 'É necessário estar <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} autenticado]</span> para definir as suas preferências.',
 'changepassword' => 'Alterar senha',
 'prefs-skin' => 'Tema',
 'skin-preview' => 'Pré-visualização',
@@ -1761,6 +1756,7 @@ Caso decida fornecê-lo, este será utilizado para dar-lhe crédito pelo seu tra
 'recentchanges-label-minor' => 'Esta é uma edição menor',
 'recentchanges-label-bot' => 'Esta edição foi feita por um robô',
 'recentchanges-label-unpatrolled' => 'Esta edição ainda não foi patrulhada',
+'recentchanges-legend-newpage' => '$1 - nova página',
 'rcnote' => "A seguir {{PLURAL:$1|está listada '''uma''' alteração ocorrida|estão listadas '''$1''' alterações ocorridas}} {{PLURAL:$2|no último dia|nos últimos '''$2''' dias}}, a partir das $5 de $4.",
 'rcnotefrom' => "Seguem as alterações desde as '''$4''' de '''$3''' (limitadas a '''$1''').",
 'rclistfrom' => 'Mostrar as novas alterações a partir das $1',
@@ -3013,7 +3009,7 @@ Para o último caso, é possível obter o XML a partir de um link direto (por ex
 'allmessagesdefault' => 'Texto padrão',
 'allmessagescurrent' => 'Texto atual',
 'allmessagestext' => 'Esta é uma lista de todas as mensagens de sistema disponíveis no espaço nominal {{ns:mediawiki}}.
-Acesse [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] caso deseje contribuir para traduções do MediaWiki feitas para uso geral.',
+Acesse [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] caso deseje contribuir para traduções do MediaWiki feitas para uso geral.',
 'allmessagesnotsupportedDB' => "Esta página não pode ser utilizada, uma vez que '''\$wgUseDatabaseMessages''' foi desativado.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtrar por estado de personalização:',
@@ -3212,6 +3208,8 @@ Tal bloqueio foi provavelmente causado por uma ligação para um ''website'' ext
 'spam_reverting' => 'Revertendo para a última versão que não contém links para $1',
 'spam_blanking' => 'Todas revisões contendo links para $1, limpando',
 'spam_deleting' => 'Eliminada por todas as suas edições conterem links para $1',
+'simpleantispam-label' => "Verificação contra spam
+'''NÃO''' preencha isto!",
 
 # Info page
 'pageinfo-title' => 'Informações sobre "$1"',
@@ -3778,7 +3776,7 @@ Por padrão, outros campos estarão ocultos.
 
 # External editor support
 'edit-externally' => 'Editar este arquivo a partir de um programa externo',
-'edit-externally-help' => '(Consulte as [//www.mediawiki.org/wiki/Manual:External_editors instruções de instalação] para maiores informações)',
+'edit-externally-help' => '(Consulte as [https://www.mediawiki.org/wiki/Manual:External_editors instruções de instalação] para maiores informações)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todas',
@@ -3967,7 +3965,7 @@ Você também pode [[Special:EditWatchlist|editar a lista da maneira convenciona
 'version-hook-subscribedby' => 'Subscrito por',
 'version-version' => '(Versão $1)',
 'version-license' => 'Licença',
-'version-poweredby-credits' => "Este é um wiki '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Este é um wiki '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'outros',
 'version-poweredby-translators' => 'tradutores da translatewiki.net',
 'version-credits-summary' => 'Gostaríamos de agradecer às seguintes pessoas por suas contribuições no [[Special:Version|MediaWiki]]',
@@ -4008,8 +4006,7 @@ Em conjunto com este programa deve ter recebido [{{SERVER}}{{SCRIPTPATH}}/COPYIN
 
 # Special:SpecialPages
 'specialpages' => 'Páginas especiais',
-'specialpages-note' => '----
-* Páginas especiais normais.
+'specialpages-note' => '* Páginas especiais normais.
 * <span class="mw-specialpagerestricted">Páginas especiais restritas.</span>',
 'specialpages-group-maintenance' => 'Relatórios de manutenção',
 'specialpages-group-other' => 'Outras páginas especiais',
@@ -4223,4 +4220,21 @@ Caso contrário, você poderá usar o formulário simplificado a seguir. Seu com
 'limitreport-expansiondepth' => 'Máxima profundidade de expansão',
 'limitreport-expensivefunctioncount' => 'Conta da função expansiva do analizador',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandir predefinições',
+'expand_templates_intro' => 'Esta página especial pega algum texto e expande todas as predefinições nela existentes recursivamente. 
+Também expande funções do analisador (parser) como 
+<code><nowiki>{{</nowiki>#language:…}}</code>, e variáveis como 
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Na verdade, expande tudo que está entre chaves duplas.',
+'expand_templates_title' => 'Título de contexto para {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Texto de entrada:',
+'expand_templates_output' => 'Resultado',
+'expand_templates_xml_output' => 'Resultado XML',
+'expand_templates_ok' => 'Expandir',
+'expand_templates_remove_comments' => 'Remover comentários',
+'expand_templates_remove_nowiki' => 'Suprima marcações <nowiki> no resultado',
+'expand_templates_generate_xml' => 'Mostrar árvore de análise (parse) do XML',
+'expand_templates_preview' => 'Pré-visualização',
+
 );
index bbe797c..9367717 100644 (file)
@@ -70,6 +70,7 @@
  * @author Lejonel
  * @author Li-sung
  * @author Liangent
+ * @author Liuxinyu970226
  * @author Lloffiwr
  * @author MF-Warburg
  * @author Malafaya
  * @author SPQRobin
  * @author Sanbec
  * @author Sborsody
+ * @author Scimonster
  * @author Se4598
  * @author Seb35
  * @author Sherbrooke
@@ -426,8 +428,6 @@ The pagination links in category viewer. Parameters:
 * $1 - the previous link, uses {{msg-mw|Prevn}}
 * $2 - the next link, uses {{msg-mw|Nextn}}',
 
-'linkprefix' => '{{optional}}',
-
 'about' => '{{Identical|About}}',
 'article' => "A 'content page' is a page that forms part of the purpose of the wiki. It includes the main page and pages in the main namespace and any other namespaces that are included when the wiki is customised. For example on Wikimedia Commons 'content pages' include pages in the file and category namespaces. On Wikinews 'content pages' include pages in the Portal namespace. For technical definition of 'content namespaces' see [[mw:Manual:Using_custom_namespaces#Content_namespaces|MediaWiki]].
 
@@ -484,7 +484,8 @@ This can also appear in the credits page if the credits feature is enabled,for e
 'qbmyoptions' => 'Heading in the Cologne Blue skin user menu containing links to user (talk) page, preferences, watchlist, etc.
 {{Identical|My pages}}',
 'qbspecialpages' => '{{Identical|Special page}}',
-'faq' => "FAQ is short for ''frequently asked questions''.",
+'faq' => "FAQ is short for ''frequently asked questions''.
+{{Identical|FAQ}}",
 'faqpage' => '{{doc-important|Do not translate <code>Project:</code> part.}}
 "FAQ" is short for "frequently asked questions".
 
@@ -813,32 +814,21 @@ Parameters:
 ** {{msg-mw|Sp-contributions-newbies-title}}",
 'pagetitle-view-mainpage' => '{{optional}}',
 'backlinksubtitle' => '{{optional}}
-Appears in subtitle
-* $1 is a link to the page (HTML)',
+Appears in subtitle. Parameters:
+* $1 - a link to the page (HTML)',
 'retrievedfrom' => 'Message which appears in the source of every page, but it is hidden. It is shown when printing.
 
 Parameters:
 * $1 - a link back to the current page: {{FULLURL:{{FULLPAGENAME}}}}',
 'youhavenewmessages' => 'The yellow message appearing when someone edited your user talk page.
 
-The format is: "{{int:youhavenewmessages| [[MediaWiki:Newmessageslink/{{SUBPAGENAME}}|{{int:newmessageslink}}]] |[[MediaWiki:Newmessagesdifflink/{{SUBPAGENAME}}|{{int:newmessagesdifflink}}]]}}"
+The format is: "{{int:youhavenewmessages| [[MediaWiki:Newmessageslinkplural/{{SUBPAGENAME}}|{{int:newmessageslinkplural}}]] |[[MediaWiki:Newmessagesdifflinkplural/{{SUBPAGENAME}}|{{int:newmessagesdifflinkplural}}]]}}"
 
 Parameters:
-* $1 - a link points to new messages. Its text is {{msg-mw|Newmessageslink}}
-* $2 - a link points to new messages diff. Its text is {{msg-mw|Newmessagesdifflink}}
+* $1 - a link points to new messages. Its text is {{msg-mw|Newmessageslinkplural}}
+* $2 - a link points to new messages diff. Its text is {{msg-mw|Newmessagesdifflinkplural}}
 See also:
 * {{msg-mw|Youhavenewmessagesmanyusers}}',
-'newmessageslink' => 'This is the first link displayed in an orange rectangle when a user gets a message on their talk page.
-
-Used as <code>$1</code> in message {{msg-mw|Youhavenewmessages}}.
-{{Identical|New messages}}',
-'newmessagesdifflink' => 'This is the second link displayed in an orange rectangle when a user gets a message on his talk page.
-
-Used as <code>$2</code> in message {{msg-mw|Youhavenewmessages}}.
-
-See also:
-* {{msg-mw|Newmessagesdifflinkplural}}
-{{Identical|Last change}}',
 'youhavenewmessagesfromusers' => 'New talk indicator message: the message appearing when someone edited your user talk page. Parameters:
 * $1 - defined as {{msg-mw|newmessageslinkplural}}
 * $2 - defined as {{msg-mw|newmessagesdifflinkplural}}
@@ -852,28 +842,30 @@ Parameters:
 * $2 - {{msg-mw|newmessagesdifflinkplural}}
 See also:
 * {{msg-mw|Youhavenewmessages}}',
-'newmessageslinkplural' => "Like {{msg-mw|Newmessageslink}} but supporting pluralization.
+'newmessageslinkplural' => "This is the first link displayed in an orange rectangle when a user gets a message on their talk page.
 
-Used as <code>$1</code> in {{msg-mw|Youhavenewmessagesfromusers}}.
+Used as <code>$1</code> in messages {{msg-mw|youhavenewmessagesfromusers}}, {{msg-mw|youhavenewmessagesmanyusers}}, {{msg-mw|youhavenewmessages}}.
 
 Parameters:
-* $1 - 1 or 2:
+* $1 - 1 or 999:
 ** 1 - if there was '''one''' new edit since the last time the user has seen their talk page
-** 2 - if there was '''more than one''' new edit since the last time the user has seen their talk page
+** 999 - if there was '''more than one''' new edit since the last time the user has seen their talk page
 {{Identical|New messages}}",
-'newmessagesdifflinkplural' => 'Parameters:
-* $1 - the number of new edits since the last time the user has seen their talk page: it should be used only for correct [[plural]] as in the source text, as the exact number is not relevant.
+'newmessagesdifflinkplural' => "This is the second link displayed in an orange rectangle when a user gets a message on his talk page.
 
-Like {{msg-mw|Newmessagesdifflink}} but supporting pluralization.
+Used as <code>$2</code> in messages {{msg-mw|youhavenewmessagesfromusers}}, {{msg-mw|youhavenewmessagesmanyusers}}, {{msg-mw|youhavenewmessages}}.
 
-Used as <code>$2</code> in message {{msg-mw|Youhavenewmessagesfromusers}}.
-{{Identical|Last change}}',
+Parameters:
+* $1 - 1 or 999:
+** 1 - if there was '''one''' new edit since the last time the user has seen their talk page
+** 999 - if there was '''more than one''' new edit since the last time the user has seen their talk page
+{{Identical|Last change}}",
 'youhavenewmessagesmulti' => 'The alternative of {{msg-mw|youhavenewmessages}} as used on wikis with a special setup so they can receive the "new message" notice on other wikis as well. Used on [http://www.wikia.com/ Wikia].
 
-The format is: "{{int:youhavenewmessagesmulti| [[MediaWiki:Newmessageslink/{{SUBPAGENAME}}|{{int:newmessageslink}}]]}}"
+The format is: "{{int:youhavenewmessagesmulti| [[MediaWiki:Newmessageslinkplural/{{SUBPAGENAME}}|{{int:newmessageslinkplural}}]]}}"
 
 Parameters:
-* $1 - a link points to new messages. Its text is {{msg-mw|Newmessageslink}}',
+* $1 - a link points to new messages. Its text is {{msg-mw|Newmessageslinkplural}}',
 'editsection' => 'Display name of link to edit a section on a content page. Example: [{{MediaWiki:Editsection}}].
 
 {{Identical|Edit}}',
@@ -1223,6 +1215,10 @@ Parameters:
 'exception-nologin' => 'Generic page title used on error page when a user is not logged in. Message used by the UserNotLoggedIn exception.
 {{Identical|Not logged in}}',
 'exception-nologin-text' => 'Generic reason displayed on error page when a user is not logged in. Message used by the UserNotLoggedIn exception.',
+'exception-nologin-text-manual' => 'Generic reason displayed on error page when a user is not logged in.
+
+Parameters:
+* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description',
 
 # Virus scanner
 'virus-badscanner' => 'Used as error message. Parameters:
@@ -1343,7 +1339,8 @@ The link points to the local [[Special:PasswordReset]].
 
 See example: [[Special:UserLogin]]
 
-userlogin-resetpassword-link may have to be shorter than the old {{msg-mw|userlogin-resetlink}}',
+userlogin-resetpassword-link may have to be shorter than the old {{msg-mw|userlogin-resetlink}}.
+{{Identical|Forgot your password}}',
 'helplogin-url' => '{{doc-important|Do not translate the namespace name <code>Help</code>.}}
 Used as name of the page that provides information about logging into the wiki.
 
@@ -1442,7 +1439,7 @@ Parameters:
 {{Identical|Login error}}',
 'createacct-error' => 'Used as heading for the error message.',
 'createaccounterror' => 'Parameters:
-* $1 is an error message',
+* $1 - an error message',
 'nocookiesnew' => "This message is displayed when a new account was successfully created, but the browser doesn't accept cookies.",
 'nocookieslogin' => "This message is displayed when someone tried to login, but the browser doesn't accept cookies.",
 'nocookiesfornew' => "This message is displayed when the user tried to create a new account, but it failed the cross-site request forgery (CSRF) check. It could be blocking an attack, but most likely, the browser isn't  accepting cookies.",
@@ -1486,7 +1483,8 @@ Parameters:
 * $1 - the minimum number of characters in the password',
 'password-name-match' => 'Used as error message when password validity check failed.',
 'password-login-forbidden' => 'Error message shown when the user has tried to log in using one of the special username/password combinations used for MediaWiki testing. (See [[mwr:75589]], [[mwr:75605]].)',
-'mailmypassword' => 'Heading in [[Special:PasswordReset]]',
+'mailmypassword' => 'Used as label for Submit button in [[Special:PasswordReset]].
+{{Identical|Reset password}}',
 'passwordremindertitle' => 'Title of email which contains temporary password',
 'passwordremindertext' => 'This text is used in an email sent when a user requests a new temporary password (he has forgotten his password) or when an sysop creates a new user account choosing to have password and username sent to the new user by email.
 
@@ -1523,7 +1521,7 @@ Parameters:
 * $3 - time',
 'emailnotauthenticated' => 'Message in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.
 
-It appears after saving your email address but before it has been authenticated.',
+It appears after saving your email address but before you confirm it.',
 'noemailprefs' => 'Message appearing in the "Email options" section of the "User profile" page in [[Special:Preferences|Preferences]], when no user email address has been entered.',
 'emailconfirmlink' => 'Link to [[Special:ConfirmEmail]].
 
@@ -1845,7 +1843,7 @@ See also:
 * {{msg-mw|cantcreateaccount-text}}.
 {{Identical|No reason given}}',
 'whitelistedittext' => 'Used as error message. Parameters:
-* $1 is a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description
+* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description
 See also:
 * {{msg-mw|Nocreatetext}}
 * {{msg-mw|Uploadnologintext}}
@@ -1901,8 +1899,10 @@ Parameters:
 
 Parameters:
 * $1 - a possible username that has not been registered',
-'userpage-userdoesnotexist-view' => 'Shown in user pages of non existing users. See for example [{{canonicalurl:User:Foo}} User:Foo]. Parameters:
-* $1 is a username.',
+'userpage-userdoesnotexist-view' => 'Shown in user pages of non existing users. See for example [{{canonicalurl:User:Foo}} User:Foo].
+
+Parameters:
+* $1 - a username',
 'blocked-notice-logextract' => '{{gender}}
 Parameters:
 * $1 - (Optional) the name of the blocked user. Can be used for GENDER.',
@@ -2026,7 +2026,7 @@ See also:
 Parameters:
 * \$1 - number of categories",
 'edittools' => '{{optional}}
-This text will be shown below edit and upload forms. It can be used to offer special characters not present on most keyboards for copying/pasting, and also often makes them clickable for insertion via a javascript. Since these are seen as specific to a wiki, however, this message should not contain anything but an html comment explaining how it should be used once the wiki has been installed.',
+This text will be shown below edit and upload forms. It can be used to offer special characters not present on most keyboards for copying/pasting, and also often makes them clickable for insertion via a JavaScript. Since these are seen as specific to a wiki, however, this message should not contain anything but an html comment explaining how it should be used once the wiki has been installed.',
 'edittools-upload' => '{{optional}}
 This text will be shown below upload forms. It will default to the contents of edittools.',
 'nocreatetext' => 'Used as error message.
@@ -2048,7 +2048,9 @@ See also:
 * {{msg-mw|loginreqtitle}}
 {{Identical|Permission error}}',
 'permissionserrorstext' => "This message is \"without action\" version of {{msg-mw|Permissionserrorstext-withaction}}.
-* \$1 is the number of reasons that were found why ''the action'' cannot be performed.",
+
+Parameters:
+* \$1 - the number of reasons that were found why ''the action'' cannot be performed",
 'permissionserrorstext-withaction' => 'This message is "with action" version of {{msg-mw|Permissionserrorstext}}.
 
 Parameters:
@@ -2143,8 +2145,10 @@ This message is substituted in:
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => 'On some (expensive) [[MetaWikipedia:Help:ParserFunctions|parser functions]] (e.g. <code><nowiki>{{#ifexist:}}</nowiki></code>) there is a limit of how many times it may be used. This is an error message shown when the limit is exceeded.
-* $1 is the current number of parser function calls.
-* $2 is the allowed number of parser function calls.
+
+Parameters:
+* $1 - the current number of parser function calls
+* $2 - the allowed number of parser function calls
 See also [[:mw:Manual:$wgExpensiveParserFunctionLimit|$wgExpensiveParserFunctionLimit in the MediaWiki manual]].
 
 See also:
@@ -2259,10 +2263,14 @@ See the error message:
 * {{msg-mw|history-feed-empty}}',
 'currentrev' => 'Used in Diff Preview page. The diff is between {{msg-mw|currentrev}} and {{msg-mw|yourtext}}.
 {{Identical|Current revision}}',
-'currentrev-asof' => 'Used on a difference page when comparing the current versions of a page with each other. See {{msg-mw|Revisionasof}} for the message for non-current version.
-* $1 is a date and time
-* $2 is a date (optional)
-* $3 is a time (optional)',
+'currentrev-asof' => 'Used on a difference page when comparing the current versions of a page with each other.
+
+See {{msg-mw|Revisionasof}} for the message for non-current version.
+
+Parameters:
+* $1 - a date and time
+* $2 - (Optional) a date
+* $3 - (Optional) a time',
 'revisionasof' => 'Used on a difference page when comparing different versions of a page or when viewing an non-current version of a page.
 
 See {{msg-mw|Currentrev-asof}} for the message for the current version.
@@ -2448,14 +2456,14 @@ There are three radio buttons in each row, and the captions above each column re
 * {{msg-mw|Revdelete-radio-same}}
 * {{msg-mw|Revdelete-radio-set}}
 * {{msg-mw|Revdelete-radio-unset}}
-{{Identical|Yes}}',
+{{Identical|Hidden}}',
 'revdelete-radio-unset' => 'This message is a part of the [[mw:RevisionDelete|RevisionDelete]] feature. The message is a caption for a column of radioboxes inside a box with {{msg-mw|Revdelete-legend}} as a title.
 [[File:RevDelete Special-RevisionDelete (r60428).png|frame|center|Screenshot of the interface]]
 There are three radio buttons in each row, and the captions above each column read:
 * {{msg-mw|Revdelete-radio-same}}
 * {{msg-mw|Revdelete-radio-set}}
 * {{msg-mw|Revdelete-radio-unset}}
-{{Identical|No}}',
+{{Identical|Visible}}',
 'revdelete-suppress' => 'Option for oversight; used in [[Special:RevisionDelete]].
 
 See also:
@@ -2509,30 +2517,37 @@ Links to page history at Special:RevisionDelete header together with links to th
 Links to [[Special:Undelete]] at [[Special:RevisionDelete]] header together with links to the logs and page history.',
 'revdelete-hide-current' => '{{RevisionDelete}}
 Parameters:
-* $1 is a date
-* $2 is a time',
+* $1 - a date
+* $2 - a time
+{{Related|Revdelete}}',
 'revdelete-show-no-access' => '{{RevisionDelete}}
 Parameters:
-* $1 is a date
-* $2 is a time',
+* $1 - a date
+* $2 - a time
+{{Related|Revdelete}}',
 'revdelete-modify-no-access' => '{{RevisionDelete}}
 Parameters:
-* $1 is a date
-* $2 is a time',
+* $1 - a date
+* $2 - a time
+{{Related|Revdelete}}',
 'revdelete-modify-missing' => '{{RevisionDelete}}
-* $1 is a revision ID',
+* $1 - a revision ID
+{{Related|Revdelete}}',
 'revdelete-no-change' => '{{RevisionDelete}}
 Parameters:
-* $1 is a date
-* $2 is a time',
+* $1 - a date
+* $2 - a time
+{{Related|Revdelete}}',
 'revdelete-concurrent-change' => '{{RevisionDelete}}
 Parameters:
-* $1 is a date
-* $2 is a time',
+* $1 - a date
+* $2 - a time
+{{Related|Revdelete}}',
 'revdelete-only-restricted' => '{{RevisionDelete}}
 Parameters:
 *$1 - date
-*$2 - time',
+*$2 - time
+{{Related|Revdelete}}',
 'revdelete-reason-dropdown' => '{{RevisionDelete}}
 Used as item list for dropdown.
 [[File:RevDelete Special-RevisionDelete (r60428).png|frame|center|Screenshot of the interface]]
@@ -2746,8 +2761,9 @@ See also:
 
 Example: [{{canonicalurl:Project:News|diff=426850&oldid=99999999}} Diff with invalid revision#]
 
-* $1 is the list of missing revisions IDs
-* $2 is the number of items in $1 (one or two)',
+Parameters:
+* $1 - the list of missing revisions IDs
+* $2 - the number of items in $1 (one or two)',
 
 # Search results
 'searchresults' => 'This is the title of the page that contains the results of a search.
@@ -2948,8 +2964,8 @@ See also:
 In this sentence, "their indexes" refers to "Google\'s indexes".
 
 Shown on [[Special:Search]] when the internal search is disabled.',
-'search-error' => 'Shown when an error has occurred when performing a search
-* $1 is the localized error that was returned',
+'search-error' => 'Shown when an error has occurred when performing a search. Parameters:
+* $1 - the localized error that was returned',
 
 # Preferences page
 'preferences' => 'Title of the [[Special:Preferences]] page.
@@ -2962,9 +2978,8 @@ See also:
 * {{msg-mw|Tooltip-pt-preferences}}
 {{Identical|Preferences}}',
 'prefs-edits' => 'In user preferences.',
-'prefsnologin' => '{{Identical|Not logged in}}',
-'prefsnologintext' => 'Parameters:
-* $1 - URI for "returnto" argument',
+'prefsnologintext2' => 'Parameters:
+* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description',
 'changepassword' => "Section heading on [[Special:Preferences]], tab 'User profile'.
 {{Identical|Change password}}",
 'prefs-skin' => 'Used in user preferences.
@@ -3014,7 +3029,8 @@ See also:
 * {{msg-mw|prefs-help-email-others|help}}
 * {{msg-mw|prefs-changeemail|link title}}',
 'prefs-email' => 'Used as section name in [[Special:Preferences]].',
-'prefs-rendering' => 'Title of tab in [[Special:Preferences]].',
+'prefs-rendering' => 'Title of tab in [[Special:Preferences]].
+{{Identical|Appearance}}',
 'saveprefs' => 'Button for saving changes in the preferences page.
 
 See also:
@@ -3031,7 +3047,8 @@ When changing this message, please also update {{msg-mw|vector-editwarning-warni
 {{Identical|Editing}}',
 'rows' => 'Used on [[Special:Preferences]], "Editing" section in the "Size of editing window" fieldset.
 {{Identical|Row}}',
-'columns' => 'Used on [[Special:Preferences]], "Editing" section in the "Size of editing window" fieldset',
+'columns' => 'Used on [[Special:Preferences]], "Editing" section in the "Size of editing window" fieldset.
+{{Identical|Column}}',
 'searchresultshead' => 'This is the label of the tab in [[Special:Preferences|my preferences]] which contains options for searching the wiki.
 
 {{Identical|Search}}',
@@ -3113,8 +3130,8 @@ See also:
 * {{msg-mw|Prefs-memberingroups-type}}',
 'prefs-memberingroups-type' => '{{optional}}
 Parameters:
-* $1 is list of group names
-* $2 is list of group member names. Label for these is {{msg-mw|prefs-memberingroups}}.',
+* $1 - list of group names
+* $2 - list of group member names. Label for these is {{msg-mw|Prefs-memberingroups}}',
 'prefs-registration' => 'Used in [[Special:Preferences]].',
 'prefs-registration-date-time' => '{{optional}}
 Used in [[Special:Preferences]]. Parameters are:
@@ -3266,8 +3283,8 @@ Parameters:
 * $2 - (Optional) the user name, for GENDER',
 'userrights-groupsmember-type' => '{{optional}}
 Parameters:
-* $1 is list of group names.
-* $2 is list of group member names. Used with labels {{msg-mw|userrights-groupsmember}} and {{msg-mw|userrights-groupsmember-auto}}',
+* $1 - list of group names
+* $2 - list of group member names. Used with labels {{msg-mw|Userrights-groupsmember}} and {{msg-mw|Userrights-groupsmember-auto}}',
 'userrights-groups-help' => 'Instructions displayed on [[Special:UserRights]]. Parameters:
 * $1 - (Optional) a username, can be used for GENDER',
 'userrights-reason' => 'Text beside log field when editing user groups
@@ -3588,10 +3605,18 @@ See also:
 'recentchanges-summary' => 'Summary of [[Special:RecentChanges]].',
 'recentchanges-noresult' => 'Used in [[Special:RecentChanges]], [[Special:RecentChangesLinked]], and [[Special:Watchlist]] when there are no changes to be shown.',
 'recentchanges-feed-description' => 'Used in feed of RecentChanges. See example [{{canonicalurl:Special:RecentChanges|feed=atom}} feed].',
-'recentchanges-label-newpage' => 'Tooltip for {{msg-mw|newpageletter}}',
-'recentchanges-label-minor' => 'Tooltip for {{msg-mw|minoreditletter}}',
-'recentchanges-label-bot' => 'Tooltip for {{msg-mw|boteditletter}}',
+'recentchanges-label-newpage' => '# Used as tooltip for {{msg-mw|Newpageletter}}.
+# Also used as legend. Preceded by {{msg-mw|Newpageletter}} and followed by {{msg-mw|Recentchanges-legend-newpage}}.',
+'recentchanges-label-minor' => '# Used as tooltip for {{msg-mw|Minoreditletter}}
+# Also used as legend. Preceded by {{msg-mw|Minoreditletter}}',
+'recentchanges-label-bot' => '# Used as tooltip for {{msg-mw|Boteditletter}}
+# Also used as legend. Preceded by {{msg-mw|Boteditletter}}',
 'recentchanges-label-unpatrolled' => 'Tooltip for {{msg-mw|unpatrolledletter}}',
+'recentchanges-label-plusminus' => 'Legend item for plus/minus.
+
+Preceded by legend example {{msg-mw|Recentchanges-legend-plusminus}}.',
+'recentchanges-legend-newpage' => 'Used as legend in [[Special:RecentChanges]]. Preceded by {{msg-mw|Recentchanges-label-newpage}}.',
+'recentchanges-legend-plusminus' => 'A plus/minus sign with a number for the legend.',
 'rcnote' => 'Used on [[Special:RecentChanges]].
 
 Similar to {{msg-mw|wlnote}} which is used on [[Special:Watchlist]].
@@ -3624,22 +3649,22 @@ Parameters:
 * $1 - a link to the revision of a specific date and time. The date and the time are the link description (without split of date and time, [[bugzilla:19104|Bug 19104]]).
 
 The corresponding message is {{msg-mw|Rcnotefrom}}.',
-'rcshowhideminor' => "Option text in [[Special:RecentChanges]]. Parameters:
-* $1 is the 'show/hide' command, with the text taken from either {{msg-mw|show}} or {{msg-mw|hide}}.",
-'rcshowhidebots' => "Option text in [[Special:RecentChanges]]. Parameters:
-* $1 is the 'show/hide' command, with the text taken from either {{msg-mw|show}} or {{msg-mw|hide}}.
-{{Identical|$1 bots}}",
+'rcshowhideminor' => 'Option text in [[Special:RecentChanges]]. Parameters:
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
+'rcshowhidebots' => 'Option text in [[Special:RecentChanges]]. Parameters:
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}
+{{Identical|$1 bots}}',
 'rcshowhideliu' => 'Option text in [[Special:RecentChanges]]. Parameters:
 * $1 - any one of the following messages:
 ** {{msg-mw|Show}}
 ** {{msg-mw|Hide}}',
-'rcshowhideanons' => "Option text in [[Special:RecentChanges]]. Parameters:
-* $1 is the 'show/hide' command, with the text taken from either {{msg-mw|show}} or {{msg-mw|hide}}.
-{{Identical|Anonymous user}}",
-'rcshowhidepatr' => "Option text in [[Special:RecentChanges]]. Parameters:
-* $1 is the 'show/hide' command, with the text taken from either {{msg-mw|show}} or {{msg-mw|hide}}.",
-'rcshowhidemine' => "Option text in [[Special:RecentChanges]]. Parameters:
-* $1 is the 'show/hide' command, with the text taken from either {{msg-mw|show}} or {{msg-mw|hide}}.",
+'rcshowhideanons' => 'Option text in [[Special:RecentChanges]]. Parameters:
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}
+{{Identical|Anonymous user}}',
+'rcshowhidepatr' => 'Option text in [[Special:RecentChanges]]. Parameters:
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
+'rcshowhidemine' => 'Option text in [[Special:RecentChanges]]. Parameters:
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
 'rclinks' => "Used on [[Special:RecentChanges]].
 * \$1 - a list of different choices with number of pages to be shown.<br />&nbsp;Example: \"''50{{int:pipe-separator}}100{{int:pipe-separator}}250{{int:pipe-separator}}500\".
 * \$2 - a list of clickable links with a number of days for which recent changes are to be displayed.<br />&nbsp;Example: \"''1{{int:pipe-separator}}3{{int:pipe-separator}}7{{int:pipe-separator}}14{{int:pipe-separator}}30''\".
@@ -3830,8 +3855,8 @@ See also:
 'badfilename' => 'Parameters:
 * $1 - filename',
 'filetype-mime-mismatch' => 'Upload error. Parameters:
-* $1 is the extension of the uploaded file
-* $2 is the MIME type of the uploaded file',
+* $1 - the extension of the uploaded file
+* $2 - the MIME type of the uploaded file',
 'filetype-badmime' => 'Parameters:
 * $1 - string representing the MIME type',
 'filetype-bad-ie-mime' => 'Parameters:
@@ -4157,11 +4182,10 @@ See also:
 * {{msg-mw|upload-warning-subj|subject}}
 * {{msg-mw|upload-warning-msg|message}}',
 'upload-warning-msg' => 'Used as warning body which is posted on the user talk page. Parameters:
-* $1 is the URL the file was uploaded from, when using upload-by-URL
-* $2 is the session key for the upload
+* $1 - the URL the file was uploaded from, when using upload-by-URL
+* $2 - the session key for the upload
 See also:
-* {{msg-mw|upload-warning-subj|subject}}
-* {{msg-mw|upload-warning-msg|message}}',
+* {{msg-mw|Upload-warning-subj|subject}}',
 
 'upload-proto-error' => 'See also:
 * {{msg-mw|Upload-proto-error|title}}
@@ -4478,7 +4502,8 @@ See also:
 'file-anchor-link' => '{{Identical|File}}',
 'filehist' => 'Text shown on a media description page. Heads the section where the different versions of the file are displayed.',
 'filehist-help' => 'In file description page',
-'filehist-deleteall' => 'Link in image description page for admins.',
+'filehist-deleteall' => 'Link in image description page for admins.
+{{Identical|Delete all}}',
 'filehist-deleteone' => 'Link description on file description page to delete an earlier version of a file.
 
 {{Identical|Delete}}',
@@ -5909,6 +5934,7 @@ Example (in English):
 {{Identical|View}}
 {{Identical|Restore}}',
 'undeleteviewlink' => 'First part of {{msg-mw|undeletelink}}.
+Display name of link to view a deleted page used on [[Special:Log/delete]].
 {{Identical|View}}',
 'undeletereset' => 'Shown on [[Special:Undelete]] as button caption.
 {{Identical|Reset}}',
@@ -5989,15 +6015,17 @@ Parameters:
 * $3 - the time of the displayed revision
 {{Identical|Are you sure you want to view the deleted revision of the file...}}',
 'undelete-show-file-submit' => '{{Identical|Yes}}',
-'undelete-revisionrow' => "{{Optional}}
+'undelete-revision-row' => "{{Optional}}
 A revision row in the undelete page. Parameters:
 * $1 is a checkBox to indicate whether to restore this specific revision
 * $2 is a link to the revision
 * $3 is a link to the last revision of a page ({{msg-mw|last}})
 * $4 is a link to the page
 * $5 is a link to the revision's user
-* $6 is the revision size
-* $7 is the revision comment",
+* $6 is the revision's minor edit identifier
+* $7 is the revision size
+* $8 is the revision comment
+* $9 is the revision's tags",
 
 # Namespace form on various pages
 'namespace' => 'This message is located at [[Special:Contributions]].
@@ -6521,7 +6549,8 @@ See also:
 * {{msg-mw|sp-contributions-logs}}
 * {{msg-mw|sp-contributions-deleted}}
 * {{msg-mw|sp-contributions-userrights}}',
-'contribslink' => 'Short for "contributions". Used as display name for a link to user contributions on history pages, [[Special:RecentChanges]], [[Special:Watchlist]], etc.',
+'contribslink' => 'Short for "contributions". Used as display name for a link to user contributions on history pages, [[Special:RecentChanges]], [[Special:Watchlist]], etc.
+{{Identical|Contribution}}',
 'emaillink' => 'Used as display name for a link to send an e-mail to a user in the user tool links. Example: "(Talk | contribs | block | send e-mail)".
 
 {{Identical|E-mail}}',
@@ -7840,7 +7869,8 @@ See also:
 * {{msg-mw|Summary}}
 * {{msg-mw|Accesskey-summary}}
 * {{msg-mw|Tooltip-summary}}',
-'tooltip-iwiki' => 'Format of a sidebar interwiki link tooltip. Parameters:
+'interlanguage-link-title' => '{{Optional}}
+Format of a sidebar interwiki link tooltip. Parameters:
 * $1 - page name in the target wiki
 * $2 - target wiki language autonym',
 
@@ -7990,6 +8020,9 @@ Used when a page is deleted because all revisions contained a particular link.
 
 Parameters:
 * $1 - a spammed domain name',
+'simpleantispam-label' => 'Used as label for the input box in "Edit" page.
+
+The label and the input box are always hidden.',
 
 # Info page
 'pageinfo-title' => 'Page title for action=info. Parameters:
@@ -8005,6 +8038,13 @@ Parameters:
 'pageinfo-length' => 'The length of the page, in bytes.',
 'pageinfo-article-id' => 'The numeric identifier of the page.',
 'pageinfo-language' => 'Language in which the page content is written.',
+'pageinfo-content-model' => 'The model in which the page content is written.
+
+Used as label at [{{fullurl:Main Page|action=info}} action=info]. Followed by one of the following messages:
+* {{msg-mw|Content-model-wikitext}}
+* {{msg-mw|Content-model-javascript}}
+* {{msg-mw|Content-model-css}}
+* {{msg-mw|Content-model-text}}',
 'pageinfo-robot-policy' => 'The search engine status of the page.
 
 Used as label. Followed by any one of the following messages:
@@ -8238,7 +8278,8 @@ Non-animated images use {{msg-mw|svg-long-desc}}.',
 * $1 - the error message
 See also:
 * {{msg-mw|Thumbnail error}}',
-'show-big-image' => 'Displayed under an image at the image description page, when it is displayed smaller there than it was uploaded.',
+'show-big-image' => 'Displayed under the file on file description pages, when a reduced-size thumbnail of the original file is being displayed.
+{{Identical|Original file}}',
 'show-big-image-preview' => 'Message shown under the image description page thumbnail.
 
 Can be followed by {{msg-mw|Show-big-image-other}}.
@@ -8277,7 +8318,9 @@ This message may be overridden by a more specific message:
 
 # Special:NewFiles
 'newimages' => 'Page title of [[Special:NewImages]].',
-'imagelisttext' => 'This is text on [[Special:NewImages]]. $1 is the number of files. $2 is the message {{msg-mw|Bydate}}.',
+'imagelisttext' => 'This is text on [[Special:NewImages]]. Parameters:
+* $1 - the number of files
+* $2 - the message {{msg-mw|Bydate}}',
 'newimages-summary' => 'This message is displayed at the top of [[Special:NewImages]] to explain what is shown on that special page.',
 'newimages-legend' => 'Caption of the fieldset for the filter on [[Special:NewImages]]
 
@@ -8909,7 +8952,8 @@ See 2:30 of http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf',
 'exif-originaltransmissionref' => 'This is basically a job ID. This could help an individual keep track of for what reason the image was created.
 
 See Job Id on page 19 of http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata-201007_1.pdf',
-'exif-identifier' => 'A formal identifier for the image. Often this is a URL.',
+'exif-identifier' => 'A formal identifier for the image. Often this is a URL.
+{{Identical|Identifier}}',
 'exif-lens' => 'Description of lens used. This is taken from aux:Lens XMP property. See http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart2.pdf',
 'exif-serialnumber' => 'Serial number of camera. See aux:SerialNumber in http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart2.pdf',
 'exif-cameraownername' => 'Who owns the camera.',
@@ -9353,7 +9397,8 @@ See: http://www.awaresystems.be/imaging/tiff/tifftags/ycbcrpositioning.html
 'exif-dc-publisher' => 'One or more publisher of resource.
 {{Identical|Publisher}}',
 'exif-dc-relation' => "Something related to this image. Often a list of URL's to related images.",
-'exif-dc-rights' => 'Copyright information about the image/media given in informal language.',
+'exif-dc-rights' => 'Copyright information about the image/media given in informal language.
+{{Identical|Right}}',
 'exif-dc-source' => 'Source of the image. This is another image that this image is based on. This does not refer to the person who provided the image.',
 'exif-dc-type' => 'Type or genre of image/media. This might be something like painting or photograph.',
 
@@ -9404,7 +9449,7 @@ Parameters:
 
 # External editor support
 'edit-externally' => 'Displayed on image description pages. See for example [[:Image:Yes.png#filehistory]].',
-'edit-externally-help' => '{{doc-important|Please leave the link "<code>http://www.mediawiki.org/wiki/Manual:External_editors</code>" exactly as it is.}}
+'edit-externally-help' => '{{doc-important|Please leave the link "<code>https://www.mediawiki.org/wiki/Manual:External_editors</code>" exactly as it is.}}
 Displayed on image description pages. See for example [[:Image:Yes.png#filehistory]].',
 
 # 'all' in various places, this might be different for inflected languages
@@ -9544,6 +9589,12 @@ Most languages use a space, but some Asian languages, such as Thai and Chinese,
 'percent' => '{{optional}}',
 'parentheses' => '{{optional}}',
 'brackets' => '{{Optional}}',
+'quotation-marks' => 'Quotation marks, for quoting, sometimes titles etc., depending on the language.
+
+See: [[w:Non-English usage of quotation marks|Non-English usage of quotation marks on Wikipedia]].
+
+Parameters: 
+* $1 - text to be wrapped in quotation marks',
 
 # Multipage image navigation
 'imgmultipageprev' => '{{Identical|Previous page}}',
@@ -9920,7 +9971,8 @@ Used at the end of {{msg-mw|version-poweredby-credits}} on [[Special:Version]].'
 'version-license-info' => '[[wikipedia:GNU GPL|GNU GPL]] notice shown at [[Special:Version]]. See //www.gnu.org/licenses/old-licenses/gpl-2.0-translations.html for available translations.',
 'version-software' => 'Message shown on [[Special:Version]].
 This message is followed by the list of installed software (MediaWiki, PHP and MySQL).',
-'version-software-product' => 'Shown in [[Special:Version]]',
+'version-software-product' => 'Shown in [[Special:Version]].
+{{Identical|Product}}',
 'version-software-version' => '{{Identical|Version}}',
 'version-entrypoints' => 'Header on [[Special:Version]] above a table that lists the URLs of various entry points in this MediaWiki installation. Entry points are the "places" where the wiki\'s content and information can be accessed in various ways, for instance the standard index.php which shows normal pages, histories etc.',
 'version-entrypoints-header-entrypoint' => 'Header for the first column in the entry points table on [[Special:Version]].
@@ -9993,6 +10045,8 @@ See also:
 * {{msg-mw|Accesskey-t-specialpages}}
 * {{msg-mw|Tooltip-t-specialpages}}
 {{Identical|Special page}}',
+'specialpages-note-top' => 'Heading for {{msg-mw|specialpages-note}}.
+{{Identical|Legend}}',
 'specialpages-note' => 'Footer note for the [[Special:SpecialPages]] page',
 'specialpages-group-maintenance' => '{{doc-special-group|like=[[Special:DoubleRedirects]], [[Special:LonelyPages]] and [[Special:WantedPages]]}}',
 'specialpages-group-other' => '{{doc-special-group|like=[[Special:AdminLinks]] and [[Special:BookSources]]}}',
@@ -10035,7 +10089,8 @@ It appears that the word 'valid' describes 'tags', not 'change'. It also appears
 Parameters:
 * $1 - number of distinct tags for given edit
 * $2 - comma-separated list of tags for given edit',
-'tags-title' => 'The title of [[Special:Tags]]',
+'tags-title' => 'The title of [[Special:Tags]].
+{{Identical|Tag}}',
 'tags-intro' => 'Explanation on top of [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
 'tags-tag' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
 'tags-display-header' => 'Caption of a column in [[Special:Tags]]. For more information on tags see [[mw:Manual:Tags|MediaWiki]].',
@@ -10498,4 +10553,36 @@ Parameters:
 * $1 - the usage
 * $2 - the maximum',
 
+# Special:ExpandTemplates
+'expandtemplates' => '{{doc-special|ExpandTemplates}}
+The name of the [[mw:Extension:ExpandTemplates|Expand Templates extension]].',
+'expand_templates_intro' => 'This is the explanation given in the heading of the [[Special:ExpandTemplates]] page; it describes its functionality to the users.
+For more information, see [[mw:Extension:ExpandTemplates]]',
+'expand_templates_title' => 'The label of the input box for the context title on the form displayed at [[Special:ExpandTemplates]] page.',
+'expand_templates_input' => '{{Identical|Input text}}',
+'expand_templates_output' => '{{Identical|Result}}',
+'expand_templates_xml_output' => 'Used as HTML <code><nowiki><h2></nowiki></code> heading.',
+'expand_templates_ok' => '{{Identical|OK}}',
+'expand_templates_remove_comments' => 'Check box to tell [[mw:Extension:ExpandTemplates]] to not show comments in the expanded template.',
+'expand_templates_remove_nowiki' => "Option on [[Special:Expandtemplates]]
+
+Here's what the tick box does:
+
+For:
+<pre>
+&lt;nowiki>test&lt;/nowiki>
+</pre>
+
+Not ticked:
+<pre>
+&lt;nowiki>test&lt;/nowiki>
+</pre>
+
+Ticked:
+<pre>
+test
+</pre>",
+'expand_templates_generate_xml' => 'Used as checkbox label.',
+'expand_templates_preview' => '{{Identical|Preview}}',
+
 );
index c03c5bf..c58b2e7 100644 (file)
@@ -46,7 +46,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'MawkaPanqa' ),
        'Blankpage'                 => array( 'PanqataChusaqchay' ),
        'Block'                     => array( 'Harkay', 'RuraqtaHarkay', 'IPHarkay' ),
-       'Blockme'                   => array( 'Harkaway' ),
        'Booksources'               => array( 'PukyuLiwru' ),
        'BrokenRedirects'           => array( 'PantaPusapuna', 'PitisqaPusapuna' ),
        'Categories'                => array( 'Katiguriyakuna' ),
@@ -56,7 +55,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'RakiqunaKamariy' ),
        'Deadendpages'              => array( 'Lluqsinannaq' ),
        'DeletedContributions'      => array( 'QullusqaRurasqa', 'QullusqaLlamkapusqa' ),
-       'Disambiguations'           => array( 'SutichanaQillqa' ),
        'DoubleRedirects'           => array( 'IskayllaPusapuna' ),
        'Emailuser'                 => array( 'EChaskitaManakuy' ),
        'Export'                    => array( 'HawamanQuy' ),
@@ -192,7 +190,7 @@ $magicWords = array(
        'img_center'                => array( '1', 'chawpi', 'centro', 'centrado', 'centrada', 'centrar', 'center', 'centre' ),
        'img_framed'                => array( '1', 'inchuyuq', 'inchu', 'marco', 'enmarcado', 'enmarcada', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'inchunnaq', 'sinmarco', 'sin_embarcar', 'sinenmarcar', 'sin_enmarcar', 'frameless' ),
-       'img_page'                  => array( '1', 'panqa=$1', 'pagina=$1', 'página=$1', 'pagina $1', 'página $1', 'pagina_$1', 'página_$1', 'page=$1', 'page $1' ),
+       'img_page'                  => array( '1', 'panqa=$1', 'pagina=$1', 'página=$1', 'pagina_$1', 'página_$1', 'page=$1', 'page $1' ),
        'img_upright'               => array( '1', 'sayaq', 'sayaq=$1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'saywa', 'borde', 'border' ),
        'img_baseline'              => array( '1', 'tiksisiqi', 'baseline' ),
@@ -539,8 +537,6 @@ $1",
 'ok' => 'Arí niy',
 'retrievedfrom' => '"$1" p\'anqamanta chaskisqa (Qhichwa / Quechua)',
 'youhavenewmessages' => '$1 qhawanayki kachkan ($2).',
-'newmessageslink' => 'Musuq willaymi',
-'newmessagesdifflink' => 'qayna hukchasqapi wakin kaynin',
 'youhavenewmessagesfromusers' => '$1 {{PLURAL:$3|huk ruraqmanta|$3 ruraqkunamanta}} qhawanayki kachkan ($2).',
 'youhavenewmessagesmanyusers' => '$1 achka ruraqkunamanta qhawanayki kachkan ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|Musuq willaymi|Musuq willaykunam}}',
@@ -596,6 +592,11 @@ Allin sapaq p'anqakunataqa tarinki [[Special:SpecialPages|Sapaq p'anqakuna]] nis
 # General errors
 'error' => 'Pantasqa',
 'databaseerror' => 'Willañiqintin pantasqa',
+'databaseerror-text' => "Willañiqintin maskana pantasqam tukurqan. Llamp'u kaqpi pantasqachá kachkan.",
+'databaseerror-textcl' => 'Willañiqintin maskana pantasqam tukurqan.',
+'databaseerror-query' => 'Maskana: $1',
+'databaseerror-function' => 'Ruray paqtachi: $1',
+'databaseerror-error' => 'Pantasqa: $1',
 'laggedslavemode' => "'''Paqtataq''': Kay p'anqapiqa manaraqchá kachkanchu aswan qayna musuqchasqakuna.",
 'readonly' => "Willañiqintinqa hark'asqam",
 'enterlockreason' => "Qillqamuy imarayku hark'asqa karqan, hayk'appas manañachá hark'asqachu kanqa",
@@ -629,6 +630,7 @@ P\'anqaqa pipapas qullusqanñachá.',
 'cannotdelete-title' => 'Manam atinichu "$1" sutiyuq p\'anqata qulluyta',
 'delete-hook-aborted' => "Ch'iwinam qulluyta t'ipirqan.
 Manam nirqanchu imarayku.",
+'no-null-revision' => 'Manam atinichu "$1" p\'anqapaq musuq ch\'usaq musuqchasqata kamariyta.',
 'badtitle' => "P'anqap sutinqa manam allinchu",
 'badtitletext' => "Kay p'anqap sutinqa manam allinchu, mana allin interwiki t'inkichá icha ch'usaqchá, p'anqa sutipaq mana saqillasqa sananchayuqchá.",
 'perfcached' => "Kay qatiq willakunaqa ''cache'' nisqa pakasqa hallch'apim kachkan, chayrayku manañachá musuqchasqachu. {{PLURAL:$1|Huklla|$1-lla}} taripasqam pakasqa hallch'api aypalla kachkan, manam aswanchu.",
@@ -656,6 +658,8 @@ $2",
 'customjsprotected' => "Manam saqillasunkichu kay JavaScript p'anqata llamk'apuyta, huk ruraqpa kikin tiyachisqankunayuq kaptinmi.",
 'mycustomcssprotected' => "Kay CSS p'anqataqa manam llamk'apuyta atinkichu.",
 'mycustomjsprotected' => "Kay JavaScript p'anqataqa manam llamk'apuyta atinkichu.",
+'myprivateinfoprotected' => "Manam saqillasqachu kanki kikiykip akuna willaykikunata llamk'apunaykipaq.",
+'mypreferencesprotected' => "Manam saqillasqachu kanki allinkachinaykikunata llamk'apunaykipaq.",
 'ns-specialprotected' => "{{ns:special}} suti k'itipi p'anqakunaqa manam llamk'apunallachu.",
 'titleprotected' => "Kay p'anqa sutitaqa [[User:$1|$1]] sutiyuq ruraq kamariymanta hark'arqanmi, kayraykum nispa: ''$2''.",
 'filereadonlyerror' => 'Manam atinichu "$1" sutiyuq willañiqita hukchayta, "$2" sutiyuq willañiqi churamuna ñawirillanapaq kachkaptinmi.
@@ -681,6 +685,7 @@ Ama qunqaychu [[Special:Preferences|{{SITENAME}} allinkachinaykikunata]] hukchay
 'yourname' => 'Ruraq sutiyki:',
 'userlogin-yourname' => 'Ruraqpa sutin',
 'userlogin-yourname-ph' => 'Ruraqpa sutiykita yaykuchiy',
+'createacct-another-username-ph' => 'Ruraqpa sutinta yaykuchiy',
 'yourpassword' => 'Yaykuna rimayki',
 'userlogin-yourpassword' => 'Yaykuna rima',
 'userlogin-yourpassword-ph' => 'Yaykuna rimaykita yaykuchiy',
@@ -713,10 +718,12 @@ Ama qunqaychu [[Special:Preferences|{{SITENAME}} allinkachinaykikunata]] hukchay
 'userlogin-resetpassword-link' => 'Yaykuna rimaykita kutichiy',
 'helplogin-url' => 'Help:Yaykuy',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Yaykunapaq yanapa]]',
+'userlogin-createanother' => 'Huk rakiqunata kamariy',
 'createacct-join' => 'Kay qatiqpi willaykita yaykuchiy.',
 'createacct-emailrequired' => 'E-chaski imamayta',
 'createacct-emailoptional' => 'E-chaski imamayta (munaspayki)',
 'createacct-email-ph' => 'E-chaski imamaytaykita yaykuchiy',
+'createacct-another-email-ph' => 'E-chaski imamaytata yaykuchiy',
 'createaccountmail' => "Kikinmanta tukusqa mit'alla yaykuna rimata llamk'achispa akllasqa e-chaski imamaytaman kachay",
 'createacct-realname' => 'Chiqap suti (munaspayki)',
 'createaccountreason' => 'Kayrayku:',
@@ -725,6 +732,7 @@ Ama qunqaychu [[Special:Preferences|{{SITENAME}} allinkachinaykikunata]] hukchay
 'createacct-captcha' => 'Amachana llanchiy',
 'createacct-imgcaptcha-ph' => 'Hanaqpi rikusqayki qillqata yaykuchiy',
 'createacct-submit' => 'Rakiqunaykita kamariy',
+'createacct-another-submit' => 'Huk rakiqunata kamariy',
 'createacct-benefit-heading' => '{{SITENAME}}taqa qam hina runakunam ruran.',
 'createacct-benefit-body1' => "{{PLURAL:$1|llamk'apusqa|llamk'apusqakuna}}",
 'createacct-benefit-body2' => "{{PLURAL:$1|p'anqa|p'anqakuna}}",
@@ -788,6 +796,7 @@ Kay willay pantasqa kaptinqa, qhawarparillay.',
 'login-abort-generic' => 'Yaykuykachaspayki manam ayparqankichu - Allqasqa',
 'loginlanguagelabel' => 'Rimay: $1',
 'suspicious-userlogout' => "Lluqsiy mañakuyniykiqa mananchasqam karqan, waqllisqa wamp'unamanta icha pakaq proksimanta kachasqa kaspanchá.",
+'createacct-another-realname-tip' => "* Chiqap sutiqa munanallapaqmi. Quwaptiykiqa, llamk'apusqakunam paywan sananchasqa kanqa.",
 
 # Email sending
 'php-mail-error-unknown' => 'Mana riqsisqa pantasqa PHP mail() rurananpi',
@@ -864,6 +873,15 @@ Mit'alla yaykuna rima: $2",
 'changeemail-submit' => 'E-chaskita wakinchay',
 'changeemail-cancel' => 'Ama niy',
 
+# Special:ResetTokens
+'resettokens' => 'Llawikunata kutichiy',
+'resettokens-no-tokens' => 'Manam kanchu kutichina llawikuna.',
+'resettokens-legend' => 'Llawikunata kutichiy',
+'resettokens-tokens' => 'Llawikuna:',
+'resettokens-token-label' => '$1 (kunan chani: $2)',
+'resettokens-done' => 'Llawikunaqa kutichimusqañam.',
+'resettokens-resetbutton' => 'Akllasqa llawikunata kutichimuy',
+
 # Edit page toolbar
 'bold_sample' => 'Yanasapa qillqa',
 'bold_tip' => 'Yanasapa qillqa',
@@ -1087,6 +1105,7 @@ Chay niykunaqa manam chaninchasqachu.",
 'undo-failure' => "Manam atinichu llamk'apusqata kutichiyta, huk ruraqtaq musuqta llamk'apurquptinñam.",
 'undo-norev' => "Manam atinichu llamk'apusqata kutichiyta, mana kaptinmi icha qullusqa kaptinmi.",
 'undo-summary' => '[[Special:Contributions/$2|$2]]-pa $1 hukchasqanta kutichisqa ([[User talk:$2|rimay]])',
+'undo-summary-username-hidden' => 'Pakasqa ruraqpa $1 nisqa musuqchasqata kutichiy',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Manam atinichu rakiqunata kichayta',
@@ -1264,6 +1283,7 @@ Takyachikuy kay hukchayqa allin wiñay kawsay ñiqita ama waqllichunchu chaylla.
 'compareselectedversions' => "Akllasqa llamk'apusqakunata wakichay",
 'showhideselectedversions' => 'Akllasqa musuqchasqakunata rikuchiy/pakay',
 'editundo' => 'kutichiy',
+'diff-empty' => '(Manam wak hina kanchu)',
 'diff-multi' => "({{PLURAL:$2|Huk ruraqpa|$2 ruraqpa}} {{PLURAL:$1|chawpipi huk llamk'apusqanqa manam rikuchisqachu|chawpipi $1 llamk'apusqankunaqa manam rikuchisqachu}})",
 'diff-multi-manyusers' => "({{PLURAL:$2|Hukmanta|$2-manta}} aswan ruraqkunap {{PLURAL:$1|chawpipi huk llamk'apusqanqa manam rikuchisqachu|chawpipi $1 llamk'apusqankunaqa manam rikuchisqachu}})",
 'difference-missing-revision' => "Kay wakin kaymanta ($1) {{PLURAL:$2|huk musuqchasqa|$2 musuqchasqakuna}} manam tarisqachu.
@@ -1337,8 +1357,6 @@ Imaymanata [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} qulluy ha
 'preferences' => 'Allinkachinakuna',
 'mypreferences' => 'Allinkachinaykuna',
 'prefs-edits' => 'Hukchasqakunap yupaynin:',
-'prefsnologin' => 'Manam yaykurqankichu',
-'prefsnologintext' => '<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Yaykunaykim]</span> tiyan allinkachinaykikunata hukchanaykipaq.',
 'changepassword' => 'Yaykuna rimata hukchay',
 'prefs-skin' => 'Qara',
 'skin-preview' => 'Ñawpaqta qhaway',
@@ -1435,6 +1453,8 @@ $1 {{PLURAL:$1|sanampamanta|sanampakunamanta}} aswan pisi kananmi.',
 'prefs-dateformat' => "P'unchaw rikch'ay",
 'prefs-timeoffset' => 'Pacha wakinyay',
 'prefs-advancedediting' => 'Sapsi akllanakuna',
+'prefs-editor' => "P'anqachaq",
+'prefs-preview' => 'Ñawpaqta qhawallay',
 'prefs-advancedrc' => 'Ñawparikusqa akllanakuna',
 'prefs-advancedrendering' => 'Ñawparikusqa akllanakuna',
 'prefs-advancedsearchoptions' => 'Ñawparikusqa akllanakuna',
@@ -1442,6 +1462,7 @@ $1 {{PLURAL:$1|sanampamanta|sanampakunamanta}} aswan pisi kananmi.',
 'prefs-displayrc' => 'Akllanakunata rikuchiy',
 'prefs-displaysearchoptions' => 'Akllanakunata rikuchiy',
 'prefs-displaywatchlist' => 'Akllanakunata rikuchiy',
+'prefs-tokenwatchlist' => 'Llawi',
 'prefs-diffs' => 'Wakin kaykuna',
 
 # User preference: email validation using jQuery
@@ -1536,12 +1557,18 @@ $1 {{PLURAL:$1|sanampamanta|sanampakunamanta}} aswan pisi kananmi.',
 'right-unblockself' => "Kikinta hark'asqamanta qispikuy",
 'right-protect' => "Amachasqa kachkayta hukchay, ch'aqtasqa amachasqa p'anqakunata llamk'apuy",
 'right-editprotected' => 'Amachasqa p\'anqakunata "{{int:protect-level-sysop}}" hina llamk\'apuy',
+'right-editsemiprotected' => '"{{int:protect-level-autoconfirmed}}" hina amachasqa p\'anqakunata llamk\'apuy',
 'right-editinterface' => "Ruraqpaq uyapurata llamk'apuy",
 'right-editusercssjs' => "Huk ruraqkunap CSS, JS willañiqinkunata llamk'apuy",
 'right-editusercss' => "Huk ruraqkunap CSS willañiqinkunata llamk'apuy",
 'right-edituserjs' => "Huk ruraqkunap JS willañiqinkunata llamk'apuy",
 'right-editmyusercss' => "Kikiykip ruraqpaq CSS willañiqiykikunata llamk'apuy",
 'right-editmyuserjs' => "Kikiykip ruraqpaq JavaScript willañiqiykikunata llamk'apuy",
+'right-viewmywatchlist' => 'Kikiykip watiqasqayki sutisuyuykita qhaway',
+'right-editmywatchlist' => "Kikiykip watiqasqayki sutisuyuykita llamk'apuy. Paqtataq, huk ruranakunaqa p'anqakunata yapanqaraqmi kay hañi mana kaptinpas.",
+'right-viewmyprivateinfo' => 'Kikiykip akuna willaykikunata qhaway (ahinataq e-chaski imamaytayki, chiqap sutiyki)',
+'right-editmyprivateinfo' => "Kikiykip akuna willaykikunata llamk'apuy (ahinataq e-chaski imamaytayki, chiqap sutiyki)",
+'right-editmyoptions' => "Kikiykip allinkachinaykikunata llamk'apuy",
 'right-rollback' => "Huk p'anqapi qhipaq llamk'apuqpa hukchasqankunata utqaylla kutichiy",
 'right-markbotedits' => "Kutichisqa llamk'apusqakunata rurana antachap llamk'apusqankunata hina sananchay",
 'right-noratelimit' => 'Achura saywakunap manam chayachisqanchu',
@@ -1603,17 +1630,25 @@ $1 {{PLURAL:$1|sanampamanta|sanampakunamanta}} aswan pisi kananmi.',
 'action-userrights-interwiki' => "hawa wikikunapi ruraqkunap hayñinkunata llamk'apuy",
 'action-siteadmin' => "willañiqintinta hark'ay icha paskay",
 'action-sendemail' => 'e-chaskikunata kachay',
+'action-editmywatchlist' => "watiqasqayki sutisuyuta llamk'apuy",
+'action-viewmywatchlist' => 'watiqasqayki sutisuyuta qhaway',
+'action-viewmyprivateinfo' => 'kikiykip akuna willaykikunata qhaway',
+'action-editmyprivateinfo' => "kikiykip akuna willaykikunata llamk'apuy",
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|hukchasqa|hukchasqakuna}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|qhipaq watukusqamantapacha}}',
+'enhancedrc-history' => 'wiñay kawsay',
 'recentchanges' => 'Ñaqha hukchasqa',
 'recentchanges-legend' => 'Ñaqha hukchasqapaq allinkachinakuna',
 'recentchanges-summary' => "Kay p'anqapiqa aswan qhipaq ñaqha hukchasqakunam.",
+'recentchanges-noresult' => "Kay taripanakama hukchasqakunaqa akllasqa mit'api manam kanchu.",
 'recentchanges-feed-description' => 'Kay mikhuchinapi wikipi qhipaq ñaqha hukchasqakunata qatiy.',
 'recentchanges-label-newpage' => "Kayta llamk'apuptiykim musuq p'anqam tukukurqun",
 'recentchanges-label-minor' => "Kayqa aslla llamk'apuymi",
 'recentchanges-label-bot' => "Kayqa rurana antachap llamk'apusqanmi",
 'recentchanges-label-unpatrolled' => "Kay llamk'apusqaqa manaraqmi patrullasqachu",
+'recentchanges-legend-newpage' => "$1 - musuq p'anqa",
 'rcnote' => "Kay qatiqpiqa qhipaq {{PLURAL:$1|'''1''' hukchasqam|'''$1''' hukchasqakunam}} qhipaq {{PLURAL:$2|p'unchawpi|'''$2''' p'unchawkunapi}}, musuqchasqa $5, $4.",
 'rcnotefrom' => "Kay qatiqpiqa '''$2'''-mantapacha ('''$1'''-kama) hukchasqakunatam rikunki.",
 'rclistfrom' => '$1-manta musuq hukchasqakunata rikuchiy',
@@ -1885,6 +1920,10 @@ Lliwmanta aswan alliku kanapaqqa, img_auth.php manam atinchu.',
 'listfiles_size' => 'Hatun kay',
 'listfiles_description' => "T'iktuna",
 'listfiles_count' => 'Musuqchasqakuna',
+'listfiles-show-all' => "Rikchakunamanta mawk'a musuqchasqakunata ch'aqtay",
+'listfiles-latestversion' => 'Kunan musuqchasqa',
+'listfiles-latestversion-yes' => 'Arí',
+'listfiles-latestversion-no' => 'Mana',
 
 # File description page
 'file-anchor-link' => 'Rikcha',
@@ -1979,6 +2018,13 @@ Ama hina kaspa, [$2 willañiqi ch'uyanchana p'anqata] qhaway astawan willachikun
 'randompage' => "Mayninpi p'anqa",
 'randompage-nopages' => "Manam ima p'anqapas kanchu kay suti {{PLURAL:$2|k'itipi|k'itikunapi}}: $1.",
 
+# Random page in category
+'randomincategory' => "Katiguriyapi kikinmanta p'anqa",
+'randomincategory-invalidcategory' => '"$1" nisqaqa katiguriyapaq manam allin sutinchu.',
+'randomincategory-nopages' => "[[:Category:$1|$1]] katiguriyapiqa manam p'anqakuna kanchu.",
+'randomincategory-selectcategory' => "Katiguriyamanta kikinmanta p'anqata chaskiy: $1 $2.",
+'randomincategory-selectcategory-submit' => 'Riy',
+
 # Random redirect
 'randomredirect' => "Mayninpi pusapuna p'anqa",
 'randomredirect-nopages' => 'Manam kanchu "$1" nisqa suti k\'itipi pusapuna p\'anqakuna.',
@@ -2790,7 +2836,7 @@ Qhipaqta munaspaykiqa, t'inkitapas llamk'achiyta atinki, ahinataq [[{{#Special:E
 'allmessagesdefault' => 'Ñawpaq qillqa',
 'allmessagescurrent' => 'Kunan kachkaq qillqa',
 'allmessagestext' => "Kayqa MediaWiki suti k'itipi llamk'achinalla willaykunayuq sutisuyum.
-Ama hina kaspa, [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] nisqata, [//translatewiki.net translatewiki.net] nisqatapas watukuy, MediaWiki nisqata t'ikraywan yanapayta munaspaykiqa.",
+Ama hina kaspa, [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] nisqata, [//translatewiki.net translatewiki.net] nisqatapas watukuy, MediaWiki nisqata t'ikraywan yanapayta munaspaykiqa.",
 'allmessagesnotsupportedDB' => "Kay p'anqaqa manam llamk'achinallachu, '''\$wgUseDatabaseMessages''' nisqaman ama nisqa kaptinmi.",
 'allmessages-filter-legend' => "Ch'illchina",
 'allmessages-filter' => "Ch'illchina, allinchasqa kachkaykama:",
@@ -3545,7 +3591,7 @@ Kikin siq'ipi ima qatiq t'inkillapas sapaqllatam hamut'arisqa, ahinataq siq'ipi
 
 # External editor support
 'edit-externally' => "Kay willañiqita hawa rurana wakichiwan llamk'apuy",
-'edit-externally-help' => 'Astawan willasunaykipaqqa [//www.mediawiki.org/wiki/Manual:External_editors tiyachina yanapata] (inlish simipi) ñawiriy.',
+'edit-externally-help' => 'Astawan willasunaykipaqqa [https://www.mediawiki.org/wiki/Manual:External_editors tiyachina yanapata] (inlish simipi) ñawiriy.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'lliw',
@@ -3716,7 +3762,7 @@ Sapsilla ñawpaq qhawariyta tukuykachay.',
 'version-hook-subscribedby' => 'Kay runap mañaykusqan:',
 'version-version' => '(Musuqchasqa $1)',
 'version-license' => 'Saqillay',
-'version-poweredby-credits' => "Kay wikitaqa '''[//www.mediawiki.org/ MediaWiki-m]''' atichin, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Kay wikitaqa '''[https://www.mediawiki.org/ MediaWiki-m]''' atichin, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'hukkuna',
 'version-credits-summary' => "Kay qatiqpi runakunatam [[Special:Version|MediaWiki]] nisqapaq llamk'apusqankunapaq riqsichiyta munayku.",
 'version-license-info' => "MediaWiki llamp'u kaqqa qispim; mast'ariytam icha wakinchaytam atinki GNU General Public License nisqa saqillaypa kamachisqankama, Free Software Foundation nisqap uyaychasqan; saqillaypa iskay ñiqin musuqchasqan, munaspaykiqa aswan musuq musuqchasqan.
@@ -3755,8 +3801,7 @@ MediaWikitaqa mast'ariyku runakunata yanapanapaqmi, ichataq MANAM FIYAKUYTA ATIY
 
 # Special:SpecialPages
 'specialpages' => "Sapaq p'anqakuna",
-'specialpages-note' => '----
-* Sapsipaq sapaq p\'anqakuna.
+'specialpages-note' => '* Sapsipaq sapaq p\'anqakuna.
 * <span class="mw-specialpagerestricted">Sapaqkunallapaq sapaq p\'anqakuna.</span>',
 'specialpages-group-maintenance' => 'Hatalliy willaykuna',
 'specialpages-group-other' => "Huk sapaq p'anqakuna",
@@ -3794,7 +3839,10 @@ MediaWikitaqa mast'ariyku runakunata yanapanapaqmi, ichataq MANAM FIYAKUYTA ATIY
 'tags-tag' => 'Unanchachap sutin',
 'tags-display-header' => "Hukchasqakunamanta sutisuyup rikch'akuynin",
 'tags-description-header' => "Sut'inmanta hunt'a ch'uyanchaynin",
+'tags-active-header' => 'Ruraqllachu?',
 'tags-hitcount-header' => 'Unanchasqa hukchasqakuna',
+'tags-active-yes' => 'Arí',
+'tags-active-no' => 'Mana',
 'tags-edit' => "llamk'apuy",
 'tags-hitcount' => '$1 {{PLURAL:$1|hukchasqa|hukchasqakuna}}',
 
@@ -3950,4 +3998,17 @@ Mana chayqa, kay qatiqpi kaq hunt'ana p'anqatam llamk'achiyta atinki. Willapuyni
 # Image rotation
 'rotate-comment' => "Rikch'aqa pacha rikuchiqwan $1 {{PLURAL:$1|k'atma}} muyusqam",
 
+# Limit report
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|sikundu|sikundukuna}}',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|sikundu|sikundukuna}}',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|byte}}',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|byte}}',
+
+# Special:ExpandTemplates
+'expandtemplates' => "Plantillakunata mast'ariy",
+'expand_templates_input' => 'Yaykuchina qillqa:',
+'expand_templates_output' => 'Lluqsiynin:',
+'expand_templates_remove_comments' => 'Willapusqakunata qichuy',
+'expand_templates_preview' => 'Ñawpaqta qhawallay',
+
 );
index 47e5546..713c469 100644 (file)
@@ -277,8 +277,6 @@ $1',
 'ok' => 'Ari nina',
 'retrievedfrom' => '$1 pankamanta hapishka',
 'youhavenewmessages' => '$1 charipanki ($2).',
-'newmessageslink' => 'Mushuk willaymi',
-'newmessagesdifflink' => 'yalli mushuk killkay',
 'youhavenewmessagesmulti' => '$1-pi mushuk chaskikunata charipankimi.',
 'editsection' => 'Killkana',
 'editold' => 'Killkana',
@@ -867,7 +865,7 @@ Shuk aspipi, shukniki tinkika ima tinkita wichkashkami kanka nin, kay aspipi shu
 
 # External editor support
 'edit-externally' => 'Kay archiwuta shuk hawa antanawan llankana',
-'edit-externally-help' => 'Ashtawan yachakunkakak [//www.mediawiki.org/wiki/Manual:External_editors kay yanapata] (inlish shimipi) killkakatipay',
+'edit-externally-help' => 'Ashtawan yachakunkakak [https://www.mediawiki.org/wiki/Manual:External_editors kay yanapata] (inlish shimipi) killkakatipay',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tukuy',
index f944b96..9c2ad54 100644 (file)
@@ -11,6 +11,7 @@
  * @author Gion-andri
  * @author Kaganer
  * @author Kazu89
+ * @author Shirayuki
  * @author Urhixidur
  * @author לערי ריינהארט
  */
@@ -299,8 +300,6 @@ $1',
 'ok' => "D'accord",
 'retrievedfrom' => 'Da "$1"',
 'youhavenewmessages' => 'Ti has $1 ($2).',
-'newmessageslink' => 'novs messadis',
-'newmessagesdifflink' => "l'ultima midada",
 'youhavenewmessagesfromusers' => 'Ti has $1 da{{PLURAL:$3|d in utilisader| $3 utilisaders}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ti has $1 da divers utilisaders ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|in nov messadi|novs messadis}}',
@@ -1097,8 +1096,6 @@ Considerescha che lur index da {{SITENAME}} po cuntegnair datas ch'èn betg pli
 'preferences' => 'Preferenzas',
 'mypreferences' => 'Preferenzas',
 'prefs-edits' => 'Dumber da las modificaziuns:',
-'prefsnologin' => "Betg t'annunzià",
-'prefsnologintext' => 'Ti stos esser <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} t\'annunzià]</span> per midar tias preferenzas.',
 'changepassword' => 'Midar pled-clav',
 'prefs-skin' => 'Skin',
 'skin-preview' => 'Prevista',
@@ -1374,6 +1371,7 @@ Tia adressa dad e-mail na vegn betg mussada sche auters utilisaders ta contactes
 'recentchanges-label-minor' => 'Quai è ina pitschna modificaziun',
 'recentchanges-label-bot' => 'Questa modificaziun è vegnida exequida dad in bot',
 'recentchanges-label-unpatrolled' => "Questa midada n'è anc betg vegnida controllada",
+'recentchanges-legend-newpage' => '$1 - nova pagina',
 'rcnote' => "Sutvart {{PLURAL:$1|è '''ina''' midada|èn las ultimas '''$1''' midadass}} {{PLURAL:$2|da l'ultim di|dals ultims '''$2''' dis}}, versiun dals  $4 $5.",
 'rcnotefrom' => "Midadas dapi '''$2''' (maximalmain '''$1''' vegnan mussads).",
 'rclistfrom' => 'Mussar las novas midadas entschavend cun $1',
@@ -2607,7 +2605,7 @@ En cas che ti vul be exportar l'ultima versiun pos ti era utilisar in link, p.ex
 'allmessagesdefault' => 'text original',
 'allmessagescurrent' => 'text actual',
 'allmessagestext' => 'Quai è ina glista da tut ils messadis dals differents tips da paginas da MediaWiki che vegnan utilisadas da la software MediaWiki.
-Fai ina visita sin [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] sche ti vuls gidar da translatar la software MediaWiki.',
+Fai ina visita sin [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] sche ti vuls gidar da translatar la software MediaWiki.',
 'allmessagesnotsupportedDB' => "Questa pagina na po betg vegnir mussada, perquai che '''\$wgUseDatabaseMessages''' è vegnì deactivà.",
 'allmessages-filter-legend' => 'Filtrar',
 'allmessages-filter' => 'Filtrar tenor standi da modificaziun:',
@@ -3343,7 +3341,7 @@ Sche la datoteca è vegnida midada dal status original èn tscherts detagls even
 
 # External editor support
 'edit-externally' => 'Modifitgar questa datoteca cun in program extern',
-'edit-externally-help' => "(Legia [//www.mediawiki.org/wiki/Manual:External_editors instrucziuns d'installaziun] per ulteriuras infurmaziuns)",
+'edit-externally-help' => "(Legia [https://www.mediawiki.org/wiki/Manual:External_editors instrucziuns d'installaziun] per ulteriuras infurmaziuns)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tut',
@@ -3530,7 +3528,7 @@ Ti pos era utilisar [[Special:EditWatchlist|la pagina da standard]].',
 'version-hook-subscribedby' => 'Abonnà da',
 'version-version' => '(Versiun $1)',
 'version-license' => 'Licenza',
-'version-poweredby-credits' => "Questa wiki utilisescha '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Questa wiki utilisescha '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'auters',
 'version-credits-summary' => 'Nus vulain engraziar a suandantas persunas per lur contribuziun a [[Special:Version|MediaWiki]].',
 'version-license-info' => "MediaWiki è software liba; ti la pos redistribuir e/u la modifitgar tenor ils terms da la GNU General Public License sco ch'ella vegn publitgada da la Free Software Foundation; ti pos utilisar la versiun 2 da la licenza u (sche ti vul) mintga versiun che succeda. 
@@ -3558,8 +3556,7 @@ Ti duessas avair retschavì [{{SERVER}}{{SCRIPTPATH}}/COPYING ina copia da la GN
 
 # Special:SpecialPages
 'specialpages' => 'Paginas spezialas',
-'specialpages-note' => '----
-* Paginas spezialas normalas.
+'specialpages-note' => '* Paginas spezialas normalas.
 * <span class="mw-specialpagerestricted">Paginas spezialas restrenschidas.</span>
 * <span class="mw-specialpagecached">Paginas spezialas en il cache (pon esser antiquadas).</span>',
 'specialpages-group-maintenance' => 'Rapports da mantegnamant',
index 269298f..0e64e7f 100644 (file)
@@ -200,7 +200,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Pagini_vechi' ),
        'Blankpage'                 => array( 'Pagină_goală' ),
        'Block'                     => array( 'Blochează_IP' ),
-       'Blockme'                   => array( 'Blochează-mă' ),
        'Booksources'               => array( 'Referințe_în_cărți' ),
        'BrokenRedirects'           => array( 'Redirectări_invalide' ),
        'Categories'                => array( 'Categorii' ),
@@ -210,7 +209,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Înregistrare' ),
        'Deadendpages'              => array( 'Pagini_fără_legături' ),
        'DeletedContributions'      => array( 'Contribuții_șterse' ),
-       'Disambiguations'           => array( 'Dezambiguizări' ),
        'DoubleRedirects'           => array( 'Redirectări_duble' ),
        'Emailuser'                 => array( 'Email_utilizator' ),
        'Export'                    => array( 'Exportă' ),
@@ -438,8 +436,6 @@ $messages = array(
 'noindex-category' => 'Pagini neindexate',
 'broken-file-category' => 'Pagini cu legături invalide către fișiere',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Despre',
 'article' => 'Articol',
 'newwindow' => '(se deschide într-o fereastră nouă)',
@@ -574,12 +570,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Adus de la „$1”',
 'youhavenewmessages' => 'Aveți $1 ($2).',
-'newmessageslink' => 'mesaje noi',
-'newmessagesdifflink' => 'comparație cu versiunea precedentă',
 'youhavenewmessagesfromusers' => 'Aveți $1 de la {{PLURAL:$3|un alt utilizator|$3 utilizatori}} ($2).',
 'youhavenewmessagesmanyusers' => 'Aveți $1 de la mai mulți utilizatori ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|un mesaj nou|mesaje noi}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|ultima modificare|ultimele modificări}}',
+'newmessageslinkplural' => '{{PLURAL:$1|un mesaj nou|999=mesaje noi}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|ultima modificare|999=ultimele modificări}}',
 'youhavenewmessagesmulti' => 'Aveți mesaje noi la $1',
 'editsection' => 'modificare',
 'editold' => 'modificare',
@@ -711,7 +705,8 @@ Administratorul care a efectuat blocarea a furnizat explicația: „$3”.',
 'invalidtitle-knownnamespace' => 'Titlu invalid cu spațiul de nume „$2” și textul „$3”',
 'invalidtitle-unknownnamespace' => 'Titlu invalid cu numărul spațiului de nume $1 necunoscut și textul „$2”',
 'exception-nologin' => 'Neautentificat{{GENDER:||ă}}.',
-'exception-nologin-text' => 'Această pagină sau acțiune necesită ca dumneavoastră să fiți autentificat{{GENDER:||ă}} pe acest wiki.',
+'exception-nologin-text' => 'Vă rugăm să vă [[Special:Userlogin|autentificați]] pentru a accesa această pagină sau acțiune.',
+'exception-nologin-text-manual' => 'Vă rugăm să vă $1 pentru a accesa această pagină sau acțiune.',
 
 # Virus scanner
 'virus-badscanner' => "Configurație greșită: scaner de virus necunoscut: ''$1''",
@@ -758,7 +753,7 @@ Nu uitați să vă modificați [[Special:Preferences|preferințele]] pentru {{SI
 'gotaccount' => "Aveți deja un cont de utilizator? '''$1'''.",
 'gotaccountlink' => 'Autentificați-vă',
 'userlogin-resetlink' => 'Ați uitat datele de autentificare?',
-'userlogin-resetpassword-link' => 'Resetare parolă',
+'userlogin-resetpassword-link' => 'V-ați uitat parola?',
 'helplogin-url' => 'Help:Autentificare',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ajutor la autentificare]]',
 'userlogin-loggedin' => 'Sunteți deja {{GENDER:$1|autentificat|autentificată}} ca {{GENDER:$1|$1}}.
@@ -808,7 +803,7 @@ Verificați ortografierea.',
 'passwordtooshort' => 'Parola trebuie să aibă cel puțin {{PLURAL:$1|1 caracter|$1 caractere|$1 de caractere}}.',
 'password-name-match' => 'Parola dumneavoastră trebuie să fie diferită de numele de utilizator.',
 'password-login-forbidden' => 'Utilizarea acestui nume de utilizator și a acestei parole este interzisă.',
-'mailmypassword' => 'Trimite-mi parola pe e-mail!',
+'mailmypassword' => 'Resetează parola',
 'passwordremindertitle' => 'Noua parolă temporară la {{SITENAME}}',
 'passwordremindertext' => 'Cineva (probabil dumneavoastră, de la adresa $1)
 a cerut să vi se trimită o nouă parolă pentru {{SITENAME}} ($4).
@@ -822,13 +817,14 @@ să folosiți vechea parolă.',
 'noemailcreate' => 'Trebuie oferită o adresă e e-mail validă.',
 'passwordsent' => 'O nouă parolă a fost trimisă la adresa de e-mail a utilizatorului "$1". Te rugăm să te autentifici pe {{SITENAME}} după ce o primești.',
 'blocked-mailpassword' => 'Această adresă IP este blocată la editare, și deci nu este permisă utilizarea funcției de recuperare a parolei pentru a preveni abuzul.',
-'eauthentsent' => 'Un email de confirmare a fost trimis adresei nominalizate. Înainte de a fi trimis orice alt email acestui cont, trebuie să urmați intrucțiunile din email, pentru a confirma că acest cont este într-adevăr al dvs.',
+'eauthentsent' => 'Un e-mail de confirmare a fost trimis către adresa specificată.
+Înainte ca orice alt e-mail să mai fie trimis către acel cont, trebuie să urmați instrucțiunile prezente în e-mail pentru a confirma că acest cont este într-adevăr al dumneavoastră.',
 'throttled-mailpassword' => 'Un e-mail pentru resetarea parolei a fost deja trimis în {{PLURAL:$1|ultima oră|ultimele $1 ore|ultimele $1 de ore}}. Pentru a preveni abuzul, se va trimite doar un e-mail de resetare a parolei la un interval de o {{PLURAL:$1|o oră|$1 ore|$1 de ore}}.',
 'mailerror' => 'Eroare la trimitere e-mail: $1',
 'acct_creation_throttle_hit' => 'De la această adresă IP, vizitatorii sitului au creat {{PLURAL:$1|1 cont|$1 conturi|$1 de conturi}} de utilizator în ultimele zile, acest număr de noi conturi fiind maximul admis în această perioadă de timp.
 Prin urmare, vizitatorii care folosesc același IP nu mai pot crea alte conturi pentru moment.',
 'emailauthenticated' => 'Adresa de e-mail a fost autentificată pe $2, la $3.',
-'emailnotauthenticated' => 'Adresa de email <strong>nu este autentificată încă</strong>. Nici un email nu va fi trimis pentru nici una din întrebuințările următoare.',
+'emailnotauthenticated' => 'Adresa dumneavoastră de e-mail nu este autentificată încă. Nici un e-mail nu va fi trimis pentru nici una din întrebuințările următoare.',
 'noemailprefs' => 'Nu a fost specificată o adresă email, următoarele nu vor funcționa.',
 'emailconfirmlink' => 'Confirmați adresa dvs. de email',
 'invalidemailaddress' => 'Adresa de email nu a putut fi acceptată pentru că pare a avea un format invalid. Vă rugăm să reintroduceți o adresă bine formatată sau să goliți acel câmp.',
@@ -877,7 +873,7 @@ Este posibil să fi reușit deja schimbarea parolei sau să fi cerut o parolă t
 # Special:PasswordReset
 'passwordreset' => 'Resetare parolă',
 'passwordreset-text-one' => 'Completați acest formular pentru a vă reseta parola.',
-'passwordreset-text-many' => '{{PLURAL:$1|Completați unul din câmpuri pentru a vă reseta parola.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Completați unul din câmpuri pentru a primi o parolă temporară prin e-mail.}}',
 'passwordreset-legend' => 'Resetare parolă',
 'passwordreset-disabled' => 'Resetarea parolei a fost dezactivată pe acest wiki.',
 'passwordreset-emaildisabled' => 'Funcțiile de e-mail au fost dezactivate de pe acest wiki.',
@@ -1264,18 +1260,19 @@ funcție, fie versiunea specificată nu există, ori sunteți pe cale să ascund
 'revdelete-text' => "'''Versiunile șterse vor apărea în istoricul paginii, dar conținutul lor nu va fi accesibil publicului.''' Administratorii {{SITENAME}} pot accesa conținutul șters și îl pot recupera prin aceeași interfață, dacă nu este impusă altă restricție de către operatorii sitului.",
 'revdelete-confirm' => 'Vă rugăm să confirmați că intenționați să faceți acest lucru, că înțelegeți consecințele și că faceți asta în conformitate cu [[{{MediaWiki:Policy-url}}|politica]].',
 'revdelete-suppress-text' => "Suprimarea trebuie folosită '''doar''' în următoarele cazuri:
+* Informații potențial calomnioase
 * Informații personale inadecvate
-*: ''adrese și numere de telefon personale, CNP, numere de securitate socială, etc.''",
+*: ''adrese și numere de telefon personale, CNP, numere de securitate socială etc.''",
 'revdelete-legend' => 'Restricții de afișare',
-'revdelete-hide-text' => 'Șterge textul versiunii',
+'revdelete-hide-text' => 'Textul versiunii',
 'revdelete-hide-image' => 'Șterge conținutul fișierului',
 'revdelete-hide-name' => 'Șterge operația și obiectul',
-'revdelete-hide-comment' => 'Șterge descrierea modificării',
-'revdelete-hide-user' => 'Șterge numele de utilizator sau adresa IP',
+'revdelete-hide-comment' => 'Descrierea modificării',
+'revdelete-hide-user' => 'Numele de utilizator sau adresa IP',
 'revdelete-hide-restricted' => 'Ascunde informațiile față de administratori și față de alți utilizatori',
 'revdelete-radio-same' => '(nu schimba)',
-'revdelete-radio-set' => 'Da',
-'revdelete-radio-unset' => 'Nu',
+'revdelete-radio-set' => 'Ascuns',
+'revdelete-radio-unset' => 'Vizibil',
 'revdelete-suppress' => 'Ascunde versiunile și față de administratori',
 'revdelete-unsuppress' => 'Anulează restricțiile la versiunile restaurate',
 'revdelete-log' => 'Motivul ștergerii:',
@@ -1430,8 +1427,7 @@ Detalii se pot găsi în [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE
 'preferences' => 'Preferințe',
 'mypreferences' => 'Preferințe',
 'prefs-edits' => 'Număr de modificări:',
-'prefsnologin' => 'Neautentificat',
-'prefsnologintext' => 'Trebuie să fiți <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} autentificat]</span> pentru a vă putea salva preferințele.',
+'prefsnologintext2' => 'Vă rugăm să vă $1 pentru a vă seta preferințele de utilizator.',
 'changepassword' => 'Schimbare parolă',
 'prefs-skin' => 'Aspect',
 'skin-preview' => 'Previzualizare',
@@ -1731,6 +1727,9 @@ Dacă decideți furnizarea sa, acesta va fi folosit pentru a vă atribui munca.'
 'recentchanges-label-minor' => 'Aceasta este o modificare minoră',
 'recentchanges-label-bot' => 'Această modificare a fost efectuată de un robot',
 'recentchanges-label-unpatrolled' => 'Această modificare nu a fost încă verificată',
+'recentchanges-label-plusminus' => 'Dimensiunea paginii s-a modificat corespunzător acestui număr de octeți',
+'recentchanges-legend-newpage' => '(vezi și [[Special:NewPages|lista cu pagini noi]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Mai jos se află {{PLURAL:\$|ultima modificare|ultimele '''\$1''' modificări|ultimele '''\$1''' de modificări}} din {{PLURAL:\$2|ultima zi|ultimele '''\$2''' zile|ultimele '''\$2''' de zile}}, începând cu \$5, \$4.",
 'rcnotefrom' => 'Dedesubt sunt modificările de la <b>$2</b> (maxim <b>$1</b> de modificări sunt afișate - schimbă numărul maxim de linii alegând altă valoare mai jos).',
 'rclistfrom' => 'Se arată modificările începând cu $1',
@@ -2460,9 +2459,9 @@ Puteți contacta utilizatorul:
 e-mail: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Nu veți mai primi notificări în cazul unor viitoare modificări până când nu veți vizitați pagina. Puteți de asemenea reseta notificările pentru toate pagini pe care le urmăriți.
+Nu veți mai primi notificări în cazul unei viitoare activități până când nu veți vizitați pagina ca utilizator autentificat. Puteți de asemenea reseta notificările pentru toate pagini pe care le urmăriți.
 
-             Al dumneavoastră amic, sistemul de notificare de la {{SITENAME}}
+Al dumneavoastră amic, sistemul de notificare de la {{SITENAME}}
 
 --
 Pentru a modifica setările notificării prin e-mail, vizitați
@@ -2984,7 +2983,7 @@ Pentru a exporta, introduceți titlurile în căsuța de mai jos, unul pe linie,
 'allmessagesdefault' => 'Textul standard',
 'allmessagescurrent' => 'Textul curent',
 'allmessagestext' => 'Aceasta este lista completă a mesajelor disponibile în domeniul MediaWiki.
-Vă rugăm să vizitați [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] și [//translatewiki.net translatewiki.net] dacă vreți să contribuiți la localizarea programului MediaWiki generic.',
+Vă rugăm să vizitați [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] și [//translatewiki.net translatewiki.net] dacă vreți să contribuiți la localizarea programului MediaWiki generic.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' nu poate fi folosit deoarece '''\$wgUseDatabaseMessages''' este închisă.",
 'allmessages-filter-legend' => 'Filtru',
 'allmessages-filter' => 'Filtru după statutul de modificare:',
@@ -3148,7 +3147,7 @@ Un dosar temporar lipsește.',
 Permite adăugarea unui motiv în descrierea modificărilor',
 'tooltip-preferences-save' => 'Salvează preferințele',
 'tooltip-summary' => 'Descrieți pe scurt modificarea',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/** CSS plasate aici vor fi aplicate tuturor aparițiilor */',
@@ -3181,6 +3180,8 @@ Permite adăugarea unui motiv în descrierea modificărilor',
 'spam_reverting' => 'Revenire la ultima versiune care nu conține legături către $1',
 'spam_blanking' => 'Toate versiunile conținând legături către $1 au fost golite',
 'spam_deleting' => 'Toate versiunile conținând legături către $1 au fost șterse',
+'simpleantispam-label' => "Verificare antispam.
+'''NU''' completați!",
 
 # Info page
 'pageinfo-title' => 'Informații pentru „$1”',
@@ -3194,6 +3195,7 @@ Permite adăugarea unui motiv în descrierea modificărilor',
 'pageinfo-length' => 'Lungimea paginii (în octeți)',
 'pageinfo-article-id' => 'ID pagină',
 'pageinfo-language' => 'Limba conținutului paginii',
+'pageinfo-content-model' => 'Modelul conținutului paginii',
 'pageinfo-robot-policy' => 'Indexare de către roboți',
 'pageinfo-robot-index' => 'Permisă',
 'pageinfo-robot-noindex' => 'Nepermisă',
@@ -3281,7 +3283,7 @@ Executându-l, sistemul dvs. poate fi compromis.",
 'svg-long-desc' => 'Fișier SVG, cu dimensiunea nominală de $1 × $2 pixeli, mărime fișier: $3',
 'svg-long-desc-animated' => 'Fișier SVG animat, cu dimensiunea nominală de $1 × $2 pixeli, mărime fișier: $3',
 'svg-long-error' => 'Fișier SVG invalid: $1',
-'show-big-image' => 'Rezoluție maximă',
+'show-big-image' => 'Fișier original',
 'show-big-image-preview' => 'Mărimea acestei previzualizări: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Altă rezoluție|Alte rezoluții}}: $1.',
 'show-big-image-size' => '$1 × $2 pixeli',
@@ -3752,7 +3754,7 @@ Altele vor fi ascunse implicit.
 
 # External editor support
 'edit-externally' => 'Editează acest fișier folosind o aplicație externă.',
-'edit-externally-help' => '(Vedeți [//www.mediawiki.org/wiki/Manual:External_editors instrucțiuni de instalare] pentru mai multe informații)',
+'edit-externally-help' => '(Vedeți [https://www.mediawiki.org/wiki/Manual:External_editors instrucțiuni de instalare] pentru mai multe informații)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'toate',
@@ -3761,7 +3763,7 @@ Altele vor fi ascunse implicit.
 'limitall' => 'toate',
 
 # Email address confirmation
-'confirmemail' => 'Confirmă adresa de e-mail',
+'confirmemail' => 'Confirmare adresă e-mail',
 'confirmemail_noemail' => 'Nu aveți o adresă de e-mail validă setată la [[Special:Preferences|preferințe]].',
 'confirmemail_text' => '{{SITENAME}} solicită validarea adresei de e-mail înaintea utilizării funcțiilor specifice poștei electronice.
 Apăsați butonul de mai jos pentru ca un e-mail de confirmare să fie trimis către adresa dumneavoastră.
@@ -3843,6 +3845,9 @@ Vă rugăm să confirmați faptul că într-adevăr doriți să recreați acest
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Eliminați această pagină din lista de pagini urmărite?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1”',
+
 # Multipage image navigation
 'imgmultipageprev' => '← pagina anterioară',
 'imgmultipagenext' => 'pagina următoare →',
@@ -3928,7 +3933,7 @@ Puteți folosi în schimb [[Special:EditWatchlist|editorul standard]].',
 'version-hook-subscribedby' => 'Subscris de',
 'version-version' => '(Versiune $1)',
 'version-license' => 'Licență',
-'version-poweredby-credits' => "Acest wiki este dezvoltat de '''[//www.mediawiki.org/ MediaWiki]''', drepturi de autor © 2001-$1 $2.",
+'version-poweredby-credits' => "Acest wiki este motorizat de '''[https://www.mediawiki.org/ MediaWiki]''', drepturi de autor © 2001-$1 $2.",
 'version-poweredby-others' => 'alții',
 'version-poweredby-translators' => 'traducătorii de la translatewiki.net',
 'version-credits-summary' => 'Am dori să amintim următoarele persoane pentru contribuțiile aduse proiectului [[Special:Version|MediaWiki]].',
@@ -3947,7 +3952,7 @@ MediaWiki este distribuit în speranța că va fi folositor, dar FĂRĂ VREO GAR
 # Special:Redirect
 'redirect' => 'Redirecționare după fișier, utilizator sau ID-ul versiunii',
 'redirect-legend' => 'Redirecționare către un fișier sau o pagină',
-'redirect-summary' => 'Această pagină specială vă redirecționează către un fișier (dat fiind un nume de fișier), o pagină (dat fiind ID-ul unei versiuni) sau o pagină de utilizator (dat fiind un ID numeric al utilizatorului).',
+'redirect-summary' => 'Această pagină specială vă redirecționează către un fișier (dat fiind un nume de fișier), o pagină (dat fiind ID-ul unei versiuni) sau o pagină de utilizator (dat fiind un ID numeric al utilizatorului). Utilizare: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] sau [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Du-te',
 'redirect-lookup' => 'Căutare:',
 'redirect-value' => 'Valoare:',
@@ -3969,10 +3974,9 @@ MediaWiki este distribuit în speranța că va fi folositor, dar FĂRĂ VREO GAR
 
 # Special:SpecialPages
 'specialpages' => 'Pagini speciale',
-'specialpages-note' => '----
-* Pagini speciale normale.
-* <span class="mw-specialpagerestricted">Pagini speciale restricționate.</span>
-* <span class="mw-specialpagecached">Pagini speciale aflate doar în memoria cache (pot fi neactualizate).</span>',
+'specialpages-note-top' => 'Legendă',
+'specialpages-note' => '* Pagini speciale normale.
+* <span class="mw-specialpagerestricted">Pagini speciale restricționate.</span>',
 'specialpages-group-maintenance' => 'Întreținere',
 'specialpages-group-other' => 'Alte pagini speciale',
 'specialpages-group-login' => 'Autentificare / creare cont',
@@ -4185,4 +4189,17 @@ MediaWiki este distribuit în speranța că va fi folositor, dar FĂRĂ VREO GAR
 'limitreport-expansiondepth' => 'Cea mai mare profunzime a expansiunii',
 'limitreport-expensivefunctioncount' => 'Număr de funcții de analiză costisitoare',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandare formate',
+'expand_templates_intro' => "Această pagină specială servește la expandarea recursivă a tuturor formatelor dintr-un text. Ea acționează și asupra funcțiilor de analiză (''parser'') de tipul <nowiki>{{</nowiki>#if:...}}, a variabilelor precum <nowiki>{{</nowiki>CURRENTDAY}} și în general asupra oricăror coduri cuprinse între acolade duble.",
+'expand_templates_title' => 'Titlul contextului (de exemplu pentru {{PAGENAME}}):',
+'expand_templates_input' => 'Introduceți textul aici:',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'Ieșire XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Elimină comentariile',
+'expand_templates_remove_nowiki' => 'Suprimă etichetele <nowiki> în rezultat',
+'expand_templates_generate_xml' => 'Arată arborele de analiză XML',
+'expand_templates_preview' => 'Previzualizare',
+
 );
index 0eab3d6..f4d77d3 100644 (file)
@@ -165,8 +165,6 @@ $messages = array(
 'broken-file-category' => 'Pàggene cu collegaminde a le file scuasciate',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Sus a',
 'article' => 'Pàgene de le condenute',
 'newwindow' => "(iapre jndr'à 'na fenestra nova)",
@@ -305,8 +303,6 @@ Vide [[Special:Version|Versione d'a pàgene]].",
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Pigghjete da "$1"',
 'youhavenewmessages' => 'Tu tine $1 ($2).',
-'newmessageslink' => 'messàgge nuève',
-'newmessagesdifflink' => 'urteme cangiaminde',
 'youhavenewmessagesfromusers' => "Tu è $1 da {{PLURAL:$3|'n'otre utende|$3 utinde}} ($2).",
 'youhavenewmessagesmanyusers' => 'Tu è $1 da assaije utinde ($2).',
 'newmessageslinkplural' => "{{PLURAL:$1|'nu messàgge nuève|messàgge nuève}}",
@@ -1189,8 +1185,6 @@ Però fa attenzione purcè l'indice lore sus a {{SITENAME}} ponne condenè pàgg
 'preferences' => 'Me piece accussì',
 'mypreferences' => 'Me piace accussì',
 'prefs-edits' => 'Numere de cangiaminde:',
-'prefsnologin' => 'Non ge sinde colleghete',
-'prefsnologintext' => 'Tu a essere <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} colleghete]</span> pe \'mbostà le preferenze de l\'utinde.',
 'changepassword' => "Cange 'a password",
 'prefs-skin' => 'Skin',
 'skin-preview' => 'Andeprime',
@@ -1492,6 +1486,7 @@ Ce tu 'u mitte, a fatje ca è fatte t'avène ricanusciute.",
 'recentchanges-label-minor' => "Quiste ète 'nu cangiamende stuèdeche",
 'recentchanges-label-bot' => "Stu cangiamende ha state fatte da 'nu bot",
 'recentchanges-label-unpatrolled' => "Stu cangiamende non g'à state angore condrollate",
+'recentchanges-legend-newpage' => '$1 - pàgena nove',
 'rcnote' => "Sotte {{PLURAL:$1|jè '''1''' cangiamende|sonde le urteme '''$1''' cangiaminde}} jndr'à l'urteme{{PLURAL:$2|sciurne|'''$2''' sciurne}}, jndr'à $5, $4.",
 'rcnotefrom' => "Sotte stonne le cangiaminde da '''$2''' (fine a '''$1''' mustrete).",
 'rclistfrom' => 'Fà vedè le urteme cangiaminde partenne da $1',
@@ -2442,7 +2437,6 @@ Pò essere ca già ha state scangellate.",
 $1",
 'undelete-show-file-confirm' => 'Sì secure ca tu vuè ccu vide \'na revisiona scangellate d\'u file "<nowiki>$1</nowiki>" d\'u $2 a le $3?',
 'undelete-show-file-submit' => 'Sine',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'Namespace:',
@@ -2774,7 +2768,7 @@ Cumme urteme case, tu puè pure ausà 'nu collegamende, pe esembie [[{{#Special:
 'allmessagesdefault' => 'Teste de default',
 'allmessagescurrent' => 'Teste corrende',
 'allmessagestext' => "Queste jè 'na liste de tutte le messagge d'u sisteme ca se ponne acchià jndr'à le namespace de MediaUicchi.
-Pe piacere vè vide [//www.mediawiki.org/wiki/Localisation Localizzazione de MediaUicchi] e [//translatewiki.net translatewiki.net] ce tu vuè ccu condrebbuisce a 'a localizzazione de MediaUicchi.",
+Pe piacere vè vide [https://www.mediawiki.org/wiki/Localisation Localizzazione de MediaUicchi] e [//translatewiki.net translatewiki.net] ce tu vuè ccu condrebbuisce a 'a localizzazione de MediaUicchi.",
 'allmessagesnotsupportedDB' => "Sta pàgene non ge pò essere ausate purcè '''\$wgUseDatabaseMessages''' ha state disabbilitate.",
 'allmessages-filter-legend' => 'Filtre',
 'allmessages-filter' => "Filtre cu 'nu state personalizzate:",
@@ -2991,6 +2985,8 @@ Stu fatte ha state causate da 'nu collegamende a 'nu site esterne ca appartene a
 'spam_reverting' => "Turnanne a l'urtema revisione no ge condiene collegaminde a $1",
 'spam_blanking' => 'Tutte le revisiune condènene collegaminde a $1, vacande',
 'spam_deleting' => 'Tutte le revisiune condènene collegaminde a $1, stoche a scangelle',
+'simpleantispam-label' => "Verifiche andi-spam.
+'''NO''' anghiè quiste!",
 
 # Info page
 'pageinfo-title' => '\'Mbormaziune pe "$1"',
@@ -3661,7 +3657,7 @@ $8',
 
 # External editor support
 'edit-externally' => "Cange stu fail usanne n'applicazione esterne",
-'edit-externally-help' => "(Vide le [//www.mediawiki.org/wiki/Manual:External_editors 'struzione de configurazione] pe avèje cchiù dettaglie)",
+'edit-externally-help' => "(Vide le [https://www.mediawiki.org/wiki/Manual:External_editors 'struzione de configurazione] pe avèje cchiù dettaglie)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tutte',
@@ -3940,7 +3936,7 @@ Tu puè pure [[Special:EditWatchlist|ausà 'u cangiatore standàrd]].",
 'version-version' => '(Versione $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Licenze',
-'version-poweredby-credits' => "Sta Uicchi jè fatte da '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Sta Uicchi jè fatte da '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'otre',
 'version-poweredby-translators' => 'tradutture de translatewiki.net',
 'version-credits-summary' => 'Nuje vulesseme acchià le persone seguende pe le lore condrebbute a [[Special:Version|MediaUicchi]].',
@@ -3981,8 +3977,7 @@ Avisse avè ricevute [{{SERVER}}{{SCRIPTPATH}}/COPYING 'na copie d'a GNU (Licenz
 
 # Special:SpecialPages
 'specialpages' => 'Pàggene speciele',
-'specialpages-note' => '----
-* Pàggene speciale normale.
+'specialpages-note' => '* Pàggene speciale normale.
 * <span class="mw-specialpagerestricted">Pàggene speciale cu le restriziune.</span>
 * <span class="mw-specialpagecached">Pàggene speciale in memorie cache (ponne essere vecchie).</span>',
 'specialpages-group-maintenance' => "Report d'a manutenzione",
@@ -4194,4 +4189,21 @@ Ce nò, tu puè ausà 'u module facile aqquà sotte. 'U commende tune avène agg
 'limitreport-expansiondepth' => 'Espanzione massime de profonnetà',
 'limitreport-expensivefunctioncount' => "Analizzatore d'u cunde d'a funzione ca coste assaije",
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Template spannute',
+'expand_templates_intro' => "Sta pàgena speciale pigghie quacche teste e spanne tutte le template jndr'à jidde recorsivamende.<br />
+Jidde spanne pure le funziune de analise cumme<br />
+<code><nowiki>{{</nowiki>#language:…}}</code>, e variabbele cumme <br />
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.<br />
+In pratiche tutte quidde ca stè jndr'à le doppie parendesi graffe.<br />",
+'expand_templates_title' => 'Titele condestuale, pe {{FULLPAGENAME}} ecc.:',
+'expand_templates_input' => 'Teste de input:',
+'expand_templates_output' => 'Resultete',
+'expand_templates_xml_output' => 'XML de output',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Live le commende',
+'expand_templates_remove_nowiki' => "No fà vede le tag <nowiki> jndr'à 'u resultate",
+'expand_templates_generate_xml' => "Fà vedè l'arvule de l'analisi XML",
+'expand_templates_preview' => 'Andeprime',
+
 );
index a595abe..0fccf00 100644 (file)
@@ -93,6 +93,7 @@
  * @author Александр Сигачёв
  * @author Гусейн
  * @author ОйЛ
+ * @author Сай
  * @author Умар
  * @author Чаховіч Уладзіслаў
  * @author לערי ריינהארט
@@ -131,11 +132,11 @@ $namespaceGenderAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Активные_участники' ),
        'Allmessages'               => array( 'Системные_сообщения' ),
+       'AllMyUploads'              => array( 'Все_мои_файлы' ),
        'Allpages'                  => array( 'Все_страницы' ),
        'Badtitle'                  => array( 'Недопустимое_название' ),
        'Blankpage'                 => array( 'Пустая_страница' ),
        'Block'                     => array( 'Заблокировать' ),
-       'Blockme'                   => array( 'Заблокируй_меня' ),
        'Booksources'               => array( 'Источники_книг' ),
        'BrokenRedirects'           => array( 'Разорванные_перенаправления' ),
        'Categories'                => array( 'Категории' ),
@@ -147,10 +148,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Создать_учётную_запись', 'Создать_пользователя', 'Зарегистрироваться' ),
        'Deadendpages'              => array( 'Тупиковые_страницы' ),
        'DeletedContributions'      => array( 'Удалённый_вклад' ),
-       'Disambiguations'           => array( 'Неоднозначности' ),
        'DoubleRedirects'           => array( 'Двойные_перенаправления' ),
        'EditWatchlist'             => array( 'Править_список_наблюдения' ),
        'Emailuser'                 => array( 'Письмо_участнику', 'Отправить_письмо' ),
+       'ExpandTemplates'           => array( 'Развёртка_шаблонов' ),
        'Export'                    => array( 'Экспорт', 'Выгрузка' ),
        'Fewestrevisions'           => array( 'Редко_редактируемые' ),
        'FileDuplicateSearch'       => array( 'Поиск_дубликатов_файлов' ),
@@ -713,12 +714,10 @@ $1',
 'pagetitle' => '$1 — {{SITENAME}}',
 'retrievedfrom' => 'Источник — «$1»',
 'youhavenewmessages' => 'Вы получили $1 ($2).',
-'newmessageslink' => 'новые сообщения',
-'newmessagesdifflink' => 'последнее изменение',
 'youhavenewmessagesfromusers' => 'Вы получили $1 от {{PLURAL:$3|$3 участника|$3 участников}} ($2).',
 'youhavenewmessagesmanyusers' => 'Вы получили $1 от множества пользователей ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|новое сообщение|новые сообщения}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|последнее изменение|последние изменения}}',
+'newmessageslinkplural' => '{{PLURAL:$1|новое сообщение|999=новые сообщения}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|последнее изменение|999=последние изменения}}',
 'youhavenewmessagesmulti' => 'Вы получили новые сообщения на $1',
 'editsection' => 'править',
 'editold' => 'править',
@@ -848,7 +847,8 @@ $2',
 'invalidtitle-knownnamespace' => 'Недопустимый заголовок с пространством имен «$2» и текстом «$3»',
 'invalidtitle-unknownnamespace' => 'Недопустимый заголовок с неизвестным номером пространства $1 и текстом «$2»',
 'exception-nologin' => 'Вы не представились системе',
-'exception-nologin-text' => 'Для просмотра этой станицы или выполнения запрошенного действия необходимо представиться системе.',
+'exception-nologin-text' => 'Необходимо [[Special:Userlogin|представиться]], чтобы иметь доступ к этой странице или действию.',
+'exception-nologin-text-manual' => 'Необходимо $1, чтобы иметь доступ к этой странице или действию.',
 
 # Virus scanner
 'virus-badscanner' => "Ошибка настройки. Неизвестный сканер вирусов: ''$1''",
@@ -887,7 +887,7 @@ $2',
 'logout' => 'Завершение сеанса',
 'userlogout' => 'Завершение сеанса',
 'notloggedin' => 'Вы не представились системе',
-'userlogin-noaccount' => 'Нет учетной записи?',
+'userlogin-noaccount' => 'Нет учётной записи?',
 'userlogin-joinproject' => 'Присоединиться к проекту',
 'nologin' => 'Нет учётной записи? $1.',
 'nologinlink' => 'Создать учётную запись',
@@ -895,7 +895,7 @@ $2',
 'gotaccount' => "Вы уже зарегистрированы? '''$1'''.",
 'gotaccountlink' => 'Представьтесь',
 'userlogin-resetlink' => 'Забыли данные для входа?',
-'userlogin-resetpassword-link' => 'Сброс пароля',
+'userlogin-resetpassword-link' => 'Сбросить ваш пароль?',
 'helplogin-url' => 'Help:Представление системе',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Помощь со входом в систему]]',
 'userlogin-loggedin' => 'Вы уже вошли как {{GENDER:$1|$1}}.
@@ -944,7 +944,7 @@ $2',
 'passwordtooshort' => 'Пароль должен состоять не менее чем из $1 {{PLURAL:$1|символа|символов|символов}}.',
 'password-name-match' => 'Введённый пароль должен отличаться от имени участника.',
 'password-login-forbidden' => 'Использование этого имени участника и пароля запрещено.',
-'mailmypassword' => 'Ð\92Ñ\8bÑ\81лаÑ\82Ñ\8c Ð½Ð¾Ð²Ñ\8bй Ð¿Ð°Ñ\80олÑ\8c Ð¿Ð¾ Ñ\8dлекÑ\82Ñ\80онной Ð¿Ð¾Ñ\87Ñ\82е',
+'mailmypassword' => 'СбÑ\80оÑ\81иÑ\82Ñ\8c Ð¿Ð°Ñ\80олÑ\8c',
 'passwordremindertitle' => 'Напоминание пароля участника {{grammar:genitive|{{SITENAME}}}}',
 'passwordremindertext' => 'Кто-то (вероятно, вы, с IP-адреса $1) запросил создать
 новый пароль для {{grammar:genitive|{{SITENAME}}}} ($4). Для участника $2
@@ -962,14 +962,15 @@ $2',
 Пожалуйста, представьтесь системе заново после получения пароля.',
 'blocked-mailpassword' => 'Редактирование с вашего IP-адреса запрещено, поэтому заблокирована и функция восстановления пароля.',
 'eauthentsent' => 'На указанный адрес электронной почты отправлено письмо. 
¡ледуйте изложенным там инструкциям для подтверждения того, что этот адрес действительно принадлежит вам.',
§Ñ\82об Ð¿Ð¾Ð»Ñ\83Ñ\87аÑ\82Ñ\8c Ð¿Ð¸Ñ\81Ñ\8cма Ð² Ð´Ð°Ð»Ñ\8cнейÑ\88ем, Ñ\81ледуйте изложенным там инструкциям для подтверждения того, что этот адрес действительно принадлежит вам.',
 'throttled-mailpassword' => 'Функция напоминания пароля уже использовалась в течение {{PLURAL:$1|последнего часа|последних $1 часов}}.
 Для предотвращения злоупотреблений, разрешено запрашивать не более одного напоминания за $1 {{PLURAL:$1|час|часа|часов}}.',
 'mailerror' => 'Ошибка при отправке почты: $1',
 'acct_creation_throttle_hit' => 'За сутки с вашего IP-адреса {{PLURAL:$1|была создана $1 учётная запись участника|было создано $1 учётных записей участников|было создано $1 учётных записей участников}}, что является пределом для данного отрезка времени.
 Таким образом, пользователи, обладающие данным IP-адресом, в данный момент больше не могут создавать новых учётных записей.',
-'emailauthenticated' => 'Ваш почтовый адрес подтверждён $2 в $3.',
-'emailnotauthenticated' => 'Ваш адрес электронной почты ещё не был подтверждён, функции вики-движка по работе с эл. почтой отключены.',
+'emailauthenticated' => 'Ваш адрес электронной почты подтверждён $2 в $3.',
+'emailnotauthenticated' => 'Ваш адрес электронной почты ещё не был подтверждён.
+Письма не будут отправляться ни для одной из следующий функций.',
 'noemailprefs' => 'Адрес электронной почты не был указан, функции вики-движка по работе с эл. почтой отключены.',
 'emailconfirmlink' => 'Подтвердить ваш адрес электронной почты',
 'invalidemailaddress' => 'Адрес электронной почты не может быть принят, так как он не соответствует формату.
@@ -1020,7 +1021,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => 'Сброс пароля',
 'passwordreset-text-one' => 'Заполните эту форму, чтобы сбросить свой пароль.',
-'passwordreset-text-many' => '{{PLURAL:$1|Заполните одно из полей для сброса пароля.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Заполните одно из полей для получения временного пароля на e-mail.}}',
 'passwordreset-legend' => 'Сбросить пароль',
 'passwordreset-disabled' => 'Сбросы пароля отключены на этой вики.',
 'passwordreset-emaildisabled' => 'Функции электронной почты отключены в этой вики.',
@@ -1068,9 +1069,9 @@ $2
 
 # Special:ResetTokens
 'resettokens' => 'Сбросить токены',
-'resettokens-text' => 'Ð\92Ñ\8b Ð¼Ð¾Ð¶ÐµÑ\82е Ñ\81бÑ\80оÑ\81иÑ\82Ñ\8c Ñ\82окенÑ\8b, ÐºÐ¾Ñ\82оÑ\80Ñ\8bе Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñ\8fÑ\8eÑ\82 Ð¸Ð¼ÐµÑ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ðº Ð½ÐµÐºÐ¾Ñ\82оÑ\80Ñ\8bм Ð»Ð¸Ñ\87нÑ\8bм Ð´Ð°Ð½Ð½Ñ\8bм, ÐºÐ¾Ñ\82оÑ\80Ñ\8bе Ñ\81вÑ\8fзанÑ\8b Ñ\81 Ð²Ð°Ñ\88ей Ñ\83Ñ\87Ñ\91Ñ\82ной Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8cÑ\8e
+'resettokens-text' => 'Ð\92Ñ\8b Ð¼Ð¾Ð¶ÐµÑ\82е Ñ\81бÑ\80оÑ\81иÑ\82Ñ\8c Ñ\82окенÑ\8b, Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñ\8fÑ\8eÑ\89ие Ð¿Ð¾Ð»Ñ\83Ñ\87иÑ\82Ñ\8c Ð´Ð¾Ñ\81Ñ\82Ñ\83п Ðº Ð½ÐµÐºÐ¾Ñ\82оÑ\80Ñ\8bм Ð»Ð¸Ñ\87нÑ\8bм Ð´Ð°Ð½Ð½Ñ\8bм, Ñ\81вÑ\8fзаннÑ\8bм Ñ\81 Ð²Ð°Ñ\88ей Ñ\83Ñ\87Ñ\91Ñ\82ной Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8cÑ\8e Ð½Ð° Ñ\8dÑ\82ом Ñ\81айÑ\82е.
 
-Вам необходимо сделать это, если вы случайно поделился ими с кем-то, или если ваш аккаунт был взломан.',
+Вам необходимо сделать это, если вы случайно поделились ими с кем-то, или если ваша учётная запись была взломана.',
 'resettokens-no-tokens' => 'Нет токенов для сброса.',
 'resettokens-legend' => 'Сбросить токены',
 'resettokens-tokens' => 'Токены:',
@@ -1411,19 +1412,19 @@ $3 {{GENDER:$3|указал|указала}} следующую причину:
 Администраторы проекта {{SITENAME}} будут иметь доступ к скрытому содержанию и смогут восстановить его через этот же интерфейс, за исключением случаев, когда установлено дополнительное ограничение.",
 'revdelete-confirm' => 'Пожалуйста, подтвердите, что вы действительно желаете совершить это действие, осознаёте последствия, делаете это в соответствии с [[{{MediaWiki:Policy-url}}|правилами]].',
 'revdelete-suppress-text' => "Сокрытие может производиться '''только''' в следующих случаях:
-
+* Потенциально клеветническая информация
 * Неуместная личная информация
 *: ''домашний адрес, номера телефонов, номер паспорта и т. д.''",
 'revdelete-legend' => 'Установить ограничения:',
-'revdelete-hide-text' => 'СкÑ\80Ñ\8bÑ\82Ñ\8c Ñ\82екÑ\81Ñ\82 Ñ\8dÑ\82ой Ð²ÐµÑ\80Ñ\81ии Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\8b',
+'revdelete-hide-text' => 'ТекÑ\81Ñ\82 Ð¿Ñ\80авки',
 'revdelete-hide-image' => 'Скрыть содержимое файла',
 'revdelete-hide-name' => 'Скрыть действие и его объект',
-'revdelete-hide-comment' => 'СкÑ\80Ñ\8bÑ\82Ñ\8c Ð¾писание изменений',
-'revdelete-hide-user' => 'СкÑ\80Ñ\8bÑ\82Ñ\8c Ð¸Ð¼Ñ\8f Ð°Ð²Ñ\82оÑ\80а',
+'revdelete-hide-comment' => 'Ð\9eписание изменений',
+'revdelete-hide-user' => 'Ð\98мÑ\8f Ñ\83Ñ\87аÑ\81Ñ\82ника/IP-адÑ\80еÑ\81',
 'revdelete-hide-restricted' => 'Скрыть данные также и от администраторов',
 'revdelete-radio-same' => '(не изменять)',
-'revdelete-radio-set' => 'Ð\94а',
-'revdelete-radio-unset' => 'Ð\9dеÑ\82',
+'revdelete-radio-set' => 'СкÑ\80Ñ\8bÑ\82аÑ\8f',
+'revdelete-radio-unset' => 'Ð\92идимаÑ\8f',
 'revdelete-suppress' => 'Скрывать данные также и от администраторов',
 'revdelete-unsuppress' => 'Снять ограничения с восстановленных версий',
 'revdelete-log' => 'Причина:',
@@ -1577,8 +1578,7 @@ $1",
 'preferences' => 'Настройки',
 'mypreferences' => 'Настройки',
 'prefs-edits' => 'Количество правок:',
-'prefsnologin' => 'Вы не представились системе',
-'prefsnologintext' => 'Вы должны <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} представиться системе]</span>, чтобы изменять настройки участника.',
+'prefsnologintext2' => 'Необходимо $1, чтобы изменять настройки.',
 'changepassword' => 'Изменение пароля',
 'prefs-skin' => 'Тема оформления',
 'skin-preview' => 'Предпросмотр',
@@ -1866,7 +1866,7 @@ $1",
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|изменение|изменения|изменений}}',
-'enhancedrc-since-last-visit' => '$1 с последнего посещения',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|с последнего посещения}}',
 'enhancedrc-history' => 'история',
 'recentchanges' => 'Свежие правки',
 'recentchanges-legend' => 'Настройки свежих правок',
@@ -1877,6 +1877,9 @@ $1",
 'recentchanges-label-minor' => 'Это незначительное изменение',
 'recentchanges-label-bot' => 'Эта правка сделана ботом',
 'recentchanges-label-unpatrolled' => 'Эта правку ещё никем не патрулировалась',
+'recentchanges-label-plusminus' => 'Размер страницы изменился на данное количество байт',
+'recentchanges-legend-newpage' => '(см. также [[Special:NewPages|список новых страниц]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "{{PLURAL:$1|Последнее '''$1''' изменение|Последние '''$1''' изменения|Последние '''$1''' изменений}} за '''$2''' {{PLURAL:$2|день|дня|дней}}, на момент времени $5 $4.",
 'rcnotefrom' => "Ниже перечислены изменения с '''$2''' (не более '''$1''').",
 'rclistfrom' => 'Показать изменения с $1.',
@@ -2606,9 +2609,9 @@ $PAGEINTRO $NEWPAGE
 эл. почта: $PAGEEDITOR_EMAIL
 вики: $PAGEEDITOR_WIKI
 
\95Ñ\81ли Ð²Ñ\8b Ð½Ðµ Ð¿Ð¾Ñ\81еÑ\82иÑ\82е Ñ\8dÑ\82Ñ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83, Ñ\82о в случае её дальнейших изменений уведомлений больше не будет. Вы можете также отключить опцию уведомления для всех страниц в вашем списке наблюдения.
\95Ñ\81ли Ð²Ñ\8b Ð½Ðµ Ð·Ð°Ð¹Ð´Ñ\91Ñ\82е Ð½Ð° Ñ\8dÑ\82Ñ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 Ð¿Ð¾Ð´ Ñ\81воей Ñ\83Ñ\87Ñ\91Ñ\82ной Ð·Ð°Ð¿Ð¸Ñ\81Ñ\8cÑ\8e, в случае её дальнейших изменений уведомлений больше не будет. Вы можете также отключить опцию уведомления для всех страниц в вашем списке наблюдения.
 
-             Система оповещения {{grammar:genitive|{{SITENAME}}}}
+Система оповещения {{grammar:genitive|{{SITENAME}}}}
 
 --
 Изменение настройки уведомлений
@@ -3124,7 +3127,7 @@ $1',
 'allmessagesdefault' => 'Текст по умолчанию',
 'allmessagescurrent' => 'Текущий текст',
 'allmessagestext' => 'Это список системных сообщений, доступных в пространстве имён «MediaWiki».
-Если вы хотите внести вклад в общую локализацию MediaWiki, пожалуйста, посетите страницу [//www.mediawiki.org/wiki/Localisation описания локализации] и проект [//translatewiki.net translatewiki.net].',
+Если вы хотите внести вклад в общую локализацию MediaWiki, пожалуйста, посетите страницу [https://www.mediawiki.org/wiki/Localisation описания локализации] и проект [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => "Эта страница недоступна, так как отключена опция '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Фильтр',
 'allmessages-filter' => 'Фильтр по статусу изменения:',
@@ -3285,7 +3288,7 @@ $2',
 'tooltip-undo' => 'Убрать внесённую правку и показать предпросмотр, с возможностью указать причину отмены',
 'tooltip-preferences-save' => 'Сохранить настройки',
 'tooltip-summary' => 'Введите краткое описание',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Размещённый здесь CSS будет применяться ко всем темам оформления */',
@@ -3336,6 +3339,8 @@ The wiki server can't provide data in a format your client can read.",
 'spam_reverting' => 'Откат к последней версии, не содержащей ссылки на $1',
 'spam_blanking' => 'Все версии содержат ссылки на $1, очистка',
 'spam_deleting' => 'Все версии содержали ссылки на $1, производится удаление',
+'simpleantispam-label' => "Анти-спам проверка.
+'''НЕ''' заполняйте это!",
 
 # Info page
 'pageinfo-title' => 'Сведения по «$1»',
@@ -3349,6 +3354,7 @@ The wiki server can't provide data in a format your client can read.",
 'pageinfo-length' => 'Длина страницы (в байтах)',
 'pageinfo-article-id' => 'Идентификатор страницы',
 'pageinfo-language' => 'Язык страницы',
+'pageinfo-content-model' => 'Модель содержимого страницы',
 'pageinfo-robot-policy' => 'Индексация поисковыми роботами',
 'pageinfo-robot-index' => 'Разрешено',
 'pageinfo-robot-noindex' => 'Не разрешено',
@@ -3436,7 +3442,7 @@ $1',
 'svg-long-desc' => 'SVG-файл, номинально $1 × $2 {{PLURAL:$2|пиксель|пикселя|пикселей}}, размер файла: $3',
 'svg-long-desc-animated' => 'Анимированный SVG-файл, номинально $1 × $2 {{PLURAL:$2|пиксель|пикселя|пикселей}}, размер файла: $3',
 'svg-long-error' => 'неправильный SVG-файл: $1',
-'show-big-image' => 'Изображение в более высоком разрешении',
+'show-big-image' => 'Исходный файл',
 'show-big-image-preview' => 'Размер при предпросмотре: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Другое разрешение|Другие разрешения}}: $1.',
 'show-big-image-size' => '$1 × $2 пикселей',
@@ -3911,7 +3917,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Редактировать этот файл, используя внешнюю программу',
-'edit-externally-help' => '(подробнее см. в [//www.mediawiki.org/wiki/Manual:External_editors руководстве по установке])',
+'edit-externally-help' => '(подробнее см. в [https://www.mediawiki.org/wiki/Manual:External_editors руководстве по установке])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'все',
@@ -4021,6 +4027,7 @@ $5
 'word-separator' => '&#32;',
 'ellipsis' => '…',
 'parentheses' => '($1)',
+'quotation-marks' => '«$1»',
 
 # Multipage image navigation
 'imgmultipageprev' => '← предыдущая страница',
@@ -4177,7 +4184,7 @@ $5
 'version-hook-subscribedby' => 'Подписан на',
 'version-version' => '(Версия $1)',
 'version-license' => 'Лицензия',
-'version-poweredby-credits' => "Эта вики работает на движке '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Эта вики работает на движке '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'другие',
 'version-poweredby-translators' => 'переводчики translatewiki.net',
 'version-credits-summary' => 'Хотим поблагодарить следующих участников за их вклад в развитие [[Special:Version|MediaWiki]].',
@@ -4198,7 +4205,8 @@ MediaWiki распространяется в надежде, что она бу
 # Special:Redirect
 'redirect' => 'Перенаправление с файла, участника или идентификатора версии',
 'redirect-legend' => 'Перенаправление на файл или страницу',
-'redirect-summary' => 'Эта специальная страница перенаправляет на файл (с имени файла), страницу (с идентификатора версии) или страницу участника (с числового идентификатора участника).',
+'redirect-summary' => 'Эта специальная страница перенаправляет на файл (с имени файла), страницу (с идентификатора версии) или страницу участника (с числового идентификатора участника).
+Использование: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] или [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Перейти',
 'redirect-lookup' => 'Поиск:',
 'redirect-value' => 'Значение:',
@@ -4220,10 +4228,9 @@ MediaWiki распространяется в надежде, что она бу
 
 # Special:SpecialPages
 'specialpages' => 'Спецстраницы',
-'specialpages-note' => '----
-* Обычные служебные страницы.
-* <span class="mw-specialpagerestricted">Служебные страницы с ограниченным доступом.</span>
-* <span class="mw-specialpagecached">Закэшированные служебные страницы (могут быть устаревшими).</span>',
+'specialpages-note-top' => 'Легенда',
+'specialpages-note' => '* Обычные служебные страницы.
+* <span class="mw-specialpagerestricted">Служебные страницы с ограниченным доступом.</span>',
 'specialpages-group-maintenance' => 'Отчёты технического обслуживания',
 'specialpages-group-other' => 'Другие служебные страницы',
 'specialpages-group-login' => 'Представиться / Зарегистрироваться',
@@ -4436,4 +4443,20 @@ MediaWiki распространяется в надежде, что она бу
 'limitreport-expansiondepth' => 'Наибольшая глубина расширения',
 'limitreport-expensivefunctioncount' => 'Количество «дорогих» функций анализатора',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Развёртка шаблонов',
+'expand_templates_intro' => 'Эта служебная страница преобразует текст, рекурсивно разворачивая все шаблоны в нём.
+Также развёртке подвергаются функции парсера
+<code><nowiki>{{#language:…}}</nowiki></code> и переменные вида
+<code><nowiki>{{CURRENTDAY}}</nowiki></code> — в общем, всё внутри двойных фигурных скобок.',
+'expand_templates_title' => 'Заголовок страницы для {{FULLPAGENAME}} и т. п.:',
+'expand_templates_input' => 'Входной текст:',
+'expand_templates_output' => 'Результат',
+'expand_templates_xml_output' => 'XML вывод',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Удалить комментарии',
+'expand_templates_remove_nowiki' => 'Подавлять теги <nowiki> в результате',
+'expand_templates_generate_xml' => 'Показать дерево разбора XML',
+'expand_templates_preview' => 'Предпросмотр',
+
 );
index a82354e..b3a95d9 100644 (file)
@@ -51,7 +51,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Планый_тітул' ),
        'Blankpage'                 => array( 'Порожня_сторінка' ),
        'Block'                     => array( 'Заблоковати' ),
-       'Blockme'                   => array( 'Заблокуйте_ня' ),
        'Booksources'               => array( 'Жрідла_книг' ),
        'BrokenRedirects'           => array( 'Розорваны_напрямлїня' ),
        'Categories'                => array( 'Катеґорії' ),
@@ -63,7 +62,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Створити_конто' ),
        'Deadendpages'              => array( 'Сторінкы_без_одказів' ),
        'DeletedContributions'      => array( 'Вымазаный_вклад' ),
-       'Disambiguations'           => array( 'Неєднозначны_одказы' ),
        'DoubleRedirects'           => array( 'Подвійны_напрямлїня' ),
        'EditWatchlist'             => array( 'Правити_список_мерькованя' ),
        'Emailuser'                 => array( 'Писмо_хоснователёви' ),
@@ -391,8 +389,6 @@ $1',
 'ok' => 'ОК',
 'retrievedfrom' => 'Обтримане з "$1"',
 'youhavenewmessages' => 'Маєте $1 ($2).',
-'newmessageslink' => 'новы повідомлїня',
-'newmessagesdifflink' => 'послїдня зміна',
 'youhavenewmessagesfromusers' => 'Мате $1 од {{PLURAL:$3|іншого хоснователя|$3 іншых хоснователїв}} ($2).',
 'youhavenewmessagesmanyusers' => 'Мате $1 од много далшых хоснователїв ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлїня|новы повідомлїня}}',
@@ -1226,8 +1222,6 @@ $1",
 'preferences' => 'Наставлїня',
 'mypreferences' => 'Наставлїня',
 'prefs-edits' => 'Чісло едітовань:',
-'prefsnologin' => 'Не сьте приголошеный(а)!',
-'prefsnologintext' => 'Кідь хочете мінити хосновательскы наставлїня, мусите ся <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} приголосити]</span>.',
 'changepassword' => 'Змінити гесло',
 'prefs-skin' => 'Взгляд',
 'skin-preview' => 'Попереднїй нагляд',
@@ -1526,6 +1520,7 @@ $1",
 'recentchanges-label-minor' => 'Тото є мала зміна',
 'recentchanges-label-bot' => 'Тото едітованя зроблене ботом',
 'recentchanges-label-unpatrolled' => 'Тота зміна дотеперь не была патролёвана.',
+'recentchanges-legend-newpage' => '$1 — нова сторінка',
 'rcnote' => "{{PLURAL:$1|Послїдня '''$1''' зміна|Послїднї '''$1''' зміны|Послїднїх '''$1''' змін}} за '''$2''' {{PLURAL:$2|день|днї|днїв}}, на час $5, $4.",
 'rcnotefrom' => 'Ниже {{PLURAL:$1|є|суть|є}} найвеце <b>$1</b> {{PLURAL:$1|зміна|зміны|змін}} од <b>$2</b>.',
 'rclistfrom' => 'Вказати едітованя почінаючі з $1.',
@@ -2738,7 +2733,7 @@ $1',
 'allmessagesdefault' => 'Штандартный текст',
 'allmessagescurrent' => 'Актуалный текст',
 'allmessagestext' => 'Тото є список вшыткых повідомлїнь доступных в просторї назв «MediaWiki».
-Кідь хочете приспівати ку локалізації софтверу MediaWiki, навщівте [//www.mediawiki.org/wiki/Localisation локалізачну сторінку на mediawiki.org] і [//translatewiki.net сервер server translatewiki.net].',
+Кідь хочете приспівати ку локалізації софтверу MediaWiki, навщівте [https://www.mediawiki.org/wiki/Localisation локалізачну сторінку на mediawiki.org] і [//translatewiki.net сервер server translatewiki.net].',
 'allmessagesnotsupportedDB' => '{{ns:special}}:AllMessages не є підпороване, бо wgUseDatabaseMessages є выпнуте.',
 'allmessages-filter-legend' => 'Філтер',
 'allmessages-filter' => 'Філтер за станом:',
@@ -2922,6 +2917,8 @@ $2',
 'spam_reverting' => 'Реверт на послїдню верзію необсягуючу одказы на $1',
 'spam_blanking' => 'Вшыткы ревізії обсяговали одказы на $1, выпорожнєны',
 'spam_deleting' => 'Вшыткы ревізії обсяговали одказы на $1, змазане',
+'simpleantispam-label' => "Перевірка на спам.
+'''НЕ''' заповнюйте тото!",
 
 # Info page
 'pageinfo-title' => 'Інформація про "$1"',
@@ -3484,7 +3481,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Едітовати тот файл хоснувчі екстерну аплікацію',
-'edit-externally-help' => '(Веце інформацій найдете в [//www.mediawiki.org/wiki/Manual:External_editors інштрукції про наставлїня].)',
+'edit-externally-help' => '(Веце інформацій найдете в [https://www.mediawiki.org/wiki/Manual:External_editors інштрукції про наставлїня].)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'вшыткы',
@@ -3662,7 +3659,7 @@ $5
 'version-hook-subscribedby' => 'Підписаный на',
 'version-version' => '(Верзія $1)',
 'version-license' => 'Ліценція',
-'version-poweredby-credits' => "Тота вікі біжыть на '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Тота вікі біжыть на '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'іншы',
 'version-poweredby-translators' => 'перекладателї на translatewiki.net',
 'version-credits-summary' => 'Слїдуючім людям бы сьме радо подяковали за їх приспівкы [[Special:Version|MediaWiki]].',
@@ -3703,8 +3700,7 @@ MediaWiki є дістрібуована в надїї, же буде хосно
 
 # Special:SpecialPages
 'specialpages' => 'Шпеціалны сторінкы',
-'specialpages-note' => '----
-* Звычайны шпеціалны сторінкы.
+'specialpages-note' => '* Звычайны шпеціалны сторінкы.
 * <span class="mw-specialpagerestricted">Шпеціалны сторінкы з&nbsp;обмедженым приступом</span>
 * <span class="mw-specialpagecached">Кешованы шпеціалны сторінкы</span>',
 'specialpages-group-maintenance' => 'Технічны репорты',
@@ -3914,4 +3910,17 @@ MediaWiki є дістрібуована в надїї, же буде хосно
 'limitreport-expansiondepth' => 'Найвысша глубка росшырїня',
 'limitreport-expensivefunctioncount' => 'Чісло дорогой функції аналізатора',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Розгортаня шаблон',
+'expand_templates_intro' => 'Тота шпеціална сторінка перетворює текст, рекурзівно розгортаювші у ній вшыткы шаблоны як <code><nowiki>{{</nowiki>#language:…...}}</code> ці перемінны як <code><nowiki>{{</nowiki>CURRENTDAY}}</code> – тзн. практічно вшытко у двоїтых заперках. Ку тому ся хоснують прямо одповідаючі функціі парсера MediaWiki.',
+'expand_templates_title' => 'Назва сторінкы про контекст про {{FULLPAGENAME}} ітд.:',
+'expand_templates_input' => 'Вступный текст:',
+'expand_templates_output' => 'Резултат',
+'expand_templates_xml_output' => 'XML-выступ',
+'expand_templates_ok' => 'ОК',
+'expand_templates_remove_comments' => 'Одстранити коментарї',
+'expand_templates_remove_nowiki' => 'Іґноровати в резултатї значкы <nowiki>',
+'expand_templates_generate_xml' => 'Указати сінтаксічный стром в XML',
+'expand_templates_preview' => 'Нагляд',
+
 );
index 15635a1..3ff6808 100644 (file)
@@ -87,7 +87,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'पूर्वतनपृष्टानि' ),
        'Blankpage'                 => array( 'रिक्तपृष्ठ' ),
        'Block'                     => array( 'सदस्यप्रतिबन्ध' ),
-       'Blockme'                   => array( 'मदर्थेप्रतिबन्ध' ),
        'Booksources'               => array( 'पुस्तकस्रोत' ),
        'BrokenRedirects'           => array( 'खण्डीतपुनर्निर्देशन' ),
        'Categories'                => array( 'वर्गः' ),
@@ -97,9 +96,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'सृज्उपयोजकसंज्ञा' ),
        'Deadendpages'              => array( 'निराग्रपृष्टानि' ),
        'DeletedContributions'      => array( 'परित्यागितयोगदान' ),
-       'Disambiguations'           => array( 'नि:संदिग्धीकरण' ),
        'DoubleRedirects'           => array( 'पुनर्निर्देशनद्वंद्व' ),
        'Emailuser'                 => array( 'विपत्रयोजक' ),
+       'ExpandTemplates'           => array( 'बिंबधरविस्तारकरोसि' ),
        'Export'                    => array( 'निर्यात' ),
        'Fewestrevisions'           => array( 'स्वल्पपरिवर्तन' ),
        'FileDuplicateSearch'       => array( 'अनुकृतसंचिकाशोध' ),
@@ -139,6 +138,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'सुरक्षितपृष्टानि' ),
        'Protectedtitles'           => array( 'सुरक्षितशिर्षकम्' ),
        'Randompage'                => array( 'अविशीष्टपृष्ठम्' ),
+       'RandomInCategory'          => array( 'अविशिष्टवर्ग' ),
        'Randomredirect'            => array( 'अविशीष्टविचालन्‌' ),
        'Recentchanges'             => array( 'नवीनतम_परिवर्तन' ),
        'Recentchangeslinked'       => array( 'नवीनतमसम्भन्दिन_परिवर्त' ),
@@ -537,8 +537,6 @@ $1',
 'pagetitle' => '$1 - {{SITENAME}}',
 'retrievedfrom' => '"$1" इत्यस्माद् उद्धृतम्',
 'youhavenewmessages' => 'भवदर्थम् $1 सन्ति। ($2).',
-'newmessageslink' => 'नूतनाः सन्देशाः',
-'newmessagesdifflink' => 'अन्तिमं परिवर्तनम्',
 'youhavenewmessagesfromusers' => 'भवदर्थम् {{PLURAL:$3|अन्यस्मात् सदस्यात्|$3 सदस्येभ्यः}} $1 अस्ति ($2)।',
 'youhavenewmessagesmanyusers' => 'नैकेभ्यः योजकेभ्यः ते $1 सन्ति $2 ।',
 'newmessageslinkplural' => '{{PLURAL:$1|नूतनः सन्देशः|नूतनसन्देशाः}}',
@@ -1304,8 +1302,6 @@ You can still [$1 view this revision]",
 'preferences' => 'इष्टतमानि',
 'mypreferences' => 'मम इष्टतमानि',
 'prefs-edits' => 'सम्पादनानां सख्याः',
-'prefsnologin' => 'नैव प्रविष्ट',
-'prefsnologintext' => 'वरीयतां परिवर्तयितुं भवता <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}}नामाभिलेखः]</span> करणियः।',
 'changepassword' => 'कूटशब्दः परिवर्त्यताम्',
 'prefs-skin' => 'त्वक्',
 'skin-preview' => 'प्राग्दृश्यम्',
@@ -2787,7 +2783,7 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'allmessagesname' => 'नाम',
 'allmessagesdefault' => 'डिफॉल्टसन्देशपाठ',
 'allmessagescurrent' => 'सद्यः सन्देशपाठः ।',
-'allmessagestext' => 'एषा मीडियाविकिनामस्थाने उपलब्धा काचित् तन्त्रसन्देशस्य सूचिका अस्ति ।  यदि भवान् सामान्यमीडियाविकि क्षेत्रीयकरणे योगदानं कर्तुमिच्छति तर्हि[//www.mediawiki.org/wiki/Localisation मीडियाविकि क्षेत्रीयकरणम्] अथवा [//translatewiki.net translatewiki.net] इत्यत्र गच्छतु ।',
+'allmessagestext' => 'एषा मीडियाविकिनामस्थाने उपलब्धा काचित् तन्त्रसन्देशस्य सूचिका अस्ति ।  यदि भवान् सामान्यमीडियाविकि क्षेत्रीयकरणे योगदानं कर्तुमिच्छति तर्हि[https://www.mediawiki.org/wiki/Localisation मीडियाविकि क्षेत्रीयकरणम्] अथवा [//translatewiki.net translatewiki.net] इत्यत्र गच्छतु ।',
 'allmessagesnotsupportedDB' => "अस्य पुटस्य उपयोगः नैव शक्यते यतः '''\$wgUseDatabaseMessages''' तटास्थम् अस्ति ।",
 'allmessages-filter-legend' => 'शोधनी ।',
 'allmessages-filter' => 'ग्राहकीकरणस्य स्थितौ शोधनी ।',
@@ -2974,6 +2970,8 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 'spam_reverting' => '$1 इत्यनेन नानुबद्धनां प्राचीनपुनरावृत्तीनां पुनस्थापनं कुर्वन्ति ।',
 'spam_blanking' => 'सर्वाः पुनरावृत्तयः $1 इत्यस्य अनुबन्धाः पूर्णपाठाः अपनीयन्ते ।',
 'spam_deleting' => 'सर्वाः पुनरावृत्तयः $1 इत्यस्य अनुबन्धाः । पूर्णपाठाः अपनीयन्ते ।',
+'simpleantispam-label' => "अनिष्टसन्देशविरोधपरीक्षणम् ।
+अस्मिन् '''नहि''' पूर्यताम् !",
 
 # Info page
 'pageinfo-title' => '"$1" कृते सूचनाः ।',
@@ -3521,7 +3519,7 @@ $2 इति प्रकारस्य अवरोधं कर्तुं 
 
 # External editor support
 'edit-externally' => 'बाह्यां प्रणालीम् उपयुज्य इयं सञ्चिका सम्पाद्यताम् ।',
-'edit-externally-help' => '(अधिकासूचनार्थं [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] इत्येतत् दृश्यताम्)',
+'edit-externally-help' => '(अधिकासूचनार्थं [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] इत्येतत् दृश्यताम्)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'सर्वाणि',
@@ -3698,9 +3696,9 @@ $5
 'version-hook-subscribedby' => 'सदस्यत्वम् अनेन प्राप्तम् ।',
 'version-version' => '(आवृत्तिः$1)',
 'version-license' => 'अनुज्ञापत्रम्',
-'version-poweredby-credits' => "इयं विकिः अनेन सञ्चालिता '''[//www.mediawiki.org/ MediaWiki]''', स्वामित्वम् © 2001 - $1  $2 ।",
+'version-poweredby-credits' => "इयं विकिः अनेन सञ्चालिता '''[https://www.mediawiki.org/ MediaWiki]''', स्वामित्वम् © 2001 - $1  $2 ।",
 'version-poweredby-others' => 'अन्य',
-'version-credits-summary' => '[[Special:Version|MediaWiki] इत्यत्र योगदानार्थं वयं अधोलिखितान् जनान् प्रशंसितुमिच्छामः।',
+'version-credits-summary' => '[[Special:Version|MediaWiki]] इत्यत्र योगदानार्थं वयं अधोलिखितान् जनान् प्रशंसितुमिच्छामः।',
 'version-license-info' => 'मिडियाविकिः तु निश्शुल्कतन्त्रांशः ; भवान् पुनः वितर्तुं शक्नोति अथवा GNU सामान्यसार्वजनिकानुज्ञपत्रस्य नियमानुगुणं द्वीतीयावृत्तिम् अथवा अन्यनूतनावृतिं संस्कर्तुं शक्नोति । 
 
 एषा बहूपयोगाय भवेत् इति धिया मिडियाविकिः वितीर्णा । किन्तु केनापि प्रमाणत्वेन विना दत्ता । अथवा निर्दिष्टोद्देशर्थे अनुकूलकरं वेति अपरिशील्य अथवा वाणिज्यस्य आनुषङ्गिकानुज्ञापत्रेण विना अपि मीडियाविकिः प्रदत्ता । विशेषविवरणप्राप्तये GNU सर्वजनसामान्यम् अनुज्ञापत्रं पश्यतु ।
@@ -3726,8 +3724,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'विशेषपृष्ठानि',
-'specialpages-note' => '----
-* साधारणं विशेषपुटम् । 
+'specialpages-note' => '* साधारणं विशेषपुटम् । 
 * <span class="mw-specialpagerestricted">प्रतिद्धं विशेषपुटम् ।</span>',
 'specialpages-group-maintenance' => 'निर्वहणवृत्तानि ।',
 'specialpages-group-other' => 'अन्यविशेषपुटानि ।',
@@ -3915,4 +3912,9 @@ $1 इत्यनेन $3 इति पृष्ठम् $4 इत्ये
 'duration-centuries' => '$1 {{PLURAL:$1|शतकम्|शतकानि}}',
 'duration-millennia' => '$1 {{PLURAL:$1|सहस्राब्धः|सहस्राब्धाः}}',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'परिणामम्',
+'expand_templates_ok' => 'अस्तु',
+'expand_templates_preview' => 'प्राग्दृश्यम् दर्श्यताम्',
+
 );
index ebc7d1c..a9df4d0 100644 (file)
@@ -261,7 +261,7 @@ $messages = array(
 'articlepage' => 'Ыстатыйаны көр',
 'talk' => 'Ырытыы',
 'views' => 'Көрүүлэр',
-'toolbox' => 'Үнүстүрүмүөннэр',
+'toolbox' => 'Сэп-сэбиргэл',
 'userpage' => 'Кыттааччы туһунан сирэй',
 'projectpage' => 'Бырайыак сирэйэ',
 'imagepage' => 'Билэ сирэйин көрүү',
@@ -291,7 +291,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}} туһунан',
 'aboutpage' => 'Project:туһунан',
-'copyright' => 'Ð\9cанÑ\8b Ñ\82Ñ\83һанаÑ\80Ñ\8b $1 ÐºÓ©Ò¥Ò¯Ð»Ð»Ò¯Ò¯Ñ\80.',
+'copyright' => 'Ð\9cанÑ\8b Ñ\82Ñ\83һанаÑ\80Ñ\8b $1 Ð»Ð¸Ñ\81Ñ\81иÑ\8dнÑ\81ийÑ\8d ÐºÓ©Ò¥Ò¯Ð»Ð»Ò¯Ò¯Ñ\80 (аÑ\82Ñ\8bн Ñ\8bйÑ\8bллÑ\8bбÑ\8bÑ\82аÑ\85 Ð±Ñ\83оллаÒ\95Ñ\8bна).',
 'copyrightpage' => '{{ns:project}}:бас билиитэ',
 'currentevents' => 'Туох буола турара',
 'currentevents-url' => 'Project:Сонуннар',
@@ -317,8 +317,6 @@ $1',
 'ok' => 'Сөп',
 'retrievedfrom' => '"$1" -н кэллэ',
 'youhavenewmessages' => '$1 ($2) кэллэ',
-'newmessageslink' => 'саҥа суруктар',
-'newmessagesdifflink' => 'кэлиҥҥи уларытыы',
 'youhavenewmessagesfromusers' => 'Маны $1 {{PLURAL:$3|соҕотох кыттааччыттан|$3 кыттааччыттан}} туппуккун ($2).',
 'youhavenewmessagesmanyusers' => 'Маны $1 элбэх кыттааччыттан туппуккун ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|саҥа этии|саҥа этии}}',
@@ -409,6 +407,7 @@ $1',
 'cannotdelete-title' => '«$1» сирэйи сотор сатаммат',
 'delete-hook-aborted' => 'Көннөрүү төттөрү көннөрүллүбүт.
 Эбии туох да быһаарыллыбатах.',
+'no-null-revision' => '«$1» сирэйгэ кураанах көннөрүүнү оҥорор табыллыбата',
 'badtitle' => 'Табыллыбат аат',
 'badtitletext' => 'Ыйытыллыбыт сирэй аата сыыһа, иччитэх, эбэтэр сыыһа ыйынньыктаах тыллар ыккардыларынааҕы дуу, биикилэр ыккардыларынааҕы дуу аат.',
 'perfcached' => 'Бу кээстэн ылыллыбыт онон бүтэһик уларыйыылары аахсымыан сөп. Кээскэ {{PLURAL:$1|соҕотох суруктан|$1 суруктан}} ордук хараллыбат.',
@@ -497,6 +496,9 @@ $2',
 'userlogin-resetpassword-link' => 'Киирии тылы уларытыы',
 'helplogin-url' => 'Help:Бэлиэ-ааты киллэрии',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Бэлиэтэниигэ көмө]]',
+'userlogin-loggedin' => 'Маннык аатынан киирбиккин {{GENDER:$1|$1}}.
+Атын аатынан киирэргэ аллара көстөр форманы туһан.',
+'userlogin-createanother' => 'Атын аатынан бэлиэтэн',
 'createacct-join' => 'Аллара суруй.',
 'createacct-another-join' => 'Саҥа бэлиэ-аат туһунан аллара суруй.',
 'createacct-emailrequired' => 'Email аадырыс',
@@ -557,7 +559,7 @@ $2',
 Системаҕа саҥа киирии тылы туһанан киир.',
 'blocked-mailpassword' => 'Эн IP аадырыскыттан манна тугу эмэ уларытар бобуллубут,
 онон киирии тылы өйдөтөр кыах эмиэ суох.',
-'eauthentsent' => 'Ð\91Ñ\8bÑ\81Ñ\82аÑ\85 ÐºÑ\8dмҥÑ\8d Ñ\82Ñ\83Ñ\82Ñ\82Ñ\83ллаÑ\80 ÐºÐ¸Ð¸Ñ\80ии Ñ\82Ñ\8bл Ñ\81аҥа ÐºÑ\8bÑ\82Ñ\82ааÑ\87Ñ\87Ñ\8b Ñ\8dл. Ð¿Ð¾Ñ\87Ñ\82аÑ\82Ñ\8bгаÑ\80 ыытылынна.
+'eauthentsent' => 'Эл. Ð¿Ð¾Ñ\87Ñ\82аÒ\95аÑ\80 Ñ\81Ñ\83Ñ\80Ñ\83к ыытылынна.
 Бу аадырыс эйиэнэ буоларын бигэргэтэргэ өссө тугу гыныахтааҕыҥ туһунан сурукка кэпсэниллэр.',
 'throttled-mailpassword' => 'Киирии тылы өйдөтөр тэрил бүтэһик {{PLURAL:$1|чаас|$1 чаас}} иһигэр туттулла сылдьыбыт.
 Көмүскэнэр соруктан сылтаан киирии тылы {{PLURAL:$1|чааска|$1 чааска}} биирдэ эрэ ыйытыахха сөп.',
@@ -1162,8 +1164,6 @@ $1",
 'preferences' => 'Уларытыылар',
 'mypreferences' => 'Туруоруулар',
 'prefs-edits' => 'Көннөрүү ахсаана:',
-'prefsnologin' => 'Ааккын эппэтиҥ',
-'prefsnologintext' => 'Эн <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ааккын эттэххинэ]</span> эрэ кыттаачы туруорууларын уларытар кыахтаныаҥ.',
 'changepassword' => 'Киирии тылы уларытарга',
 'prefs-skin' => 'Тас көстүү',
 'skin-preview' => 'Хайдах буолара',
@@ -1456,6 +1456,7 @@ $1 {{PLURAL:$1|бэлиэттэн|бэлиэттэн (буукубаттан)}}
 'recentchanges-label-minor' => 'Бу улахан суолтата суох уларытыы',
 'recentchanges-label-bot' => 'Бу уларытыыны робот оҥорбут',
 'recentchanges-label-unpatrolled' => 'Бу уларытыы өссө ботурууллана илик',
+'recentchanges-legend-newpage' => '$1 — саҥа сирэй',
 'rcnote' => "{{PLURAL:$2|хонук|'''$2''' хонуктар}} иһинэн бүтэһик {{PLURAL:$1|'''1''' уларыйыы|'''$1''' уларыйыылар}}, $5, $4.",
 'rcnotefrom' => "Мантан '''$2''' маныаха '''$1''' дылы уларыыйылар көрдөрүлүннүлэр.",
 'rclistfrom' => 'Бу кэм $1 кэнниттэн оҥоһуллубуттары көрдөр',
@@ -2701,7 +2702,7 @@ $1',
 'allmessagesdefault' => 'Туспа этиллибэтэҕинэ суруллар тиэкис',
 'allmessagescurrent' => 'Билиҥҥи тиэкис',
 'allmessagestext' => 'Манна MediaWiki биллэриилэрин испииһэгэ көстөр.
-Эн MediaWiki движогун тылбаастыырга көмөлөһүөххүн баҕарар буоллаххына манна [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] уонна манна [//translatewiki.net translatewiki.net] киир.',
+Эн MediaWiki движогун тылбаастыырга көмөлөһүөххүн баҕарар буоллаххына манна [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] уонна манна [//translatewiki.net translatewiki.net] киир.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' туттуллар кыаҕа суох, тоҕо диэтэххэ '''\$wgUseDatabaseMessages''' араарыллыбыт.",
 'allmessages-filter-legend' => 'Сиидэ',
 'allmessages-filter' => 'Уларытыы көрүҥүнэн наардыыр сиидэ:',
@@ -2896,6 +2897,8 @@ $2',
 'spam_reverting' => 'Манна: $1 ыйынньыга суох бүтэһик торуму сөргүтүү (төннөрүү)',
 'spam_blanking' => 'Бары торумнар манна "$1" ыйынньыктаахтар, барытын суох оҥоруу',
 'spam_deleting' => 'Бары барыллар манна "$1" сигэнэллэр эит, сотуу бара турар',
+'simpleantispam-label' => "Анти-спам бэрэбиэркэтэ.
+Маны '''толорумаҥ'''!",
 
 # Info page
 'pageinfo-title' => '"$1" туһунан',
@@ -3460,7 +3463,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Бу билэни таһынааҕы бырагыраамма көмөтүнэн уларытарга',
-'edit-externally-help' => 'Сиһилии бу ыйынньыгынан баран көр: [//www.mediawiki.org/wiki/Manual:External_editors туруоруулар туһунан].',
+'edit-externally-help' => 'Сиһилии бу ыйынньыгынан баран көр: [https://www.mediawiki.org/wiki/Manual:External_editors туруоруулар туһунан].',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'бары',
@@ -3644,7 +3647,7 @@ $5
 'version-hook-subscribedby' => 'Суруттарыыта:',
 'version-version' => '(Торум $1)',
 'version-license' => 'Лиссиэнзийэ',
-'version-poweredby-credits' => "Бу биики бу движокка олоҕурар '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Бу биики бу движокка олоҕурар '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'атыттар',
 'version-poweredby-translators' => 'translatewiki.net тылбаасчыттара',
 'version-credits-summary' => '[[Special:Version|MediaWiki]] сайдыытыгар үлэлэрин иһин манна ахтыллыбыт дьоҥҥо махтанабыт.',
@@ -3684,8 +3687,7 @@ MediaWiki туһалаах буоллун диэн тарҕатыллар, ол
 
 # Special:SpecialPages
 'specialpages' => 'Анал сирэйдэр',
-'specialpages-note' => '----
-* Көннөрү анал сирэйдэр.
+'specialpages-note' => '* Көннөрү анал сирэйдэр.
 * <strong class="mw-specialpagerestricted">Хааччахтардаах анал сирэйдэр.</strong>
 * <span class="mw-specialpagecached">Кээстэммит анал сирэйдэр (эргэрбит буолуохтарын сөп).</span>',
 'specialpages-group-maintenance' => 'Техническэй отчуоттар',
@@ -3882,4 +3884,19 @@ MediaWiki туһалаах буоллун диэн тарҕатыллар, ол
 # Image rotation
 'rotate-comment' => 'Ойуу $1 кыраадыс чаһы хоту эргитиллибит',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Халыыптары тэнитии',
+'expand_templates_intro' => 'Бу аналлаах сирэй тиэкиһи уларытарытарыгар туох баар халыыптары тэнитэн көрдөрөр.
+Парсер функциялара эмиэ тэнитиллэллэр. Холобур, <nowiki>{{</nowiki>#language:...}} уонна переменнайдар <nowiki>{{</nowiki>CURRENTDAY}} уо.&nbsp;д.&nbsp;а. — уопсайынан, хос фигурнай скобка иһигэр баар барыта.
+Бу дьайыы сыыһата суох, MediaWiki көмөтүнэн оҥоһуллар.',
+'expand_templates_title' => '{{FULLPAGENAME}} сирэй аата уонна да атын сибидиэнньэлэр:',
+'expand_templates_input' => 'Киирэр сурук:',
+'expand_templates_output' => 'Түмүк',
+'expand_templates_xml_output' => 'XML тахсыыта',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Ырытыылары сот',
+'expand_templates_remove_nowiki' => 'Түмүккэ <nowiki> бэлиэни аахсыма',
+'expand_templates_generate_xml' => 'XML-ы мас курдук көрдөр',
+'expand_templates_preview' => 'Холоон көрүү',
+
 );
index 0b18a5c..9d46180 100644 (file)
@@ -276,8 +276,6 @@ $1',
 'ok' => 'Ṭhik gea',
 'retrievedfrom' => '"$1" khon ñam ạgui',
 'youhavenewmessages' => 'Amaḱ do $1 ($2) menaḱa',
-'newmessageslink' => 'Nãwã sombat',
-'newmessagesdifflink' => 'Mucạt bodol',
 'youhavenewmessagesmulti' => 'Amaḱ nãwã mesagko do $1 menaḱa',
 'editsection' => 'So̠mpado̠n',
 'editold' => 'So̠mpado̠n',
@@ -1162,7 +1160,7 @@ jeleń',
 
 # External editor support
 'edit-externally' => 'Noa rẽt tońge joṛao lạgitte bahre reaḱ koejoń  beoharme',
-'edit-externally-help' => '(Nonḍe ńelme [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] bạṛtite baḍay lạgit)',
+'edit-externally-help' => '(Nonḍe ńelme [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] bạṛtite baḍay lạgit)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Sanam, sanamak, sanamko',
index bfc2b2b..7eba0ea 100644 (file)
@@ -177,8 +177,6 @@ $messages = array(
 'index-category' => 'Pàginas indicizadas',
 'noindex-category' => 'Pàginas no indicitzadas',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'A propòsitu de',
 'article' => 'Artìculu',
 'newwindow' => '(aberit in una bentana noa)',
@@ -295,8 +293,6 @@ $messages = array(
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Bogau dae  "$1"',
 'youhavenewmessages' => 'Tenes $1 ($2).',
-'newmessageslink' => 'messàgios noos',
-'newmessagesdifflink' => 'ùrtima mudàntzia',
 'youhavenewmessagesmulti' => 'Tenes messàgios noos in $1',
 'editsection' => 'acontza',
 'editold' => 'acontza',
@@ -654,8 +650,6 @@ Prova a seberare ''totu:'' pro chircare in totu su cuntènnidu (inclùdidas pàg
 'preferences' => 'Preferèntzias',
 'mypreferences' => 'Preferèntzias meas',
 'prefs-edits' => 'Nùmeru de acontzos:',
-'prefsnologin' => 'Non ses intrau',
-'prefsnologintext' => 'Depes èsser <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} intradu]</span> pro seberare is preferèntzias.',
 'changepassword' => 'Càmbia password',
 'prefs-skin' => 'Bisura',
 'skin-preview' => 'Antiprima',
@@ -777,6 +771,7 @@ Prova a seberare ''totu:'' pro chircare in totu su cuntènnidu (inclùdidas pàg
 'recentchanges-label-newpage' => 'Custu acontzu at creadu una pàgina noa',
 'recentchanges-label-minor' => 'Custu est unu acontzu minore',
 'recentchanges-label-bot' => 'Custu acontzu est stadu fatu dae unu bot',
+'recentchanges-legend-newpage' => '$1 - pàgina noa',
 'rcnote' => "Inoghe sighende {{PLURAL:$1|b'est s'ùrtima mudàntzia|bi sunt is ùrtimas '''$1''' mudàntzias}} {{PLURAL:$2|in s'ùrtima die|in is ùrtimas '''$2''' dies}}; is datos sunt agiornados a  $5, $4.",
 'rcnotefrom' => "Sas chi sighint sunt sas mudàntzias dae '''$2''' (fintzas a '''$1''').",
 'rclistfrom' => 'Ammustra mudàntzias dae $1',
@@ -1443,7 +1438,7 @@ Is acàpius chi sighint in sa matessi lìnia sunt cunsideraus comente eccetzione
 
 # External editor support
 'edit-externally' => 'Acontza custu file usendi unu programma de foras',
-'edit-externally-help' => '(Pro àteras informatziones càstia is [//www.mediawiki.org/wiki/Manual:External_editors istrutziones])',
+'edit-externally-help' => '(Pro àteras informatziones càstia is [https://www.mediawiki.org/wiki/Manual:External_editors istrutziones])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'totu',
@@ -1527,4 +1522,7 @@ Is acàpius chi sighint in sa matessi lìnia sunt cunsideraus comente eccetzione
 # Search suggestions
 'searchsuggest-search' => 'Chirca',
 
+# Special:ExpandTemplates
+'expand_templates_preview' => 'Antiprima',
+
 );
index 4a257c8..0103657 100644 (file)
@@ -58,7 +58,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'TitoloErrato' ),
        'Blankpage'                 => array( 'PaginaVuota' ),
        'Block'                     => array( 'Blocca' ),
-       'Blockme'                   => array( 'BloccaProxy' ),
        'Booksources'               => array( 'RicercaISBN' ),
        'BrokenRedirects'           => array( 'RedirectErrati' ),
        'Categories'                => array( 'Categorie' ),
@@ -70,10 +69,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'CreaAccount' ),
        'Deadendpages'              => array( 'PagineSenzaUscita' ),
        'DeletedContributions'      => array( 'ContributiCancellati' ),
-       'Disambiguations'           => array( 'Disambigua' ),
        'DoubleRedirects'           => array( 'RedirectDoppi' ),
        'EditWatchlist'             => array( 'ModificaOsservati', 'ModificaOsservatiSpeciali', 'ModificaListaSeguiti' ),
        'Emailuser'                 => array( 'InviaEMail' ),
+       'ExpandTemplates'           => array( 'EspandiTemplate' ),
        'Export'                    => array( 'Esporta' ),
        'Fewestrevisions'           => array( 'PagineConMenoRevisioni' ),
        'FileDuplicateSearch'       => array( 'CercaFileDuplicati' ),
@@ -117,6 +116,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'PagineProtette' ),
        'Protectedtitles'           => array( 'TitoliProtetti' ),
        'Randompage'                => array( 'PaginaCasuale' ),
+       'RandomInCategory'          => array( 'CasualeInCategoria' ),
        'Randomredirect'            => array( 'RedirectCasuale' ),
        'Recentchanges'             => array( 'UltimeModifiche' ),
        'Recentchangeslinked'       => array( 'ModificheCorrelate' ),
@@ -138,8 +138,8 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'TemplateNonUsati' ),
        'Unwatchedpages'            => array( 'PagineNonOsservate' ),
        'Upload'                    => array( 'Carica' ),
-       'Userlogin'                 => array( 'Entra', 'Login' ),
-       'Userlogout'                => array( 'Esci', 'Logout' ),
+       'Userlogin'                 => array( 'Entra' ),
+       'Userlogout'                => array( 'Esci' ),
        'Userrights'                => array( 'PermessiUtente' ),
        'Version'                   => array( 'Versione' ),
        'Wantedcategories'          => array( 'CategorieRichieste' ),
@@ -423,8 +423,6 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Estrattu di "$1"',
 'youhavenewmessages' => 'Ricivìsti $1 ($2).',
-'newmessageslink' => 'missaggi novi',
-'newmessagesdifflink' => 'ùrtimi canciamenti',
 'youhavenewmessagesfromusers' => "Hai $1 di {{PLURAL:$3|n'àutru utenti|$3 utenti}} ($2).",
 'youhavenewmessagesmanyusers' => 'Hai $1 di na pocu di utenti ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|Nu missaggiu novu|missaggi novi}}',
@@ -1082,8 +1080,6 @@ S'havi accirtari ca la cuntinuità storica di la pàggina nun veni altirata.",
 'preferences' => 'prifirenzi',
 'mypreferences' => 'Li mè prifirenzi',
 'prefs-edits' => 'Nùmmuru di canciamenti:',
-'prefsnologin' => 'Accessu nun effittuatu',
-'prefsnologintext' => 'Pi putiri pirsunalizzari li prifirenzi è nicissariu fari l\'<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} accessu]</span>.',
 'changepassword' => 'Cancia la password',
 'prefs-skin' => 'Aspettu',
 'skin-preview' => 'Antiprima',
@@ -1336,6 +1332,7 @@ L'operazioni nun pò èssiri annullata.",
 'recentchanges-label-minor' => 'Chista è nu canciamentu nnicu',
 'recentchanges-label-bot' => 'Stu canciamentu fu fattu dû bot',
 'recentchanges-label-unpatrolled' => 'Stu canciamentu nun havi ancora statu virificatu',
+'recentchanges-legend-newpage' => '$1 - pàggina nova',
 'rcnote' => "Ccà sutta {{PLURAL:$1|c'è lu canciamentu cchiù ricenti appurtatu|cci sunnu l'ùrtimi '''$1''' canciamenti appurtati}} ô situ {{PLURAL:$2|nta l'ùrtimi 24 uri|nta l'ùrtimi '''$2''' giorni}}; li dati sunnu aggiurnati ê $5 dû $4.",
 'rcnotefrom' => 'Ccà sutta cci sunnu li canciamenti a pàrtiri dû <b>$2</b> (ammustrati nzinu ô <b>$1</b>).',
 'rclistfrom' => 'Ammustra li canciamenti novi a pàrtiri di $1',
@@ -2270,7 +2267,7 @@ Nta st'ùrtimu casu si pò macari utilizzari un culligamentu, p'asempiu [[{{#Spe
 'allmessagesdefault' => 'Testu pridifinitu',
 'allmessagescurrent' => 'Testu attuali',
 'allmessagestext' => "Chista è na lista di missaggi di sistema chi s'attròvanu sutta MediaWiki:''nomu''.
-Visita [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si voi cuntribbuiri â localizzazioni generica di MediaWiki.",
+Visita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] si voi cuntribbuiri â localizzazioni generica di MediaWiki.",
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' nun è suppurtatu pirchì lu flag '''\$wgUseDatabaseMessages''' nun è attivu.",
 'allmessages-filter-legend' => 'Filtru',
 'allmessages-filter' => 'Filtru pi statu di canciamentu:',
@@ -2789,7 +2786,7 @@ Li lijami succissivi, supra la stissa riga, sunnu cunzidirati comu eccizzioni (p
 
 # External editor support
 'edit-externally' => 'Cancia stu file usannu un prugramma sternu',
-'edit-externally-help' => "Pi chiossai nfurmazzioni cunzurtari l'[//www.mediawiki.org/wiki/Manual:External_editors istruzzioni] ('n ngrisi)",
+'edit-externally-help' => "Pi chiossai nfurmazzioni cunzurtari l'[https://www.mediawiki.org/wiki/Manual:External_editors istruzzioni] ('n ngrisi)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tutti',
@@ -2939,8 +2936,7 @@ Stu còdici di cunferma scadi automaticamenti a li $4.',
 
 # Special:SpecialPages
 'specialpages' => 'Pàggini spiciali',
-'specialpages-note' => '----
-* Pàggini spiciali non risirvati.
+'specialpages-note' => '* Pàggini spiciali non risirvati.
 * <strong class="mw-specialpagerestricted">Pàggini spiciali risirvati sulu a quarchi catigurìa d\'utenti.</strong>',
 'specialpages-group-maintenance' => 'Resocunti di manutinzioni',
 'specialpages-group-other' => 'Autri pàggini spiciali',
index 736c64f..c4e01f1 100644 (file)
@@ -259,8 +259,6 @@ $messages = array(
 'ok' => 'Okay',
 'retrievedfrom' => 'Taen frae "$1"',
 'youhavenewmessages' => 'Ye hae $1 ($2).',
-'newmessageslink' => 'new messages',
-'newmessagesdifflink' => 'diff wi last-but-ane reveision',
 'youhavenewmessagesmulti' => 'Ye hae neow messages on $1',
 'editsection' => 'edit',
 'editold' => 'edit',
@@ -733,8 +731,6 @@ there micht be parteeculars in the [{{fullurl:{{#Special:Log}}/suppress|page={{F
 
 # Preferences page
 'mypreferences' => 'Ma preferences',
-'prefsnologin' => 'No loggit in',
-'prefsnologintext' => 'Ye maun be [[Special:UserLogin|loggit in]] tae set uiser preferences.',
 'changepassword' => 'Chynge password',
 'prefs-skin' => 'Huil',
 'skin-preview' => 'First Leuk',
@@ -1451,7 +1447,7 @@ If th' file haes bin modified frae tis original state, some details kin nae full
 
 # External editor support
 'edit-externally' => 'Edit this file uisin an external application',
-'edit-externally-help' => '(See the [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] for mair guidance.)',
+'edit-externally-help' => '(See the [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] for mair guidance.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'aw',
index 3e8bbae..798365f 100644 (file)
@@ -37,13 +37,11 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'سڀ صفحا' ),
        'Ancientpages'              => array( 'قديم صفحا' ),
        'Block'                     => array( 'آءِ پي بندش' ),
-       'Blockme'                   => array( 'مونکي بندشيو' ),
        'BrokenRedirects'           => array( 'ٽٽل چورڻا' ),
        'Categories'                => array( 'زمرا' ),
        'Confirmemail'              => array( 'برقٽپال تصديقيو' ),
        'Contributions'             => array( 'ڀاڱيداريون' ),
        'CreateAccount'             => array( 'کاتو کوليو' ),
-       'Disambiguations'           => array( 'سلجھائپ' ),
        'DoubleRedirects'           => array( 'ٻٽا چورڻا' ),
        'Emailuser'                 => array( 'برقٽپال يوزر' ),
        'Export'                    => array( 'برآمد' ),
@@ -333,8 +331,6 @@ $messages = array(
 'ok' => 'ٺيڪ',
 'retrievedfrom' => '"$1" تان ورتل',
 'youhavenewmessages' => 'توهان لاءِ $1 ($2) آهن.',
-'newmessageslink' => 'نوان نياپا',
-'newmessagesdifflink' => 'آخري تبديلي',
 'editsection' => 'سنواريو',
 'editold' => 'سنواريو',
 'viewsourceold' => 'ڪوڊ ڏسو',
@@ -954,7 +950,7 @@ $1 {{PLURAL:$1|اکر|اکرن}} کان ننڍي هوڻ گھرجي.',
 
 # External editor support
 'edit-externally' => 'هيءُ فائيل ڪنهن خارجي منتقڪريءَ سان سنواريو',
-'edit-externally-help' => 'وڌيڪ معلومات لاءِ [//www.mediawiki.org/wiki/Manual:External_editors هدايتون براءِ تنصيبڪاري] ڏسندا.',
+'edit-externally-help' => 'وڌيڪ معلومات لاءِ [https://www.mediawiki.org/wiki/Manual:External_editors هدايتون براءِ تنصيبڪاري] ڏسندا.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'سڀ',
index 2c4cb3b..ee6d07f 100644 (file)
@@ -35,14 +35,12 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'TuttiLiPàgini' ),
        'Ancientpages'              => array( 'PàginiMancuRizzenti' ),
        'Block'                     => array( 'Brocca' ),
-       'Blockme'                   => array( 'BroccaProxy' ),
        'Booksources'               => array( 'ZirchaISBN' ),
        'BrokenRedirects'           => array( 'RinviiIbbagliaddi' ),
        'Categories'                => array( 'Categuri' ),
        'ChangePassword'            => array( 'RimpusthàParàuraDÓrdhini' ),
        'Contributions'             => array( 'Cuntributi', 'CuntributiUtente' ),
        'Deadendpages'              => array( 'PàginiChenaIscidda' ),
-       'Disambiguations'           => array( 'CuLuMatessiInnommu' ),
        'DoubleRedirects'           => array( 'RinviiDoppi' ),
        'Emailuser'                 => array( 'InviaPosthaErettrònica' ),
        'Export'                    => array( 'Ippurtha' ),
@@ -94,8 +92,8 @@ $specialPageAliases = array(
        'Unusedtemplates'           => array( 'MudelliInutirizaddi' ),
        'Unwatchedpages'            => array( 'PàginiNòAbbaidaddi' ),
        'Upload'                    => array( 'Carrigga' ),
-       'Userlogin'                 => array( 'Intra', 'Login', 'Accesso' ),
-       'Userlogout'                => array( 'Isci', 'Logout', 'Uscita' ),
+       'Userlogin'                 => array( 'Intra', 'Accesso' ),
+       'Userlogout'                => array( 'Isci', 'Uscita' ),
        'Userrights'                => array( 'PrimmissiUtenti' ),
        'Version'                   => array( 'Versioni' ),
        'Wantedcategories'          => array( 'CateguriDumandaddi' ),
@@ -322,8 +320,6 @@ $messages = array(
 'ok' => 'EMMU',
 'retrievedfrom' => 'Buggaddu da "$1"',
 'youhavenewmessages' => 'Ài $1 ($2).',
-'newmessageslink' => 'nobi imbasciaddi',
-'newmessagesdifflink' => 'diffarènzia cu la revisioni prizzidenti',
 'youhavenewmessagesmulti' => 'Ài nobi imbasciaddi i $1',
 'editsection' => 'mudifigga',
 'editold' => 'mudifigga',
@@ -787,8 +783,6 @@ Cunsulthà lu [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} rigi
 'preferences' => 'Prifirenzi',
 'mypreferences' => "Li me' prifirenzi",
 'prefs-edits' => 'Mudìfigghi effettuaddi:',
-'prefsnologin' => 'Intradda nò effettuadda',
-'prefsnologintext' => 'Pa mudìfiggà li prifirenzi è nezzessàriu [[Special:UserLogin|intrà]].',
 'changepassword' => "Ciamba paràura d'órdhini",
 'prefs-skin' => 'Aipettu gràficu',
 'skin-preview' => 'antiprimma',
@@ -1597,7 +1591,7 @@ In chisth'ulthimu casu si pó utilizzà puru un cullegamentu, pa esempiu [[{{#Sp
 'allmessagesdefault' => 'Testhu pridifiniddu',
 'allmessagescurrent' => 'Testhu attuari',
 'allmessagestext' => "Chistha è la listha di tutti l'imbasciaddi di sisthema dipunìbiri i' lu tipu di pàgina MediaWiki.
-Pa piazeri utirizà [//www.mediawiki.org/wiki/Localisation MediaWiki Lucarizazioni] e [//translatewiki.net translatewiki.net] pa l'althri traduzioni.",
+Pa piazeri utirizà [https://www.mediawiki.org/wiki/Localisation MediaWiki Lucarizazioni] e [//translatewiki.net translatewiki.net] pa l'althri traduzioni.",
 'allmessagesnotsupportedDB' => "Chistha pàgina nò è supporthadda parchí l'indicadori '''\$wgUseDatabaseMessages''' nò è attibuu.",
 'allmessages-filter-unmodified' => 'Nò mudifiggaddi',
 'allmessages-filter-all' => 'Tutti',
@@ -1871,7 +1865,7 @@ So cunsidaraddi soru l'erenchi puntaddi (righi ch'ischumenzani cu' lu caràtteri
 
 # External editor support
 'edit-externally' => 'Mudìfigga chistu file usendi un prugramma esthernu',
-'edit-externally-help' => "Pa maggiori infuimmazioni cunsulthà l'[//www.mediawiki.org/wiki/Manual:External_editors isthruzioni] (in ingresu).",
+'edit-externally-help' => "Pa maggiori infuimmazioni cunsulthà l'[https://www.mediawiki.org/wiki/Manual:External_editors isthruzioni] (in ingresu).",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tutti',
index 3233988..0d8ae43 100644 (file)
@@ -50,7 +50,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Veadjemeahttun_bajilčála' ),
        'Blankpage'                 => array( 'Guoros_siidu' ),
        'Block'                     => array( 'Hehtte', 'Hehtte_geavaheaddji', 'Hehtte_IP' ),
-       'Blockme'                   => array( 'Hehtte_mu' ),
        'Booksources'               => array( 'Girjegáldut' ),
        'BrokenRedirects'           => array( 'Boatkanan_stivremat', 'Boatkanan_ođđasitstivremat' ),
        'Categories'                => array( 'Kategoriijat' ),
@@ -60,7 +59,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Rievdadusat' ),
        'CreateAccount'             => array( 'Ráhkat_dovddaldaga', 'Ráhkat_konttu' ),
        'DeletedContributions'      => array( 'Sihkkojuvvon_rievdadusat' ),
-       'Disambiguations'           => array( 'Liŋkkat_dárkonsiidduide' ),
        'DoubleRedirects'           => array( 'Guoktegeardásaš_ođđasitstivremat' ),
        'EditWatchlist'             => array( 'Rievdat_čuovvunlisttu' ),
        'Emailuser'                 => array( 'Sádde_e-poastta' ),
@@ -343,8 +341,6 @@ $messages = array(
 
 'retrievedfrom' => 'Vižžojuvvon čujuhusas $1',
 'youhavenewmessages' => 'Dutnje leat $1 ($2).',
-'newmessageslink' => 'ođđa dieđut',
-'newmessagesdifflink' => 'maŋimus rievdadus',
 'youhavenewmessagesmulti' => 'Dutnje lea ođđa dieđut siiddus $1',
 'editsection' => 'rievdat',
 'editold' => 'rievdat',
@@ -634,8 +630,6 @@ $1 {{int:pipe-separator}} $2',
 'preferences' => 'Ásahusat',
 'mypreferences' => 'Ásahusat',
 'prefs-edits' => 'Rievdadusaid mearri:',
-'prefsnologin' => 'It leat čálligoahtán sisa',
-'prefsnologintext' => 'Don fertet [[Special:UserLogin|čálligoahtit sisa]], ovdalgo sáhtát rievdadit du ásahusaid.',
 'changepassword' => 'Suollemassáni molson',
 'prefs-skin' => 'Olggosoaidnu',
 'skin-preview' => 'ovdalgihtii geahččan...',
index e1d8e0d..fc806bf 100644 (file)
@@ -216,8 +216,6 @@ $messages = array(
 'ok' => 'ton',
 'retrievedfrom' => 'Paluatlde "$1"',
 'youhavenewmessages' => 'Mecui $1 ($2).',
-'newmessageslink' => 'huniitóm',
-'newmessagesdifflink' => 'quiixcui',
 'youhavenewmessagesmulti' => 'Mecui huniitom $1 iti',
 'editsection' => 'ticpatlöx',
 'editold' => 'ticpatlöx',
@@ -569,8 +567,6 @@ Informacion: (curt) = quiíxde vercion currentua,
 'preferences' => 'Quáatlaác',
 'mypreferences' => 'Hequáatlaác',
 'prefs-edits' => 'Ticpatlöx jöxualtec ID-cort:',
-'prefsnologin' => 'Necaápo',
-'prefsnologintext' => 'Zo coccebj Neces [[Special:UserLogin|caápo]] quiixom hequáatlaác.',
 'changepassword' => "Reset'quimx canj",
 'prefs-skin' => 'Zuláugaum',
 'skin-preview' => 'Cuáxiit',
index 95e53d8..48580a5 100644 (file)
@@ -303,8 +303,6 @@ $1',
 'ok' => 'Gerā',
 'retrievedfrom' => 'Gautė ėš „$1“',
 'youhavenewmessages' => 'Tamsta toret $1 ($2).',
-'newmessageslink' => 'naujū žėnotiu',
-'newmessagesdifflink' => 'paskotinis pakeitėms',
 'youhavenewmessagesmulti' => 'Toret naujū žėnotiu $1',
 'editsection' => 'taisītė',
 'editold' => 'taisītė',
@@ -760,8 +758,6 @@ Kėtė admėnėstratuorē šėtom pruojekte vėsdar galės pasėiktė pasliepta
 'preferences' => 'Nustatīmā',
 'mypreferences' => 'Mona nustatīmā',
 'prefs-edits' => 'Keitėmu skaitlius:',
-'prefsnologin' => 'Naprisėjongis',
-'prefsnologintext' => 'Tamstā rēk būtė <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prisėjongosam]</span>, kū galietomiet keistė sava nustatīmus.',
 'changepassword' => 'Pakeistė slaptažuodė',
 'prefs-skin' => 'Ėšruoda',
 'skin-preview' => 'Parveiza',
@@ -1792,7 +1788,7 @@ Vėsas kėtas nūoruodas tuo patiuo eilotie īr laikomas ėšėmtim, tas rēšk
 
 # External editor support
 'edit-externally' => 'Atdarītė ėšuoriniam redaktuorio',
-'edit-externally-help' => 'Nuoriedamė gautė daugiau infuormacėjės, veiziekėt [//www.mediawiki.org/wiki/Manual:External_editors kruovėma instrokcėjės].',
+'edit-externally-help' => 'Nuoriedamė gautė daugiau infuormacėjės, veiziekėt [https://www.mediawiki.org/wiki/Manual:External_editors kruovėma instrokcėjės].',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'vėsos',
@@ -1900,8 +1896,7 @@ Tamsta tēpuogi galėt [[Special:EditWatchlist/raw|redagoutė grīnaji keravuoja
 
 # Special:SpecialPages
 'specialpages' => 'Specēlė̅jė poslapē',
-'specialpages-note' => '----
-* Normalūs specēlė̅jė puslapē.
+'specialpages-note' => '* Normalūs specēlė̅jė puslapē.
 * <strong class="mw-specialpagerestricted">Apribuotė specēlė̅jė puslapē.</strong>',
 'specialpages-group-maintenance' => 'Sėstemas palaikīma pranešėmā',
 'specialpages-group-other' => 'Kėtė specēlė̅jė poslapē',
@@ -1943,4 +1938,7 @@ Tamsta tēpuogi galėt [[Special:EditWatchlist/raw|redagoutė grīnaji keravuoja
 'logentry-newusers-autocreate' => 'Paskīra $1 bova padėrbta autuomatėškā',
 'rightsnone' => '(juokiū)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Ėšskeistė šabluonus',
+
 );
index 5bafdd5..1b9bede 100644 (file)
@@ -36,7 +36,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'Sve_stranice' ),
        'Ancientpages'              => array( 'Najstarije_stranice' ),
        'Blankpage'                 => array( 'Prazna_stranica' ),
-       'Blockme'                   => array( 'Blokiraj_me' ),
        'Booksources'               => array( 'Traži_ISBN' ),
        'BrokenRedirects'           => array( 'Kriva_preusmjerenja' ),
        'Categories'                => array( 'Kategorije' ),
@@ -45,7 +44,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Stvori_račun' ),
        'Deadendpages'              => array( 'Mrtve_stranice' ),
        'DeletedContributions'      => array( 'Obrisani_doprinosi' ),
-       'Disambiguations'           => array( 'Razvrstavanja' ),
        'DoubleRedirects'           => array( 'Dvostruka_preusmjerenja' ),
        'Emailuser'                 => array( 'E-mail', 'Elektronska_pošta' ),
        'Export'                    => array( 'Izvezi' ),
@@ -480,8 +478,6 @@ $1',
 'ok' => 'da',
 'retrievedfrom' => 'Dobavljeno iz "$1"',
 'youhavenewmessages' => 'Imate $1 ($2).',
-'newmessageslink' => 'novih promjena',
-'newmessagesdifflink' => 'posljednja promjena',
 'youhavenewmessagesfromusers' => 'Imate $1 od {{PLURAL:$3|drugog korisnika|$3 korisnika|$3 korisnika}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od mnogo korisnika ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|$1 nove poruke|$1 novih poruka}}',
@@ -1331,8 +1327,6 @@ Uzmite u obzir da njegovi indeksi za ovu Wiki ne moraju biti ažurirani.',
 'preferences' => 'Postavke',
 'mypreferences' => 'Postavke',
 'prefs-edits' => 'Broj izmjena:',
-'prefsnologin' => 'Niste prijavljeni',
-'prefsnologintext' => 'Da biste mogli podešavati korisničke postavke, morate <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} biti prijavljeni]</span>.',
 'changepassword' => 'Promijeni lozinku',
 'prefs-skin' => 'Izgled (skin)',
 'skin-preview' => 'Pretpregled',
@@ -1625,6 +1619,7 @@ Ako izaberete da date ime, biće korišteno za pripisivanje Vašeg rada.',
 'recentchanges-label-minor' => 'Ovo je manja izmjena',
 'recentchanges-label-bot' => 'Ovu je izmjenu učinio bot',
 'recentchanges-label-unpatrolled' => 'Ova izmjena još nije patrolirana',
+'recentchanges-legend-newpage' => '$1 - nova stranica',
 'rcnote' => "Ispod {{PLURAL:$1|je '''$1''' promjena|su '''$1''' zadnje promjene|su '''$1''' zadnjih promjena}} u {{PLURAL:$2|posljednjem '''$2''' danu|posljednja '''$2''' dana|posljednjih '''$2''' dana}}, od $4, $5.",
 'rcnotefrom' => "Ispod {{PLURAL:$1|je '''$1''' izmjena|su '''$1''' zadnje izmjene|su '''$1''' zadnjih izmjena}} u {{PLURAL:$2|posljednjem '''$2''' danu|posljednja '''$2''' dana|posljednjih '''$2''' dana}}, od $4, $5.",
 'rclistfrom' => 'Prikaži nove izmjene počevši od $1',
@@ -2864,7 +2859,7 @@ U drugom slučaju možete koristiti i vezu, npr. [[{{#Special:Export}}/{{MediaWi
 'allmessagesdefault' => 'Uobičajeni tekst',
 'allmessagescurrent' => 'Trenutni tekst',
 'allmessagestext' => 'Ovo je spisak svih sistemskih poruka u dostupnih u MediaWiki imenskom prostoru.
-Molimo posjetite [//www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.',
+Molimo posjetite [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizaciju] i [//translatewiki.net translatewiki.net] ako želite doprinijeti općoj lokalizaciji MediaWikija.',
 'allmessagesnotsupportedDB' => "Ova stranica ne može biti korištena jer je '''\$wgUseDatabaseMessages''' isključen.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter po stanju podešavanja:',
@@ -3624,7 +3619,7 @@ Svi drugi linkovi u istoj liniji se smatraju izuzecima, npr. kod stranica gdje s
 
 # External editor support
 'edit-externally' => 'Izmijeni ovu datoteku/fajl koristeći eksternu aplikaciju',
-'edit-externally-help' => '(Pogledajte [//www.mediawiki.org/wiki/Manual:External_editors instrukcije za podešavanje] za više informacija)',
+'edit-externally-help' => '(Pogledajte [https://www.mediawiki.org/wiki/Manual:External_editors instrukcije za podešavanje] za više informacija)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sve',
@@ -3807,7 +3802,7 @@ Također možete [[Special:EditWatchlist|koristiti standardni uređivač]].',
 'version-hook-subscribedby' => 'Pretplaćeno od',
 'version-version' => '(Verzija $1)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Ova wiki je zasnovana na '''[//www.mediawiki.org/ MediaWiki]''', autorska prava zadržana © 2001-$1 $2.",
+'version-poweredby-credits' => "Ova wiki je zasnovana na '''[https://www.mediawiki.org/ MediaWiki]''', autorska prava zadržana © 2001-$1 $2.",
 'version-poweredby-others' => 'ostali',
 'version-credits-summary' => 'Htjeli bismo da zahvalimo sljedećim osobama na njihovom doprinosu [[Special:Version|MediaWiki]].',
 'version-license-info' => 'Mediawiki je slobodni softver, možete ga redistribuirati i/ili mijenjati pod uslovima GNU opće javne licence kao što je objavljeno od strane Fondacije Slobodnog Softvera, bilo u verziji 2 licence, ili (po vašoj volji) nekoj od kasniji verzija.
@@ -3847,8 +3842,7 @@ Trebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU GNU opće javne licence] z
 
 # Special:SpecialPages
 'specialpages' => 'Posebne stranice',
-'specialpages-note' => '----
-* Normalne posebne stranice.
+'specialpages-note' => '* Normalne posebne stranice.
 * <span class="mw-specialpagerestricted">Ograničene posebne stranice.</span>
 * <span class="mw-specialpagecached">Keširane posebne stranice (mogu biti zastarjele).</span>',
 'specialpages-group-maintenance' => 'Izvještaji za održavanje',
index 35fbfed..2e97f04 100644 (file)
@@ -264,12 +264,10 @@ $1',
 Ẓr [[Special:Version|ayyaw tasna]].',
 
 'ok' => 'Waxxa',
-'pagetitle' => '(MediaWiki)$1 - {{SITENAME}}',
+'pagetitle' => '$1 - {{SITENAME}}',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Yurrid z "$1"',
 'youhavenewmessages' => 'Illa dark $1 ($2).',
-'newmessageslink' => 'Tibratin timaynutin',
-'newmessagesdifflink' => 'Imbddeln imĝura',
 'youhavenewmessagesmulti' => 'Dark tibratin timaynutin ɣ $1',
 'editsection' => 'Ẓreg (bddel)',
 'editold' => 'Ẓreg (bddel)',
@@ -649,7 +647,6 @@ Izdar ad urtili ɣ isbidn n mayllan ɣ {{SITENAME}} .',
 'preferences' => 'Timssusmin',
 'mypreferences' => 'Timssusmin',
 'prefs-edits' => 'Uṭṭun n n imbddeln',
-'prefsnologin' => 'Ur tmlit mat git',
 'changepassword' => 'bdl awal ihdan',
 'prefs-skin' => 'odm',
 'skin-preview' => 'Ammal',
@@ -1215,7 +1212,7 @@ Wiyyaḍ raggis ḥbun s ɣiklli sttin kkan gantn.
 
 # External editor support
 'edit-externally' => 'Bddl asdaw ad s wasnas abrrani',
-'edit-externally-help' => '(Ẓṛ [//www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d’installation] bac ad taf uggar n inɣmisn)',
+'edit-externally-help' => '(Ẓṛ [https://www.mediawiki.org/wiki/Manual:External_editors/fr les instructions d’installation] bac ad taf uggar n inɣmisn)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kraygat (kullu)',
index 704055d..9d30bc7 100644 (file)
@@ -63,7 +63,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'නුසුසුදු_මාතෘකාව' ),
        'Blankpage'                 => array( 'හිස්_පිටුව' ),
        'Block'                     => array( 'වාරණය_කරන්න', 'IP_වාරණය_කරන්න', 'පරිශීලක_වාරණය_කරන්න' ),
-       'Blockme'                   => array( 'මා_වාරණය_කරන්න' ),
        'Booksources'               => array( 'ග්‍රන්ථ_මූලාශ්‍ර' ),
        'BrokenRedirects'           => array( 'භින්න_යළි-යොමුකිරීම්' ),
        'Categories'                => array( 'ප්‍රවර්ග' ),
@@ -73,7 +72,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'ගිණුම_තැනීමට' ),
        'Deadendpages'              => array( 'අග_ඇවුරුණු_පිටුව' ),
        'DeletedContributions'      => array( 'මකාදැමුණු_දායකත්වයන්' ),
-       'Disambiguations'           => array( 'වක්‍රෝත්තිහරණයන්' ),
        'DoubleRedirects'           => array( 'ද්විත්ව_යළි-යොමුකිරීම්' ),
        'Emailuser'                 => array( 'පරිශීලකට_විද්‍යුත්-තැපැලක්_යැවිම' ),
        'Export'                    => array( 'නිර්යාතකරන්න' ),
@@ -331,8 +329,6 @@ $messages = array(
 'noindex-category' => 'සූචිගත නොකළ පිටු',
 'broken-file-category' => 'භින්න වූ ගොනු සබැඳි සහිත පිටු',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'පිළිබඳ',
 'article' => 'පටුන',
 'newwindow' => '(නව කවුළුවක විවෘතවේ)',
@@ -468,8 +464,6 @@ $1",
 'ok' => 'හරි',
 'retrievedfrom' => '"$1" වෙතින් සම්ප්‍රවේශනය කෙරිණි',
 'youhavenewmessages' => 'ඔබ හට $1 ($2)',
-'newmessageslink' => 'නව පණිවුඩ',
-'newmessagesdifflink' => 'අවසාන වෙනස',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|තවත් එක් පරිශීලකයෙකුගෙන්|පරිශීලකයන් $3 දෙනෙකුගෙන්}} ඔබ හට $1 ඇත ($2).',
 'youhavenewmessagesmanyusers' => 'බොහෝ පරිශීලකයන් වෙතින් ඔබ හට $1 ඇත ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|නව පණිවුඩයක්|නව පණිවුඩ}}',
@@ -1272,8 +1266,6 @@ $1",
 'preferences' => 'අභිරුචි',
 'mypreferences' => 'අභිරුචීන්',
 'prefs-edits' => 'සංස්කරණයන් සංඛ්‍යාව:',
-'prefsnologin' => 'පිවිසී නැත (Not logged in)',
-'prefsnologintext' => 'පරිශීලක අභිරුචි සැකසීමට නම්, ඔබ  <span class="plainlinks">[{{fullurl:Special:Userlogin|returnto=$1}} ප්‍රවිෂ්ටවී]</span> සිටිය යුතුය.',
 'changepassword' => 'මුරපදය වෙනස් කරන්න',
 'prefs-skin' => 'ඡවිය',
 'skin-preview' => 'පෙරදසුන',
@@ -1548,6 +1540,7 @@ HTML ටැගයන් පිරික්සන්න.',
 'recentchanges-label-minor' => 'මෙය සුළු සංස්කරණයකි',
 'recentchanges-label-bot' => 'මෙය රොබෝවක් විසින් කරන ලද සංස්කරණයකි',
 'recentchanges-label-unpatrolled' => 'මෙම සංස්කරණය තවම විමර්ශනය කර නොමැත',
+'recentchanges-legend-newpage' => '$1 -  නව පිටුව',
 'rcnote' => "$4 දින, $5 වන තෙක්, අවසන් {{PLURAL:$2|දිනදී|දින '''$2''' තුලදී}} සිදුවී ඇති, {{PLURAL:$1| '''1''' ක් වෙනස|අවසන් වෙනස්වීම් '''$1'''}} පහත දැක්වේ.",
 'rcnotefrom' => "'''$2''' න් පසු සිදුවී ඇති වෙනස්කම් මෙහි පහත දැක්වේ ('''$1''' ක ප්‍රමාණයක උපරිමයක් පෙන්වා ඇත).",
 'rclistfrom' => '$1 සිට බලපැවැත්වෙන මෑත වෙනස්වීම් පෙන්වන්න',
@@ -2758,7 +2751,7 @@ $1 ගේ වාරණයට හේතුව මෙය වේ: "$2"',
 'allmessagesdefault' => 'සාමාන්‍ය පණිවුඩ පෙළ',
 'allmessagescurrent' => 'වත්මන් පෙළ',
 'allmessagestext' => 'මේ මාධ්‍යවිකි නාමඅවකාශයෙහිදී  හමුවන පද්ධති පණිවුඩයන් ලැයිස්තුවකි.
-වර්ගීය මාධ්‍යවිකි ප්‍රාදේශීයකරණයට දායක වීමට ඔබ රිසි නම් කරුණාකර [//www.mediawiki.org/wiki/Localisation මාධ්‍යවිකි ප්‍රාදේශීයකරණය]  සහ [//translatewiki.net බීටාවිකි] වෙත පිවිසෙන්න.',
+වර්ගීය මාධ්‍යවිකි ප්‍රාදේශීයකරණයට දායක වීමට ඔබ රිසි නම් කරුණාකර [https://www.mediawiki.org/wiki/Localisation මාධ්‍යවිකි ප්‍රාදේශීයකරණය]  සහ [//translatewiki.net බීටාවිකි] වෙත පිවිසෙන්න.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' අක්‍රීය කොට ඇති බැවින්, මෙම පිටුව භාවිතා කල නොහැක.",
 'allmessages-filter-legend' => 'පෙරහන',
 'allmessages-filter' => 'පාරිභෝගීකරණ තත්ත්වය අනුව පෙරීම:',
@@ -2950,6 +2943,8 @@ $1 ගේ වාරණයට හේතුව මෙය වේ: "$2"',
 'spambot_username' => 'මීඩියාවිකි ස්පෑම් ඉවත්කිරීම',
 'spam_reverting' => ' $1 හට සබැඳියන් නොමැති අවසන් අනුවාදය වෙත ප්‍රතිවර්තනය වෙමින්',
 'spam_blanking' => 'සියළු සංශෝධනයන්හි  $1 වෙතවූ සබැඳියන් අඩංගු විය, හිස්කරමින්',
+'simpleantispam-label' => "ප්‍රති-ස්පෑම පරීක්‍ෂාව.
+කරුණාකර මෙය පුරවන්න '''එපා'''!",
 
 # Info page
 'pageinfo-title' => '"$1" සඳහා තොරතුරු',
@@ -3539,7 +3534,7 @@ Others will be hidden by default.
 
 # External editor support
 'edit-externally' => 'බාහිර  උපයෝගයක් භාවිතා කරමින් මෙම ගොනුව සංස්කරණය කරන්න',
-'edit-externally-help' => '(වැඩිදුර තොරතුරු සඳහා [//www.mediawiki.org/wiki/Manual:External_editors පිහිටුවීම් උපදෙස්] බලන්න.)',
+'edit-externally-help' => '(වැඩිදුර තොරතුරු සඳහා [https://www.mediawiki.org/wiki/Manual:External_editors පිහිටුවීම් උපදෙස්] බලන්න.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'සියල්ල',
@@ -3792,7 +3787,7 @@ This confirmation code will expire at $4.',
 'version-hook-subscribedby' => 'දායකවී ඇත්තේ',
 'version-version' => '(අනුවාදය $1)',
 'version-license' => 'වරපත',
-'version-poweredby-credits' => "මෙම විකිය '''[//www.mediawiki.org/ MediaWiki]''' මගින් බලගන්වා ඇත, copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "මෙම විකිය '''[https://www.mediawiki.org/ MediaWiki]''' මගින් බලගන්වා ඇත, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'අනෙකුත්',
 'version-license-info' => 'MediaWiki යනු නිදහස් මෘදුකාංගයකි; නිදහස් මෘදුකාංග පදනමේ (Free Software Foundation) හි GNU General Public License නම් බලපත්‍රයේ වගන්තිවලට අනුව ඔබට එය නැවත බෙදාහැරීම සහ/හෝ සංස්කරණය කළ හැක; ඒ, එම බලපත්‍රයේ 2වන හෝ (ඔබට කැමති නම්) ඉන්පසු එන සංස්කරණයකට අනුවය.
 
@@ -3819,8 +3814,7 @@ MediaWiki බෙදාහැර ඇත්තේ එය ප්‍රයෝජන
 
 # Special:SpecialPages
 'specialpages' => 'විශේෂ පිටු',
-'specialpages-note' => '----
-* සාමාන්‍ය විශේෂ පිටු.
+'specialpages-note' => '* සාමාන්‍ය විශේෂ පිටු.
 * <span class="mw-specialpagerestricted">සීමිත විශේෂ පිටු.</span>
 * <span class="mw-specialpagecached">කෑෂිත වි‍ශේෂ පිටු (යල් පැන ගිය විය හැක).</span>',
 'specialpages-group-maintenance' => 'නඩත්තු වාර්තා',
@@ -3994,4 +3988,21 @@ MediaWiki බෙදාහැර ඇත්තේ එය ප්‍රයෝජන
 'duration-centuries' => '{{PLURAL:$1|ශතවර්ෂ|ශතවර්ෂ}} $1 ක්',
 'duration-millennia' => '{{PLURAL:$1|සහස‍්‍රවර්ෂ|සහස‍්‍රවර්ෂ}} $1 ක්',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'සැකිලි පුළුල් කරන්න',
+'expand_templates_intro' => 'මෙම විශේෂ පිටුව විසින් යම් පෙළක්  ගෙන එහි සියළු සැකිලි ආවර්තනික ලෙස පුළුල් කරයි.
+එය  <nowiki>{{</nowiki>#language:…}} වැනි ව්‍යාකරණ විග්‍රහ ශ්‍රිතයන් හා,
+<nowiki>{{</nowiki>CURRENTDAY}}වැනි විචල්‍යයන් ද&mdash; ඇත්ත වශයෙන්ම
+ද්විත්ව-සඟල වරහන් තුල හමුවන සැම දෙයක්ම පාහේ  පුළුල් කරයි.
+එය විසින් මෙය සිදුකරනුයේ මාධයවිකි විසින්ම අදාල ව්‍යාකරණ විග්‍රහ අදියර ඇමතීමෙනි.',
+'expand_templates_title' => '{{FULLPAGENAME}} වැන්න සඳහා, ප්‍රකරණ ශීර්ෂය.:',
+'expand_templates_input' => 'ප්‍රදාන පෙළ:',
+'expand_templates_output' => 'ප්‍රතිඵලය',
+'expand_templates_xml_output' => 'XML ප්‍රතිදානය',
+'expand_templates_ok' => 'හරි',
+'expand_templates_remove_comments' => 'පරිකථනයන්  ඉවත්කරන්න',
+'expand_templates_remove_nowiki' => 'ප්‍රතිපලයෙහි <nowiki> ටැග යටපත් කරන්න',
+'expand_templates_generate_xml' => 'XML ව්‍යාකරණ විග්‍රහ රුක පෙන්වන්න',
+'expand_templates_preview' => 'පෙරදසුන',
+
 );
index 65f1589..d426014 100644 (file)
@@ -12,6 +12,7 @@
  * @author Geitost
  * @author Helix84
  * @author Kaganer
+ * @author KuboF
  * @author Kusavica
  * @author Liso
  * @author Maros
@@ -40,7 +41,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'StaréStránky' ),
        'Blankpage'                 => array( 'PrázdnaStránka' ),
        'Block'                     => array( 'Blokovanie' ),
-       'Blockme'                   => array( 'ZablokovaťMa' ),
        'Booksources'               => array( 'KnižnéZdroje' ),
        'BrokenRedirects'           => array( 'PokazenéPresmerovania' ),
        'Categories'                => array( 'Kategórie' ),
@@ -50,7 +50,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'VytvorenieÚčtu' ),
        'Deadendpages'              => array( 'StránkyBezOdkazov' ),
        'DeletedContributions'      => array( 'ZmazanéPríspevky' ),
-       'Disambiguations'           => array( 'RozlišovacieStránky' ),
        'DoubleRedirects'           => array( 'DvojitéPresmerovania' ),
        'Emailuser'                 => array( 'EmailPoužívateľovi' ),
        'Fewestrevisions'           => array( 'NajmenejRevízií' ),
@@ -291,7 +290,7 @@ $messages = array(
 'tog-hidepatrolled' => 'Skryť strážené úpravy v Posledných úpravách',
 'tog-newpageshidepatrolled' => 'Skryť strážené stránky zo zoznamu nových stránok',
 'tog-extendwatchlist' => 'Rozšíriť zoznam sledovaných stránok, aby zobrazoval všetky zmeny, nie len posledné',
-'tog-usenewrc' => 'Zoskupiť v posledných úpravách a na zozname sledovaných stránok podľa stránky (vyžaduje JavaScript)',
+'tog-usenewrc' => 'Zoskupiť zmeny v posledných úpravách a na zozname sledovaných stránok podľa stránky',
 'tog-numberheadings' => 'Automaticky číslovať nadpisy',
 'tog-showtoolbar' => 'Zobraziť panel nástrojov úprav',
 'tog-editondblclick' => 'Upravovať stránky po dvojitom kliknutí',
@@ -558,8 +557,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Zdroj: „$1“',
 'youhavenewmessages' => 'Máte $1 ($2).',
-'newmessageslink' => 'nové správy',
-'newmessagesdifflink' => 'posledná zmena',
 'youhavenewmessagesfromusers' => 'Máte $1 od {{PLURAL:$3|iného používateľa|$3 iných používateľov}} ($2).',
 'youhavenewmessagesmanyusers' => 'Máte $1 od viacerých ďalších používateľov ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novú správu|nové správy}}',
@@ -617,6 +614,7 @@ Zoznam platných špeciálnych stránok nájdete na [[Special:SpecialPages|{{int
 'databaseerror' => 'Chyba v databáze',
 'databaseerror-text' => 'Došlo k chybe pri otázke do databázy.
 Môže to byť spôsobené chybou v softvéri.',
+'databaseerror-textcl' => 'Vyskytla sa chyba dopytu do databázy.',
 'databaseerror-query' => 'Otázka: $1',
 'databaseerror-function' => 'Funkcia: $1',
 'databaseerror-error' => 'Chyba: $1',
@@ -739,7 +737,7 @@ Nezabudnite zmeniť svoje [[Special:Preferences|Predvoľby {{GRAMMAR:genitív|{{
 'gotaccount' => "Máte už vytvorený účet? '''$1'''.",
 'gotaccountlink' => 'Prihlásiť',
 'userlogin-resetlink' => 'Zabudli ste svoje prihlasovacie údaje?',
-'userlogin-resetpassword-link' => 'Obnoviť heslo',
+'userlogin-resetpassword-link' => 'Zabudli ste heslo?',
 'helplogin-url' => 'Help:Prihlasovanie',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoc s prihlásením]]',
 'userlogin-loggedin' => 'Ste už {{GENDER:$1|prihĺasený|prihlásená}} ako $1.
@@ -805,14 +803,15 @@ používateľa „$1“.
 Prosím, prihláste sa znovu, keď ho dostanete.',
 'blocked-mailpassword' => 'Boli zablokované úpravy z vašej IP adresy, a tak nie je dovolené použiť funkciu znovuvyžiadania hesla, aby sa zabránilo zneužitiu.',
 'eauthentsent' => 'Email s potvrdením bol zaslaný na uvedenú emailovú adresu.
-Predtým ako sa na účet pošle akákoľvek ďalšia pošta, musíte splniť inštrukcie v emaili, aby sa potvrdilo, že účet je skutočne váš.',
+Predtým ako sa na účet pošle akákoľvek ďalšia pošta, musíte splniť inštrukcie v emaili, aby ste potvrdili, že účet je skutočne váš.',
 'throttled-mailpassword' => 'E-mail na obnovenie hesla už bol odoslaný v priebehu {{PLURAL:$1|poslednej $1 hodiny|posledných $1 hodín}}.
 Aby sa zabránilo zneužitiu, obnovenie hesla emailom je možné vykonať iba raz za {{PLURAL:$1|$1 hodinu|$1 hodiny|$1 hodín}}.',
 'mailerror' => 'Chyba pri posielaní e-mailu: $1',
 'acct_creation_throttle_hit' => 'Návštevníci tejto wiki z vašej IP adresy už za posledný deň vytvorili {{PLURAL:$1|$1 účet|$1 účty|$1 účtov}}, čo je maximálny počet povolený za toto časové obdobie.
 Z tohto dôvodu nemôžu návštevníci z tejto IP adresy momentálne vytvoriť ďalšie účty.',
 'emailauthenticated' => 'Vaša emailová adresa bola overená $2 $3.',
-'emailnotauthenticated' => 'Vaša e-mailová adresa ešte nebola overená. Preto nemôžete prijať emaily pre žiadnu z nasledovných funkcií.',
+'emailnotauthenticated' => 'Vaša e-mailová adresa ešte nebola overená.
+Preto nemôžete prijať emaily pre žiadnu z nasledovných funkcií.',
 'noemailprefs' => 'Tieto nástroje budú prístupné po vyplnení emailovej adresy vo vašich nastaveniach.',
 'emailconfirmlink' => 'Potvrďte svoju e-mailovú adresu',
 'invalidemailaddress' => 'Emailovú adresu nemožno akceptovať, pretože sa zdá, že má neplatný formát. Zadajte adresu v správnom tvare alebo nechajte príslušné políčko prázdne.',
@@ -831,6 +830,8 @@ Prosím, počkajte $1 predtým, než to skúsite znova.',
 'login-abort-generic' => 'Vaše prihlásenie nebolo úspešné - zrušené',
 'loginlanguagelabel' => 'Jazyk: $1',
 'suspicious-userlogout' => 'Vaša požiadavka odhlásiť sa bola zamietnutá, pretože to vyzerá, že ju poslal pokazený prehliadač alebo proxy server.',
+'createacct-another-realname-tip' => 'Skutočné meno je nepovinné.
+Ak sa rozhodnete ho poskytnúť, použije sa na označenie vašej práce.',
 
 # Email sending
 'php-mail-error-unknown' => 'Neznáma chyba vo funkcii PHP mail()',
@@ -846,7 +847,7 @@ Prosím, počkajte $1 predtým, než to skúsite znova.',
 'newpassword' => 'Nové heslo:',
 'retypenew' => 'Nové heslo (ešte raz):',
 'resetpass_submit' => 'Nastaviť heslo a prihlásiť sa',
-'changepassword-success' => 'Vaše heslo bolo úspešne zmenené! Prebieha prihlasovanie...',
+'changepassword-success' => 'Vaše heslo bolo úspešne zmenené!',
 'resetpass_forbidden' => 'Heslá nie je možné zmeniť',
 'resetpass-no-info' => 'Aby ste mohli priamo pristupovať k tejto stránke, musíte sa prihlásiť.',
 'resetpass-submit-loggedin' => 'Zmeniť heslo',
@@ -891,7 +892,7 @@ ignorovať a ďalej používať vaše staré heslo.',
 Dočasné heslo:$2',
 'passwordreset-emailsent' => 'Email s novým heslom bol odoslaný.',
 'passwordreset-emailsent-capture' => 'Bol odoslaný email s novým heslom, ktorý je zobrazený nižšie.',
-'passwordreset-emailerror-capture' => 'Bol odoslaný email s novým heslom, ktorý je zobrazený nižšie, ale nepodarilo sa ho odoslať používateľovi: $1',
+'passwordreset-emailerror-capture' => 'Bol odoslaný email s novým heslom, ktorý je zobrazený nižšie, ale nepodarilo sa ho odoslať {{GENDER:$2|používateľovi}}: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'Zmeniť emailovú adresu',
@@ -906,7 +907,17 @@ Dočasné heslo:$2',
 'changeemail-cancel' => 'Zrušiť',
 
 # Special:ResetTokens
+'resettokens' => 'Obnoviť tokeny',
+'resettokens-text' => 'Tu môžete obnoviť tokeny, ktoré umožňujú prístup k určitým súkromným údajom spojeným s vaším účtom.
+
+Mali by ste to urobiť, ak ste ich omylom niekomu poskytli alebo ak bolo vaše konto zneužité.',
+'resettokens-no-tokens' => 'Neexistujú žiadne tokeny, ktoré by bolo možné obnoviť.',
+'resettokens-legend' => 'Obnoviť tokeny',
 'resettokens-tokens' => 'Tokeny:',
+'resettokens-token-label' => '$1 (aktuálna hodnota: $2)',
+'resettokens-watchlist-token' => 'Token pre webový kanál (Atom/RSS) [[Special:Watchlist|zmien na stránkach, ktoré sledujete]]',
+'resettokens-done' => 'Tokeny boli obnovené.',
+'resettokens-resetbutton' => 'Obnoviť zvolené tokeny.',
 
 # Edit page toolbar
 'bold_sample' => 'Tučný text',
@@ -987,9 +998,7 @@ Možno bola presunutá alebo zmazaná odkedy ste si stránku zobrazili.',
 'loginreqlink' => 'prihlásiť',
 'loginreqpagetext' => 'Aby ste mohli prezerať ďalšie stránky, musíte sa $1.',
 'accmailtitle' => 'Heslo bolo odoslané.',
-'accmailtext' => "Náhodne vytvorené heslo pre používateľa [[User talk:$1|$1]] bolo poslané na $2.
-
-Heslo tohto nového účtu je možné zmeniť na stránke ''[[Special:ChangePassword|zmena hesla]]'' po prihlásení.",
+'accmailtext' => "Náhodne vytvorené heslo pre používateľa [[User talk:$1|$1]] bolo poslané na $2. Je možné ho zmeniť na stránke ''[[Special:ChangePassword|zmena hesla]]'' po prihlásení.",
 'newarticle' => '(Nový)',
 'newarticletext' => "Sledovali ste odkaz na stránku, ktorá zatiaľ neexistuje.
 Stránku vytvoríte tak, že začnete písať do dolného poľa a potom stlačíte tlačidlo „Uložiť stránku“.
@@ -1000,8 +1009,7 @@ Preto musíme na jeho identifikáciu použiť numerickú IP adresu. Je možné,
 Ak ste anonymný používateľ a máte pocit, že vám boli adresované irelevantné diskusné príspevky, [[Special:UserLogin/signup|vytvorte si konto]] alebo sa [[Special:UserLogin|prihláste]], aby sa zamedzilo budúcim zámenám s inými anonymnými používateľmi.''",
 'noarticletext' => 'Na tejto stránke sa momentálne nenachádza žiadny text.
 Môžete [[Special:Search/{{PAGENAME}}|vyhľadávať názov tejto stránky]] v obsahu iných stránok,
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} vyhľadávať v súvisiacich záznamoch],
-alebo [{{fullurl:{{FULLPAGENAME}}|action=edit}} upravovať túto stránku]</span>.',
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} vyhľadávať v súvisiacich záznamoch] alebo [{{fullurl:{{FULLPAGENAME}}|action=edit}} upravovať túto stránku]</span>.',
 'noarticletext-nopermission' => 'Táto stránka momentálne neobsahuje žiadny text.
 Môžete [[Special:Search/{{PAGENAME}}|hľadať názov tejto stránky]] v texte iných stránok
 alebo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hľadať v súvisiacich záznamoch]</span>, ale nemáte oprávnenie túto stránku vytvoriť.',
@@ -1150,6 +1158,7 @@ Tieto argumenty boli vynechané.',
 'undo-failure' => 'Úpravu nie je možné vrátiť kvôli konfliktným medziľahlým úpravám.',
 'undo-norev' => 'Túto úpravu nie je možné vrátiť, pretože neexistuje alebo bola zmazaná.',
 'undo-summary' => 'Revízia $1 používateľa [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusia]]) bola vrátená',
+'undo-summary-username-hidden' => 'Vrátiť revíziu $1, ktorú vykonal skrytý používateľ',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Nie je možné vytvoriť účet',
@@ -1169,7 +1178,7 @@ Dôvod, ktorý $3 uviedol, je ''$2''",
 'currentrevisionlink' => 'Aktuálna úprava',
 'cur' => 'aktuálna',
 'next' => 'ďalšia',
-'last' => 'posledná',
+'last' => 'predošlá',
 'page_first' => 'prvá',
 'page_last' => 'posledná',
 'histlegend' => 'Porovnanie zmien: označte výberové políčka revízií, ktoré sa majú porovnať a kliknite na tlačidlo dolu.<br />
@@ -1239,18 +1248,19 @@ Ako správca si môžete tento rozdiel zobraziť; podrobnosti môžete nájsť v
 Iní správcovia {{GRAMMAR:genitív|{{SITENAME}}}} budú stále môcť pristupovať k skrytému obsahu a môžu ho znova obnoviť použitím tohto rozhrania v prípade, že nie sú stanovené ďalšie obmedzenia.",
 'revdelete-confirm' => 'Prosím, potvrďte, že to naozaj chcete vykonať, rozumiete následkom a že to robíte v súlade s [[{{MediaWiki:Policy-url}}|politikou]].',
 'revdelete-suppress-text' => "Zatajenie by sa malo používať '''výlučne''' v nasledovných prípadoch:
+* Potenciálne hanlivé informácie
 * Nevhodné osobné údaje
-*: ''adresy, telefóne čísla, rodné čísla a pod.''",
+*: ''domáce adresy, telefóne čísla, rodné čísla a pod.''",
 'revdelete-legend' => 'Nastaviť obmedzenia viditeľnosti',
-'revdelete-hide-text' => 'Skryť text revízie',
+'revdelete-hide-text' => 'Text revízie',
 'revdelete-hide-image' => 'Skryť obsah súboru',
 'revdelete-hide-name' => 'Skryť činnosť a cieľ',
-'revdelete-hide-comment' => 'Skryť zhrnutie úprav',
-'revdelete-hide-user' => 'Skryť používateľské meno/IP',
+'revdelete-hide-comment' => 'Zhrnutie úprav',
+'revdelete-hide-user' => 'Používateľské meno/IP redaktora',
 'revdelete-hide-restricted' => 'Zatajiť údaje pred všetkými, aj pred správcami',
 'revdelete-radio-same' => '(nezmeniť)',
-'revdelete-radio-set' => 'Áno',
-'revdelete-radio-unset' => 'Nie',
+'revdelete-radio-set' => 'Skrytý',
+'revdelete-radio-unset' => 'Viditeľný',
 'revdelete-suppress' => 'Skryť údaje pred správcami rovnako ako pred ostatnými',
 'revdelete-unsuppress' => 'Odstrániť obmedzenia obnovených revízií',
 'revdelete-log' => 'Dôvod:',
@@ -1403,8 +1413,6 @@ Podrobnosti nájdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'preferences' => 'Nastavenia',
 'mypreferences' => 'Nastavenia',
 'prefs-edits' => 'Počet úprav:',
-'prefsnologin' => 'Nie ste prihlásený/á',
-'prefsnologintext' => 'Aby ste mohli zmeniť svoje nastavenia, musíte byť <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prihlásený]</span>.',
 'changepassword' => 'Zmeniť heslo',
 'prefs-skin' => 'Vzhľad',
 'skin-preview' => 'Náhľad',
@@ -1429,7 +1437,7 @@ Podrobnosti nájdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'prefs-rendering' => 'Vzhľad',
 'saveprefs' => 'Uložiť nastavenia',
 'resetprefs' => 'Obnoviť pôvodné nastavenia',
-'restoreprefs' => 'Obnoviť všetky nastavenia na štandardné hodnoty',
+'restoreprefs' => 'Obnoviť všetky predvolené nastavenia (vo všetkých sekciách)',
 'prefs-editing' => 'Úpravy',
 'rows' => 'Riadky:',
 'columns' => 'Stĺpce:',
@@ -1441,6 +1449,9 @@ Podrobnosti nájdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'recentchangesdays-max' => '(maximálne $1 {{PLURAL:$1|deň|dni|dní}})',
 'recentchangescount' => 'Štandardne zobrazovaný počet úprav:',
 'prefs-help-recentchangescount' => 'Toto sa týka posledných úprav, histórií stránok a záznamov.',
+'prefs-help-watchlist-token2' => 'Toto je tajný kľúč k webovému kanálu vášho zoznamu sledovaných stránok.
+každý, kto ho pozná si bude môcť prečítať váš zoznam sledovaných stránok, preto ho nezverejňujte.
+[[Special:ResetTokens|Kliknite sem, ak potrebujete vytvoriť nový]].',
 'savedprefs' => 'Vaše nastavenia boli uložené.',
 'timezonelegend' => 'Časové pásmo:',
 'localtime' => 'Miestny čas:',
@@ -1472,8 +1483,8 @@ Podrobnosti nájdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 Túto operáciu nemožno vrátiť.',
 'prefs-emailconfirm-label' => 'Potvrdenie emailu:',
 'youremail' => 'Váš e-mail²',
-'username' => 'Používateľské meno:',
-'uid' => 'ID používateľa:',
+'username' => '{{GENDER:$1|Používateľské meno}}:',
+'uid' => 'ID {{GENDER:$1|používateľa}}:',
 'prefs-memberingroups' => '{{GENDER:$2|Člen|Členovia}} {{PLURAL:$1|skupiny|skupín}}:',
 'prefs-registration' => 'Čas registrácie:',
 'yourrealname' => 'Skutočné meno *:',
@@ -1485,11 +1496,12 @@ Túto operáciu nemožno vrátiť.',
 'badsig' => 'Neplatný podpis v pôvodnom tvare; skontrolujte HTML značky.',
 'badsiglength' => 'Váš podpis je príliš dlhý.
 Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
-'yourgender' => 'Pohlavie:',
-'gender-unknown' => 'Neuvedené',
-'gender-male' => 'Muž',
-'gender-female' => 'Žena',
-'prefs-help-gender' => 'Nepovinné: používa softvér na správne oslovenie v závislosti od rodu. Táto informácia bude verejná.',
+'yourgender' => 'Ako si želáte byť označovaný?',
+'gender-unknown' => 'Radšej nechcem uviesť',
+'gender-male' => 'On upravuje wiki stránky',
+'gender-female' => 'Ona upravuje wiki stránky',
+'prefs-help-gender' => 'Nastavenie tejto voľby nie je povinné.
+Softvér používa toto nastavenie na správne oslovenie a označenie vás ostatným v závislosti od gramatického rodu. Táto informácia bude verejná.',
 'email' => 'E-mail',
 'prefs-help-realname' => '¹ Skutočné meno (nepovinné): ak sa rozhodnete ho poskytnúť, bude použité na označenie vašej práce.',
 'prefs-help-email' => 'Emailová adresa je nepovinný údaj, ale je potrebná v prípade, že ak zabudnete heslo, môžete si na email vyžiadať nové.',
@@ -1500,7 +1512,8 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'prefs-signature' => 'Podpis',
 'prefs-dateformat' => 'Formát dátumu',
 'prefs-timeoffset' => 'Časový posun',
-'prefs-advancedediting' => 'Rozšírené možnosti',
+'prefs-advancedediting' => 'Všeobecné možnosti',
+'prefs-editor' => 'Redaktor',
 'prefs-preview' => 'Náhľad',
 'prefs-advancedrc' => 'Rozšírené možnosti',
 'prefs-advancedrendering' => 'Rozšírené možnosti',
@@ -1510,6 +1523,7 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'prefs-displaysearchoptions' => 'Možnosti zobrazenia',
 'prefs-displaywatchlist' => 'Možnosti zobrazenia',
 'prefs-diffs' => 'Rozdiely',
+'prefs-help-prefershttps' => 'Táto voľba sa prejaví pri vašom ďalšom prihlásení.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'Formát e-mailovej adresa vyzerá byť správny',
@@ -1533,9 +1547,11 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'userrights-no-interwiki' => 'Nemáte oprávnenie upravovať práva používateľov na iných wiki.',
 'userrights-nodatabase' => 'Databáza $1 neexistuje alebo nie je lokálna.',
 'userrights-nologin' => 'Aby ste mohli prideľovať používateľom oprávnenia, musíte sa [[Special:UserLogin|prihlásiť]] s účtom správcu.',
-'userrights-notallowed' => 'Váš účet nemá oprávnenie prideľovať alebo odoberať používateľom oprávnenia.',
+'userrights-notallowed' => 'Nemáte oprávnenie prideľovať alebo odoberať používateľom oprávnenia.',
 'userrights-changeable-col' => 'Skupiny, ktoré môžete zmeniť',
 'userrights-unchangeable-col' => 'Skupiny, ktoré nemôžete zmeniť',
+'userrights-conflict' => 'Konflikt zmien práv používateľov! Prosím, skontrolujte ho a potvrďte svoje zmeny.',
+'userrights-removed-self' => 'Úspešne ste odstránili svoje vlastné práva. Z toho dôvodu už nebudete mať prístup k tejto stránke.',
 
 # Groups
 'group' => 'Skupina:',
@@ -1579,7 +1595,7 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'right-reupload-shared' => 'Nahrávať lokálne súbory, ktoré majú prednosť pred zdieľaným úložiskom',
 'right-upload_by_url' => 'Nahrávať súbor z URL adresy',
 'right-purge' => 'Čistiť vyrovnávaciu pamäť stránky bez potvrdzovacej stránky',
-'right-autoconfirmed' => 'Upravovať čiastočne zamknuté stránky',
+'right-autoconfirmed' => 'Neovplyvnený obmedzeniami na základe IP adresy',
 'right-bot' => 'Byť považovaný za automatický proces',
 'right-nominornewtalk' => 'Pri drobných úpravách diskusnej stránky nevypisovať hlásenie o nových správach',
 'right-apihighlimits' => 'Používať vyššie limity v požiadavkách API',
@@ -1599,13 +1615,20 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'right-hideuser' => 'Zablokovať používateľské meno tak, že bude verejnosti skryté',
 'right-ipblock-exempt' => 'Obchádzať blokovanie IP adries, rozsahov a automatické blokovanie',
 'right-proxyunbannable' => 'Obchádzať automatické blokovanie proxy serverov',
-'right-unblockself' => 'Odblokovať samých seba',
-'right-protect' => 'Meniť úroveň zamknutia a upravovať zamknuté stránky',
-'right-editprotected' => 'Upravovať zamknuté schránky (bez kaskádovej ochrany)',
+'right-unblockself' => 'Odblokovať seba samého',
+'right-protect' => 'Meniť úroveň zamknutia a upravovať kaskádovito zamknuté stránky',
+'right-editprotected' => 'Upravovať stránky zamknuté ako „{{int:protect-level-sysop}}“',
+'right-editsemiprotected' => 'Upravovať stránky zamknuté ako „{{int:protect-level-autoconfirmed}}“',
 'right-editinterface' => 'Upravovať správy používateľského rozhrania',
 'right-editusercssjs' => 'Upravovať CSS a JS súbory ostatných používateľov',
 'right-editusercss' => 'Upravovať CSS súbory ostatných používateľov',
 'right-edituserjs' => 'Upravovať JS súbory ostatných používateľov',
+'right-editmyusercss' => 'Upraviť svoje vlastné používateľské súbory CSS',
+'right-editmyuserjs' => 'Upraviť svoje vlastné používateľské súbory JavaScript',
+'right-viewmywatchlist' => 'Zobraziť vlastný zoznam sledovaných stránok',
+'right-editmywatchlist' => 'Upraviť vlastný zoznam sledovaných stránok. Všimnite si, že niektoré operácie budú môcť pridať stránky aj bez tohto oprávnenia.',
+'right-viewmyprivateinfo' => 'Zobraziť vlastné súkromné údaje (napríklad e-mailovú adresu, skutočné meno)',
+'right-editmyprivateinfo' => 'Upraviť vlastné súkromné údaje (napríklad e-mailovú adresu, skutočné meno)',
 'right-editmyoptions' => 'Upraviť vlastné nastavenia',
 'right-rollback' => 'Rýchlo vrátiť úpravy posledného používateľa, ktorý upravoval danú stránku',
 'right-markbotedits' => 'Označiť vrátené úpravy ako úpravy robota',
@@ -1658,8 +1681,8 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'action-block' => 'zablokovať úpravy tohto používateľa',
 'action-protect' => 'zmeniť úrovne ochrany tejto stránky',
 'action-rollback' => 'rýchlo vrátiť úpravy posledného používateľa, ktorý upravoval danú stránku',
-'action-import' => 'importovať túto stránku z inej wiki',
-'action-importupload' => 'importovať túto stránku z nahraného súboru',
+'action-import' => 'importovať stránky z inej wiki',
+'action-importupload' => 'importovať stránky z nahraného súboru',
 'action-patrol' => 'označiť úpravy iných ako strážené',
 'action-autopatrol' => 'označiť vlastné úpravy ako strážené',
 'action-unwatchedpages' => 'zobraziť zoznam nesledovaných stránok',
@@ -1675,6 +1698,7 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|zmena|zmeny|zmien}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|od poslednej návštevy}}',
 'enhancedrc-history' => 'história',
 'recentchanges' => 'Posledné úpravy',
 'recentchanges-legend' => 'Možnosti posledných zmien',
@@ -1685,6 +1709,7 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'recentchanges-label-minor' => 'Toto je drobná úprava',
 'recentchanges-label-bot' => 'Túto úpravy vykonal robot',
 'recentchanges-label-unpatrolled' => 'Táto úprava zatiaľ nebola strážená',
+'recentchanges-legend-newpage' => '(pozri tiež [[Special:NewPages|zoznam nových stránok]])',
 'rcnote' => "Tu {{PLURAL:$1|je posledná úprava|sú posledné '''$1''' úpravy|je posledných '''$1''' úprav}} počas {{PLURAL:$2|posledného dňa|posledných '''$2''' dní}} z $4, $5.",
 'rcnotefrom' => "Nižšie sú zobrazené úpravy od '''$2''' (do '''$1''').",
 'rclistfrom' => 'Zobraziť nové úpravy počnúc od $1',
@@ -1697,7 +1722,7 @@ Musí obsahovať menej ako $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'rclinks' => 'Zobraziť posledných $1 úprav v posledných $2 dňoch<br />$3',
 'diff' => 'rozdiel',
 'hist' => 'história',
-'hide' => 'skryť',
+'hide' => 'Skryť',
 'show' => 'zobraziť',
 'minoreditletter' => 'd',
 'newpageletter' => 'N',
@@ -2114,6 +2139,8 @@ Možno chcete upraviť popis na jeho [$2 popisnej stránke súboru] tam.',
 'pageswithprop-text' => 'Táto stránka obsahuje stránky, ktoré používajú konkrétnu vlastnosť stránky.',
 'pageswithprop-prop' => 'Názov vlastnosti:',
 'pageswithprop-submit' => 'Vykonať',
+'pageswithprop-prophidden-long' => 'dlhá hodnota textovej vlastnosti bola skrytá ($1)',
+'pageswithprop-prophidden-binary' => 'hodnota binárnej vlastnosti bola skrytá ($1)',
 
 'doubleredirects' => 'Dvojité presmerovania',
 'doubleredirectstext' => 'Táto stránka obsahuje zoznam stránok, ktoré presmerovávajú na iné presmerovacie stránky.
@@ -2187,6 +2214,7 @@ Každý riadok obsahuje odkaz na prvé a druhé presmerovanie a tiež prvý riad
 'listusers' => 'Zoznam používateľov',
 'listusers-editsonly' => 'Vynechať používateľov bez úprav',
 'listusers-creationsort' => 'Zoradiť podľa dátumu vytvorenia',
+'listusers-desc' => 'Zoradiť zostupne',
 'usereditcount' => '$1 {{PLURAL:$1|úprava|úpravy|úprav}}',
 'usercreated' => '{{GENDER:$3|Registrovaný|Registrovaná|Registrovaný(á)}} $1 $2',
 'newpages' => 'Nové stránky',
@@ -2282,7 +2310,7 @@ Povinná je minimálne doména najvyššej úrovne, napr. „*.org“.<br />
 # Special:ActiveUsers
 'activeusers' => 'Zoznam aktívnych používateľov',
 'activeusers-intro' => 'Toto je zoznam používateľov, ktorí $1 {{PLURAL:$1|za posledný 1 deň|za posledné $1 dni|za posledných $1 dní}} vykonali nejakú aktivitu.',
-'activeusers-count' => '$1 {{PLURAL:$1|úprava|úpravy|úprav}} za {{PLURAL:$3|posledný deň|posledné $3 dni|posledných $3 dní}}',
+'activeusers-count' => '$1 {{PLURAL:$1|operácia|operácie|operácií}} za {{PLURAL:$3|posledný deň|posledné $3 dni|posledných $3 dní}}',
 'activeusers-from' => 'Zobraziť používateľov počínajúc:',
 'activeusers-hidebots' => 'Skryť robotov',
 'activeusers-hidesysops' => 'Skryť správcov',
@@ -2443,10 +2471,12 @@ Na $2 nájdete zoznam posledných zmazaní.',
 'deletecomment' => 'Dôvod:',
 'deleteotherreason' => 'Iný/ďalší dôvod:',
 'deletereasonotherlist' => 'Iný dôvod',
-'deletereason-dropdown' => '*Bežné dôvody zmazania
-** Na žiadosť autora
+'deletereason-dropdown' => '* Bežné dôvody zmazania
+** Spam
+** Vandalizmus
 ** Porušenie autorských práv
-** Vandalizmus',
+** Na žiadosť autora
+** Chybné presmerovanie',
 'delete-edit-reasonlist' => 'Upraviť dôvody zmazania',
 'delete-toobig' => 'Táto stránka má veľkú históriu úprav, viac ako $1 {{PLURAL:$1|revíziu|revízie|revízií}}. Mazanie takýchto stránok bolo obmedzené, aby sa zabránilo náhodnému poškodeniu {{GRAMMAR:genitív|{{SITENAME}}}}.',
 'delete-warning-toobig' => 'Táto stránka má veľkú históriu úprav, viac ako $1 {{PLURAL:$1|revíziu|revízie|revízií}}. Jej zmazanie by mohlo narušiť databázové operácie {{GRAMMAR:genitív|{{SITENAME}}}}; postupujte opatrne.',
@@ -2454,7 +2484,7 @@ Na $2 nájdete zoznam posledných zmazaní.',
 # Rollback
 'rollback' => 'Vrátiť späť úpravy',
 'rollback_short' => 'Vrátiť',
-'rollbacklink' => 'rollback',
+'rollbacklink' => 'vrátiť',
 'rollbacklinkcount' => 'vrátenie $1 {{PLURAL:$1|úpravy|úprav}}',
 'rollbacklinkcount-morethan' => 'vrátiť viac ako $1 {{PLURAL:$1|úpravu|úprav}}',
 'rollbackfailed' => 'Rollback neúspešný',
@@ -2464,7 +2494,7 @@ Na $2 nájdete zoznam posledných zmazaní.',
 Autorom poslednej úpravy je [[User:$3|$3]] ([[User talk:$3|Diskusia]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Zhrnutie úpravy bolo: „''$1''“.",
 'revertpage' => 'Posledné úpravy používateľa [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusia]]) vrátené; bola obnovená posledná úprava $1',
-'revertpage-nouser' => 'Vrátené úpravy (meno používateľa odstránené) na poslednú revíziu od [[User:$1|$1]]',
+'revertpage-nouser' => 'Vrátené úpravy od skrytého používateľa na poslednú revíziu od {{GENDER:$1|[[User:$1|$1]]}}',
 'rollback-success' => 'Úpravy $1 vrátené; obnovená posledná verzia od $2.',
 
 # Edit tokens
@@ -2604,7 +2634,7 @@ $1',
 'contributions' => 'Príspevky {{GENDER:$1|používateľa|používateľky}}',
 'contributions-title' => 'Príspevky používateľa pre $1',
 'mycontris' => 'Príspevky',
-'contribsub2' => 'Príspevky $1 ($2)',
+'contribsub2' => 'Príspevky {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Neboli nájdené úpravy, ktoré by zodpovedali týmto kritériám.',
 'uctop' => '(aktuálne)',
 'month' => 'Mesiac:',
@@ -2726,7 +2756,7 @@ z/od momentálne zablokovanej IP adresy/používateľa.',
 'ipblocklist-empty' => 'Zoznam blokovaní je prázdny.',
 'ipblocklist-no-results' => 'Požadovaná IP adresa alebo používateľské meno nie je blokovaná.',
 'blocklink' => 'zablokovať',
-'unblocklink' => 'odblokuj',
+'unblocklink' => 'odblokovať',
 'change-blocklink' => 'zmeniť blokovanie',
 'contribslink' => 'príspevky',
 'emaillink' => 'poslať email',
@@ -2764,6 +2794,7 @@ blokované IP adresy nie sú zahrnuté. Pozri zoznam
 'proxyblockreason' => 'Vaša IP adresa bola zablokovaná, pretože je otvorená proxy. Prosím kontaktujte vášho internetového poskytovateľa alebo technickú podporu a informujte ich o tomto vážnom bezpečnostnom probléme.',
 'sorbsreason' => 'Vaša IP adresa je vedená ako nezabezpečený proxy server v DNSBL.',
 'sorbs_create_account_reason' => 'Vaša IP adresa je vedená ako nezabezpečený proxy server v databáze DNSBL, ktorú používa {{SITENAME}}. Nemôžete si vytvoriť účet.',
+'xffblockreason' => 'IP adresa prítomná v hlavičke X-Forwarded-For patriaca buď vám alebo proxy serveru, ktorý používate, je zablokovaná. Pôvodný dôvod zablokovania bol: $1',
 'cant-block-while-blocked' => 'Nemôžete blokovať iných používateľov, kým ste zablokovaný.',
 'cant-see-hidden-user' => 'Používateľ, ktorého sa pokúšate zablokovať už bol zablokovaný a skrytý. Pretože nemáte právo hideuser, nemôžete vidieť ani upravovať blokovanie používateľa.',
 'ipbblocked' => 'Nemôžete zablokovať ani odblokovať iných používateľov, pretože ste sami zablokovaní',
@@ -2868,7 +2899,7 @@ Prosím, zlúčte ich ručne.'''",
 'movesubpagetext' => 'Táto stránka má $1 {{PLURAL:$1|podstránku, ktorá je zobrazená nižšie|podstránky, ktoré sú zobrazené nižšie|podstránok, ktoré sú zobrazené nižšie}}.',
 'movenosubpage' => 'Táto stránka nemá podstránky.',
 'movereason' => 'Dôvod:',
-'revertmove' => 'obnova',
+'revertmove' => 'obnov',
 'delete_and_move' => 'Vymazať a presunúť',
 'delete_and_move_text' => '==Je potrebné zmazať stránku==
 
@@ -2896,7 +2927,7 @@ Cieľová stránka „[[:$1]]“ už existuje. Chcete ho vymazať a vytvoriť ta
 Prosím, zvoľte iný názov.',
 
 # Export
-'export' => 'Export stránok',
+'export' => 'Exportovať stránky',
 'exporttext' => 'Môžete exportovať text a históriu úprav konkrétnej
 stránky alebo množiny stránok do XML; tieto môžu byť potom importované do inej
 wiki používajúceho MediaWiki softvér pomocou stránky Special:Import.
@@ -2924,7 +2955,7 @@ V druhom prípade môžete tiež použiť odkaz, napr. [[{{#Special:Export}}/{{M
 'allmessagesdefault' => 'štandardný text',
 'allmessagescurrent' => 'aktuálny text',
 'allmessagestext' => 'Toto je zoznam všetkých správ dostupných v mennom priestore MediaWiki.
-Prosím, navštívte [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net] ak chcete prispieť k všeobecnej lokalizácii MediaWiki.',
+Prosím, navštívte [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] a [//translatewiki.net translatewiki.net] ak chcete prispieť k všeobecnej lokalizácii MediaWiki.',
 'allmessagesnotsupportedDB' => "Túto stránku nemožno použiť, pretože '''\$wgUseDatabaseMessages''' je vypnuté.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filter podľa stavu prispôsobenia:',
@@ -3023,16 +3054,16 @@ Uložte ho na svoj disk a nahrajte sem.',
 'tooltip-pt-anonuserpage' => 'Používateľská stránka pre ip adresu, ktorú upravujete ako',
 'tooltip-pt-mytalk' => 'Vaša diskusná stránka',
 'tooltip-pt-anontalk' => 'Diskusia o úpravách z tejto ip adresy',
-'tooltip-pt-preferences' => 'Moje nastavenia',
+'tooltip-pt-preferences' => 'Vaše nastavenia',
 'tooltip-pt-watchlist' => 'Zoznam stránok, na ktorých sledujete zmeny.',
 'tooltip-pt-mycontris' => 'Zoznam vašich príspevkov',
 'tooltip-pt-login' => 'Odporúčame vám prihlásiť sa, nie je to však povinné.',
 'tooltip-pt-anonlogin' => 'Odporúčame vám prihlásiť sa, nie je to však povinné.',
 'tooltip-pt-logout' => 'Odhlásiť',
 'tooltip-ca-talk' => 'Diskusia o obsahu stránky',
-'tooltip-ca-edit' => 'Môžete upravovať túto stránku. Prosíme, pred uložením použite tlačidlo Zobraziť náhľad.',
+'tooltip-ca-edit' => 'Môžete upravovať túto stránku. Prosím, pred uložením použite tlačidlo Zobraziť náhľad.',
 'tooltip-ca-addsection' => 'Začať novú sekciu',
-'tooltip-ca-viewsource' => 'Táto stránka je zamknutá. Môžete však vidieť jej zdrojový text.',
+'tooltip-ca-viewsource' => 'Táto stránka je zamknutá. Môžete však zobraziť jej zdrojový text.',
 'tooltip-ca-history' => 'Minulé verzie tejto stránky.',
 'tooltip-ca-protect' => 'Zamknúť túto stránku',
 'tooltip-ca-unprotect' => 'Zmeniť stav ochrany tejto stránky',
@@ -3044,34 +3075,34 @@ Uložte ho na svoj disk a nahrajte sem.',
 'tooltip-search' => 'Vyhľadávanie na {{GRAMMAR:datív|{{SITENAME}}}}',
 'tooltip-search-go' => 'Prejsť na stránku s presne takýmto názvom, ak existuje',
 'tooltip-search-fulltext' => 'Hľadať tento text na stránkach',
-'tooltip-p-logo' => 'Hlavná stránka',
+'tooltip-p-logo' => 'Navštívte Hlavnú stránku',
 'tooltip-n-mainpage' => 'Navštíviť Hlavnú stránku',
 'tooltip-n-mainpage-description' => 'Navštíviť hlavnú stránku',
 'tooltip-n-portal' => 'O projekte, ako môžete prispieť, kde čo nájsť',
 'tooltip-n-currentevents' => 'Aktuálne udalosti a ich pozadie',
-'tooltip-n-recentchanges' => 'Zoznam posledných úprav vo wiki.',
-'tooltip-n-randompage' => 'Zobrazenie náhodnej stránky',
-'tooltip-n-help' => 'Pozrieť si pomoc.',
+'tooltip-n-recentchanges' => 'Zoznam posledných úprav na wiki.',
+'tooltip-n-randompage' => 'Zobraziť náhodnú stránku',
+'tooltip-n-help' => 'Miesto, kde sa môžete dozvedieť',
 'tooltip-t-whatlinkshere' => 'Zoznam všetkých wiki stránok, ktoré sem odkazujú',
-'tooltip-t-recentchangeslinked' => 'Posledné úpravy v stránkach, ktoré odkazujú na túto stránku',
+'tooltip-t-recentchangeslinked' => 'Posledné úpravy v stránkach, na ktoré odkazuje táto stránka',
 'tooltip-feed-rss' => 'RSS feed pre túto stránku',
-'tooltip-feed-atom' => 'Atom feed pre túto stránku',
+'tooltip-feed-atom' => 'Kanál Atom pre túto stránku',
 'tooltip-t-contributions' => 'Pozrieť si zoznam príspevkov od tohto používateľa',
 'tooltip-t-emailuser' => 'Poslať e-mail tomuto používateľovi',
-'tooltip-t-upload' => 'Nahranie obrázkových alebo multimediálnych súborov',
+'tooltip-t-upload' => 'Nahranie súborov',
 'tooltip-t-specialpages' => 'Zoznam všetkých špeciálnych stránok',
 'tooltip-t-print' => 'Verzia tejto stránky pre tlač',
 'tooltip-t-permalink' => 'Trvalý odkaz na túto verziu stránky',
-'tooltip-ca-nstab-main' => 'Pozrieť si obsah stránky',
+'tooltip-ca-nstab-main' => 'Zobraziť obsah stránky',
 'tooltip-ca-nstab-user' => 'Pozrieť si stránku používateľa',
 'tooltip-ca-nstab-media' => 'Pozrieť si stránku médií',
 'tooltip-ca-nstab-special' => 'Toto je špeciálna stránka, nemôžete ju upravovať.',
 'tooltip-ca-nstab-project' => 'Pozrieť si stránku projektu',
 'tooltip-ca-nstab-image' => 'Zobraziť popisnú stránku súboru',
 'tooltip-ca-nstab-mediawiki' => 'Pozrieť si systémovú stránku',
-'tooltip-ca-nstab-template' => 'Pozrieť si šablónu',
+'tooltip-ca-nstab-template' => 'Zobraziť šablónu',
 'tooltip-ca-nstab-help' => 'Pozrieť si stránku Pomocníka',
-'tooltip-ca-nstab-category' => 'Pozrieť si stránku s kategóriami',
+'tooltip-ca-nstab-category' => 'Zobraziť stránku s kategóriami',
 'tooltip-minoredit' => 'Označiť túto úpravu ako drobnú',
 'tooltip-save' => 'Uložiť vaše úpravy',
 'tooltip-preview' => 'Náhľad úprav, prosím použite pred uložením!',
@@ -3136,6 +3167,8 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 'spam_reverting' => 'Vraciam poslednú verziu, ktorá neobsahuje odkazy na $1',
 'spam_blanking' => 'Všetky revízie obsahovali odkaz na $1, odstraňujem obsah',
 'spam_deleting' => 'Všetky revízie obsahovali odkaz na $1, odstraňuje sa',
+'simpleantispam-label' => "Antispamová kontrola.
+'''NEVYPĹŇAJTE''' nasledovné!",
 
 # Info page
 'pageinfo-title' => 'Informácie o „$1“',
@@ -3149,13 +3182,14 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 'pageinfo-length' => 'Dĺžka stránky (v bajtoch)',
 'pageinfo-article-id' => 'ID stránky',
 'pageinfo-language' => 'Jazyk obsahu stránok',
-'pageinfo-robot-policy' => 'Stav vyhľadávača',
-'pageinfo-robot-index' => 'Indexovať stránku',
-'pageinfo-robot-noindex' => 'Neindexovať stránku',
+'pageinfo-content-model' => 'Model obsahu stránky',
+'pageinfo-robot-policy' => 'Indexovanie pomocou robotov',
+'pageinfo-robot-index' => 'Povolené',
+'pageinfo-robot-noindex' => 'Nepovolené',
 'pageinfo-views' => 'Počet zobrazení',
 'pageinfo-watchers' => 'Počet používateľov sledujúcich stránku',
 'pageinfo-few-watchers' => 'Menej ako $1 {{PLURAL:$1|sledujúci|sledujúci|sledujúcich}}',
-'pageinfo-redirects-name' => 'Presmerovania na túto stránku',
+'pageinfo-redirects-name' => 'Počet presmerovaní na túto stránku',
 'pageinfo-subpages-name' => 'Podstránky tejto stránky',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|presmerovanie|presmerovania|presmerovaní}}; $3 {{PLURAL:$3|nie je presmerovanie|nie sú presmerovania}})',
 'pageinfo-firstuser' => 'Tvorca stránky',
@@ -3235,7 +3269,7 @@ Jeho spustením môžete kompromitovať svoj systém.",
 'svg-long-desc' => 'SVG súbor, $1 × $2 pixelov, veľkosť súboru: $3',
 'svg-long-desc-animated' => 'Animovaný súbor SVG, nominálne $1 × $2 pixlov, veľkosť súboru: $3',
 'svg-long-error' => 'Neplatný súbor SVG: $1',
-'show-big-image' => 'Obrázok vo vyššom rozlíšení',
+'show-big-image' => 'Pôvodný súbor',
 'show-big-image-preview' => 'Veľkosť tohto náhľadu: $1.',
 'show-big-image-other' => 'Iné {{PLURAL:$2|rozlíšenie|rozlíšenia}}: $1 .',
 'show-big-image-size' => '$1 × $2 pixlov',
@@ -3701,7 +3735,7 @@ Ostatné budú predvolene skryté.
 
 # External editor support
 'edit-externally' => 'Upraviť tento súbor pomocou externého programu',
-'edit-externally-help' => '(Viac informácií poskytnú inštrukcie pre nastavenie [//www.mediawiki.org/wiki/Manual:External_editors externého editora])',
+'edit-externally-help' => '(Viac informácií poskytnú inštrukcie pre nastavenie [https://www.mediawiki.org/wiki/Manual:External_editors externého editora])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'všetky',
@@ -3763,7 +3797,7 @@ ktorý zruší potvrdenie emailovej adresy:
 $5
 
 Platnosť tohto potvrdzovacieho kódu vyprší $4.',
-'confirmemail_body_set' => 'Niekto, pravdepodobne vy, z IP adresy $1
+'confirmemail_body_set' => 'Niekto, pravdepodobne vy, z IP adresy $1
 nastavil e-mailovú adresu účtu „$2“ na túto adresu na {{GRAMMAR:genitív|{{SITENAME}}}}.
 
 Ak chcete potvrdiť, že tento účet skutočne patrí vám a aktivovať
@@ -3772,7 +3806,7 @@ e-mailové funkcie na {{GRAMMAR:genitív|{{SITENAME}}}}, otvorte tento odkaz vo
 $3
 
 Ak účet nie je *nepatrí* patrí k vám, nasledujte tento odkaz,
-ktorú zruší potvrdenie e-mailovej adresy:
+ktorý zruší potvrdenie e-mailovej adresy:
 
 $5
 
@@ -3805,6 +3839,9 @@ Prosím, potvrďte, že túto stránku chcete skutočne znovu vytvoriť.",
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Odstrániť túto stránku z vášho zoznamu sledovaných?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1“',
+
 # Multipage image navigation
 'imgmultipageprev' => '&larr; predošlá stránka',
 'imgmultipagenext' => 'ďalšia stránka &rarr;',
@@ -3894,7 +3931,7 @@ Tiež môžete [[Special:EditWatchlist|použiť štandardný editor]].',
 'version-hook-subscribedby' => 'Pripojené',
 'version-version' => '(Verzia $1)',
 'version-license' => 'Licencia',
-'version-poweredby-credits' => "Táto wiki beží na '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Táto wiki beží na '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'ďalší',
 'version-poweredby-translators' => 'prekladatelia na translatewiki.net',
 'version-credits-summary' => 'Nasledujúcim osobám by sme radi poďakovali za ich príspevky k vývoju [[Special:Version|MediaWiki]].',
@@ -3913,7 +3950,7 @@ Spolu s týmto programom by ste obdržať [{{SERVER}}{{SCRIPTPATH}}/COPYING kóp
 # Special:Redirect
 'redirect' => 'Presmerovanie podľa súboru, používateľa alebo ID revízie',
 'redirect-legend' => 'Presmerovanie na súbor alebo stránku',
-'redirect-summary' => 'Táto špeciálna stránka presmerováva na súbor (podľa názvu), stránku (podľa identifikátora revízie) alebo používateľa (podľa číselného identifikátora používateľa).',
+'redirect-summary' => 'Táto špeciálna stránka presmerováva na súbor (podľa názvu súboru), stránku (podľa identifikátora revízie) alebo používateľa (podľa číselného identifikátora používateľa). Použitie: [[{{#Special:Redirect}}/file/Príklad.jpg]], [[{{#Special:Redirect}}/revision/328429]], resp. [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Ísť',
 'redirect-lookup' => 'Vyhľadať:',
 'redirect-value' => 'Hodnota:',
@@ -3935,8 +3972,7 @@ Spolu s týmto programom by ste obdržať [{{SERVER}}{{SCRIPTPATH}}/COPYING kóp
 
 # Special:SpecialPages
 'specialpages' => 'Špeciálne stránky',
-'specialpages-note' => '----
-* Bežné špeciálne stránky.
+'specialpages-note' => '* Bežné špeciálne stránky.
 * <strong class="mw-specialpagerestricted">Špeciálne stránky s obmedzeným prístupom.</strong>
 * <span class="mw-specialpagecached">Špeciálne stránky vo vyrovnávacej pamäti (môže byť neaktuálne).</span>',
 'specialpages-group-maintenance' => 'Údržbové správy',
@@ -3976,6 +4012,7 @@ Spolu s týmto programom by ste obdržať [{{SERVER}}{{SCRIPTPATH}}/COPYING kóp
 'tags-tag' => 'Názov značky',
 'tags-display-header' => 'Vzhľad v zoznamoch úprav',
 'tags-description-header' => 'Úplný popis významu',
+'tags-active-header' => 'Aktívny?',
 'tags-hitcount-header' => 'Označené úpravy',
 'tags-active-yes' => 'Áno',
 'tags-active-no' => 'Nie',
@@ -4136,10 +4173,38 @@ V opačnom prípade môžete použiť zjednodušený formulár nižšie. Váš k
 'rotate-comment' => 'Obrázok otočený o $1 {{PLURAL:$1|stupeň|stupne|stupňov}} v smere hodinových ručičiek',
 
 # Limit report
+'limitreport-title' => 'Profilovacie údaje analyzátora:',
+'limitreport-cputime' => 'Čas využitia procesora',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|sekunda|sekundy|sekúnd}}',
+'limitreport-walltime' => 'Reálny čas využitia',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekunda|sekundy|sekúnd}}',
+'limitreport-ppvisitednodes' => 'Počet uzlov, ktoré preprocesor navštívil',
+'limitreport-ppgeneratednodes' => 'Počet uzlov, ktoré preprocesor vytvoril',
+'limitreport-postexpandincludesize' => 'Veľkosť vloženého objektu po rozbalení',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bajt|bajty|bajtov}}',
 'limitreport-templateargumentsize' => 'Veľkosť argumentov šablón',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bajt|bajty|bajtov}}',
 'limitreport-expansiondepth' => 'Najväčšia hĺbka expanzie',
 'limitreport-expensivefunctioncount' => 'Počet náročných funkcií parseru',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Substituovať šablóny',
+'expand_templates_intro' => 'Táto špeciálna stránka prijme na
+vstup text a rekurzívne substituuje všetky šablóny,
+ktoré sú v ňom použité. Tiež expanduje funkcie
+syntaktického analyzátora ako <nowiki>{{</nowiki>#language:...}}
+a premenné ako <nowiki>{{</nowiki>CURRENTDAY}}—v podstate
+takmer všetko v zložených zátvorkách. Robí to pomocou
+volania relevantnej fázy syntaktického analyzátora
+samotného MediaWiki.',
+'expand_templates_title' => 'Názov kontextu pre {{FULLPAGENAME}} atď.:',
+'expand_templates_input' => 'Vstupný text:',
+'expand_templates_output' => 'Výsledok',
+'expand_templates_xml_output' => 'XML výstup',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Odstrániť komentáre',
+'expand_templates_remove_nowiki' => 'Potlačiť značky <nowiki> vo výsledku',
+'expand_templates_generate_xml' => 'Zobraziť strom XML',
+'expand_templates_preview' => 'Náhľad',
+
 );
index 040fef7..9e762a4 100644 (file)
@@ -48,7 +48,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'StarodavneStrani' ),
        'Blankpage'                 => array( 'PraznaStran' ),
        'Block'                     => array( 'Blokiraj', 'BlokirajIP', 'BlokirajUporabnika' ),
-       'Blockme'                   => array( 'BlokirajMe' ),
        'Booksources'               => array( 'ViriKnjig' ),
        'BrokenRedirects'           => array( 'PretrganePreusmeritve' ),
        'Categories'                => array( 'Kategorije' ),
@@ -56,7 +55,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Prispevki' ),
        'CreateAccount'             => array( 'Registracija' ),
        'DeletedContributions'      => array( 'IzbrisaniPrispevki' ),
-       'Disambiguations'           => array( 'Razločitve' ),
        'DoubleRedirects'           => array( 'DvojnePreusmeritve' ),
        'Export'                    => array( 'Izvozi' ),
        'Fewestrevisions'           => array( 'NajmanjRedakcij' ),
@@ -405,7 +403,7 @@ $messages = array(
 'articlepage' => 'Prikaže članek',
 'talk' => 'Pogovor',
 'views' => 'Pogled',
-'toolbox' => 'Pripomočki',
+'toolbox' => 'Orodja',
 'userpage' => 'Prikaži uporabnikovo stran',
 'projectpage' => 'Prikaži projektno stran',
 'imagepage' => 'Pokaži stran z datoteko',
@@ -462,8 +460,6 @@ $1',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Vzpostavljeno iz »$1«',
 'youhavenewmessages' => 'Imate $1 ($2)',
-'newmessageslink' => 'nova sporočila',
-'newmessagesdifflink' => 'zadnja sprememba',
 'youhavenewmessagesfromusers' => 'Imate $1 od {{PLURAL:$3|drugega uporabnika|$3 uporabnikov}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od veliko uporabnikov ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novo sporočilo|nova sporočila}}',
@@ -519,9 +515,9 @@ Seznam vseh prepoznanih posebnih strani je na razpolago na strani [[Special:Spec
 # General errors
 'error' => 'Napaka',
 'databaseerror' => 'Napaka zbirke podatkov',
-'databaseerror-text' => 'Prišlo je do napake poizvedbe v zbirki podatkov.
-To lahko pomeni hrošča v programju.',
-'databaseerror-textcl' => 'Prišlo je do napake poizvedbe v zbirki podatkov.',
+'databaseerror-text' => 'Pri poizvedbi v zbirki podatkov je prišlo do napake.
+Vzrok za to je morda programski hrošč.',
+'databaseerror-textcl' => 'Pri poizvedbi v zbirki podatkov je prišlo do napake.',
 'databaseerror-query' => 'Poizvedba: $1',
 'databaseerror-function' => 'Funkcija: $1',
 'databaseerror-error' => 'Napaka: $1',
@@ -574,7 +570,7 @@ Poizvedba: $2',
 'actionthrottledtext' => 'Kot ukrep proti smetju, je število izvajanj tega dejanja v časovnem obdobju omejeno, in vi ste ta limit presegli.
 Prosimo, poskusite znova čez nekaj minut.',
 'protectedpagetext' => 'Ta stran je bila zaklenjena za preprečitev urejanja ali drugih dejanj.',
-'viewsourcetext' => 'Lahko si ogledate in kopirate vsebino te strani:',
+'viewsourcetext' => 'Vsebino te strani si lahko ogledate in kopirate:',
 'viewyourtext' => "Lahko si ogledate in kopirate vsebino '''vaših urejanj''' te strani:",
 'protectedinterface' => 'Prikazana stran vsebuje besedilo vmesnika programja na tem wikiju in je zaradi preprečevanja zlorab zaščitena.
 
@@ -647,10 +643,10 @@ Ne pozabite si prilagoditi vaših [[Special:Preferences|nastavitev {{GRAMMAR:rod
 'gotaccount' => 'Račun že imate? $1.',
 'gotaccountlink' => 'Prijavite se',
 'userlogin-resetlink' => 'Ste pozabili svoje prijavne podatke?',
-'userlogin-resetpassword-link' => 'Ponastavite svoje geslo',
+'userlogin-resetpassword-link' => 'Ste pozabili svoje geslo?',
 'helplogin-url' => 'Help:Prijava',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoč pri prijavi]]',
-'userlogin-loggedin' => 'Ste že prijavljeni kot {{GENDER:$1|$1}}.
+'userlogin-loggedin' => 'Prijavljeni ste že kot {{GENDER:$1|$1}}.
 Uporabite spodnji obrazec, da se prijavite kot drug uporabnik.',
 'userlogin-createanother' => 'Ustvari drug račun',
 'createacct-join' => 'Spodaj vnesite svoje informacije.',
@@ -727,8 +723,8 @@ Za preprečevanje zlorab lahko na {{PLURAL:$1|uro|$1 uri|$1 ure|$1 ur}} pošljem
 
 Če urejate prek AOL ali iz Bližnjega vzhoda, Afrike, Avstralije, Nove Zelandije ali iz šole, knjižnice ali podjetja, si IP-naslov morda delite z drugimi uporabniki. Če je tako, ste to sporočilo morda prejeli, čeprav niste ustvarili še nobenega računa. Znova se lahko poskusite registrirati po nekaj urah.',
 'emailauthenticated' => 'Vaš e-poštni naslov je bil potrjen dne $2 ob $3.',
-'emailnotauthenticated' => 'Vaš e-poštni naslov še ni potrjen. Za navedene
-možnosti se e-pošte ne bo pošiljalo.',
+'emailnotauthenticated' => 'Vaš e-poštni naslov še ni potrjen.
+Za navedene možnosti e-pošte ne bomo pošiljali.',
 'noemailprefs' => 'E-poštnega naslova niste vnesli, zato naslednje možnosti ne bodo delovale.',
 'emailconfirmlink' => 'Potrdite svoj e-poštni naslov',
 'invalidemailaddress' => 'E-poštni naslov zaradi neveljavne oblike ni sprejemljiv.
@@ -777,8 +773,8 @@ Morda ste že uspešno spremenili geslo ali pa ste zahtevali novo začasno geslo
 
 # Special:PasswordReset
 'passwordreset' => 'Ponastavitev gesla',
-'passwordreset-text-one' => 'Izpolnite obrazec, da ponastavite svoje geslo.',
-'passwordreset-text-many' => 'Izpolnite {{PLURAL:$1|polje|enega od polj}}, da ponastavite svoje geslo.',
+'passwordreset-text-one' => 'Da ponastavite svoje geslo, izpolnite naslednji obrazec.',
+'passwordreset-text-many' => '{{PLURAL:$1|Da ponastavite svoje geslo, izpolnite eno od polj.}}',
 'passwordreset-legend' => 'Ponastavitev gesla',
 'passwordreset-disabled' => 'Ponastavljanje gesla je na tem wikiju onemogočeno.',
 'passwordreset-emaildisabled' => 'Na tem wikiju so možnosti e-pošte onemogočene.',
@@ -879,17 +875,17 @@ To storite, če ste po nesreči žetone z nekom delili, ali če je bil vaš rač
 'summary-preview' => 'Predogled povzetka',
 'subject-preview' => 'Predogled zadeve/naslova:',
 'blockedtitle' => 'Uporabnik je blokiran',
-'blockedtext' => "'''Urejanje z vašim uporabniškim imenom oziroma IP-naslovom je bilo onemogočeno.'''
+'blockedtext' => "'''Urejanje z vašim uporabniškim imenom oziroma IP-naslovom je onemogočeno.'''
 
 Blokiral vas je $1.
-Podan razlog je ''$2''.
+Podani razlog je ''$2''.
 
-* Začetek blokade: $8
-* Potek blokade: $6
-* Namen blokade: $7
+* začetek blokade: $8
+* potek blokade: $6
+* blokirani uporabnik: $7
 
-O blokiranju se lahko pogovorite z $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].
-Vedite, da lahko ukaz »Pošlji uporabniku e-pismo« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov ter le-ta ni bil blokiran.
+O blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].
+Vedite, da lahko ukaz »Pošlji uporabniku e-pismo« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.
 Vaš IP-naslov je $3, številka blokade pa #$5.
 Prosimo, vključite ju v vse morebitne poizvedbe.",
 'autoblockedtext' => "Vaš IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.
@@ -1072,7 +1068,7 @@ Naslednji argumenti so bili izpuščeni.",
 'converter-manual-rule-error' => 'Odkril sem napako v ročnem pravilu pretvorbe jezikov',
 
 # "Undo" feature
-'undo-success' => 'Urejanje ste razveljavili. Prosim, potrdite in nato shranite spodnje spremembe.',
+'undo-success' => 'Urejanje ste razveljavili. Prosimo, preverite prikazano primerjavo redakcij in, če ustrezajo, shranite spremembe.',
 'undo-failure' => 'Zaradi navzkrižij urejanj, ki so se vmes pojavila, tega urejanja ni moč razveljaviti.',
 'undo-norev' => 'Urejanja ni mogoče razveljaviti, ker ne obstaja ali je bilo izbrisano.',
 'undo-summary' => 'Redakcija $1 uporabnika [[Special:Contributions/$2|$2]] ([[User talk:$2|pogovor]]) razveljavljena',
@@ -1080,9 +1076,9 @@ Naslednji argumenti so bili izpuščeni.",
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Računa ni moč ustvariti',
-'cantcreateaccount-text' => "Registracija novega uporabnika iz tega IP-naslova ('''$1''') je bila blokirana s strani [[User:$3|$3]].
+'cantcreateaccount-text' => "Registracije z IP-naslova ('''$1''') je administrator(ka) [[User:$3|$3]] blokiral(a).
 
-Razlog, ki ga je podal $3, je ''$2''.",
+Razlog, ki ga je $3 podal(a), je ''$2''.",
 
 # History pages
 'viewpagelogs' => 'Poglej dnevniške zapise o strani',
@@ -1164,19 +1160,19 @@ To redakcijo si lahko ogledate; podrobnosti lahko najdete v [{{fullurl:{{#Specia
 Do skrite vsebine bodo še vedno lahko dostopali drugi administratorji {{GRAMMAR:rodilnik|{{SITENAME}}}} in jo z uporabo istega vmesnika tudi obnovili, razen kjer bodo uveljavljene dodatne omejitve.",
 'revdelete-confirm' => 'Prosim potrdite da nameravate to storiti, da se zavedate posledic in da to počnete v skladu s [[{{MediaWiki:Policy-url}}|politiko]].',
 'revdelete-suppress-text' => "Zadrževanje naj bi bilo uporabljeno '''le''' v sledečih primerih:
-* Potencialni klevetniški podatki
+* Morebitni klevetniški podatki
 * Neprimerni osebni podatki
-*: ''domači naslovi in telefonske številke, številke socialnega zavarovanja, etc.''",
+*: ''domači naslovi in telefonske številke, narodne številke istovetnosti itn.''",
 'revdelete-legend' => 'Nastavi omejitve vidnosti',
-'revdelete-hide-text' => 'Skrij besedilo redakcije',
+'revdelete-hide-text' => 'Besedilo redakcije',
 'revdelete-hide-image' => 'Skrij vsebino datoteke.',
 'revdelete-hide-name' => 'Skrij dejanje in cilj',
-'revdelete-hide-comment' => 'Skrij povzetek urejanja',
-'revdelete-hide-user' => 'Skrij uporabniško ime/IP-naslov urejevalca',
+'revdelete-hide-comment' => 'Povzetek urejanja',
+'revdelete-hide-user' => 'Uporabniško ime/IP-naslov urejevalca',
 'revdelete-hide-restricted' => 'Zadrži podatke od administratorjev kakor tudi od ostalih',
 'revdelete-radio-same' => '(ne spremeni)',
-'revdelete-radio-set' => 'Da',
-'revdelete-radio-unset' => 'Ne',
+'revdelete-radio-set' => 'Skrito',
+'revdelete-radio-unset' => 'Vidno',
 'revdelete-suppress' => 'Zadrži podatke od administratorjev kakor tudi od ostalih',
 'revdelete-unsuppress' => 'Odpraviti omejitve na obnovljenih redakcijah.',
 'revdelete-log' => 'Razlog:',
@@ -1334,8 +1330,6 @@ Upoštevajte, da so njihovi podatki vsebine {{GRAMMAR:rodilnik|{{SITENAME}}}} mo
 'preferences' => 'Nastavitve',
 'mypreferences' => 'Nastavitve',
 'prefs-edits' => 'Število urejanj:',
-'prefsnologin' => 'Niste prijavljeni',
-'prefsnologintext' => 'Za spreminjanje uporabniških nastavitev morate biti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prijavljeni]</span>.',
 'changepassword' => 'Zamenjava gesla',
 'prefs-skin' => 'Koža',
 'skin-preview' => 'Predogled',
@@ -1360,7 +1354,7 @@ Upoštevajte, da so njihovi podatki vsebine {{GRAMMAR:rodilnik|{{SITENAME}}}} mo
 'prefs-rendering' => 'Videz',
 'saveprefs' => 'Shrani',
 'resetprefs' => 'Počisti neshranjene spremembe',
-'restoreprefs' => 'Obnovi vse privzete nastavitve (v vseh razdelkih)',
+'restoreprefs' => 'obnova vseh privzetih nastavitev (v vseh razdelkih)',
 'prefs-editing' => 'Urejanje',
 'rows' => 'Vrstic:',
 'columns' => 'Stolpcev:',
@@ -1635,6 +1629,7 @@ Ko vas drugi uporabniki kontaktirajo, jim vašega e-poštnega naslova ne bomo ra
 'recentchanges-label-minor' => 'Manjše urejanje',
 'recentchanges-label-bot' => 'To urejanje je bilo izvedeno z botom',
 'recentchanges-label-unpatrolled' => 'Urejanje še ni bilo pregledano',
+'recentchanges-legend-newpage' => '$1 - nova stran',
 'rcnote' => "Prikazujem {{PLURAL:$1|zadnjo spremembo|zadnji '''$1''' spremembi|zadnje '''$1''' spremembe|zadnjih '''$1''' sprememb|zadnjih '''$1''' sprememb}} v {{PLURAL:$2|zadnjem|zadnjih|zadnjih|zadnjih|zadnjih}} '''$2''' {{PLURAL:$2|dnevu|dneh|dneh|dneh|dneh}}, od $5, $4.",
 'rcnotefrom' => "Navedene so spremembe od '''$2''' dalje (prikazujem jih do '''$1''').",
 'rclistfrom' => 'Prikaži spremembe od $1 naprej',
@@ -2686,16 +2681,16 @@ Oglejte si [[Special:BlockList|seznam blokad]] za pregled blokad.',
 'unblocked-id' => 'Blokada $1 je odstranjena',
 'blocklist' => 'Blokirani uporabniki',
 'ipblocklist' => 'Blokirani uporabniki',
-'ipblocklist-legend' => 'Najdi blokiranega uporabnika',
-'blocklist-userblocks' => 'Skrij blokade računov',
-'blocklist-tempblocks' => 'Skrij začasne blokade',
-'blocklist-addressblocks' => 'Skrij blokade enega IP-naslova',
-'blocklist-rangeblocks' => 'Skrij bloke obsegov',
+'ipblocklist-legend' => 'Poišči blokiranega uporabnika',
+'blocklist-userblocks' => 'skrij blokade računov',
+'blocklist-tempblocks' => 'skrij začasne blokade',
+'blocklist-addressblocks' => 'skrij blokade posameznih IP-naslovov',
+'blocklist-rangeblocks' => 'skrij blokade razponov',
 'blocklist-timestamp' => 'Časovni žig',
 'blocklist-target' => 'Cilj',
 'blocklist-expiry' => 'Poteče',
-'blocklist-by' => 'Administrator, ki je izvedel blokado',
-'blocklist-params' => 'Parametri blokade',
+'blocklist-by' => 'Administrator',
+'blocklist-params' => 'Parametri',
 'blocklist-reason' => 'Razlog',
 'ipblocklist-submit' => 'Išči',
 'ipblocklist-localblock' => 'Lokalna blokada',
@@ -2703,8 +2698,8 @@ Oglejte si [[Special:BlockList|seznam blokad]] za pregled blokad.',
 'infiniteblock' => 'neomejen čas',
 'expiringblock' => 'preteče $1 ob $2',
 'anononlyblock' => 'samo brezim.',
-'noautoblockblock' => 'samodejna blokada je onemogočena',
-'createaccountblock' => 'ustvarjanje računov onemogočeno',
+'noautoblockblock' => 'onemogočena samodejna blokada',
+'createaccountblock' => 'onemogočeno ustvarjanje računov',
 'emailblock' => 'e-pošta blokirana',
 'blocklist-nousertalk' => 'preprečeno urejanje lastne pogovorne strani',
 'ipblocklist-empty' => 'Seznam blokad je prazen.',
@@ -2722,11 +2717,11 @@ Za sklicevanje so tule navedeni vnosi v dnevniku blokiranja:',
 'blocklog-showsuppresslog' => 'Ta uporabnik je že bil blokiran in skrit.
 Dnevnik skrivanja je na voljo spodaj:',
 'blocklogentry' => '[[$1]] blokiran s časom poteka blokade $2 $3',
-'reblock-logentry' => 'spremenil nastavitve blokade za [[$1]] z iztekom dne $2 ob $3',
+'reblock-logentry' => 'je spremenil(a) nastavitve blokade za [[$1]] na čas $2 $3',
 'blocklogtext' => 'Prikazan je dnevnik blokiranja in deblokiranja uporabnikov. Samodejno blokirani IP-naslovi niso navedeni. Trenutno veljavna blokiranja so navedena na [[Special:BlockList|seznamu blokad]].',
 'unblocklogentry' => 'je deblokiral(-a) »$1«',
 'block-log-flags-anononly' => 'samo za brezimne uporabnike',
-'block-log-flags-nocreate' => 'ustvarjanje uporabniških računov onemogočeno',
+'block-log-flags-nocreate' => 'onemogočeno ustvarjanje računov',
 'block-log-flags-noautoblock' => 'samodejno blokiranje onemogočeno',
 'block-log-flags-noemail' => 'e-naslov blokiran',
 'block-log-flags-nousertalk' => 'prepreči urejanje lastne pogovorne strani',
@@ -2904,7 +2899,7 @@ stran »[[{{MediaWiki:Mainpage}}]]«.',
 'allmessagesdefault' => 'Prednastavljeno besedilo',
 'allmessagescurrent' => 'Trenutno besedilo',
 'allmessagestext' => 'Navedena so v imenskem prostoru MediaWiki dostopna sistemska sporočila.
-Za lokalizacijo in prevajanje obiščite [//www.mediawiki.org/wiki/Localisation MediaWiki] in [//translatewiki.net translatewiki.net] ter tako prispevajte k splošnemu prevodu programja.',
+Za lokalizacijo in prevajanje obiščite [https://www.mediawiki.org/wiki/Localisation MediaWiki] in [//translatewiki.net translatewiki.net] ter tako prispevajte k splošnemu prevodu programja.',
 'allmessagesnotsupportedDB' => "Te strani ni mogoče uporabljati, ker je bilo '''\$wgUseDatabaseMessages''' izključeno.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filtriraj po prilagoditvenem stanju:',
@@ -3071,6 +3066,7 @@ Prosimo, poskusite znova.',
 Omogoča vnos pojasnila v povzetku urejanja.',
 'tooltip-preferences-save' => 'Shrani nastavitve',
 'tooltip-summary' => 'Vnesite kratek povzetek',
+'interlanguage-link-title' => '$1 – $2',
 
 # Metadata
 'notacceptable' => 'V obliki, ki jo lahko bere vaš odjemalec, wikistrežnik podatkov ne more ponuditi.',
@@ -3095,6 +3091,8 @@ Omogoča vnos pojasnila v povzetku urejanja.',
 'spam_reverting' => 'Vračanje na zadnjo redakcijo brez povezav na $1',
 'spam_blanking' => 'Vse redakcije so vsebovale povezave na $1, izpraznjujem',
 'spam_deleting' => 'Vse redakcije so vsebovale povezave na $1, brišem',
+'simpleantispam-label' => "Preverjanje proti smetju.
+'''NE''' izpolnite tega!",
 
 # Info page
 'pageinfo-title' => 'Informacije o »$1«',
@@ -3108,6 +3106,7 @@ Omogoča vnos pojasnila v povzetku urejanja.',
 'pageinfo-length' => 'Dolžina strani (v bajtih)',
 'pageinfo-article-id' => 'ID strani',
 'pageinfo-language' => 'Jezik vsebine strani',
+'pageinfo-content-model' => 'Model vsebine strani',
 'pageinfo-robot-policy' => 'Robotsko indeksiranje',
 'pageinfo-robot-index' => 'Dovoljeno',
 'pageinfo-robot-noindex' => 'Nedovoljeno',
@@ -3189,7 +3188,7 @@ Z njenim zagonom lahko ogrozite vaš sistem.",
 'svg-long-desc' => 'datoteka SVG, v izvirniku $1 × $2 slikovnih točk, velikost datoteke: $3',
 'svg-long-desc-animated' => 'animirana datoteka SVG, v izvirniku $1 × $2 slikovnih točk, velikost datoteke: $3',
 'svg-long-error' => 'Neveljavna datoteka SVG: $1',
-'show-big-image' => 'Slika v višji ločljivosti',
+'show-big-image' => 'Izvirna datoteka',
 'show-big-image-preview' => 'Velikost predogleda: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Druga ločljivost|Drugi ločljivosti|Druge ločljivosti}}: $1.',
 'show-big-image-size' => '$1 × $2 točk',
@@ -3664,7 +3663,7 @@ Druga bodo po privzetem skrita.
 
 # External editor support
 'edit-externally' => 'Uredite datoteko z uporabo zunanjega orodja',
-'edit-externally-help' => '(Za več informacij glejte [//www.mediawiki.org/wiki/Manual:External_editors navodila za namestitev])',
+'edit-externally-help' => '(Za več informacij glejte [https://www.mediawiki.org/wiki/Manual:External_editors navodila za namestitev])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'vse',
@@ -3767,6 +3766,7 @@ Prosimo, potrdite, da jo resnično želite znova ustvariti.",
 
 # Separators for various lists, etc.
 'percent' => '$1&#160;%',
+'quotation-marks' => '»$1«',
 
 # Multipage image navigation
 'imgmultipageprev' => '← prejšnja stran',
@@ -3854,7 +3854,7 @@ Uporabite lahko tudi [[Special:EditWatchlist|standardni urejevalnik]].',
 'version-hook-subscribedby' => 'Naročen s strani',
 'version-version' => '(Različica $1)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Ta wiki poganja '''[//www.mediawiki.org/ MediaWiki]''', vse pravice pridržave © 2001-$1 $2.",
+'version-poweredby-credits' => "Ta wiki poganja '''[https://www.mediawiki.org/ MediaWiki]''', vse pravice pridržave © 2001-$1 $2.",
 'version-poweredby-others' => 'drugi',
 'version-poweredby-translators' => 'Prevajalci translatewiki.net',
 'version-credits-summary' => 'Radi bi priznali prispevek naslednjih oseb k [[Special:Version|MediaWiki]].',
@@ -3875,7 +3875,7 @@ Skupaj s programom bi morali bi prejeti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopijo
 # Special:Redirect
 'redirect' => 'Preusmeri po datoteki, uporabniku ali ID-ju redakcije',
 'redirect-legend' => 'Preusmeritev na datoteko ali stran',
-'redirect-summary' => 'Posebna stran preusmeri na datoteko (če podate ime datoteke), stran (če podate ID redakcije) ali uporabniško stran (če podatek številski ID uporabnika).',
+'redirect-summary' => 'Posebna stran preusmeri na datoteko (če podate ime datoteke), stran (če podate ID redakcije) ali uporabniško stran (če podate številski ID uporabnika). Primer: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] ali [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Pojdi',
 'redirect-lookup' => 'Iskanje:',
 'redirect-value' => 'Vrednost:',
@@ -3897,10 +3897,9 @@ Skupaj s programom bi morali bi prejeti [{{SERVER}}{{SCRIPTPATH}}/COPYING kopijo
 
 # Special:SpecialPages
 'specialpages' => 'Posebne strani',
-'specialpages-note' => '----
-* Navadne posebne strani.
-* <span class="mw-specialpagerestricted">Omejene posebne strani.</span>
-* <span class="mw-specialpagecached">Predpomnjene posebne strani (morda so zastarele).</span>',
+'specialpages-note-top' => 'Legenda',
+'specialpages-note' => '* Navadne posebne strani.
+* <span class="mw-specialpagerestricted">Omejene posebne strani.</span>',
 'specialpages-group-maintenance' => 'Vzdrževalna poročila',
 'specialpages-group-other' => 'Ostale posebne strani',
 'specialpages-group-login' => 'Prijavite se / ustvarite račun',
@@ -4113,4 +4112,21 @@ V nasprotnem primeru lahko uporabite preprost obrazec spodaj. Vašo pripombo bom
 'limitreport-expansiondepth' => 'Največja globina razširitve',
 'limitreport-expensivefunctioncount' => 'Število dragih funkcij razčlenjevalnika',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Razširi predloge',
+'expand_templates_intro' => 'Ta posebna stran nekaj vnesenega besedila predela tako, da klice predlog v njem zamenja z njihovo vsebino.
+Prav tako razreši izraze kot
+<code><nowiki>{{</nowiki>#language:…}}</code> in spremenljivke kot
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Pravzaprav razširi skoraj vse v dvojnih zavitih oklepajih.',
+'expand_templates_title' => 'Naslov sobesedila, za {{FULLPAGENAME}} ipd.:',
+'expand_templates_input' => 'Vhodno besedilo:',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'Izhod XML',
+'expand_templates_ok' => 'V redu',
+'expand_templates_remove_comments' => 'Odstrani komentarje',
+'expand_templates_remove_nowiki' => 'V rezultatu odstrani oznake <nowiki>',
+'expand_templates_generate_xml' => 'Pokaži razčlenitveno drevo XML',
+'expand_templates_preview' => 'Predogled',
+
 );
index d9f0412..91e34a7 100644 (file)
@@ -259,8 +259,6 @@ $1",
 
 'retrievedfrom' => 'voo "$1"',
 'youhavenewmessages' => 'Du hust $1 ($2).',
-'newmessageslink' => 'Neue Noachrichta',
-'newmessagesdifflink' => 'neue Noachrichta',
 'youhavenewmessagesmulti' => 'Du hast neue Nachrichta: $1',
 'editsection' => 'Bearbta',
 'editold' => 'Bearbta',
@@ -798,8 +796,6 @@ Stelle sicher, doaß de Versionsgeschichte anner Seite historisch korrekt ies.',
 'preferences' => 'Eenstellunga',
 'mypreferences' => 'Meene Eistellunga',
 'prefs-edits' => 'Oazoahl dar Beoarbeetunga:',
-'prefsnologin' => 'Ne oagemeldet',
-'prefsnologintext' => 'Du mußt <span class="plainlinks">[{{fullurl:{{#special:UserLogin}}|returnto=$1}} oagemeldet]</span> sei, im denne Einstellunga ändern zu kinna.',
 'changepassword' => 'Poaßwurt ändern',
 'prefs-personal' => 'Nutzerdaten',
 'prefs-rc' => 'Letzte Änderunga',
@@ -989,6 +985,7 @@ Stelle sicher, doaß de Versionsgeschichte anner Seite historisch korrekt ies.',
 'recentchanges-label-minor' => 'Klenne Änderung',
 'recentchanges-label-bot' => "Änderung durch an'n Bot",
 'recentchanges-label-unpatrolled' => 'Nicht-kontrollierte Änderung',
+'recentchanges-legend-newpage' => '$1 - neue Seite',
 'rcnote' => "Oagezeegt {{PLURAL:$1|wird '''1''' Ännerong|waan de letzta '''$1''' Änneronga}} {{PLURAL:$2|des letzta Taages|dar letzta '''$2''' Taage}}. Stand: $4, $5. (<b><tt>N</tt></b>&nbsp;– neuer Eentrag; <b><tt>K</tt></b>&nbsp;– kleene Ännerong; <b><tt>B</tt></b>&nbsp;– Ännerong dorch eena Bot; ''(± Zoahl)''&nbsp;– Greeßaännerong ei Byte)",
 'rcnotefrom' => "Oagezeigt waan de Änderunga seit '''$2''' (max. '''$1''' Einträge).",
 'rclistfrom' => 'Oack Änneronga seit $1 zeiga.',
@@ -1801,7 +1798,7 @@ Alternativ ies der Export au miet der Syntax [[{{#Special:Export}}/{{MediaWiki:M
 'allmessagesname' => 'Noame',
 'allmessagesdefault' => 'Standardtext',
 'allmessagestext' => 'Dies ies anne Liste dar MediaWiki-Systemtexte.
-Besiche de Seyta [//www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], wenn du diech oa dar Lokalisierung vu MediaWiki beteiliga mechtest.',
+Besiche de Seyta [https://www.mediawiki.org/wiki/Localisation MediaWiki-Lokalisierung] und [//translatewiki.net translatewiki.net], wenn du diech oa dar Lokalisierung vu MediaWiki beteiliga mechtest.',
 'allmessagesnotsupportedDB' => 'Diese Spezialseyte stieht ne zur Verfigung, do se ieber dann Parameter <tt>$wgUseDatabaseMessages</tt> deaktiviert wurde.',
 'allmessages-filter-all' => 'Olle',
 'allmessages-language' => 'Sproache:',
@@ -2140,7 +2137,7 @@ Weitere werden standardmäßig nicht angezeigt.
 
 # External editor support
 'edit-externally' => 'Diese Datei mit annem externen Programm bearbta',
-'edit-externally-help' => '(Siehe de [//www.mediawiki.org/wiki/Manual:External_editors Installationsoaweisunga] fier weitere Informationen)',
+'edit-externally-help' => '(Siehe de [https://www.mediawiki.org/wiki/Manual:External_editors Installationsoaweisunga] fier weitere Informationen)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'olle',
@@ -2280,8 +2277,7 @@ Du koast au de [[Special:EditWatchlist|Standard-Beoarbeetungsseyte]] benutza.',
 
 # Special:SpecialPages
 'specialpages' => 'Spezialseyta',
-'specialpages-note' => '----
-* Spezialseyta fier Jedermoan
+'specialpages-note' => '* Spezialseyta fier Jedermoan
 * <strong class="mw-specialpagerestricted">Spezialseyta fier Nutzer miet erweiterta Rechta</strong>',
 'specialpages-group-other' => 'Andere Spezialseyta',
 'specialpages-group-login' => 'Oamelda',
index cfba54f..10b0421 100644 (file)
@@ -270,12 +270,10 @@ fiiri [[Special:Version|nooca bogga]].',
 'ok' => 'waayahay',
 'retrievedfrom' => 'Waxaa laga keenay "$1"',
 'youhavenewmessages' => 'Waxaa heysataa $1 ($2).',
-'newmessageslink' => 'Fariimaha cusub',
-'newmessagesdifflink' => 'bedelkii ugu dambeeyay',
 'youhavenewmessagesfromusers' => 'Waxay $1 kaaga timid {{PLURAL:$3|adeegsade kale|$3 adeegsade}} ($2).',
 'youhavenewmessagesmanyusers' => 'Waxay ka $1 timid adeegsade yaal farabadan ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|Waa fariin cusub|fariin cusub}}',
-'newmessagesdifflinkplural' => '$1 {{PLURAL:$1|bedelkii ugu dambeeyey|bedeladii ugu dambeeyey}}',
+'newmessageslinkplural' => '{{PLURAL:$1|farriin cusub|999=farriimo cusub}}',
+'newmessagesdifflinkplural' => 'isbedel {{PLURAL:$1|dhow|999=isbedello dhow}}',
 'youhavenewmessagesmulti' => '$1 waxaa kuu yaalo fariimo cusub',
 'editsection' => 'Wax ka bedel',
 'editold' => 'Wax ka bedel',
@@ -799,8 +797,6 @@ sababteeda neh waxaa laga heli kartaa  [{{fullurl:{{#Special:Log}}/delete|page={
 # Preferences page
 'preferences' => 'Dooqyada',
 'mypreferences' => 'Dooqyadeyda',
-'prefsnologin' => 'Gudaha kuma jirtid',
-'prefsnologintext' => 'Waa in aad <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Gudaha ku jirtaa]</span> si aad dooqyadaada u dalbatid.',
 'prefs-skin' => 'Jirka',
 'skin-preview' => 'Horfiirin',
 'datedefault' => "Ma'jiro dooq",
@@ -1319,7 +1315,7 @@ Eeg [[Special:BlockList|Mamnuucyada]] si aad u aragto liiska mamnuucyada ee hadd
 'allmessagesdefault' => "Qoraalka la'isku ogyahay",
 'allmessagescurrent' => 'Qoraalka hada qoran',
 'allmessagestext' => 'Kan waa liiska fariimaha systemka oo laga heli karo xarun magaceedka MediaWiki.
-Fadlan booqo [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] iyo [//translatewiki.net translatewiki.net] hadii aad rabto in aad wax ku darsatid guud ahaanba MediaWiki ku fasirida luqadaada.',
+Fadlan booqo [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] iyo [//translatewiki.net translatewiki.net] hadii aad rabto in aad wax ku darsatid guud ahaanba MediaWiki ku fasirida luqadaada.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' la'ma isticmaalikaro, '''\$wgUseDatabaseMessages''' oo dansan daraadeed.",
 'allmessages-language' => 'Luqad:',
 'allmessages-filter-submit' => 'Soco',
@@ -1436,7 +1432,7 @@ Hadii faylka wax laga badalay sida oo markiisa hore ahaa, waxaa laga yaabaa in e
 
 # External editor support
 'edit-externally' => 'wax ka bedel faylkaan adiga oo isticmaalaya brogram dheeraad ah',
-'edit-externally-help' => '(Ka fiiri wax war ah oo kale  [//www.mediawiki.org/wiki/Manual:External_editors sidii oo wax ugu habeysmi lahaa] )',
+'edit-externally-help' => '(Ka fiiri wax war ah oo kale  [https://www.mediawiki.org/wiki/Manual:External_editors sidii oo wax ugu habeysmi lahaa] )',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'dhamaan',
index 35a67cb..83cfaab 100644 (file)
@@ -70,7 +70,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'FaqetAntike' ),
        'Blankpage'                 => array( 'FaqeBosh' ),
        'Block'                     => array( 'BllokoIP' ),
-       'Blockme'                   => array( 'BllokomMua' ),
        'Booksources'               => array( 'BurimeteLibrave' ),
        'Categories'                => array( 'Kategori' ),
        'ChangeEmail'               => array( 'NdryshoEmail' ),
@@ -488,8 +487,6 @@ $1",
 'ok' => 'Ok',
 'retrievedfrom' => 'Marrë nga "$1"',
 'youhavenewmessages' => 'Ju keni $1 ($2).',
-'newmessageslink' => 'mesazhe të reja',
-'newmessagesdifflink' => 'ndryshimi i fundit',
 'youhavenewmessagesfromusers' => 'Ju keni $1 nga {{PLURAL:$3|një përdorues tjetër|$3 përdorues}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ju keni $1 nga shumë përdorues ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|një mesazh i ri|mesazhe të reja}}',
@@ -1264,8 +1261,6 @@ Kini kujdes se përdorimi i lidhjeve të shfletimit do të ndryshojë përzgjedh
 'preferences' => 'Parapëlqimet',
 'mypreferences' => 'Parapëlqimet',
 'prefs-edits' => 'Numri i redaktimeve:',
-'prefsnologin' => 'Nuk keni hyrë brenda',
-'prefsnologintext' => 'Duhet të jeni <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} të kyçur]</span> për të caktuar parapëlqimet e përdoruesit.',
 'changepassword' => 'Ndërroni fjalëkalimin',
 'prefs-skin' => 'Pamja',
 'skin-preview' => 'Parapamje',
@@ -1539,6 +1534,7 @@ Kjo informatë është publike.',
 'recentchanges-label-minor' => 'Ky është një editim i vogël',
 'recentchanges-label-bot' => 'Ky editim është kryer nga një bot',
 'recentchanges-label-unpatrolled' => 'Ky editim ende nuk është patrolluar',
+'recentchanges-legend-newpage' => '$1 - faqe të re',
 'rcnote' => "Më poshtë {{PLURAL:$1|është '''1''' ndryshim| janë '''$1''' ndryshime}} së fundmi gjatë <strong>$2</strong> ditëve sipas të dhënave nga $4, $5.",
 'rcnotefrom' => 'Më poshtë janë ndryshime së fundmi nga <b>$2</b> (treguar deri në <b>$1</b>).',
 'rclistfrom' => 'Tregon ndryshime së fundmi duke filluar nga $1',
@@ -2748,7 +2744,7 @@ Për të eksportuar faqe, thjesht shtypni një emër për çdo rresht, ose krijo
 'allmessagesdefault' => 'Teksti i parazgjedhur',
 'allmessagescurrent' => 'Teksti i tanishëshm',
 'allmessagestext' => 'Kjo është një listë e të gjitha faqeve në hapësirën MediaWiki:
-Ju lutemi vizitoni [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dhe [//translatewiki.net translatewiki.net] nëse dëshironi të kontribuoni në lokalizimin e përgjithshëm MediaWiki',
+Ju lutemi vizitoni [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] dhe [//translatewiki.net translatewiki.net] nëse dëshironi të kontribuoni në lokalizimin e përgjithshëm MediaWiki',
 'allmessagesnotsupportedDB' => "Kjo faqe nuk mund të përdoret sepse '''\$wgUseDatabaseMessages''' është çaktivizuar.",
 'allmessages-filter-legend' => 'Filtër',
 'allmessages-filter' => 'Filtroni nga shteti',
@@ -2933,6 +2929,8 @@ Ju lutemi provoni përsëri.',
 'spam_reverting' => "U kthye tek versioni i fundit që s'ka lidhje tek $1",
 'spam_blanking' => 'U boshatis sepse të gjitha versionet kanë lidhje tek $1',
 'spam_deleting' => 'Të gjitha inspektimet përmbanin lidhje në $1, duke fshirë',
+'simpleantispam-label' => "Kontroll anti-spam.
+'''MOS''' e plotësoni këtë!",
 
 # Info page
 'pageinfo-title' => 'Informacion për " $1 "',
@@ -3435,7 +3433,7 @@ Në qoftë se skeda është ndryshuar nga gjendja origjinale, disa hollësira mu
 
 # External editor support
 'edit-externally' => 'Ndryshoni këtë skedë me një mjet të jashtëm',
-'edit-externally-help' => '(Shikoni [//www.mediawiki.org/wiki/Manual:External_editors udhëzimet e instalimit] për më shumë informacion)',
+'edit-externally-help' => '(Shikoni [https://www.mediawiki.org/wiki/Manual:External_editors udhëzimet e instalimit] për më shumë informacion)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'të gjitha',
@@ -3615,7 +3613,7 @@ Ju gjithashtu mund [[Special:EditWatchlist|të përdorni redaktuesin standart]].
 'version-hook-subscribedby' => 'Abonuar nga',
 'version-version' => '(Versioni $1)',
 'version-license' => 'Licensa',
-'version-poweredby-credits' => "Ky wiki është mundësuar nga '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ky wiki është mundësuar nga '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'të tjerë',
 'version-license-info' => 'MediaWiki është një softuer i lirë; ju mund ta shpërndani dhe redakatoni atë nën kushtet GNU General Public License si e publikuar nga fondacioni Free Software; ose versioni 2 i licensës, ose çdo version më i vonshëm.
 
@@ -3824,4 +3822,13 @@ Përndryshe, ju mund të formularin e thjeshtë më poshtë. Komenti juaj do të
 'duration-centuries' => '$1 {{PLURAL:$1|shekull|shekuj}}',
 'duration-millennia' => '$1 {{PLURAL:$1|milennium|mileniume}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Parapamje stampash',
+'expand_templates_intro' => 'Kjo faqe speciale merr tekstin me stampa dhe të tregon se si do të duket teksti pasi të jenë stamposur të tëra. Kjo faqe gjithashtu tregon parapamjen e funksioneve dhe fjalëve magjike si p.sh. <nowiki>{{</nowiki>#language:...}} dhe <nowiki>{{</nowiki>CURRENTDAY}}.',
+'expand_templates_title' => 'Titulli i faqes për rrethanën, si {{FULLPAGENAME}} etj.:',
+'expand_templates_input' => 'Teksti me stampa:',
+'expand_templates_output' => 'Parapamja',
+'expand_templates_ok' => 'Shko',
+'expand_templates_remove_comments' => 'Hiq komentet',
+
 );
index 6b190a5..3ef54e9 100644 (file)
@@ -100,14 +100,12 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'НајстаријиЧланци' ),
        'Badtitle'                  => array( 'Лош_наслов' ),
        'Block'                     => array( 'Блокирај', 'БлокирајИП', 'БлокирајКорисника' ),
-       'Blockme'                   => array( 'БлокирајМе', 'Блокирај_ме' ),
        'BrokenRedirects'           => array( 'Покварена_преусмерења', 'Неисправна_преусмерења' ),
        'Categories'                => array( 'Категорије' ),
        'ComparePages'              => array( 'Упореди_странице' ),
        'Confirmemail'              => array( 'ПотврдиЕ-пошту', 'Потврда_е-поште' ),
        'Contributions'             => array( 'Доприноси', 'Прилози' ),
        'CreateAccount'             => array( 'ОтвориНалог', 'Отвори_налог' ),
-       'Disambiguations'           => array( 'Вишезначне_одреднице' ),
        'DoubleRedirects'           => array( 'Двострука_преусмерења' ),
        'Export'                    => array( 'Извези' ),
        'Fewestrevisions'           => array( 'ЧланциСаНајмањеРевизија' ),
@@ -136,7 +134,7 @@ $specialPageAliases = array(
        'Mypage'                    => array( 'МојаСтраница', 'Моја_страница' ),
        'Mytalk'                    => array( 'МојРазговор', 'Мој_разговор' ),
        'Myuploads'                 => array( 'Моја_слања' ),
-       'Newimages'                 => array( 'Ð\9dовиФаÑ\98лови', 'Ð\9dове_даÑ\82оÑ\82еке', 'НовеСлике' ),
+       'Newimages'                 => array( 'Ð\9dовеÐ\94аÑ\82оÑ\82еке', 'Ð\9dовиФаÑ\98лови', 'НовеСлике' ),
        'Newpages'                  => array( 'НовеСтране' ),
        'PermanentLink'             => array( 'Привремена_веза' ),
        'Popularpages'              => array( 'Популарне_странице' ),
@@ -151,13 +149,13 @@ $specialPageAliases = array(
        'Statistics'                => array( 'Статистике' ),
        'Tags'                      => array( 'Ознаке' ),
        'Uncategorizedcategories'   => array( 'КатегоријеБезКатегорија', 'Несврстане_категорије' ),
-       'Uncategorizedimages'       => array( 'СликеÐ\91езÐ\9aаÑ\82егоÑ\80иÑ\98а', 'ФаÑ\98ловиБезКатегорија' ),
+       'Uncategorizedimages'       => array( 'СликеÐ\91езÐ\9aаÑ\82егоÑ\80иÑ\98а', 'Ð\94аÑ\82оÑ\82екеБезКатегорија' ),
        'Uncategorizedpages'        => array( 'ЧланциБезКатегорија', 'Чланци_без_категорија' ),
        'Uncategorizedtemplates'    => array( 'ШаблониБезКатегорија' ),
        'Undelete'                  => array( 'Врати' ),
        'Unlockdb'                  => array( 'ОткључајБазу', 'Откључај_базу' ),
        'Unusedcategories'          => array( 'НеискоришћенеКатегорије' ),
-       'Unusedimages'              => array( 'Ð\9dеиÑ\81коÑ\80иÑ\88Ñ\9bенеСлике', 'Ð\9dеиÑ\81коÑ\80иÑ\88Ñ\9bениФаÑ\98лови' ),
+       'Unusedimages'              => array( 'Ð\9dеиÑ\81коÑ\80иÑ\88Ñ\9bенеСлике', 'Ð\9dеиÑ\81коÑ\80иÑ\88Ñ\9bенеÐ\94аÑ\82оÑ\82еке' ),
        'Upload'                    => array( 'Пошаљи' ),
        'UploadStash'               => array( 'Складиште' ),
        'Userlogin'                 => array( 'Корисничка_пријава' ),
@@ -536,8 +534,6 @@ $messages = array(
 'noindex-category' => 'Непописане странице',
 'broken-file-category' => 'Странице с неисправним везама до датотека',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'О нама',
 'article' => 'Страница са садржајем',
 'newwindow' => '(отвара се у новом прозору)',
@@ -646,10 +642,10 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'О пројекту {{SITENAME}}',
 'aboutpage' => 'Project:О нама',
-'copyright' => 'Садржај је доступан под лиценцом $1.',
+'copyright' => 'Садржај је доступан под лиценцом $1 осим ако је другачије наведено.',
 'copyrightpage' => '{{ns:project}}:Ауторска права',
 'currentevents' => 'Актуелности',
-'currentevents-url' => 'Project:Ð\9dовости',
+'currentevents-url' => 'Project:Ð\90кÑ\82Ñ\83елности',
 'disclaimers' => 'Одрицање одговорности',
 'disclaimerpage' => 'Project:Одрицање одговорности',
 'edithelp' => 'Помоћ при уређивању',
@@ -676,8 +672,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Преузето из „$1“',
 'youhavenewmessages' => 'Имате $1 ($2).',
-'newmessageslink' => 'нових порука',
-'newmessagesdifflink' => 'последња измена',
 'youhavenewmessagesfromusers' => 'Имате $1 од {{PLURAL:$3|другог корисника|$3 корисника|$3 корисника}} ($2).',
 'youhavenewmessagesmanyusers' => 'Имате $1 од много корисника ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|нову поруку|нове поруке}}',
@@ -802,8 +796,7 @@ $2',
 'myprivateinfoprotected' => 'Немате дозволу за мењање ваших личних информација.',
 'mypreferencesprotected' => 'Немате дозволу за мењање ваших подешавања.',
 'ns-specialprotected' => 'Посебне странице се не могу уређивати.',
-'titleprotected' => "Овај наслов је {{GENDER:$1|заштитио корисник|заштитила корисница|заштитио корисник}} [[User:$1|$1]].
-Наведени разлог: ''$2''.",
+'titleprotected' => "Овај назив је [[User:$1|$1]] заштитио од прављења. Разлог: ''$2''.",
 'filereadonlyerror' => 'Не могу да изменим датотеку „$1“ јер је ризница „$2“ у режиму за читање.
 
 Администратор који ју је закључао понудио је следеће објашњење: „$3“.',
@@ -857,9 +850,11 @@ $2',
 'gotaccount' => 'Већ имате налог? Идите на страницу „$1“.',
 'gotaccountlink' => 'Пријава',
 'userlogin-resetlink' => 'Заборавили сте податке за пријаву?',
-'userlogin-resetpassword-link' => 'РеÑ\81еÑ\82Ñ\83Ñ\98Ñ\82е Ð»Ð¾Ð·Ð¸Ð½ÐºÑ\83',
+'userlogin-resetpassword-link' => 'Ð\97абоÑ\80авили Ñ\81Ñ\82е Ð»Ð¾Ð·Ð¸Ð½ÐºÑ\83?',
 'helplogin-url' => 'Help:Logging in',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Помоћ при пријављивању]]',
+'userlogin-loggedin' => 'Већ сте пријављени као {{GENDER:$1|$1}}.
+Користите доњи образац да бисте се пријавили као други корисник.',
 'userlogin-createanother' => 'Отвори још један налог',
 'createacct-join' => 'Унесите своје податке испод',
 'createacct-another-join' => 'Унесите податке за нови налог испод.',
@@ -1174,8 +1169,9 @@ $2
 'storedversion' => 'Ускладиштена измена',
 'nonunicodebrowser' => "'''Упозорење: ваш прегледач не подржава уникод.'''
 Промените га пре него што почнете с уређивањем.",
-'editingold' => "'''Упозорење: уређујете застарелу измену ове странице.
-Ако је сачувате, све новије измене ће бити изгубљене.'''",
+'editingold' => '<div style="background: #FFBDBD; border: 1px solid #BB7979; color: #000000; font-weight: bold; margin: 2em 0 1em; padding: .5em 1em; vertical-align: middle; clear: both;">Упозорење: Ви уређујете старију ревизију ове странице.<br />
+Ако је сачувате, све промене учињене од ове ревизије биће изгубљене.
+</div>',
 'yourdiff' => 'Разлике',
 'copyrightwarning' => "Имајте на уму да се сви доприноси на овом викију сматрају као објављени под лиценцом $2 (више на $1).
 Ако не желите да се ваши текстови мењају и размењују без ограничења, онда их не шаљите овде.<br />
@@ -1269,7 +1265,7 @@ $2
 Проверите разлике испод, па сачувајте измене.',
 'undo-failure' => 'Не могу да вратим измену због постојања сукобљених међуизмена.',
 'undo-norev' => 'Не могу да вратим измену јер не постоји или је обрисана.',
-'undo-summary' => 'Поништена измена $1  {{GENDER:$2|корисника|кориснице}} [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]])',
+'undo-summary' => 'Поништена измена $1 {{GENDER:$2|корисника|кориснице}} [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]])',
 'undo-summary-username-hidden' => 'Поништи измену $1 скривеног корисника',
 
 # Account creation failure
@@ -1363,15 +1359,15 @@ $2
 * Неприкладни лични подаци
 *: ''кућна адреса и број телефона, број банковне картице итд.''",
 'revdelete-legend' => 'Ограничења видљивости',
-'revdelete-hide-text' => 'сакриј текст измене',
+'revdelete-hide-text' => 'Текст ревизије',
 'revdelete-hide-image' => 'Сакриј садржај датотеке',
 'revdelete-hide-name' => 'Сакриј радњу и одредиште',
 'revdelete-hide-comment' => 'сакриј опис измене',
-'revdelete-hide-user' => 'сакриј име уређивача',
+'revdelete-hide-user' => 'Кориснчко име уредника/ИП адреса',
 'revdelete-hide-restricted' => 'Сакриј податке од администратора и других корисника',
 'revdelete-radio-same' => '(не мењај)',
-'revdelete-radio-set' => 'да',
-'revdelete-radio-unset' => 'не',
+'revdelete-radio-set' => 'СакÑ\80ивено',
+'revdelete-radio-unset' => 'Ð\92идÑ\99иво',
 'revdelete-suppress' => 'Сакриј податке од администратора и других корисника',
 'revdelete-unsuppress' => 'Уклони ограничења на враћеним изменама',
 'revdelete-log' => 'Разлог:',
@@ -1441,7 +1437,7 @@ $1",
 'mergelog' => 'Дневник спајања',
 'pagemerge-logentry' => 'страница [[$1]] је спојена у [[$2]] (све до измене $3)',
 'revertmerge' => 'растави',
-'mergelogpagetext' => 'Ð\98Ñ\81под Ñ\81е Ð½Ð°Ð»Ð°Ð·Ð¸ Ñ\81пиÑ\81ак Ñ\81коÑ\80аÑ\88Ñ\9aиÑ\85 Ñ\81паÑ\98аÑ\9aа Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а страница.',
+'mergelogpagetext' => 'Ð\98Ñ\81под Ñ\98е Ñ\81пиÑ\81ак Ð½Ð°Ñ\98Ñ\81коÑ\80иÑ\98иÑ\85 Ñ\81паÑ\98аÑ\9aа Ð¸Ñ\81Ñ\82оÑ\80иÑ\98а Ð´Ð²ÐµÑ\98Ñ\83 страница.',
 
 # Diffs
 'history-title' => 'Историја измена странице „$1“',
@@ -1528,8 +1524,6 @@ $1",
 'preferences' => 'Подешавања',
 'mypreferences' => 'Подешавања',
 'prefs-edits' => 'Број измена:',
-'prefsnologin' => 'Нисте пријављени',
-'prefsnologintext' => 'Морате бити <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} пријављени]</span> да бисте подешавали корисничке поставке.',
 'changepassword' => 'Промени лозинку',
 'prefs-skin' => 'Тема',
 'skin-preview' => 'Прегледај',
@@ -1775,10 +1769,10 @@ $1",
 'action-createtalk' => 'прављење страница за разговор',
 'action-createaccount' => 'отварање овог корисничког налога',
 'action-minoredit' => 'означавање ове измене као мање',
-'action-move' => 'пÑ\80емеÑ\88Ñ\82аÑ\9aе Ð¾Ð²Ðµ Ñ\81Ñ\82Ñ\80аниÑ\86е',
-'action-move-subpages' => 'пÑ\80емеÑ\88Ñ\82аÑ\9aе Ð¾Ð²Ðµ Ñ\81Ñ\82Ñ\80аниÑ\86е Ð¸ Ñ\9aениÑ\85 Ð¿Ð¾Ð´Ñ\81Ñ\82Ñ\80аниÑ\86а',
+'action-move' => 'пÑ\80емеÑ\81Ñ\82и Ð¾Ð²Ñ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83',
+'action-move-subpages' => 'пÑ\80емеÑ\81Ñ\82и Ð¾Ð²Ñ\83 Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83, ÐºÐ°Ð¾ Ð¸ Ñ\9aене Ð¿Ð¾Ð´Ñ\81Ñ\82Ñ\80аниÑ\86е',
 'action-move-rootuserpages' => 'премештање основних корисничких страница',
-'action-movefile' => 'пÑ\80емеÑ\88Ñ\82аÑ\9aе Ð¾Ð²Ðµ Ð´Ð°Ñ\82оÑ\82еке',
+'action-movefile' => 'пÑ\80емеÑ\81Ñ\82и Ð¾Ð²Ñ\83 Ð´Ð°Ñ\82оÑ\82екÑ\83',
 'action-upload' => 'слање ове датотеке',
 'action-reupload' => 'замењивање постојеће датотеке',
 'action-reupload-shared' => 'постављање ове датотеке на заједничко складиште',
@@ -1818,6 +1812,7 @@ $1",
 'recentchanges-label-minor' => 'Мања измена',
 'recentchanges-label-bot' => 'Ову измену је направио бот',
 'recentchanges-label-unpatrolled' => 'Ова измена још није прегледана',
+'recentchanges-legend-newpage' => '(такође погледајте [[Special:NewPages|списак нових страница]])',
 'rcnote' => "Испод {{PLURAL:$1|је '''1''' измена|су последње '''$1''' измене|су последњих '''$1''' измена}} {{PLURAL:$2|претходни дан|у последњa '''$2''' дана|у последњих '''$2''' дана}}, од $4; $5.",
 'rcnotefrom' => 'Испод су измене од <b>$3; $4</b> (до <b>$1</b> измена).',
 'rclistfrom' => 'Прикажи нове измене почев од $1',
@@ -1831,7 +1826,7 @@ $1",
 'diff' => 'разл',
 'hist' => 'ист',
 'hide' => 'сакриј',
-'show' => 'прикажи',
+'show' => 'Ð\9fрикажи',
 'minoreditletter' => ' м',
 'newpageletter' => 'Н',
 'boteditletter' => 'б',
@@ -2130,6 +2125,7 @@ $1',
 'listfiles_size' => 'Величина',
 'listfiles_description' => 'Опис',
 'listfiles_count' => 'Верзије',
+'listfiles-show-all' => 'Обухвати старе верзије слика',
 'listfiles-latestversion' => 'Тренутна верзија',
 'listfiles-latestversion-yes' => 'Да',
 'listfiles-latestversion-no' => 'Не',
@@ -2183,7 +2179,7 @@ $1',
 'filerevert-legend' => 'Врати датотеку',
 'filerevert-intro' => "Враћате датотеку '''[[Media:$1|$1]]''' на [$4 издање од $2; $3].",
 'filerevert-comment' => 'Разлог:',
-'filerevert-defaultcomment' => 'Ð\92Ñ\80аÑ\9bено Ð½Ð° Ð¸Ð·Ð´Ð°Ñ\9aе Ð¾Ð´ $1; $2',
+'filerevert-defaultcomment' => 'Ð\92Ñ\80аÑ\9bено Ð½Ð° Ð²ÐµÑ\80зиÑ\98Ñ\83 Ð¾Ð´ $2, $1',
 'filerevert-submit' => 'Врати',
 'filerevert-success' => "Датотека '''[[Media:$1|$1]]''' је враћена на [$4 издање од $2; $3].",
 'filerevert-badversion' => 'Не постоји раније локално издање датотеке с наведеним временским подацима.',
@@ -2588,7 +2584,7 @@ $UNWATCHURL
 'deletepage' => 'Обриши страницу',
 'confirm' => 'Потврди',
 'excontent' => 'садржај је био: „$1“',
-'excontentauthor' => 'садржај је био: „$1“ (једину измену {{GENDER:|направио је|направила је|направио је}} [[Special:Contributions/$2|$2]])',
+'excontentauthor' => 'садржај је био: „$1“ (а једини уредник је био „[[Special:Contributions/$2|$2]]“)',
 'exbeforeblank' => 'садржај пре брисања је био: „$1“',
 'exblank' => 'страница је била празна',
 'delete-confirm' => 'Брисање странице „$1“',
@@ -2608,6 +2604,7 @@ $UNWATCHURL
 'deleteotherreason' => 'Други/додатни разлог:',
 'deletereasonotherlist' => 'Други разлог',
 'deletereason-dropdown' => '*Најчешћи разлози за брисање
+** Спам
 ** Захтев аутора
 ** Кршење ауторских права
 ** Вандализам',
@@ -2631,7 +2628,7 @@ $UNWATCHURL
 Последњу измену је {{GENDER:$3|направио|направила|направио}} [[User:$3|$3]] ([[User talk:$3|разговор]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Опис измене: \"''\$1''\".",
 'revertpage' => 'Враћене измене [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]]) на последњу измену корисника [[User:$1|$1]]',
-'revertpage-nouser' => 'Враћене су измене скривеног корисника на последњу измену члана [[User:$1|$1]]',
+'revertpage-nouser' => 'Враћене су измене скривеног корисника на последњу измену {{GENDER:$1|корисника|кориснице}} [[User:$1|$1]]',
 'rollback-success' => 'Враћене су измене {{GENDER:$1|корисника|кориснице|корисника}} $1
 на последњу измену {{GENDER:$2|корисника|кориснице|корисника}} $2.',
 
@@ -2720,8 +2717,8 @@ $UNWATCHURL
 'undeleteextrahelp' => "Да бисте вратили целу историју странице, оставите све кућице неозначене и кликните на дугме '''''{{int:undeletebtn}}'''''.
 Ако желите да вратите одређене измене, означите их и кликните на '''''{{int:undeletebtn}}'''''.",
 'undeleterevisions' => '$1 {{PLURAL:$1|измена је архивирана|измене су архивиране|измена је архивирано}}',
-'undeletehistory' => 'Ако вратите страницу, све измене ће бити враћене њеној историји.
\90ко Ñ\98е Ñ\83 Ð¼ÐµÑ\92Ñ\83вÑ\80еменÑ\83 Ð½Ð°Ð¿Ñ\80авÑ\99ена Ð½Ð¾Ð²Ð° Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81 Ð¸Ñ\81Ñ\82им Ð½Ð°Ð·Ð¸Ð²Ð¾Ð¼, Ð²Ñ\80аÑ\9bене Ð¸Ð·Ð¼ÐµÐ½Ðµ Ñ\9bе Ñ\81е Ð¿Ð¾Ñ\98авиÑ\82и Ñ\83 Ñ\80аниÑ\98ом историји.',
+'undeletehistory' => 'Ако вратите страницу, све ревизије ће бити враћене њеној историји.
\90ко Ñ\98е Ñ\83 Ð¼ÐµÑ\92Ñ\83вÑ\80еменÑ\83 Ð½Ð°Ð¿Ñ\80авÑ\99ена Ð½Ð¾Ð²Ð° Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81 Ð¸Ñ\81Ñ\82им Ð½Ð°Ð·Ð¸Ð²Ð¾Ð¼, Ð²Ñ\80аÑ\9bене Ð¸Ð·Ð¼ÐµÐ½Ðµ Ñ\9bе Ñ\81е Ð¿Ð¾Ñ\98авиÑ\82и Ñ\83 Ñ\9aеноÑ\98 Ñ\80аниÑ\98оÑ\98 историји.',
 'undeleterevdel' => 'Враћање неће бити извршено ако је резултат тога делимично брисање последње измене.
 У таквим случајевима морате искључити или открити најновије обрисане измене.',
 'undeletehistorynoadmin' => 'Ова страница је обрисана.
@@ -3093,7 +3090,7 @@ $1',
 'allmessagesdefault' => 'Подразумевани текст',
 'allmessagescurrent' => 'Текст поруке',
 'allmessagestext' => 'Ово је списак свих системских порука које су доступне у именском простору „Медијавики“.
-Посетите [//www.mediawiki.org/wiki/Localisation Медијавики локализацију] и [//translatewiki.net Транслејтвики] ако желите да помогнете у превођењу.',
+Посетите [https://www.mediawiki.org/wiki/Localisation Медијавики локализацију] и [//translatewiki.net Транслејтвики] ако желите да помогнете у превођењу.',
 'allmessagesnotsupportedDB' => "Ова страница не може да се користи јер је '''\$wgUseDatabaseMessages''' онемогућен.",
 'allmessages-filter-legend' => 'Филтер',
 'allmessages-filter' => 'Филтрирај по стању:',
@@ -3306,6 +3303,7 @@ $1',
 'spam_reverting' => 'Враћам на последњу измену која не садржи везе до $1',
 'spam_blanking' => 'Све измене садрже везе до $1. Чистим',
 'spam_deleting' => 'Све измене садрже везе до $1. Бришем',
+'simpleantispam-label' => "Провера спама. '''НЕ''' попуњавај ово унутра!",
 
 # Info page
 'pageinfo-title' => 'Подаци о „$1“',
@@ -3974,7 +3972,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'Измени ову датотеку користећи спољашњи програм',
-'edit-externally-help' => '(Погледајте [//www.mediawiki.org/wiki/Manual:External_editors упутство за подешавање] за више информација)',
+'edit-externally-help' => '(Погледајте [https://www.mediawiki.org/wiki/Manual:External_editors упутство за подешавање] за више информација)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'све',
@@ -4080,6 +4078,7 @@ $5
 'ellipsis' => '…',
 'percent' => '$1%',
 'parentheses' => '($1)',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← претходна страница',
@@ -4100,10 +4099,10 @@ $5
 'table_pager_empty' => 'Нема резултата',
 
 # Auto-summaries
-'autosumm-blank' => 'Ð\9fоÑ\82пÑ\83но Ð¾Ð±Ñ\80иÑ\81ана Ñ\81Ñ\82Ñ\80аниÑ\86а',
+'autosumm-blank' => 'УклоÑ\9aен Ñ\86елокÑ\83пан Ñ\81адÑ\80жаÑ\98 Ñ\81Ñ\82Ñ\80аниÑ\86е',
 'autosumm-replace' => 'Замена садржаја странице са „$1“',
 'autoredircomment' => 'Преусмерење на [[$1]]',
-'autosumm-new' => 'Ð\9dапÑ\80авÑ\99ена Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81а: â\80\9e$1â\80\9c',
+'autosumm-new' => 'Ð\9dова Ñ\81Ñ\82Ñ\80аниÑ\86а: $1',
 
 # Size units
 'size-bytes' => '$1 B',
@@ -4133,7 +4132,7 @@ $5
 Можете и да [[Special:EditWatchlist/raw|уредите сиров списак]].',
 'watchlistedit-normal-submit' => 'Уклони',
 'watchlistedit-normal-done' => '{{PLURAL:$1|Једна страница је уклоњена|$1 странице су уклоњене|$1 страница је уклоњено}} с вашег списка надгледања:',
-'watchlistedit-raw-title' => 'Ð\9dапÑ\80едно Ñ\83Ñ\80еÑ\92иваÑ\9aе Ñ\81пиÑ\81ка надгледања',
+'watchlistedit-raw-title' => 'Ð\98змени Ñ\81иÑ\80ов Ñ\81пиÑ\81ак надгледања',
 'watchlistedit-raw-legend' => 'Напредно уређивање списка надгледања',
 'watchlistedit-raw-explain' => 'Наслови са списка надгледања су приказани испод и могу се уређивати додавањем или уклањањем ставки са списка;
 један наслов по реду.
@@ -4235,7 +4234,7 @@ $5
 'version-version' => '(издање $1)',
 'version-svn-revision' => '(изм. $2)',
 'version-license' => 'Лиценца',
-'version-poweredby-credits' => "Овај вики покреће '''[//www.mediawiki.org/ Медијавики]''', ауторска права © 2001-$1 $2.",
+'version-poweredby-credits' => "Овај вики покреће '''[https://www.mediawiki.org/ Медијавики]''', ауторска права © 2001-$1 $2.",
 'version-poweredby-others' => 'остали',
 'version-poweredby-translators' => 'translatewiki.net преводиоци',
 'version-credits-summary' => 'Желели бисмо да захвалимо следећим људима на њиховом доприносу [[Special:Version|Медијавикији]].',
@@ -4271,10 +4270,9 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Посебне странице',
-'specialpages-note' => '----
-* обичне посебне странице
-* <span class="mw-specialpagerestricted">ограничене посебне странице</span>
-* <span class="mw-specialpagecached">привремено меморисане посебне странице</span>',
+'specialpages-note-top' => 'Легенда',
+'specialpages-note' => '* Нормалне посебне странице
+* <span class="mw-specialpagerestricted">Ограничене посебне странице</span>',
 'specialpages-group-maintenance' => 'Извештаји одржавања',
 'specialpages-group-other' => 'Остале посебне странице',
 'specialpages-group-login' => 'Пријава/регистрација',
@@ -4312,7 +4310,10 @@ $5
 'tags-tag' => 'Назив ознаке',
 'tags-display-header' => 'Изглед на списковима измена',
 'tags-description-header' => 'Опис значења',
+'tags-active-header' => 'Активна?',
 'tags-hitcount-header' => 'Означене измене',
+'tags-active-yes' => 'Да',
+'tags-active-no' => 'Не',
 'tags-edit' => 'уреди',
 'tags-hitcount' => '$1 {{PLURAL:$1|измена|измене|измена}}',
 
@@ -4357,17 +4358,17 @@ $5
 'sqlite-no-fts' => '$1 без подршке претраге целог текста',
 
 # New logging system
-'logentry-delete-delete' => '$1 је {{GENDER:|обрисао|обрисала}} $3',
+'logentry-delete-delete' => '$1 је {{GENDER:|обрисао|обрисала}} страницу $3',
 'logentry-delete-restore' => '$1 је {{GENDER:$2|вратио|вратила}} страницу $3',
 'logentry-delete-event' => '$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|догађаја|$5 догађаја}} у дневнику на $3: $4',
 'logentry-delete-revision' => '$1 је {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|измене|$5 измена}} на страници $3: $4',
 'logentry-delete-event-legacy' => '$1 је {{GENDER:$2|променио|променила}} видљивост догађаја у дневнику на $3',
-'logentry-delete-revision-legacy' => '$1 је {{GENDER:$2|променио|променила}} видљивост изменâ на страници $3',
+'logentry-delete-revision-legacy' => '$1 је {{GENDER:$2|променио|променила}} видљивост измена на страници $3',
 'logentry-suppress-delete' => '$1 је {{GENDER:$2|потиснуо|потиснула}} страницу $3',
-'logentry-suppress-event' => '$1 је потајно {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|догађаја|$5 догађаја}} у дневнику на $3: $4',
-'logentry-suppress-revision' => '$1 је потајно {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|измене|$5 измена}} на страници $3: $4',
+'logentry-suppress-event' => '$1 је тајно {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|догађаја|$5 догађаја}} у дневнику на $3: $4',
+'logentry-suppress-revision' => '$1 је тајно {{GENDER:$2|променио|променила}} видљивост {{PLURAL:$5|измене|$5 измена}} на страници $3: $4',
 'logentry-suppress-event-legacy' => '$1 је потајно {{GENDER:$2|променио|променила}} видљивост догађаја у дневнику на $3',
-'logentry-suppress-revision-legacy' => '$1 је потајно {{GENDER:$2|променио|променила}} видљивост измена на страници $3',
+'logentry-suppress-revision-legacy' => '$1 је тајно {{GENDER:$2|променио|променила}} видљивост измена на страници $3',
 'revdelete-content-hid' => 'садржај је сакривен',
 'revdelete-summary-hid' => 'опис измене је сакривен',
 'revdelete-uname-hid' => 'корисничко име је сакривено',
@@ -4473,4 +4474,19 @@ $5
 'limitreport-postexpandincludesize-value' => '$1/$2 бајтова',
 'limitreport-templateargumentsize-value' => '$1/$2 бајтова',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Замена шаблона',
+'expand_templates_intro' => 'Ова посебна страница узима текст и мења све шаблоне у њему рекурзивно.
+Такође мења функције парсера као што је <code><nowiki>{{</nowiki>#language:…}}</code> и променљиве као што је <code><nowiki>{{</nowiki>CURRENTDAY}}</code>. 
+Заправо практично све што се налази између витичастих заграда.',
+'expand_templates_title' => 'Назив контекста; за {{СТРАНИЦА}} итд.:',
+'expand_templates_input' => 'Унос:',
+'expand_templates_output' => 'Резултат',
+'expand_templates_xml_output' => 'XML излаз',
+'expand_templates_ok' => 'У реду',
+'expand_templates_remove_comments' => 'Уклони коментаре',
+'expand_templates_remove_nowiki' => 'Поништава ефекат <nowiki> тагова у приказу чланака',
+'expand_templates_generate_xml' => 'прикажи XML стабло',
+'expand_templates_preview' => 'Приказ',
+
 );
index ddb5668..4464361 100644 (file)
@@ -349,6 +349,7 @@ $messages = array(
 'tog-noconvertlink' => 'Onemogući pretvaranje naslova veza',
 'tog-norollbackdiff' => 'Izostavi razliku nakon izvršenog vraćanja',
 'tog-useeditwarning' => 'Upozori me kada napuštam stranicu sa nesačuvanim promenama',
+'tog-prefershttps' => 'Uvek koristi sigurnu konekciju kada sam prijavljen.',
 
 'underline-always' => 'uvek podvlači',
 'underline-never' => 'nikad ne podvlači',
@@ -444,8 +445,6 @@ $messages = array(
 'noindex-category' => 'Nepopisane stranice',
 'broken-file-category' => 'Stranice s neispravnim vezama do datoteka',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'O nama',
 'article' => 'Stranica sa sadržajem',
 'newwindow' => '(otvara u novom prozoru)',
@@ -480,7 +479,7 @@ $messages = array(
 'vector-view-edit' => 'Uredi',
 'vector-view-history' => 'Istorija',
 'vector-view-view' => 'Čitaj',
-'vector-view-viewsource' => 'Izvornik',
+'vector-view-viewsource' => 'Izvorni kod',
 'actions' => 'Radnje',
 'namespaces' => 'Imenski prostori',
 'variants' => 'Varijante',
@@ -552,10 +551,10 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'O projektu {{SITENAME}}',
 'aboutpage' => 'Project:O nama',
-'copyright' => 'Sadržaj je dostupan pod licencom $1.',
+'copyright' => 'Sadržaj je dostupan pod licencom $1 osim ako je drugačije navedeno.',
 'copyrightpage' => '{{ns:project}}:Autorska prava',
 'currentevents' => 'Aktuelnosti',
-'currentevents-url' => 'Project:Novosti',
+'currentevents-url' => 'Project:Aktuelnosti',
 'disclaimers' => 'Odricanje odgovornosti',
 'disclaimerpage' => 'Project:Odricanje odgovornosti',
 'edithelp' => 'Pomoć pri uređivanju',
@@ -582,8 +581,6 @@ Pogledajte stranicu za [[Special:Version|izdanje]].',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Preuzeto iz „$1“',
 'youhavenewmessages' => 'Imate $1 ($2).',
-'newmessageslink' => 'novih poruka',
-'newmessagesdifflink' => 'poslednju izmenu',
 'youhavenewmessagesfromusers' => 'Imate $1 od {{PLURAL:$3|drugog korisnika|$3 korisnika|$3 korisnika}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od mnogo korisnika ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|nove poruke}}',
@@ -591,7 +588,7 @@ Pogledajte stranicu za [[Special:Version|izdanje]].',
 'youhavenewmessagesmulti' => 'Imate novih poruka na $1',
 'editsection' => 'uredi',
 'editold' => 'uredi',
-'viewsourceold' => 'izvornik',
+'viewsourceold' => 'izvorni kod',
 'editlink' => 'uredi',
 'viewsourcelink' => 'Izvor',
 'editsectionhint' => 'Uredite odeljak „$1“',
@@ -684,11 +681,11 @@ Podaci koji se ovde nalaze mogu biti zastareli.',
 'wrong_wfQuery_params' => 'Neispravni parametri za wfQuery()<br />
 Funkcija: $1<br />
 Upit: $2',
-'viewsource' => 'Izvornik',
+'viewsource' => 'Izvorni kod',
 'viewsource-title' => 'Prikaz izvora stranice $1',
 'actionthrottled' => 'Radnja je usporena',
 'actionthrottledtext' => 'U cilju borbe protiv nepoželjnih poruka, ograničene su vam izmene u određenom vremenu, a upravo ste prešli to ograničenje. Pokušajte ponovo za nekoliko minuta.',
-'protectedpagetext' => 'Ova stranica je zaključana za uređivanja.',
+'protectedpagetext' => 'Ova stranica je zaključana za izmene i druge radnje.',
 'viewsourcetext' => 'Možete da pogledate i umnožite izvorni tekst ove stranice:',
 'viewyourtext' => "Možete da pogledate i umnožite izvor '''vaših izmena''' na ovoj stranici:",
 'protectedinterface' => 'Ova stranica sadrži tekst korisničkog okruženja za softver na ovom vikiju i zaštićena je radi sprečavanja zloupotrebe.
@@ -702,8 +699,7 @@ $2',
 'customcssprotected' => 'Nemate dozvolu da menjate ovu CSS stranicu jer sadrži lične postavke drugog korisnika.',
 'customjsprotected' => 'Nemate dozvolu da menjate ovu stranicu javaskripta jer sadrži lične postavke drugog korisnika.',
 'ns-specialprotected' => 'Posebne stranice se ne mogu uređivati.',
-'titleprotected' => "Ovaj naslov je {{GENDER:$1|zaštitio korisnik|zaštitila korisnica|zaštitio korisnik}} [[User:$1|$1]].
-Navedeni razlog: ''$2''.",
+'titleprotected' => "Ovaj naziv je [[User:$1|$1]] zaštitio od pravljenja. Razlog: ''$2''.",
 'filereadonlyerror' => 'Ne mogu da izmenim datoteku „$1“ jer je riznica „$2“ u režimu za čitanje.
 
 Administrator koji ju je zaključao ponudio je sledeće objašnjenje: „$3“.',
@@ -754,7 +750,7 @@ Imajte na umu da neke stranice mogu nastaviti da se prikazuju kao da ste još pr
 'gotaccount' => 'Već imate nalog? Idite na stranicu „$1“.',
 'gotaccountlink' => 'Prijava',
 'userlogin-resetlink' => 'Zaboravili ste podatke za prijavu?',
-'userlogin-resetpassword-link' => 'Resetuj lozinku',
+'userlogin-resetpassword-link' => 'Zaboravili ste lozinku?',
 'helplogin-url' => 'Help:Logging in',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Pomoć pri prijavljivanju]]',
 'createacct-join' => 'Unesite svoje podatke ispod.',
@@ -934,7 +930,7 @@ Privremena lozinka: $2',
 'watchthis' => 'nadgledaj ovu stranicu',
 'savearticle' => 'Sačuvaj stranicu',
 'preview' => 'Pregled',
-'showpreview' => 'Pregledaj',
+'showpreview' => 'Prikaži pretpregled',
 'showlivepreview' => 'Trenutni pregled',
 'showdiff' => 'Prikaži izmene',
 'anoneditwarning' => "'''Upozorenje:''' niste prijavljeni.
@@ -1059,8 +1055,9 @@ Moraćete da unesete svoje promene u postojeći tekst.
 'storedversion' => 'Uskladištena izmena',
 'nonunicodebrowser' => "'''Upozorenje: vaš pregledač ne podržava unikod.'''
 Promenite ga pre nego što počnete s uređivanjem.",
-'editingold' => "'''Upozorenje: uređujete zastarelu izmenu ove stranice.
-Ako je sačuvate, sve novije izmene će biti izgubljene.'''",
+'editingold' => '<div style="background: #FFBDBD; border: 1px solid #BB7979; color: #000000; font-weight: bold; margin: 2em 0 1em; padding: .5em 1em; vertical-align: middle; clear: both;">Upozorenje: Vi uređujete stariju reviziju ove stranice.<br />
+Ako je sačuvate, sve promene učinjene od ove revizije biće izgubljene.
+</div>',
 'yourdiff' => 'Razlike',
 'copyrightwarning' => "Imajte na umu da se svi doprinosi na ovom vikiju smatraju kao objavljeni pod licencom $2 (više na $1).
 Ako ne želite da se vaši tekstovi menjaju i razmenjuju bez ograničenja, onda ih ne šaljite ovde.<br />
@@ -1254,8 +1251,8 @@ Drugi administratori na ovom vikiju će i dalje imati pristup sakrivenom sadrža
 'revdelete-hide-user' => 'sakrij ime uređivača',
 'revdelete-hide-restricted' => 'Sakrij podatke od administratora i drugih korisnika',
 'revdelete-radio-same' => '(ne menjaj)',
-'revdelete-radio-set' => 'da',
-'revdelete-radio-unset' => 'ne',
+'revdelete-radio-set' => 'Sakriveno',
+'revdelete-radio-unset' => 'Vidljivo',
 'revdelete-suppress' => 'Sakrij podatke od administratora i drugih korisnika',
 'revdelete-unsuppress' => 'Ukloni ograničenja na vraćenim izmenama',
 'revdelete-log' => 'Razlog:',
@@ -1325,7 +1322,7 @@ Korišćenje navigacionih veza će poništiti ovu kolonu.',
 'mergelog' => 'Dnevnik spajanja',
 'pagemerge-logentry' => 'stranica [[$1]] je spojena u [[$2]] (sve do izmene $3)',
 'revertmerge' => 'rastavi',
-'mergelogpagetext' => 'Ispod se nalazi spisak skorašnjih spajanja istorija stranica.',
+'mergelogpagetext' => 'Ispod je spisak najskorijih spajanja istorija dveju stranica.',
 
 # Diffs
 'history-title' => 'Istorija izmena stranice „$1“',
@@ -1336,6 +1333,7 @@ Korišćenje navigacionih veza će poništiti ovu kolonu.',
 'compareselectedversions' => 'Uporedi izabrane izmene',
 'showhideselectedversions' => 'Prikaži/sakrij izabrane izmene',
 'editundo' => 'poništi',
+'diff-empty' => '(Nema razlike)',
 'diff-multi' => '({{PLURAL:$1|nije prikazana međuizmena|nisu prikazane $1 međuizmene|nije prikazano $1 međuizmena}} {{PLURAL:$2|jednog|$2|$2}} korisnika)',
 'diff-multi-manyusers' => '({{PLURAL:$1|Nije prikazana međuizmena|Nisu prikazane $1 međuizmene|Nije prikazano $1 međuizmena}} od više od $2 korisnika)',
 'difference-missing-revision' => 'Ne mogu da pronađem {{PLURAL:$2|jednu izmenu|$2 izmene|$2 izmena}} od ove razlike ($1).
@@ -1411,8 +1409,6 @@ Upamtite da njegovi popisi ovog vikija mogu biti zastareli.',
 'preferences' => 'Podešavanja',
 'mypreferences' => 'Podešavanja',
 'prefs-edits' => 'Broj izmena:',
-'prefsnologin' => 'Niste prijavljeni',
-'prefsnologintext' => 'Morate biti <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} prijavljeni]</span> da biste podešavali korisničke postavke.',
 'changepassword' => 'Promeni lozinku',
 'prefs-skin' => 'Tema',
 'skin-preview' => 'Pregledaj',
@@ -1522,6 +1518,7 @@ Ako izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rad
 'prefs-displaysearchoptions' => 'Postavke prikaza',
 'prefs-displaywatchlist' => 'Postavke prikaza',
 'prefs-diffs' => 'Razlike',
+'prefs-help-prefershttps' => 'Ova podešavanja će stupiti na snagu pri sledećoj prijavi.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'E-adresa je ispravna',
@@ -1651,10 +1648,10 @@ Ako izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rad
 'action-createtalk' => 'pravljenje stranica za razgovor',
 'action-createaccount' => 'otvaranje ovog korisničkog naloga',
 'action-minoredit' => 'označavanje ove izmene kao manje',
-'action-move' => 'premeštanje ove stranice',
-'action-move-subpages' => 'premeštanje ove stranice i njenih podstranica',
+'action-move' => 'premesti ovu stranicu',
+'action-move-subpages' => 'premesti ovu stranicu, kao i njene podstranice',
 'action-move-rootuserpages' => 'premeštanje osnovnih korisničkih stranica',
-'action-movefile' => 'premeštanje ove datoteke',
+'action-movefile' => 'premesti ovu datoteku',
 'action-upload' => 'slanje ove datoteke',
 'action-reupload' => 'zamenjivanje postojeće datoteke',
 'action-reupload-shared' => 'postavljanje ove datoteke na zajedničko skladište',
@@ -1691,6 +1688,7 @@ Ako izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rad
 'recentchanges-label-minor' => 'Manja izmena',
 'recentchanges-label-bot' => 'Ovu izmenu je napravio bot',
 'recentchanges-label-unpatrolled' => 'Ova izmena još nije pregledana',
+'recentchanges-legend-newpage' => '$1 - nova stranica',
 'rcnote' => "Ispod {{PLURAL:$1|je '''1''' izmena|su poslednje '''$1''' izmene|su poslednjih '''$1''' izmena}} {{PLURAL:$2|prethodni dan|u poslednja '''$2''' dana|u poslednjih '''$2''' dana}}, od $4; $5.",
 'rcnotefrom' => 'Ispod su izmene od <b>$3; $4</b> (do <b>$1</b> izmena).',
 'rclistfrom' => 'Prikaži nove izmene počev od $1',
@@ -1704,7 +1702,7 @@ Ako izaberete da ga unesete, ono će biti korišćeno za pripisivanje vašeg rad
 'diff' => 'razl',
 'hist' => 'ist',
 'hide' => 'sakrij',
-'show' => 'prikaži',
+'show' => 'Prikaži',
 'minoreditletter' => ' m',
 'newpageletter' => 'N',
 'boteditletter' => 'b',
@@ -2003,6 +2001,10 @@ Probajte kasnije kada bude manje opterećenje.',
 'listfiles_size' => 'Veličina',
 'listfiles_description' => 'Opis',
 'listfiles_count' => 'Verzije',
+'listfiles-show-all' => 'Obuhvati stare verzije slika',
+'listfiles-latestversion' => 'Trenutna verzija',
+'listfiles-latestversion-yes' => 'Da',
+'listfiles-latestversion-no' => 'Ne',
 
 # File description page
 'file-anchor-link' => 'Datoteka',
@@ -2053,7 +2055,7 @@ Njen opis možete da izmenite na [$2 odgovarajućoj stranici].',
 'filerevert-legend' => 'Vrati datoteku',
 'filerevert-intro' => "Vraćate datoteku '''[[Media:$1|$1]]''' na [$4 izdanje od $2; $3].",
 'filerevert-comment' => 'Razlog:',
-'filerevert-defaultcomment' => 'Vraćeno na izdanje od $1; $2',
+'filerevert-defaultcomment' => 'Vraćeno na verziju od $2, $1',
 'filerevert-submit' => 'Vrati',
 'filerevert-success' => "Datoteka '''[[Media:$1|$1]]''' je vraćena na [$4 izdanje od $2; $3].",
 'filerevert-badversion' => 'Ne postoji ranije lokalno izdanje datoteke s navedenim vremenskim podacima.',
@@ -2284,7 +2286,7 @@ Pogledajte i [[Special:WantedCategories|tražene kategorije]].',
 'linksearch-ok' => 'Pretraži',
 'linksearch-text' => 'Mogu se koristiti džokeri poput „*.wikipedia.org“.<br />
 Potreban je najviši domen, kao „*.org“.<br />
-Podržani protokoli: <code>$1</code> (zadaje http:// ako ne navedete protokol).',
+{{PLURAL:$2|Podržan protokol|Podržani protokoli}}: <code>$1</code> (zadaje http:// ako ne navedete protokol).',
 'linksearch-line' => '$1 veza u $2',
 'linksearch-error' => 'Džokeri se mogu pojaviti samo na početku adrese.',
 
@@ -2441,7 +2443,7 @@ Podrška i dalja pomoć:
 'deletepage' => 'Obriši stranicu',
 'confirm' => 'Potvrdi',
 'excontent' => 'sadržaj je bio: „$1“',
-'excontentauthor' => 'sadržaj je bio: „$1“ (jedinu izmenu {{GENDER:|napravio je|napravila je|napravio je}} [[Special:Contributions/$2|$2]])',
+'excontentauthor' => 'sadržaj je bio: „$1“ (a jedini urednik je bio „[[Special:Contributions/$2|$2]]“)',
 'exbeforeblank' => 'sadržaj pre brisanja je bio: „$1“',
 'exblank' => 'stranica je bila prazna',
 'delete-confirm' => 'Brisanje stranice „$1“',
@@ -2461,6 +2463,7 @@ Pogledajte ''$2'' za više detalja.",
 'deleteotherreason' => 'Drugi/dodatni razlog:',
 'deletereasonotherlist' => 'Drugi razlog',
 'deletereason-dropdown' => '*Najčešći razlozi za brisanje
+** Spam
 ** Zahtev autora
 ** Kršenje autorskih prava
 ** Vandalizam',
@@ -2483,8 +2486,8 @@ Poslednji autor je ujedno i jedini.',
 
 Poslednju izmenu je {{GENDER:$3|napravio|napravila|napravio}} [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Opis izmene: \"''\$1''\".",
-'revertpage' => 'Vraćene izmene [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na poslednju  izmenu korisnika [[User:$1|$1]]',
-'revertpage-nouser' => 'Vraćene su izmene skrivengo korisnika na poslednju izmenu člana [[User:$1|$1]]',
+'revertpage' => 'Vraćene izmene [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na poslednju izmenu korisnika [[User:$1|$1]]',
+'revertpage-nouser' => 'Vraćene su izmene skrivenog korisnika na poslednju izmenu {{GENDER:$1|korisnika|korisnice}} [[User:$1|$1]]',
 'rollback-success' => 'Vraćene su izmene {{GENDER:$1|korisnika|korisnice|korisnika}} $1
 na poslednju izmenu {{GENDER:$2|korisnika|korisnice|korisnika}} $2.',
 
@@ -2524,9 +2527,9 @@ Ovo su trenutne postavke stranice '''$1''':",
 'protect-cascadeon' => 'Ova stranica je trenutno zaštićena jer se nalazi na {{PLURAL:$1|stranici koja ima|stranicama koje imaju}} prenosivu zaštitu.
 Možete da promenite stepen zaštite, ali to neće uticati na prenosivu zaštitu.',
 'protect-default' => 'Dozvoli svim korisnicima',
-'protect-fallback' => 'Potrebno je imati ovlašćenja „$1“',
-'protect-level-autoconfirmed' => 'Blokiraj nove i anonimne korisnike',
-'protect-level-sysop' => 'Samo administratori',
+'protect-fallback' => 'Dozvoljeno samo korisnicima sa dozvolom „$1“',
+'protect-level-autoconfirmed' => 'Dopušteno samo automatski potvrđenim korisnicima',
+'protect-level-sysop' => 'Dopušteno samo administratorima',
 'protect-summary-cascade' => 'prenosiva zaštita',
 'protect-expiring' => 'ističe $1 (UTC)',
 'protect-expiring-local' => 'ističe $1',
@@ -2573,8 +2576,8 @@ Arhiva se povremeno čisti od ovakvih stranica.',
 'undeleteextrahelp' => "Da biste vratili celu istoriju stranice, ostavite sve kućice neoznačene i kliknite na dugme '''''{{int:undeletebtn}}'''''.
 Ako želite da vratite određene izmene, označite ih i kliknite na '''''{{int:undeletebtn}}'''''.",
 'undeleterevisions' => '$1 {{PLURAL:$1|izmena je arhivirana|izmene su arhivirane|izmena je arhivirano}}',
-'undeletehistory' => 'Ako vratite stranicu, sve izmene će biti vraćene njenoj istoriji.
-Ako je u međuvremenu napravljena nova stranica s istim nazivom, vraćene izmene će se pojaviti u ranijom istoriji.',
+'undeletehistory' => 'Ako vratite stranicu, sve revizije će biti vraćene njenoj istoriji.
+Ako je u međuvremenu napravljena nova stranica s istim nazivom, vraćene izmene će se pojaviti u njenoj ranijoj istoriji.',
 'undeleterevdel' => 'Vraćanje neće biti izvršeno ako je rezultat toga delimično brisanje poslednje izmene.
 U takvim slučajevima morate isključiti ili otkriti najnovije obrisane izmene.',
 'undeletehistorynoadmin' => 'Ova stranica je obrisana.
@@ -2946,7 +2949,7 @@ U drugom slučaju, možete koristiti i vezu, na primer [[{{#Special:Export}}/{{M
 'allmessagesdefault' => 'Podrazumevani tekst',
 'allmessagescurrent' => 'Tekst poruke',
 'allmessagestext' => 'Ovo je spisak svih sistemskih poruka koje su dostupne u imenskom prostoru „Medijaviki“.
-Posetite [//www.mediawiki.org/wiki/Localisation Medijaviki lokalizaciju] i [//translatewiki.net Translejtviki] ako želite da pomognete u prevođenju.',
+Posetite [https://www.mediawiki.org/wiki/Localisation Medijaviki lokalizaciju] i [//translatewiki.net Translejtviki] ako želite da pomognete u prevođenju.',
 'allmessagesnotsupportedDB' => "Ova stranica ne može da se koristi jer je '''\$wgUseDatabaseMessages''' onemogućen.",
 'allmessages-filter-legend' => 'Filter',
 'allmessages-filter' => 'Filtriraj po stanju:',
@@ -3158,6 +3161,7 @@ Ovo je verovatno izazvano vezom do spoljašnjeg sajta koji se nalazi na crnoj li
 'spam_reverting' => 'Vraćam na poslednju izmenu koja ne sadrži veze do $1',
 'spam_blanking' => 'Sve izmene sadrže veze do $1. Čistim',
 'spam_deleting' => 'Sve izmene sadrže veze do $1. Brišem',
+'simpleantispam-label' => "Provera spama. '''NE''' popunjavaj ovo unutra!",
 
 # Info page
 'pageinfo-title' => 'Podaci o „$1“',
@@ -3191,6 +3195,7 @@ Ovo je verovatno izazvano vezom do spoljašnjeg sajta koji se nalazi na crnoj li
 'pageinfo-magic-words' => '{{PLURAL:$1|Magična reč|Magične reči}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}} ($1)',
 'pageinfo-templates' => '{{PLURAL:$1|Uključeni šablon|Uključeni šabloni}} ($1)',
+'pageinfo-transclusions' => '{{PLURAL:$1|Stranica|Stranice}} uključene u ($1)',
 'pageinfo-toolboxlink' => 'Podaci o stranici',
 'pageinfo-redirectsto' => 'Preusmerava na',
 'pageinfo-redirectsto-info' => 'podaci',
@@ -3809,7 +3814,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'Izmeni ovu datoteku koristeći spoljašnji program',
-'edit-externally-help' => '(Pogledajte [//www.mediawiki.org/wiki/Manual:External_editors uputstvo za podešavanje] za više informacija)',
+'edit-externally-help' => '(Pogledajte [https://www.mediawiki.org/wiki/Manual:External_editors uputstvo za podešavanje] za više informacija)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sve',
@@ -3914,6 +3919,7 @@ Potvrdite da stvarno želite da napravite stranicu.",
 'ellipsis' => '…',
 'percent' => '$1%',
 'parentheses' => '($1)',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← prethodna stranica',
@@ -3934,10 +3940,10 @@ Potvrdite da stvarno želite da napravite stranicu.",
 'table_pager_empty' => 'Nema rezultata',
 
 # Auto-summaries
-'autosumm-blank' => 'Potpuno obrisana stranica',
+'autosumm-blank' => 'Uklonjen celokupan sadržaj stranice',
 'autosumm-replace' => 'Zamena sadržaja stranice sa „$1“',
 'autoredircomment' => 'Preusmerenje na [[$1]]',
-'autosumm-new' => 'Napravljena stranica sa: „$1“',
+'autosumm-new' => 'Nova stranica: $1',
 
 # Size units
 'size-bytes' => '$1 B',
@@ -3967,7 +3973,7 @@ Da biste uklonili naslov, označite kućicu do njega i kliknite na „{{int:Watc
 Možete i da [[Special:EditWatchlist/raw|uredite sirov spisak]].',
 'watchlistedit-normal-submit' => 'Ukloni',
 'watchlistedit-normal-done' => '{{PLURAL:$1|Jedna stranica je uklonjena|$1 stranice su uklonjene|$1 stranica je uklonjeno}} s vašeg spiska nadgledanja:',
-'watchlistedit-raw-title' => 'Napredno uređivanje spiska nadgledanja',
+'watchlistedit-raw-title' => 'Izmeni sirov spisak nadgledanja',
 'watchlistedit-raw-legend' => 'Napredno uređivanje spiska nadgledanja',
 'watchlistedit-raw-explain' => 'Naslovi sa spiska nadgledanja su prikazani ispod i mogu se uređivati dodavanjem ili uklanjanjem stavki sa spiska;
 jedan naslov po redu.
@@ -4069,7 +4075,7 @@ Možete da [[Special:EditWatchlist|koristite i običan uređivač]].',
 'version-version' => '(izdanje $1)',
 'version-svn-revision' => '(izm. $2)',
 'version-license' => 'Licenca',
-'version-poweredby-credits' => "Ovaj viki pokreće '''[//www.mediawiki.org/ Medijaviki]''', autorska prava © 2001-$1 $2.",
+'version-poweredby-credits' => "Ovaj viki pokreće '''[https://www.mediawiki.org/ Medijaviki]''', autorska prava © 2001-$1 $2.",
 'version-poweredby-others' => 'ostali',
 'version-credits-summary' => 'Želeli bismo da zahvalimo sledećim ljudima na njihovom doprinosu [[Special:Version|Medijavikiji]].',
 'version-license-info' => 'Medijaviki je slobodan softver možete ga redistribuirati i/ili modifikovati pod uslovima GNU-ove opšte javne licence verzija 2 ili svake sledeće koju objavi Zadužbina za slobodan softver.
@@ -4104,10 +4110,8 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 
 # Special:SpecialPages
 'specialpages' => 'Posebne stranice',
-'specialpages-note' => '----
-* obične posebne stranice
-* <span class="mw-specialpagerestricted">ograničene posebne stranice</span>
-* <span class="mw-specialpagecached">privremeno memorisane posebne stranice</span>',
+'specialpages-note' => '* Normalne posebne stranice
+* <span class="mw-specialpagerestricted">Ograničene posebne stranice</span>',
 'specialpages-group-maintenance' => 'Izveštaji održavanja',
 'specialpages-group-other' => 'Ostale posebne stranice',
 'specialpages-group-login' => 'Prijava/registracija',
@@ -4139,12 +4143,16 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 'tags' => 'Važeće oznake izmena',
 'tag-filter' => 'Filter za [[Special:Tags|oznake]]:',
 'tag-filter-submit' => 'Filtriraj',
+'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Oznaka|Oznake}}]]: $2)',
 'tags-title' => 'Oznake',
 'tags-intro' => 'Na ovoj stranici je naveden spisak oznaka s kojima program može da označi izmene i njegovo značenje.',
 'tags-tag' => 'Naziv oznake',
 'tags-display-header' => 'Izgled na spiskovima izmena',
 'tags-description-header' => 'Opis značenja',
+'tags-active-header' => 'Aktivna?',
 'tags-hitcount-header' => 'Označene izmene',
+'tags-active-yes' => 'Da',
+'tags-active-no' => 'Ne',
 'tags-edit' => 'uredi',
 'tags-hitcount' => '$1 {{PLURAL:$1|izmena|izmene|izmena}}',
 
@@ -4189,17 +4197,17 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 'sqlite-no-fts' => '$1 bez podrške pretrage celog teksta',
 
 # New logging system
-'logentry-delete-delete' => '$1 {{GENDER:|je obrisao|je obrisala|je obrisao}} $3',
-'logentry-delete-restore' => '$1 {{GENDER:|je vratio|je vratila|je vratio}} stranicu $3',
-'logentry-delete-event' => '$1 {{GENDER:$2|je promenio|je promenila|je promenio}} vidljivost {{PLURAL:$5|događaja|$5 događaja|$5 događaja}} u dnevniku na $3: $4',
-'logentry-delete-revision' => '$1 {{GENDER:|je promenio|je promenila|je promenio}} vidljivost {{PLURAL:$5|izmene|$5 izmene|$5 izmena}} na stranici $3: $4',
+'logentry-delete-delete' => '$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3',
+'logentry-delete-restore' => '$1 je {{GENDER:$2|vratio|vratila}} stranicu $3',
+'logentry-delete-event' => '$1 je {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|događaja|$5 daogađaja}} u dnevniku na $3: $4',
+'logentry-delete-revision' => '$1 je {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|izmene|$5 izmena}} na stranici $3: $4',
 'logentry-delete-event-legacy' => '$1 je {{GENDER:$2|promenio|promenila}} vidljivost događaja u dnevniku na $3',
-'logentry-delete-revision-legacy' => '$1 {{GENDER:|je promenio|je promenila|je promenio}} vidljivost izmenâ na stranici $3',
-'logentry-suppress-delete' => '$1 {{GENDER:|je potisnuo|je potisnula|je potisnuo}} stranicu $3',
-'logentry-suppress-event' => '$1 je potajno {{GENDER:|promenio|promenila|promenio}} vidljivost {{PLURAL:$5|događaja|$5 događaja|$5 događaja}} u dnevniku na $3: $4',
-'logentry-suppress-revision' => '$1 je potajno {{GENDER:|promenio|promenila|promenio}} vidljivost {{PLURAL:$5|izmene|$5 izmene|$5 izmena}} na stranici $3: $4',
-'logentry-suppress-event-legacy' => '$1 je potajno {{GENDER:|promenio|promenila|promenio}} vidljivost događajâ u dnevniku na $3',
-'logentry-suppress-revision-legacy' => '$1 je potajno {{GENDER:|promenio|promenila}} vidljivost izmena na stranici $3',
+'logentry-delete-revision-legacy' => '$1 je {{GENDER:$2|promenio|promenila}} vidljivost izmena na stranici $3',
+'logentry-suppress-delete' => '$1 je {{GENDER:$2|potisnuo|potisnula}} stranicu $3',
+'logentry-suppress-event' => '$1 je tajno {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|događaja|$5 događaja}} u dnevniku na $3: $4',
+'logentry-suppress-revision' => '$1 je tajno {{GENDER:$2|promenio|promenila}} vidljivost {{PLURAL:$5|izmene|$5 izmena}} na stranici $3: $4',
+'logentry-suppress-event-legacy' => '$1 је tajno {{GENDER:$2|promenio|promenila}} vidljivost događaj u dnevniku na $3',
+'logentry-suppress-revision-legacy' => '$1 je tajno {{GENDER:$2|promenio|promenila}} vidljivost izmena na stranici $3',
 'revdelete-content-hid' => 'sadržaj je sakriven',
 'revdelete-summary-hid' => 'opis izmene je sakriven',
 'revdelete-uname-hid' => 'korisničko ime je sakriveno',
@@ -4212,15 +4220,16 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 'logentry-move-move-noredirect' => '$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 bez ostavljanja preusmerenja',
 'logentry-move-move_redir' => '$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 preko preusmerenja',
 'logentry-move-move_redir-noredirect' => '$1 je {{GENDER:|premestio|premestila}} stranicu $3 na $4 preko preusmerenja bez ostavljanja preusmerenja',
-'logentry-patrol-patrol' => '$1 {{GENDER:|je označio|je označila|je označio}} izmenu $4 stranice $3 kao patroliranu',
+'logentry-patrol-patrol' => '$1 je {{GENDER:$2|označio|označila}} izmenu $4 stranice $3 kao patroliranu',
 'logentry-patrol-patrol-auto' => '$1 je automatski {{GENDER:$2|označio|označila}} izmenu $4 stranice $3 kao pregledanu',
 'logentry-newusers-newusers' => '$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog',
 'logentry-newusers-create' => '$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog',
 'logentry-newusers-create2' => '$1 je {{GENDER:$2|otvorio|otvorila}} korisnički nalog $3',
+'logentry-newusers-byemail' => 'Korisnički nalog $3 je {{GENDER:$2|napravljen}} od strane $1 i lozinka je poslata na e-poštu',
 'logentry-newusers-autocreate' => 'Korisnički nalog $1 je automatski {{GENDER:$2|otvoren}}',
 'logentry-rights-rights' => '$1 je {{GENDER:$1|promenio|promenila}} članstvo grupe za $3 iz $4 u $5',
-'logentry-rights-rights-legacy' => '$1 {{GENDER:$1|je promenio|je promenila|je promenio}} članstvo grupe za $3',
-'logentry-rights-autopromote' => '$1 je automatski {{GENDER:$1|unapređen|unapređena|unapređen}} iz $4 u $5',
+'logentry-rights-rights-legacy' => '$1 je {{GENDER:$2|promenio|promenila}} čalnstvo grupe za $3',
+'logentry-rights-autopromote' => '$1 je automatski {{GENDER:$1|unapređen|unapređena}} iz $4 u $5',
 'rightsnone' => '(ništa)',
 
 # Feedback
@@ -4298,4 +4307,19 @@ U suprotnom, poslužite se jednostavnim obrascem ispod. Vaš komentar će stajat
 # Image rotation
 'rotate-comment' => 'Slika je rotirana za $1° u smeru kazaljke na satu',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Zamena šablona',
+'expand_templates_intro' => 'Ova posebna stranica uzima tekst i menja sve šablone u njemu rekurzivno.
+Takođe menja funkcije parsera kao što je <code><nowiki>{{</nowiki>#language:…}}</code> i promenljive kao što je <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Zapravo praktično sve što se nalazi između vitičastih zagrada.',
+'expand_templates_title' => 'Naziv konteksta; za {{STRANICA}} itd.:',
+'expand_templates_input' => 'Unos:',
+'expand_templates_output' => 'Rezultat',
+'expand_templates_xml_output' => 'XML izlaz',
+'expand_templates_ok' => 'U redu',
+'expand_templates_remove_comments' => 'Ukloni komentare',
+'expand_templates_remove_nowiki' => 'Poništava efekat <nowiki> tagova u prikazu članaka',
+'expand_templates_generate_xml' => 'prikaži XML stablo',
+'expand_templates_preview' => 'Prikaz',
+
 );
index d210911..62620b1 100644 (file)
@@ -55,12 +55,10 @@ $specialPageAliases = array(
        'Allmessages'               => array( 'Boskopu' ),
        'Allpages'                  => array( 'AlaPeprewoysi' ),
        'Ancientpages'              => array( 'PasaOwruPeprewoysi' ),
-       'Blockme'                   => array( 'SpikriMi' ),
        'BrokenRedirects'           => array( 'BrokoStirpeprewoysi' ),
        'Categories'                => array( 'Guru' ),
        'Contributions'             => array( 'Kenki' ),
        'Deadendpages'              => array( 'NoSkakiPeprewoysi' ),
-       'Disambiguations'           => array( 'PeprewoysiFuKumakriki' ),
        'DoubleRedirects'           => array( 'Tustirpeprewoysi' ),
        'Emailuser'                 => array( 'EmailMasyin' ),
        'Fewestrevisions'           => array( 'MenaKenki' ),
@@ -364,8 +362,6 @@ $messages = array(
 'ok' => 'Abun',
 'retrievedfrom' => 'Teki baka fu "$1"',
 'youhavenewmessages' => 'Yu abi $1 ($2).',
-'newmessageslink' => 'nyun boskopu',
-'newmessagesdifflink' => 'laste kenki',
 'youhavenewmessagesmulti' => 'Yu abi nyun boskopu na tapu $1',
 'editsection' => 'kenki',
 'editold' => 'kenki',
@@ -640,7 +636,6 @@ A kan ben trowe efu dribi.
 'preferences' => 'Seti',
 'mypreferences' => 'Mi seti',
 'prefs-edits' => 'Nomru fu kenki:',
-'prefsnologin' => 'No kon',
 'changepassword' => 'Kenki yu waktiwortu',
 'prefs-skin' => 'Buba',
 'skin-preview' => 'Si-na-fesi',
@@ -1188,7 +1183,7 @@ Trawan o kibri.
 
 # External editor support
 'edit-externally' => 'Kenki a file disi ini wan dorosey wrokosani.',
-'edit-externally-help' => 'Luku ini a [//www.mediawiki.org/wiki/Manual:External_editors skorobuku fu den seti] gi moro yepi.',
+'edit-externally-help' => 'Luku ini a [https://www.mediawiki.org/wiki/Manual:External_editors skorobuku fu den seti] gi moro yepi.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ala',
index 89997c0..1cddf44 100644 (file)
@@ -300,8 +300,6 @@ $1',
 'ok' => 'Säike (09)',
 'retrievedfrom' => 'Fon "$1"',
 'youhavenewmessages' => 'Du hääst $1 ($2).',
-'newmessageslink' => 'näie Ättergjuchte',
-'newmessagesdifflink' => 'Unnerskeed tou ju foarlääste Version',
 'youhavenewmessagesmulti' => 'Du hääst näie Ättergjuchte: $1',
 'editsection' => 'Beoarbaidje',
 'editold' => 'Beoarbaidje',
@@ -1007,8 +1005,6 @@ Staal deertruch sicher, dät ju Versionsgeskichte fon n Artikkel historisk akroa
 'preferences' => 'Ienstaalengen',
 'mypreferences' => 'Ienstaalengen',
 'prefs-edits' => 'Antaal Beoarbaidengen:',
-'prefsnologin' => 'Nit anmälded',
-'prefsnologintext' => 'Du moast <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} anmälded]</span> weese, uum dien Ienstaalengen annerje tou konnen.',
 'changepassword' => 'Paaswoud annerje',
 'prefs-skin' => 'Skin',
 'skin-preview' => 'Foarskau',
@@ -1274,6 +1270,7 @@ Ju duur maximoal $1 {{PLURAL:$1|Teeken|Teekene}} loang weese.',
 'recentchanges-label-minor' => 'Litje Annerenge',
 'recentchanges-label-bot' => 'Annerenge truch n Bot',
 'recentchanges-label-unpatrolled' => 'Nit-kontrollierde Annerenge',
+'recentchanges-legend-newpage' => '$1 - näie Siede',
 'rcnote' => "Anwiesd {{PLURAL:$1|wäd '''1''' Annerenge|wäide do lääste '''$1''' Annerengen}} in {{PLURAL:$2|dän lääste Dai|do lääste '''$2''' Deege}} siet $5, $4.",
 'rcnotefrom' => "Anwiesd wäide do Annerengen siet '''$2''' (max. '''$1''' Iendraage).",
 'rclistfrom' => 'Bloot näie Annerengen siet $1 wiese.',
@@ -2380,7 +2377,7 @@ Alternativ is die Export uk mäd de Syntax [[{{#Special:Export}}/{{MediaWiki:Mai
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'Dissen Text',
 'allmessagestext' => 'Dit is ne Lieste fon aal System-Ättergjuchte do in dän MediaWiki-Noomenruum tou Ferföigenge stounde.
-Besäik jädden [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net], wan du mee-oarbaidje wolt an ju MediaWiki-Sortierenge.',
+Besäik jädden [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] un [//translatewiki.net translatewiki.net], wan du mee-oarbaidje wolt an ju MediaWiki-Sortierenge.',
 'allmessagesnotsupportedDB' => 'Disse Spezioalsiede stoant nit tou Ferföigenge, deer ju uur dän Parameter <tt>$wgUseDatabaseMessages</tt> deaktivierd wuude.',
 'allmessages-filter-legend' => 'Sieuwe',
 'allmessages-filter' => 'Sieuwe foar anpaaseden Toustand:',
@@ -2547,6 +2544,7 @@ Do ap dän lokoale Reekener spiekerje un deerätter hier hoochleede.',
 'spambot_username' => 'MediaWiki Spam-Süüwerenge',
 'spam_reverting' => 'Lääste Version sunner Links tou $1 wier häärstoald.',
 'spam_blanking' => 'Aal Versione äntheelden Links tou $1, skeenmoaked.',
+'simpleantispam-label' => "Spamskuts-Wröige. Hier '''niks''' iendreege!",
 
 # Info page
 'pageinfo-title' => 'Informatione tou „$1“',
@@ -2956,7 +2954,7 @@ Wiedere wäide standoardmäitich nit anwiesd.
 
 # External editor support
 'edit-externally' => 'Disse Doatäi mäd n extern Program beoarbaidje',
-'edit-externally-help' => '(Sjuch do [//www.mediawiki.org/wiki/Manual:External_editors Installationsanwiesengen] foar wiedere Informatione)',
+'edit-externally-help' => '(Sjuch do [https://www.mediawiki.org/wiki/Manual:External_editors Installationsanwiesengen] foar wiedere Informatione)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'aal',
@@ -3129,7 +3127,7 @@ Du koast dien Beooboachtengslieste uk in dät [[Special:EditWatchlist/raw|Lieste
 'version-hook-subscribedby' => 'Aproup fon',
 'version-version' => '(Version $1)',
 'version-license' => 'Lizenz',
-'version-poweredby-credits' => "Disse Website nutset '''[//www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
+'version-poweredby-credits' => "Disse Website nutset '''[https://www.mediawiki.org/wiki/MediaWiki/de MediaWiki]''', Copyright © 2001–$1 $2.",
 'version-poweredby-others' => 'uur',
 'version-license-info' => "MediaWiki is fräie Software, dät hat dät ju ätter do Bedingengen fon ju truch de Free Software Foundation fereepenlikede ''GNU General Public License'', fääreferdeeld un/ of modifizierd wäide kon. Deerbie kon ju version 2, of ätter oainen Uurdeel, älke näiere Version fon ju Lizenz ferwoand wäide.
 
@@ -3153,8 +3151,7 @@ Ne [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie fon ju ''GNU General Public License''
 
 # Special:SpecialPages
 'specialpages' => 'Spezioalsieden',
-'specialpages-note' => '----
-* Reguläre Spezioalsieden
+'specialpages-note' => '* Reguläre Spezioalsieden
 * <span class="mw-specialpagerestricted">Tougriepsbeskränkede Spezioalsieden</span>
 * <span class="mw-specialpagecached">Cachegenerierde Spezioalsieden</span>',
 'specialpages-group-maintenance' => 'Fersuurgengsliesten',
@@ -3240,4 +3237,16 @@ Ne [{{SERVER}}{{SCRIPTPATH}}/COPYING Kopie fon ju ''GNU General Public License''
 'searchsuggest-search' => 'Säik',
 'searchsuggest-containing' => 'Fultextsäike ätter ...',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Foarloagen expandierje',
+'expand_templates_intro' => "In disse Spezialsiede kon Text ienroat wäide un aal Foarloagen in hier wäide rekursiv expandierd. Uk Parserfunktione as <nowiki>{{</nowiki>#language:...}} un Variabelen as <nowiki>{{</nowiki>CURRENTDAY}} wäide benutsed - faktisk alles wät twiske dubbelde swoangene Klammere '''{{}}''' stoant. Dit geböärt truch dän Aproup fon apstuunse Parser-Phasen in MediaWiki.",
+'expand_templates_title' => 'Kontexttittel, foar {{FULLPAGENAME}} etc.:',
+'expand_templates_input' => 'Iengoawefäild:',
+'expand_templates_output' => 'Resultoat',
+'expand_templates_xml_output' => 'XML-Uutgoawe',
+'expand_templates_ok' => 'Uutfiere',
+'expand_templates_remove_comments' => 'Kommentoare wächhoalje',
+'expand_templates_generate_xml' => 'Wies XML Parser-Boom',
+'expand_templates_preview' => 'Foarskau',
+
 );
index 410e1ba..327a003 100644 (file)
@@ -49,7 +49,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'KacaKolot' ),
        'Blankpage'                 => array( 'KacaKosong' ),
        'Block'                     => array( 'PeungpeukIP' ),
-       'Blockme'                   => array( 'PeungpeukKuring' ),
        'Booksources'               => array( 'SumberPustaka' ),
        'BrokenRedirects'           => array( 'AlihanPegat' ),
        'Categories'                => array( 'Kategori' ),
@@ -58,7 +57,6 @@ $specialPageAliases = array(
        'Contributions'             => array( 'Kontribusi' ),
        'CreateAccount'             => array( 'NyieunRekening' ),
        'Deadendpages'              => array( 'KacaBuntu' ),
-       'Disambiguations'           => array( 'Disambiguasi' ),
        'DoubleRedirects'           => array( 'AlihanGanda' ),
        'Emailuser'                 => array( 'SurelekPamake' ),
        'Export'                    => array( 'Ekspor' ),
@@ -387,8 +385,6 @@ $1',
 'ok' => 'Heug',
 'retrievedfrom' => 'Disalin ti "$1"',
 'youhavenewmessages' => 'Anjeun boga $1 ($2).',
-'newmessageslink' => 'talatah anyar',
-'newmessagesdifflink' => 'bédana ti nu saméméhna',
 'youhavenewmessagesmulti' => 'Anjeun boga talatah anyar di $1',
 'editsection' => 'édit',
 'editold' => 'édit',
@@ -1074,8 +1070,6 @@ Coba susud dimimitian ku ''all:'' pikeun nyusud sakabéh kandunganana (kaasup ka
 'preferences' => 'Préferénsi',
 'mypreferences' => 'Préferéns',
 'prefs-edits' => 'Jumlah éditan:',
-'prefsnologin' => 'Can asup log',
-'prefsnologintext' => 'Anjeun kudu <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} asup log]</span> pikeun ngatur préferénsi pamaké.',
 'changepassword' => 'Robah sandi',
 'prefs-skin' => 'Kulit',
 'skin-preview' => 'Pramidang',
@@ -1333,6 +1327,7 @@ Mun geus anggeus teu bisa dibolaykeun.',
 'recentchanges-label-minor' => 'Ieu éditan minor',
 'recentchanges-label-bot' => 'Ieu parobahan dijieun ku bot',
 'recentchanges-label-unpatrolled' => 'Ieu éditan can karoris',
+'recentchanges-legend-newpage' => '$1 - kaca anyar',
 'rcnote' => "Di handap ieu {{PLURAL:$1|'''1''' parobahan| '''$1''' parobahan anyar}} dina  {{PLURAL:$2|poé|'''$2''' poé}} ahir, nepi $5, $4.",
 'rcnotefrom' => 'Di handap ieu parobahan saprak <b>$2</b> (nu ditémbongkeun nepi ka <b>$1</b>).',
 'rclistfrom' => 'Témbongkeun nu anyar robah nepi ka $1',
@@ -2792,7 +2787,7 @@ Nu séjénna bakal disumputkeun sakumaha asalna.
 
 # External editor support
 'edit-externally' => 'Édit koropak ieu migunakeun aplikasi éksternal',
-'edit-externally-help' => 'Baca [//www.mediawiki.org/wiki/Manual:External_editors pituduh ngatur] pikeun émbaran leuwih jéntré.',
+'edit-externally-help' => 'Baca [https://www.mediawiki.org/wiki/Manual:External_editors pituduh ngatur] pikeun émbaran leuwih jéntré.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'sadaya',
@@ -2932,8 +2927,7 @@ Coba ku sawangan normal.',
 
 # Special:SpecialPages
 'specialpages' => 'Kaca husus',
-'specialpages-note' => '----
-* Kaca husus bisa di buka ku umum.
+'specialpages-note' => '* Kaca husus bisa di buka ku umum.
 * <strong class="mw-specialpagerestricted">Cetak kandel kaca husus nu kawates.</strong>',
 'specialpages-group-maintenance' => 'Laporan pigawéeun',
 'specialpages-group-other' => 'Kaca husus lainna',
@@ -3026,4 +3020,12 @@ Coba ku sawangan normal.',
 'duration-centuries' => '$1 {{PLURAL:$1|abad|abad}}',
 'duration-millennia' => '$1 {{PLURAL:$1|milénium|milénium}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Mekarkeun citakan',
+'expand_templates_input' => 'Téks input:',
+'expand_templates_output' => 'Hasil:',
+'expand_templates_xml_output' => 'Output XML',
+'expand_templates_ok' => 'Heug',
+'expand_templates_preview' => 'Pramidang',
+
 );
index 30dd4d0..1014778 100644 (file)
@@ -98,7 +98,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'Gamla_sidor' ),
        'Blankpage'                 => array( 'Tom_sida' ),
        'Block'                     => array( 'Blockera' ),
-       'Blockme'                   => array( 'Blockera_mig' ),
        'Booksources'               => array( 'Bokkällor' ),
        'BrokenRedirects'           => array( 'Trasiga_omdirigeringar', 'Dåliga_omdirigeringar' ),
        'Categories'                => array( 'Kategorier' ),
@@ -108,9 +107,9 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Skapa_konto' ),
        'Deadendpages'              => array( 'Sidor_utan_länkar', 'Sidor_utan_länkar_från' ),
        'DeletedContributions'      => array( 'Raderade_bidrag' ),
-       'Disambiguations'           => array( 'Förgreningssidor' ),
        'DoubleRedirects'           => array( 'Dubbla_omdirigeringar' ),
        'Emailuser'                 => array( 'E-mail' ),
+       'ExpandTemplates'           => array( 'Expandera_mallar', 'Utöka_mallar' ),
        'Export'                    => array( 'Exportera' ),
        'Fewestrevisions'           => array( 'Minst_versioner' ),
        'FileDuplicateSearch'       => array( 'Dublettfilsökning' ),
@@ -600,12 +599,10 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Hämtad från "$1"',
 'youhavenewmessages' => 'Du har $1 ($2).',
-'newmessageslink' => 'nya meddelanden',
-'newmessagesdifflink' => 'senaste ändringen',
 'youhavenewmessagesfromusers' => 'Du har $1 från {{PLURAL:$3|en annan användare|$3 användare}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du har $1 från många användare ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|ett nytt meddelande|nya meddelanden}}',
-'newmessagesdifflinkplural' => 'senaste {{PLURAL:$1|ändring|ändringar}}',
+'newmessageslinkplural' => '{{PLURAL:$1|ett nytt meddelande|999=nya meddelanden}}',
+'newmessagesdifflinkplural' => 'senaste {{PLURAL:$1|ändring|999=ändringar}}',
 'youhavenewmessagesmulti' => 'Du har nya meddelanden på $1',
 'editsection' => 'redigera',
 'editold' => 'redigera',
@@ -734,7 +731,8 @@ Den administratören som låste den gav denna anledning: "\'\'$3\'\'".',
 'invalidtitle-knownnamespace' => 'Ogiltig titel med namnrymden "$2" och texten "$3"',
 'invalidtitle-unknownnamespace' => 'Ogiltig titel med okänt namnrymdsnummer $1 och texten "$2"',
 'exception-nologin' => 'Inte inloggad',
-'exception-nologin-text' => 'Denna sida eller åtgärd kräver att du måste vara inloggad på denna wiki.',
+'exception-nologin-text' => 'Var god [[Special:Userlogin|logga in]] för att komma åt denna sida eller åtgärd.',
+'exception-nologin-text-manual' => 'Var god $1 för att få tillgång till denna sida eller åtgärd.',
 
 # Virus scanner
 'virus-badscanner' => "Dålig konfigurering: okänd virusskanner: ''$1''",
@@ -781,7 +779,7 @@ Glöm inte att justera dina [[Special:Preferences|{{SITENAME}}-inställningar]].
 'gotaccount' => "Har du redan ett användarkonto? '''$1'''.",
 'gotaccountlink' => 'Logga in',
 'userlogin-resetlink' => 'Har du glömt dina inloggningsuppgifter?',
-'userlogin-resetpassword-link' => 'Återställ ditt lösenord',
+'userlogin-resetpassword-link' => 'Glömt ditt lösenord?',
 'helplogin-url' => 'Help:Logga in',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hjälp med inloggning]]',
 'userlogin-loggedin' => 'Du är redan inloggad som {{GENDER:$1|$1}}.
@@ -844,15 +842,15 @@ fortsätta använda ditt gamla lösenord.',
 'noemailcreate' => 'Du måste ange en giltig e-postadress',
 'passwordsent' => 'Ett nytt lösenord har skickats till den e-postadress som användaren "$1" har registrerat. När du får meddelandet, var god logga in igen.',
 'blocked-mailpassword' => 'Din IP-adress är blockerad, därför kan den inte användas för att få ett nytt lösenord.',
-'eauthentsent' => 'Ett e-brev för bekräftelse har skickats till den e-postadress som angivits.
-Innan någon annan e-post kan skickas härifrån till kontot, måste du följa instruktionerna i e-brevet för att bekräfta att kontot verkligen är ditt.',
+'eauthentsent' => 'Ett e-postmeddelande för bekräftelse har skickats till den angivna e-postadressen.
+Innan någon annan e-post kan skickas till kontot, måste du följa instruktionerna i e-postmeddelandet för att bekräfta att kontot verkligen är ditt.',
 'throttled-mailpassword' => 'En lösenordsåterställning har redan skickats för mindre än {{PLURAL:$1|en timme|$1 timmar}} sedan.
 För att förhindra missbruk skickas bara en lösenordsåterställning per {{PLURAL:$1|timme|$1-timmarsperiod}}.',
 'mailerror' => 'Fel vid skickande av e-post: $1',
 'acct_creation_throttle_hit' => 'Besökare till den här wikin som har använt din IP-adress har skapat {{PLURAL:$1|1 användarkonto|$1 användarkonton}} under det senaste dygnet, vilket är det maximalt tillåtna inom den tidsperioden.
 Som ett resultat kan besökare som använder den här IP-adressen inte skapa några fler användarkonton just nu.',
 'emailauthenticated' => 'Din e-postadress bekräftades den $2 kl. $3.',
-'emailnotauthenticated' => 'Din e-postadress är ännu inte bekräftad. Ingen e-post kommer att skickas vad gäller det följande:',
+'emailnotauthenticated' => 'Din e-postadress är ännu inte bekräftad. Ingen e-post kommer att skickas vad gäller det följande funktionerna.',
 'noemailprefs' => 'Uppge en e-postadress i dina inställningar för att få dessa funktioner att fungera.',
 'emailconfirmlink' => 'Bekräfta din e-postadress',
 'invalidemailaddress' => 'E-postadressen kan inte godtas då formatet verkar vara felaktigt.
@@ -1216,7 +1214,7 @@ Anledningen till blockeringen var "$2".',
 'next' => 'nästa',
 'last' => 'föregående',
 'page_first' => 'första',
-'page_last' => 'senaste',
+'page_last' => 'sista',
 'histlegend' => "Val av diff: markera i klickrutorna för att jämföra versioner och tryck enter eller knappen längst ner.<br />
 Förklaring: (nuvarande) = skillnad mot nuvarande version; (föregående) = skillnad mot föregående version; '''m''' = mindre ändring.",
 'history-fieldset-title' => 'Bläddra i historiken',
@@ -1284,18 +1282,19 @@ eller så försöker du gömma den senaste versionen av sidan.',
 Andra administratörer på {{SITENAME}} kommer fortfarande att kunna läsa det dolda innehållet och kan återställa sidan genom samma gränssnitt, om inte ytterligare begränsningar finns.",
 'revdelete-confirm' => 'Var god bekräfta att du vill göra detta, och att du förstår konsekvenserna, och att du gör så i enlighet med [[{{MediaWiki:Policy-url}}|policyn]].',
 'revdelete-suppress-text' => "Undanhållande ska '''bara''' användas i följande fall:
+* Eventuell förolämpande information
 * Opassande personlig information
 *: ''hemadresser och telefonnummer, personnummer, etc.''",
 'revdelete-legend' => 'Ändra synlighet',
-'revdelete-hide-text' => 'Dölj versionstext',
+'revdelete-hide-text' => 'Versionstext',
 'revdelete-hide-image' => 'Dölj filinnehåll',
 'revdelete-hide-name' => 'Dölj åtgärd och sidnamn',
-'revdelete-hide-comment' => 'Dölj redigeringskommentar',
-'revdelete-hide-user' => 'Dölj skribentens användarnamn/IP-adress',
+'revdelete-hide-comment' => 'Redigeringssammanfattning',
+'revdelete-hide-user' => 'Redigerarens användarnamn/IP-adress',
 'revdelete-hide-restricted' => 'Undanhåll data från administratörer så väl som från övriga',
 'revdelete-radio-same' => '(låt vara)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Nej',
+'revdelete-radio-set' => 'Dold',
+'revdelete-radio-unset' => 'Synlig',
 'revdelete-suppress' => 'Undanhåll data även från administratörer',
 'revdelete-unsuppress' => 'Ta bort begränsningar på återställda versioner',
 'revdelete-log' => 'Anledning:',
@@ -1452,8 +1451,7 @@ Notera dock att deras indexering av {{SITENAME}} kan vara något föråldrad.',
 'preferences' => 'Inställningar',
 'mypreferences' => 'Inställningar',
 'prefs-edits' => 'Antal redigeringar:',
-'prefsnologin' => 'Inte inloggad',
-'prefsnologintext' => 'Du måste vara <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} inloggad]</span> för att kunna ändra dina inställningar.',
+'prefsnologintext2' => 'Var god $1 för att ändra användarinställningar.',
 'changepassword' => 'Byt lösenord',
 'prefs-skin' => 'Utseende',
 'skin-preview' => 'förhandsvisning',
@@ -1491,7 +1489,7 @@ Notera dock att deras indexering av {{SITENAME}} kan vara något föråldrad.',
 'recentchangescount' => 'Antal redigeringar som visas som standard:',
 'prefs-help-recentchangescount' => 'Detta inkluderar senaste ändringarna, sidhistorik och loggar.',
 'prefs-help-watchlist-token2' => 'Detta är den hemliga nyckeln till webbflödet i din bevakningslista.
-Någon som vet den kommer att kunna läsa din bevakningslista, så inte dela ut den.
+Någon som vet den kommer att kunna läsa din bevakningslista, så dela inte ut den.
 [[Special:ResetTokens|Klicka här om du behöver återställa den]].',
 'savedprefs' => 'Dina inställningar har sparats',
 'timezonelegend' => 'Tidszon:',
@@ -1752,6 +1750,7 @@ Om du väljer att ange ditt riktiga namn, kommer det att användas för att till
 'recentchanges-label-minor' => 'Detta är en mindre ändring',
 'recentchanges-label-bot' => 'Denna redigering gjordes av en bot',
 'recentchanges-label-unpatrolled' => 'Denna redigering har inte blivit kontrollerad ännu',
+'recentchanges-legend-newpage' => '(se även [[Special:NewPages|listan över nya sidor]])',
 'rcnote' => "Nedan visas {{PLURAL:$1|'''1''' ändring|de senaste '''$1''' ändringarna}} från {{PLURAL:$2|det senaste dygnet|de senaste '''$2''' dygnen}}, per $4, kl. $5.",
 'rcnotefrom' => "Nedan visas ändringar sedan '''$2''' (upp till '''$1''' visas).",
 'rclistfrom' => 'Visa ändringar efter $1',
@@ -2480,8 +2479,7 @@ Kontakta användaren:
 e-post: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Såvida du inte besöker sidan, kommer du inte att få flera meddelanden om aktivitet på sidan.
-Du kan också ta bort flaggan för meddelanden om ändringar på alla sidor i din bevakningslista.
+Såvida du inte besöker sidan, kommer du inte att få flera meddelanden om aktivitet på sidan när du är inloggad. Du kan också ta bort flaggan för meddelanden om ändringar på alla sidor i din bevakningslista.
 
 Hälsningar från {{SITENAME}}s meddelandesystem
 
@@ -2997,7 +2995,7 @@ I det senare fallet kan du även använda en länk, exempel [[{{#Special:Export}
 'allmessagesdefault' => 'Standardtext',
 'allmessagescurrent' => 'Nuvarande text',
 'allmessagestext' => 'Detta är en lista över alla meddelanden i namnrymden MediaWiki.
-Besök [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] eller [//translatewiki.net translatewiki.net] om du vill bidra till översättningen av MediaWiki.',
+Besök [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] eller [//translatewiki.net translatewiki.net] om du vill bidra till översättningen av MediaWiki.',
 'allmessagesnotsupportedDB' => "Den här sidan kan inte användas eftersom '''\$wgUseDatabaseMessages''' är avstängd.",
 'allmessages-filter-legend' => 'Filtrera',
 'allmessages-filter' => 'Filtrera efter anpassningsgrad:',
@@ -3161,7 +3159,7 @@ Vänligen använd förhandsgranskningsknappen innan du sparar.',
 Ger möjlighet att skriva en motivering i redigeringssammanfattningen',
 'tooltip-preferences-save' => 'Spara inställningar',
 'tooltip-summary' => 'Skriv en kort sammanfattning',
-'tooltip-iwiki' => '$1 - $2',
+'interlanguage-link-title' => '$1 - $2',
 
 # Stylesheets
 'common.css' => '/* CSS som skrivs här påverkar alla skal */',
@@ -3211,6 +3209,8 @@ Detta orsakades troligen av en länk till en svartlistad webbplats.',
 'spam_reverting' => 'Återställer till den senaste versionen som inte innehåller länkar till $1',
 'spam_blanking' => 'Alla versioner innehöll en länk till $1, blankar',
 'spam_deleting' => 'Alla ändringar innehöll länkar till $1, raderar',
+'simpleantispam-label' => "Anti-spamkontroll.
+Fyll '''INTE''' i den här!",
 
 # Info page
 'pageinfo-title' => 'Information om "$1"',
@@ -3310,7 +3310,7 @@ Om du kör den kan din dator skadas.",
 'svg-long-desc' => 'SVG-fil, grundstorlek: $1 × $2 pixlar, filstorlek: $3',
 'svg-long-desc-animated' => 'Animerad SVG-fil, standardstorlek $1 × $2 pixlar, filstorlek: $3',
 'svg-long-error' => 'Felaktig SVG-fil: $1',
-'show-big-image' => 'Högupplöst version',
+'show-big-image' => 'Originalfil',
 'show-big-image-preview' => 'Storlek på förhandsvisningen: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Annan upplösning|Andra upplösningar}}: $1.',
 'show-big-image-size' => '$1 × $2 pixlar',
@@ -3779,7 +3779,7 @@ Andra kommer att gömmas som standard
 
 # External editor support
 'edit-externally' => 'Redigera denna fil med hjälp av extern programvara',
-'edit-externally-help' => '(Se [//www.mediawiki.org/wiki/Manual:External_editors installationsinstruktionerna] för mer information)',
+'edit-externally-help' => '(Se [https://www.mediawiki.org/wiki/Manual:External_editors installationsinstruktionerna] för mer information)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'alla',
@@ -3964,7 +3964,7 @@ Du kan också [[Special:EditWatchlist|använda standardeditorn]].',
 'version-hook-subscribedby' => 'Används av',
 'version-version' => '(Version $1)',
 'version-license' => 'Licens',
-'version-poweredby-credits' => "Den här wikin drivs av '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Den här wikin drivs av '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'andra',
 'version-poweredby-translators' => 'översättare från translatewiki.net',
 'version-credits-summary' => 'Vi skulle vilja tacka följande personer för deras bidrag till [[Special:Version|MediaWiki]].',
@@ -3983,7 +3983,7 @@ Du bör ha fått [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopia av GNU General Publi
 # Special:Redirect
 'redirect' => 'Omdirigering efter filnamn, användar-ID eller versions-ID',
 'redirect-legend' => 'Omdirigera till en fil eller sida',
-'redirect-summary' => 'Den här specialsidan omdirigerar till en fil (efter filnamn), en sida (efter versions-id) eller en användarsida (efter användar-id).',
+'redirect-summary' => 'Den här specialsidan omdirigerar till en fil (efter filnamn), en sida (efter versions-id) eller en användarsida (efter användar-id). Användning: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], eller [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Kör',
 'redirect-lookup' => 'Slå upp:',
 'redirect-value' => 'Värde:',
@@ -4005,10 +4005,9 @@ Du bör ha fått [{{SERVER}}{{SCRIPTPATH}}/COPYING en kopia av GNU General Publi
 
 # Special:SpecialPages
 'specialpages' => 'Specialsidor',
-'specialpages-note' => '----
-* Normala specialsidor.
-* <span class="mw-specialpagerestricted">Specialsidor med begränsad åtkomst.</span>
-* <span class="mw-specialpagecached">Cachade specialsidor (kan vara föråldrade).</span>',
+'specialpages-note-top' => 'Teckenförklaring',
+'specialpages-note' => '* Normala specialsidor.
+* <span class="mw-specialpagerestricted">Specialsidor med begränsad åtkomst.</span>',
 'specialpages-group-maintenance' => 'Underhållsrapporter',
 'specialpages-group-other' => 'Övriga specialsidor',
 'specialpages-group-login' => 'Logga in / skapa konto',
@@ -4221,4 +4220,17 @@ Annars kan du använda det enkla formuläret nedan. Din kommentar kommer att lä
 'limitreport-expansiondepth' => 'Största expansionsdjup',
 'limitreport-expensivefunctioncount' => 'Antal dyra parser-funktioner',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Expandera mallar',
+'expand_templates_intro' => 'Den här specialsidan tar en text och expanderar rekursivt alla mallar som används. Även parserfunktioner (som <code><nowiki>{{</nowiki>#language:...}}</code>), variabler som <code><nowiki>{{</nowiki>CURRENTDAY}}</code> och annan kod med dubbla klammerparenteser expanderas.',
+'expand_templates_title' => 'Sidans titel, används för t.ex. {{FULLPAGENAME}}:',
+'expand_templates_input' => 'Text som ska expanderas:',
+'expand_templates_output' => 'Expanderad kod',
+'expand_templates_xml_output' => 'XML-kod',
+'expand_templates_ok' => 'Expandera',
+'expand_templates_remove_comments' => 'Ta bort kommentarer',
+'expand_templates_remove_nowiki' => 'Undertryck <nowiki> taggar i resultatet',
+'expand_templates_generate_xml' => 'Visa parseträd som XML',
+'expand_templates_preview' => 'Förhandsvisning',
+
 );
index d8ef376..a1bdd4a 100644 (file)
@@ -53,7 +53,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'KurasazaZamani' ),
        'Blankpage'                 => array( 'KurasaTupu' ),
        'Block'                     => array( 'Zui', 'ZuiaIP', 'ZuiaMtumiaji' ),
-       'Blockme'                   => array( 'Nizuiye' ),
        'Booksources'               => array( 'ZuiaChanzo' ),
        'BrokenRedirects'           => array( 'ElekezoIliovunjika' ),
        'Categories'                => array( 'Jamii' ),
@@ -62,7 +61,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'SajiliAkaunti' ),
        'Deadendpages'              => array( 'KurasaZilizoondoshwa' ),
        'DeletedContributions'      => array( 'MichangoIliyofutwa' ),
-       'Disambiguations'           => array( 'Maana' ),
        'DoubleRedirects'           => array( 'ElekezoMbili' ),
        'Emailuser'                 => array( 'BaruapepeyaMtumiaji' ),
        'Export'                    => array( 'Toa' ),
@@ -397,8 +395,6 @@ Tazama [[Special:Version|ukurasa wa toleo]].',
 'ok' => 'Sawa',
 'retrievedfrom' => 'Rudishwa kutoka "$1"',
 'youhavenewmessages' => 'Una $1 ($2).',
-'newmessageslink' => 'ujumbe mpya',
-'newmessagesdifflink' => 'badiliko la mwisho',
 'youhavenewmessagesfromusers' => 'Una $1 kutoka {{PLURAL:$3|another user|$3 users}} ($2)',
 'youhavenewmessagesmanyusers' => 'Una $1 kutoka kwa watumiaji wengi $2',
 'newmessageslinkplural' => '{{PLURAL:$1|a new message|ujumbe mpya}}',
@@ -454,6 +450,7 @@ Orodha ya kurasa maalumu zinapatika kwenye [[Special:SpecialPages|{{int:kurasama
 # General errors
 'error' => 'Hitilafu',
 'databaseerror' => 'Hitilafu ya hifadhidata',
+'databaseerror-error' => 'Hitilafu: $1',
 'laggedslavemode' => "'''Ilani:'''Labda masahihisho ya hivi karibuni bado hayajaonekana.",
 'readonly' => 'Hifadhidata imefungika',
 'enterlockreason' => 'Ingiza sababu za kufunga, pamoja na makisio yake lini itafunguliwa',
@@ -530,10 +527,13 @@ Unaweza kuendelea kutumia {{SITENAME}} bila kutaja jina lako, au unaweza <span c
 'yourname' => 'Jina la mtumiaji:',
 'userlogin-yourname' => 'Jina la mtumiaji',
 'userlogin-yourname-ph' => 'Weka jina lako la mtumiaji',
+'createacct-another-username-ph' => 'Weka jina la mtumiaji',
 'yourpassword' => 'Neno la siri:',
 'userlogin-yourpassword' => 'Neno la siri',
 'userlogin-yourpassword-ph' => 'Weka neno lako la siri',
+'createacct-yourpassword-ph' => 'Weka neno la siri',
 'yourpasswordagain' => 'Andika tena neno la siri',
+'createacct-yourpasswordagain-ph' => 'Weka neno la siri tena',
 'remembermypassword' => 'Kumbuka kuingia kwangu katika kivinjari hiki (kwa muda usiozidi {{PLURAL:$1|siku}} $1)',
 'yourdomainname' => 'Tovuti yako:',
 'password-change-forbidden' => 'Hauwezi kubadili nywila katika Wiki hii.',
@@ -554,8 +554,12 @@ Unaweza kuendelea kutumia {{SITENAME}} bila kutaja jina lako, au unaweza <span c
 'gotaccount' => "Unayo akaunti tayari? '''$1'''",
 'gotaccountlink' => 'Ingia',
 'userlogin-resetlink' => 'Umesahau maelezo yako ya kuingia?',
+'createacct-emailrequired' => 'Anwani ya barua pepe',
+'createacct-email-ph' => 'Weka anwani yako ya barua pepe',
+'createacct-another-email-ph' => 'Weka anwani ya barua pepe',
 'createaccountmail' => 'Kwa barua pepe',
 'createaccountreason' => 'Sababu:',
+'createacct-reason' => 'Sababu',
 'badretype' => 'Maneno uliyoyaandika ni tofauti.',
 'userexists' => 'Jina la mtumiaji uliloingiza tayari linatumika.
 Tafadhali chagua jina lingine.',
@@ -993,8 +997,8 @@ Wakabidhi wengine wa {{SITENAME}} bado wataweza kuliona lile lililofichwa pamoja
 'revdelete-hide-user' => 'Ficha jina la mhariri/anwani ya IP ya mhariri',
 'revdelete-hide-restricted' => 'Wakabidhi (vilevile wengine) wasiweze kuona data',
 'revdelete-radio-same' => '(isibadilishwe)',
-'revdelete-radio-set' => 'Ndiyo',
-'revdelete-radio-unset' => 'Hapana',
+'revdelete-radio-set' => 'Halionekani',
+'revdelete-radio-unset' => 'Linaonekana',
 'revdelete-suppress' => 'Wakabidhi (vilevile wengine) wasiweze kuona data',
 'revdelete-unsuppress' => 'Uzuio wa kuona mapitio uondolewe, mapitio yanaporudishwa',
 'revdelete-log' => 'Sababu:',
@@ -1128,8 +1132,6 @@ Ujue lakini kwamba kumbukumbu za {{SITENAME}} kule Google labda zilipitwa na wak
 'preferences' => 'Mapendekezo',
 'mypreferences' => 'Mapendekezo',
 'prefs-edits' => 'Idadi ya marekebisho:',
-'prefsnologin' => 'Hujaingia',
-'prefsnologintext' => 'Inabidi <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} uingie akaunti yako]</span> ili ubadilishe mapendekezo yako.',
 'changepassword' => 'Badilisha neno la siri',
 'prefs-skin' => 'Umbo',
 'skin-preview' => 'Hakiki',
@@ -1227,6 +1229,7 @@ Taarifa hii itakuwa wazi.',
 'prefs-dateformat' => 'Jinsi inayoandikwa tarehe',
 'prefs-timeoffset' => 'Kuweka saa tofauti na saa ya seva',
 'prefs-advancedediting' => 'Hitiari za hali ya juu',
+'prefs-preview' => 'Hakiki',
 'prefs-advancedrc' => 'Hitiari za hali ya juu',
 'prefs-advancedrendering' => 'Hitiari za hali ya juu',
 'prefs-advancedsearchoptions' => 'Hitiari za hali ya juu',
@@ -1378,6 +1381,7 @@ Taarifa hii itakuwa wazi.',
 
 # Recent changes
 'nchanges' => '{{PLURAL:$1|badiliko|mabadiliko}} $1',
+'enhancedrc-history' => 'historia',
 'recentchanges' => 'Mabadiliko ya karibuni',
 'recentchanges-legend' => "Machaguo ya 'mabadaliko ya karibuni'",
 'recentchanges-summary' => 'Orodha ya mabadilisho yaliyofanywa katika {{SITENAME}} siku zilizopita.',
@@ -1386,6 +1390,7 @@ Taarifa hii itakuwa wazi.',
 'recentchanges-label-minor' => 'Hili ni badiliko dogo',
 'recentchanges-label-bot' => 'Sahihisho hili lilitekelezwa na bot',
 'recentchanges-label-unpatrolled' => 'Haririo hili bado halijafanyiwa doria',
+'recentchanges-legend-newpage' => '$1 - ukurasa mpya',
 'rcnote' => "{{PLURAL:$1|Linalofuata ni badiliko '''1'''|Yanayofuata ni mabadiliko '''$1''' ya mwisho}} kutoka katika {{PLURAL:$2|siku iliyopita|siku '''$2''' zilizopita}}, hadi saa $5, tarehe $4.",
 'rcnotefrom' => "Hapo chini yaonekana mabadiliko tangu '''$2''' (tunaonyesha hadi '''$1''').",
 'rclistfrom' => 'Onyesha mabadiliko mapya kuanzia $1',
@@ -1407,7 +1412,7 @@ Taarifa hii itakuwa wazi.',
 'rc_categories' => 'Chagua jamii zingine (uzitenge na kigawaji hiki "|")',
 'rc_categories_any' => 'Yoyote',
 'newsectionsummary' => '/* $1 */ mjadala mpya',
-'rc-enhanced-expand' => 'Onyesha maelezo mengine (inahitaji JavaScript)',
+'rc-enhanced-expand' => 'Onyesha maelezo',
 'rc-enhanced-hide' => 'Ficha maelezo mengine',
 'rc-old-title' => 'ilitengenezwa hapo awali na "$1"',
 
@@ -1723,6 +1728,9 @@ Kumbuka kuhakikisha kwamba hakuna viungo vingine vinavyoelekea kigezo fulani kab
 'randompage' => 'Ukurasa wa bahati',
 'randompage-nopages' => 'Hakuna kurasa katika {{PLURAL:$2|eneo la wiki lifuatalo|maeneo ya wiki yafuatayo}}: $1.',
 
+# Random page in category
+'randomincategory-selectcategory-submit' => 'Nenda',
+
 # Random redirect
 'randomredirect' => 'Elekezo la bahati',
 'randomredirect-nopages' => 'Hakuna maelekezo katika eneo la wiki la "$1".',
@@ -1748,6 +1756,8 @@ Kumbuka kuhakikisha kwamba hakuna viungo vingine vinavyoelekea kigezo fulani kab
 'statistics-users-active-desc' => 'Watumiaji waliofanya kazi katika siku {{PLURAL:$1|iliyopita|$1 zilizopita}}',
 'statistics-mostpopular' => 'Kurasa zinazotazamwa sana',
 
+'pageswithprop-submit' => 'Nenda',
+
 'doubleredirects' => 'Maelekezo mawilimawili',
 'doubleredirectstext' => 'Ukurasa huu unaorodhesha kurasa zinazoelekeza kurasa zingine za kuelekeza.
 Katika kila mstari kuna viungo vinavyokwenda katika kurasa za kuelekeza zote mbili, pamoja na ukurasa wa mwishilio mwa elekezo la pili. Ukurasa huu wa mwishilio huwa ni ukurasa unaostahili kuelekezwa kutoka kwa ukurasa wa kuelekeza wa kwanza. Vitu <del>vilivyokatwa kwa mstari</del> vimeshatatuliwa.',
@@ -2183,7 +2193,7 @@ $1',
 'contributions' => 'Michango ya {{GENDER:$1|mtumiaji}}',
 'contributions-title' => 'Michango ya mtumiaji $1',
 'mycontris' => 'Michango',
-'contribsub2' => 'Kwa $1 ($2)',
+'contribsub2' => 'Kwa {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Mabadiliko yanayolingana na vigezo vilivyoulizwa hayakupatikana.',
 'uctop' => '(ya kisasa)',
 'month' => 'Kutoka mwezi (na zamani zaidi):',
@@ -2416,7 +2426,7 @@ Ukipeleka haririo ya kisasa tu, unaweza kutumia kiungo kinachokwenda ukurasa wa
 'allmessagesdefault' => 'Ujumbe uliopo bidhaa pepe',
 'allmessagescurrent' => 'Ujumbe unapo sasa hivi',
 'allmessagestext' => 'Hii ni orodha ya jumbe za mfumo zilizopo katika eneo la MediaWiki.
-Ukitaka kusaidia kazi ya kutohoa MediaWiki yote katika lugha nyingi, tafadhali uende tovuti ya [//www.mediawiki.org/wiki/Localisation Kutohoa MediaWiki Kwenye Lugha Nyingi] na [//translatewiki.net translatewiki.net].',
+Ukitaka kusaidia kazi ya kutohoa MediaWiki yote katika lugha nyingi, tafadhali uende tovuti ya [https://www.mediawiki.org/wiki/Localisation Kutohoa MediaWiki Kwenye Lugha Nyingi] na [//translatewiki.net translatewiki.net].',
 'allmessagesnotsupportedDB' => "Ukurasa huu hauwezi kutumika kwa sababu '''\$wgUseDatabaseMessages''' imelemazwa.",
 'allmessages-filter-legend' => 'Chuja',
 'allmessages-filter' => 'Zichujwe kwa hali ya kutengenezwa:',
@@ -2591,7 +2601,7 @@ Ukilitekeleza faili, mashine yako huenda ikawa matatani.',
 'file-info-size-pages' => 'Piseli $1 × $2, ukubwa wa faili: $3, aina ya MIME: $4, {{PLURAL:$5|ukurasa|kurasa}} $5',
 'file-nohires' => 'Hakuna saizi kubwa zaidi.',
 'svg-long-desc' => 'faili la SVG, husemwa kuwa piseli $1 × $2, saizi ya faili: $3',
-'show-big-image' => 'Ukubwa wa awali',
+'show-big-image' => 'Faili lenyewe',
 'show-big-image-preview' => 'Ukubwa wa hakikisho: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Ukubwa mwingine|Ukubwa zingine}}: $1.',
 'show-big-image-size' => 'piseli $1 × $2',
@@ -2840,7 +2850,7 @@ likifupishwa. Nyuga zingine zitafichwa kama chaguo-msingi.
 
 # External editor support
 'edit-externally' => 'Tumia programu ya nje kuhariri faili hii',
-'edit-externally-help' => '(Ona [//www.mediawiki.org/wiki/Manual:External_editors maelezo (kwa Kiingereza)] kwa maarifa mengine.)',
+'edit-externally-help' => '(Ona [https://www.mediawiki.org/wiki/Manual:External_editors maelezo (kwa Kiingereza)] kwa maarifa mengine.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'zote',
@@ -3008,7 +3018,7 @@ Pia unaweza [[Special:EditWatchlist|kutumia kihariri cha kawaida]].',
 'version-other' => 'Zingine',
 'version-version' => '(Toleo $1)',
 'version-license' => 'Ruhusa',
-'version-poweredby-credits' => "Wiki hii inaendeshwa na bidhaa pepe ya '''[//www.mediawiki.org/ MediaWiki]''', hakimiliki © 2001-$1 $2.",
+'version-poweredby-credits' => "Wiki hii inaendeshwa na bidhaa pepe ya '''[https://www.mediawiki.org/ MediaWiki]''', hakimiliki © 2001-$1 $2.",
 'version-poweredby-others' => 'wengine',
 'version-license-info' => 'MediaWiki ni bidhaa pepe huru; unaweza kuisambaza pamoja na kuitumia na kuibadilisha kutokana na masharti ya leseni ya GNU General Public License inayotolewa na Free Software Foundation (Shirika la Bidhaa Pepe Huru); ama toleo 2 la hakimiliki, ama (ukitaka) toleo lolote linalofuata.
 
@@ -3033,8 +3043,7 @@ Huwa unapokea [{{SERVER}}{{SCRIPTPATH}}/COPYING nakala ya GNU General Public Lic
 
 # Special:SpecialPages
 'specialpages' => 'Kurasa maalum',
-'specialpages-note' => '----
-* Kurasa maalum za kawaida.
+'specialpages-note' => '* Kurasa maalum za kawaida.
 * <span class="mw-specialpagerestricted">Kurasa maalum zisizoonekana na wote.</span>
 * <span class="mw-specialpagecached">Kurasa maalum zinazotoka "cache" (might be obsolete).</span>',
 'specialpages-group-maintenance' => 'Ripoti za kurekebisha na kutunza kurasa',
@@ -3170,4 +3179,8 @@ Huwa unapokea [{{SERVER}}{{SCRIPTPATH}}/COPYING nakala ya GNU General Public Lic
 'duration-years' => '{{PLURAL:$1|mwaka|miaka}} $1',
 'duration-centuries' => '{{PLURAL:$1|karne}} $1',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Sawa',
+'expand_templates_preview' => 'Hakiki',
+
 );
index c70d627..e5c7f79 100644 (file)
@@ -13,6 +13,7 @@
  * @author Gaj777
  * @author Herr Kriss
  * @author Kaganer
+ * @author Krol111
  * @author Lajsikonik
  * @author Leinad
  * @author Lwh
@@ -69,15 +70,15 @@ $messages = array(
 'tog-justify' => 'Wyrůwnowej tekst we akapitach (justowańy)',
 'tog-hideminor' => 'Schow drobne pomjyńańa we ńydowno pomjyńanych',
 'tog-hidepatrolled' => 'Schow sprowdzůne sprowjyńa we ńydowno pomjyńanych',
-'tog-newpageshidepatrolled' => 'Schow sprowdzůne zajty na wykoźe nowych zajtůw',
-'tog-extendwatchlist' => 'Pokoż na mojij pozůrliśće wszyjske, a ńyjyno uostatńe sprowjyńa',
+'tog-newpageshidepatrolled' => 'Schow sprawdzůne zajty na wykoźe nowych zajtůw',
+'tog-extendwatchlist' => 'Pokoż na mojij pozůrliśće wszyjske, a ńy jyno uostatńe sprowjyńa',
 'tog-usenewrc' => 'Używej poszyrzyńo ńydowno pomjyńanych (JavaScript)',
 'tog-numberheadings' => 'Automatyczno numeracyjo titlůw',
 'tog-showtoolbar' => 'Pokoż gurt werkcojgůw (JavaScript)',
-'tog-editondblclick' => 'Edycja napoczynajům dwa klikńyńća (JavaScript)',
+'tog-editondblclick' => 'Edycyjo napoczynajům dwa klikńyńća (JavaScript)',
 'tog-editsection' => 'Kożdo tajla zajty sprowjano uosobno',
-'tog-editsectiononrightclick' => 'Klikńyńće prawym kneflym myszy na titlu tajli<br />napoczyno jego sprowjańy(JavaScript)',
-'tog-showtoc' => 'Pokoż spis treśći (na zajtach, kere majům wjyncy jak trzi tajle)',
+'tog-editsectiononrightclick' => 'Klikńyńće prawym kneflym myszy na titlu tajli<br />napoczyno jigo sprowjańy(JavaScript)',
+'tog-showtoc' => 'Pokoż spis treśći (na zajtach, kere majům wjyncyj kej trzi tajle)',
 'tog-rememberpassword' => 'Pamjyntej můj ausdruk na tym kůmputrze (nojdalij bez $1 {{PLURAL:$1|dźyń|dńůw}})',
 'tog-watchcreations' => 'Dowům pozůr na zajty, kere żech naszkryfloł',
 'tog-watchdefault' => 'Dowům pozůr na zajty, kere żech sprowjoł',
@@ -88,13 +89,13 @@ $messages = array(
 'tog-previewonfirst' => 'Obźyrej zajta przi pjyrszym sprowjańu',
 'tog-nocache' => 'Wypńij podrynczno pamjyńć',
 'tog-enotifwatchlistpages' => 'Wyślij e-brifa, kej ftoś zmjyńi zajta, na kero dowom pozůr',
-'tog-enotifusertalkpages' => 'Wyślij e-brifa, kej zajta mojij godki bydźe pomjyńono',
+'tog-enotifusertalkpages' => 'Wyślij e-brifa, kej zajta mojij godki bydźe půmjyńono',
 'tog-enotifminoredits' => 'Wyślij e-brifa tyż, kej by szło uo drobne pomjyńańa',
 'tog-enotifrevealaddr' => 'Ńy chow mojigo e-brifa we powjadomjyńach',
 'tog-shownumberswatching' => 'Pokoż, wjela sprowjorzy dowo pozůr',
 'tog-oldsig' => 'Teroźni wyglůnd Twojygo szrajbowańo',
-'tog-fancysig' => 'Szrajbńij s kodůma wiki (bez autůmatycznygo linka)',
-'tog-uselivepreview' => 'Używej dynamiczne uobźyrańy (JavaScript) (eksperymentalny)',
+'tog-fancysig' => 'Szrajbńij ze kodůma wiki (bez autůmatycznygo linka)',
+'tog-uselivepreview' => 'Używej dynamiczne uobźyrańy (JavaScript) (ekszperymentalny)',
 'tog-forceeditsummary' => 'Pedź, kejbych ńic ńy naszkryfloł we uopiśe pomjyńań',
 'tog-watchlisthideown' => 'Schow moje pomjyńańa we artiklach, na kere dowom pozůr',
 'tog-watchlisthidebots' => 'Schow pomjyńańa sprowjone bez boty we artiklach, na kere dowom pozůr',
@@ -103,9 +104,11 @@ $messages = array(
 'tog-watchlisthideanons' => 'Schow sprowjyńa anůńimowych sprowjoczy na liśće artikli, na kere dowom pozůr',
 'tog-watchlisthidepatrolled' => 'Schowej sprowdzůne sprowjyńa na pozorliśće',
 'tog-ccmeonemails' => 'Przesyłej mi kopje e-brifůw co żech je posłoł inkszym sprowjaczom',
-'tog-diffonly' => 'Å\83y pokozuj treÅ\9bÄ\87i zajtůw půnižyj porůwnańo pomjyńań',
+'tog-diffonly' => 'Å\83y pokozuj treÅ\9bÄ\87i zajtůw půniżyj porůwnańo pomjyńań',
 'tog-showhiddencats' => 'Pokoż schowane kategoryje',
 'tog-norollbackdiff' => 'Uomiń pokozywańy pomjyńań po użyću funkcyje „cofej”',
+'tog-useeditwarning' => 'Uostrzegej mje, kej uopuszczom zajta edycyji bez spamjyntańo půmjań',
+'tog-prefershttps' => 'Zowdy używej pewne połůnczyńe przi logowańu',
 
 'underline-always' => 'Dycki',
 'underline-never' => 'Ńigdy',
@@ -135,11 +138,11 @@ $messages = array(
 'sat' => 'Sob',
 'january' => 'styczyń',
 'february' => 'luty',
-'march' => 'merc',
+'march' => 'marzec',
 'april' => 'kwjećyń',
 'may_long' => 'moj',
-'june' => 'czyrwjyń',
-'july' => 'lipjyń',
+'june' => 'czyrwjyc',
+'july' => 'lipjyc',
 'august' => 'śyrpjyń',
 'september' => 'wrześyń',
 'october' => 'paźdźerńik',
@@ -147,19 +150,19 @@ $messages = array(
 'december' => 'grudźyń',
 'january-gen' => 'styczńa',
 'february-gen' => 'lutygo',
-'march-gen' => 'merca',
+'march-gen' => 'marca',
 'april-gen' => 'kwjetńa',
-'may-gen' => 'maja',
-'june-gen' => 'czyrwńa',
-'july-gen' => 'lipńa',
+'may-gen' => 'moja',
+'june-gen' => 'czyrwca',
+'july-gen' => 'lipca',
 'august-gen' => 'śyrpńa',
-'september-gen' => 'wrześńa',
+'september-gen' => 'wrzyśńa',
 'october-gen' => 'paźdźerńika',
 'november-gen' => 'listopada',
 'december-gen' => 'grudńa',
 'jan' => 'sty',
 'feb' => 'lut',
-'mar' => 'mer',
+'mar' => 'mar',
 'apr' => 'kwj',
 'may' => 'moj',
 'jun' => 'czy',
@@ -169,12 +172,21 @@ $messages = array(
 'oct' => 'paź',
 'nov' => 'lis',
 'dec' => 'gru',
+'january-date' => '$1 styczńa',
+'february-date' => '$1 lutygo',
+'april-date' => '$1 kwjytńa',
+'may-date' => '$1 moja',
+'june-date' => '$1 czyrwca',
+'august-date' => '$1 śyrpńa',
+'september-date' => '$1 wrzyśńa',
+'october-date' => '$1 paźdźyrńika',
+'december-date' => '$1 grudńa',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|Kategoryjo|Kategoryje|Kategoryj}}',
+'pagecategories' => '{{PLURAL:$1|Kategoryjo|Kategoryje|Kategoryji}}',
 'category_header' => 'Zajty we katygoryji "$1"',
 'subcategories' => 'Podkatygoryje',
-'category-media-header' => 'Pliki w katygoryji "$1"',
+'category-media-header' => 'Pliki we katygoryji "$1"',
 'category-empty' => "''Terozki w tyj katygoryji sům żodne artikle a pliki''",
 'hidden-categories' => '{{PLURAL:$1|Schowano katygoryjo|Schowane katygoryje|Schowanych katygoryj}}',
 'hidden-category-category' => 'Schowane katygoryje',
@@ -182,7 +194,7 @@ $messages = array(
 'category-subcat-count-limited' => 'Ta katygoryjo mo {{PLURAL:$1|tako podkatygoryjo|$1 podkatygoryje|$1 podkatygoryji}}.',
 'category-article-count' => '{{PLURAL:$2|W tyj katygoryji je jyno jydno zajta.|W katygoryji {{PLURAL:$1|je ukozano $1 zajta|sům ukozane $1 zajty|je ukozanych $1 zajtůw}} ze cołkij wjelośći $2 zajtůw.}}',
 'category-article-count-limited' => 'W katygoryji {{PLURAL:$1|je pokozano $1 zajta|sům pokozane $1 zajty|je pokazanych $1 zajtůw}}.',
-'category-file-count' => '{{PLURAL:$2|W katygoryji snojduje śe jydyn plik.|W katygoryji {{PLURAL:$1|je pokozany $1 plik|sům pokozane $1 pliki|je pokozanych $1 plikůw}} s cołkyj liczby $2 plikůw.}}',
+'category-file-count' => '{{PLURAL:$2|W katygoryji znojduje śe jydyn plik.|W katygoryji {{PLURAL:$1|je pokozany $1 plik|sům pokozane $1 pliki|je pokozanych $1 plikůw}} ze cołkyj liczby $2 plikůw.}}',
 'category-file-count-limited' => 'W katygoryji {{PLURAL:$1|je pokozany $1 plik|sům pokozane $1 pliki|je pokozanych $1 plikůw}}.',
 'listingcontinuesabbrev' => 'ć.d.',
 'index-category' => 'Indeksowane zajty',
@@ -193,9 +205,10 @@ $messages = array(
 'article' => 'zajta',
 'newwindow' => '(uodwjyro śe we nowym uokńe)',
 'cancel' => 'Uodćepej',
-'moredotdotdot' => 'Wjyncy...',
-'mypage' => 'Moja zajta',
-'mytalk' => 'Mojo dyskusyjo',
+'moredotdotdot' => 'Wjyncyj...',
+'morenotlisted' => 'Ńy je to kůmplytno lista',
+'mypage' => 'Zajta',
+'mytalk' => 'Dyskusyjo',
 'anontalk' => 'Godka tygo IP',
 'navigation' => 'Nawigacyjo',
 'and' => '&#32;a',
@@ -206,7 +219,7 @@ $messages = array(
 'qbedit' => 'Sprowjej',
 'qbpageoptions' => 'Ta zajta',
 'qbmyoptions' => 'Moje zajty',
-'qbspecialpages' => 'Szpecyjalne zajty',
+'qbspecialpages' => 'Szpecyjolne zajty',
 'faq' => 'FAQ',
 'faqpage' => 'Project:FAQ',
 
@@ -217,7 +230,7 @@ $messages = array(
 'vector-action-protect' => 'Zawrzij',
 'vector-action-undelete' => 'Wćep',
 'vector-action-unprotect' => 'Uodymkńij',
-'vector-simplesearch-preference' => 'Włącz zaawansowane podpowiedzi wyszukiwania (tylko dla skórki Wektor)',
+'vector-simplesearch-preference' => 'Używej zaawansowane podpowjedźi sznupańo (ino lo skůrki Wektor)',
 'vector-view-create' => 'Stwůrz',
 'vector-view-edit' => 'Sprowjej',
 'vector-view-history' => 'Uobocz gyszichta',
@@ -227,6 +240,7 @@ $messages = array(
 'namespaces' => 'Raumy mjan',
 'variants' => 'Warjanty',
 
+'navigation-heading' => 'Menu nawigacyji',
 'errorpagetitle' => 'Feler',
 'returnto' => 'Nazod do zajty $1.',
 'tagline' => 'Ze {{GRAMMAR:D.lp|{{SITENAME}}}}',
@@ -238,9 +252,9 @@ $messages = array(
 'history' => 'Gyszichta zajty',
 'history_short' => 'Gyszichta',
 'updatedmarker' => 'pomjyńane uod uostatńij wizyty',
-'printableversion' => 'Wersyjo do durku',
+'printableversion' => 'Wersyjo do druku',
 'permalink' => 'Link do tyj wersyje zajty',
-'print' => 'Durkuj',
+'print' => 'Drukuj',
 'view' => 'Podglůnd',
 'edit' => 'Sprowjej',
 'create' => 'Stwůrz',
@@ -248,17 +262,18 @@ $messages = array(
 'create-this-page' => 'Stwůrz ta zajta',
 'delete' => 'Wyćep',
 'deletethispage' => 'Wyćep ta zajta',
+'undeletethispage' => 'Prziwrůć ta zajta',
 'undelete_short' => 'Wćep nazod {{PLURAL:$1|jedna wersyjo|$1 wersyje|$1 wersyji}}',
 'viewdeleted_short' => '{{PLURAL:$1|jedna wyćepano wersyjo|$1 wyćepane wersyje|$1 wyćepanych wersyjůw}}',
 'protect' => 'Zawrzij',
 'protect_change' => 'půmjyń',
-'protectthispage' => 'Zawřij ta zajta',
+'protectthispage' => 'Zawrzij ta zajta',
 'unprotect' => 'Uodymkńij',
 'unprotectthispage' => 'Uodymkńij ta zajta',
 'newpage' => 'Nowy artikel',
 'talkpage' => 'Godej uo tym artiklu',
 'talkpagelinktext' => 'dyskusyjo',
-'specialpage' => 'Špecyjalno zajta',
+'specialpage' => 'Szpecyjolno zajta',
 'personaltools' => 'Perzůnolne',
 'postcomment' => 'Skůmyntuj',
 'articlepage' => 'Zajta artikla',
@@ -267,14 +282,14 @@ $messages = array(
 'toolbox' => 'Werkcojg',
 'userpage' => 'Zajta sprowjorza',
 'projectpage' => 'Zajta projekta',
-'imagepage' => 'Zobejrz zajte pliku',
+'imagepage' => 'Uobejrz zajta pliku',
 'mediawikipage' => 'Zajta komuńikata',
-'templatepage' => 'Zajta šablůna',
-'viewhelppage' => 'Zajta pomocy',
+'templatepage' => 'Zajta mustra',
+'viewhelppage' => 'Zajta půmocy',
 'categorypage' => 'Zajta katygoryji',
 'viewtalkpage' => 'Zajta godki',
 'otherlanguages' => 'We inkszych godkach',
-'redirectedfrom' => '(Punkńyńto s $1)',
+'redirectedfrom' => '(Punkńyńto ze $1)',
 'redirectpagesub' => 'Zajta przekerowujůnco',
 'lastmodifiedat' => 'Ta zajta bůła uostatńo sprowjano $2, $1.',
 'viewcount' => 'W ta zajta filowano {{PLURAL:$1|tylko roz|$1 rozůw}}.',
@@ -282,17 +297,17 @@ $messages = array(
 'jumpto' => 'Przyńdź do:',
 'jumptonavigation' => 'nawigacyje',
 'jumptosearch' => 'sznupańo',
-'view-pool-error' => 'Felerńe, syrwyry sům przecionżone.
+'view-pool-error' => 'Felerńe, syrwyry sům przećůnżone.
 
 $1',
-'pool-timeout' => 'Zbyt długi czas oczekiwania na blokadę',
-'pool-queuefull' => 'Kolejka zadań jest pełna',
-'pool-errorunknown' => 'Feler ńyznany',
+'pool-timeout' => 'Za dugi czas uoczekiwańo na blokada',
+'pool-queuefull' => 'Kolyjność zadań je pełno',
+'pool-errorunknown' => 'Feler ńyznony',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Uo {{GRAMMAR:MS.lp|{{SITENAME}}}}',
 'aboutpage' => 'Project:Uo serwiśe',
-'copyright' => 'Tekst udostympńany na licencyji $1.',
+'copyright' => 'Tekst udostympńany na licencyji $1, eli inakszyj ńy podano.',
 'copyrightpage' => '{{ns:project}}:Autorske prawa',
 'currentevents' => 'Aktualne przitrefjyńa',
 'currentevents-url' => 'Project:Aktualne przitrefjyńa',
@@ -302,24 +317,26 @@ $1',
 'helppage' => 'Help:Treść',
 'mainpage' => 'Przodńo zajta',
 'mainpage-description' => 'Przodńo zajta',
-'policy-url' => 'Project:Prawidua',
+'policy-url' => 'Project:Prawidła',
 'portal' => 'Portal używoczůw',
 'portal-url' => 'Project:Portal używoczůw',
 'privacy' => 'Prawidła chrůńyńo prywotnośći',
 'privacypage' => 'Project:Prawidła chrůńyńo prywotnośći',
 
 'badaccess' => 'Felerne uprawńyńo',
-'badaccess-group0' => 'Ńy moš uprawńyń coby wykůnać ta uoperacyjo.',
-'badaccess-groups' => 'Ta uoperacyjo mogům wykůnaÄ\87 ino užytkownicy s keryjś z grup {{PLURAL:$2|grupa|grupy}}:$1.',
+'badaccess-group0' => 'Ńy mosz uprawńyń coby wykůnać ta uoperacyjo.',
+'badaccess-groups' => 'Ta uoperacyjo mogům wykůnaÄ\87 ino użytkownicy ze keryjś z grup {{PLURAL:$2|grupa|grupy}}:$1.',
 
 'versionrequired' => 'Wymagano MediaWiki we wersyji $1',
-'versionrequiredtext' => 'Wymagano jest MediaWiki we wersji $1 coby skořistać s tyj zajty. Uoboč [[Special:Version]]',
+'versionrequiredtext' => 'Wymagano jest MediaWiki we wersji $1 coby skorzistać zr tyj zajty. Uobocz [[Special:Version]]',
 
 'ok' => 'OK',
 'retrievedfrom' => 'Zdrzůdło "$1"',
 'youhavenewmessages' => 'Mosz $1 ($2).',
-'newmessageslink' => 'nowe powjadůmjyńa',
-'newmessagesdifflink' => 'uostatńe pomjyńyńy',
+'youhavenewmessagesfromusers' => 'Mosz $1 uod {{PLURAL:$3|inszygo używocza|$3 używoczy}} ($2).',
+'youhavenewmessagesmanyusers' => 'Mosz $1 uod wjelu używoczy ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|jedno nowina|999=nowiny}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|uostatńe sprowjyńe|999=uostatńe sprowjyńa}}',
 'youhavenewmessagesmulti' => 'Mosz nowe powjadůmjyńa: $1',
 'editsection' => 'Sprowjej',
 'editold' => 'sprowjej',
@@ -328,28 +345,28 @@ $1',
 'viewsourcelink' => 'zdrzůdłowy tekst',
 'editsectionhint' => 'Sprowjej tajla: $1',
 'toc' => 'Treść',
-'showtoc' => 'pokož',
+'showtoc' => 'uobejrzij',
 'hidetoc' => 'schrůń',
 'collapsible-collapse' => 'Zwjyń',
 'collapsible-expand' => 'Rozwjyń',
-'thisisdeleted' => 'Pokož/wćepej nazod $1',
-'viewdeleted' => 'Uobejřij $1',
+'thisisdeleted' => 'Pokoż/wćepej nazod $1',
+'viewdeleted' => 'Uobejrzij $1',
 'restorelink' => '{{PLURAL:$1|jedna wyćepano wersyjo|$1 wyćepane wersyje|$1 wyćepanych wersyjůw}}',
-'feedlinks' => 'Kanauy:',
-'feed-invalid' => 'Ńywuaściwy typ kanauů informacyjnygo.',
-'feed-unavailable' => 'Kanouy informacyjne ńy sům dostympne',
-'site-rss-feed' => 'Kanau RSS {{GRAMMAR:D.lp|$1}}',
+'feedlinks' => 'Kanały:',
+'feed-invalid' => 'Ńywłaściwy typ kanałů informacyjnygo.',
+'feed-unavailable' => 'Kanoły informacyjne ńy sům dostympne',
+'site-rss-feed' => 'Kan RSS {{GRAMMAR:D.lp|$1}}',
 'site-atom-feed' => 'Kanoł Atom {{GRAMMAR:D.lp|$1}}',
-'page-rss-feed' => 'Kanau RSS "$1"',
+'page-rss-feed' => 'Kan RSS "$1"',
 'page-atom-feed' => 'Kanoł Atom "$1"',
 'red-link-title' => '$1 (ńy mo zajty)',
-'sort-descending' => 'Sortuj malejąco',
-'sort-ascending' => 'Sortuj rosnąco',
+'sort-descending' => 'Sortuj pomńijszajůnco',
+'sort-ascending' => 'Sortuj rosnůnco',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Zajta',
 'nstab-user' => '{{GENDER:{{BASEPAGENAME}}|Zajta używocza|Zajta używoczki}}',
-'nstab-media' => 'Medja',
+'nstab-media' => 'Pliki',
 'nstab-special' => 'Ekstra zajta',
 'nstab-project' => 'Zajta projektu',
 'nstab-image' => 'Plik',
@@ -361,21 +378,26 @@ $1',
 # Main script and global functions
 'nosuchaction' => 'Ńy mo takij uoperacyji',
 'nosuchactiontext' => 'Uoprogramowańy ńy rozpoznowo uoperacyji takij kej podano w URL.',
-'nosuchspecialpage' => 'Ńy mo takij špecyjalnyj zajty',
-'nospecialpagetext' => '<strong>Uoprogramowańy ńy rozpoznowo takij špecyjalnyj zajty.</strong>
+'nosuchspecialpage' => 'Ńy mo takij szpecyjolnyj zajty',
+'nospecialpagetext' => '<strong>Uoprogramowańy ńy rozpoznowo takij szpecyjalnyj zajty.</strong>
 
-Lista špecyjalnych zajtůw znejdźeš na [[Special:SpecialPages|{{int:specialpages}}]].',
+Lista szpecyjalnych zajtůw znojdźesz na [[Special:SpecialPages|{{int:specialpages}}]].',
 
 # General errors
 'error' => 'Feler',
 'databaseerror' => 'Feler bazy danych',
-'laggedslavemode' => 'Dej pozůr: Ta zajta može ńy mjeć nojnowšych aktualizacyjůw.',
+'databaseerror-text' => 'Pojawjůł śe feler przi wysyłańu zapytańa do bazy danych. Mogebność je, aże je to feler we uoprogramowańu.',
+'databaseerror-textcl' => 'Pojawjůł śe feler przi wysyłańu zapytańa do bazy danych.',
+'databaseerror-query' => 'Zapytańe: $1',
+'databaseerror-function' => 'Funkcyjo: $1',
+'databaseerror-error' => 'Feler: $1',
+'laggedslavemode' => 'Dej pozůr: Ta zajta może ńy mjeć nojnowszych aktualizacyjůw.',
 'readonly' => 'Baza danych je zawarto',
-'enterlockreason' => 'Naškryflej sam powůd zawarća bazy danych a za wjela (myńi-wjyncyj) ja uodymkńeš',
+'enterlockreason' => 'Naszkryflej sam powůd zawarćo bazy danych a za wjela (myńi-wjyncyj) ja uodymkńesz',
 'readonlytext' => 'Baza danych jest terozki zawarto
-- Å\84y do Å\9be wÄ\87epywaÄ\87 nowych artikli Å\84i sprowjaÄ\87 juž wćepanych. Powodym
-sům prawdopodańy čynnośći admińistracyjne. Po jejich zakůńčeńu pouno funkcjonalność bazy bydźe přywrůcono.
-Administrator, kery zablokowou baza, podou takie wyjaśńyńy:<br /> $1',
+- Å\84y do Å\9be wÄ\87epywaÄ\87 nowych artikli Å\84i sprowjaÄ\87 już wćepanych. Powodym
+sům prawdopodańy czynnośći admińistracyjne. Po jejich zakůńczyńu cołko funkcjonalność bazy bydźe prziwrůcono.
+Administrator, kery zablokowoł baza, podoł takie wyjaśńyńy:<br /> $1',
 'missing-article' => 'W databaźe ńy idzie nolyźć treść zajty „$1” $2.
 
 Uobwykle je to spůsobiůne tym, że sznupoł żeś po ńyaktualnym linku na zmjyny mjyndzy půmjyńańami, abo do wyćepanyj wersyje z gyszichty sprowjyń zajty.
@@ -383,51 +405,56 @@ Uobwykle je to spůsobiůne tym, że sznupoł żeś po ńyaktualnym linku na zmj
 Eli tak ńy je, możno śe trefił feler we softwaru MediaWiki. Kej ja, pedz uo tym [[Special:ListUsers/sysop|admińistratorowi]] a podej mu adres URL.',
 'missingarticle-rev' => '(wersyjo#: $1)',
 'missingarticle-diff' => '(dyferencyjo: $1, $2)',
-'readonly_lag' => 'Baza danych zostoua automatyčńy zawarto na čas potřebny na synchrońizacyjo zmjan mjyndzy serwerym guůwnym a serwerami postředńičůncymi.',
-'internalerror' => 'Wewnyntřny feler',
-'internalerror_info' => 'Wewnytřny feler: $1',
+'readonly_lag' => 'Baza danych zostoła automatyczńy zawarto na czas potrzebny na synchrońizacyjo zmjan mjyndzy serwerym głůwnym a serwerami postrzedńiczůncymi.',
+'internalerror' => 'Wewnyntrzny feler',
+'internalerror_info' => 'Wewnytrzny feler: $1',
 'fileappenderrorread' => 'Feler uodczytu "$1".',
 'fileappenderror' => 'Ńy idźe skopjować plika "$1" do "$2".',
 'filecopyerror' => 'Ńy idźe skopjować plika "$1" do "$2".',
 'filerenameerror' => 'Ńy idźe zmjyńić mjana plika "$1" na "$2".',
 'filedeleteerror' => 'Ńy idźe wyćepać plika "$1".',
-'directorycreateerror' => 'Ńy idźe utwořić katalogu "$1".',
+'directorycreateerror' => 'Ńy idźe utworzić katalogu "$1".',
 'filenotfound' => 'Ńy idźe znejść plika "$1".',
 'fileexistserror' => 'Ńy idźe sprowjać we pliku "$1": plik istńeje',
 'unexpected' => 'Ńyspodźewano wartość: "$1"="$2".',
-'formerror' => 'Feler: ńy idźe wysuać formulařa',
+'formerror' => 'Feler: ńy idźe wysłać formulazra',
 'badarticleerror' => 'Tyj uoperacyje ńy idźe zrobić lo tyj zajty.',
 'cannotdelete' => 'Ńy idźe wyćepać podanyj zajty abo grafiki $1.',
 'cannotdelete-title' => 'Ńy idźie wyćepać zajty "$1".',
-'badtitle' => 'Felerno tytůua',
-'badtitletext' => 'Podano felerny titel zajty. Prawdopodańy sům w ńim znoki, kerych ńy wolno užywać we titlach abo je pusty.',
-'perfcached' => 'To co sam je naszkryflane, to ino kopja s pamjyńći podryncznyj a może ńy być aktualne. Nojwjyncyj {{PLURAL:$1|jydyn wynik je|$1 wyniki sům}} w tyj pamjyńći.',
+'delete-hook-aborted' => 'Wyćepywańe sztopńynte bez hak. Przyczyna ńyuokreślůno.',
+'badtitle' => 'Felerny titel',
+'badtitletext' => 'Podano felerny titel zajty. Prawdopodańy sům w ńim znoki, kerych ńy wolno używać we titlach abo je pusty.',
+'perfcached' => 'To co sam je naszkryflane, to ino kopja ze pamjyńći podryncznyj a może ńy być aktualne. Nojwjyncyj {{PLURAL:$1|jydyn wynik je|$1 wyniki sům}} we tyj pamjyńći.',
 'perfcachedts' => 'To co sam je naszkryflane, to ino kopja s pamjyńći podryncznyj a bůło uaktualńůne $1. Nojwjyncyj {{PLURAL:$4|jeden wynik je|$4 wyniki sům}} dostympne.',
-'querypage-no-updates' => 'UaktualÅ\84\84o lo tyj zajty sům terozki zawarte. Dane, kere sam sům, Å\84y zostouy uodÅ\9bwjyžůne.',
-'wrong_wfQuery_params' => 'Felerne parametry překozane do wfQuery()<br />
+'querypage-no-updates' => 'UaktualÅ\84\84o lo tyj zajty sům terozki zawarte. Dane, kere sam sům, Å\84y zostouy uodÅ\9bwjyżůne.',
+'wrong_wfQuery_params' => 'Felerne parametry przekozane do wfQuery()<br />
 Funkcyjo: $1<br />
 Zapytańy: $2',
 'viewsource' => 'Zdrzůdłowy tekst',
 'viewsource-title' => 'Uobocz zdrzůdło lo $1',
-'actionthrottled' => 'Akcyjo wstřimano',
-'actionthrottledtext' => 'Mechańizm uobrůny před spamym uograńičo ličba wykonań tyj čynnośći we jednostce času. Průbowoužeś go uocygańić. Proša, sprůbuj na nowo za pora minut.',
+'actionthrottled' => 'Akcyjo wstrzimano',
+'actionthrottledtext' => 'Mechańizm uobrůny przed spamym uograńiczo liczba wykonań tyj czynnośći we jednostce czasu. Průbowołżeś go uocygańić. Prosza, sprůbuj na nowo za pora minut.',
 'protectedpagetext' => 'Ta zajta je zawarto przed sprowjańym.',
 'viewsourcetext' => 'We tekst zdrzůduowy tyj zajty możno dali filować, idźe go tyż kopjyrować.',
 'viewyourtext' => 'We tekst zdrzůduowy tyj zajty możno dali filować, idźe go tyż kopjować.',
-'protectedinterface' => 'Na tyj zajće znojduje śe tekst interfejsu uoprogramowańo, bestož uůna je zawarto uod sprowjańo.',
-'editinginterface' => "''''Dej pozůr:''' Sprowjosz zajta, na keryj je tekst interfejsu uoprogramowańo. Pomjyńyńa na tyj zajće zmjyńům wyglůnd interfejsu lo inkšych užytkowńikůw.",
-'cascadeprotected' => 'Ta zajta je zawarto uod sprowjańo, po takymu, co uůna je zauončono na {{PLURAL:$1|nastympujůncyj zajće, kero zostaua zawarto|nastympujůncych zajtach, kere zostauy zawarte}} ze zauončonům opcyjům dźedźičyńo:
+'protectedinterface' => 'Na tyj zajće znojduje śe tekst interfejsu uoprogramowańo, bestůż uůna je zawarto uod sprowjańo. Coby doćepnůńć abo sprowjić tůmaczyńa wszyskich serwerůw, użyj [//translatewiki.net/ translatewiki.net], průjyktu lokalizacyji MediaWiki.',
+'editinginterface' => "''''Dej pozůr:''' Sprowjosz zajta, na keryj je tekst interfejsu uoprogramowańo. Pomjyńyńa na tyj zajće zmjyńům wyglůnd interfejsu lo inkszych użytkowńikůw. Coby doćepnůńć abo sprowjić tůmaczyńa, użyj [//translatewiki.net/wiki/Main_Page?setlang=szl translatewiki.net].",
+'cascadeprotected' => 'Ta zajta je zawarto uod sprowjańo, po takymu, co uůna je załůnczůno na {{PLURAL:$1|nastympujůncyj zajće, kero zostoła zawarto|nastympujůncych zajtach, kere zostoły zawarte}} ze załůnczůnům uopcyjům dźedźiczyńo:
 $2',
-'namespaceprotected' => "Ńy moš uprowńyń, coby sprowjać zajty we přestřeńi mjan '''$1'''.",
+'namespaceprotected' => "Ńy mosz uprowńyń, coby sprowjać zajty we raumje mjan '''$1'''.",
 'customcssprotected' => 'Ńy mosz uprawńyń do sprowjańo tyj zajty, bo na ńij sům uosobiste sztalowańo inkszego użytkowńika.',
 'customjsprotected' => 'Ńy mosz uprawńyń do sprowjańo tyj zajty, bo na ńij sům uosobiste sztalowańo inkszego użytkowńika.',
-'ns-specialprotected' => 'Ńy idźe sprowjać zajtůw we přestřyni mjan {{ns:special}}.',
+'mycustomcssprotected' => 'Ńy mosz uprawńyń do sprowjańo tyj zajty CSS.',
+'mycustomjsprotected' => 'Ńy mosz uprawńyń do sprowjańo tyj zajty JavaScript.',
+'ns-specialprotected' => 'Ńy idźe sprowjać zajtůw we przestrzyni mjan {{ns:special}}.',
 'titleprotected' => "Wćepańy sam zajty uo takim mjańe zawar [[User:$1|$1]].
 Powůd zawarćo: ''$2''.",
 'filereadonlyerror' => 'Ńy idźe pomjyńać plika "$1" abo repozytorjum "$2" terozki je zawarte.
 
 Administrator kery zawarł wćepał kůmyntorz: "$3".',
 'invalidtitle-knownnamespace' => 'Felerne mjano "$3" w przestrzeńy "$2".',
+'exception-nologin' => 'Ńy jest żeś zalogůwany',
+'exception-nologin-text' => 'Prosza [[Special:Userlogin|zaloguj śe]] coby mjeć mogebność przejśćo do tyj zajty abo akcyji.',
 
 # Virus scanner
 'virus-badscanner' => "Felerno konfiguracyjo – ńyznany skaner antywirusowy ''$1''",
@@ -435,105 +462,144 @@ Administrator kery zawarł wćepał kůmyntorz: "$3".',
 'virus-unknownscanner' => 'ńyznajůmy průgram antywirusowy',
 
 # Login and logout pages
-'logouttext' => "'''Terozki ježeś wylůgowany'''.
+'logouttext' => "'''Terozki jeżeś wylůgowany'''.
 
-Možeš dali sam sprowjać zajty we {{SITENAME}} kej ńyzalůgowany užytkowńik, abo <span class='plainlinks'>[$1 zalůgować śe nazod]</span> kej tyn som abo inkšy užytkowńik.
-Dej pozůr, co na ńykerych zajtach přeglůndarka može dali pokozywać co ježeś zalůgowany, a bydźe tak aže uodśwjyžyš jeij cache.",
+Dej pozůr, co na ńykerych zajtach przeglůndarka może dali pokozywać co jeżeś zalůgowany, a bydźe tak aże uodśwjyżysz jeij cache.",
+'welcomeuser' => 'Witej, $1',
+'welcomecreation-msg' => 'Uotwarli my sam lo Ćebje kůnto.
+Pamjyntej coby posztalować [[Special:Preferences|preferencyji]]',
 'yourname' => 'Mjano użytkowńika:',
+'userlogin-yourname' => 'Mjano używocza',
+'userlogin-yourname-ph' => 'Wszkryflej swoje mjano użytkowńika',
+'createacct-another-username-ph' => 'Wszkryflej mjano użytkowńika',
 'yourpassword' => 'Hasło:',
+'userlogin-yourpassword-ph' => 'Wszkryflej swoje hasło',
+'createacct-yourpassword-ph' => 'Wszkryflej hasło',
 'yourpasswordagain' => 'Naszkryflej ausdruk zaś',
+'createacct-yourpasswordagain' => 'Potwjyrdź hasło',
+'createacct-yourpasswordagain-ph' => 'Wszkryflej hasło jeszcze roz',
 'remembermypassword' => 'Pamjyntej můj ausdruk na tym kůmputrze (nojdalij bez $1 {{PLURAL:$1|dźyń|dńůw}})',
+'userlogin-remembermypassword' => 'Ńy wylogůwywuj mje',
+'userlogin-signwithsecure' => 'Użyj bezpjecznygo połůnczyńa',
 'yourdomainname' => 'Twoja domyna',
-'externaldberror' => 'Je jaki feler we zewnyntřnyj baźe autentyfikacyjnyj, abo ńy moš uprawńyń potřebnych do aktualizacyji zewnyntřnego kůnta.',
+'password-change-forbidden' => 'Ńy można půmjyńać haseł na tyj wiki.',
+'externaldberror' => 'Je jaki feler we zewnyntrznyj baźe autentyfikacyjnyj, abo ńy mosz uprawńyń potrzebnych do aktualizacyji zewnyntrznego kůnta.',
 'login' => 'Zaloguj śe',
-'nav-login-createaccount' => 'Logowańy / tworzińy kůnta',
-'loginprompt' => 'Muśisz mjeć zołůnczůne cookies coby můc śe sam zalůgować.',
-'userlogin' => 'Lůgowańy / Tworzyńy kůnta',
-'userloginnocreate' => 'Zalůguj śe',
+'nav-login-createaccount' => 'Logowańy / Tworzyńy kůnta',
+'loginprompt' => 'Muśisz mjeć załůnczůne cookies coby můc śe sam zalogować.',
+'userlogin' => 'Logowańy / Tworzyńy kůnta',
+'userloginnocreate' => 'Zaloguj śe',
 'logout' => 'Wyloguj',
 'userlogout' => 'Uodloguj śe',
-'notloggedin' => 'Ńy ježeś zalůgowany',
+'notloggedin' => 'Ńy jeżeś zalogowany',
+'userlogin-noaccount' => 'Ńy mosz kůnta?',
+'userlogin-joinproject' => 'Doćep śe do {{SITENAME}}',
 'nologin' => "Ńy mosz kůnta? '''$1'''.",
 'nologinlink' => 'Twůrz kůnto',
 'createaccount' => 'Twůrz nowe kůnto',
 'gotaccount' => "Mosz już kůnto? '''$1'''.",
 'gotaccountlink' => 'Naloguj śe',
 'userlogin-resetlink' => 'Zapomńoł żeś dane lo nalogowańo?',
-'createaccountmail' => 'e-brifym',
+'userlogin-resetpassword-link' => 'Ńy pamjyntosz hasła?',
+'helplogin-url' => 'Help:Logowańy',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Hilfa ze logowańym]]',
+'userlogin-loggedin' => 'Zalogowano kej {{GENDER:$1|$1}}. Użyj formulara půńiżyj, coby zalogować śe kej inkszy używocz.',
+'userlogin-createanother' => 'Twůrz inksze kůnto',
+'createacct-join' => 'Wszkryflej půńiżyj swoje dane.',
+'createacct-another-join' => 'Wszkryflej půńiżyj szczegůły nowygo kůnta.',
+'createacct-emailrequired' => 'E-brif',
+'createacct-emailoptional' => 'E-brif (uopcjůnalne)',
+'createacct-email-ph' => 'Wszkryflej swůj adres do e-brifa',
+'createacct-another-email-ph' => 'Nastow e-brif',
+'createaccountmail' => 'Użyj chwilowygo hasła losowo genyrowanygo a wyślij je na wrychtowany adres e-brifa.',
+'createacct-realname' => 'Prawdźiwe imje a nazwisko (uopcjůnalńe)',
 'createaccountreason' => 'Kůmyntorz:',
-'badretype' => 'Hasua kere žeś naškryflou ńy zgodzajům śe jydne s drugim.',
+'createacct-reason' => 'Powůd:',
+'createacct-reason-ph' => 'Pojakymu tworzisz nowe kůnta',
+'createacct-captcha' => 'Zicherkontrola',
+'createacct-imgcaptcha-ph' => 'Wszkryflej tekst, kery widoć powyżyj',
+'createacct-submit' => 'Twůrz kůnto',
+'createacct-another-submit' => 'Twůrz inksze kůnto',
+'createacct-benefit-heading' => '{{grammar:B.lp|{{SITENAME}}}} tworzům perzůny take kej Ty.',
+'createacct-benefit-body1' => '{{PLURAL:$1|edycyjo|edycyje|edycyji}}',
+'createacct-benefit-body2' => '{{PLURAL:$1|zajta|zajty|zajt}}',
+'createacct-benefit-body3' => '{{PLURAL:$1|używocz|używoczůw}} we uostatńim czaśe',
+'badretype' => 'Hasła kere żeś naszkryfloł ńy zgodzajům śe jydne ze drugim.',
 'userexists' => 'Mjano użytkowńika, kere żeś wybroł, je zajynte. Wybjer, prosza, inksze mjano.',
-'loginerror' => 'Feler při logůwańu',
+'loginerror' => 'Feler przi logowańu',
+'createacct-error' => 'Feler tworzyńo kůnta',
 'createaccounterror' => 'Ńy możno stworzić konta $1',
 'nocookiesnew' => 'Kůnto użytkowńika zostoło utworzůne, nale ńy jeżeś zalůgowany. {{SITENAME}} używo ćosteczek do logůwańo. Mosz wyłůnczone ćosteczka. Coby śe zalůgować, uodymknij ćosteczka a podej mjano a hasło swojigo kůnta.',
-'nocookieslogin' => '{{SITENAME}} užywo Ä\87osteÄ\8dek do lůgowaÅ\84o užytkowÅ\84ikůw. MoÅ¡ zablokowano jejich uobsuůga. Sprůbuj zaÅ\9b jak zauůnÄ\8dyÅ¡ uobsuůga Ä\87osteÄ\8dek.',
-'nocookiesfornew' => 'Konto sprowjorza ńy uostoło stworzone. Sprawdź, cze mosz uodymkńynto obsługe cookies.',
-'noname' => 'To ńy je půprowne mjano użytkowńika.',
-'loginsuccesstitle' => 'Lůgowańy udane',
-'loginsuccess' => "'''Terozki ježeÅ\9b zalůgowany do {{SITENAME}} jako \"\$1\".'''",
+'nocookieslogin' => '{{SITENAME}} używo Ä\87osteczek do logowaÅ\84o użytkowÅ\84ikůw. Mosz zablokowano jejich uobsÅ\82ůga. Sprůbuj zaÅ\9b kej zaÅ\82ůnczysz uobsÅ\82ůga Ä\87osteczek.',
+'nocookiesfornew' => 'Konto sprowjorza ńy uostoło stworzone. Sprawdź, co mosz uodymkńynto uobsługa cookies.',
+'noname' => 'To ńy je poprowne mjano użytkowńika.',
+'loginsuccesstitle' => 'Logowańy udane',
+'loginsuccess' => "'''Terozki jeżeÅ\9b zalogowany do {{SITENAME}} kej \"\$1\".'''",
 'nosuchuser' => 'Ńy ma sam użytkowńika uo mjańe "$1".
 Sprowdź szrajbůng, abo [[Special:UserLogin/signup|utwůrz nowe kůnto]].',
-'nosuchusershort' => 'Å\83y mo sam užytkowńika uo mjańe "$1".',
+'nosuchusershort' => 'Å\83y mo sam użytkowńika uo mjańe "$1".',
 'nouserspecified' => 'Podej mjano użytkowńika.',
-'login-userblocked' => 'Tyn sprowjorz ma zawrzite sprowjyńa. Ńy możno sie zalgować.',
+'login-userblocked' => 'Tyn sprowjorz ma zawrzite sprowjyńa. Ńy możno sie zalogować.',
 'wrongpassword' => 'Hasło kere żeś naszkryfloł je felerne. Poprůbůj naszkryflać je jeszcze roz.',
-'wrongpasswordempty' => 'Hasuo kere žeś podou je puste. Naškryflej je ješče roz.',
+'wrongpasswordempty' => 'Hasło kere żeś podou je uostawjůne blank. Naszkryflej je jeszcze roz.',
 'passwordtooshort' => 'Hasło kere żeś podoł je felerne abo za krůtke.
-Hasło muśi mjeć przinojmńij {{PLURAL:$1|1 buchsztaba|$1 buchsztabůw}} a być inksze od mjana użytkowńika.',
-'password-name-match' => 'Hasło musi być inne niż nazwa użytkownika.',
-'password-login-forbidden' => 'Ńy wolno mjyć takij nazwy a hasua.',
+Hasło muśi mjeć przinojmńij {{PLURAL:$1|1 buchsztaba|$1 buchsztabůw}} a być inksze uod mjana użytkowńika.',
+'password-name-match' => 'Hasło mo być inksze atoli mjano używocza.',
+'password-login-forbidden' => 'Mogebność wyboru tygo mjana używocza abo hasła je zawarte.',
 'mailmypassword' => 'Wyślij mi nowe hasło bez e-brif',
-'passwordremindertitle' => 'Nowe tymčasowe hasuo dla {{SITENAME}}',
-'passwordremindertext' => 'Ftůś (cheba Ty, s IP $1)
+'passwordremindertitle' => 'Nowe tymczasowe hasło lo {{SITENAME}}',
+'passwordremindertext' => 'Ftoś (cheba Ty, ze IP $1)
 pado, aże chce nowe hasło do {{SITENAME}} ($4).
 Lo użytkowńika "$2" wygenyrowano nowe hasło a je ńim "$3".
 Jak chćołżeś gynał to zrobjyć, to zalůgůj śe terozki a podej swoje hasło.
 Hasło wygaśnie za {{PLURAL:$5|1 dzień|$5 dni}}.
 
-Jak ktůś inkszy chćoł nowe hasło abo jak Ci śe przipůmńouo stare a ńy chcesz nowygo, to zignoruj to a używej starygo hasła.',
+Jak ftoś inkszy chćoł nowe hasło abo jak Ci śe przipůmńouo stare a ńy chcesz nowygo, to zignoruj to a używej starygo hasła.',
 'noemail' => 'Ńy mo u nos adresu e-brifa do "$1".',
-'noemailcreate' => 'Podaj dobry e-mail ausdruk',
-'passwordsent' => 'Nowe hasuo pošuo na e-brifa uod užytkowńika "$1".
-Zalůguj śe zaś jak dostańyš tygo brifa.',
-'blocked-mailpassword' => 'Twůj adres IP zostou zawarty a ńy možeš užywać funkcyje odzyskiwańo hasua skuli možliwośći jeji nadužywańo.',
+'noemailcreate' => 'Podej dobry e-mail ausdruk',
+'passwordsent' => 'Nowe hasło polozło na e-brifa uod użytkowńika "$1".
+Zaloguj śe zaś jak dostańysz tygo brifa.',
+'blocked-mailpassword' => 'Twůj adres IP zostoł zawarty a ńy moższ używać funkcyje uodzyskiwańo hasła skuli mogebnośći jeji nadużywańo.',
 'eauthentsent' => 'Potwjerdzeńy zostoło posłane na e-brifa.
-Jak bydźesz chćoł, coby wysyłouo Ći e-brify, pjyrwyj go przeczytej. Bydźesz tam mjoł instrukcyjo co mosz zrobić, coby pokozać, aże tyn ausdruk je Twůj.',
-'throttled-mailpassword' => 'Připůmńyńy hasua bůuo juž wysuane bez {{PLURAL:$1|uostatńo godźina|uostatńe $1 godźin}}.
-Coby powstřimać nadužyća, možliwość wysyuańa připůmńeń naštalowano na jydne bez {{PLURAL:$1|godźina|$1 godźiny}}.',
-'mailerror' => 'Při wysyuańu e-brifa zdořiu śe feler: $1',
-'acct_creation_throttle_hit' => 'Przikro nom, założył(a)żeś już {{PLURAL:$1|1 kůnto|$1 kůnta}}. Ńy możesz założyć kolejnygo.',
-'emailauthenticated' => 'Twůj adres e-brifa zostou uwjeřitelńůny $2 uo $3.',
-'emailnotauthenticated' => 'Twůj adres e-brifa ńy je uwjeřitelńůny. Půnižše funkcyje počty ńy bydům dźauać.',
-'noemailprefs' => 'Muśiš podać adres e-brifa, coby te funkcyje dźouauy.',
-'emailconfirmlink' => 'Potwjerdź swůj adres e-brifa',
-'invalidemailaddress' => 'E-brif Å\84y bydźe zaakceptůwany skiž tygo co jego format Å\84y speuÅ\84o formalnych wymagaÅ\84. ProÅ¡a naÅ¡kryflaÄ\87 poprowny adres e-brifa abo wyÄ\8dyśćić pole.',
+Jak bydźesz chćoł, coby wysyłoło Ći e-brify, pjyrwyj go przeczytej. Bydźesz tam mjoł instrukcyjo co mosz zrobić, coby pokozać, aże tyn ausdruk je Twůj.',
+'throttled-mailpassword' => 'Przipůmńyńy hasła bůło już wysłane bez {{PLURAL:$1|uostatńo godźina|uostatńe $1 godźin}}.
+Coby powstrzimać nadużyća, mogebność wysyłańo przipůmńyń nasztalowano na jydne bez {{PLURAL:$1|godźina|$1 godźiny}}.',
+'mailerror' => 'Przi wysyłańu e-brifa zdorził śe feler: $1',
+'acct_creation_throttle_hit' => 'Przikro nom, założůł(a)żeś już {{PLURAL:$1|1 kůnto|$1 kůnta}}. Ńy możesz założyć kolejnygo.',
+'emailauthenticated' => 'Twůj ausdruk e-brifa zostoł powjerzitelńůny $2 uo $3.',
+'emailnotauthenticated' => 'Twůj adres e-brifa ńy je powjerzitelńůny. Půniższe funkcyje poczty ńy dźołajům.',
+'noemailprefs' => 'Muśisz podać adres e-brifa, coby te funkcyje dźołały.',
+'emailconfirmlink' => 'Potwjyrdź swůj adres e-brifa',
+'invalidemailaddress' => 'E-brif Å\84y bydźe zaakceptůwany skiż tygo co jigo format Å\84y speÅ\82Å\84o formalnych wymagaÅ\84. Prosza naszkryflaÄ\87 poprowny adres e-brifa abo wyczyśćić pole.',
 'cannotchangeemail' => 'Ńy możno pomjyńyc ausdruku e-mail.',
 'emaildisabled' => 'Ta zajta ńy je mogebna posyłać e-brify.',
-'accountcreated' => 'Utwůřůno kůnto',
-'accountcreatedtext' => 'Kůnto lo $1 zostouo utwůřůne.',
-'createaccount-title' => 'Stwořyńy kůnta na {{GRAMMAR:MS.lp|{{SITENAME}}}}',
-'createaccount-text' => 'Ktoś utworził na {{GRAMMAR:MS.lp|{{SITENAME}}}} ($4) dla Twojego adresa e-brif kůnto "$2". Aktualne hasło to "$3". Powińeżeś śe terozki zalogůwać a je zmjyńić.',
+'accountcreated' => 'Utwůrzůno kůnto',
+'accountcreatedtext' => 'Kůnto lo [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|dyskusyjo]]) je utwůrzůne.',
+'createaccount-title' => 'Stworzyńy kůnta na {{GRAMMAR:MS.lp|{{SITENAME}}}}',
+'createaccount-text' => 'Ftoś utworził na {{GRAMMAR:MS.lp|{{SITENAME}}}} ($4) lo Twojigo adresa e-brif kůnto "$2". Aktuelne hasło to "$3". Powińeżeś śe terozki zalogůwać a je zmjyńić.',
 'usernamehasherror' => 'Nazwa sprowjorza ńy może mjyć buchsztaby "#".',
-'login-throttled' => '!Wykonołżeś za wjela průb zalůgowańo śe na te kůnto. Poczekej chwila ńym zaś sprůbujesz.',
+'login-throttled' => 'Wykonołżeś za wjela průb zalůgowańo śe na te kůnto. Uodczekej $1 ńym zaś sprůbujesz.',
 'login-abort-generic' => 'Felerne logowańe',
 'loginlanguagelabel' => 'Godka: $1',
-'suspicious-userlogout' => 'Żądanie wylogowania zostało odrzucone ponieważ wygląda na to, że zostało wysłane przez uszkodzoną przeglądarkę lub buforujący serwer proxy.',
+'suspicious-userlogout' => 'Polecyńe wylogowańo uostoło uodćepńynte skiż tygo co wyglůnda, aże uostoło posłane bez uszkodzůna przeglůndarka abo buforujůncy serwer proxy.',
+'createacct-another-realname-tip' => 'Wszkryflańy twojigo mjana a nazwiska ńy je końyczne.
+Kej bydźesz chćoł je podoć, bydům użyte, coby dokůmyntowoć Twoje autorstwo.',
 
 # Email sending
 'php-mail-error-unknown' => 'Ńyznany feler we funkcyji mail()',
-'user-mail-no-addy' => 'Próba wysłania e‐maila bez adresu odbiorcy',
+'user-mail-no-addy' => 'Průba posłańo e‐brifa bez adresu uodbjorcy',
 
 # Change password dialog
 'resetpass' => 'Pomjyńaj hasło',
-'resetpass_announce' => 'Zalůgowoužeś śe s tymčasowym kodym uotřimanym bez e-brif. Coby zakůńčyć proces logůwańo muśiš naštalować nowe hasuo:',
+'resetpass_announce' => 'Zalůgowołżeś śe ze tymczasowym kodym uotrzimanym bez e-brif. Coby zakůńczyć proces logůwańo muśisz nasztalować nowe hasło:',
 'resetpass_header' => 'Zmjyń hasło lů swojygo kůnta',
 'oldpassword' => 'Stare hasło',
 'newpassword' => 'Nowe hasło',
 'retypenew' => 'Naszkryflej jeszcze roz nowe hasło:',
-'resetpass_submit' => 'Naštaluj hasuo a zalůguj',
-'changepassword-success' => 'Twoje hasuo zostouo půmyślńy pomjyńone! Trwo logůwańe...',
-'resetpass_forbidden' => 'Ńy idźe sam půmjyńyć hasuůw.',
-'resetpass-no-info' => 'Muśysz być zalogowany, coby uzyskać bezpostrzedńi dostymp do tyj zajty.',
+'resetpass_submit' => 'Nasztaluj hasło a zaloguj',
+'changepassword-success' => 'Twoje hasło zostoło půmyślńy půmjyńone!',
+'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-submit-loggedin' => 'Zmjyń hasło',
 'resetpass-submit-cancel' => 'Uodćepej',
 'resetpass-wrong-oldpass' => 'Felerne tymczasowe abo aktualne hasło.
@@ -546,35 +612,35 @@ Możliwe co właśńy zmjyńiłżeś swoje hasło abo poprosiłżeś uo nowe tym
 'passwordreset-disabled' => 'No tyj wiki zamkńynto resytowańy hasył.',
 'passwordreset-username' => 'Mjano używacza:',
 'passwordreset-domain' => 'Domyna:',
-'passwordreset-capture' => 'Czy pokazywać treść wiadomości e‐mail?',
-'passwordreset-capture-help' => 'Eli zaznaczysz to pole, łoboczysz wjadomość e-mail z hasłem.',
+'passwordreset-capture' => 'Pokozać treść e-brifa?',
+'passwordreset-capture-help' => 'Eli zaznaczysz to pole, uobejrzisz wjadůmość e-brifa ze hasłym.',
 'passwordreset-email' => 'E-brif:',
 'passwordreset-emailtitle' => 'Kůnto na {{GRAMMAR:MS.lp|{{SITENAME}}}}',
-'passwordreset-emailtext-ip' => 'Ftůś (cheba Ty, s IP $1)
+'passwordreset-emailtext-ip' => 'Ftoś (cheba Ty, s IP $1)
 pado, aże chce informacyji lo konta do {{GRAMMAR:MS.lp{{SITENAME}}}} ($4).
-Z tem ausdrukiem sum powjonzyne konta:
+Ze tym ausdrukym sům powjůnzane kůnta:
 $2
 
-{{PLURAL:$3|Tymczasowygo hasła|Tymczasowych haseł}} możno użyć w ciągu {{PLURAL:$5|jednego dnia|$5 dni}}.
+{{PLURAL:$3|Tymczasowygo hasła|Tymczasowych hasył}} możno użyć we {{PLURAL:$5|jedyn dźyń|$5 dńi}}.
 
-Jak chćołżeś gynał to zrobjyć, to zalůgůj śe terozki a podej swoje hasło.
+Jak chćołżeś gynał to zrobjyć, to zaloguj śe terozki a podej swoje hasło.
 
-Jak ktůś inkszy chćoł nowe hasło abo jak Ci śe przipůmńouo stare a ńy chcesz nowygo, to zignoruj to a używej starygo hasła.',
-'passwordreset-emailelement' => 'Nazwa sprowjorza: $1
+Jak ftoś inkszy chćoł nowe hasło abo jak Ci śe przipůmńoło stare a ńy chcysz nowygo, to zignoruj to a używej starygo hasła.',
+'passwordreset-emailelement' => 'Mjano sprowjorza: $1
 Tymczasowe hasło: $2',
 'passwordreset-emailsent' => 'E-brif posłany.',
 'passwordreset-emailsent-capture' => 'E-brif posłony, kerego widać niżej.',
-'passwordreset-emailerror-capture' => 'Ńy udało sie wysłać wjadomości lo sprowjorza: $1',
+'passwordreset-emailerror-capture' => 'Ńy udoło śe posłać wjadomości lo {{GENDER:$2|używocza|używoczki}}: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'Pomjyno ausdruka e-mail',
 'changeemail-header' => 'Pomjyno ausduku e-mail',
 'changeemail-text' => 'Wypełnij formularz, podej nowy ausdruk a hasło.',
-'changeemail-no-info' => 'Muśysz być zalogowany, coby uzyskać bezpostrzedńi dostymp do tyj zajty.',
+'changeemail-no-info' => 'Muśisz być zalogowany, coby uzyskać bezpostrzedńi dostymp do tyj zajty.',
 'changeemail-oldemail' => 'Uobecny ausdruk:',
 'changeemail-newemail' => 'Nowy adresu e-brif',
 'changeemail-none' => 'podstawowo',
-'changeemail-submit' => 'Zapisz nowy',
+'changeemail-submit' => 'Spamjyntej nowy',
 'changeemail-cancel' => 'Uodćepej',
 
 # Edit page toolbar
@@ -592,37 +658,37 @@ Tymczasowe hasło: $2',
 'nowiki_tip' => 'Zignoruj formatowańy wiki',
 'image_tip' => 'Plik uosadzůny we zajće',
 'media_tip' => 'Link do plika',
-'sig_tip' => 'Twůj podpis z datumym i czasym',
+'sig_tip' => 'Twojo szrajbka ze datum a czasym',
 'hr_tip' => 'Poźůmo lińijo (używej mjyrńy)',
 
 # Edit pages
 'summary' => 'Popis půmjyńań:',
-'subject' => 'Tymat/naguůwek:',
+'subject' => 'Tyjma/iberszryft:',
 'minoredit' => 'To je ńywjelge sprowjyńy',
 'watchthis' => 'Dej pozůr',
 'savearticle' => 'Spamjyntej',
 'preview' => 'Uobźyrańy',
 'showpreview' => 'Uobźyrej',
-'showlivepreview' => 'Dynamičny podglůnd',
+'showlivepreview' => 'Dynamiczny podglůnd',
 'showdiff' => 'Pozdrzyj na půmjyńańy',
-'anoneditwarning' => 'Ńy jeżeś nalogowany. We gyszichće sprowjyń tyj zajty bydźe naszkryflůny twůj adres IP.',
-'anonpreviewwarning' => 'Ńy jeżeś zalogowany. Twój adres IP łostonie zapisany, eli ty bydzies sprowjać zajte.',
-'missingsummary' => "'''Připomńyńy:''' Ńy wprowadźiužeś uopisu pomjyńań. Kej go ńy chceš wprowadzać, naćiś knefel Škryflej ješče roz.",
-'missingcommenttext' => 'Wćepej kůmyntoř půńižyj.',
-'missingcommentheader' => "'''Dej pozůr:''' Treść nagłůwka je pusto - uzupeuńij go! Jeli tego ńy zrobisz, Twůj kůmyntorz bydźe naszkryflany bez naguůwka.",
+'anoneditwarning' => 'Ńy jeżeś terozki zalogowany. We gyszichće sprowjyń tyj zajty bydźe naszkryflůny twůj ausdruk IP.',
+'anonpreviewwarning' => 'Ńy jeżeś zalogowany. Twój IP ausdruk uostańy spamjyntany, eli ty bydźesz sprowjać zajte.',
+'missingsummary' => "'''Pozůr:''' Ńy wprowadźůł żeś uopisu pomjyńań. Kej go ńy chcesz wprowadzać, naćiś knefel Spamjyntej jeszcze roz.",
+'missingcommenttext' => 'Wćepej kůmyntorz půńiż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.",
 'summary-preview' => 'Podglůnd uopisu:',
-'subject-preview' => 'Podglůnd tematu/naguůwka:',
-'blockedtitle' => 'Užytkowńik je zawarty uod sprowjyń',
-'blockedtext' => '\'\'\'Twoje kůnto abo adres IP sům zawarte.\'\'\'
+'subject-preview' => 'Podglůnd tyjmy/nagłůwka:',
+'blockedtitle' => 'Użytkowńik je zawarty uod sprowjyń',
+'blockedtext' => '\'\'\'Twoje kůnto abo IP ausdruk sům zawarte.\'\'\'
 
-Uo zawarću zdecydowou $1. Pado, aže skuli: \'\'$2\'\'.
+Uo zawarću zdecydowoł $1. Pado, aże skuli: \'\'$2\'\'.
 
 * Zawarte uod: $8
 * Uodymkńe śe: $6
-* Bez cůž: $7
+* Zawarće skiż: $7
 
-Coby wyjaśńić sprawa zawarćo, naškryflej do $1 abo inkšygo [[{{MediaWiki:Grouppage-sysop}}|admińistratora]].
\83y možeÅ¡ posuaÄ\87 e-brifa bez "poÅ\9blij e-brifa tymu užytkowÅ\84ikowi", jak Å¾eÅ\9b Å\84y podou dobrygo adresa e-brifa we [[Special:Preferences|preferencyjach kůnta]], abo jak e-brify moÅ¡ tyž zawarte. Terozki moÅ¡ adres IP $3 a nůmer zawarÄ\87a to #$5. ProÅ¡ymy podaÄ\87 jedyn abo uobadwa jak chceÅ¡ pouosprawjać uo zawarću.',
+Coby wyjaśńić sprawa zawarćo, naszkryflej do $1 abo inkszygo [[{{MediaWiki:Grouppage-sysop}}|admińistratora]].
\83y możesz posÅ\82\87 e-brifa bez "poÅ\9blij e-brifa tymu użytkowÅ\84ikowi", jak Å¼eÅ\9b Å\84y podoÅ\82 dobrygo ausdruku e-brifa we [[Special:Preferences|preferencyjach kůnta]], abo jak e-brify mosz tyż zawarte. Terozki mosz ausdruk IP $3 a nůmera zawarÄ\87o to #$5. Proszymy podaÄ\87 jedyn abo uoba jak chcysz poÅ\82osprawjać uo zawarću.',
 'autoblockedtext' => 'Tyn adres IP zostou zawarty automatyčńy, gdyž kořisto s ńygo inkšy užytkowńik, zawarty uod sprowjyń bez administratora $1.
 Powůd zawarćo:
 
@@ -632,52 +698,48 @@ Powůd zawarćo:
 * Zawarće wygaso: $6
 * Zawarće je skiž: $7
 
-Možyš skůntaktować śe s $1 abo jednym s pozostauych [[{{MediaWiki:Grouppage-sysop}}|admińistratorůw]] kejbyś chćou uzyskać informacyje uo zawarću.
-
-Pozůr: Kejžeś we [[Special:Preferences|preferencyjach]] ńy naštalowou prowiduowygo adresa e-brifa, abo e-brify moš tyž zawarte, ńy možeš skožystać s uopcyje "Poślij e-brifa tymu užytkowńikowi".
-
-Twůj adres IP je terozki $3. Idyntyfikator Twojij blokady to $5. Zanotuj śe go a podej admińistratorowi.',
-'blockednoreason' => 'ńy podano skuli čego',
-'whitelistedittext' => 'Muśiš $1 coby můc sprowjać artikle.',
-'confirmedittext' => 'Muśiš podać a potwjerdźić swůj e-brif, coby můc sam sprowjać.
-Možeš to zrobić we [[Special:Preferences|swojich štalowańach]].',
+* Zawarte uod: $8 * Uodymkńe śe: $6 * Zawarće skiż: $7 Coby wyjaśńić sprawa zawarćo, naszkryflej do $1 abo inkszygo [[{{MediaWiki:Grouppage-sysop}}|admińistratora]]. Ńy możesz posłać e-brifa bez "poślij e-brifa tymu użytkowńikowi", jak żeś ńy podoł dobrygo ausdruku e-brifa we [[Special:Preferences|preferencyjach kůnta]], abo jak e-brify mosz tyż zawarte. Terozki mosz ausdruk IP $3 a nůmera zawarćo to #$5. Proszymy podać jedyn abo uoba jak chcysz połosprawjać uo zawarću.',
+'blockednoreason' => 'ńy podano skuli czygo',
+'whitelistedittext' => 'Muśisz $1 coby můc sprowjać artikle.',
+'confirmedittext' => 'Muśisz podać a potwjerdźić swůj e-brif, coby můc sam sprowjać.
+Możesz to zrobić we [[Special:Preferences|swojich sztalowańach]].',
 'nosuchsectiontitle' => 'Ńy mo takij tajli',
 'nosuchsectiontext' => 'Průbowołżeś sprowjać tajla kero ńy istńeje.',
-'loginreqtitle' => 'Muśiš śe zalůgować',
-'loginreqlink' => 'zalůguj śe',
-'loginreqpagetext' => 'Muśiš $1 coby můc přeglůndać inkše zajty.',
-'accmailtitle' => 'Hasuo wysuane.',
-'accmailtext' => '!Hasło użytkowńika "[[User talk:$1|$1]]" zostauo wysłane pod adres $2.
-
-Hasło można pomjyńyć [[Special:ChangePassword|tu]].',
+'loginreqtitle' => 'Muśisz śe zalogować',
+'loginreqlink' => 'zaloguj śe',
+'loginreqpagetext' => 'Muśisz $1 coby můc przeglůndać inksze zajty.',
+'accmailtitle' => 'Hasło posłane.',
+'accmailtext' => "Cufalńe hasło lo [[User talk:$1|$1]] uostoło posłane do $2. Hasło lo tygo nowygo kůnta po zalogowańu je mogebność pomjyńić na zajće ''[[Special:ChangePassword|pomjyńańe hasła]]''.",
 'newarticle' => '(Nowy)',
-'newarticletext' => 'Ńy mo sam jeszcze artikla uo takijj titli. Eli chcesz go sprowjać, naszkryflej niżyj jego tekst (wjyncy informacyj nojdźesz [[{{MediaWiki:Helppage}}|na zajće půmocy]]). Eli żeś chćoł zrobić cosik inksze, naćiś ino knefel "Nazod".',
+'newarticletext' => 'Ńy mo sam jeszcze artikla uo takijj titli. Eli chcesz go sprowjać, naszkryflej niżyj jego tekst (wjyncy informacyj nojdźesz [[{{MediaWiki:Helppage}}|na zajće půmocy]]). Eli żeś chćoł zrobić cośik inksze, naćiś ino knefel "Nazod".',
 'anontalkpagetext' => "---- ''To je zajta godki lo anůnimowych używoczy  - takich, kerzi ńy majům jeszcze swojigo kůnta abo ńy chcům go terozki używać.
 By jejich idyntyfikować, używomy numerůw IP.
 Eli jeżeś anůnimowym używoczym a wydowo Ći śe, aże zamjyszczůne sam kůmyntorze ńy sům skjyrowane do Ćebje, [[Special:UserLogin|utwůrz prosza kůnto]] abo [[Special:UserLogin|zalůguj śe]] - beztůż uńikńesz potym podobnych ńyporozumjyń.''",
 'noarticletext' => 'Ńy můmy zajta uo takij titli. Mogesz [{{fullurl:{{FULLPAGENAME}}|action=edit}} wćepać artikel {{FULLPAGENAME}}] abo [[Special:Search/{{PAGENAME}}|sznupać {{PAGENAME}} we inkszych]].',
-'noarticletext-nopermission' => 'Na tyj zajće ńy mo jeszcze artikla.
-Mogesz [[Special:Search/{{PAGENAME}}|wysznupać ta titla]] we treśći inkszych zajtůw
-abo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przesznupać powjůnzane logi].</span>',
-'userpage-userdoesnotexist' => 'Užytkowńik "<nowiki>$1</nowiki>" ńy je zareještrowany. Sprowdź eli na pewno chćoužeś stwořyć/pomjynić gynau ta zajta.',
+'noarticletext-nopermission' => 'Ta zajta terozki je pusto.
+Mogesz [[Special:Search/{{PAGENAME}}|wysznupać ta titla]] we treśćach inkszych zajtůw, abo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przesznupać powjůnzane rejery]</span>, nale ńy mosz uprowńyń coby ta zajta wćepać',
+'userpage-userdoesnotexist' => 'Użytkowńik "<nowiki>$1</nowiki>" ńy je zarejesztrowany. Sprowdź eli na pewno chćołżeś stworzyć/pomjynić gynał ta zajta.',
 'userpage-userdoesnotexist-view' => "Konto sprowjorza ''$1'' ńy istnieje.",
 'blocked-notice-logextract' => '{{GENDER:$1|Tyn sprowjorz|Ta sprowjorka}} mo zawrzite sprowjyńa.',
 'clearyourcache' => "'''Dej pozůr:''' Coby uobejrzeć pomjyńańo pů naszkryflańu nowych sztalowań poleć przeglůndorce wyczyśćić zawartość pamjyńći podryncznyj (cache). '''Mozilla / Firefox / Safari:''' przitrzimej ''Shift'' klikajůnc na ''Uodśwjyž'' abo wciś ''Ctrl-Shift-R'' (''Cmd-Shift-R'' na Macu), '''IE :''' przitrzimej ''Ctrl'' klikajůnc na ''Uodśwjyž'' abo wciś ''Ctrl-F5''; '''Konqueror:''': kliknij knefel ''Uodśwjyž'' abo wciś ''F5''; użytkowńicy '''Opery''' mogům być zmuszeńi coby cołkym wyczyśćić jejich pamjyńć podrynczno we menu ''Werkcojgi→Preferencyje''.; '''Internet Explorer:''' trzim ''Ctrl'' a wćiś ''Uodśwjyż'', abo wćiś ''Ctrl-F5''.",
 'usercssyoucanpreview' => "!'''Podpowjydź:''' Użyj knefla \"Podglůnd\", coby przetestować Twůj nowy arkusz stylůw CSS abo kod JavaScript przed jego zaszrajbowańym.",
 'userjsyoucanpreview' => "!'''Podpowjydź:''' Użyj knefla \"Podglůnd\", coby przetestować Twůj nowy arkusz stylůw CSS abo kod JavaScript przed jego zaszrajbowańym.",
-'usercsspreview' => "'''Pamjyntej, aže to je na raźe ino podglůnd Twojego arkuša stylůw CSS.'''
-'''Ńic ješče ńy zostouo naškryflone!'''",
-'userjspreview' => "'''Pamjyntej, aže to je na raźe ino podglůnd Twojego JavaScriptu - nic ješče ńy zostouo naškryflone!'''",
+'usercsspreview' => "'''Pamjyntej, aże to je no raźe ino podglůnd Twojego arkusza stylůw CSS.'''
+'''Ńic jeszcze ńy zostoło naszkryflane!'''",
+'userjspreview' => "'''Pamjyntej, aże to je no raźe ino podglůnd Twojego arkusza stylůw JavaScriptu.'''
+'''Ńic jeszcze ńy zostoło naszkryflane!'''",
 'sitecsspreview' => "'''Pamjyntej, aże to je na raźe ino podglůnd Twojego arkusza stylůw CSS.'''
-'''Ńic jeszczče ńy zostoło naszkryflone!'''",
-'sitejspreview' => "'''Pamjyntej, aże to je na raźe ino podglůnd Twojego JavaScriptu - nic jeszcze ńy zostoło naškryflone!'''",
-'userinvalidcssjstitle' => "'''Pozůr:''' Å\83y mo skůrki uo mjaÅ\84e \"\$1\". Pamjyntej, aže zajty užytkowÅ\84ika zawjyrajůnce CSS i JavaScript powinny zaÄ\8dynaÄ\87 Å\9be mouům buchÅ¡tabům, np. {{ns:user}}:Foo/vector.css.",
+'''Ńic jeszcze ńy zostoło naszkryflane!'''",
+'sitejspreview' => "'''Pamjyntej, aże to je na raźe ino podglůnd Twojego JavaScriptu - nic jeszcze ńy zostoło naszkryflane!'''",
+'userinvalidcssjstitle' => "'''Pozůr:''' Å\83y mo skůrki uo mjaÅ\84e \"\$1\". Pamjyntej, aże zajty użytkowÅ\84ika zawjyrajůnce CSS i JavaScript powinny zaczynaÄ\87 Å\9be maÅ\82ům buchsztabům, lb. {{ns:user}}:Foo/vector.css.",
 'updated' => '(Pomjyńano)',
 'note' => "'''Pozůr:'''",
 'previewnote' => "'''To je ino podglůnd - artikel jeszcze ńy je spamjyntany!'''",
-'continue-editing' => 'Sprowjej dalej',
-'previewconflict' => 'Wersyjo podglůndano uodnośi śe do tekstu s pola edycyje na wjyrchu. Tak bydźe wyglůndać zajta jeli zdecyduješ śe jům naškryflać.',
-'session_fail_preview' => "'''Přeprašomy! Serwer ńy može přetwořyć tygo sprowjyńo skuli utraty danych ze sesyji. Sprůbuj ješče roz. Kejby to ńy pomoguo - wylůguj śe i zalogůj uod nowa.'''",
+'continue-editing' => 'Przyndź do pola sprowjańo',
+'previewconflict' => 'Wersyjo podglůndano uodnośi śe do tekstu ze pola edycyje na wjyrchu. Tak bydźe wyglůndać zajta jeli zdecydujesz śe jům naszkryflać.',
+'session_fail_preview' => "'''Pozůr! Serwer ńy może przetworzić tyj edycyji, beztuż co dane sesyji uostoły utracůne.
+Poprůbuj jeszcze roz.
+Eli to tyż ńy do podpory – [[Special:UserLogout|wyloguj śe]] a zaloguj jeszcze roz.'''",
 'session_fail_preview_html' => "'''Přeprašomy! Serwer ńy može přetwořyć tygo sprowjyńo skuli utraty danych ze sesyji.'''
 
 ''Jako iže na {{GRAMMAR:MS.lp|{{SITENAME}}}} wuůnčono zostoua uopcyjo \"raw HTML\", podglůnd zostou schrůńony coby zabezpječyć před atakami JavaScript.''
@@ -689,56 +751,57 @@ abo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}
 'editingsection' => 'Sprowjosz $1 (sekcyjo)',
 'editingcomment' => 'Sprowjosz "$1" (nowy kůmyntorz)',
 'editconflict' => 'Kůnflikt sprowjyń: $1',
-'explainconflict' => "Ktoś zdůnžyu wćepać swoja wersyjo artikla ńim žeś naškryflou sprowjyńy.
-We polu edycyji na wjyrchu moš tekst zajty aktůalńy naškryflany w baźe danych.
-Twoje pomjyńańo sům we polu edycyji půnižyj.
-By wćepać swoje pomjyńańo muśiš pomjyńać tekst w polu na wjyrchu.
-'''Tylko''' tekst z pola na wjyrchu bydźe naškryflany we baźe jak wciśńeš \"{{int:savearticle}}\".",
+'explainconflict' => "Ftoś zdůnżůł wćepać swoja wersyjo artikla ńim żeś naszkryflou sprowjyńy.
+We polu edycyji na wjyrchu mosz tekst zajty aktuelńy naszkryflany we baźe danych.
+Twoje pomjyńańo sům we polu edycyji půńiżyj.
+By wćepać swoje pomjyńańo muśisz pomjyńać tekst we polu na wjyrchu.
+'''Ino''' tekst ze pola na wjyrchu bydźe naszkryflany we baźe jak 
+wciśńesz knefel \"{{int:savearticle}}\".",
 'yourtext' => 'Twůj tekst',
-'storedversion' => 'Naškryflano wersyjo',
+'storedversion' => 'Naszkryflano wersyjo',
 'nonunicodebrowser' => "'''Pozůr! Twoja přeglůndorka ńy umje poprowńy rozpoznować kodowańo UTF-8 (Unicode). Bestož wšyjske znoki, kerych Twoja přeglůndorka ńy umje rozpoznować, zamjeńůno na jejich kody heksadecymalne.'''",
 'editingold' => "'''Dej pozůr: Sprowjoš inkšo wersyjo zajty kej bježůnco. Jeli jům naškryfloš, wšyjske půźńyjše pomjyńańa bydům wyćepane.'''",
 'yourdiff' => 'Růžńice',
-'copyrightwarning' => "Pamjyntej uo tym, aže couki wkuod do {{SITENAME}} udostympÅ\84ůmy wedle zasad $2 (dokuadÅ\84ij w $1). Jak Å\84y chceÅ¡, coby koždy můg go zmjyÅ\84\87 i dali rozpowÅ¡ychÅ\84\87, Å\84y wÄ\87epuj go sam. Å kryflajůnc sam tukej poÅ\9bwjadÄ\8doÅ¡ tyž, co te pisaÅ\84y je twoje wuasne, abo Å¾eÅ\9b go wźůn(a) s materjouůw kere sům na ''public domain'', abo kůmpatybilne.<br />
-'''PROŠA ŃY WĆEPYWAĆ SAM MATYRJOUŮW KERE SŮM CHRŮŃONE PRAWYM AUTORSKIM BEZ DOZWOLEŃO WUAŚĆIĆELA!'''",
-'copyrightwarning2' => "Pamjyntej uo tym, aže couki wkuod do {{GRAMMAR:MS.lp|{{SITENAME}}}} može byÄ\87 sprowjany, pomjyÅ\84any abo wyÄ\87epany bez inkÅ¡ych užytkownikůw. Jak Å\84y chceÅ¡, coby koždy můg go zmjyÅ\84\87 i dali rozpowÅ¡ychÅ\84\87 bez uograniÄ\8dyń, ńy wćepuj go sam.<br />
-Škryflajůnc sam tukej pośwjadčoš tyž, co te pisańy je twoje wuasne, abo žeś go wźůn(a) s matyrjouůw kere sům na public domain, abo kůmpatybilne (kuknij tyž: $1).
-'''PROŠA ŃY WĆEPYWAĆ SAM MATYRJOUŮW KERE SŮM CHRŮŃONE PRAWYM AUTORSKIM BEZ DOZWOLEŃO WUAŚĆIĆELA!'''",
+'copyrightwarning' => "Pamjyntej uo tym, aże coÅ\82ki wkÅ\82od do {{SITENAME}} udostympÅ\84ůmy wedle zasad $2 (dokÅ\82adÅ\84ij we $1). Jak Å\84y chcesz, coby kożdy můg go půmjyÅ\84\87 a dalij rozpowszychÅ\84\87, Å\84y wÄ\87epuj uůnygo sam. Szkryflajůnc sam tukej poÅ\9bwjadczosz tyż, co te pisaÅ\84y je twoje wÅ\82asne, abo Å¼eÅ\9b go wźůn(a) ze materjoÅ\82ůw kere sům na ''public domain'', abo kůmpatybilne.<br />
+'''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Å\82ki wkÅ\82od do {{GRAMMAR:MS.lp|{{SITENAME}}}} może byÄ\87 sprowjany, pomjyÅ\84any abo wyÄ\87epany bez inkszych użytkownikůw. Jak Å\84y chcysz, coby kożdy můg uůnygo zmjyÅ\84\87 a dalij rozpowszychÅ\84\87 bez uograniczyń, ńy wćepuj go sam.<br />
+Szkryflajů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).
+'''PROSZA ŃY WĆEPYWAĆ SAM MATYRJOŁŮW KERE SŮM CHRŮŃONE PRAWYM AUTORSKIM BEZ DOZWOLEŃO WŁAŚĆIĆELA!'''",
 '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.'''
 
 Admiń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 s uprawńyńami admińistratora.'''
+'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.'''
 Uostatńy wpis w rejerze je poniżej.",
 'semiprotectedpagewarning' => "'''Pozůr:''' Ta zajta zostoła zawarto a ino zaregiszterowani użytkownicy mogům jům sprowjać.
 Uostotńy wpis w rejerze je ńyżej.",
-'cascadeprotectedwarning' => "'''Dej pozůr:''' Ta zajta zostoua zawarto a ino užytkowńicy s uprawńyńami admińistratora mogům jům sprowjać. Zajta ta je podpjynto pod {{PLURAL:$1|nastympujůnco zajta, kero zostoua zawarto|nastympujůncych zajtach, kere zostouy zawarte}} ze zauůnčonům opcjům dźedźičyńo:",
+'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ć.'''
 Uostatńy wpis z rejera je ńyżej.",
-'templatesused' => '{{PLURAL:$1|Szablon|Szablůny}} użyte na tyj zajće:',
-'templatesusedpreview' => '{{PLURAL:$1|Szablon|Szablůny}} użyte na tyj zajće:',
-'templatesusedsection' => '{{PLURAL:$1|Szablon|Szablůny}} użyte w tyj tajli:',
+'templatesused' => '{{PLURAL:$1|Muster|Mustry}} użyte na tyj zajće:',
+'templatesusedpreview' => '{{PLURAL:$1|Muster|Mustry}} użyte na tyj zajće:',
+'templatesusedsection' => '{{PLURAL:$1|Szablon|Szablůny}} użyte we tyj tajli:',
 'template-protected' => '(zawrzity uod sprowjańo)',
 'template-semiprotected' => '(tajlowo zawarte)',
-'hiddencategories' => 'Ta zajta je {{PLURAL:$1|w jednyj schrůńunyj katygoryji|we $1 schrůńunych katygoryjach}}:',
+'hiddencategories' => 'Ta zajta je {{PLURAL:$1|we jednyj schrůńunyj katygoryji|we $1 schrůńunych katygoryjach}}:',
 'nocreatetext' => 'Na {{GRAMMAR:MS.lp|{{SITENAME}}}} twořyńy nowych zajtůw uograńičůno.
 Možeš sprowjać te co juž sům, abo [[Special:UserLogin|zalogować śe, abo zauožyć konto]].',
-'nocreate-loggedin' => 'Ńy moš uprowńyń do twořyńo nowych zajtůw.',
+'nocreate-loggedin' => 'Ńy mosz uprowńyń do tworzyńo nowych zajtůw.',
 'sectioneditnotsupported-title' => 'Sprowjańy tajli ńymogebne',
 'sectioneditnotsupported-text' => 'Sprowjańy tajli ńymogebne na tyj zajće.',
-'permissionserrors' => 'Felerne uprowńyńa',
-'permissionserrorstext' => 'Ńy moš uprowńyń do takij akcyje {{PLURAL:$1|skuli tego, co:|bestůž, co:}}',
+'permissionserrors' => 'Felerne uprawńyńo',
+'permissionserrorstext' => 'Ńy mosz uprowńyń do takij akcyje {{PLURAL:$1|skuli tego, co:|bestůż, co:}}',
 'permissionserrorstext-withaction' => 'Ńy mogesz $2, ze {{PLURAL:$1|takigo powodu|takich powodůw}}:',
 'recreate-moveddeleted-warn' => "'''ůostrzeżyńy: Wćepujesz samo zajta, kery bůu poprzedńo wyćepany.'''
 
 Zastanůw śe, czy powinno śe go sam wćepywać.
 Rejer wyćepań tyj zajty je podany půńiżej, cobyś mioł wygoda:",
-'moveddeleted-notice' => 'Ta zajta zostoua wyćepńynto. Rejer wyćepań tyj zajty je pokozany půńižyj.',
+'moveddeleted-notice' => 'Ta zajta zostoła wyćepńynto. Rejer wyćepań tyj zajty je pokozany půńiżyj.',
 'log-fulllog' => 'Ukoż rejer',
 'edit-hook-aborted' => 'Sprowjyńy štopńynte skiž hoka.
 Ńy je wjadůme pů jakymu.',
 'edit-gone-missing' => 'Ńy idźe zaktualizować zajty.
-Zdowo śe, co zostoua wyćepano.',
+Zdowo śe, co zostoła wyćepano.',
 'edit-conflict' => 'Kůnflikt sprowjyń.',
 'edit-no-change' => 'Twoje sprowjyńe uostouo zignorowane pů takymu, co ńic žeś we tekśće ńy zmjyńiu.',
 'edit-already-exists' => 'Ńy idźe utwořić nowyj zajty.
@@ -755,7 +818,7 @@ Powinno być myńi jak $2 {{PLURAL:$2|wywouańy|wywouańo|wywouań}}, a terozki
 'post-expand-template-inclusion-category' => 'Zajty, na kerych dokuplowane mustry sům moc wjelge',
 'post-expand-template-argument-warning' => 'Dej pozůr: Ta zajta zawjyro přinojmyńi jedyn argument we šablůńe kery powoduje co je ůun za wjelgi. Te argumynty bydům pomińynte.',
 'post-expand-template-argument-category' => 'Zajty na kerych sům šablůny s pomińyntymi argumyntůma.',
-'parser-template-loop-warning' => 'Wykryto szablůn zapyntlyńo: [[$1]]',
+'parser-template-loop-warning' => 'Wykryto muster zapyntlyńo: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Przekroczůno limit głymbokośći rekurencyji szablona ($1)',
 
 # "Undo" feature
@@ -787,12 +850,12 @@ Skuli: ''$2''",
 'page_last' => 'kůńec',
 'histlegend' => 'Wybůr růżńic do porůwnańo: postow kropki we boksach a naćiś enter abo knefel na dole.<br />
 Legynda: (akt.) - růżńice s wersyjům bjeżůncům, (poprz.) - růżńice s wersyjům poprzedzajůncům, d - drobne zmjany',
-'history-fieldset-title' => 'Přeglůndej historyjo',
+'history-fieldset-title' => 'Przeglůndej gyszichta',
 'history-show-deleted' => 'Jyno wyćepane',
-'histfirst' => 'uod počůnku',
-'histlast' => 'uod uostatka',
+'histfirst' => 'nojstarsze',
+'histlast' => 'nojnowsze',
 'historysize' => '({{PLURAL:$1|1 bajt|$1 bajty|$1 bajtůw}})',
-'historyempty' => '(pusto)',
+'historyempty' => '(blank)',
 
 # Revision feed
 'history-feed-title' => 'Gyszichta wersyjůw',
@@ -831,11 +894,11 @@ Inkśi admińistratorzi {{GRAMMAR:D.lp|{{SITENAME}}}} dali bydům mjeć dostymp
 'revdelete-hide-user' => 'Schrůń mjano użytkowńika/adres IP',
 'revdelete-hide-restricted' => 'Schrůń informacyje zarůwno przed admińistratorůma jak i przed inkszymi',
 'revdelete-radio-same' => '(byz pomjyń)',
-'revdelete-radio-set' => 'Ja',
-'revdelete-radio-unset' => 'Ńy',
+'revdelete-radio-set' => 'Zakryty',
+'revdelete-radio-unset' => 'Widoczny',
 'revdelete-suppress' => 'Schrůń informacyje zarůwno před admińistratorůma jak i před inkšymi',
 'revdelete-unsuppress' => 'Usůń uograńičyńo lo wćepanej nazod historyje pomjyńań',
-'revdelete-log' => 'Čymu:',
+'revdelete-log' => 'Czymu:',
 'revdelete-submit' => 'Zaakceptuj do wybrany{{PLURAL:$1|j wersyji|ch wersyji}}',
 'revdelete-success' => 'Půmyślńy zmjyńůno widoczność wersyji.',
 'revdelete-failure' => 'Feler przi zmjyńůńu widoczności wersyji.
@@ -904,6 +967,7 @@ $1',
 'editundo' => 'uodćepej',
 'diff-multi' => '(Ńy pokozano {{PLURAL:$1|jydnyj wersyji postrzedńij|$1 wersyji postrzedńich}}, sprowjanej bez {{PLURAL:$2|jydnygo sprowjorza|$2 sprowjorzow}} .)',
 'diff-multi-manyusers' => '(Ńy pokozano {{PLURAL:$1|jydnyj wersyji postrzedńij|$1 wersyji postrzedńich}}, sprowjanej bez {{PLURAL:$2|jydnygo sprowjorza|$2 sprowjorzow}} .)',
+'difference-missing-revision' => '{{PLURAL:$2|Wersyjo|$2 wersyje|$2 wersyji}} #$1 zajty "{{PAGENAME}}" ńy {{PLURAL:$2|uostoła znaleźůno|uostoły znaleźůne|uostoło znaleźůnych}}. Zauobycz je to skiż starygo linky do wyćępanyj zajty. Powůd wyćepańa nojdźesz we [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rejerze].',
 
 # Search results
 'searchresults' => 'Wyńiki sznupańo',
@@ -946,7 +1010,7 @@ $1',
 'search-interwiki-default' => '$1 wyńiki:',
 'search-interwiki-more' => '(wjyncyj)',
 'search-relatedarticle' => 'Podane',
-'mwsuggest-disable' => 'Wyuůnč sůgestyje AJAX',
+'mwsuggest-disable' => 'Wyłůncz sůgestyje AJAX',
 'searcheverything-enable' => 'Sznupej we wszech mjan',
 'searchrelated' => 'podane',
 'searchall' => 'wszyjske',
@@ -956,22 +1020,21 @@ $1',
 'nonefound' => "'''Dej pozůr''': Důmyślńy přešukiwane sům ino ńykere přestřyńy mjan. Poprůbuj popředźić wyšukiwano fraza předrostkym ''all:'', co spowoduje přešukańy coukij zawartośći {{GRAMMAR:D.lp|{{SITENAME}}}} (wůunčńy ze zajtami godki, šablůnůma atp.), abo poprůbuj užyć kej předrostka wybranyj, jydnyj přestřyńi mjan.",
 'search-nonefound' => 'Ńy mo wynikůw, kere uodpadajům kryterjům zapytańo.',
 'powersearch' => 'Sznupańy zaawansowane',
-'powersearch-legend' => 'Šnupańy zaawansowane',
+'powersearch-legend' => 'Sznupańy zaawansowane',
 'powersearch-ns' => 'Sznupej we przestrzyńach mjan:',
 'powersearch-redir' => 'Pokož překerowańa',
-'powersearch-field' => 'Šnupej',
+'powersearch-field' => 'Sznupej',
 'powersearch-togglelabel' => 'Zaznocz:',
 'powersearch-toggleall' => 'Wszyjsko',
 'powersearch-togglenone' => 'żodno',
 'search-external' => 'Šnupańy zewnyntřne',
 'searchdisabled' => 'Šnupańy we {{GRAMMAR:MS.lp|{{SITENAME}}}} zostouo zawarte. Zańim go zouůnčům, možeš sprůbować šnupańo bez Google. Ino zauwaž, co informacyje uo treśći {{GRAMMAR:MS.lp|{{SITENAME}}}} můgům być we Google ńyakuratne.',
+'search-error' => 'Wystůmpjůł feler przi sznupańu: $1',
 
 # Preferences page
 'preferences' => 'Preferyncyje',
-'mypreferences' => 'Moje preferyncyje',
+'mypreferences' => 'Preferyncyje',
 'prefs-edits' => 'Liczba sprowjyń:',
-'prefsnologin' => 'Ńy ježeś zalůgowany',
-'prefsnologintext' => 'Muśiš śe <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} zalůgować]</span> coby štalować swoje preferyncyje.',
 'changepassword' => 'Zmjana hasua',
 'prefs-skin' => 'Skůrka',
 'skin-preview' => 'podglůnd',
@@ -1027,14 +1090,14 @@ $1',
 'timezoneregion-indian' => 'Ocean Indyjski',
 'timezoneregion-pacific' => 'Uocean Spokojny',
 'allowemail' => 'Inkśi užytkowńicy můgům přesyuać mje e-brify',
-'prefs-searchoptions' => 'Uopcyje šnupańo',
-'prefs-namespaces' => 'Přystřyńe mjan',
+'prefs-searchoptions' => 'Sznupańe',
+'prefs-namespaces' => 'Raumy mjan',
 'defaultns' => 'Důmyślńy sznupej we nastympujůncych przystrzyńach mjan:',
 'default' => 'důmyślńy',
 'prefs-files' => 'Pliki',
 'youremail' => 'E-brif:',
-'username' => 'Mjano użytkowńika:',
-'uid' => 'ID užytkowńika:',
+'username' => '{{GENDER:$1|Mjano używocza}}:',
+'uid' => '{{GENDER:$1|ID używocza}}:',
 'prefs-memberingroups' => 'Należy do {{PLURAL:$1|grupy|grup:}}',
 'prefs-registration' => 'Czas twůrzyńa kůnta:',
 'yourrealname' => 'Prawdźiwe mjano',
@@ -1042,8 +1105,8 @@ $1',
 'yournick' => 'Twoja šrajba:',
 'badsig' => 'Felerno šrajba, sprowdź značńiki HTML.',
 'badsiglength' => 'Twůj szrajbůng je za dugi. Maksymalno jego dugość to $1 {{PLURAL:$1|buchsztaby|buchsztabůw}}',
-'yourgender' => 'Płeć',
-'gender-unknown' => 'ńyznana',
+'yourgender' => 'Płeć:',
+'gender-unknown' => 'ńyznano',
 'gender-male' => 'chop',
 'gender-female' => 'baba',
 'email' => 'E-brif',
@@ -1066,7 +1129,7 @@ $1',
 *Zaznačůne pole uoznačo přinoležność užytkowńika do danej grupy.
 *Ńy zaznačůne pole uoznačo, aže užytkowńik ńy noležy do danej grupy.
 * Gwjozdka * infomuje, co ńy možeš wyćepać s grupy po dodańu do ńij abo dodać po wyćepańu s grupy.',
-'userrights-reason' => 'Čymu:',
+'userrights-reason' => 'Czymu:',
 'userrights-no-interwiki' => 'Ńy moš dostympu do sprowjańo uprawńyń.',
 'userrights-nodatabase' => 'Baza danych $1 ńy istńije abo ńy je lokalno.',
 'userrights-nologin' => 'Muśiš [[Special:UserLogin|zalůgować śe]] na kůnto admińistratora, coby nadować uprawńyńo užytkowńikům.',
@@ -1081,8 +1144,8 @@ $1',
 'group-bot' => 'Boty',
 'group-sysop' => 'Admińi',
 'group-bureaucrat' => 'Bjurokraty',
-'group-suppress' => 'Rewizoře',
-'group-all' => '(wšyjscy)',
+'group-suppress' => 'Rewizorze',
+'group-all' => '(wszyjscy)',
 
 'group-user-member' => '{{GENDER:$1|używacz}}',
 'group-autoconfirmed-member' => 'Autůmatyczńy zatwjerdzůny używacz',
@@ -1091,21 +1154,21 @@ $1',
 'group-bureaucrat-member' => '{{GENDER:$1|bjurokrata}}',
 'group-suppress-member' => '{{GENDER:$1|rewizůr}}',
 
-'grouppage-user' => '{{ns:project}}:Sprowjorze',
+'grouppage-user' => '{{ns:project}}:Używacze',
 'grouppage-autoconfirmed' => '{{ns:project}}:Autůmatyczńy zatwjerdzyńi używacze',
 'grouppage-bot' => '{{ns:project}}:Boty',
 'grouppage-sysop' => '{{ns:project}}:Admińistratory',
 'grouppage-bureaucrat' => '{{ns:project}}:Bjurokraty',
-'grouppage-suppress' => '{{ns:project}}:Rewizoře',
+'grouppage-suppress' => '{{ns:project}}:Rewizorze',
 
 # Rights
-'right-read' => 'Čytej zajty',
+'right-read' => 'Czytej zajty',
 'right-edit' => 'Sprowjej zajty',
-'right-createpage' => 'Utwořůne zajty (kere ńy sům zajtůma godki)',
-'right-createtalk' => 'Utwořůne zajty godki',
+'right-createpage' => 'Utworzůne zajty (kere ńy sům zajtůma godki)',
+'right-createtalk' => 'Utworzůne zajty godki',
 'right-createaccount' => 'Utwořůne nowe kůnta užytkowńikůw',
-'right-minoredit' => 'Uoznoč půmjyńańo kej drobne',
-'right-move' => 'Přećepane zajty',
+'right-minoredit' => 'Uoznocz půmjyńańo kej drobne',
+'right-move' => 'Przećepane zajty',
 'right-move-subpages' => 'Przećep zajty wroz s jejich podzajtůma',
 'right-move-rootuserpages' => 'Překludzańy zajtůw uod užytkowńikůw',
 'right-movefile' => 'Przećepańe plikůw',
@@ -1228,7 +1291,7 @@ $1',
 'rc_categories' => 'Uůgrańič do katygorii (oddźelej za půmocům "|")',
 'rc_categories_any' => 'Wšyskie',
 'newsectionsummary' => '/* $1 */ nowo tajla',
-'rc-enhanced-expand' => 'Pokož Å¡Ä\8dygůuy (wymogo JavaScript)',
+'rc-enhanced-expand' => 'Pokoż szczygůÅ\82y',
 'rc-enhanced-hide' => 'Schrůń detajle',
 
 # Recent changes linked
@@ -1321,7 +1384,7 @@ Idź nazod i wćepej tyn plik pod inkšym mjanym. [[File:$1|thumb|center|$1]]',
 'filename-bad-prefix' => "Mjano plika, kery wćepuješ, začyno śe uod '''\"\$1\"''' &ndash; je to mjano nojčynśćy připisywane autůmatyčńy bez cyfrowe fotoaparaty, uůno ńy dowo žodnych informacyji uo zawartośći plika. Prošymy cobyś nadou plikowi inkše, lepij zrozůmjaue mjano.",
 'upload-success-subj' => 'Wćepańe plika udouo śe',
 
-'upload-proto-error' => 'Ńyprowiduowy protokůu',
+'upload-proto-error' => 'Ńyprowidłowy protokůł',
 'upload-proto-error-text' => 'Zdalne přesůuańy plikůw wymago podańo adresu URL kery začyno śe na <code>http://</code> abo <code>ftp://</code>.',
 'upload-file-error' => 'Wewnyntřny feler',
 'upload-file-error-text' => 'Wystůmpiu wewnyntřny feler kej průbowano naškryflać tymčasowy plik na serweře. Skůntaktuj śe s [[Special:ListUsers/sysop|admińistratorym systemu]].',
@@ -1482,31 +1545,31 @@ Niżyj sům informacyje ze [$2 zajty popisu] tygo pliku.',
 'lonelypagestext' => 'Do zajtůw půńiżyj ńy adresuje żodno inkszo zajta we {{SITENAME}}.',
 'uncategorizedpages' => 'Zajty bez kategoryje',
 'uncategorizedcategories' => 'Kategoryje bez kategoriůw',
-'uncategorizedimages' => 'Pliki bez kategoriůw',
-'uncategorizedtemplates' => 'Šablôny bez kategorii',
-'unusedcategories' => 'Å\83yužywane kategoryje',
-'unusedimages' => 'Å\83yužywane pliki',
-'popularpages' => 'Zajty we kere nojčynśćej sam filujům',
-'wantedcategories' => 'Potřebne katygoryje',
-'wantedpages' => 'Nojpotřebńijše zajty',
+'uncategorizedimages' => 'Pliki bez kategoryjůw',
+'uncategorizedtemplates' => 'Mustry bez kategorii',
+'unusedcategories' => 'Å\83yużywane kategoryje',
+'unusedimages' => 'Å\83yużywane pliki',
+'popularpages' => 'Zajty we kere nojczynśćij sam filujům',
+'wantedcategories' => 'Potrzebne katygoryje',
+'wantedpages' => 'Nojpotrzebńijsze zajty',
 'wantedfiles' => 'Potrzebne pliki',
 'wantedtemplates' => 'Potrzebne szablůny',
-'mostlinked' => 'Nojčyńśćej adrésowane',
-'mostlinkedcategories' => 'Kategoryje we kerych je nojwjyncyi artikli',
-'mostlinkedtemplates' => 'Nojčyńśćej adrésowane šablôny',
-'mostcategories' => 'Zajty kere majům nojwiyncyi kategoriůw',
-'mostimages' => 'Nojčyńśćij adresowane pliki',
-'mostrevisions' => 'Nojčyńśćej sprowjane artikle',
+'mostlinked' => 'Nojczyńśćij adresowane',
+'mostlinkedcategories' => 'Kategoryje we kerych je nojwjyncyj artikli',
+'mostlinkedtemplates' => 'Nojczyńśćij adresowane mustry',
+'mostcategories' => 'Zajty kere majům nojwiyncyj kategoryjůw',
+'mostimages' => 'Nojczyńśćij adresowane pliki',
+'mostrevisions' => 'Nojczyńśćij sprowjane artikle',
 'prefixindex' => 'Wszyskie zajty wedle prefiksa',
-'shortpages' => 'Nojkrůtše zajty',
+'shortpages' => 'Nojkrůtsze zajty',
 'longpages' => 'Duge artikle',
 'deadendpages' => 'Artikle bez linkůw',
-'deadendpagestext' => 'Zajty wymjyÅ\84ůne půÅ\84¾ej Å\84y majům uodnoÅ\9bÅ\84ikůw do Å¾odnych inkÅ¡ych zajtůw kere sům na tej wiki.',
+'deadendpagestext' => 'Zajty wymjyÅ\84ůne půÅ\84¼yj Å\84y majům uodnoÅ\9bÅ\84ikůw do Å¼odnych inkszych zajtůw kere sům na tyj wiki.',
 'protectedpages' => 'Zawarte zajty',
-'protectedpages-indef' => 'Yno zabezpječyńo ńyokreślůne',
+'protectedpages-indef' => 'Ino zabezpjeczyńo ńyuokreślůne',
 'protectedpages-cascade' => 'Yno zajty zabezpjeczůne rekursywńy',
-'protectedpagestext' => 'Zajty wymjyÅ\84ůne půÅ\84¾ej sům zawarte uod prećepywańo i sprowjańo.',
-'protectedpagesempty' => 'Žodno zajta Å\84y je terozki zawarto s podanymi parametrami.',
+'protectedpagestext' => 'Zajty wymjyÅ\84ůne půÅ\84¼yj sům zawarte uod przećepywańo i sprowjańo.',
+'protectedpagesempty' => 'Å»odno zajta Å\84y je terozki zawarto ze podanymi parametrami.',
 'protectedtitles' => 'Zawarte mjana artikli',
 'protectedtitlestext' => 'Ůtwořyńy artikli uo nastympujůncych mjanach je zawarte',
 'protectedtitlesempty' => 'Do tych štalowań utwořyńy artikla uo dowolnym mjańy ńy je zawarte',
@@ -1533,7 +1596,7 @@ Niżyj sům informacyje ze [$2 zajty popisu] tygo pliku.',
 'booksources' => 'Kśůnžki',
 'booksources-search-legend' => 'Šnupej za zdřůduůma kśiůnžkowymi',
 'booksources-go' => 'Pokož',
-'booksources-text' => 'PůÅ\84¾ej znojdowo Å\9be lista uodnoÅ\9bÅ\84ikůw do inkÅ¡ych witryn, kere poÅ\9bredÅ\84\8dům we spÅ\99edažy nowych i užywanych kÅ\9b\85žek, a tyž můgům mjeÄ\87 dalÅ¡e informacyje uo poÅ¡ukiwany bez Ä\87ebje kÅ\9bůnžce',
+'booksources-text' => 'PůÅ\84¼yj je lista uodnoÅ\9bÅ\84ikůw do inkszych witryn, kere poÅ\9bredÅ\84iczům we sprzedaży nowych a używanych buchůw, a tyż můgům mjeÄ\87 dolsze informacyje uo poszukiwanym bez Ä\87ebje buchu.',
 'booksources-invalid-isbn' => 'Podany numer ISBN zostoł rozpoznany kej felerny. Sprowdź aże podany numer je zgodny s numerym kery je we zdrzůdle.',
 
 # Special:Log
@@ -1589,7 +1652,7 @@ Uobsůgiwane protokoły: <code>$1</code>',
 
 # Special:ListUsers
 'listusersfrom' => 'Pokaž užytkowńikůw začynojůnc uod:',
-'listusers-submit' => 'Pokož',
+'listusers-submit' => 'Uobejrzij',
 'listusers-noresult' => 'Ńy znejdźůno žodnygo užytkowńika.',
 
 # Special:ActiveUsers
@@ -1643,8 +1706,8 @@ Adres e-brifa, kery zostoł bez Ćebje wkludzůny we [[Special:Preferences|Twoji
 '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”.',
 
 # Watchlist
-'watchlist' => 'Pozorlista',
-'mywatchlist' => 'Mojo pozůrlista',
+'watchlist' => 'Pozůrlista',
+'mywatchlist' => 'Pozůrlista',
 'watchlistfor2' => 'Lo $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',
@@ -1749,21 +1812,21 @@ Kto inkszy zdůnżůł już to zrobić abo wprowadźił własne poprowki do tre
 Autorym 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: „''$1''”.",
 'revertpage' => 'Wycofano sprowjyńe użytkowńika [[Special:Contributions/$2|$2]] ([[User talk:$2|godka]]). Autor prziwrůcůnej wersyji to [[User:$1|$1]].',
-'rollback-success' => 'Wycofano sprowjyÅ\84a užytkowńika $1.
-Přiwrůcůno uostatńo wersyja autorstwa  $2.',
+'rollback-success' => 'Wycofano sprowjyÅ\84a użytkowńika $1.
+Prziwrůcůno uostatńo wersyja autorstwa  $2.',
 
 # Edit tokens
 'sessionfailure' => 'Feler weryfikacyji zalůgowańo.
-Polecyńy zostouo anulowane, aby ůńiknůńć přechwycyńo sesyji.
+Polecyńy zostoło anulowane, coby ůńiknůńć przechwycyńo sesyji.
 
-Naćiś „cofej”, přeuaduj zajta, a potym zaś wydej polecyńy',
+Naćiś knefel „cofej”, przeładuj zajta, a potym zaś wydej polecyńy',
 
 # Protect
 'protectlogpage' => 'Zawarte',
 'protectlogtext' => 'Půńižej znojdowo śe lista zawarć i uodymkńjyńć pojydynčych zajtůw.
 Coby přejřeć lista uobecńy zawartych zajtůw, přeńdź na zajta wykazu [[Special:ProtectedPages|zawartych zajtůw]].',
 'protectedarticle' => 'zawar [[$1]]',
-'modifiedarticleprotection' => 'pomjyńiu poziům zawarćo [[$1]]',
+'modifiedarticleprotection' => 'pomjyńiu poźům zawarćo [[$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”',
@@ -1831,14 +1894,14 @@ Naćiśńyńće '''Wyczyść''' usůńy wszyjstke zaznaczyńo a wyczyśći pole
 Jak uod czasu wyćepańo ktoś utworzůł nowo zajta uo idyntycznym mjańy, uodtwarzane wersyje znojdům śe w jeij historyji, a uobecno wersyjo pozostańy bez půmjyńań.',
 'undeleterevdel' => 'Wćepańy nazod zajty ńy bydźe přeprowadzůne kej by můguo spowodować tajlowe wyćepańy aktualnej wersyji.
 W takej sytuacyji noležy uodznačyć abo přiwrůćić widočność nojnowšym wyćepanym wersjům.',
-'undeletehistorynoadmin' => 'Ta zajta zostoua wyćepano.
-Powůd wyÄ\87epaÅ\84o je podany w podsůmowaÅ\84u půÅ\84¾ej, razym s danymi užytkowÅ\84ika, kery sprawjou zajta pÅ\99ed jei wyćepańym.
-Sama treść wyćepanych wersyji je dostympna ino do admińistratorůw',
+'undeletehistorynoadmin' => 'Ta zajta zostoła wyćepano.
+Powůd wyÄ\87epaÅ\84o je podany w podsůmowaÅ\84u půÅ\84¼yj, razym ze danymi użytkowÅ\84ika, kery sprowjoÅ\82 zajta przed jei wyćepańym.
+Samo treść wyćepanych wersyji je dostympna ino do admińistratorůw',
 'undelete-revision' => 'Wyćepńynto wersyjo $1 (s $5 $4) keryj autorym je $3:',
 'undeleterevision-missing' => 'Felerno abo brakujůnco wersyjo.
-MožeÅ¡ mjeÄ\87 felerny link abo wersyjo můgua zostaÄ\87 wÄ\87epano nazod, abo wyÄ\87epano s archiwům.',
+Możesz mjeÄ\87 felerny link abo wersyjo můgÅ\82a zostaÄ\87 wÄ\87epano nazod, abo wyÄ\87epano ze archiwům.',
 'undelete-nodiff' => 'Ńy znejdźono popřednich wersyji.',
-'undeletebtn' => 'Uodtwůř',
+'undeletebtn' => 'Uodtwůrz',
 'undeletelink' => 'ukoż abo uodtwůrz',
 'undeleteviewlink' => 'ukoż',
 'undeletereset' => 'Wyčyść',
@@ -1875,12 +1938,12 @@ $1',
 'blanknamespace' => '(przodńo)',
 
 # Contributions
-'contributions' => 'Ajnzac sprowjorza',
+'contributions' => 'Ajnzac {{GENDER:$1|używocza|używoczki}}',
 'contributions-title' => 'Wkłod użytkowńika $1',
-'mycontris' => 'Uody mje sprowjane',
-'contribsub2' => 'Do užytkowńika $1 ($2)',
+'mycontris' => 'Sprowjyńa',
+'contribsub2' => 'Lo {{GENDER:$3|używocza|używoczki}} $1 ($2)',
 'nocontribs' => 'Brak pomjyńań uodpowjadajůncych tym kryterjům.',
-'uctop' => '(uostatnio)',
+'uctop' => '(teroźńo)',
 'month' => 'Uod mjeśůnca (i downiyjše):',
 'year' => 'Uod roku (i dowńijše):',
 
@@ -1914,15 +1977,15 @@ $1',
 'whatlinkshere-hideredirs' => '$1 {{PLURAL:$1|punkńyńćy|punkńyńćo|puńkńyńć}}',
 'whatlinkshere-hidetrans' => '$1 {{PLURAL:$1|dokuplowańy|dokuplowańo|dokuplowań}}',
 'whatlinkshere-hidelinks' => '$1 {{PLURAL:$1|link|linki|linkůw}}',
-'whatlinkshere-hideimages' => '$1 linki s grafik',
+'whatlinkshere-hideimages' => '$1 linki ze plikůw',
 'whatlinkshere-filters' => 'Filtery',
 
 # Block/unblock
 'blockip' => 'Zawrzij sprowjorza',
 'blockip-legend' => 'Zawrzij sprowjorza',
-'blockiptext' => 'Tyn formulař suužy do zawjerańo sprowjyń spod uokreślůnygo adresu IP abo kůnkretnymu užytkowńikowi.
-ZawjeraÄ\87 noležy jydyÅ\84y po to, by zapobjec wandalizmům, zgodÅ\84y s [[{{MediaWiki:Policy-url}}|pÅ\99ijyntymi zasadami]].
-Podej powůd (np. umješčajůnc mjana zajtůw, na kerych dopuščůno śe wandalizmu).',
+'blockiptext' => 'Tyn formularz służy do zawjerańo sprowjyń spod uokreślůnygo adresu IP abo kůnkretnymu użytkowńikowi.
+ZawjeraÄ\87 noleży jydyÅ\84y po to, by zapobjec wandalizmům, zgodÅ\84y ze [[{{MediaWiki:Policy-url}}|przijyntymi reglůma]].
+Podej powůd (np. umjeszczajůnc mjana zajtůw, na kerych dopuszczůno śe wandalizmu).',
 'ipadressorusername' => 'Adres IP abo mjano użytkowńika',
 'ipbexpiry' => 'Wygaso:',
 'ipbreason' => 'Čymu:',
@@ -1936,12 +1999,12 @@ Podej powůd (np. umješčajůnc mjana zajtůw, na kerych dopuščůno śe wanda
 ** Ůsuwańy treśći zajtůw
 ** Wprowadzańy fołszywych informacyji
 ** Wulgaryzmy
-** Wypisywańy guůpot na zajtach',
+** Wypisywańy gůpot na zajtach',
 'ipbcreateaccount' => 'Ńy dozwůl utwožyć kůnta',
-'ipbemailban' => 'Zawřij možliwość wysůuańo e-brifůw',
+'ipbemailban' => 'Zawrzij mogebność wysůłańo e-brifůw',
 'ipbenableautoblock' => 'Zawřij uostatńi adres IP tygo užytkowńika i autůmatyčńy wšyjstke kolejne, s kerych bydźe průbowou sprowjać zajty',
 'ipbsubmit' => 'Zawřij uod sprowjyń tygo užytkowńika',
-'ipbother' => 'Ikšy čas',
+'ipbother' => 'Ikszy czas',
 'ipboptions' => '2 godźiny:2 hours,1 dźyń:1 day,3 dńi:3 days,1 tydźyń:1 week,2 tydńe:2 weeks,1 mjeśůnc:1 month,3 mjeśůnce:3 months,6 mjeśůncůw:6 months,1 rok:1 year,nawdy:infinite',
 'ipbotheroption' => 'inkšy',
 'ipbotherreason' => 'Inkšy powůd:',
@@ -1978,7 +2041,7 @@ Přyńdź do [[Special:BlockList|listy zawartych adresůw IP]] coby přejřeć z
 'unblocklink' => 'uodymknij',
 'change-blocklink' => 'půmjyń zawarće uod sprowjyń',
 'contribslink' => 'ajnzace',
-'autoblocker' => 'Zawarto Ci sprowjyńo autůmatyčńy, bez tůž co užywaš tygo samygo adresu IP, co užytkowńik „[[User:$1|$1]]”.
+'autoblocker' => 'Zawarto Ci sprowjyńo autůmatyczńy, bez tůż co używosz tygo samygo adresu IP, co używocz „[[User:$1|$1]]”.
 Powůd zawarća $1 to: „$2”',
 'blocklogpage' => 'Gyszichta zawjyrańo',
 'blocklogentry' => 'zawarto [[$1]], bydźe uodymkńynty: $2 $3',
@@ -1988,8 +2051,8 @@ Na li'śće ńy mo adresůw IP, kere zawarto w sposůb autůmatyčny.
 Coby přejřeć lista uobecńy aktywnych zawarć, přyńdź na zajta [[Special:BlockList|zawartych adresůw i užytkowńikůw]].",
 'unblocklogentry' => 'uodymknyu $1',
 'block-log-flags-anononly' => 'ino anůnimowi',
-'block-log-flags-nocreate' => 'tworzińy kůnta je zawrzite',
-'block-log-flags-noautoblock' => 'autůmatyčne zawjerańy uod sprawjyń wůuůnčůne',
+'block-log-flags-nocreate' => 'tworzińy kůnta je zawarte',
+'block-log-flags-noautoblock' => 'autůmatyczne zawjerańy uod sprawjyń wyłůnczůne',
 'block-log-flags-noemail' => 'e-brif zawarty',
 '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',
@@ -2032,7 +2095,7 @@ Zawjerańy i uodmykańy bazy danych wymogo coby plik můgu być naškreflany bez
 
 # Move page
 'move-page' => 'Przećep $1',
-'move-page-legend' => 'Přećiś artikel',
+'move-page-legend' => 'Przećiś artikel',
 'movepagetext' => "Przi půmocy formularza půńiżej możesz půmjyńyć mjano zajty i przećepnůńć jej gyszichta. Pod downym mjanym uostańe śa zajta przekerowujůnca. Zajty adresowane na stare mjano uostanům jak bůły.
 
 Jak śe na to decydujesz, sprowdź, eli ńy je to [[Special:DoubleRedirects|podwůjne]] abo [[Special:BrokenRedirects|złomane przekerowańy]].
@@ -2049,23 +2112,23 @@ To może być drastyczno abo ńyprzewidywalno zmjano, jak przećepńysz jako pop
 *ńy přećepuješ zajty do inkšy přestřeńy mjan
 *ńy ma sam zajty godki o takiym mjańe
 W takiych razach tekst godki třa přećepać, a jak třeba to i pouůnčyć z tym co juž sam jest, rynčńe. Abo možeš sie namyślić i nie přećepywać wcale ("checkbox" půnižyi).',
-'movearticle' => 'Přećiś artikel:',
-'movenologin' => 'Ńy jestžeś zalůgowany',
+'movearticle' => 'Przećiś artikel:',
+'movenologin' => 'Ńy jeżeś zalůgowany',
 'movenologintext' => 'Muśyš być zarejerowanym i [[Special:UserLogin|zalůgowanym]] užytkowńikym coby můc přećepnůńć zajta.',
 'movenotallowed' => 'Ńy moš uprownień do přećepywańo zajtůw.',
 'cant-move-user-page' => 'Ńy mosz uprowńyń do przekludzańo zajtůw użytkowńikůw (wyjůntkym sům jejich podstrony).',
 'cant-move-to-user-page' => 'Ńy mosz uprowńyń coby przekludźić zajta na plac kaj je zajta użytkowńika (wyjůntkym sům podzajty użytkowńika).',
 'newtitle' => 'Nowy titel:',
 'move-watch' => 'Dej pozůr',
-'movepagebtn' => 'Přećiś artikel',
-'pagemovedsub' => 'Přećiśńjyńće gotowe',
-'movepage-moved' => '\'\'\'"$1" přećiśńjynto ku "$2"\'\'\'',
-'articleexists' => 'Artikel s takym mjanym juž je, abo mjano je zue.
-Wybjer inkše mjano.',
-'cantmove-titleprotected' => 'Å\83y možeÅ¡ pÅ\99\87epnůÅ\84Ä\87 zajty, bez tůž co jei nowe mjano je Å\84ydozwolůne s kuli zabezpjeÄ\8d\84o pÅ\99ed utwoÅ\99yńym',
-'talkexists' => 'Zajta artikla zostaua přećepano, ale zajta godki ńy - zajta godki uo nowym mjańe juž sam jest. Poůunč, proša, teksty oubydwůch godek rynčńe.',
-'movedto' => 'přećiśńjynto ku',
-'movetalk' => 'Přećiś godke, jak možno.',
+'movepagebtn' => 'Przećiś artikel',
+'pagemovedsub' => 'Przećiśńyńće je fertig',
+'movepage-moved' => '\'\'\'"$1" przećiśńjynto ku "$2"\'\'\'',
+'articleexists' => 'Artikel ze takym mjanym już je, abo mjano je złe.
+Wybjer inksze mjano.',
+'cantmove-titleprotected' => 'Å\83y możesz przeÄ\87epnůÅ\84Ä\87 zajty, beztuż co jeij nowe mjano je Å\84ydozwolůne skuli zabezpjeczyÅ\84o przed utworzyńym',
+'talkexists' => 'Zajta artikla zostoła przećepano, nale zajta godki ńy - zajta godki uo nowym mjańe już sam jest. Połuncz, prosza, teksty uobydwůch godek rynczńe.',
+'movedto' => 'przećiśńjynto ku',
+'movetalk' => 'Przećiś godke, jak możno.',
 '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ć.',
@@ -2074,12 +2137,12 @@ Wybjer inkše mjano.',
 'movepage-max-pages' => 'Przekludzůnych uostało $1 {{PLURAL:$1|zajta|zajty|zajtůw}}. Wjynkszyj liczby ńy idźe przekludźić automatyczńy.',
 'movelogpage' => 'Przećepńynte',
 'movelogpagetext' => 'Uoto lista zajtůw, kere uostatńo zostouy přećepane.',
-'movereason' => 'Čymu:',
+'movereason' => 'Czymu:',
 'revertmove' => 'cofej',
 'delete_and_move' => 'Wyćep i przećep',
-'delete_and_move_text' => '== Přećepańy wymaga wyćepańo inkšyj zajty ==
-Zajta docelowo â\80\9e[[:$1]]â\80\9d juž sam jest.
-Čy chceš jům wyćepać, coby zrobić plac do přećepywanej zajty?',
+'delete_and_move_text' => '== Przećepańy wymogo wyćepańo inkszyj zajty ==
+Zajta docelowo â\80\9e[[:$1]]â\80\9d już sam jest.
+Czy chcysz jům wyćepać, coby zrobić plac do przećepywanej zajty?',
 'delete_and_move_confirm' => 'Toć, wyćep zajta',
 'delete_and_move_reason' => 'Wyćepano coby zrobić plac do přećepywanyj zajty',
 'selfmove' => 'Mjana zajtůw zdřůdowyj i docelowyj sům take same.
@@ -2118,7 +2181,7 @@ Možeš tyž užyć linku, np.[[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] do
 'allmessagesdefault' => 'Tekst důmyślny',
 'allmessagescurrent' => 'Tekst uobecny',
 'allmessagestext' => 'Uoto lista wšyjstkych kůmůńikatůw systymowych dostympnych w přestřyńi mjan MedjaWiki.
-Uodwjydź [//www.mediawiki.org/wiki/Localisation Tuůmačyńy MediaWiki] a tyž [//translatewiki.net translatewiki.net] kejbyś chćou učestńičyć w tuůmačyńu uoprůgramowańo MediaWiki.',
+Uodwjydź [https://www.mediawiki.org/wiki/Localisation Tuůmačyńy MediaWiki] a tyž [//translatewiki.net translatewiki.net] kejbyś chćou učestńičyć w tuůmačyńu uoprůgramowańo MediaWiki.',
 'allmessagesnotsupportedDB' => "Ta zajta ńy može być užyta, bez tůž co zmjynna '''\$wgUseDatabaseMessages''' je wůuůnčůno.",
 
 # Thumbnails
@@ -2285,12 +2348,12 @@ Nojprawdopodobńij zostoło to spowodowane bez link do zewnyntrznyj zajty intern
 
 $1',
 'filedelete-missing' => 'Plika „$1” ńy idźe wyćepać, bo ńy istńije.',
-'filedelete-old-unregistered' => 'Žůndanyj wersyji plika „$1” ńy ma w baźe danych.',
+'filedelete-old-unregistered' => 'Å»ůndanyj wersyji plika „$1” ńy ma w baźe danych.',
 'filedelete-current-unregistered' => 'Plika „$1” ńy ma w baźe danych.',
-'filedelete-archive-read-only' => 'Serwer WWW Å\84y može naÅ¡kryflaÄ\87 w katalůgu s archiwůma „$1”.',
+'filedelete-archive-read-only' => 'Serwer WWW Å\84y może naszkryflaÄ\87 we katalogu ze archiwůma „$1”.',
 
 # Browsing diffs
-'previousdiff' => '← Popředńy sprowjyńy',
+'previousdiff' => '← Poprzedńy sprowjyńy',
 'nextdiff' => 'Nostympne sprowjyńy →',
 
 # Media information
@@ -2302,12 +2365,12 @@ $1',
 'file-info-size' => '$1 × $2 pikselůw, wjelgość plika: $3, zorta MIME: $4',
 'file-nohires' => 'Wjynksze wymjyry ńy sům dostympne',
 'svg-long-desc' => 'Plik SVG, nůminalńe $1 × $2 pixelůw, rozmior plika: $3',
-'show-big-image' => 'Pełne wymjyry',
+'show-big-image' => 'Pjyrwy wymjor',
 
 # Special:NewFiles
 'newimages' => 'Galerjo nowych uobrozků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 tyi ekstra zajće prezyntowane sům uostatńo wćepńynte pliki.',
+'newimages-summary' => 'Na tyj ekstra zajće prezyntowane sům uostatńo wćepńynte pliki.',
 'newimages-legend' => 'Filtruj',
 'newimages-label' => 'Mjano plika (abo jygo tajla):',
 'showhidebots' => '($1 boty)',
@@ -2378,8 +2441,8 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 'exif-colorspace' => 'Přestřyń kolorůw',
 'exif-componentsconfiguration' => 'Značyńy skuadowych',
 'exif-compressedbitsperpixel' => 'Skůmpresowanych bitůw na piksel',
-'exif-pixelydimension' => 'Prawiduowa šyrokość uobrozu',
-'exif-pixelxdimension' => 'Prawiduowo wysokość uobrozu',
+'exif-pixelydimension' => 'Prawidłowa szyrzka uobrozu',
+'exif-pixelxdimension' => 'Prawidłowo wyżka uobrozu',
 'exif-usercomment' => 'Kůmyntoř užytkowńika',
 'exif-relatedsoundfile' => 'Powjůnzany plik audjo',
 'exif-datetimeoriginal' => 'Data i čas utwořyńo uoryginouu',
@@ -2393,8 +2456,8 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 'exif-exposureprogram' => 'Progrům ekspozycyji',
 'exif-spectralsensitivity' => 'Čuuość widmowa',
 'exif-isospeedratings' => 'Šybkość aparatu zgodńy ze ISO12232',
-'exif-shutterspeedvalue' => 'Šybkość migawki',
-'exif-aperturevalue' => 'Přisuůna uobjektywu',
+'exif-shutterspeedvalue' => 'Wartkość migawki',
+'exif-aperturevalue' => 'Przisłůna uobjektywu',
 'exif-brightnessvalue' => 'Jasność',
 'exif-exposurebiasvalue' => 'Uodchylyńy ekspozycyji',
 'exif-maxaperturevalue' => 'Maksymalno wartość přisuůny',
@@ -2439,7 +2502,7 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 'exif-gpsmeasuremode' => 'Tryb půmjaru',
 'exif-gpsdop' => 'Precyzjo půmjaru',
 'exif-gpsspeedref' => 'Jydnostka gibkości',
-'exif-gpsspeed' => 'Gibkość poźomo',
+'exif-gpsspeed' => 'Gibkość poźůmo',
 'exif-gpstrackref' => 'Poprawka půmjyndzy kerůnkym i celym',
 'exif-gpstrack' => 'Kerunek ruchu',
 'exif-gpsimgdirectionref' => 'Poprawka do kerůnku zdjyńćo',
@@ -2468,9 +2531,9 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 'exif-orientation-3' => 'uobroz uobrůcůny uo 180°',
 'exif-orientation-4' => 'uodbiće we źřadle w pjůńy',
 'exif-orientation-5' => 'uobroz uobrůcůny uo 90° přećiwńy do ruchu wskazůwek zygora i uodbiće we źřadle w pjůńy',
-'exif-orientation-6' => 'uobroz uobrůcůny uo 90° zgodńy s ruchym wskazůwek zygora',
+'exif-orientation-6' => 'Uobroz uobrůcůny uo 90° przećiwńy lo ruchu wskazůwek zygora',
 'exif-orientation-7' => 'uobrůt uo 90° zgodńy ze wskazůwkůma zygora i uodbiće we źřadle w pjůńy',
-'exif-orientation-8' => 'uobrůt uo 90° přećiwńy do wskazůwek zygora',
+'exif-orientation-8' => 'uobrůt uo 90° zgodńy do ruchu wskazůwek zygora',
 
 'exif-planarconfiguration-1' => 'format masywny',
 'exif-planarconfiguration-2' => 'format powjeřchńowy',
@@ -2559,7 +2622,7 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 'exif-gaincontrol-1' => 'ńiske wzmocńyńe',
 'exif-gaincontrol-2' => 'wysoke wzmocńyńe',
 'exif-gaincontrol-3' => 'ńiske uosuabjyńy',
-'exif-gaincontrol-4' => 'wysoke uosuabjyńy',
+'exif-gaincontrol-4' => 'wysoke uosłabjyńy',
 
 'exif-contrast-0' => 'normalny',
 'exif-contrast-1' => 'Lichy',
@@ -2603,7 +2666,7 @@ Eli plik był modyfikowany, dane mogům w tajli ńy być we zgodźe ze parametr
 
 # External editor support
 'edit-externally' => 'Sprowjej tyn plik bez eksterno aplikacyjo',
-'edit-externally-help' => '(Zobocz [//www.mediawiki.org/wiki/Manual:External_editors instrukcyje sztalowańo eksternych edytorůw], kaj je uo tym wjyncy naszkryflůne)',
+'edit-externally-help' => '(Zobocz [https://www.mediawiki.org/wiki/Manual:External_editors instrukcyje sztalowańo eksternych edytorůw], kaj je uo tym wjyncy naszkryflůne)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'do kupy',
@@ -2686,10 +2749,10 @@ Potwjerdź chęć wćepańo nazod tygo artikla.",
 'table_pager_empty' => 'Brak wynikůw',
 
 # Auto-summaries
-'autosumm-blank' => 'POZŮR! Usůńjyńće treśći (zajta pozostoua pusto)!',
+'autosumm-blank' => 'POZŮR! Usůńjyńće treśći (zajta pozostoła pusto)!',
 'autosumm-replace' => 'POZŮR! Zastůmpjyńy treśći hasua bardzo krůtkym tekstym: „$1”',
 'autoredircomment' => 'Překerowańy do [[$1]]',
-'autosumm-new' => 'Nowo zajta: $1',
+'autosumm-new' => 'Wćepano nowo zajta: "$1"',
 
 # Live preview
 'livepreview-loading' => 'Trwo uadowańy…',
@@ -2706,9 +2769,9 @@ Potwjerdź chęć wćepańo nazod tygo artikla.",
 'watchlistedit-noitems' => 'Twoja lista artikli na kere dowoš pozůr je pusto.',
 'watchlistedit-normal-title' => 'Sprowjej lista zajtůw na kere dowom pozůr',
 'watchlistedit-normal-legend' => 'Wyćep zajty s listy artikli na kere dowoš pozůr',
-'watchlistedit-normal-explain' => 'PůÅ\84¾y moÅ¡ lista artikli na kere dowoÅ¡ pozůr.
-Coby wyćepać s ńij jako zajta,zaznač pole při ńij i naćiś knefel "Wyćep zaznačůne pozycyje".
-MožeÅ¡ tyž skoÅ\99istaÄ\87 ze [[Special:EditWatchlist/raw|tekstowygo edytora listy artikli na kere dowoÅ¡ pozůr]].',
+'watchlistedit-normal-explain' => 'PůÅ\84¼yj mosz lista artikli na kere dowosz pozůr.
+Coby wyćepać z ńij jako zajta, zaznocz pole przi ńij i naćiś knefel „{{int:Watchlistedit-normal-submit}}”.
+Możesz tyż skorzistaÄ\87 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-raw-title' => 'Tekstowy edytor listy artikli na kere dowoš pozůr',
@@ -2734,9 +2797,9 @@ Možeš tyž [[Special:EditWatchlist|užyć standardowygo edytora]].',
 'version' => 'Wersjo',
 'version-extensions' => 'Zainstalowane rozšeřyńa',
 'version-specialpages' => 'Szpecjalne zajty',
-'version-parserhooks' => 'Haki analizatora skuadńi (ang. parser hooks)',
+'version-parserhooks' => 'Haki analizatora składńi (yng. parser hooks)',
 'version-variables' => 'Zmjynne',
-'version-other' => 'Inkše',
+'version-other' => 'Inksze',
 'version-mediahandlers' => 'Wtyčki uobsůgi medjůw',
 'version-hooks' => 'Haki (ang. hooks)',
 'version-parser-extensiontags' => 'Značńiki rozšeřyń do analizatora skuadńi',
@@ -2761,19 +2824,18 @@ Možeš tyž [[Special:EditWatchlist|užyć standardowygo edytora]].',
 
 # Special:SpecialPages
 'specialpages' => 'Szpecjalne zajty',
-'specialpages-note' => '----
-* Ekstra zajty uogůlńy dostympne.
+'specialpages-note' => '* Ekstra zajty uogůlńy dostympne.
 * <strong class="mw-specialpagerestricted">Ekstra zajty do kerych dostymp je uograńiczůny.</strong>',
 'specialpages-group-maintenance' => 'Raporty kůnserwacyjne',
 'specialpages-group-other' => 'Inkše ekstra zajty',
-'specialpages-group-login' => 'Lůgowańy / rejerowańy',
+'specialpages-group-login' => 'Logowańy / regisztrowańy',
 'specialpages-group-changes' => 'Pomjyńane na uostatku a rejery',
 'specialpages-group-media' => 'Pliki',
 'specialpages-group-users' => 'Użytkowńiki i uprawńyńa',
 'specialpages-group-highuse' => 'Zajty čynsto užywane',
-'specialpages-group-pages' => 'Zajty',
+'specialpages-group-pages' => 'Listy zajt',
 'specialpages-group-pagetools' => 'Nořyńdźa zajtůw',
-'specialpages-group-wiki' => 'Informacyje a nořyńdźa wiki',
+'specialpages-group-wiki' => 'Informacyje a werkcojgi wiki',
 'specialpages-group-redirects' => 'Ekstra zajty, kere kerujům',
 'specialpages-group-spam' => 'Nořyńdźa do wyćepywanio spamu',
 
@@ -2798,4 +2860,7 @@ Možeš tyž [[Special:EditWatchlist|užyć standardowygo edytora]].',
 'revdelete-unrestricted' => 'wycofej uograničyńo do administratorůw',
 'rightsnone' => 'podstawowo',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'OK',
+
 );
index d2fd4c6..c2d9245 100644 (file)
@@ -94,7 +94,7 @@ $messages = array(
 'tog-extendwatchlist' => 'அனைத்து பொருத்தமான மாற்றங்களைக் காட்டுமாறு கவனிப்புப் பட்டியலை விரிவாக்கு',
 'tog-usenewrc' => 'அண்மைய மாற்றங்கள் மற்றும் கவனிப்புப் பட்டியல் பக்கத்தில் மாற்றங்களை பக்கத்தை பொறுத்து குழுவாக்கு',
 'tog-numberheadings' => 'தலைப்புகளுக்கு தானியங்கி இலக்கமிடு',
-'tog-showtoolbar' => 'கருவிப் பட்டையைக் காட்டு',
+'tog-showtoolbar' => 'கருவிப்பட்டையைக் காட்டு',
 'tog-editondblclick' => 'இரட்டைச் சொடுக்கில் பக்கங்களைத் தொகு',
 'tog-editsection' => '(தொகு) இணைப்புகளின் வழியாக பிரிவுத் தொகுத்தலை செயலாக்கவும்',
 'tog-editsectiononrightclick' => 'பிரிவுத் தலைப்பின் மீது வலச் சொடுக்குவதன் மூலம் பகுதித்  தொகுப்பை செயலாக்கவும்',
@@ -115,7 +115,7 @@ $messages = array(
 'tog-shownumberswatching' => 'கவனிக்கும் பயனர்களின் எண்ணிக்கையைக் காட்டவும்',
 'tog-oldsig' => 'நடப்பு கையொப்பம்:',
 'tog-fancysig' => 'வெற்றுக் கையொப்பம் (தானியங்கி இணைப்பின்றி)',
-'tog-uselivepreview' => 'நேரடி முன்தோற்றத்தைப் பயன்படுத்து (சோதனையிலுள்ளது)',
+'tog-uselivepreview' => 'நேரடி முன்தோற்றத்தைப் பயன்படுத்துங்கள் (சோதனையிலுள்ளது)',
 'tog-forceeditsummary' => 'தொகுப்புச் சுருக்கம் வெற்றாக இருக்கும் போது எனக்கு நினைவூட்டு',
 'tog-watchlisthideown' => 'எனது தொகுப்புக்களைக் கவனிப்புப் பட்டியலிலிருந்து மறை',
 'tog-watchlisthidebots' => 'தானியங்கித் தொகுப்புக்களைக் கவனிப்புப் பட்டியலிலிருந்து மறை',
@@ -229,7 +229,7 @@ $messages = array(
 'newwindow' => '(புதிய சாளரத்துள் திறக்கும்)',
 'cancel' => 'சேமிக்காமல் திரும்பு',
 'moredotdotdot' => 'மேலும்...',
-'morenotlisted' => 'இந்த பட்டியல்கல் முழுமையாக்கவில்லை.',
+'morenotlisted' => 'இந்தப் பட்டியல் முழுமையானதல்ல.',
 'mypage' => 'பக்கம்',
 'mytalk' => 'பேச்சு',
 'anontalk' => 'இந்த ஐ.பி. முகவரிக்கான பேச்சு',
@@ -304,7 +304,7 @@ $messages = array(
 'articlepage' => 'உள்ளடக்கப் பக்கத்தைப் பார்',
 'talk' => 'உரையாடல்',
 'views' => 'பார்வைகள்',
-'toolbox' => 'à®\95à®°à¯\81விபà¯\8d à®ªà¯\86à®\9fà¯\8dà®\9fி',
+'toolbox' => 'à®\95à®°à¯\81விà®\95ளà¯\8d',
 'userpage' => 'பயனர் பக்கத்தைப் பார்',
 'projectpage' => 'திட்டப் பக்கத்தைப் பார்',
 'imagepage' => 'கோப்புப் பக்கத்தை நோக்க',
@@ -334,7 +334,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}} பற்றி',
 'aboutpage' => 'Project:விவரம்',
-'copyright' => 'உள்ளடக்கங்கள் $1 இன் கீழ் கிடைக்கின்றன.',
+'copyright' => 'à®\95à¯\81றிà®\95à¯\8dà®\95பà¯\8dபà®\9fபà¯\8dபà®\9fாவிà®\9fà¯\8dà®\9fாலà¯\8d à®\89ளà¯\8dளà®\9fà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளà¯\8d $1 à®\87னà¯\8d à®\95à¯\80à®´à¯\8d à®\95ிà®\9fà¯\88à®\95à¯\8dà®\95ினà¯\8dறன.',
 'copyrightpage' => '{{ns:project}}:பதிப்புரிமை',
 'currentevents' => 'தற்போதைய நிகழ்வுகள்',
 'currentevents-url' => 'Project:நடப்பு நிகழ்வுகள்',
@@ -360,8 +360,6 @@ $1',
 'ok' => 'சரி',
 'retrievedfrom' => '"$1" இருந்து மீள்விக்கப்பட்டது',
 'youhavenewmessages' => 'உங்களுக்குப் $1 உள்ளன ($2).',
-'newmessageslink' => 'புதிய செய்திகள்',
-'newmessagesdifflink' => 'கடைசி மாற்றம்',
 'youhavenewmessagesfromusers' => 'உங்களுக்கு $1 {{PLURAL:$3|வேறொரு பயனரிடம்|$3 பயனர்களிடம்}} இருந்து உள்ளது ($2).',
 'youhavenewmessagesmanyusers' => 'உங்களுக்கு பல பயனர்களிடமிருந்து $1 பதிய செய்திகள்  உள்ளன ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ஒரு புதிய செய்தி|புதிய செய்திகள்}}',
@@ -460,7 +458,7 @@ $1',
 'viewsource-title' => '$1க்கான மூலத்தைப்  பார்',
 'actionthrottled' => 'செயற்பாடு கட்டுப்படுத்தப்பட்டது',
 'actionthrottledtext' => 'எரிதக் காப்பு நடவடிக்கையாகப் பயனொருவர் குறித்த சிறு கால இடைவெளியில் இச்செயற்பாட்டை அதிகளவில் செய்வது தடுக்கப்பட்டுள்ளது. நீர் அவ்வெல்லையைத் தாண்டிவிட்டீர். அருள் கூர்ந்து சில நிமிடங்களில் முயலவும்.',
-'protectedpagetext' => 'இப்பக்கம் தொகுக்கப்படுவதை தவிர்ப்பதற்காக பூட்டப்பட்டுள்ளது.',
+'protectedpagetext' => 'இப்பக்கம் தொகுக்கப்படுவதையோ அல்லது பிற செயல்களைத் தவிர்ப்பதற்காகவோ பூட்டப்பட்டுள்ளது.',
 'viewsourcetext' => 'நீங்கள் இந்தப் பக்கத்தின் மூலத்தைப் பார்க்கவும் அதனை நகலெடுக்கவும் முடியும்:',
 'viewyourtext' => "நீங்கள் இந்த பக்கத்திற்கான ''' உங்கள் திருத்தங்களுக்கான ''' மூலத்தைக் காணவும்  நகலெடுக்கவும் முடியும்.",
 'protectedinterface' => 'இப்பக்கம் இம்மென் பொருளுக்கான பயனர் இடைமுக உரைகளை வழங்குகிறது, விசம தொகுப்புக்களை தவிர்ப்பதற்க்காக இப்பக்கம் பூட்டப்பட்டுள்ளது.',
@@ -526,9 +524,10 @@ $1',
 'gotaccount' => "ஏற்கனவே பயனர் கணக்கு உள்ளதா? '''$1'''.",
 'gotaccountlink' => 'புகுபதிகை',
 'userlogin-resetlink' => 'உங்கள் புகுபதிகைக் குறிப்புகளை மறந்துவிட்டீர்களா?',
-'userlogin-resetpassword-link' => 'உங்கள் கடவுச்சொல் மறந்துவிட்டதா?',
+'userlogin-resetpassword-link' => 'உங்கள் கடவுச் சொல்லை மறந்து விட்டீர்களா?',
 'helplogin-url' => 'Help:புகுபதிகை',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|புகுபதிவதற்கான உதவி]]',
+'userlogin-createanother' => 'மற்றொரு கணக்கு ஒன்றை உருவாக்கவும்',
 'createacct-join' => 'உங்களின் தகவலை கீழிடவும்',
 'createacct-another-join' => 'கீழே புதிய கணக்கிற்கான தகவல்களை உள்ளிடவும்.',
 'createacct-emailrequired' => 'மின்னஞ்சல் முகவரி',
@@ -585,7 +584,8 @@ $1',
 'noemailcreate' => 'ஒரு செல்லத்தக்க மின்னஞ்சல் முகவரியை நீங்கள் தரவேண்டும்.',
 'passwordsent' => '"$1" பயனருக்கான மின்னஞ்சல் முகவரிக்கு ஒரு புதிய கடவுச்சொல் அனுப்பப்பட்டுள்ளது. பெற்றுக்கொண்டதும் தயவுசெய்து மீண்டும் புகுபதிகை செய்யவும்.',
 'blocked-mailpassword' => 'உங்கள் ஐ.பி. முகவரி தடுக்கப்பட்டுள்ளது, விசம செயற்பாடுகளைத் தவிர்க்க கடவுச்சொல் மீட்புச் செயலியை நீங்கள் பயன்படுத்து அனுமதிக்கப்படவில்லை.',
-'eauthentsent' => 'உறுதிப்படுத்தல் மின்னஞ்சலொன்று நீங்கள் கொடுத்த மின்னஞ்சல் முகவரிக்கு அனுப்பப் பட்டுள்ளது. மேலதிகமாக எந்த மின்னஞ்சலும் இந்த முகவரிக்கு அனுப்பப்படு முன்னர், மின்னலில் கொடுக்கப்பட்டுள்ள அறிவுறுத்தல்களின் படி, இம்மின்னஞ்சல் முகவரி உங்களுடையது என்பதை உறுதிப்படுத்தவும்.',
+'eauthentsent' => 'உறுதிப்படுத்தல் மின்னஞ்சலொன்று நீங்கள் கொடுத்த மின்னஞ்சல் முகவரிக்கு அனுப்பப் பட்டுள்ளது.
+மேலும் மின்னஞ்சல்கள் இந்த முகவரிக்கு அனுப்பப்படும் முன்னர், மின்னஞ்சலில் கொடுக்கப்பட்டுள்ள வழிமுறைகளை பின்பற்றி, இம்மின்னஞ்சல் முகவரி உங்களுடையது தான் என்பதை உறுதிப்படுத்தவும்.',
 'throttled-mailpassword' => 'கடந்த {{PLURAL:$1|மணிநேரத்துக்குள்|$1 மணிநேரங்களுக்குள்}} ஒரு கடவுச்சொல் நினைவூட்டல் மின்னஞ்சல் ஏற்கனவே அனுப்பப்பட்டுவிட்டது. விசமப் பயன்பாடுகளைத் தவிர்ப்பதற்காக {{PLURAL:$1|மணிநேரத்திற்கு|$1 மணிநேரங்களுக்கு}} ஒரு கடவுச்சொல் நினைவூட்டல் மின்னஞ்சல் மட்டுமே அனுப்பப்படும்.',
 'mailerror' => 'மின்னஞ்சல் அனுப்புவதில் தவறு: $1',
 'acct_creation_throttle_hit' => 'தங்களது IP முகவரியை பயன்படுத்தி இந்த விக்கியில் நேற்று {{PLURAL:$1|1 கணக்கு |$1 கணக்குகள்}} உருவாக்கப்பட்டுள்ளது.  தற்போது இதுவே மிக அதிகமாக அனுமதிக்கப்பட்ட அளவாகும்.
@@ -638,8 +638,11 @@ $1',
 
 # Special:PasswordReset
 'passwordreset' => 'கடவுச்சொல்லை மீட்டமை',
+'passwordreset-text-one' => 'உங்கள் கடவுச்சொல்லை மீட்டமைக்க இந்த படிவத்தை நிறைவு செய்க.',
+'passwordreset-text-many' => '{{PLURAL:$1|உங்கள் கடவுச்சொல்லை மீட்டமைக்க புலங்கள் ஒன்றினை நிரப்பவும்.}}',
 'passwordreset-legend' => 'கடவுச்சொல்லை மீட்டமை',
 'passwordreset-disabled' => 'கடவுச்சொல் மீட்டமைப்பு இந்த விக்கியில் செயலிழக்க செய்யப்பட்டுள்ளது.',
+'passwordreset-emaildisabled' => 'மின்னஞ்சல் வசதி இந்த விக்கியில் முடக்கப்பட்டுள்ளது.',
 'passwordreset-username' => 'பயனர் பெயர்:',
 'passwordreset-domain' => 'இணையதள முகவரி:',
 'passwordreset-capture' => 'விளைவு மின்னஞ்சலை காண்',
@@ -751,9 +754,7 @@ $1 எனும் பயனரையோ வேறு [[{{MediaWiki:Grouppage-sy
 'loginreqlink' => 'புகுபதிகை',
 'loginreqpagetext' => 'ஏனைய பக்கங்களைப் பார்க்க  நீங்கள் $1 செய்ய வேண்டும்.',
 'accmailtitle' => 'கடவுச்சொல் அனுப்பப்பட்டுள்ளது.',
-'accmailtext' => "தான்தோன்றித்தனமான ஒரு கடவுச்சொல்லை [[User talk:$1|பயனர் பேச்சு:$1|$1]] $2-க்கு அனுப்பி வைக்கப்பட்டுள்ளது.
-
-இந்த புதிய கணக்கிற்கான கடவுச்சொல்லை புகுபதிகை செய்தவுடன் மாற்றிக்கொள்ளவும் ''[[Special:ChangePassword|கடவுச்சொல்லை மாற்று]]''.",
+'accmailtext' => "தானியக்கமாக [[User talk:$1|$1]]-க்கு ஒரு கடவுச்சொலை உறுவாக்கி $2-க்கு அனுப்பி வைக்கப்பட்டுள்ளது. இதனை புகுபதிகை செய்தவுடன் ''[[Special:ChangePassword|கடவுச்சொல்லை மாற்று]]'' பக்கத்தில் மாற்றிக்கொள்ளளாம்.",
 'newarticle' => '(புதிது)',
 'newarticletext' => 'ஒரு இணைப்பினூடாக நீங்கள் வந்துள்ள இப்பக்கம் இன்னும் உருவாக்கப்படவில்லை. பக்கத்தை உருவாக்குவதற்குக் கீழேயுள்ள கட்டத்துள் தட்டச்சிடத் தொடங்குங்கள். (மேலதிக விபரங்களுக்கு [[{{MediaWiki:Helppage}}|உதவிப் பக்கத்தைப்]] பார்க்கவும்). நீங்கள் தவறுதலாக இங்கே வந்திருந்தால், உங்கள் உலாவியின் பின் செல்வதற்கான பொத்தானைச் சொடுக்கவும்.',
 'anontalkpagetext' => "----''இது இன்னும் கணக்கொன்று ஏற்படுத்தாத அல்லது வழமையாக பயனர் கணக்கை பயன்படுத்தாத பயனர்களுக்குரிய கலந்துரையாடல் பக்கமாகும். அதனால் நாங்கள் இவரை அடையாளம் காண்பதற்கு எண்சார்ந்த ஐபி முகவரியைப் பயன்படுத்த வேண்டியதாய் இருக்கின்றது. இவ்வாறான ஐபி முகவரிகள் பல பயனர்களினால் பகிர்ந்துகொள்ளப்படலாம்.
@@ -767,12 +768,11 @@ $1 எனும் பயனரையோ வேறு [[{{MediaWiki:Grouppage-sy
 'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" என்றக் கணக்கு இன்னமும் பதிவுச் செய்யப்படவில்லை. இதை உருவாக்க/தொகுக்க வேண்டுமா என்பதை உறுதிப்படுத்தவும்.',
 'userpage-userdoesnotexist-view' => 'பயனர் கணக்கு "$1" பதியப்படவில்லை',
 'blocked-notice-logextract' => 'இந்தப் பயனர் தற்சமயம் தடை செய்யப்பட்டுள்ளார். இவரது தடை பதிகையின் அண்மைய மாற்றம் கீழே தரப்பட்டுள்ளது:',
-'clearyourcache' => "'''à®\95வனிà®\95à¯\8dà®\95''' - சேமித்த பின்னர், நீங்கள் செய்த மாற்றங்களைக் காண்பதற்கு உங்கள் உலவியின் இடைமாற்று அகற்றப்பட வேண்டும்.'''
+'clearyourcache' => "'''à®\95à¯\81றிபà¯\8dபà¯\81''' - சேமித்த பின்னர், நீங்கள் செய்த மாற்றங்களைக் காண்பதற்கு உங்கள் உலவியின் இடைமாற்று அகற்றப்பட வேண்டும்.'''
 *'''மொஸில்லா பயர்பாக்ஸ் / சபாரி:''' ''Shift+Reload'', அல்லது ''Ctrl-F5'' அல்லது ''Ctrl-R'' (''⌘-R'' Mac ல்)
 *'''கூகிள் குரோம்''' ''Ctrl-Shift-R'' அழுத்தவும். (''⌘-Shift-R''  Mac ல்) ;
-*'''கொன்குவெரர்: ''' ''Reload'' அல்லது ''F5'' கிளிக் செய்யவும்;
-*'''ஒபேரா:''' ''Tools → Preferences'' இல் இடைமாற்றை அகற்றவும்;
-*'''இண்டர்நெட் எக்ஸ்ப்ளோரர்:''' ''Ctrl-Refresh'' அல்லது ''Ctrl-F5'' ஐ அழுத்தவும்.",
+*'''இண்டர்நெட் எக்ஸ்ப்ளோரர்:''' ''Ctrl-Refresh'' அல்லது ''Ctrl-F5'' ஐ அழுத்தவும்.
+*'''ஒபேரா:''' ''Tools → Preferences'' இல் இடைமாற்றை அகற்றவும்;",
 'usercssyoucanpreview' => "'''சிறு உதவி:''' தங்களது சி.எஸ்.எஸ்(CSS)-ஐ சேமிப்பதற்கு முன்பாக \"{{int:showpreview}}\" பொத்தானைப் பயனபடுத்தி சோதனை செய்யவும்",
 'userjsyoucanpreview' => "'''சிறு உதவி:''' தங்களது ஜாவா-வரிவடிவத்தை (JavaScript-ஐ) சேமிப்பதற்கு முன்பாக \"{{int:showpreview}}\" பொத்தானைப் பயனபடுத்தி சோதனை செய்யவும்",
 'usercsspreview' => "'''உங்களது பயனர் சி.எஸ்.எஸ். இன் முன் தோற்றத்தை மட்டுமே காண்கிறீர்கள் என்பதை நினைவில் கொள்ளவும்.'''
@@ -925,7 +925,7 @@ $1 எனும் பயனரையோ வேறு [[{{MediaWiki:Grouppage-sy
 'history-fieldset-title' => 'வரலாற்றில் தேடவும்',
 'history-show-deleted' => 'நீக்கப்பட்டவை மட்டும்',
 'histfirst' => 'மிகப் பழைய',
-'histlast' => 'மிக புதிய',
+'histlast' => 'மிகப் புதிய',
 'historysize' => '({{PLURAL:$1|1 பைட்டு|$1 பைட்டுகள்}})',
 'historyempty' => '(வெற்று)',
 
@@ -1000,8 +1000,8 @@ $1 எனும் பயனரையோ வேறு [[{{MediaWiki:Grouppage-sy
 'revdelete-hide-user' => 'தொகுப்பவரின் ஐ.பி./பயனர்பெயரை மறை',
 'revdelete-hide-restricted' => 'குறிப்புக்களை அதிகாரிகள் உட்பட எல்லோரிடமிருந்தும் மறைத்துவிடு (காட்டத்தேவையில்லை).',
 'revdelete-radio-same' => '(தயவுசெய்து மாற்ற வேண்டாம்)',
-'revdelete-radio-set' => 'à®\86à®®à¯\8d',
-'revdelete-radio-unset' => 'à®\87லà¯\8dலà¯\88',
+'revdelete-radio-set' => 'à®\95ாணà®\95à¯\8dà®\95à¯\82à®\9fியதà¯\81',
+'revdelete-radio-unset' => 'மறà¯\88à®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\8dà®\9fதà¯\81',
 'revdelete-suppress' => 'நிர்வாகிகள் உட்பட இனவரிடமிருந்தாக தரவுகளை அடக்கு',
 'revdelete-unsuppress' => 'மீட்கப்பட்ட திருத்தங்கள் மீதான கட்டுப்பாடுகளை நீக்கு',
 'revdelete-log' => 'காரணம்:',
@@ -1152,8 +1152,6 @@ $1",
 'preferences' => 'விருப்பங்கள்',
 'mypreferences' => 'விருப்பத்தேர்வுகள்',
 'prefs-edits' => 'தொகுப்புகளின் எண்ணிக்கை:',
-'prefsnologin' => 'புகுபதிகை செய்யப்படவில்லை',
-'prefsnologintext' => 'பயனர் விருப்பத்தேர்வுகளை அமைப்பதற்கு நீங்கள் <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} புகுபதிகை ]</span> செய்திருக்க வேண்டும்.',
 'changepassword' => 'கடவுச்சொல்லை மாற்று',
 'prefs-skin' => 'முகப்புறை',
 'skin-preview' => 'முன்தோற்றம்',
@@ -1178,7 +1176,7 @@ $1",
 'prefs-rendering' => 'தோற்றம்',
 'saveprefs' => 'சேமி',
 'resetprefs' => 'சேமிக்காத மாற்றங்கள் நீக்குக',
-'restoreprefs' => 'எல்லோருக்கும் பொதுவான வடிவமைப்பைத் திரும்பக்கொண்டுவரவும்.',
+'restoreprefs' => 'எல்லோருக்கும் பொதுவான வடிவமைப்பைத் திரும்பக்கொண்டுவரவும் (எல்லா பிரிவுகளிலும்).',
 'prefs-editing' => 'தொகுத்தல்',
 'rows' => 'நிரைகள் (கிடை வரிசைகள்):',
 'columns' => 'நிரல்கள்',
@@ -1235,8 +1233,8 @@ $1",
 'badsiglength' => 'தங்களது கையெழுத்து மிக நீளமானது.
 
 அது $1 {{PLURAL:$1|எழுத்து|எழுத்துக்களுக்கு}} மேல் இருக்கக்கூடாது.',
-'yourgender' => 'பாலà¯\8d:',
-'gender-unknown' => 'à®\95à¯\81றிபà¯\8dபிà®\9fபà¯\8dபà®\9fவில்லை',
+'yourgender' => 'à®\89à®\99à¯\8dà®\95ளà¯\88 à®\8eபà¯\8dபà®\9fி à®µà®¿à®µà®°à®¿à®\95à¯\8dà®\95 à®µà®¿à®°à¯\81à®®à¯\8dபà¯\81à®\95ினà¯\8dà®±à¯\80à®°à¯\8dà®\95ளà¯\8d?',
+'gender-unknown' => 'நானà¯\8d à®\95à¯\81றிபà¯\8dபிà®\9f à®µà®¿à®°à¯\81à®®à¯\8dபவில்லை',
 'gender-male' => 'ஆண்',
 'gender-female' => 'பெண்',
 'prefs-help-gender' => 'விருப்பத் தேர்வுதான்: ஒருவரைக் குறிப்பிடும்பொழுது, அவருடைய பால் சரியானதாக இருக்க மென்கலம் பயன்படுத்தும் தகவல். இத்தகவல் பொதுவில் கிடைக்கும்படி இனி இருக்கும்.',
@@ -1250,7 +1248,7 @@ $1",
 'prefs-signature' => 'கையெழுத்து',
 'prefs-dateformat' => 'தேதியின் வடிவமைப்பு',
 'prefs-timeoffset' => 'நேர வித்தியாசம்',
-'prefs-advancedediting' => 'à®®à¯\87à®®à¯\8dபà®\9fà¯\8dà®\9f விருப்பத்தேர்வுகள்',
+'prefs-advancedediting' => 'பà¯\8aதà¯\81 விருப்பத்தேர்வுகள்',
 'prefs-editor' => 'தொகுப்பாளர்',
 'prefs-preview' => 'முன்தோற்றம்',
 'prefs-advancedrc' => 'மேம்பட்ட விருப்பத்தேர்வுகள்',
@@ -1261,6 +1259,7 @@ $1",
 'prefs-displaysearchoptions' => 'விருப்பத்தேர்வுகளைக் காட்டு',
 'prefs-displaywatchlist' => 'விருப்பத்தேர்வுகளைக் காட்டு',
 'prefs-diffs' => 'வித்தியாசங்கள்',
+'prefs-help-prefershttps' => 'இந்த விருப்பத்தேர்வு உங்களின் அடுத்த புகுபதிகையிலிருந்து செயல்பாட்டுக்கு வரும்.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'மின்னஞ்சல் முகவரி முறையானதாகத் தோன்றுகிறது',
@@ -1286,9 +1285,11 @@ $1",
 'userrights-no-interwiki' => 'ஏனைய விக்கிகளில் பயனர் உரிமைகளை மாற்றும் அனுமதி உங்களுக்குக் கிடையாது.',
 'userrights-nodatabase' => '$1 தரவுத்தளம் கிடையாது அல்லது உள்ளக விக்கியில் கிடையாது.',
 'userrights-nologin' => 'பயனர் உரிமைகளை வழங்குவதற்கு நீங்கள் நிர்வாகி கணக்கில் [[Special:UserLogin|புகுபதிகை]] செய்ய வேண்டும்.',
-'userrights-notallowed' => 'பயனரà¯\8d à®\89ரிமà¯\88à®\95ளà¯\88 à®®à®¾à®±à¯\8dà®±à¯\81à®®à¯\8d à®\85னà¯\81மதி à®\89à®\99à¯\8dà®\95ளà¯\8d à®ªà®¯à®©à®°à¯\8d à®\95ணà®\95à¯\8dà®\95à¯\81à®\95à¯\8d கிடையாது.',
+'userrights-notallowed' => 'பயனரà¯\8d à®\89ரிமà¯\88à®\95ளà¯\88 à®®à®¾à®±à¯\8dà®±à¯\81à®®à¯\8d à®\85னà¯\81மதி à®\89à®\99à¯\8dà®\95ளà¯\81à®\95à¯\8dà®\95à¯\81 கிடையாது.',
 'userrights-changeable-col' => 'நீங்கள் மாற்றக்கூடிய குழுக்கள்',
 'userrights-unchangeable-col' => 'நீங்கள் மாற்ற முடியாத குழுக்கள்',
+'userrights-conflict' => 'பயனர் உரிமைகளின் மாற்றங்களில் முரண்பாடு உள்ளது! மறு ஆய்வு செய்து, உங்கள் மாற்றங்களை உறுதி செய்க.',
+'userrights-removed-self' => 'நீங்கள் உங்களது சொந்த உரிமைகளை வெற்றிகரமாக நீக்கியுள்ளீர்கள். இதனால் நீங்கள் இனி இந்தப்பக்கத்தினை பார்க்க இயலாது.',
 
 # Groups
 'group' => 'குழு:',
@@ -1332,7 +1333,7 @@ $1",
 'right-reupload-shared' => 'பகிர்விலுள்ள ஊடகக் கிடங்கியில் உள்ள கோப்புகளை உள்ளகப் பயன்பாட்டுக்காக மேலுரிமையுடன் பதிவேற்று',
 'right-upload_by_url' => 'யூ.ஆர்.எல். ஒன்றிலிருந்து கோப்பை பதிவேற்றல்',
 'right-purge' => 'உறுதிப்படுத்தல் பக்கமெதுவுமின்றி பக்க இடைமாற்றை நீக்கல்',
-'right-autoconfirmed' => 'பà®\95à¯\81தியாà®\95 à®\95ாà®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\8dà®\9f à®ªà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளà¯\88 à®¤à¯\8aà®\95à¯\81தà¯\8dதல்',
+'right-autoconfirmed' => 'à®\87ணà¯\88ய à®¨à¯\86றிமà¯\81à®±à¯\88 à®®à¯\81à®\95வரியினà¯\8d (IP) à®\85à®\9fிபà¯\8dபà®\9fà¯\88யிலà¯\8d à®\89ளà¯\8dள à®µà®¿à®\95ித à®µà®°à®®à¯\8dபà¯\81à®\95ளினà¯\8d à®\95à®\9fà¯\8dà®\9fà¯\81பà¯\8dபாà®\9fà¯\8dà®\9fà¯\81à®\95à¯\8dà®\95à¯\81 à®\89à®\9fà¯\8dபà®\9fாதà¯\80à®°à¯\8dà®\95ள்',
 'right-bot' => 'தானாக செய்யப்பட்டசெயலாக கருதப்படும்',
 'right-nominornewtalk' => 'உரையாடல் பக்கங்களில் செய்யும் சிறு தொகுப்புகளை அறிவிக்கப் புதிய செய்தி ஏதும் அனுப்பவேண்டாம்.',
 'right-apihighlimits' => 'உயர் தரம் கொண்ட  API கேள்விளை பயன்படுத்தவும்',
@@ -1410,8 +1411,8 @@ $1",
 'action-block' => 'இப்பயனரை மேலும் தொகுக்க அனுமதிக்க வேண்டாம்',
 'action-protect' => 'இந்த பக்கத்திற்கான பாதுகாப்பு நிலைகளை மாற்றவும்',
 'action-rollback' => 'ஒரு குறிப்பிட்ட பக்கத்தை திருத்திய பயனரின் திருத்தங்களை பழைய நிலைமைக்கு மாற்றவும்.',
-'action-import' => 'மறà¯\8dà®±à¯\8aà®°à¯\81 à®µà®¿à®\95à¯\8dà®\95ியிலà¯\8d à®\87à®°à¯\81நà¯\8dதà¯\81 à®\87பà¯\8dபà®\95à¯\8dà®\95தà¯\8dதை இறக்குமதி செய்யவும்',
-'action-importupload' => 'à®\95à¯\8bபà¯\8dபà¯\81 à®ªà®¤à®¿à®µà¯\87à®±à¯\8dறதà¯\8dதிலிரà¯\81நà¯\8dதà¯\81 à®\87பà¯\8dபà®\95à¯\8dà®\95தà¯\8dதை இறக்கவும்',
+'action-import' => 'மறà¯\8dà®±à¯\8aà®°à¯\81 à®µà®¿à®\95à¯\8dà®\95ியிலà¯\8d à®\87à®°à¯\81நà¯\8dதà¯\81 à®ªà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளை இறக்குமதி செய்யவும்',
+'action-importupload' => 'à®\95à¯\8bபà¯\8dபà¯\81 à®ªà®¤à®¿à®µà¯\87à®±à¯\8dறதà¯\8dதிலிரà¯\81நà¯\8dதà¯\81 à®ªà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளை இறக்கவும்',
 'action-patrol' => 'மற்றவர்களின் தொகுப்புகளைப் பார்வையிட்டதாகக் குறிக்கவும்',
 'action-autopatrol' => 'உங்களது திருத்தத்தைப் பார்வையிட்டதாகக் குறிப்பிட்டுக் கொள்க.',
 'action-unwatchedpages' => 'கவனிக்கப்படாத பக்கங்களின் பட்டியலைப் பார்க்க',
@@ -1420,6 +1421,8 @@ $1",
 'action-userrights-interwiki' => 'ஏனைய விக்கித் தளங்களின் பயனர் உரிமைகளைத் தொகு',
 'action-siteadmin' => 'தரவுதளத்தை பூட்டு அல்லது  பூட்டாதே',
 'action-sendemail' => 'மின்னஞ்சல்கள் அனுப்பு',
+'action-editmywatchlist' => 'உங்கள் கவனிப்பு பட்டியலை தொகு',
+'action-viewmywatchlist' => 'உங்கள் கவனிப்பு பட்டியலை பார்',
 
 # Recent changes
 'nchanges' => '{{PLURAL:$1|ஓர் மாற்றம்|$1 மாற்றங்கள்}}',
@@ -1431,6 +1434,7 @@ $1",
 'recentchanges-label-minor' => 'இது ஒரு சிறு தொகுப்பு',
 'recentchanges-label-bot' => 'இந்த தொகுப்பானது ஒரு தானியங்கியால் செய்யப்பட்டதாகும்',
 'recentchanges-label-unpatrolled' => 'இந்த  தொகுப்பு  இன்னும் ரோந்திடப்படவில்லை',
+'recentchanges-legend-newpage' => '$1 - புதிய பக்கம்',
 'rcnote' => "கீழே காணப்படுவது $4 ஆம் தேதி $5 மணிக்கு் உள்ளபடி கடைசி {{PLURAL:$2|24 மணிகளில்|'''$2''' நாட்களில்}} செய்யப்பட்ட {{PLURAL:$1|'''ஒரு''' மாற்றம்|'''$1''' கடைசி மாற்றங்கள்}} ஆகும்.",
 'rcnotefrom' => "கீழே காணப்படுவது '''$2''' இலிருந்து செய்யப்பட்ட மாற்றங்களாகும் ('''$1''' வரைக் காட்டப்பட்டுள்ளது).",
 'rclistfrom' => '$1 தொடக்கம் செய்யப்பட்ட புதிய மாற்றங்களைக் காட்டவும்',
@@ -1453,7 +1457,7 @@ $1",
 'rc_categories_any' => 'ஏதாவது',
 'rc-change-size-new' => '$1 {{PLURAL:$1|பைட்டு|பைட்டுகள்}} -மாற்றத்திற்குப் பிறகு',
 'newsectionsummary' => '/* $1 */ புதிய பகுதி',
-'rc-enhanced-expand' => 'விவரà®\99à¯\8dà®\95ளà¯\88à®\95à¯\8d à®\95ாà®\9fà¯\8dà®\9fà¯\81 (à®\9aாவாநிரலà¯\8d à®¤à¯\87வà¯\88)',
+'rc-enhanced-expand' => 'விவரதà¯\8dதà¯\88 à®\95ாà®\9fà¯\8dà®\9fà¯\81',
 'rc-enhanced-hide' => 'விவரங்களை மறை',
 'rc-old-title' => 'முதலில் "$1" என உருவாக்கப்பட்டது',
 
@@ -1472,7 +1476,7 @@ $1",
 'reuploaddesc' => 'பதிவேற்றத்தை நிறுத்திவிட்டு பதிவேற்றும் படிவத்துக்கு மீளச் செல்க',
 'upload-tryagain' => 'மாற்றம் செய்யப்பட்ட கோப்புத் தகவலைச் சமர்ப்பிக்கவும்',
 'uploadnologin' => 'புகுபதிகை செய்யப்படவில்லை',
-'uploadnologintext' => 'கோப்புகளைப் பதிவேற்றம் செய்வதற்கு நீங்கள் [[Special:UserLogin|புகுபதிகை]] செய்திருக்க வேண்டும்.',
+'uploadnologintext' => 'கோப்புகளைப் பதிவேற்ற நீங்கள் $1 செய்திருக்க வேண்டும்.',
 'upload_directory_missing' => 'தரவேற்றப்படும் அடைவு (டைரெக்டரி) ( $1 ) ஐ காணவில்லை, அதோடு வலைத்தளவழங்கி வழியாக உருவாக்கவும் இயலவில்லை.',
 'upload_directory_read_only' => 'பதிவேற்ற அடைவு ($1) வழங்கனால் எழுதப்படமுடியாது.',
 'uploaderror' => 'பதிவேற்றத் தவறு',
@@ -1646,9 +1650,9 @@ $1',
 # img_auth script messages
 'img-auth-accessdenied' => 'அனுமதி மறுக்கப்பட்டது',
 'img-auth-nopathinfo' => 'PATH_INFO காணவில்லை.
-உங்கள் வழங்கி  இந்தத் தகவலை அனுப்புமாறு அமைக்கப்படவில்லை
-இது  சிச்சிஐ (CGI)- அடிப்படையிலானதாக இருக்கலாம் மற்றும் img_authக்கும் ஆதரவு கிடையாது.
-பார்க்கவும் : https://www.mediawiki.org/wiki/Manual:Image_Authorization See image authorization.',
+உங்கள் வழங்கி இந்தத் தகவலை அனுப்ப அமைக்கப்படவில்லை
+இது சிஜிஐ (CGI)- அடிப்படையிலானதாகவோ img_auth-ஐ ஆதரக்காததாகவோ இருக்கலாம் .
+பார்க்கவும் https://www.mediawiki.org/wiki/Manual:Image_Authorization.',
 'img-auth-notindir' => 'கோரிய பாதை இந்த குறிப்பிட்ட தகவலேற்று கோப்புறையில் இல்லை.',
 'img-auth-badtitle' => 'செல்லத்தக்க தலைப்பு "$1" ஐ கட்ட இயலவில்லை.',
 'img-auth-nologinnWL' => 'நீங்கள் புகுபதிகை செய்யவில்லை, மேலும் "$1"  அனுமதிக்கப்பெற்ற பட்டியலில் இல்லை',
@@ -1684,8 +1688,7 @@ $1',
 'upload_source_file' => ' (உங்கள் கணணியில் உள்ள கோப்பு)',
 
 # Special:ListFiles
-'listfiles-summary' => 'இந்த சிறப்புப் பக்கம் அனைத்து தரவேற்றப்பட்ட கோப்புகளையும் காண்பிக்கும்.
-பயனர் பெயர் மூலம் வடிகட்டும் போது, அந்த பயனர் தரவேற்றிய கோப்பின் மிக சமீபத்திய பதிப்பு மட்டும் காண்பிக்கப்பட்டுள்ளது.',
+'listfiles-summary' => 'இச்சிறப்புப் பக்கம் பதிவேற்றப்பட்ட கோப்புகளைப் பட்டியலிடுகிறது.',
 'listfiles_search_for' => 'பின்வரும் பெயருள்ள ஊடகக் கோப்பைத் தேடு:',
 'imgfile' => 'கோப்பு',
 'listfiles' => 'படிமங்களின் பட்டியல்',
@@ -1696,6 +1699,8 @@ $1',
 'listfiles_size' => 'அளவு',
 'listfiles_description' => 'விளக்கம்',
 'listfiles_count' => 'பதிப்புக்கள்',
+'listfiles-latestversion-yes' => 'ஆம்',
+'listfiles-latestversion-no' => 'இல்லை',
 
 # File description page
 'file-anchor-link' => 'கோப்பு',
@@ -1887,8 +1892,8 @@ $1',
 'ancientpages' => 'மிகப்பழைய கட்டுரைகள்',
 'move' => 'நகர்த்தவும்',
 'movethispage' => 'இப்பக்கத்தை நகர்த்து',
-'unusedimagestext' => 'à®\95à¯\80à®´à¯\8dவரà¯\81à®®à¯\8d à®\95à¯\8bபà¯\8dபà¯\81à®\95ளà¯\8d à®\89ணà¯\8dà®\9fà¯\81, ஆனாலும் அவை எந்த ஒரு பக்கத்திலும் இணைக்கப்படவில்லை.
-இக்கோப்பு ஏனைய இணையத்தளங்களினால் நேரடியான இணையமுகவரியை பயன்படுத்தி இனைக்கப்பட்டிருக்கக் கூடுமென்பதுடன், செயல்படு பயன்பாட்டில் இருந்தும் கூட இங்கே பட்டியலிடப்பட்டிருக்கக்கூடும் என்பதையும் கவனிக்கவும்.',
+'unusedimagestext' => 'à®\95à¯\80à®´à¯\8dவரà¯\81à®®à¯\8d à®\95à¯\8bபà¯\8dபà¯\81à®\95ளà¯\8d à®\87à®°à¯\81நà¯\8dதாலà¯\81à®®à¯\8d, ஆனாலும் அவை எந்த ஒரு பக்கத்திலும் இணைக்கப்படவில்லை.
+இக்கோப்புகள் ஏனைய இணையத்தளங்களினால் இணையமுகவரியை பயன்படுத்தி நேரடியாக இனைக்கப்பட்டிருக்கக் கூடுமென்பதால் இவை பயன்பாட்டில் இருந்தாலும் இங்கே பட்டியலிடப்பட்டிருக்கக்கூடும் என்பதை கவனத்தில் கொள்ளவும்.',
 'unusedcategoriestext' => 'பின்வரும் பகுப்புகள் உருவாக்கப்பட்டுள்ளன எனினும் வேறு எந்தப் பக்கமோ அல்லது பகுப்போ இதைப் பயன்படுத்தவில்லை.',
 'notargettitle' => 'இலக்கு இல்லை',
 'notargettext' => 'நீங்கள் இந்தச் செயலை எந்தப் பயனர் அல்லது பக்கம் தொடர்பில் செய்வது என்பதைக் குறிப்பிடவில்லை.',
@@ -1976,8 +1981,9 @@ $1',
 
 # Special:ListGroupRights
 'listgrouprights' => 'பயனர் குழு உரிமைகள்',
-'listgrouprights-key' => '<span class="listgrouprights-granted">உரிமை வழங்கப்பட்டது</span>
- * <span class="listgrouprights-revoked">உரிமை பறிக்கபட்டது</span>',
+'listgrouprights-key' => 'குறியீட்டு விளக்கம்:
+* <span class="listgrouprights-granted">உரிமை வழங்கப்பட்டது</span>
+* <span class="listgrouprights-revoked">உரிமை பறிக்கபட்டது</span>',
 'listgrouprights-group' => 'குழு',
 'listgrouprights-rights' => 'உரிமைகள்',
 'listgrouprights-helppage' => 'Help:குழு உரிமைகள்',
@@ -2049,8 +2055,8 @@ $1',
 'notanarticle' => 'ஒரு கட்டுரைப் பக்கமல்ல',
 'notvisiblerev' => 'திருத்தம் நீக்கப்பட்டுள்ளது',
 'watchlist-details' => 'பேச்சுப் பக்கங்களைத் தவிர்த்து, {{PLURAL:$1|$1 பக்கம் கவனிக்கப்பட்டது.|$1 பக்கங்கள் கவனிக்கப்பட்டன.}}',
-'wlheader-enotif' => 'மினà¯\8dனà®\9eà¯\8dà®\9aலà¯\8d à®\85றிவிதà¯\8dதலà¯\8dகள் செயல்படுத்தப்பட்டுள்ளன.',
-'wlheader-showupdated' => "à®\89மதà¯\81 à®\95à®\9fà¯\88à®\9aி à®µà®°à¯\81à®\95à¯\88à®\95à¯\8dà®\95à¯\81பà¯\8d à®ªà®¿à®©à¯\8dனரà¯\8d à®®à®¾à®±à¯\8dà®±à®\99à¯\8dà®\95ளà¯\8d à®\9aà¯\86யà¯\8dயபà¯\8dபà®\9fà¯\8dà®\9f à®ªà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளà¯\8d '''தà®\9fிதà¯\8dத à®\8eà®´à¯\81தà¯\8dதà¯\81à®\95à¯\8dà®\95ளால்''' காட்டப்பட்டுள்ளன",
+'wlheader-enotif' => 'மினà¯\8dனà®\9eà¯\8dà®\9aலà¯\8d à®\85றிவிபà¯\8dபà¯\81கள் செயல்படுத்தப்பட்டுள்ளன.',
+'wlheader-showupdated' => "à®\89à®\99à¯\8dà®\95ளà¯\8d à®\95à®\9fà¯\88à®\9aி à®µà®°à¯\81à®\95à¯\88à®\95à¯\8dà®\95à¯\81பà¯\8d à®ªà®¿à®©à¯\8dனரà¯\8d à®®à®¾à®±à¯\8dà®±à®\99à¯\8dà®\95ளà¯\8d à®\9aà¯\86யà¯\8dயபà¯\8dபà®\9fà¯\8dà®\9f à®ªà®\95à¯\8dà®\95à®\99à¯\8dà®\95ளà¯\8d '''தà®\9fிதà¯\8dத à®\8eà®´à¯\81தà¯\8dதà¯\81à®\95à¯\8dà®\95ளில்''' காட்டப்பட்டுள்ளன",
 'watchmethod-recent' => 'கவனிக்கப்படுகின்ற பக்கங்களுக்காக, அண்மைய தொகுப்புகள் தேடிப் பார்க்கப்படுகிறன',
 'watchmethod-list' => 'அண்மைய தொகுப்புகளுக்காக, கவனிக்கப்படுகின்ற பக்கங்கள் தேடிப் பார்க்கப்படுகிறன',
 'watchlistcontains' => 'உங்கள் கவனிப்புப் பட்டியல் {{PLURAL:$1|ஒரு பக்கத்தைக்|$1 பக்கங்களைக்}} கொண்டுள்ளது.',
@@ -2119,10 +2125,12 @@ $NEWPAGE
 'deletecomment' => 'காரணம்:',
 'deleteotherreason' => 'வேறு மேலதிக காரணம்:',
 'deletereasonotherlist' => 'வேறு காரணம்',
-'deletereason-dropdown' => '*பொதுவான நீக்கல் காரணங்கள்
-** à®\95ாபà¯\8dபà¯\81ரிமà¯\88 à®®à¯\80றபà¯\8dபà®\9fà¯\8dà®\9fà®®à¯\88
+'deletereason-dropdown' => '* பொதுவான நீக்கல் காரணங்கள்
+** à®\8eரிதமà¯\8d/வà¯\80ணà¯\8dà®\9aà¯\86யà¯\8dதிà®\95ளà¯\8d
 ** விசமத் தொகுப்பு
-** ஆசிரியர் வேண்டுகோள்',
+** காப்புரிமை மீறப்பட்டமை
+** ஆசிரியர் வேண்டுகோள்
+** உடைந்த வழிமாற்று',
 'delete-edit-reasonlist' => 'நீக்கல் காரணங்களைத் தொகு',
 'delete-toobig' => 'இப்பக்கம் அதிகமான திருத்தங்களை கொண்டுள்ளது, குறிப்பாக $1 {{PLURAL:$1|திருத்தத்திற்கு|திருத்தங்களிற்கு}} மேல்.
 {{SITENAME}} தளத்தின் தரவுகள் தற்செயலாக அழிந்துப்போவதை தடுப்பதற்க்காக இவ்வாறான பக்கங்கள் நீக்கப்படுவது முடக்கப்பட்டுள்ளது.',
@@ -2143,7 +2151,7 @@ $NEWPAGE
 இப்பக்கத்தை கடைசியாகத் தொகுத்தவர் [[User:$3|$3]] ([[User talk:$3|Talk]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "தொகுப்பிற்கான சிறுகுறிப்புக்கள் இவை:\"''\$1''\".",
 'revertpage' => '[[Special:Contributions/$2|$2]] ([[User talk:$2|பேச்சு]]) செய்தத் தொகுப்புகள் நீக்கப்பட்டு [[User:$1|$1]] இன் பதிப்புக்கு முன்நிலையாக்கப்பட்டது',
-'revertpage-nouser' => '(பயனர் பெயர் நீக்கப்பட்டது) செய்த தொகுப்புகளை இல்லாது செய்து, [[User:$1|$1]] கடைசியாகச் செய்த திருத்தத்துக்கு மாற்றப்பட்டது',
+'revertpage-nouser' => 'மறைக்கப்பட்ட பயனர் செய்த தொகுப்புகள் இல்லாது செய்யப்பட்டு, {{GENDER:$1|[[User:$1|$1]]}} கடைசியாகச் செய்த திருத்தத்துக்கு முன்நிலையாக்கப்பட்டது',
 'rollback-success' => '$1 செய்தத் தொகுப்புகள் நீக்கப்பட்டு $2 இன் பதிப்புக்கு முன்நிலையாக்கப்பட்டது.',
 
 # Edit tokens
@@ -2177,8 +2185,8 @@ $NEWPAGE
 '''$1''' பக்கத்துக்கான நடப்பு அமைப்புகள் பின்வருமாறு:",
 'protect-cascadeon' => 'இந்தப்பக்கம் படிநிலை காப்புகுட்படுத்தப்பட்ட {{PLURAL:$1|பக்கத்திற்கு|பக்கங்களிற்கு}} இணைக்கப்பட்டுள்ளமையால் காப்புச் செய்யப்பட்டுள்ளது. இந்த பக்கத்தின் காப்பு நிலையை நீங்கள் மாற்றம் செய்யலாம் எனினும் இது படிநிலை காப்பினை மாற்றம் செய்யாது.',
 'protect-default' => 'அனைத்துப் பயனரையும் உள்ளிடு',
-'protect-fallback' => '"$1" à®\85னà¯\81மதி à®¤à¯\87வà¯\88',
-'protect-level-autoconfirmed' => 'பà¯\81திய, à®ªà®¤à®¿à®µà¯\81 à®\9aà¯\86யà¯\8dயாத à®ªà®¯à®©à®°à¯\8dà®\95ளà¯\88தà¯\8d à®¤à®\9fà¯\88 à®\9aà¯\86யà¯\8d',
+'protect-fallback' => '"$1" à®\85னà¯\81மதி à®ªà¯\86à®±à¯\8dà®± à®ªà®¯à®©à®°à¯\8dà®\95ளà¯\81à®\95à¯\8dà®\95à¯\81 à®®à®\9fà¯\8dà®\9fà¯\81à®®à¯\8d à®\87à®\9aà¯\88வளி',
+'protect-level-autoconfirmed' => 'தானாà®\95 à®\89à®±à¯\81தியளிà®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\8dà®\9f à®ªà®¯à®©à®°à¯\8dà®\95ளà¯\88 à®®à®\9fà¯\8dà®\9fà¯\81à®®à¯\8d à®\85னà¯\81மதி',
 'protect-level-sysop' => 'நிருவாகிகளை மட்டும் அனுமதிக்கவும்',
 'protect-summary-cascade' => 'படிநிலை',
 'protect-expiring' => '$1 (UTC) மணிக்கு காலாவதியாகிறது',
@@ -2244,7 +2252,8 @@ $NEWPAGE
 'undeletedrevisions' => '{{PLURAL:$1|1 திருத்தம் மீட்கப்பட்டது|$1 திருத்தங்கள் மீட்கப்பட்டன}}',
 'undeletedrevisions-files' => '{{PLURAL:$1|1 திருத்தம்|$1 திருத்தங்கள்}} மற்றும் {{PLURAL:$2|1 கோப்பு|$2 கோப்புகள்}} மீட்கப்பட்டன.',
 'undeletedfiles' => '{{PLURAL:$1|ஒரு கோப்பு மீட்டெடுக்கப்பட்டது|$1 கோப்புகள் மீட்டெடுக்கப்பட்டன}}',
-'cannotundelete' => 'மீள்வித்தல் தோல்வி: $1',
+'cannotundelete' => 'மீள்வித்தல் தோல்வி:
+$1',
 'undeletedpage' => "'''$1 மீட்கப்பட்டது'''
 
 அண்மைய நீக்கல்களுக்கும் மீட்புக்களுக்கும் [[Special:Log/delete|நீக்கல் பதிவைப்]] பார்க்கவும்.",
@@ -2274,7 +2283,7 @@ $1',
 'blanknamespace' => '(முதன்மை)',
 
 # Contributions
-'contributions' => 'பயனர் பங்களிப்புக்கள்',
+'contributions' => '{{GENDER:$1|பயனர்}} பங்களிப்புக்கள்',
 'contributions-title' => '$1 இற்கான பயனர் பங்களிப்புகள்',
 'mycontris' => 'பங்களிப்புக்கள்',
 'contribsub2' => '$1 பயனரின் ($2)',
@@ -2358,7 +2367,7 @@ $1',
 'badipaddress' => 'செல்லுபடியற்ற ஐ.பி. முகவரி',
 'blockipsuccesssub' => 'தடுப்பு வெற்றி',
 'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] தடுக்கப்பட்டுள்ளார்.<br />
-தà®\9fà¯\81பà¯\8dபà¯\88 à®®à¯\80ளாயà¯\8dவà¯\81 à®\9aà¯\86யà¯\8dய [[Special:BlockList|தà®\9fà¯\81à®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\8dà®\9f à®\90.பி. à®®à¯\81à®\95வரிà®\95ளினà¯\8d à®ªà®\9fà¯\8dà®\9fியலà¯\88பà¯\8d]] à®ªà®¾à®°்.',
+தà®\9fà¯\81பà¯\8dபà¯\88 à®®à®±à¯\81à®\86யà¯\8dவà¯\81 à®\9aà¯\86யà¯\8dய [[Special:BlockList|தà®\9fà¯\81பà¯\8dபà¯\81 à®ªà®\9fà¯\8dà®\9fியலà¯\88பà¯\8d]] à®ªà®¾à®°à¯\8dà®\95வà¯\81à®®்.',
 'ipb-blockingself' => 'நீங்கள் உங்களையே தடுக்க முயல்கிறீர்கள்! உறுதியாக இதை செய்ய விரும்புகிறீர்களா?',
 'ipb-edit-dropdown' => 'தடை காரணங்கள் தொகு',
 'ipb-unblock-addr' => '$1 இன் தடையை நீக்கு',
@@ -2575,7 +2584,7 @@ $1',
 'allmessagesdefault' => 'இயல்பிருப்பு உரை',
 'allmessagescurrent' => 'தற்போதைய உரை',
 'allmessagestext' => 'இது மீடியாவிக்கி பெயர்வெளியிலுள்ள எல்லா முறைமை தகவல்களினதும் பட்டியலாகும்.
-மொழிபெயர்ப்பில் உதவ விரும்பின் அருள்கூர்ந்து [//translatewiki.net பீட்டாவிக்கி], [//www.mediawiki.org/wiki/Localisation மீடியாவிக்கி மொழியாக்க]  தளங்களுக்குச் செல்லவும்.',
+மொழிபெயர்ப்பில் உதவ விரும்பின் அருள்கூர்ந்து [//translatewiki.net பீட்டாவிக்கி], [https://www.mediawiki.org/wiki/Localisation மீடியாவிக்கி மொழியாக்க]  தளங்களுக்குச் செல்லவும்.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' முடக்கப்பட்டுள்ளப் படியால் இப்பக்கததை பயன்படுத்த முடியாது.",
 'allmessages-filter-legend' => 'வடிகட்டி',
 'allmessages-filter' => 'தனிப்பயனாக்கத்தின்படி வடிகட்டு.',
@@ -2725,7 +2734,7 @@ $1',
 'tooltip-undo' => '"பின்வாங்கு" என்பது முன்பு செய்த தொகுப்புக்களை இல்லாது செய்கிறது. மேலும் தாங்கள் செய்த தொகுப்பினை முன்தோற்ற நிலைக்கு கொண்டுவந்து காட்டும். அது தங்களுக்குச் சிறுகுறிப்புப் பகுதியில் அதற்கான காரணத்தைக் கூற அனுமதிக்கிறது.',
 'tooltip-preferences-save' => 'விருப்பங்களை சேமி',
 'tooltip-summary' => 'குறுகிய சுருக்கத்தை உள்ளிடவும்.',
-'tooltip-iwiki' => '$1 - $2',
+'interlanguage-link-title' => '$1 - $2',
 
 # Metadata
 'notacceptable' => 'உங்களது சேவையாளர் வாசிக்க கூடிய விதத்தில் இந்த விக்கியால தரவுகளை வழங்க முடியாது.',
@@ -2760,13 +2769,13 @@ $1',
 'pageinfo-length' => 'பக்க நீளம் (எண்ணுண்மிகளில்)',
 'pageinfo-article-id' => 'பக்க அடையாள இலக்கம்',
 'pageinfo-language' => 'பக்க உள்ளடக்க மொழி',
-'pageinfo-robot-policy' => 'தà¯\87à®\9fà®±à¯\8dபà¯\8aறி à®¨à®¿à®²à¯\88à®®à¯\88',
-'pageinfo-robot-index' => 'வà®\95à¯\88பà¯\8dபà®\9fà®\95à¯\8dà®\95à¯\82à®\9fியது',
-'pageinfo-robot-noindex' => 'வà®\95à¯\88பà¯\8dபà®\9fாததà¯\81.',
+'pageinfo-robot-policy' => 'தானியà®\99à¯\8dà®\95ி à®®à¯\82லமà¯\8d à®\85à®\9fà¯\8dà®\9fவணà¯\88பà¯\8dபà®\9fà¯\81தà¯\8dதலà¯\8d',
+'pageinfo-robot-index' => 'à®\85னà¯\81மதிà®\95à¯\8dà®\95பà¯\8dபà®\9fà¯\81à®\95ிறது',
+'pageinfo-robot-noindex' => 'à®\85னà¯\81மதிà®\95à¯\8dà®\95பà¯\8dபà®\9fாததà¯\81',
 'pageinfo-views' => 'காட்சிகள் எண்ணிக்கை',
 'pageinfo-watchers' => 'பக்கப் பார்வையாளர்கள் எண்ணிக்கை',
 'pageinfo-few-watchers' => 'விட குறைவானது $1 {{PLURAL:$1|watcher|watchers}}',
-'pageinfo-redirects-name' => 'à®\87நà¯\8dதபà¯\8d à®ªà®\95à¯\8dà®\95தà¯\8dதிறà¯\8dà®\95ான à®µà®´à®¿à®®à®¾à®±à¯\8dà®±à¯\81à®\95ளà¯\8d',
+'pageinfo-redirects-name' => 'à®\87நà¯\8dதபà¯\8d à®ªà®\95à¯\8dà®\95தà¯\8dதிறà¯\8dà®\95ான à®µà®´à®¿à®®à®¾à®±à¯\8dà®±à¯\81à®\95ளினà¯\8d à®\8eணà¯\8dணிà®\95à¯\8dà®\95à¯\88',
 'pageinfo-subpages-name' => 'இந்தப் பக்கத்தின் துணைப் பக்கங்கள்',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|வழிமாற்று|வழிமாற்றுகள்}}; $3 {{PLURAL:$3|வழிமாற்றில்லாதது|வழிமாற்றில்லாதவை}})',
 'pageinfo-firstuser' => 'பக்க உருவாக்குநர்',
@@ -2836,7 +2845,7 @@ $1',
 'file-nohires' => 'இதைவிட அளவில் பெரிய படிமம் இல்லை.',
 'svg-long-desc' => 'SVG கோப்பு, பெயரளவில் $1 × $2 பிக்சல்கள், கோப்பு அளவு: $3',
 'svg-long-error' => 'செல்லாத SVG கோப்பு: $1',
-'show-big-image' => 'à®®à¯\81à®´à¯\81 à®\85ளவிலான à®ªà®\9fிமமà¯\8d',
+'show-big-image' => 'à®®à¯\82லà®\95à¯\8dà®\95à¯\8bபà¯\8dபà¯\81',
 'show-big-image-preview' => 'இந்த முன்னோட்டத்தின் அளவு:  $1 .',
 'show-big-image-other' => 'மற்ற  {{PLURAL:$2|பிரிதிறன்|பிரிதிறன்கள்}}:  $1 .',
 'show-big-image-size' => '$1 × $2 படப்புள்ளிகள்',
@@ -3085,7 +3094,7 @@ $1',
 'exif-compression-1' => 'சுருக்கப்படாத',
 
 'exif-copyrighted-true' => 'பதிப்புரிமைப்பட்டது',
-'exif-copyrighted-false' => 'பà¯\8aதà¯\81 à®\95ளமà¯\8d',
+'exif-copyrighted-false' => 'பதிபà¯\8dபà¯\81ரிமà¯\88 à®¨à®¿à®²à¯\88யà¯\88 à®¤à®¿à®°à®¿à®µà¯\81à®\9aà¯\86யà¯\8dயபà¯\8dபà®\9fவிலà¯\8dலà¯\88',
 
 'exif-unknowndate' => 'நாள் தெரியாது',
 
@@ -3291,7 +3300,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'இக்கோப்பை வெளி மென்பொருள் கொண்டு தொகுக்க',
-'edit-externally-help' => 'மேலும் தகவல்களுக்கு [//www.mediawiki.org/wiki/Manual:External_editors அமைப்பு அறிவுறுத்தல்கள்] பக்கத்தைப் பார்க்கவும்.',
+'edit-externally-help' => 'மேலும் தகவல்களுக்கு [https://www.mediawiki.org/wiki/Manual:External_editors அமைப்பு அறிவுறுத்தல்கள்] பக்கத்தைப் பார்க்கவும்.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'அனைத்து',
@@ -3464,7 +3473,7 @@ $5
 'version-hook-subscribedby' => 'பயன்பாடு',
 'version-version' => '(பதிப்பு $1)',
 'version-license' => 'அனுமதி',
-'version-poweredby-credits' => "இந்த் விக்கி '''[//www.mediawiki.org/ MediaWiki]''' இதன் மூலம் வழங்கப்படுகிறது, காப்புரிமை © 2001-$1 $2.",
+'version-poweredby-credits' => "இந்த் விக்கி '''[https://www.mediawiki.org/ MediaWiki]''' இதன் மூலம் வழங்கப்படுகிறது, காப்புரிமை © 2001-$1 $2.",
 'version-poweredby-others' => 'பிறர்',
 'version-license-info' => 'மீடியாவிக்கியானது இலவச மென்பொருள்.இதை நீங்கள் மற்றவர்களுக்கு கொடுப்பது அல்லது திருத்தம் செய்வது இலவச மென்பொருள் அறக்கட்டளை வழங்கிய   GNUவின் பொது உரிம விதிகளுக்குட்பட்டது;உரிமத்தின் இரண்டாவது பதிப்பு அல்லது அதற்கு மேற்பட்ட பதிப்பு (உங்கள் விருப்பத்திற்க்கேற்றவாறு).
 மீடியா உபயோகப்படக்கூடியது என்ற நம்பிக்கையில் வெளியிடப்பட்டுள்ளது, ஆனால் இதற்க்கு உத்தரவாதம் கிடையாது.மேலும் வணிகத்தன்மைக்கான அல்லது ஒரு குறிப்பிட்ட செயலுக்காகவும் உத்தரவாதம் கிடையாது.மேலும் விவரங்களுக்கு GNU பொது உரிமத்தை பார்க்கவும்.
@@ -3495,12 +3504,11 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'சிறப்புப் பக்கங்கள்',
-'specialpages-note' => '----
- * சராசரி சிறப்புப் பக்கங்கள்.
+'specialpages-note' => ' * சராசரி சிறப்புப் பக்கங்கள்.
  * <span class="mw-specialpagerestricted">வரையறுத்த சிறப்புப் பக்கங்கள்.</span>',
 'specialpages-group-maintenance' => 'பராமரிப்பு அறிக்கைகள்',
 'specialpages-group-other' => 'ஏனைய சிறப்புப் பக்கங்கள்',
-'specialpages-group-login' => 'புகுபதிகை / கணக்கு தொடக்கம்',
+'specialpages-group-login' => 'புகுபதிகை/பயனர் கணக்கு தொடக்கம்',
 'specialpages-group-changes' => 'அண்மைய மாற்றங்களும் பதிகைகளும்',
 'specialpages-group-media' => 'ஊடக அறிக்கைகளும் பதிவேற்றங்களும்',
 'specialpages-group-users' => 'பயனர்களும் உரிமைகளும்',
@@ -3581,7 +3589,7 @@ $5
 'sqlite-no-fts' => '$1 முழு-உரை தேடல் ஆதரவு இல்லாமல்',
 
 # New logging system
-'logentry-delete-delete' => '$3 பக்கத்தை $1 நீக்கினார்',
+'logentry-delete-delete' => '$3 பக்கத்தை $1 {{GENDER:$2|நீக்கினார்}}',
 'logentry-delete-restore' => '$1 பயனரால் $3 பக்கம் மீட்டமைக்கப்பட்டது',
 'logentry-delete-event' => '$1 மாற்றிய காட்சித்தன்மை  {{PLURAL:$5| ஒரு நிகழ்வு குறிப்பேடு| $5  நிகழ்வுகள் குறிப்பேடு}} இதில்   $3 :$4',
 'logentry-delete-revision' => '$1 மாற்றப்பட்ட  காட்சித்தன்மைக்கு  {{PLURAL:$5| ஒருபரிசீலனை| $5  பரிசீலனைகளுக்கும்}} இந்த பக்கம்  $3 :$4',
@@ -3609,7 +3617,7 @@ $5
 'logentry-newusers-newusers' => 'பயனர் கணக்கு $1 உருவாக்கப்பட்டது',
 'logentry-newusers-create' => '$1 ஒரு புதிய பயனர் கணக்கை உருவாக்கியுள்ளார்.',
 'logentry-newusers-create2' => '$3 பயனர் கணக்கினை $1 உருவாக்கினார்',
-'logentry-newusers-autocreate' => 'à®\95ணà®\95à¯\8dà®\95à¯\81  $1   à®¤à®¾à®©à®¾à®\95    உருவாக்கப்பட்டது',
+'logentry-newusers-autocreate' => 'பயணரà¯\8d à®\95ணà®\95à¯\8dà®\95à¯\81 $1 à®¤à®¾à®©à®¾à®\95 உருவாக்கப்பட்டது',
 'rightsnone' => '(எதுவுமில்லை)',
 
 # Feedback
@@ -3684,4 +3692,12 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|நூற்றாண்டு|நூற்றாண்டுகள்}}',
 'duration-millennia' => '$1 {{PLURAL:$1|ஆயிரம் ஆண்டு|ஆயிரம் ஆண்டுகள்}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'வார்ப்புருக்களை விரிவாக்கு',
+'expand_templates_input' => 'உள்ளீட்டு உரை:',
+'expand_templates_output' => 'முடிவுகள்',
+'expand_templates_ok' => 'ஆம்',
+'expand_templates_remove_comments' => 'கருத்துரைகளை நீக்கு',
+'expand_templates_preview' => 'முன்தோற்றம்',
+
 );
index 238be25..5232b6e 100644 (file)
@@ -261,8 +261,6 @@ $messages = array(
 'ok' => 'ಸರಿ',
 'retrievedfrom' => '"$1" ರ್ದ್ ದೆತ್ತಿನಂಚಿನ',
 'youhavenewmessages' => 'ಇರೆಗ್ $1 ಉಂಡು ($2).',
-'newmessageslink' => 'ಪೊಸ ಸಂದೇಶಲು',
-'newmessagesdifflink' => 'ಕಡೆತ ಬದಲಾವಣೆ',
 'youhavenewmessagesmulti' => '$1 ಡ್ ಇರೆಗ್ ಪೊಸ ಸಂದೇಶೊಲು ಉಂಡು',
 'editsection' => 'ಸಂಪಾದನೆ ಮಲ್ಪುಲೆ',
 'editold' => 'ಸಂಪಾದನೆ ಮಲ್ಪುಲೆ',
@@ -965,7 +963,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'ಬಾಹ್ಯ(ಪಿದಯಿದ) ತಂತ್ರಾಶೊನು ಉಪಯೋಗ ಮಲ್ತ್’ದ್ ಇಂದೆನ್ ಸಂಪಾದನೆ ಮಲ್ಪುಲೆ',
-'edit-externally-help' => 'ನನಲ ಮಾಹಿತಿಗ್ [//www.mediawiki.org/wiki/Manual:External_editors ಸೆಟ್-ಅಪ್ ನಿರ್ದೇಶನೊಲೆನ್] ತೂಲೆ.',
+'edit-externally-help' => 'ನನಲ ಮಾಹಿತಿಗ್ [https://www.mediawiki.org/wiki/Manual:External_editors ಸೆಟ್-ಅಪ್ ನಿರ್ದೇಶನೊಲೆನ್] ತೂಲೆ.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ಪೂರ',
index 8e8cbb8..d6add03 100644 (file)
@@ -66,7 +66,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'పురాతనపేజీలు' ),
        'Blankpage'                 => array( 'ఖాళీపేజి' ),
        'Block'                     => array( 'అడ్డగించు', 'ఐపినిఅడ్డగించు', 'వాడుకరినిఅడ్డగించు' ),
-       'Blockme'                   => array( 'నన్నుఅడ్డగించు' ),
        'Booksources'               => array( 'పుస్తకమూలాలు' ),
        'BrokenRedirects'           => array( 'తెగిపోయినదారిమార్పులు' ),
        'Categories'                => array( 'వర్గాలు' ),
@@ -74,7 +73,6 @@ $specialPageAliases = array(
        'Confirmemail'              => array( 'ఈమెయిలుధ్రువపరచు' ),
        'CreateAccount'             => array( 'ఖాతాసృష్టించు' ),
        'Deadendpages'              => array( 'అగాధపేజీలు' ),
-       'Disambiguations'           => array( 'అయోమయనివృత్తి' ),
        'DoubleRedirects'           => array( 'రెండుసార్లుదారిమార్పు' ),
        'Emailuser'                 => array( 'వాడుకరికిఈమెయిలుచెయ్యి' ),
        'Export'                    => array( 'ఎగుమతి' ),
@@ -147,31 +145,31 @@ $messages = array(
 # User preference toggles
 'tog-underline' => 'లంకె క్రీగీత:',
 'tog-justify' => 'పేరాలను ఇరు పక్కలా సమానంగా సర్దు',
-'tog-hideminor' => 'à°\87à°\9fà±\80వలి à°®à°¾à°°à±\8dà°ªà±\81లలà±\8b à°\9aà°¿à°¨à±\8dà°¨ à°®à°¾à°°à±\8dà°ªà±\81లనà±\81 à°¦à°¾à°\9aà°¿à°ªà±\86à°\9fà±\8dà°\9fà±\81',
-'tog-hidepatrolled' => 'à°\87à°\9fà±\80వలి à°®à°¾à°°à±\8dà°ªà±\81లలà±\8b à°¨à°¿à°\98à°¾ à°\89à°¨à±\8dà°¨ à°®à°¾à°°à±\8dà°ªà±\81లనà±\81 à°¦à°¾à°\9aà°¿à°ªà±\86à°\9fà±\8dà°\9fà±\81',
-'tog-newpageshidepatrolled' => 'à°\95à±\8aà°¤à±\8dà°¤ à°ªà±\87à°\9cà±\80à°² à°\9cాబితా à°¨à±\81à°\82à°\9aà°¿ à°¨à°¿à°\98à°¾ à°\89à°¨à±\8dà°¨ à°ªà±\87à°\9cà±\80లనà±\81 à°¦à°¾à°\9aà°¿à°ªà±\86à°\9fà±\8dà°\9fà±\81',
+'tog-hideminor' => 'ఇటీవలి మార్పులలో చిన్న మార్పులను దాచు',
+'tog-hidepatrolled' => 'ఇటీవలి మార్పులలో నిఘా ఉన్న మార్పులను దాచు',
+'tog-newpageshidepatrolled' => 'కొత్త పేజీల జాబితా నుంచి నిఘా ఉన్న పేజీలను దాచు',
 'tog-extendwatchlist' => 'కేవలం ఇటీవలి మార్పులే కాక, మార్పులన్నీ చూపించటానికి నా వీక్షణా జాబితాను పెద్దది చేయి',
 'tog-usenewrc' => 'ఇటీవలి మార్పులు మరియు విక్షణ జాబితాలలో మార్పులను పేజీ వారిగా చూపించు (జావాస్క్రిప్టు అవసరం)',
-'tog-numberheadings' => 'à°¶à±\80à°°à±\8dà°·à°¿à°\95à°²à°\95à±\81 à°\86à°\9fà±\8bమాà°\9fà°¿à°\95à±\8dâ\80\8cà°\97à°¾ à°µà°°à±\81à°¸ à°¸à°\82à°\96à±\8dయలà±\81 à°ªà±\86à°\9fà±\8dà°\9fు',
+'tog-numberheadings' => 'à°¶à±\80à°°à±\8dà°·à°¿à°\95à°²à°\95à±\81 à°\85à°ªà±\8dà°°à°®à±\87à°¯à°\82à°\97à°¾ à°µà°°à±\81à°¸ à°¸à°\82à°\96à±\8dయలà±\81 à°\9aà±\87à°°à±\8dà°\9aు',
 'tog-showtoolbar' => 'దిద్దుబాట్లు చేసేటప్పుడు, అందుకు సహాయపడే పరికరాలపెట్టెను చూపించు (జావాస్క్రిప్టు)',
 'tog-editondblclick' => 'డబుల్‌ క్లిక్కు చేసినప్పుడు పేజీని మార్చు (జావాస్క్రిప్టు)',
-'tog-editsection' => '[మారà±\8dà°\9aà±\81] à°²à°¿à°\82à°\95à±\81 à°¦à±\8dవారా à°µà°¿à°­à°¾à°\97à°\82 à°®à°¾à°°à±\8dà°ªà±\81 à°\95ావాలి',
+'tog-editsection' => '[మారà±\8dà°\9aà±\81] à°²à°¿à°\82à°\95à±\81 à°¦à±\8dవారా à°µà°¿à°­à°¾à°\97à°\82 à°®à°¾à°°à±\8dà°ªà±\81 à°\9aà±\87తనà°\82',
 'tog-editsectiononrightclick' => 'విభాగం పేరు మీద కుడి క్లిక్కుతో విభాగం మార్పు కావాలి (జావాస్క్రిప్టు)',
 'tog-showtoc' => 'విషయసూచిక చూపించు (3 కంటే ఎక్కువ శీర్షికలున్న పేజీలకు)',
 'tog-rememberpassword' => 'ఈ విహారిణిలో నా ప్రవేశాన్ని గుర్తుంచుకో (గరిష్ఠంగా $1 {{PLURAL:$1|రోజు|రోజుల}}కి)',
 'tog-watchcreations' => 'నేను సృష్టించే పేజీలను మరియు దస్త్రాలను నా వీక్షణ జాబితాకు చేర్చు',
 'tog-watchdefault' => 'నేను మార్చే పేజీలను మరియు దస్త్రాలను నా వీక్షణ జాబితాకు చేర్చు',
-'tog-watchmoves' => 'నేను తరలించిన పేజీలను దస్త్రాలను నా వీక్షణ జాబితాకు చేర్చు',
-'tog-watchdeletion' => 'నేను తొలగించిన పేజీలను దస్త్రాలను నా వీక్షణ జాబితాకు చేర్చు',
+'tog-watchmoves' => 'à°¨à±\87à°¨à±\81 à°¤à°°à°²à°¿à°\82à°\9aà°¿à°¨ à°ªà±\87à°\9cà±\80లనà±\81 à°®à°°à°¿à°¯à±\81 à°¦à°¸à±\8dà°¤à±\8dరాలనà±\81 à°¨à°¾ à°µà±\80à°\95à±\8dà°·à°£ à°\9cాబితాà°\95à±\81 à°\9aà±\87à°°à±\8dà°\9aà±\81',
+'tog-watchdeletion' => 'à°¨à±\87à°¨à±\81 à°¤à±\8aà°²à°\97à°¿à°\82à°\9aà°¿à°¨ à°ªà±\87à°\9cà±\80లనà±\81 à°®à°°à°¿à°¯à±\81 à°¦à°¸à±\8dà°¤à±\8dరాలనà±\81 à°¨à°¾ à°µà±\80à°\95à±\8dà°·à°£ à°\9cాబితాà°\95à±\81 à°\9aà±\87à°°à±\8dà°\9aà±\81',
 'tog-minordefault' => 'ప్రత్యేకంగా తెలుపనంతవరకూ నా మార్పులను చిన్న మార్పులుగా గుర్తించు',
-'tog-previewontop' => 'à°µà±\8dయాసà°\82 à°®à°¾à°°à±\8dà°ªà±\81à°² à°¤à°°à±\81వాత à°\8eలావà±\81à°\82à°\9fà±\81à°\82à°¦à±\8b à°®à°¾à°°à±\8dà°ªà±\81à°²â\80\8c à°¬à°¾à°\95à±\8dà°¸à±\81à°\95à±\81 పైన చూపు',
-'tog-previewonfirst' => 'దిదà±\8dదిబాà°\9fà±\8dà°²à±\81 à°\9aà±\87సిన à°µà±\8dయాసానà±\8dని à°­à°¦à±\8dరపరిà°\9aà±\87 à°®à±\81à°\82à°¦à±\81 à°\8eలా à°µà±\81à°\82à°\9fà±\81à°\82à°¦à±\8b à°\92à°\95సారి చూపించు',
-'tog-nocache' => 'విహారిణిలో పుటల కాషింగుని అచేతనంచేయి',
-'tog-enotifwatchlistpages' => 'నా à°µà±\80à°\95à±\8dషణాà°\9cాబితా à°²à±\8bని à°ªà±\87à°\9cà±\80 à°²à±\87దా à°¦à°¸à±\8dà°¤à±\8dà°°à°\82 à°®à°¾à°°à°¿à°¨à°ªà±\81à°¡à±\81 à°¨à°¾à°\95à±\81 à°\88-à°®à±\86యిలà±\81 à°ªà°\82పిà°\82à°\9aà±\81',
-'tog-enotifusertalkpages' => 'నా à°\9aà°°à±\8dà°\9aà°¾ à°ªà±\87à°\9cà±\80à°²à±\8b à°®à°¾à°°à±\8dà°ªà±\81à°²à±\81 à°\9cà°°à°¿à°\97ినపà±\81à°¡à±\81 à°¨à°¾à°\95à±\81 à°\88-à°®à±\86యిలà±\81 à°ªà°\82పిà°\82à°\9aà±\81',
-'tog-enotifminoredits' => 'à°ªà±\87à°\9cà±\80à°²à±\81 à°®à°°à°¿à°¯à±\81 à°¦à°¸à±\8dà°¤à±\8dరాలà°\95à±\81 à°\9cà°°à°¿à°\97à±\87 à°\9aà°¿à°¨à±\8dà°¨ à°®à°¾à°°à±\8dà°ªà±\81à°²à°\95à±\81 à°\95à±\82à°¡à°¾ à°¨à°¾à°\95à±\81 à°\88-à°®à±\86యిలà±\81à°¨à±\81 à°ªà°\82పిà°\82à°\9aà±\81',
+'tog-previewontop' => 'à°µà±\8dయాసà°\82 à°®à°¾à°°à±\8dà°ªà±\81à°² à°®à±\81à°¨à±\81à°\9aà±\82à°ªà±\81 à°¸à°µà°°à°¿à°\82à°\9aà±\81 à°ªà±\86à°\9fà±\8dà°\9fà±\86 పైన చూపు',
+'tog-previewonfirst' => 'à°®à±\8aà°¦à°\9fà°¿  à°¦à°¿à°¦à±\8dà°¦à±\81బాà°\9fà±\81 à°\9aà±\87సినపà±\81à°¡à±\81 à°µà±\8dయాసపà±\81 à°®à±\81à°¨à±\81à°\9aà±\82à°ªà±\81 చూపించు',
+'tog-nocache' => 'విహారిణిలో పుటల  స్థానికనకలును(కాషింగు) అచేతనం చేయి',
+'tog-enotifwatchlistpages' => 'నా వీక్షణాజాబితా లోని పేజీ లేదా దస్త్రం మారినపుడు నాకు ఈ-మెయిలు పంపు',
+'tog-enotifusertalkpages' => 'నా చర్చా పేజీలో మార్పులు జరిగినపుడు నాకు ఈ-మెయిలు పంపు',
+'tog-enotifminoredits' => 'పేజీలు మరియు దస్త్రాలకు జరిగే చిన్న మార్పులకు కూడా నాకు ఈ-మెయిలును పంపు',
 'tog-enotifrevealaddr' => 'గమనింపు మెయిళ్ళలో నా ఈ-మెయిలు చిరునామాను చూపించు',
-'tog-shownumberswatching' => 'à°µà±\80à°\95à±\8dà°·à°\95à±\81à°² à°¸à°\82à°\96à±\8dయనà±\81 à°\9aà±\82పిà°\82à°\9aà±\81',
+'tog-shownumberswatching' => 'వీక్షకుల సంఖ్యను చూపు',
 'tog-oldsig' => 'ప్రస్తుత సంతకం:',
 'tog-fancysig' => 'సంతకాన్ని వికీపాఠ్యంగా తీసుకో (ఆటోమెటిక్‌ లింకు లేకుండా)',
 'tog-uselivepreview' => 'రాస్తున్నదానిని ఎప్పటికప్పుడు సరిచూడండి (జావాస్క్రిప్టు) (పరీక్షాదశలో ఉంది)',
@@ -358,7 +356,7 @@ $messages = array(
 'articlepage' => 'విషయపు పేజీని చూడండి',
 'talk' => 'చర్చ',
 'views' => 'చూపులు',
-'toolbox' => 'పనిముట్ల పెట్టె',
+'toolbox' => 'పనిముట్ల',
 'userpage' => 'వాడుకరి పేజీని చూడండి',
 'projectpage' => 'ప్రాజెక్టు పేజీని చూడు',
 'imagepage' => 'ఫైలు పేజీని చూడండి',
@@ -367,7 +365,7 @@ $messages = array(
 'viewhelppage' => 'సహాయం పేజీని చూడు',
 'categorypage' => 'వర్గం పేజీని చూడు',
 'viewtalkpage' => 'చర్చను చూడు',
-'otherlanguages' => 'à°\87తర à°­à°¾à°·à°²à°²à±\8a',
+'otherlanguages' => 'à°\87తర à°­à°¾à°·à°²à°²à±\8b',
 'redirectedfrom' => '($1 నుండి మళ్ళించబడింది)',
 'redirectpagesub' => 'దారిమార్పు పుట',
 'lastmodifiedat' => 'ఈ పేజీకి $2, $1న చివరి మార్పు జరిగినది.',
@@ -388,7 +386,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}} గురించి',
 'aboutpage' => 'Project:గురించి',
-'copyright' => 'విషయ సంగ్రహం $1  కి లోబడి లభ్యం.',
+'copyright' => 'విషయం $1 కి లోబడి లభ్యం, వేరుగా పేర్కొంటే తప్ప.',
 'copyrightpage' => '{{ns:project}}:ప్రచురణ హక్కులు',
 'currentevents' => 'ఇప్పటి ముచ్చట్లు',
 'currentevents-url' => 'Project:ఇప్పటి ముచ్చట్లు',
@@ -414,8 +412,6 @@ $1',
 'ok' => 'సరే',
 'retrievedfrom' => '"$1" నుండి వెలికితీశారు',
 'youhavenewmessages' => 'మీకు $1 ఉన్నాయి ($2).',
-'newmessageslink' => 'కొత్త సందేశాలు',
-'newmessagesdifflink' => 'చివరి మార్పు',
 'youhavenewmessagesfromusers' => 'మీకు {{PLURAL:$3|మరో వాడుకరి|$3 వాడుకరుల}} నుండి $1 ($2).',
 'youhavenewmessagesmanyusers' => 'మీకు చాలా వాడుకరుల నుండి $1 ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ఒక కొత్త సందేశం వచ్చింది|కొత్త సందేశాలు ఉన్నాయి}}',
@@ -530,7 +526,7 @@ $2',
 'titleprotected' => "సభ్యులు [[User:$1|$1]] ఈ పేజీని సృష్టించనివ్వకుండా నిరోదిస్తున్నారు.
 అందుకు ఇచ్చిన కారణం: ''$2''.",
 'exception-nologin' => 'లోనికి ప్రవేశించిలేరు',
-'exception-nologin-text' => 'à°\88 à°µà°¿à°\95à±\80à°²à±\8b à°\88 à°ªà±\87à°\9cà±\80 à°²à±\87దా à°ªà°¨à°¿à°\95à°¿ à°®à±\80à°°à±\81 à°¤à°ªà±\8dపనిసరిà°\97à°¾ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aà°¿à°µà±\81à°\82డాలి.',
+'exception-nologin-text' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°\9aà±\82డడానిà°\95à°¿ à°²à±\87దా à°\88 à°\9aà°°à±\8dయనà±\81 à°\9aà±\86à°¯à±\8dయడానిà°\95à°¿ à°¦à°¯à°\9aà±\87సి [[Special:Userlogin|à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aà°\82à°¡à°¿]].',
 
 # Virus scanner
 'virus-badscanner' => "తప్పుడు స్వరూపణం: తెలియని వైరస్ స్కానర్: ''$1''",
@@ -552,6 +548,7 @@ $2',
 'yourname' => 'వాడుకరి పేరు:',
 'userlogin-yourname' => 'వాడుకరి పేరు',
 'userlogin-yourname-ph' => 'మీ వాడుకరి పేరును ఇవ్వండి',
+'createacct-another-username-ph' => 'మీ వాడుకరి పేరును ప్రవేశపెట్టండి',
 'yourpassword' => 'సంకేతపదం:',
 'userlogin-yourpassword' => 'సంకేతపదం',
 'userlogin-yourpassword-ph' => 'మీ సంకేతపదాన్ని ఇవ్వండి',
@@ -580,7 +577,7 @@ $2',
 'gotaccount' => 'ఇప్పటికే మీకు ఖాతా ఉందా? $1.',
 'gotaccountlink' => 'ప్రవేశించండి',
 'userlogin-resetlink' => 'మీ ప్రవేశ వివరాలను మరచిపోయారా?',
-'userlogin-resetpassword-link' => 'à°®à±\80 à°¦à°¾à°\9fà±\81మాà°\9fà°¨à±\81 à°®à°¾à°°à±\8dà°\9aà±\81à°\95à±\8bà°\82à°¡à°¿',
+'userlogin-resetpassword-link' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదానà±\8dని à°®à°°à±\8dà°\9aà°¿à°ªà±\8bయారా?',
 'helplogin-url' => 'Help:ప్రవేశించడం',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|ప్రవేశించడానికి సహాయం]]',
 'createacct-join' => 'మీ సమాచారాన్ని క్రింద ఇవ్వండి.',
@@ -890,7 +887,7 @@ $2
 'nocreate-loggedin' => 'కొత్త పేజీలను సృష్టించేందుకు మీకు అనుమతి లేదు.',
 'sectioneditnotsupported-title' => 'విభాగపు దిద్దిబాట్లకి తొడ్పాటు లేదు',
 'sectioneditnotsupported-text' => 'ఈ పేజీలో విభాగాల దిద్దుబాటుకి తోడ్పాటు లేదు.',
-'permissionserrors' => 'à°\85à°¨à±\81మతà±\81à°² à°¤à°ªà±\8dపిదాలà±\81',
+'permissionserrors' => 'à°\85à°¨à±\81మతి à°²à±\8bà°ªà°\82',
 'permissionserrorstext' => 'కింద పేర్కొన్న {{PLURAL:$1|కారణం|కారణాల}} మూలంగా, ఆ పని చెయ్యడానికి మీకు అనుమతిలేదు:',
 'permissionserrorstext-withaction' => 'ఈ క్రింది {{PLURAL:$1|కారణం|కారణాల}} వల్ల, మీకు $2 అనుమతి లేదు:',
 'recreate-moveddeleted-warn' => "'''హెచ్చరిక: ఇంతకు మునుపు ఒకసారి తొలగించిన పేజీని మళ్లీ సృష్టిద్దామని మీరు ప్రయత్నిస్తున్నారు.'''
@@ -1031,7 +1028,7 @@ $3 చెప్పిన కారణం: ''$2''",
 * అనుచితమైన వ్యక్తిగత సమాచారం
 * "ఇంటి చిరునామాలు, టెలిఫోను నంబర్లు, సోషల్ సెక్యూరిటీ నంబర్లు, వగైరాలు"',
 'revdelete-legend' => 'సందర్శక నిబంధనలు అమర్చు',
-'revdelete-hide-text' => 'à°\95à±\82à°°à±\8dà°ªà±\81 à°ªà°¾à° à±\8dయానà±\8dని à°¦à°¾à°\9aà±\81',
+'revdelete-hide-text' => 'à°ªà±\81à°¨à°\83పరిశà±\80లన à°ªà°¾à° à±\8dà°¯à°\82',
 'revdelete-hide-image' => 'ఫైలులోని విషయాన్ని దాచు',
 'revdelete-hide-name' => 'చర్యను, లక్ష్యాన్నీ దాచు',
 'revdelete-hide-comment' => 'దిద్దుబాటు వ్యాఖ్యను దాచు',
@@ -1186,8 +1183,6 @@ $1",
 'preferences' => 'అభిరుచులు',
 'mypreferences' => 'అభిరుచులు',
 'prefs-edits' => 'దిద్దుబాట్ల సంఖ్య:',
-'prefsnologin' => 'లాగిన్‌ అయిలేరు',
-'prefsnologintext' => 'వాడుకరి అభిరుచులను మార్చుకోడానికి, మీరు <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} లోనికి ప్రవేశించి]</span> ఉండాలి.',
 'changepassword' => 'సంకేతపదాన్ని మార్చండి',
 'prefs-skin' => 'అలంకారం',
 'skin-preview' => 'మునుజూపు/సరిచూడు',
@@ -1326,7 +1321,7 @@ $1",
 'group-bot' => 'బాట్‌లు',
 'group-sysop' => 'నిర్వాహకులు',
 'group-bureaucrat' => 'అధికారులు',
-'group-suppress' => 'పరాకులు',
+'group-suppress' => ' పూర్తి తొలగింపుదారులు',
 'group-all' => '(అందరూ)',
 
 'group-user-member' => '{{GENDER:$1|వాడుకరి}}',
@@ -1334,14 +1329,14 @@ $1",
 'group-bot-member' => '{{GENDER:$1|బాట్}}',
 'group-sysop-member' => '{{GENDER:$1|నిర్వాహకుడు|నిర్వాహకురాలు}}',
 'group-bureaucrat-member' => '{{GENDER:$1|అధికారి|అధికారిణి}}',
-'group-suppress-member' => 'పరాà°\95ు',
+'group-suppress-member' => 'à°ªà±\82à°°à±\8dతి   à°¤à±\8aà°²à°\97à°¿à°\82à°ªు',
 
 'grouppage-user' => '{{ns:project}}:వాడుకరులు',
 'grouppage-autoconfirmed' => '{{ns:project}}:ఆటోమాటిగ్గా నిర్ధారించబడిన వాడుకరులు',
 'grouppage-bot' => '{{ns:project}}:బాట్లు',
 'grouppage-sysop' => '{{ns:project}}:నిర్వాహకులు',
 'grouppage-bureaucrat' => '{{ns:project}}:అధికార్లు',
-'grouppage-suppress' => '{{ns:project}}:పరాà°\95ు',
+'grouppage-suppress' => '{{ns:project}}:à°ªà±\82à°°à±\8dతి à°¤à±\8aà°²à°\97à°¿à°\82à°ªు',
 
 # Rights
 'right-read' => 'పేజీలు చదవడం',
@@ -1459,6 +1454,7 @@ $1",
 'recentchanges-label-minor' => 'ఇది ఒక చిన్న మార్పు',
 'recentchanges-label-bot' => 'ఈ మార్పును ఒక బాటు చేసింది',
 'recentchanges-label-unpatrolled' => 'ఈ దిద్దుబాటు మీద నిఘా లేదు',
+'recentchanges-legend-newpage' => '$1 - కొత్త పేజీ',
 'rcnote' => "$4 నాడు $5 సమయానికి, గత {{PLURAL:$2|ఒక్క రోజులో|'''$2''' రోజులలో}} చేసిన చివరి {{PLURAL:$1|ఒక్క మార్పు కింద ఉంది|'''$1''' మార్పులు కింద ఉన్నాయి}}.",
 'rcnotefrom' => '<b>$2</b> నుండి జరిగిన మార్పులు (<b>$1</b> వరకు చూపబడ్డాయి).',
 'rclistfrom' => '$1 నుండి జరిగిన మార్పులను చూపించు',
@@ -1481,7 +1477,7 @@ $1",
 'rc_categories_any' => 'ఏదయినా',
 'rc-change-size-new' => 'మార్పు తర్వాత $1 {{PLURAL:$1|బైటు|బైట్లు}}',
 'newsectionsummary' => '/* $1 */ కొత్త విభాగం',
-'rc-enhanced-expand' => 'వివరాలని à°\9aà±\82పిà°\82à°\9aà±\81 (à°\9cావాసà±\8dà°\95à±\8dà°°à°¿à°ªà±\8dà°\9fà±\8d à°\85వసరà°\82)',
+'rc-enhanced-expand' => 'వివరాలనà±\81 à°\9aà±\82పిà°\82à°\9aà±\81',
 'rc-enhanced-hide' => 'వివరాలను దాచు',
 'rc-old-title' => 'మొదట "$1"గా సృష్టించారు',
 
@@ -1902,7 +1898,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization చూడండి.',
 'nopagetext' => 'మీరు అడిగిన పేజీ లేదు',
 'pager-newer-n' => '{{PLURAL:$1|1 కొత్తది|$1 కొత్తవి}}',
 'pager-older-n' => '{{PLURAL:$1|1 పాతది|$1 పాతవి}}',
-'suppress' => 'పరాకు',
+'suppress' => ' పూర్తి తొలగింపు',
 'querypage-disabled' => 'పనితీరు కారణాల వలన, ఈ ప్రత్యేకపేజీని అశక్తం చేసాం.',
 
 # Book sources
@@ -2279,9 +2275,9 @@ $1',
 'contributions' => '{{GENDER:$1|వాడుకరి}} రచనలు',
 'contributions-title' => '$1 యొక్క మార్పులు-చేర్పులు',
 'mycontris' => 'మార్పులు చేర్పులు',
-'contribsub2' => '$1 ($2) కొరకు',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) కొరకు',
 'nocontribs' => 'ఈ విధమైన మార్పులేమీ దొరకలేదు.',
-'uctop' => '(à°ªà±\88ది)',
+'uctop' => '(à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤)',
 'month' => 'ఈ నెల నుండి (అంతకు ముందువి):',
 'year' => 'ఈ సంవత్సరం నుండి (అంతకు ముందువి):',
 
@@ -2579,7 +2575,7 @@ $1',
 'allmessagesdefault' => 'అప్రమేయ సందేశపు పాఠ్యం',
 'allmessagescurrent' => 'ప్రస్తుత పాఠ్యం',
 'allmessagestext' => 'మీడియావికీ పేరుబరిలో ఉన్న అంతరవర్తి సందేశాల జాబితా ఇది.
-సాధారణ మీడియావికీ స్థానికీకరణకి మీరు తోడ్పడాలనుకుంటే, దయచేసి [//www.mediawiki.org/wiki/Localisation మీడియావికీ స్థానికీకరణ] మరియు [//translatewiki.net ట్రాన్స్&zwnj;లేట్&zwnj;వికీ.నెట్] సైట్లను చూడండి.',
+సాధారణ మీడియావికీ స్థానికీకరణకి మీరు తోడ్పడాలనుకుంటే, దయచేసి [https://www.mediawiki.org/wiki/Localisation మీడియావికీ స్థానికీకరణ] మరియు [//translatewiki.net ట్రాన్స్&zwnj;లేట్&zwnj;వికీ.నెట్] సైట్లను చూడండి.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' అన్నది అచేతనం చేసి ఉన్నందువల్ల ఈ పేజీని వాడలేరు.",
 'allmessages-filter-legend' => 'వడపోత',
 'allmessages-filter' => 'కస్టమైజేషను స్థితిని బట్టి వడకట్టు:',
@@ -3249,7 +3245,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'బయటి అప్లికేషను వాడి ఈ ఫైలును మార్చు',
-'edit-externally-help' => '(మరింత సమాచారం కొరకు [//www.mediawiki.org/wiki/Manual:External_editors సెటప్‌ సూచనల]ని చూడండి)',
+'edit-externally-help' => '(మరింత సమాచారం కొరకు [https://www.mediawiki.org/wiki/Manual:External_editors సెటప్‌ సూచనల]ని చూడండి)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'అన్నీ',
@@ -3415,7 +3411,7 @@ $5
 'version-hook-subscribedby' => 'ఉపయోగిస్తున్నవి',
 'version-version' => '(సంచిక $1)',
 'version-license' => 'లైసెన్సు',
-'version-poweredby-credits' => "ఈ వికీ  '''[//www.mediawiki.org/ మీడియావికీ]'''చే శక్తిమంతం, కాపీహక్కులు  © 2001-$1 $2.",
+'version-poweredby-credits' => "ఈ వికీ  '''[https://www.mediawiki.org/ మీడియావికీ]'''చే శక్తిమంతం, కాపీహక్కులు  © 2001-$1 $2.",
 'version-poweredby-others' => 'ఇతరులు',
 'version-license-info' => 'మీడియావికీ అన్నది స్వేచ్ఛా మృదూపకరణం; మీరు దీన్ని పునఃపంపిణీ చేయవచ్చు మరియు/లేదా ఫ్రీ సాఫ్ట్&zwnj;వేర్ ఫౌండేషన్ ప్రచురించిన గ్నూ జనరల్ పబ్లిక్ లైసెస్సు వెర్షను 2 లేదా (మీ ఎంపిక ప్రకారం) అంతకంటే కొత్త వెర్షను యొక్క నియమాలకు లోబడి మార్చుకోవచ్చు.
 
@@ -3450,8 +3446,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'ప్రత్యేక పేజీలు',
-'specialpages-note' => '----
-* మామూలు ప్రత్యేక పుటలు.
+'specialpages-note' => '* మామూలు ప్రత్యేక పుటలు.
 * <strong class="mw-specialpagerestricted">నియంత్రిత ప్రత్యేక పుటలు.</strong>
 * <span class="mw-specialpagecached">Cached ప్రత్యేక పుటలు (పాతబడి ఉండొచ్చు).</span>',
 'specialpages-group-maintenance' => 'నిర్వహణా నివేదికలు',
@@ -3600,4 +3595,16 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|శతాబ్దం|శతాబ్దాలు}}',
 'duration-millennia' => '$1 {{PLURAL:$1|సహస్రాబ్దం|సహస్రాబ్దాలు}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'మూసలను విస్తరించు',
+'expand_templates_intro' => 'ఈ ప్రత్యేక పేజీ మీరిచ్చిన మూసలను పూర్తిగా విస్తరించి, చూపిస్తుంది. ఇది <nowiki>{{</nowiki>#language:...}} వంటి పార్సరు ఫంక్షన్లను, <nowiki>{{</nowiki>CURRENTDAY}} వంటి చరరాశులను(వేరియబుల్) కూడా విస్తరిస్తుంది &mdash; నిజానికి జమిలి(మీసాల) బ్రాకెట్లలో ఉన్న ప్రతీదాన్నీ ఇది విస్తరిస్తుంది. మీడియావికీ నుండి సంబంధిత పార్సరు స్టేజిని పిలిచి ఇది ఈ పనిని సాధిస్తుంది.',
+'expand_templates_title' => '{{FULLPAGENAME}} మొదలగు వాటి కొరకు సందర్భ శీర్షిక:',
+'expand_templates_input' => 'విస్తరించవలసిన పాఠ్యం:',
+'expand_templates_output' => 'ఫలితం',
+'expand_templates_xml_output' => 'XML ఔట్&zwnj;పుట్',
+'expand_templates_ok' => 'సరే',
+'expand_templates_remove_comments' => 'వ్యాఖ్యలను తొలగించు',
+'expand_templates_generate_xml' => 'XML పార్స్ ట్రీని చూపించు',
+'expand_templates_preview' => 'మునుజూపు',
+
 );
index 51a6d73..2df3f10 100644 (file)
@@ -256,8 +256,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Husi "$1"',
 'youhavenewmessages' => 'Ó iha $1 ($2).',
-'newmessageslink' => 'mensajen foun',
-'newmessagesdifflink' => 'diferensa foun liu hotu',
 'youhavenewmessagesmulti' => 'Ó iha mensajen foun sira iha $1',
 'editsection' => 'edita',
 'editold' => 'edita',
@@ -915,7 +913,7 @@ Ligasaun seluk iha liña - ne'e pájina sira iha ne'ebé bele inklui imajen aat.
 'exif-urgency-high' => 'Aas ($1)',
 
 # External editor support
-'edit-externally-help' => "(Haree [//www.mediawiki.org/wiki/Manual:External_editors iha ne'e] ba informasaun barak liu)",
+'edit-externally-help' => "(Haree [https://www.mediawiki.org/wiki/Manual:External_editors iha ne'e] ba informasaun barak liu)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'hotu',
@@ -992,4 +990,7 @@ Ligasaun seluk iha liña - ne'e pájina sira iha ne'ebé bele inklui imajen aat.
 # Search suggestions
 'searchsuggest-search' => 'Buka',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'OK',
+
 );
index f7ea5cd..ee1eefa 100644 (file)
@@ -322,8 +322,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Баргирифта аз "$1"',
 'youhavenewmessages' => 'Шумо $1 ($2) доред.',
-'newmessageslink' => 'пайёмҳои нав',
-'newmessagesdifflink' => 'тағйироти охирин',
 'youhavenewmessagesmulti' => 'Шумо номаҳои нав дар $1 доред.',
 'editsection' => 'вироиш',
 'editold' => 'вироиш',
@@ -851,8 +849,6 @@ $1',
 'preferences' => 'Тарҷиҳот',
 'mypreferences' => 'Танзимот',
 'prefs-edits' => 'Шумораи вироишҳо:',
-'prefsnologin' => 'Ба систем ворид нашудаед',
-'prefsnologintext' => 'Барои танзими тарҷиҳоти корбарӣ бояд [[Special:UserLogin|вуруд ба систем шавед]].',
 'changepassword' => 'Иваз намудани калимаи убур',
 'prefs-skin' => 'Пӯст',
 'skin-preview' => 'Пешнамоиш',
@@ -1829,7 +1825,7 @@ $1',
 'allmessagesdefault' => 'Матни қарордодӣ',
 'allmessagescurrent' => 'Матни кунунӣ',
 'allmessagestext' => 'Ин феҳристи паёмҳои системавии дастрас дар фазои номи MediaWiki мебошад.
-Агар майли ҳиссагузорӣ карданро ба маҳалликунонии MediaWiki доред, пас лутан саҳифаҳои [//www.mediawiki.org/wiki/Localisation Маҳалликунонии MediaWiki] ва [//translatewiki.net translatewiki.net] нигаред.',
+Агар майли ҳиссагузорӣ карданро ба маҳалликунонии MediaWiki доред, пас лутан саҳифаҳои [https://www.mediawiki.org/wiki/Localisation Маҳалликунонии MediaWiki] ва [//translatewiki.net translatewiki.net] нигаред.',
 'allmessagesnotsupportedDB' => "Аз ин саҳифа наметавон истифода бурд, чун '''\$wgUseDatabaseMessages''' ғайрифаъол гардонида шудааст.",
 'allmessages-filter-legend' => 'Филтр',
 'allmessages-filter-all' => 'Ҳама',
@@ -2304,7 +2300,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Ин файлро бо барномаи беруна таҳрир кунед',
-'edit-externally-help' => '(Барои иттилооти бештар [//www.mediawiki.org/wiki/Manual:External_editors роҳнамои танзимотро оиди вироишгарони беруна] нигаред)',
+'edit-externally-help' => '(Барои иттилооти бештар [https://www.mediawiki.org/wiki/Manual:External_editors роҳнамои танзимотро оиди вироишгарони беруна] нигаред)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ҳама',
@@ -2520,4 +2516,19 @@ $5
 'revdelete-unrestricted' => 'маҳдудиятҳо аз мудирон бардошта шуданд',
 'rightsnone' => '(ҳеҷ)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Бастдодани шаблонҳо',
+'expand_templates_intro' => 'Ин саҳифаи вижа матнеро дарёфт карда ва тамоми шаблонҳои ба кор рафта дар онро ба таври бозгаште баст медиҳад. Ҳамчунин тобеҳои таҷзеҳ
+<nowiki>{{</nowiki>#language:...}}, ва мутағйирҳое чун
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;ро ҳам баст медиҳад – дар воқеъ тақрибан ҳар чиро ки дохили ду акулот бошад.
+Ин кор бо садо задани марҳилаи таҷзеҳи марбут дар худи МедиаВики сурат мегирад.',
+'expand_templates_title' => 'Унвони мавзӯъ, барои {{FULLPAGENAME}} ва ғайра.:',
+'expand_templates_input' => 'Матни вурудӣ:',
+'expand_templates_output' => 'Натиҷа',
+'expand_templates_xml_output' => 'Хуруҷӣ XML',
+'expand_templates_ok' => 'Таъйид',
+'expand_templates_remove_comments' => 'Ҳазфи тавзеҳот',
+'expand_templates_generate_xml' => 'Намоиши дарахти таҷзеҳи XML',
+'expand_templates_preview' => 'Пешнамоиш',
+
 );
index 40debf6..389bf17 100644 (file)
@@ -263,8 +263,6 @@ $1",
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Bargirifta az "$1"',
 'youhavenewmessages' => 'Şumo $1 ($2) dored.',
-'newmessageslink' => 'pajjomhoi nav',
-'newmessagesdifflink' => 'taƣjiroti oxirin',
 'youhavenewmessagesmulti' => 'Şumo nomahoi nav dar $1 dored.',
 'editsection' => 'viroiş',
 'editold' => 'viroiş',
@@ -725,7 +723,6 @@ Itminon hosil kuned, ki in taƣjir davomnokiji ta'rixiji sahifaro nigoh dorad.",
 'preferences' => 'Tarçihot',
 'mypreferences' => 'Tarçihoti man',
 'prefs-edits' => 'Şumorai viroişho:',
-'prefsnologin' => 'Ba sistem vorid naşudaed',
 'changepassword' => 'Ivaz namudani kalimai ubur',
 'prefs-skin' => 'Pūst',
 'skin-preview' => 'Peşnamoiş',
@@ -1615,7 +1612,7 @@ Dar holati oxir şumo metavoned pajvandero istifoda bared, namuna. [[{{#Special:
 'allmessagesdefault' => 'Matni qarordodī',
 'allmessagescurrent' => 'Matni kununī',
 'allmessagestext' => 'In fehristi pajomhoi sistemaviji dastras dar fazoi nomi MediaWiki meboşad.
-Agar majli hissaguzorī kardanro ba mahallikunoniji MediaWiki dored, pas lutan sahifahoi [//www.mediawiki.org/wiki/Localisation Mahallikunoniji MediaWiki] va [//translatewiki.net translatewiki.net] nigared.',
+Agar majli hissaguzorī kardanro ba mahallikunoniji MediaWiki dored, pas lutan sahifahoi [https://www.mediawiki.org/wiki/Localisation Mahallikunoniji MediaWiki] va [//translatewiki.net translatewiki.net] nigared.',
 'allmessagesnotsupportedDB' => "Az in sahifa nametavon istifoda burd, cun '''\$wgUseDatabaseMessages''' ƣajrifa'ol gardonida şudaast.",
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter-all' => 'Hama',
@@ -2088,7 +2085,7 @@ Faqat satrhoe, ki bo * şurū' şavand ba nazar girifta meşavand. Avvalin pajva
 
 # External editor support
 'edit-externally' => 'In fajlro bo barnomai beruna tahrir kuned',
-'edit-externally-help' => '(Baroi ittilooti beştar [//www.mediawiki.org/wiki/Manual:External_editors rohnamoi tanzimotro oidi viroişgaroni beruna] nigared)',
+'edit-externally-help' => '(Baroi ittilooti beştar [https://www.mediawiki.org/wiki/Manual:External_editors rohnamoi tanzimotro oidi viroişgaroni beruna] nigared)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'hama',
@@ -2297,4 +2294,19 @@ Tavaççūh kuned, ki şumo metavoned az [[Special:EditWatchlist|viroişgari sta
 'revdelete-unrestricted' => 'mahdudijatho az mudiron bardoşta şudand',
 'rightsnone' => '(heç)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Bastdodani şablonho',
+'expand_templates_intro' => "In sahifai viƶa matnero darjoft karda va tamomi şablonhoi ba kor rafta dar onro ba tavri bozgaşte bast medihad. Hamcunin tobehoi taçzeh
+<nowiki>{{</nowiki>#language:...}}, va mutaƣjirhoe cun
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;ro ham bast medihad – dar voqe' taqriban har ciro ki doxili du akulot boşad.
+In kor bo sado zadani marhilai taçzehi marbut dar xudi MediaViki surat megirad.",
+'expand_templates_title' => "Unvoni mavzū', baroi {{FULLPAGENAME}} va ƣajra.:",
+'expand_templates_input' => 'Matni vurudī:',
+'expand_templates_output' => 'Natiça',
+'expand_templates_xml_output' => 'Xuruçī XML',
+'expand_templates_ok' => "Ta'jid",
+'expand_templates_remove_comments' => 'Hazfi tavzehot',
+'expand_templates_generate_xml' => 'Namoişi daraxti taçzehi XML',
+'expand_templates_preview' => 'Peşnamoiş',
+
 );
index a0d9ec1..4849162 100644 (file)
@@ -60,7 +60,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'ชื่อเรื่องไม่เหมาะสม' ),
        'Blankpage'                 => array( 'หน้าว่าง' ),
        'Block'                     => array( 'บล็อกไอพี' ),
-       'Blockme'                   => array( 'บล็อกฉัน' ),
        'Booksources'               => array( 'แหล่งหนังสือ' ),
        'BrokenRedirects'           => array( 'เปลี่ยนทางเสีย' ),
        'Categories'                => array( 'หมวดหมู่' ),
@@ -72,7 +71,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'สร้างบัญชีผู้ใช้ใหม่' ),
        'Deadendpages'              => array( 'หน้าสุดทาง' ),
        'DeletedContributions'      => array( 'การแก้ไขที่ถูกลบ' ),
-       'Disambiguations'           => array( 'แก้ความกำกวม' ),
        'DoubleRedirects'           => array( 'เปลี่ยนทางซ้ำซ้อน' ),
        'EditWatchlist'             => array( 'แก้ไขรายการเฝ้าดู' ),
        'Emailuser'                 => array( 'อีเมลผู้ใช้' ),
@@ -471,8 +469,6 @@ $1',
 'ok' => 'ตกลง',
 'retrievedfrom' => 'รับข้อมูลจาก "$1"',
 'youhavenewmessages' => 'คุณมี$1 ($2)',
-'newmessageslink' => 'ข้อความใหม่',
-'newmessagesdifflink' => 'การเปลี่ยนแปลงล่าสุด',
 'youhavenewmessagesfromusers' => 'คุณมี $1จาก{{PLURAL:$3|ผู้ใช้คนอื่น|ผู้ใช้ $3 คน}} ($2)',
 'youhavenewmessagesmanyusers' => 'คุณมี $1จากผู้ใช้หลายคน ($2)',
 'newmessageslinkplural' => '$1 ข้อความใหม่',
@@ -1292,8 +1288,6 @@ $1",
 'preferences' => 'ตั้งค่าส่วนตัว',
 'mypreferences' => 'การตั้งค่า',
 'prefs-edits' => 'จำนวนการแก้ไข:',
-'prefsnologin' => 'ไม่ได้ล็อกอิน',
-'prefsnologintext' => 'คุณต้อง<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ล็อกอิน]</span>ก่อนเพื่อตั้งค่าส่วนตัว',
 'changepassword' => 'เปลี่ยนรหัสผ่าน',
 'prefs-skin' => 'หน้าตา',
 'skin-preview' => 'แสดงตัวอย่าง',
@@ -1590,6 +1584,7 @@ $1",
 'recentchanges-label-minor' => 'เป็นการแก้ไขเล็กน้อย',
 'recentchanges-label-bot' => 'การแก้ไขนี้กระทำโดยบอต',
 'recentchanges-label-unpatrolled' => 'การแก้ไขนี้ยังไม่ได้ตรวจสอบ',
+'recentchanges-legend-newpage' => '$1 - หน้าใหม่',
 'rcnote' => "รายการด้านล่างคือการแก้ไข {{PLURAL:$1|'''1''' รายการ|ล่าสุด '''$1''' รายการ}} ในช่วง '''$2''' วันที่ผ่านมา จนถึง $5, $4",
 'rcnotefrom' => "ด้านล่างเป็นการเปลี่ยนแปลงตั้งแต่ '''$2''' (มากสุด '''$1''' รายการ)",
 'rclistfrom' => 'แสดงการเปลี่ยนแปลงใหม่เริ่มตั้งแต่ $1',
@@ -2784,7 +2779,7 @@ $1',
 'allmessagesdefault' => 'ข้อความตามค่าตั้งต้น',
 'allmessagescurrent' => 'ข้อความปัจจุบัน',
 'allmessagestext' => 'นี่คือรายการข้อความของระบบที่อยู่ในเนมสเปซมีเดียวิกิ
-กรุณาอ่านหน้า[//www.mediawiki.org/wiki/Localisation เทศวิวัตน์ของมีเดียวิกิ] และ [//translatewiki.net translatewiki.net] ถ้าคุณอยากที่จะช่วยแปลข้อความของระบบมีเดียวิกิ',
+กรุณาอ่านหน้า[https://www.mediawiki.org/wiki/Localisation เทศวิวัตน์ของมีเดียวิกิ] และ [//translatewiki.net translatewiki.net] ถ้าคุณอยากที่จะช่วยแปลข้อความของระบบมีเดียวิกิ',
 'allmessagesnotsupportedDB' => "หน้านี้ไม่สามารถใช้งานได้เนื่องจาก '''\$wgUseDatabaseMessages''' ถูกระงับการใช้งาน",
 'allmessages-filter-legend' => 'กรอง',
 'allmessages-filter' => 'กรองตามสถานะที่เลือก:',
@@ -3442,7 +3437,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'แก้ไขไฟล์นี้โดยใช้ซอฟต์แวร์ตัวอื่น',
-'edit-externally-help' => '(ดู[//www.mediawiki.org/wiki/Manual:External_editors วิธีการตั้งค่า]สำหรับข้อมูลเพิ่มเติม)',
+'edit-externally-help' => '(ดู[https://www.mediawiki.org/wiki/Manual:External_editors วิธีการตั้งค่า]สำหรับข้อมูลเพิ่มเติม)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ทั้งหมด',
@@ -3645,7 +3640,7 @@ $5
 'version-hook-subscribedby' => 'สนับสนุนโดย',
 'version-version' => '(รุ่น $1)',
 'version-license' => 'สัญญาอนุญาต',
-'version-poweredby-credits' => "วิกินี้จัดทำโดย '''[//www.mediawiki.org/ MediaWiki]''', สงวนลิขสิทธิ์ © 2001-$1 โดย $2",
+'version-poweredby-credits' => "วิกินี้จัดทำโดย '''[https://www.mediawiki.org/ MediaWiki]''', สงวนลิขสิทธิ์ © 2001-$1 โดย $2",
 'version-poweredby-others' => 'ผู้อื่น',
 'version-poweredby-translators' => 'ผู้แปล translatewiki.net',
 'version-license-info' => 'มีเดียวิกิเป็นซอฟต์แวร์เสรี คุณสามารถแจกจ่าย และ/หรือ แก้ไขได้ภายใต้เงื่อนไขแห่งสัญญาอนุญาตสาธารณะทั่วไปของกนูตามที่เผยแพร่โดยมูลนิธิซอฟต์แวร์เสรี ไม่ว่ารุ่นที่ 2 แห่งสัญญาอนุญาต หรือรุ่นภายหลังอื่นใด (ตามที่คุณเลือก)
@@ -3684,8 +3679,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'หน้าพิเศษ',
-'specialpages-note' => '----
-* หน้าพิเศษปกติ
+'specialpages-note' => '* หน้าพิเศษปกติ
 * <span class="mw-specialpagerestricted">หน้าพิเศษที่ถูกจำกัด</span>',
 'specialpages-group-maintenance' => 'รายงานการเก็บกวาด',
 'specialpages-group-other' => 'หน้าพิเศษอื่น ๆ',
@@ -3841,4 +3835,8 @@ $5
 'duration-centuries' => '$1 ศตวรรษ',
 'duration-millennia' => '$1 สหัสวรรษ',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'ตกลง',
+'expand_templates_preview' => 'ตัวอย่างผลแสดง',
+
 );
index 30a9c33..a7a22fd 100644 (file)
@@ -296,8 +296,6 @@ Bu sahypany ulanmak üçin MediaWikiniň $1 wersiýasy talap edilýär. [[Specia
 'ok' => 'OK',
 'retrievedfrom' => '"$1" adresinden alyndy.',
 'youhavenewmessages' => 'Size $1 bar. ($2)',
-'newmessageslink' => 'täze habar',
-'newmessagesdifflink' => 'soňky üýtgeşme',
 'youhavenewmessagesmulti' => 'Size $1-de täze habar bar.',
 'editsection' => 'redaktirle',
 'editold' => 'redaktirle',
@@ -1000,8 +998,6 @@ Emma olaryň {{SITENAME}} indeksleriniň möwriti geçen bolmagy mümkindir.',
 'preferences' => 'Ileri tutmalar',
 'mypreferences' => 'Ileri tutmalar',
 'prefs-edits' => 'Özgerdiş sany:',
-'prefsnologin' => 'Sessiýa açmansyňyz',
-'prefsnologintext' => 'Ulanyjy ileri tutmalaryny üýtgetmek üçin <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} sessiýa açmagyňyz gerek]</span>.',
 'changepassword' => 'Paroly üýtget',
 'prefs-skin' => 'Bezeg',
 'skin-preview' => 'Deslapky syn',
@@ -1261,6 +1257,7 @@ $1 {{PLURAL:$1|simwoldan|simwoldan}} köp bolmaly däl.',
 'recentchanges-label-minor' => 'Bu bir ujypsyzja özgerdiş',
 'recentchanges-label-bot' => 'Bu özgerdiş bir bot tarapyndan amala aşyryldy',
 'recentchanges-label-unpatrolled' => 'Bu özgerdişe heniz patrullyk edilmändir',
+'recentchanges-legend-newpage' => '$1 - täze sahypa',
 'rcnote' => "Aşakda $5, $4 senesinden başlap, soňky {{PLURAL:$2|1 günde|'''$2''' günde}} edilen {{PLURAL:$1|'''1''' üýtgeşme|'''$1''' üýtgeşme}} görkezilýär.",
 'rcnotefrom' => '<b>$2</b> senesinden bäri edilen özgerdişler aşakda görkezilýär (<b>$1</b> sanysyna çenli).',
 'rclistfrom' => '$1 senesinden bäri edilen özgerdişleri görkez',
@@ -2327,7 +2324,7 @@ Ikinji ýagdaýy saýlap alan halatyňyzda, ýörite bir çykgyt hem ulanyp bile
 'allmessagesdefault' => 'Gaýybana habarlaşyk teksti',
 'allmessagescurrent' => 'Häzirki habarlaşyk teksti',
 'allmessagestext' => 'Bu sanaw MediaWiki at giňişliginde bar bolan ulgam habarlaşyklarynyň sanawydyr.
-Umumy MediaWiki lokalizasiýasyna goşan goşmak isleýän bolsaňyz, [//www.mediawiki.org/wiki/Localisation MediaWiki lokalizasiýasy] we [//translatewiki.net translatewiki.net] sahypalaryna baryp görmegiňizi haýyş edýäris.',
+Umumy MediaWiki lokalizasiýasyna goşan goşmak isleýän bolsaňyz, [https://www.mediawiki.org/wiki/Localisation MediaWiki lokalizasiýasy] we [//translatewiki.net translatewiki.net] sahypalaryna baryp görmegiňizi haýyş edýäris.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' ýapykdygy zerarly bu sahypany ulanyp bolmaýar.",
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter' => 'Üýtgediş statusy boýunça filtr:',
@@ -2488,6 +2485,8 @@ Mazmun üçin bir sebäp goşmaga rugsat berýär',
 'spambot_username' => 'MediaWiki spam arassalaýyş',
 'spam_reverting' => '$1 sahypasyna çykgytlary bolmadyk iň soňky wersiýasyna yzyna getirilýär',
 'spam_blanking' => 'Ähli wersiýalarda $1 sahypasyna çykgytlar bar, boşadylýar',
+'simpleantispam-label' => "Anti-spam barlagy.
+Muny '''DOLDURMAŇ'''!",
 
 # Patrolling
 'markaspatrolleddiff' => 'Patrullyk edilen diýip belle',
@@ -2836,7 +2835,7 @@ Ondan soňraky çykgyt(lar) kadadan çykma hökmünde kabul edilýär, meselem:
 
 # External editor support
 'edit-externally' => 'Bu faýly daşarky programmalary ulanyp redaktirläň',
-'edit-externally-help' => '(Has köp maglumat üçin metadaky [//www.mediawiki.org/wiki/Manual:External_editors gurmak boýunça gollanma] sahypasyna göz aýlaň)',
+'edit-externally-help' => '(Has köp maglumat üçin metadaky [https://www.mediawiki.org/wiki/Manual:External_editors gurmak boýunça gollanma] sahypasyna göz aýlaň)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Ählisini görkez',
@@ -2998,7 +2997,7 @@ Bolanyňyzdan soňra "{{int:Watchlistedit-raw-submit}}" düwmesine basyň.
 'version-hook-subscribedby' => 'Abuna ýazylan',
 'version-version' => '(Wersiýa $1)',
 'version-license' => 'Ygtyýarnama',
-'version-poweredby-credits' => "Bu wiki '''[//www.mediawiki.org/ MediaWiki]''' arkaly üpjün edilýär, awtorlyk hukugy © 2001-$1 $2.",
+'version-poweredby-credits' => "Bu wiki '''[https://www.mediawiki.org/ MediaWiki]''' arkaly üpjün edilýär, awtorlyk hukugy © 2001-$1 $2.",
 'version-poweredby-others' => 'beýlekiler',
 'version-license-info' => 'MediaWiki erkin programmadyr; MediaWiki-ni Erkin programma fondy tarapyndan çazp edilen GNU General Public License lisenziýasynyň ikini wersiýasynyň ýa-da (islegiňize görä) has täzeki bir wersiýasynyň şertlerine laýyklykda täzeden paýlap we/ýa-da üýtgedip bilersiňiz.
 
@@ -3021,8 +3020,7 @@ Bu programmanyň ýany bilen siz [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General P
 
 # Special:SpecialPages
 'specialpages' => 'Ýörite sahypalar',
-'specialpages-note' => '----
-* Adaty ýörite sahypalar.
+'specialpages-note' => '* Adaty ýörite sahypalar.
 * <strong class="mw-specialpagerestricted">Çäklendirilen ýörite sahypalar.</strong>',
 'specialpages-group-maintenance' => 'Tehniki abatlaýyş hasabatlary',
 'specialpages-group-other' => 'Başga ýörite sahypalar',
@@ -3107,4 +3105,21 @@ Bu programmanyň ýany bilen siz [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General P
 'searchsuggest-search' => 'Gözleg',
 'searchsuggest-containing' => 'öz içine alýar...',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Şablonlary giňelt',
+'expand_templates_intro' => 'Bu ýörite sahypa birazajyk tekst alýar we onuň içindäki ähli şablonlary rekursiw giňeldýär.
+Şeýlede şu hili parser funksiýalaryny hem giňeldýär
+<nowiki>{{</nowiki>#language:…}} we şuňa meňzeş üýtgeýänleri
+<nowiki>{{</nowiki>CURRENTDAY}}&mdash;aslynda jübüt ýaýly ähli zatlary diýen ýaly.
+Ol muny degişli parser sepgidini MediaWikiniň özünden çagyryp edýär.',
+'expand_templates_title' => 'Kontekst ady, {{FULLPAGENAME}} we ş.m. üçin:',
+'expand_templates_input' => 'Giriş teksti:',
+'expand_templates_output' => 'Netije',
+'expand_templates_xml_output' => 'XML önümi',
+'expand_templates_ok' => 'Bolýar',
+'expand_templates_remove_comments' => 'Teswirleri aýyr',
+'expand_templates_remove_nowiki' => 'Netijelerde <nowiki> teglerini bökdäň',
+'expand_templates_generate_xml' => 'XML ýygnama agajyny görkez',
+'expand_templates_preview' => 'Deslapky syn',
+
 );
index 4142d51..43c0bb5 100644 (file)
@@ -12,6 +12,7 @@
  * @author Felipe Aira
  * @author Jojit fb
  * @author Kaganer
+ * @author Namayan
  * @author Sky Harbor
  * @author tl.wikipedia.org sysops
  * @author לערי ריינהארט
@@ -51,7 +52,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Masamang_pamagat' ),
        'Blankpage'                 => array( 'Tanggalin_ang_nilalaman_ng_pahina' ),
        'Block'                     => array( 'Hadlangan', 'Hadlangan_ang_IP', 'Hadlangan_ang_tagagamit' ),
-       'Blockme'                   => array( 'Hadlangang_ako' ),
        'Booksources'               => array( 'Mga_pinagmulang_aklat' ),
        'BrokenRedirects'           => array( 'Naputol_na_mga_panturo_papunta_sa_ibang_pahina', 'NaputulangPanturo' ),
        'Categories'                => array( 'Mga_kategorya' ),
@@ -63,10 +63,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Likhain_ang_kuwenta', 'LikhaKuwenta' ),
        'Deadendpages'              => array( 'Mga_pahinang_sukol', 'Mga_pahinang_walang_lagusan' ),
        'DeletedContributions'      => array( 'Naburang_mga_ambag' ),
-       'Disambiguations'           => array( 'Mga_paglilinaw', 'Paglilinaw' ),
        'DoubleRedirects'           => array( 'Nagkadalawang_mga_panturo_papunta_sa_ibang_pahina', 'DoblengPanturo' ),
        'EditWatchlist'             => array( 'Baguhin_ang_Bantayan' ),
        'Emailuser'                 => array( 'Tagagamit_ng_e-liham' ),
+       'ExpandTemplates'           => array( 'Palawakin_ang_mga_suleras' ),
        'Export'                    => array( 'Pagluluwas' ),
        'Fewestrevisions'           => array( 'Pinakakaunting_mga_pagbabago' ),
        'FileDuplicateSearch'       => array( 'Paghahanap_ng_kamukhang_talaksan' ),
@@ -109,6 +109,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Mga_pahinang_nakasanggalang' ),
        'Protectedtitles'           => array( 'Mga_pamagat_na_nakasanggalang' ),
        'Randompage'                => array( 'Alin_man', 'Alin_mang_pahina' ),
+       'RandomInCategory'          => array( 'Alinmang_kaurian' ),
        'Randomredirect'            => array( 'Pagtuturo_papunta_sa_alin_mang_pahina' ),
        'Recentchanges'             => array( 'Mga_huling_binago', 'HulingBinago' ),
        'Recentchangeslinked'       => array( 'Nakakawing_ng_kamakailang_pagbabago', 'Kaugnay_na_mga_pagbabago' ),
@@ -285,8 +286,6 @@ $messages = array(
 'broken-file-category' => 'Mga pahina na may sirang mga kawing ng talaksan',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Patungkol',
 'article' => 'Pahina ng nilalaman',
 'newwindow' => '(magbubukas sa bagong bintana)',
@@ -423,8 +422,6 @@ Tingnan ang [[Special:Version|pahina ng bersiyon]].',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => 'Ikinuha mula sa "$1"',
 'youhavenewmessages' => 'Mayroon kang $1 ($2).',
-'newmessageslink' => 'mga bagong mensahe',
-'newmessagesdifflink' => 'huling pagbabago',
 'youhavenewmessagesfromusers' => 'Mayroon kang $1 magmula sa {{PLURAL:$3|ibang tagagamit|$3 mga tagagamit}} ($2).',
 'youhavenewmessagesmanyusers' => 'Mayroon kang $1 magmula sa maraming mga tagagamit ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|isang bagong mensahe|bagong mga mensahe}}',
@@ -1238,8 +1235,6 @@ Subuking lagyan ng unlapi/paunang ''all:'' upang hanapin ang lahat ng mga nialal
 'preferences' => 'Mga kagustuhan',
 'mypreferences' => 'Mga nais',
 'prefs-edits' => 'Bilang ng mga pagbabago:',
-'prefsnologin' => 'Hindi nakalagda/nakatala',
-'prefsnologintext' => 'Kailangan mong <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} lumagda/tumala]</span> para makapagtakda ng mga kagustuhang ng tagagamit.',
 'changepassword' => 'Baguhin ang hudyat',
 'prefs-skin' => 'Pabalat',
 'skin-preview' => 'Unang tingin',
@@ -1519,6 +1514,7 @@ Kung pipiliin mong ibigay ito, gagamitin ito para mabigyan ka ng pagkilala para
 'recentchanges-label-minor' => 'Isa itong munting pagbabago',
 'recentchanges-label-bot' => 'Gawa ng isang bot ang pagbabagong ito',
 'recentchanges-label-unpatrolled' => 'Hindi pa napapatrulyahan ang pagbabagong ito',
+'recentchanges-legend-newpage' => '$1 - bagong pahina',
 'rcnote' => "Nasa ibaba {{PLURAL:$1|ang '''1''' pagbabago|ang pinakahuling '''$1''' mga pagbabago}} sa huling {{PLURAL:$2|araw|'''$2''' mga araw}}, mula noong $5, $4.",
 'rcnotefrom' => "Nasa ibaba ang mga pagbabago mula pa noong '''$2''' (ipinapakita ang magpahanggang sa '''$1''').",
 'rclistfrom' => 'Ipakita ang bagong mga pagbabago simula sa $1',
@@ -1656,9 +1652,9 @@ bumalik at ikarga ang talaksan na ito sa bagong pangalan. [[File:$1|thumb|center
 'uploadscripted' => 'Naglalaman ang talaksan na ito ng HTML o kodigong script na maaaring mali ang pagkaintindi ng isang web browser.',
 'uploadvirus' => 'Naglalaman ng virus ang talaksan! Mga detalye: $1',
 'uploadjava' => 'Ang talaksan ay isang talaksang ZIP na naglalaman ng isang .klase ng talaksan. na Java.  Hindi pinapayagan ang pagkakarga ng mga talaksang Java, dahil nakasasanhi sila ng mga paglilimita ng kaligtasan na kailangang lampasan.',
-'upload-source' => 'Pinagmulang talaksan',
+'upload-source' => 'Batayang talaksan',
 'sourcefilename' => 'Pangalan ng panggagalingang talaksan:',
-'sourceurl' => 'Pinagmulang URL:',
+'sourceurl' => 'Batayang URL:',
 'destfilename' => 'Pangalan ng patutunguhang talaksan:',
 'upload-maxfilesize' => 'Pinakamataas na sukat ng talaksan: $1',
 'upload-description' => 'Paglalarawan ng talaksan',
@@ -2031,12 +2027,11 @@ Pakitandaan lamang na ang iba mga websayt ay maaaring nakakawing sa isang talaks
 'querypage-disabled' => 'Hindi pinagagana ang natatanging pahinang ito para sa mga dahilan ng pagganap.',
 
 # Book sources
-'booksources' => 'Mapagkukuhanang mga aklat',
+'booksources' => 'Mga mapagkukunang aklat',
 'booksources-search-legend' => 'Maghanap ng mapagkukunang aklat',
 'booksources-isbn' => 'ISBN:',
-'booksources-go' => 'Punta',
-'booksources-text' => 'Matatagpuan sa ibaba ang mga tala ng mga ugnay sa ibang mga websayt na nagbebenta ng bago at nagamit na mga aklat, at maaring mayroon din
-na iba pang impormasyon tungkol sa mga aklat na hinahanap mo:',
+'booksources-go' => 'Puntahan',
+'booksources-text' => 'Matatagpuan sa ibaba ang isang tala ng mga kawil patungo sa ibang mga website na nagtitinda ng mga bago at gamit nang aklat, at maaaring may iba pang impormasyon ito tungkol sa mga aklat na hinahanap mo:',
 'booksources-invalid-isbn' => 'Tila mukhang hindi yata katanggap-tanggap ang ibinigay na ISBN; pakisuri kung may mga kamalian ang pagkakasip/pagkakakopya mula sa orihinal na pinagmulan.',
 
 # Special:Log
@@ -2252,7 +2247,7 @@ Tugon at karagdagang tulong:
 'excontentauthor' => "ang nilalaman ay: '$1' (at ang tanging nag-ambag ay si '[[Special:Contributions/$2|$2]]')",
 'exbeforeblank' => "nilalaman bago nablangko: '$1'",
 'exblank' => 'walang laman ang pahina',
-'delete-confirm' => 'Burahin "$1"',
+'delete-confirm' => 'Kaltasin ang "$1"',
 'delete-legend' => 'Burahin',
 'historywarning' => "'''Babala''': May kasaysayan ang pahinang buburahin mo na tinatayang may $1 {{PLURAL:$1|pagbabago|mga pagbabago}}:",
 'confirmdeletetext' => 'Lubos mo nang buburahin ang pahinang ito pati ang kalahatan ng kasaysayan nito.
@@ -2418,7 +2413,6 @@ Tingnan ang [[Special:Log/delete|talaan ng pagbubura]] para sa isang talaan ng m
 $1',
 'undelete-show-file-confirm' => 'Nakatitiyak ka bang ibig mong tanawin ang isang nabura nang pagbabago ng talaksang "<nowiki>$1</nowiki>" mula $2 noong $3?',
 'undelete-show-file-submit' => 'Oo',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'Ngalan-espasyo:',
@@ -2595,7 +2589,8 @@ Tingnan ang [[Special:BlockList|talaan ng pagharang]] para sa lista ng kasalukuy
 'proxyblockreason' => 'Hinarang ang IP address mo dahil bukas na proxy ito. Makipag-ugnayan sa iyong tagabigay ng serbisyong Internet o suportang teknikal at ipaalam sa kanila itong seryesong suliranin sa seguridad.',
 'sorbs' => 'DNSBL',
 'sorbsreason' => 'Nakalista ang IP address mo bilang isang bukas na proxy sa DNSBL na ginagamit ng sayt na ito.',
-'sorbs_create_account_reason' => 'Nakalista ang IP address mo bilang isang bukas na proxy sa DNSBL na ginagamit ng sayt na ito. Hindi ka makakalikha ng akawnt',
+'sorbs_create_account_reason' => 'Nakatala ang iyong IP address bilang open proxy sa DNSBL na ginagamit ng {{SITENAME}}.
+Hindi ka makakalikha ng account',
 'cant-block-while-blocked' => 'Hindi mo mahahadlangan/mahaharang ang ibang mga tagagamit habang hinahadlangan ka.',
 'cant-see-hidden-user' => 'Ang tagagamit na sinusubukan mong hadlangan ay naharang at naikubli na.
 Dahil wala kang karapatang magkubli ng tagagamit, hindi mo makikita o mababago ang paghadlang sa tagagamit.',
@@ -2743,8 +2738,8 @@ Sa huling kaso, maaari mong gumamit ng ungay, hal. [[{{#Special:Export}}/{{Media
 'allmessagesname' => 'Pangalan',
 'allmessagesdefault' => 'Tinakdang teksto',
 'allmessagescurrent' => 'Kasalukuyang teksto',
-'allmessagestext' => 'Isa itong talaan ng mga mensahe ng sistema na makukuha mula sa espasyo ng pangalang MediaWiki.
-Pakidalaw ang [//www.mediawiki.org/wiki/Localisation Lokalisasyong MediaWiki] at [//translatewiki.net translatewiki.net] kung ibig mong magambag sa heneriko o pangkalahatang lokalisasyon ng MediaWiki.',
+'allmessagestext' => 'Isa itong talaan ng mga mensahe ng sistema na makukuha mula sa namespace ng MediaWiki.
+Pakidalaw ang [https://www.mediawiki.org/wiki/Localisation Lokalisasyong MediaWiki] at [//translatewiki.net translatewiki.net] kung ibig mong magambag sa heneriko o pangkalahatang lokalisasyon ng MediaWiki.',
 'allmessagesnotsupportedDB' => "Hindi magagamit ang '''{{ns:special}}:AllMessages''' dahil hindi gumagana ang '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Salain',
 'allmessages-filter' => 'Salain ayon sa katayuan ng pagbabagay:',
@@ -2775,7 +2770,7 @@ Pakidalaw ang [//www.mediawiki.org/wiki/Localisation Lokalisasyong MediaWiki] at
 'import-interwiki-text' => 'Pumili ng isang wiki at pamagat ng pahina na iaangkat.
 Mapapanatili ang mga petsa ng pagbabago at mga pangalan ng patnugot.
 Naitatala sa [[Special:Log/import|tala ng inangkat]] ang lahat ng mga transwiking aksyon para sa pag-angkat.',
-'import-interwiki-source' => 'Pinagmulang wiki/pahina:',
+'import-interwiki-source' => 'Batayang wiki/pahina:',
 'import-interwiki-history' => 'Kopyahin ang lahat ng mga bersyon ng kasaysayan para sa pahinang ito',
 'import-interwiki-templates' => 'Isama ang lahat ng mga suleras',
 'import-interwiki-submit' => 'Mag-angkat',
@@ -2907,7 +2902,7 @@ Maaari mong tingnan ang batayan nito.',
 
 # Stylesheets
 'common.css' => '/* Ang inilagay na CSS dito ay gagamitin para sa lahat ng mga pabalat */',
-'cologneblue.css' => "/* Ang Cascading Style Sheets na inilagay dito ay makakaapekto sa mga tagagamit ng pabalat na Bughaw na Kolown (''Cologne Blue'') */",
+'cologneblue.css' => '/* Ang Cascading Style Sheets na inilagay dito ay makakaapekto sa mga tagagamit ng pabalat na Cologne Blue */',
 'monobook.css' => '/* Ang CSS na inilagay dito ay makakaapekto sa mga tagagamit ng pabalat na Monobook */',
 'modern.css' => "/* Ang CSS na iniligay dito ay makakaapekto sa tagagamit ng Makabagong (''Modern'') pabalat */",
 'vector.css' => '/* Ang inilagay na CSS dito ay makakaapekto sa mga tagagamit ng pabalat na Vector */',
@@ -2920,7 +2915,7 @@ Maaari mong tingnan ang batayan nito.',
 
 # Scripts
 'common.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa lahat ng mga tagagamit ng bawat pahinang ikinarga. */',
-'cologneblue.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit ng pabalat na Cologne Blue o Bughaw na Kolown */',
+'cologneblue.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit ng pabalat na Cologne Blue */',
 'monobook.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng pabalat na MonoBook */',
 'modern.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng Modernong pabalat */',
 'vector.js' => '/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng pabalat na Vector */',
@@ -2953,6 +2948,8 @@ Maaaring dahil ito sa isang kawing sa isang nakatalang hinarang dahil di-kinaisn
 'spam_reverting' => "Ibinabalik sa huling bersyon na 'di-naglalaman ng mga kawing sa $1",
 'spam_blanking' => 'Lahat ng mga pagbabago ay naglalaman ng mga kawing sa $1, pagpapatlang',
 'spam_deleting' => 'Lahat ng mga pagbabago ay naglalaman ng mga kawing sa $1, binubura',
+'simpleantispam-label' => "Pagsusuring panlaban sa \"manlulusob\" (''spam'').
+'''HUWAG''' itong lagyan ng laman!",
 
 # Info page
 'pageinfo-title' => 'Kabatiran para sa "$1"',
@@ -2987,8 +2984,8 @@ Maaaring dahil ito sa isang kawing sa isang nakatalang hinarang dahil di-kinaisn
 'pageinfo-templates' => '{{PLURAL:$1|Suleras|Mga suleras}} ($1) na nasa transklusyon (kasama sa maraming mga lugar)',
 
 # Skin names
-'skinname-cologneblue' => 'Bughaw na Kolown',
-'skinname-monobook' => 'MonoAklat ("isang aklat")',
+'skinname-cologneblue' => 'Cologne Blue',
+'skinname-monobook' => 'MonoBook',
 'skinname-modern' => 'Makabago (Moderno)',
 'skinname-vector' => 'Vector',
 
@@ -3866,7 +3863,7 @@ Maaari mo ring [[Special:EditWatchlist|gamitin ang pangkaraniwang pampatnugot]].
 'version-version' => '(Bersyon $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Lisensiya',
-'version-poweredby-credits' => "Ang wiking ito ay pinapatakbo ng '''[//www.mediawiki.org/ MediaWiki]''', karapatang-ari © 2001-$1 $2.",
+'version-poweredby-credits' => "Ang wiking ito ay pinapatakbo ng '''[https://www.mediawiki.org/ MediaWiki]''', karapatang-ari © 2001-$1 $2.",
 'version-poweredby-others' => 'iba pa',
 'version-license-info' => 'Ang MediaWiki ay isang malayang sopwer; maaari mo itong ipamahagi at/o baguhin ito sa ilalim ng mga patakaran ng Pangkalahatang Pangmadlang Lisensiyang GNU ayon sa pagkakalathala ng Pundasyon ng Malayang Sopwer; na maaaring bersyong 2 ng Lisensiya, o (kung nais mo) anumang susunod na bersyon.
 Ang MediaWiki ay ipinamamahagi na umaasang magiging gamitin, subaliut WALANG ANUMANG KATIYAKAN; ni walang pahiwatig ng PAGIGING MABENTA o KAANGKUPAN PARA ISANG TIYAK NA LAYUNIN.  Tingnan ang Pangkalahatang Pangmadlang Lisensiyang GNU para sa mas marami pang mga detalye.
@@ -3893,8 +3890,7 @@ Dapat na nakatanggap ka ng [{{SERVER}}{{SCRIPTPATH}}/COPYING isang sipi ng Pangk
 
 # Special:SpecialPages
 'specialpages' => 'Mga natatanging pahina',
-'specialpages-note' => '----
-* Normal na natatanging mga pahina.
+'specialpages-note' => '* Normal na natatanging mga pahina.
 * <span class="mw-specialpagerestricted">Pinaghihigpitang natatanging mga pahina.</span>',
 'specialpages-group-maintenance' => 'Mga pagpapanatiling ulat',
 'specialpages-group-other' => 'Iba pang natatanging mga pahina',
@@ -4076,4 +4072,21 @@ O kaya, maaari mo ring gamitin ang pinadaling pormularyo sa ibaba.  Madadagdagan
 'duration-centuries' => '$1 {{PLURAL:$1|daantaon|mga daantaon}}',
 'duration-millennia' => '$1 {{PLURAL:$1|milenyo|mga milenyo}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Palaparin (palawakin) ang mga suleras',
+'expand_templates_intro' => 'Ang natatanging pahinang ito ay kumukuha ng ilang mga teksto at nagbubuka ng lahat ng mga suleras sa loob nito sa kaparaanang tinatawag ang sarili o rekursibo.
+Nagbubuka rin ito ng mga tungkuling pambanghay na katulad ng
+<nowiki>{{</nowiki>#kung:…}}, at pabagubagong mga halagang katulad ng
+<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Sa katunayan, pinabubuka nito ang halos lahat ng mga bagay-bagay na may dalawang mga bantas na pansalalay o brakete.',
+'expand_templates_title' => 'Pamagat na pampaunawa (ng konteksto), para sa {{FULLPAGENAME}} atbp.:',
+'expand_templates_input' => 'Tekstong ipinasok:',
+'expand_templates_output' => 'Kinalabasan',
+'expand_templates_xml_output' => 'kinalabasang XML',
+'expand_templates_ok' => "Sige/Ayos 'yan",
+'expand_templates_remove_comments' => 'Tanggalin ang mga puna (kumento)',
+'expand_templates_remove_nowiki' => 'Pigilin ang mga tatak na <nowiki> sa loob ng resulta',
+'expand_templates_generate_xml' => 'Ipakita ang puno na pambanghay ng XML',
+'expand_templates_preview' => 'Paunang tingin',
+
 );
index 5e73c11..2fabc68 100644 (file)
@@ -364,8 +364,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Сәвон "$1"',
 'youhavenewmessages' => 'Шымә сәјоне $1 ($2).',
-'newmessageslink' => 'нујә хәбон',
-'newmessagesdifflink' => 'охонә дәгиши',
 'newmessagesdifflinkplural' => '$1 {{PLURAL:$1|охонә дәгиши|охонә дәгишон}}',
 'editsection' => 'Sərost kardey',
 'editold' => 'Сәрост кардеј',
@@ -616,8 +614,6 @@ $messages = array(
 # Preferences page
 'preferences' => 'Кукон',
 'mypreferences' => 'Кукон',
-'prefsnologin' => 'Ыштәни едаштәнијоне',
-'prefsnologintext' => 'Шымә бәбе <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ыштәни едәштән]</span> бо иштирокәкә пеғәндон дәгиш кардеј.',
 'changepassword' => 'Пароли дәгиш кардеј',
 'skin-preview' => 'Сыфтәнә нишо дој',
 'prefs-user-pages' => 'Иштирокәкә сәһифон',
@@ -1002,7 +998,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'Редактә кардеј ым фајли де заһири програм',
-'edit-externally-help' => '(Bo mıffəssələ məlumoton bə [//www.mediawiki.org/wiki/Manual:External_editors dərsəvon bo soxtəy] diyə bıkən)',
+'edit-externally-help' => '(Bo mıffəssələ məlumoton bə [https://www.mediawiki.org/wiki/Manual:External_editors dərsəvon bo soxtəy] diyə bıkən)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'һәммәј',
index 1329371..e8c207a 100644 (file)
@@ -191,7 +191,6 @@ $messages = array(
 
 'ok' => 'Fai ā',
 'youhavenewmessages' => 'ʻOku ʻi ai haʻo $1 ($2).',
-'newmessageslink' => 'ngaahi tala foʻou',
 'youhavenewmessagesmulti' => 'ʻOku ʻi ai haʻo tala foʻou ʻi $1',
 'editsection' => 'fatuʻi vahe',
 'editold' => 'fatu',
@@ -443,7 +442,6 @@ Ko e ʻuhinga loka ko e $1 ia.",
 # Preferences page
 'preferences' => 'Faʻiteliha',
 'mypreferences' => 'faʻiteliha ʻaʻaku',
-'prefsnologin' => 'ʻOku ʻikai kau ki ai',
 'changepassword' => 'Liliu hoʻo leatapu',
 'prefs-skin' => 'Kili',
 'skin-preview' => 'Vakai pē',
@@ -1144,7 +1142,7 @@ Pea hoko ai pē hoʻo lava tānaki ha ʻuhinga ʻi he fakanounou',
 
 # External editor support
 'edit-externally' => 'Fatuʻi ʻa e failé ni ngāueʻaki mo e polokalama ʻi tuʻa',
-'edit-externally-help' => 'Vakai ki he [//www.mediawiki.org/wiki/Manual:External_editors fakahinohino ki he fokotuʻu] maʻa toe fakamatala.',
+'edit-externally-help' => 'Vakai ki he [https://www.mediawiki.org/wiki/Manual:External_editors fakahinohino ki he fokotuʻu] maʻa toe fakamatala.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kātoa',
@@ -1220,4 +1218,7 @@ Kātaki fakapapauʻi te ke fie toe fatu ʻa e kupu ni.",
 # New logging system
 'rightsnone' => '(hala)',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Fakalahiange ʻa e ngaahi sīpinga',
+
 );
index 3906b88..d15ee57 100644 (file)
@@ -254,7 +254,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Ikam long "$1"',
 'youhavenewmessages' => '$1 i kam ($2).',
-'newmessageslink' => 'Ol nupela toksave',
 'editsection' => 'senisim',
 'editold' => 'senisim',
 'viewsourceold' => 'lukim as tok',
@@ -877,4 +876,7 @@ Yu inap lukim as tok bilong em',
 # Search suggestions
 'searchsuggest-search' => 'Painim',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'OK',
+
 );
index a32169b..3ec1143 100644 (file)
@@ -96,7 +96,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'KötüBaşlık', 'BozukBaşlık' ),
        'Blankpage'                 => array( 'BoşSayfa' ),
        'Block'                     => array( 'Engelle', 'IPEngelle' ),
-       'Blockme'                   => array( 'BeniEngelle' ),
        'Booksources'               => array( 'KitapKaynakları' ),
        'BrokenRedirects'           => array( 'BozukYönlendirmeler' ),
        'Categories'                => array( 'Kategoriler', 'Ulamlar' ),
@@ -108,10 +107,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'HesapOluştur' ),
        'Deadendpages'              => array( 'BağlantısızSayfalar' ),
        'DeletedContributions'      => array( 'SilinenKatkılar' ),
-       'Disambiguations'           => array( 'AnlamAyrımı', 'AnlamAyrım' ),
        'DoubleRedirects'           => array( 'ÇiftYönlendirmeler' ),
        'EditWatchlist'             => array( 'İzlemeListesiDüzenle' ),
        'Emailuser'                 => array( 'E-postaGönder' ),
+       'ExpandTemplates'           => array( 'ŞablonlarıGenişlet' ),
        'Export'                    => array( 'DışaAktar', 'DışarıAktar' ),
        'Fewestrevisions'           => array( 'EnAzRevizyon' ),
        'FileDuplicateSearch'       => array( 'KopyaDosyaArama', 'ÇiftDosyaArama' ),
@@ -155,6 +154,7 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'KorunanSayfalar' ),
        'Protectedtitles'           => array( 'KorunanBaşlıklar' ),
        'Randompage'                => array( 'Rastgele', 'RastgeleSayfa' ),
+       'RandomInCategory'          => array( 'RastgeleKategori', 'RastgeleUlam' ),
        'Randomredirect'            => array( 'RastgeleYönlendirme' ),
        'Recentchanges'             => array( 'SonDeğişiklikler' ),
        'Recentchangeslinked'       => array( 'İlgiliDeğişiklikler' ),
@@ -362,7 +362,7 @@ $messages = array(
 'tog-extendwatchlist' => 'İzleme listesini sadece en son değil, tüm değişiklikleri göstermek için genişlet',
 'tog-usenewrc' => 'Son değişiklikler sayfasındaki ve izleme listesindeki değişiklikleri gruplandır',
 'tog-numberheadings' => 'Başlıkları otomatik numaralandır',
-'tog-showtoolbar' => 'Düzenleme yaparken araç çubuğunu göster',
+'tog-showtoolbar' => 'Düzenleme araç çubuğunu göster',
 'tog-editondblclick' => 'Çift tıklayarak sayfaları düzenle',
 'tog-editsection' => 'Bölümleri [{{int:Editsection}}] bağlantıları ile düzenlemeyi etkinleştir',
 'tog-editsectiononrightclick' => 'Bölüm başlığına sağ tıklayarak bölümleri düzenleyebilme olanağı ver',
@@ -628,8 +628,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => '"$1" adresinden alındı.',
 'youhavenewmessages' => 'Yeni $1 var ($2).',
-'newmessageslink' => 'mesajınız',
-'newmessagesdifflink' => 'son değişiklik',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başka bir kullanıcıdan|$3 kullanıcıdan}} $1 var ($2).',
 'youhavenewmessagesmanyusers' => 'Birçok kullanıcıdan $1 var ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|yeni mesajınız|yeni mesajlarınız}}',
@@ -761,7 +759,8 @@ Kilitleyen hizmetlinin bu konudaki nedeni: "$3".',
 'invalidtitle-knownnamespace' => '"$2" alan adı için "$3" metni geçersiz bir başlık',
 'invalidtitle-unknownnamespace' => 'Bilinmeyen $1 ad alanı sayısı ve geçersiz "$2" başlık',
 'exception-nologin' => 'Giriş yapılmamış',
-'exception-nologin-text' => 'Bu sayfa ya da eylem için bu vikide oturum açmış olmanız gerekir.',
+'exception-nologin-text' => 'Bu sayfaya ya da eyleme erişmek için lütfen [[Special:Userlogin|oturum açın]].',
+'exception-nologin-text-manual' => 'Bu sayfaya ya da eyleme erişebilmek için lütfen $1ın.',
 
 # Virus scanner
 'virus-badscanner' => "Yanlış ayarlama: bilinmeyen virüs tarayıcı: ''$1''",
@@ -808,9 +807,12 @@ Tarayıcınızın önbelleğini temizleyinceye kadar bazı sayfalarda, oturumunu
 'gotaccount' => 'Zaten bir hesabınız var mı? $1.',
 'gotaccountlink' => 'Oturum açın',
 'userlogin-resetlink' => 'Giriş bilgilerinizi mi unuttunuz?',
-'userlogin-resetpassword-link' => 'Parolanızı sıfırlayın',
+'userlogin-resetpassword-link' => 'Parolanızı mı unuttunuz?',
 'helplogin-url' => 'Help:Oturum açma',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Oturum açma konusunda yardım alın]]',
+'userlogin-loggedin' => 'Zaten {{GENDER:$1|$1}} olarak oturum açtınız.
+Başka bir kullanıcı olarak oturum açmak için aşağıdaki formu kullanın.',
+'userlogin-createanother' => 'Başka bir hesap oluşturun',
 'createacct-join' => 'Aşağıya bilgilerinizi girin.',
 'createacct-another-join' => 'Aşağıya yeni hesabınızın bilgilerini girin.',
 'createacct-emailrequired' => 'E-posta adresi',
@@ -866,13 +868,13 @@ Parola değişimini siz istemediyseniz veya parolanızı hatırladıysanız ve a
 'noemailcreate' => 'Geçerli bir e-posta adresi sağlamalısınız',
 'passwordsent' => '"$1" adına kayıtlı e-posta adresine yeni bir parola gönderildi. Oturumu, lütfen, iletiyi aldıktan sonra açın.',
 'blocked-mailpassword' => 'Siteye erişiminiz engellenmiş olduğundan, yeni şifre gönderilme işlemi yapılamamaktadır.',
-'eauthentsent' => 'Kaydedilen adrese onay kodu içeren bir e-posta gönderildi.
-E-postadaki yönerge uygulanıp adresin size ait olduğu onaylanmadıkça başka e-posta gönderilmeyecek.',
+'eauthentsent' => 'Belirtilen e-posta adresine onay kodu içeren bir e-posta gönderildi.
+Hesaba başka bir e-posta gönderilmeden önce, e-postadaki yönergeleri uygulayıp, hesabın gerçekten size ait olduğunu onaylamanız gerekir.',
 'throttled-mailpassword' => 'Bir parola sıfırlama e-postası son {{PLURAL:$1|bir saat|$1 saat}} içinde zaten gönderildi. Hizmeti kötüye kullanmayı önlemek için, her {{PLURAL:$1|bir saatte|$1 saatte}} sadece bir parola sıfırlama e-postası gönderilecektir.',
 'mailerror' => 'E-posta gönderim hatası: $1',
 'acct_creation_throttle_hit' => 'Sizin IP adresinizi kullanarak bu vikiyi ziyaret edenler son günde {{PLURAL:$1|1 hesap|$1 hesap}} oluşturdu, bu sayı bu zaman aralığında izin verilen azami sayıdır.
 Sonuç olarak, bu IP adresini kullanan ziyaretçiler şu anda daha fazla hesap açamazlar.',
-'emailauthenticated' => 'E-posta adresiniz $2 $3 tarihinde doğrulandı.',
+'emailauthenticated' => 'E-posta adresiniz $2 $3 tarihinde onaylandı.',
 'emailnotauthenticated' => 'E-posta adresiniz henüz onaylanmadı.
 Aşağıdaki işlevlerin hiçbiri için e-posta gönderilmeyecektir.',
 'noemailprefs' => 'Bu özelliklerin çalışması için bir e-posta adresi belirtiniz.',
@@ -1303,19 +1305,20 @@ Bir hizmetli olarak bu değişikliği görebilirsiniz; [{{fullurl:{{#Special:Log
 'revdelete-text' => "'''Silinen revizyonlar ve olaylar hala sayfa geçmişinde ve günlüklerde görünecektir, fakat içeriğin parçaları umumi olarak erişilemeyecektir.'''
 {{SITENAME}} sitesindeki diğer hizmetliler gizli içeriğe erişebilir ve ilave kısıtlamalar ayarlanmadıysa bu arayüz ile geri getirebilir.",
 'revdelete-confirm' => 'Lütfen, bunu yapmak istediğinizi , sonuçlarını anladığınızı, ve bunu [[{{MediaWiki:Policy-url}}|ilkelere]] göre yapıyor olduğunuzu onaylayın.',
-'revdelete-suppress-text' => "Saklama '''sadece''' aşağıdaki durumlar için kullanılmalıdır:
+'revdelete-suppress-text' => "Saklama '''sadece''' aşağıdaki durumlarda kullanılmalıdır:
+* Muhtemel iftira niteliğindeki bilgi
 * Uygunsuz kişisel bilgi
 *: ''ev adresleri ve telefon numaraları, sosyal güvenlik numaraları, vs.''",
 'revdelete-legend' => 'Görünürlük kısıtlamaları ayarla',
-'revdelete-hide-text' => 'Değişiklik yazısını gizle',
+'revdelete-hide-text' => 'Revizyon metni',
 'revdelete-hide-image' => 'Dosya içeriğini gizle',
 'revdelete-hide-name' => 'Olayı ve hedefi gizle',
-'revdelete-hide-comment' => 'Özeti gösterme',
-'revdelete-hide-user' => 'Değişikliği yapan kullanıcı adını/IP adresi gizle',
+'revdelete-hide-comment' => 'Değişiklik özeti',
+'revdelete-hide-user' => "Editör'ün kullanıcı adı/IP adresi",
 'revdelete-hide-restricted' => 'Verileri hizmetlilerle birlikte diğerlerinden de sakla',
 'revdelete-radio-same' => '(değiştirme)',
-'revdelete-radio-set' => 'Evet',
-'revdelete-radio-unset' => 'Hayır',
+'revdelete-radio-set' => 'Gizli',
+'revdelete-radio-unset' => 'Görünür',
 'revdelete-suppress' => 'Verileri hem diğerlerinden hem de hizmetlilerden gizle',
 'revdelete-unsuppress' => 'Geri döndürülmüş revizyonlardaki kısıtlamaları kaldır',
 'revdelete-log' => 'Neden:',
@@ -1400,6 +1403,10 @@ Gezinti bağlantılarının bu sütunu sıfırlayacağını unutmayın.',
 'diff-empty' => '(Fark yok)',
 'diff-multi' => '({{PLURAL:$2|Bir kullanıcı|$2 kullanıcı}} tarafından yapılan {{PLURAL:$1|bir ara revizyon|$1 ara revizyon}} gösterilmiyor)',
 'diff-multi-manyusers' => '($2 kullancıdan fazla {{PLURAL:$2|kullanıcı|kullanıcı}} tarafından yapılan {{PLURAL:$1|bir ara revizyon|$1 ara revizyon}} gösterilmiyor)',
+'difference-missing-revision' => 'Bu farkın {{PLURAL:$2|bir revizyonu|$2 revizyonu}} ($1) {{PLURAL:$2|bulunamadı|bulunamadı}}.
+
+Bu genellikle, silinen bir sayfaya olan eski tarihli bir fark sayfasına bağlantılardan dolayı olur.
+Ayrıntılar [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} silme günlüğünde] bulunabilir.',
 
 # Search results
 'searchresults' => 'Arama sonuçları',
@@ -1462,13 +1469,13 @@ Aramanızın başına '''all:''' önekini ekleyerek tüm içeriği aramayı (tar
 'powersearch-togglenone' => 'Hiçbiri',
 'search-external' => 'Dış arama',
 'searchdisabled' => '{{SITENAME}} sitesinde arama yapma geçici olarak durdurulmuştur. Bu arada Google kullanarak {{SITENAME}} içinde arama yapabilirsiniz. Arama sitelerinde dizinlerin biraz eski kalmış olabileceğini göz önünde bulundurunuz.',
+'search-error' => 'Arama yapılırken bir hata oluştu: $1',
 
 # Preferences page
 'preferences' => 'Tercihler',
 'mypreferences' => 'Tercihler',
 'prefs-edits' => 'Değişiklik sayısı:',
-'prefsnologin' => 'Oturum açık değil',
-'prefsnologintext' => 'Kullanıcı tercihlerinizi ayarlamak için <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} giriş yapmalısınız]</span>.',
+'prefsnologintext2' => 'Kullanıcı tercihlerini ayarlamak için lütfen $1ın.',
 'changepassword' => 'Parolayı değiştir',
 'prefs-skin' => 'Görünüm',
 'skin-preview' => 'Önizleme',
@@ -1493,7 +1500,7 @@ Aramanızın başına '''all:''' önekini ekleyerek tüm içeriği aramayı (tar
 'prefs-rendering' => 'Görünüm',
 'saveprefs' => 'Kaydet',
 'resetprefs' => 'Ayarları ilk durumuna getir',
-'restoreprefs' => 'Tüm varsayılan ayarları geri yükle',
+'restoreprefs' => 'Tüm varsayılan ayarları geri yükle (tüm bölümlerde)',
 'prefs-editing' => 'Sayfa yazma alanı',
 'rows' => 'Satır',
 'columns' => 'Sütun',
@@ -1579,6 +1586,7 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'prefs-displaywatchlist' => 'Görüntüleme seçenekleri',
 'prefs-tokenwatchlist' => 'Anahtar',
 'prefs-diffs' => 'Farklar',
+'prefs-help-prefershttps' => 'Bu tercih bir sonraki girişinizde etkili olacaktır.',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => 'E-posta adresi geçerli görünüyor',
@@ -1602,9 +1610,11 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'userrights-no-interwiki' => 'Diğer vikilerdeki kullanıcıların izinlerini değiştirmeye yetkiniz yok.',
 'userrights-nodatabase' => '$1 veritabanı mevcut veya bölgesel değil',
 'userrights-nologin' => 'Kullanıcı haklarını atamak için hizmetli hesabı ile [[Special:UserLogin|giriş yapmanız gerekir]].',
-'userrights-notallowed' => 'Hesabınızın kullanıcı hakları eklemek veya kaldırmak için izni yok.',
+'userrights-notallowed' => 'Kullanıcı hakları eklemek veya kaldırmak için izniniz yok.',
 'userrights-changeable-col' => 'Değiştirebildiğiniz gruplar',
 'userrights-unchangeable-col' => 'Değiştirebilmediğiniz gruplar',
+'userrights-conflict' => 'Kullanıcı hakları değişikliklerinde çakışma! Lütfen değişikliklerinizi gözden geçirin ve onaylayın.',
+'userrights-removed-self' => 'Kendi haklarınız başarıyla kaldırıldı. Bu nedenle, artık bu sayfaya erişemeyeceksiniz.',
 
 # Groups
 'group' => 'Grup:',
@@ -1655,6 +1665,7 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'right-writeapi' => 'API yaz kullanımı',
 'right-delete' => 'Sayfaları sil',
 'right-bigdelete' => 'Uzun tarihli sayfaları sil',
+'right-deletelogentry' => 'Belirli günlük girdilerini sil ve geri getir',
 'right-deleterevision' => 'Sayfaların belirli revizyonlarını sil ve geri yükle',
 'right-deletedhistory' => 'Silinmiş geçmiş girdilerini gör, ilgili metinleri olmadan',
 'right-deletedtext' => 'Silinmiş metni ve silinmiş revizyonlar arasındaki değişiklikleri gör',
@@ -1669,11 +1680,18 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'right-proxyunbannable' => 'Proxylerin otomatik engellemelerini atla',
 'right-unblockself' => 'Kendi engellemesini kaldır',
 'right-protect' => 'Koruma düzeylerini değiştir ve kademeli korumalı sayfaları düzenle',
-'right-editprotected' => 'Korumalı sayfalarda değişiklik yap (korumayı basamaklamadan)',
+'right-editprotected' => '"{{int:protect-level-sysop}}" olarak korunan sayfalarda değişiklik yap',
+'right-editsemiprotected' => '"{{int:protect-level-autoconfirmed}}" olarak korunan sayfalarda değişiklik yap',
 'right-editinterface' => 'Kullanıcı arayüzünü değiştirmek',
 'right-editusercssjs' => 'Diğer kullanıcıların CSS ve JS dosyalarında değişiklik yap',
 'right-editusercss' => 'Diğer kullanıcıların CSS dosyalarında değişiklik yap',
 'right-edituserjs' => 'Diğer kullanıcıların JS dosyalarında değişiklik yap',
+'right-editmyusercss' => 'Kendi kullanıcı CSS dosyaları düzenle',
+'right-editmyuserjs' => 'Kendi kullanıcı JavaScript dosyalarını düzenle',
+'right-viewmywatchlist' => 'Kendi izleme listeni gör',
+'right-editmywatchlist' => 'Kendi izleme listeni düzenle. Not, bazı eylemler bu yetki olmadan da sayfa ekleyebilir.',
+'right-viewmyprivateinfo' => 'Kendi özel bilgilerini görüntüle (e-posta adresi, gerçek isim vb.)',
+'right-editmyprivateinfo' => 'Kendi özel bilgilerini değiştir (e-posta adresi, gerçek isim vb.)',
 'right-editmyoptions' => 'tercihlerini düzenle',
 'right-rollback' => 'Belirli bir sayfayı değiştiren son kullanıcının değişikliklerini hızlıca geri döndür',
 'right-markbotedits' => 'Geri döndürülen değişiklikleri, bot değişiklikleri olarak işaretle',
@@ -1726,8 +1744,8 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'action-block' => 'bu kullanıcının değişiklik yapmasını engellemeye',
 'action-protect' => 'bu sayfa için koruma düzeylerini değiştirmeye',
 'action-rollback' => 'Belirli bir sayfayı değiştiren son kullanıcının değişikliklerini hızlıca geri döndür',
-'action-import' => 'bu sayfayı bir başka vikiden içeri aktarmaya',
-'action-importupload' => 'bu sayfayı bir dosya yüklemesinden içeri aktarmaya',
+'action-import' => 'başka bir vikiden sayfaları içeri aktarmaya',
+'action-importupload' => 'bir dosya yüklemesinden sayfaları içeri aktarmaya',
 'action-patrol' => 'diğerlerinin değişikliğini gözlenmiş olarak işaretlemeye',
 'action-autopatrol' => 'değişikliğinizi gözlenmiş olarak işaretlemeye',
 'action-unwatchedpages' => 'izlenmeyen sayfalar listesini görmeye',
@@ -1738,6 +1756,8 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'action-sendemail' => 'e-posta gönder',
 'action-editmywatchlist' => 'izleme listeni düzenle',
 'action-viewmywatchlist' => 'izleme listeni gör',
+'action-viewmyprivateinfo' => 'kendi özel bilgilerinizi görmeye',
+'action-editmyprivateinfo' => 'kendi özel bilgilerinizi değiştirmeye',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|değişiklik|değişiklik}}',
@@ -1752,6 +1772,8 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'recentchanges-label-minor' => 'Bu küçük bir değişiklik',
 'recentchanges-label-bot' => 'Bu değişiklik bir bot tarafından yapıldı',
 'recentchanges-label-unpatrolled' => 'Bu değişiklik henüz gözlenmemiş',
+'recentchanges-label-plusminus' => 'Sayfa boyutu bu bayt sayısı kadar değişti',
+'recentchanges-legend-newpage' => '(ayrıca bakınız [[Special:NewPages|yeni sayfalar listesi]])',
 'rcnote' => "$4 tarihi ve saat $5 itibarı ile, son {{PLURAL:$2|1 günde|'''$2''' günde}} yapılan, {{PLURAL:$1|'''1''' değişiklik|'''$1''' değişiklik}}, aşağıdadır.",
 'rcnotefrom' => "'''$2''' tarihinden itibaren yapılan değişiklikler aşağıdadır (en fazla <b>$1</b> tanesi gösterilmektedir).",
 'rclistfrom' => '$1 tarihinden itibaren yeni değişiklikleri göster',
@@ -1794,7 +1816,7 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'reuploaddesc' => 'Yükleme formuna geri dön.',
 'upload-tryagain' => 'Değiştirilmiş dosya açıklamasını gönder',
 'uploadnologin' => 'Oturum açık değil',
-'uploadnologintext' => 'Dosya yükleyebilmek için [[$1|oturum aç]]manız gerekiyor.',
+'uploadnologintext' => 'Dosya yükleyebilmek için $1manız gerekiyor.',
 'upload_directory_missing' => 'Yükleme dizini ($1) kayıp ve websunucusu tarafından oluşturulamıyor.',
 'upload_directory_read_only' => 'Dosya yükleme dizinine ($1) web sunucusunun yazma izni yok.',
 'uploaderror' => 'Yükleme hatası',
@@ -1932,13 +1954,19 @@ Eğer sorun tekrarlanırsa, bir [[Special:ListUsers/sysop|hizmetli]] ile temasa
 'upload-too-many-redirects' => 'URL çok fazla yönlendirme içeriyor',
 'upload-unknown-size' => 'Bilinmeyen boyut',
 'upload-http-error' => 'Bir HTTP hatası oluştu: $1',
+'upload-copy-upload-invalid-domain' => 'Kopya yüklemeler bu etki alanında mevcut değil.',
 
 # File backend
 'backend-fail-stream' => '$1 dosyası okunamadı.',
+'backend-fail-backup' => '"$1" dosyası yedeklenemedi.',
 'backend-fail-notexists' => '$1 dosyası mevcut değil.',
+'backend-fail-hashes' => 'Karşılaştırma için dosya sağlamaları alınamadı.',
+'backend-fail-notsame' => 'Aynı olmayan bir dosya "$1" konumunda zaten var.',
 'backend-fail-invalidpath' => '"$1" geçerli bir depolama yolu değil.',
 'backend-fail-delete' => '"$1" dosyası silinemedi.',
+'backend-fail-describe' => '"$1" dosyası için üstveri değiştirilemiyor.',
 'backend-fail-alreadyexists' => '"$1" dosyası zaten mevcut.',
+'backend-fail-store' => '"$1" dosyası "$2" konumuna saklanamadı.',
 'backend-fail-copy' => '"$1" dosyası, "$2" dosyasına kopyalanamadı.',
 'backend-fail-move' => '"$1" dosyası, "$2" dosyasına taşınamadı.',
 'backend-fail-opentemp' => 'Geçici dosya açılamadı.',
@@ -1947,6 +1975,29 @@ Eğer sorun tekrarlanırsa, bir [[Special:ListUsers/sysop|hizmetli]] ile temasa
 'backend-fail-read' => '$1 dosyası okunamadı.',
 'backend-fail-create' => '$1 dosyası yazılamadı.',
 'backend-fail-maxsize' => 'Dosya {{PLURAL:$2|bir bayt|$2 bayt}} daha büyük olduğu için "$1" dosyasına yazılamadı.',
+'backend-fail-readonly' => 'Depolama arkaplan uygulaması "$1" şu anda salt okunur. Verilen gerekçe: "\'\'$2\'\'"',
+'backend-fail-synced' => '"$1" dosyası dahili depolama arkaplan uygulamaları içinde tutarsız bir durumda',
+'backend-fail-connect' => '"$1" depolama arkaplan uygulamasına bağlanılamıyor.',
+'backend-fail-internal' => '"$1" depolama arkaplan uygulamasında bilinmeyen bir hata oluştu.',
+'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.',
+
+# File journal errors
+'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.',
+
+# Lock manager
+'lockmanager-notlocked' => '"$1" kilidi açılamıyor; kilitli değil.',
+'lockmanager-fail-closelock' => '"$1" için kilit dosyası kapatılamıyor.',
+'lockmanager-fail-deletelock' => '"$1" için kilit dosyası silinemiyor.',
+'lockmanager-fail-acquirelock' => '"$1" için kilit alınamıyor.',
+'lockmanager-fail-openlock' => '"$1" için kilit dosyası açılamıyor.',
+'lockmanager-fail-releaselock' => '"$1" için kilit serbest bırakılamıyor.',
+'lockmanager-fail-db-bucket' => '$1 kovasında yeterli kilit veri tabanına iletişim sağlanamadı.',
+'lockmanager-fail-db-release' => '$1 veritabanında kilitler serbest bırakılamıyor.',
+'lockmanager-fail-svr-acquire' => '$1 sunucusunda kilitler alınamıyor.',
+'lockmanager-fail-svr-release' => '$1 sunucusunda kilitler serbest bırakılamıyor.',
 
 # ZipDirectoryReader
 'zip-file-open-error' => 'Dosya ZIP denetimleri için açılırken bir hata ile karşılaşıldı.',
@@ -2011,8 +2062,7 @@ Sitenin daha az meşgul olduğu bir zamanda denemek daha iyi olabilir.',
 'upload_source_file' => ' (bilgisayarınızdaki bir dosya)',
 
 # Special:ListFiles
-'listfiles-summary' => 'Bu özel sayfa yüklenilen tüm dosyaları gösterir. 
-Kullanıcı tarafından filtrelendiğinde, sadece o kullanıcı dosyanın en son sürümünü yüklediği dosyalar gösterilir.',
+'listfiles-summary' => 'Bu özel sayfa yüklenen tüm dosyaları gösterir.',
 'listfiles_search_for' => 'Medya adı ara:',
 'imgfile' => 'dosya',
 'listfiles' => 'Dosya listesi',
@@ -2023,6 +2073,7 @@ Kullanıcı tarafından filtrelendiğinde, sadece o kullanıcı dosyanın en son
 'listfiles_size' => 'Boyut (bayt)',
 'listfiles_description' => 'Tanım',
 'listfiles_count' => 'Sürümler',
+'listfiles-show-all' => 'Görüntülerin eski sürümlerini içer',
 'listfiles-latestversion' => 'Geçerli sürüm',
 'listfiles-latestversion-yes' => 'Evet',
 'listfiles-latestversion-no' => 'Hayır',
@@ -2053,17 +2104,20 @@ Sıradaki liste sadece bu dosyaya bağlantı veren {{PLURAL:$1|ilk dosyayı|ilk
 'morelinkstoimage' => 'Bu dosyaya [[Special:WhatLinksHere/$1|daha fazla bağlantıları]] gör.',
 'linkstoimage-redirect' => '$1 (dosya yönlendirme) $2',
 'duplicatesoffile' => 'Şu {{PLURAL:$1|dosya|$1 dosya}}, bu dosyanın kopyası ([[Special:FileDuplicateSearch/$2|daha fazla ayrıntı]]):',
-'sharedupload' => 'Bu dosya $1 deposundan ve diğer projelerde kullanılıyor olabilir.',
+'sharedupload' => 'Bu dosya $1 projesinden olup, diğer projelerde kullanılıyor olabilir.',
 'sharedupload-desc-there' => 'Bu dosya $1 deposundan ve diğer projeler tarafından kullanılıyor olabilir. Daha fazla bilgi için lütfen [$2 dosya açıklama sayfasına] bakın.',
 'sharedupload-desc-here' => 'Bu dosya $1 deposundan ve diğer projeler tarafından kullanılıyor olabilir.
 Aşağıda [$2 dosya açıklama sayfasındaki] açıklama gösteriliyor.',
-'sharedupload-desc-create' => 'Bu dosya, $1 ve diğer projeler tarafından kullanılıyor olabilir. 
-Dosya açıklamasını düzenlemek isterseniz, [$2 dosya açıklama sayfası] bulunmaktadır.',
+'sharedupload-desc-edit' => 'Bu dosya $1 projesinden olup, diğer projelerde kullanılıyor olabilir.
+Dosyanın açıklama sayfasında değişiklik yapmak için ilgili sayfaya [$2 buradan] gidebilirsiniz.',
+'sharedupload-desc-create' => 'Bu dosya $1 projesinden olup, diğer projelerde kullanılıyor olabilir.
+Dosyanın açıklama sayfasında değişiklik yapmak için ilgili sayfaya [$2 buradan] gidebilirsiniz.',
 'filepage-nofile' => 'Bu isimde bir dosya yok.',
 'filepage-nofile-link' => 'Bu isimde bir dosya yok, ama siz [$1 yükleyebilirsiniz].',
 'uploadnewversion-linktext' => 'Dosyanın yenisini yükleyin',
 'shared-repo-from' => "$1'dan",
 'shared-repo' => 'ortak bir havuz',
+'upload-disallowed-here' => 'Bu dosyanın üzerine yazamazsınız.',
 
 # File reversion
 'filerevert' => '$1 dosyasını eski haline döndür',
@@ -2118,6 +2172,8 @@ Dosya açıklamasını düzenlemek isterseniz, [$2 dosya açıklama sayfası] bu
 
 # Random page in category
 'randomincategory' => 'Kategoriye göre rastgele sayfa',
+'randomincategory-invalidcategory' => '"$1" geçerli bir kategori adı değil.',
+'randomincategory-nopages' => '[[:Category:$1|$1]] kategorisinde hiç sayfa yok.',
 'randomincategory-selectcategory' => 'Rastgele sayfa alınacak kategori: $1 $2.',
 'randomincategory-selectcategory-submit' => 'Getir',
 
@@ -2147,8 +2203,12 @@ Dosya açıklamasını düzenlemek isterseniz, [$2 dosya açıklama sayfası] bu
 'statistics-mostpopular' => 'En çok ziyaret edilen sayfalar',
 
 'pageswithprop' => 'Bir sayfa özelliğine sahip sayfalar',
+'pageswithprop-legend' => 'Bir sayfa özelliğine sahip sayfalar',
 'pageswithprop-text' => 'Bu sayfa belirli bir sayfa özelliğini kullanan sayfaları listeler.',
+'pageswithprop-prop' => 'Özellik adı:',
 'pageswithprop-submit' => 'Git',
+'pageswithprop-prophidden-long' => 'uzun metin özellik değeri gizlendi ($1)',
+'pageswithprop-prophidden-binary' => 'ikili özellik değeri gizlendi ($1)',
 
 'doubleredirects' => 'Çift yönlendirmeler',
 'doubleredirectstext' => 'Bu sayfa diğer yönlendirme sayfalarına yönlendirme yapan sayfaları listeler.
@@ -2194,6 +2254,8 @@ Her satırın içerdiği bağlantılar; birinci ve ikinci yönlendirme, ayrıca
 'wantedpages' => 'İstenen sayfalar',
 'wantedpages-badtitle' => 'Sonuç kümesinde geçersiz başlık: $1',
 'wantedfiles' => 'İstenen dosyalar',
+'wantedfiletext-cat' => 'Aşağıdaki dosyalar kullanılıyor ama mevcut değil. Yabancı depolardaki dosyalar, varolsalar bile gösterilebilir. Böyle yanlış pozitiflerin <del>üstü çizilecektir</del>. Ek olarak, varolmayan dosyaları gömen sayfalar [[:$1]] sayfasında listelenmiştir.',
+'wantedfiletext-nocat' => 'Aşağıdaki dosyalar kullanılıyor ama mevcut değil. Yabancı depolardaki dosyalar, varolsalar bile gösterilebilir. Böyle yanlış pozitiflerin <del>üstü çizilecektir</del>.',
 'wantedtemplates' => 'İstenen şablonlar',
 'mostlinked' => 'Kendisine en fazla bağlantı verilmiş sayfalar',
 'mostlinkedcategories' => 'En çok maddeye sahip kategoriler',
@@ -2203,6 +2265,8 @@ Her satırın içerdiği bağlantılar; birinci ve ikinci yönlendirme, ayrıca
 'mostinterwikis' => "En çok interwiki'ye sahip sayfalar",
 'mostrevisions' => 'En çok değişikliğe uğramış sayfalar',
 'prefixindex' => 'Önek ile tüm sayfalar',
+'prefixindex-namespace' => 'Önek ile tüm sayfalar ($1 ad alanında)',
+'prefixindex-strip' => 'Listede öneki kırp',
 'shortpages' => 'Kısa sayfalar',
 'longpages' => 'Uzun sayfalar',
 'deadendpages' => 'Başka sayfalara bağlantısı olmayan sayfalar',
@@ -2218,6 +2282,7 @@ Her satırın içerdiği bağlantılar; birinci ve ikinci yönlendirme, ayrıca
 'listusers' => 'Kullanıcı listesi',
 'listusers-editsonly' => 'Sadece değişiklik yapan kullanıcıları göster',
 'listusers-creationsort' => 'Oluşturma tarihine göre sırala',
+'listusers-desc' => 'Azalan sırada sırala',
 'usereditcount' => '$1 {{PLURAL:$1|değişiklik|değişiklik}}',
 'usercreated' => "$1 tarihinde $2'de {{GENDER:$3|oluşturuldu}}.",
 'newpages' => 'Yeni sayfalar',
@@ -2253,6 +2318,7 @@ Lütfen unutmayın ki, diğer web siteleri bir dosyaya doğrudan bir URL ile ba
 Günlük tipini, kullanıcı adını (büyük-küçük harf duyarlı), ya da etkilenen sayfayı (yine büyük-küçük harf duyarlı) seçerek görünümü daraltabilirsiniz.',
 'logempty' => 'Kayıtlarda eşleşen bilgi yok.',
 'log-title-wildcard' => 'Bu metinle başlayan başlıklar ara',
+'showhideselectedlogentries' => 'Seçili günlük girdilerinin görünürlüğünü değiştir',
 
 # Special:AllPages
 'allpages' => 'Tüm sayfalar',
@@ -2273,6 +2339,8 @@ Günlük tipini, kullanıcı adını (büyük-küçük harf duyarlı), ya da etk
 'allpages-hide-redirects' => 'Yönlendirmeleri gizle',
 
 # SpecialCachedPage
+'cachedspecial-viewing-cached-ttl' => 'Bu sayfanın önbelleğe alınan bir sürümünü görüntülüyorsunuz, $1 eski olabilir.',
+'cachedspecial-viewing-cached-ts' => 'Bu sayfanın önbelleğe alınan bir sürümünü görüntülüyorsunuz, tam olarak güncel olmayabilir.',
 'cachedspecial-refresh-now' => 'En son görünüm.',
 
 # Special:Categories
@@ -2393,7 +2461,7 @@ Bundan sonra, bu sayfaya ve ilgili tartışma sayfasına yapılacak değişiklik
 'notvisiblerev' => 'Revizyon silinmiş',
 'watchlist-details' => 'Tartışma sayfaları hariç {{PLURAL:$1|$1 sayfa|$1 sayfa}} izleme listenizdedir.',
 'wlheader-enotif' => 'E-posta bildirimi etkin.',
-'wlheader-showupdated' => "Son ziyaretinizden sonraki sayfa değişiklikleri '''kalın yazıyla''' gösterilmiştir.",
+'wlheader-showupdated' => "Sayfaları son ziyaretinizden beri değişen sayfalar '''kalın''' gösterilmiştir.",
 'watchmethod-recent' => 'izlediğiniz sayfalarda yapılan son değişiklikler kontrol ediliyor',
 'watchmethod-list' => 'izlediğiniz sayfalarda yapılan son değişiklikler kontrol ediliyor',
 'watchlistcontains' => 'İzleme listenizde $1 tane {{PLURAL:$1|sayfa|sayfa}} var.',
@@ -2433,7 +2501,7 @@ Editörün iletişim bilgileri:
 e-posta: $PAGEEDITOR_EMAIL
 viki: $PAGEEDITOR_WIKI
 
-Bahsi geçen sayfayı ziyaret edinceye kadar sayfayla ilgili başka bildirim gönderilmeyecektir. Ayrıca izleme listenizdeki tüm sayfaların bildirim durumlarını sıfırlayabilirsiniz.
+Bahsi geçen sayfayı oturum açarak ziyaret edinceye kadar sayfayla ilgili başka bildirim gönderilmeyecektir. Ayrıca izleme listenizdeki tüm sayfaların bildirim durumlarını sıfırlayabilirsiniz.
 
 {{SITENAME}} bildirim sistemi
 
@@ -2475,10 +2543,12 @@ Yakın zamanda silinenleri görmek için: $2.',
 'deletecomment' => 'Neden:',
 'deleteotherreason' => 'Diğer/ilave neden:',
 'deletereasonotherlist' => 'Diğer nedenler',
-'deletereason-dropdown' => '*Genel silme gerekçeleri
-** Sayfayı oluşturan kullanıcının isteği
+'deletereason-dropdown' => '* Yaygın silme gerekçeleri
+** İstenmeyen değişiklik (spam)
+** Vandalizm
 ** Telif hakkı ihlali
-** Vandalizm',
+** Yazar talebi
+** Bozuk yönlendirme',
 'delete-edit-reasonlist' => 'Silme nedenlerini değiştir',
 'delete-toobig' => 'Bu sayfa, $1 {{PLURAL:$1|tane değişiklik|tane değişiklik}} ile çok uzun bir geçmişe sahiptir.
 Böyle sayfaların silinmesi, {{SITENAME}} sitesini bozmamak için sınırlanmaktadır.',
@@ -2491,6 +2561,7 @@ dikkatle devam edin.',
 'rollback_short' => 'geri al',
 'rollbacklink' => 'geri döndür',
 'rollbacklinkcount' => '$1 {{PLURAL:$1|değişikliği|değişikliği}} geri döndür',
+'rollbacklinkcount-morethan' => '$1 {{PLURAL:$1|değişiklikten|değişiklikten}} fazla geri döndür',
 'rollbackfailed' => 'geri alma işlemi başarısız',
 'cantrollback' => 'Sayfaya son katkıda bulunan kullanıcı, sayfaya katkıda bulunmuş tek kişi olduğu için, değişiklikler geri alınamıyor.',
 'alreadyrolled' => '[[User:$2|$2]] ([[User talk:$2|Talk]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) tarafından [[:$1]] sayfasında yapılmış son değişiklik geriye alınamıyor;
@@ -2499,7 +2570,7 @@ başka biri sayfada değişiklik yaptı ya da sayfayı geriye aldı.
 Son değişikliği yapan: [[User:$3|$3]] ([[User talk:$3|Talk]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Değişiklik özeti: \"''\$1''\" idi.",
 'revertpage' => '[[Special:Contributions/$2|$2]] [[User talk:$2|mesaj]] tarafından yapılan değişiklikler geri alınarak, [[User:$1|$1]] tarafından değiştirilmiş önceki sürüm geri getirildi.',
-'revertpage-nouser' => '(kullanıcı adı çıkarılmış) tarafından yapılan değişiklikler [[User:$1|$1]] tarafından yapılan son revizyona geri alındı',
+'revertpage-nouser' => 'Gizli bir kullanıcı tarafından yapılan değişiklikler geri alınarak {{GENDER:$1|[[User:$1|$1]]}} tarafından yapılan son revizyon geri getirildi',
 'rollback-success' => '$1 tarafından yapılan değişiklikler geri alınarak;
 $2 tarafından değiştirilmiş önceki sürüme geri dönüldü.',
 
@@ -2520,7 +2591,10 @@ Lütfen "geri" gidin ve geldiğiniz sayfayı yeniden yükleyin, sonra tekrar den
 'protect-title' => '"$1" için bir koruma seviyesi seçiniz',
 'protect-title-notallowed' => '"$1" için koruma seviyesini görüntüleyin',
 'prot_1movedto2' => '[[$1]] sayfasının yeni adı: [[$2]]',
+'protect-badnamespace-title' => 'Korumaya alınamayan ad alanı',
 'protect-badnamespace-text' => 'Bu ad alanındaki sayfalar korunamaz.',
+'protect-norestrictiontypes-text' => 'Bu sayfa mevcut kısıtlama türü bulunmadığı için korumaya alınamıyor.',
+'protect-norestrictiontypes-title' => 'Korumaya alınamayan sayfa',
 'protect-legend' => 'Korumayı onayla',
 'protectcomment' => 'Sebep:',
 'protectexpiry' => 'Bitiş tarihi:',
@@ -2537,7 +2611,7 @@ Lütfen "geri" gidin ve geldiğiniz sayfayı yeniden yükleyin, sonra tekrar den
 'protect-cascadeon' => 'Bu sayfa, kademeli koruma aktif hale getirilmiş aşağıdaki {{PLURAL:$1|$1 sayfada|$1 sayfada}} kullanıldığı için şu an koruma altındadır.
 Bu sayfanın koruma seviyesini değiştirebilirsiniz; ancak bu kademeli korumaya etki etmeyecektir.',
 'protect-default' => 'Tüm kullanıcılara izin ver',
-'protect-fallback' => '"$1" izni gerektir',
+'protect-fallback' => 'Sadece "$1" yetkisine sahip kullanıcılara izin ver',
 'protect-level-autoconfirmed' => 'Yalnızca otomatik onaylanmış kullanıcılara izin verilir',
 'protect-level-sysop' => 'Yalnızca hizmetlilere izin verilir',
 'protect-summary-cascade' => 'kademeli',
@@ -2583,7 +2657,8 @@ Bu sayfanın koruma seviyesini değiştirebilirsiniz; ancak bu kademeli korumaya
 'undeletepagetext' => 'Aşağıdaki {{PLURAL:$1|sayfa|$1 sayfa}} silinmiştir ama hala arşivdedir ve geri getirilebilir.
 Arşiv düzenli olarak temizlenebilir.',
 'undelete-fieldset-title' => 'Revizyonları geri yükle',
-'undeleteextrahelp' => "Sayfalarla birlikte geçmişi geri getirmek için onay kutularına dokunmadan '''Geri getir!''' tuşuna tıklayın. Sayfanın geçmişini ayrı ayrı getirmek için geri getirmek istediğiniz değişikliklerin onay kutularını seçip '''Geri getir!''' tuşuna tıklayın. Seçilen onay kutularını ve neden alanını sıfırlamak için '''Vazgeç''' tuşuna tıklayın.",
+'undeleteextrahelp' => "Sayfanın tüm geçmişini geri getirmek için onay kutularını boş bırakarak '''''{{int:undeletebtn}}''''' tuşuna tıklayın.
+Sayfanın geçmişini ayrı ayrı getirmek için geri getirmek istediğiniz değişikliklerin onay kutularını seçip '''''{{int:undeletebtn}}''''' tuşuna tıklayın.",
 'undeleterevisions' => '$1 {{PLURAL:$1|revizyon|revizyon}} arşivlendi',
 'undeletehistory' => 'Eğer sayfayı geri getirirseniz, tüm revizyonlar geçmişe geri getirilecektir.
 Silindikten sonra aynı isimle yeni bir sayfa oluşturulmuşsa, geri gelen revizyonlar varolan sayfanın geçmişinde görünecektir.',
@@ -2630,14 +2705,16 @@ $1',
 # Namespace form on various pages
 'namespace' => 'Ad alanı:',
 'invert' => 'Seçili haricindekileri göster',
+'tooltip-invert' => 'Seçili ad alanındaki sayfalara olan değişiklikleri gizlemek için bu kutucuğu işaretleyin (ve ilgili ad alanı, eğer seçiliyse)',
 'namespace_association' => 'İlişkili ad alanı',
+'tooltip-namespace_association' => 'Seçili ad alanıyla ilgili tartışma ya da madde ad alanlarını da eklemek için bu kutucuğu işaretleyin',
 'blanknamespace' => '(Ana)',
 
 # Contributions
 'contributions' => '{{GENDER:$1|Kullanıcı}} katkıları',
 'contributions-title' => '$1 için kullanıcı katkıları',
 'mycontris' => 'Katkılar',
-'contribsub2' => '$1 ($2)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) tarafından',
 'nocontribs' => 'Bu kriterlere uyan değişiklik bulunamadı',
 'uctop' => '(son)',
 'month' => 'Ay:',
@@ -2736,6 +2813,7 @@ Engellemeleri gözden geçirmek için [[Special:BlockList|engel listesine]] bak
 'blocklist-userblocks' => 'Hesap engellemelerini gizle',
 'blocklist-tempblocks' => 'Geçici engellemeleri gizle',
 'blocklist-addressblocks' => 'Tek IP engellemelerini gizle',
+'blocklist-rangeblocks' => 'Dizi bloklarını gizle',
 'blocklist-timestamp' => 'Tarih damgası',
 'blocklist-target' => 'Hedef',
 'blocklist-expiry' => 'Bitiş tarihi',
@@ -2796,6 +2874,7 @@ Lütfen İnternet sevis sağlayınız ile ya da teknik destek ile irtibat kurun
 'sorbsreason' => "IP adresiniz, {{SITENAME}} sitesi tarafından kullanılan DNSBL'de açık proxy olarak listelenmiş.",
 'sorbs_create_account_reason' => "IP adresiniz {{SITENAME}} sitesi tarafından kullanılan DNSBL'de açık proxy olarak listelenmiş.
 Hesap oluşturamazsınız",
+'xffblockreason' => 'Sizin ya da kullandığınız vekil sunucuya ait bir IP adresi X-Forwarded-For başlığında bulunuyor, ve engellendi. Orjinal engelleme nedeni: $1',
 'cant-block-while-blocked' => 'Siz engelliyken başka kullanıcıları engelleyemezsiniz.',
 'cant-see-hidden-user' => 'Engellemek istediğiniz kullanıcı zaten engellenmiş ve gizlenmiş. Kullanıcıgizle yetkiniz olmadığı için, kullanıcının engellenmesini göremez ya da değiştiremezsiniz.',
 'ipbblocked' => 'Diğer kullanıcıları engelleyemez ya da engellemesini kaldıramazsınız, çünkü kendiniz engellenmişsiz',
@@ -2826,12 +2905,16 @@ Bu, veritabanını kilitleyip açabilmek için, web sunucusu tarafından yazıla
 # Move page
 'move-page' => '$1 taşınıyor',
 'move-page-legend' => 'İsim değişikliği',
-'movepagetext' => "Aşağıdaki form kullanılarak sayfanın adı değiştirilir. Beraberinde tüm geçmiş kayıtları da yeni isme aktarılır. Eski isim yeni isme yönlendirme hâline dönüşür. Otomatik olarak eski başlığa yönlendirmeleri güncelleyebilirsiniz. Bu işlemi otomatik yapmak istemezseniz tüm [[Special:DoubleRedirects|çift]] veya [[Special:BrokenRedirects|geçersiz]] yönlendirmeleri kendiniz düzeltmeniz gerekecek. Yapacağınız bu değişikllikle tüm bağlantıların olması gerektiği gibi çalıştığından sizin sorumlu olduğunuzu unutmayınız.
+'movepagetext' => "Aşağıdaki formu kullanmak sayfanın adını değiştirir, tüm geçmiş kayıtlarını da yeni isme aktarır.
+Eski başlık yeni başlığa yönlendirme hâline dönüşür. Otomatik olarak eski başlığa yönlendirmeleri güncelleyebilirsiniz.
+Eğer istemezseniz, tüm [[Special:DoubleRedirects|çift]] veya [[Special:BrokenRedirects|geçersiz]] yönlendirmeleri kontrol ettiğinizden emin olun.
+Tüm bağlantıların olması gerektiği gibi çalıştığından sizin sorumlu olduğunuzu unutmayınız.
 
-Eğer yeni isimde bir madde zaten varsa isim değişikliği '''yapılmayacaktır'''. Ayrıca, isim değişikliğinden pişman olursanız değişikliği geri alabilir ve başka hiçbir sayfaya da dokunmamış olursunuz.
+Eğer yeni isimde bir madde zaten varsa isim değişikliği '''yapılmayacaktır''', sonraki bir yönlendirme olup geçmiş değişiklik geçmişi olmadığı müddetçe.
+Bu şu anlama gelir ki, eğer bir hata yaparsanız sayfayı değiştirildiği isme geri isimlendirebilirsiniz, ve mevcut bir sayfanın üstüne yazmazsınız.
 
 '''UYARI!'''
-Bu değişim popüler bir sayfa için beklenmeyen sonuçlar doğurabilir; lütfen değişikliği yapmadan önce olabilecekleri göz önünde bulundurun.",
+Bu değişim popüler bir sayfa için etkili ve beklenmeyen sonuçlar doğurabilir; lütfen devam etmeden önce olabilecekleri anladığınızdan emin olun.",
 'movepagetext-noredirectfixer' => "Aşağıdaki formu doldurmak bir sayfayı yeniden adlandırır, tüm geçmişini yeni ada taşır.
 Eski başlık yeni başlığa bir yönlendirme sayfası olur.
 [[Special:DoubleRedirects|Çift]] ya da [[Special:BrokenRedirects|nozuk yönlendirmeler]] sayfalarını kontrol edin.
@@ -2896,6 +2979,7 @@ Lütfen başka bir isim deneyiniz.',
 'immobile-target-namespace-iw' => 'Vikilerarası bağlantı, sayfa taşıması için geçerli bir hedef değil.',
 'immobile-source-page' => 'Bu sayfanın adı değiştirilemez.',
 'immobile-target-page' => 'Bu hedef başlığına taşınamaz.',
+'bad-target-model' => 'İstenen hedef farklı bir içerik modeli kullanıyor. $1 modelinden $2 modeline çevrilemiyor.',
 'imagenocrossnamespace' => 'Dosya, dosyalar için olmayan ad alanına taşınamaz',
 'nonfile-cannot-move-to-file' => 'Dosya olmayanlar, dosya ad alanına taşınamaz',
 'imagetypemismatch' => 'Yeni dosya eklentisi tipiyle eşleşmiyor',
@@ -2923,6 +3007,7 @@ Sonuncu durumda, bir link de kullanabilirsiniz, ör: "[[{{MediaWiki:Mainpage}}]]
 'exportcuronly' => 'Geçmiş sürümleri almadan sadece son sürümü al',
 'exportnohistory' => "----
 '''Not:''' Sayfaların tüm geçmişini bu formla dışa aktarmak, performans nedenlerinden ötürü devre dışı bırakılmıştır.",
+'exportlistauthors' => 'Her sayfa için katkıda bulunanların tam listesi içer',
 'export-submit' => 'Aktar',
 'export-addcattext' => 'Aşağıdaki kategoriden maddeler ekle:',
 'export-addcat' => 'Ekle',
@@ -2938,7 +3023,7 @@ Sonuncu durumda, bir link de kullanabilirsiniz, ör: "[[{{MediaWiki:Mainpage}}]]
 'allmessagesdefault' => 'Varsayılan mesaj metni',
 'allmessagescurrent' => 'Kullanımdaki metin',
 'allmessagestext' => 'Bu liste  MediaWiki ad alanında mevcut olan sistem mesajlarının listesidir.
-Genel MediaWiki yerelleştirmesine katkıda bulunmak isterseniz, lütfen [//www.mediawiki.org/wiki/Localisation MediaWiki Yerelleştirmesi] ve [//translatewiki.net translatewiki.net] sayfalarını ziyaret edin.',
+Genel MediaWiki yerelleştirmesine katkıda bulunmak isterseniz, lütfen [https://www.mediawiki.org/wiki/Localisation MediaWiki Yerelleştirmesi] ve [//translatewiki.net translatewiki.net] sayfalarını ziyaret edin.',
 'allmessagesnotsupportedDB' => "'''\$wgUseDatabaseMessages''' kapalı olduğu için '''{{ns:special}}:Allmessages''' kullanıma açık değil.",
 'allmessages-filter-legend' => 'Filtre',
 'allmessages-filter' => 'Özelleştirme durumuna göre filtrele:',
@@ -2953,8 +3038,12 @@ Genel MediaWiki yerelleştirmesine katkıda bulunmak isterseniz, lütfen [//www.
 'thumbnail-more' => 'Büyüt',
 'filemissing' => 'Dosya bulunmadı',
 'thumbnail_error' => 'Küçük resim oluşturmada hata: $1',
+'thumbnail_error_remote' => '$1 için hata mesajı:
+$2',
 'djvu_page_error' => 'DjVu sayfası kapsamdışı',
 'djvu_no_xml' => 'DjVu dosyası için XML alınamıyor',
+'thumbnail-temp-create' => 'Geçici küçük resim dosyası oluşturulamıyor',
+'thumbnail-dest-create' => 'Küçük resim hedefe kaydedilemiyor',
 'thumbnail_invalid_params' => 'Geçersiz küçük resim parametreleri',
 'thumbnail_dest_directory' => 'Hedef dizini oluşturulamıyor',
 'thumbnail_image-type' => 'Görüntü türü desteklenmiyor',
@@ -3003,6 +3092,15 @@ Geçici dosya kayıp.',
 'import-upload' => 'XML bilgileri yükle',
 'import-token-mismatch' => 'Oturum verisi kaybı. Lütfen yeniden deneyin.',
 'import-invalid-interwiki' => 'Belirtilen vikiden içe aktarım yapılamaz.',
+'import-error-edit' => '"$1" sayfası içe aktarılamadı çünkü sayfayı değiştirmeye yetkiniz yok.',
+'import-error-create' => '"$1" sayfası içe aktarılamadı çünkü sayfayı oluşturmaya yetkiniz yok.',
+'import-error-interwiki' => '"$1" sayfası içe aktarılamadı çünkü sayfanın adı dış bağlantı için ayrılmış (vikilerarası).',
+'import-error-special' => '"$1" sayfası içe aktarılamadı çünkü sayfalara izin vermeyen özel bir ad alanına ait.',
+'import-error-invalid' => '"$1" sayfası içe aktarılamadı çünkü sayfa adı geçersiz.',
+'import-error-unserialize' => '"$1" sayfasının $2 revizyonu serileştirilmesi geri alınamıyor. Revizyonun $4 olarak serileştirilmiş $3 içerik modelini kullandığı raporlandı.',
+'import-options-wrong' => 'Yanlış {{PLURAL:$2|seçenek|seçenek}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'Verilen kök sayfa geçersiz bir başlık.',
+'import-rootpage-nosubpage' => 'Kök sayfanın "$1" ad alanı alt sayfalara izin vermiyor.',
 
 # Import log
 'importlogpage' => 'Aktarım günlüğü',
@@ -3015,6 +3113,10 @@ Geçici dosya kayıp.',
 # JavaScriptTest
 'javascripttest' => 'JavaScript denemesi',
 'javascripttest-title' => '$1 testleri çalışıyor',
+'javascripttest-pagetext-noframework' => 'Bu sayfa JavaScript testleri çalıştırmak için ayrılmıştır.',
+'javascripttest-pagetext-unknownframework' => 'Bilinmeyen test çerçevesi "$1".',
+'javascripttest-pagetext-frameworks' => 'Lütfen aşağıdaki test çerçevelerinden birini seçin: $1',
+'javascripttest-pagetext-skins' => 'Testleri koşmak için bir tema seçin:',
 'javascripttest-qunit-intro' => 'mediawiki.org üzerinden [$1 deneme belgelerine] bakınız.',
 'javascripttest-qunit-heading' => 'MediaWiki JavaScript QUnit deneme paketi',
 
@@ -3116,9 +3218,13 @@ Geçici dosya kayıp.',
 'spambot_username' => 'Medyaviki spam temizleme',
 'spam_reverting' => '$1 ile bağlantı içermeyen son sürüme geri dönülüyor',
 'spam_blanking' => 'Tüm revizyonlar $1 sayfasına bağlantı içeriyor, boşaltılıyor',
+'spam_deleting' => 'Tüm revizyonlar $1 sayfasına bağlantı içeriyor, siliniyor',
+'simpleantispam-label' => "Anti-spam denetimi.
+Bunu '''doldurMAyın'''!",
 
 # Info page
 'pageinfo-title' => 'Bilgi için "$1"',
+'pageinfo-not-current' => 'Üzgünüz, eski sürümler için bu bilgileri sağlamamız mümkün değildir.',
 'pageinfo-header-basic' => 'Temel bilgiler',
 'pageinfo-header-edits' => 'Düzenleme geçmişi',
 'pageinfo-header-restrictions' => 'Sayfa koruması',
@@ -3128,14 +3234,17 @@ Geçici dosya kayıp.',
 'pageinfo-length' => 'Sayfa uzunluğu (bayt cinsinden)',
 'pageinfo-article-id' => 'Sayfa ID',
 'pageinfo-language' => 'Sayfa içeriğinin dili',
-'pageinfo-robot-policy' => 'Arama motoru durumu',
-'pageinfo-robot-index' => 'İndekslenebilir',
-'pageinfo-robot-noindex' => 'İndekslenemez',
+'pageinfo-content-model' => 'Sayfa içerik modeli',
+'pageinfo-robot-policy' => 'Robotlar tarafından endeksleniyor',
+'pageinfo-robot-index' => 'İzin verilmiş',
+'pageinfo-robot-noindex' => 'İzin verilmedi',
 'pageinfo-views' => 'Görüntülenme sayısı',
 'pageinfo-watchers' => 'Sayfanın izleyici sayısı',
-'pageinfo-redirects-name' => 'Bu sayfaya yönlendirmeler',
+'pageinfo-few-watchers' => '$1 {{PLURAL:$1|izleyiciden|izleyiciden}} az',
+'pageinfo-redirects-name' => 'Bu sayfaya yönlendirme sayısı',
 'pageinfo-redirects-value' => '$1',
 'pageinfo-subpages-name' => 'Bu sayfanın alt sayfaları',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|yönlendirme|yönlendirme}}; $3 {{PLURAL:$3|yönlendirme olmayan|non-yönlendirme olmayan}})',
 'pageinfo-firstuser' => 'Sayfa oluşturucu',
 'pageinfo-firsttime' => 'Sayfa oluşturulma tarihi',
 'pageinfo-lastuser' => 'En son düzenleyici',
@@ -3147,11 +3256,13 @@ Geçici dosya kayıp.',
 'pageinfo-magic-words' => 'Sihirli {{PLURAL:$1|kelimeler|kelimeler}} ($1)',
 'pageinfo-hidden-categories' => 'Gizli {{PLURAL:$1|kategori|kategoriler}} ($1)',
 'pageinfo-templates' => 'Görüntülenen {{PLURAL:$1|şablon|şablonlar}} ($1)',
+'pageinfo-transclusions' => 'Çapraz eklenen {{PLURAL:$1|sayfa|sayfalar}} ($1)',
 'pageinfo-toolboxlink' => 'Sayfa bilgisi',
 'pageinfo-redirectsto' => 'Yönlendirilen',
 'pageinfo-redirectsto-info' => 'bilgi',
 'pageinfo-contentpage' => 'Bir içerik sayfası sayılır',
 'pageinfo-contentpage-yes' => 'Evet',
+'pageinfo-protect-cascading' => 'korumalar buradan kademelendiriliyor',
 'pageinfo-protect-cascading-yes' => 'Evet',
 'pageinfo-protect-cascading-from' => 'Korumalar üzerinden geçiş',
 'pageinfo-category-info' => 'Kategori bilgileri',
@@ -3172,6 +3283,8 @@ Geçici dosya kayıp.',
 'markedaspatrollederror' => 'Kontrol edilmedi',
 'markedaspatrollederrortext' => 'Gözlenmiş olarak işaretlemek için bir revizyon belirtmelisiniz.',
 'markedaspatrollederror-noautopatrol' => 'Kendi değişikliklerinizi kontrol edilmiş olarak işaretleyemezsiniz.',
+'markedaspatrollednotify' => '$1 için bu değişiklik kontrol edildi olarak işaretlendi.',
+'markedaspatrollederrornotify' => 'Kontrol edildi olarak işaretleme başarısız oldu.',
 
 # Patrol log
 'patrol-log-page' => 'Kontrol kaydı',
@@ -3206,7 +3319,7 @@ Bunu çalıştırmak, sisteminizi tehlikeye atabilir.",
 'svg-long-desc' => 'SVG dosyası, sözde $1 × $2 piksel, dosya boyutu: $3',
 'svg-long-desc-animated' => 'Hareketli SVG dosyası, sözde $1 × $2 piksel, dosya boyutu: $3',
 'svg-long-error' => 'Geçersiz SVG dosyası: $1',
-'show-big-image' => 'Tam çözünürlük',
+'show-big-image' => 'Özgün dosya',
 'show-big-image-preview' => 'Ön izleme boyutu: $1.',
 'show-big-image-other' => 'Diğer {{PLURAL:$2|çözünürlük|çözünürlükleri}}: $1.',
 'show-big-image-size' => '$1 × $2 piksel',
@@ -3215,6 +3328,8 @@ Bunu çalıştırmak, sisteminizi tehlikeye atabilir.",
 'file-info-png-looped' => 'döngüye girdi',
 'file-info-png-repeat' => '$1 {{PLURAL:$1|defa|defa}} oynatıldı',
 'file-info-png-frames' => '$1 {{PLURAL:$1|frame|frames}}',
+'file-no-thumb-animation' => "'''Not: Teknik sınırlamalar nedeniyle, bu dosyanın küçük resimlerinde animasyon yoktur.'''",
+'file-no-thumb-animation-gif' => "'''Not: Teknik sınırlamalar nedeniyle, bu gibi yüksek çözünürlüklü GIF resimlerinin küçük resimlerinde animasyon yoktur.'''",
 
 # Special:NewFiles
 'newimages' => 'Yeni dosya galerisi',
@@ -3404,13 +3519,18 @@ Diğerleri varsayılan olarak gizlenecektir.
 'exif-gpsdifferential' => 'GPS differential correction',
 'exif-jpegfilecomment' => 'JPEG dosyası yorumu',
 'exif-keywords' => 'Anahtar kelimeler',
+'exif-worldregioncreated' => 'Resmin çekildiği dünya bölgesi',
 'exif-countrycreated' => 'Resmin alındığı ülke',
+'exif-countrycodecreated' => 'Resmin çekildiği ülke kodu',
+'exif-provinceorstatecreated' => 'Resmin çekildiği eyalet ya da il',
 'exif-citycreated' => 'Resmin alındığı şehir',
+'exif-sublocationcreated' => 'Resmin çekildiği şehrin alt bölgesi',
 'exif-worldregiondest' => 'Gösterilen bölge',
 'exif-countrydest' => 'Gösterilen ülke',
 'exif-countrycodedest' => 'Gösterilen ülke kodu',
 'exif-provinceorstatedest' => 'Gösterilen il ya da devlet/eyalet',
 'exif-citydest' => 'Gösterilen Şehir',
+'exif-sublocationdest' => 'Şehrin alt bölgesi gösteriliyor',
 'exif-objectname' => 'Kısa başlık',
 'exif-specialinstructions' => 'Özel talimatlar',
 'exif-headline' => 'Başlık',
@@ -3420,26 +3540,35 @@ Diğerleri varsayılan olarak gizlenecektir.
 'exif-urgency' => 'Aciliyet',
 'exif-fixtureidentifier' => 'Fikstür adı',
 'exif-locationdest' => 'Yerin konumu',
+'exif-locationdestcode' => 'Konumun kodu tanımlandı',
+'exif-objectcycle' => 'Ortamın planlandığı günün saati',
 'exif-contact' => 'İletişim bilgileri',
 'exif-writer' => 'Yazar',
 'exif-languagecode' => 'Dil',
 'exif-iimversion' => 'IIM sürümü',
 'exif-iimcategory' => 'Kategori',
+'exif-iimsupplementalcategory' => 'Tamamlayıcı kategoriler',
 'exif-datetimeexpires' => 'Bu tarihten sonra kullanmayın:',
+'exif-datetimereleased' => 'Tarihinde yayınlandı',
+'exif-originaltransmissionref' => 'Orijinal iletim konum kodu',
 'exif-identifier' => 'Tanımlayıcı',
 'exif-lens' => 'Kullanılan objektif',
 'exif-serialnumber' => 'Kameranın seri numarası',
 'exif-cameraownername' => 'Kameranın sahibi',
 'exif-label' => 'Etiket',
+'exif-datetimemetadata' => 'Üstveri son değişim tarihi',
 'exif-nickname' => 'Görüntünün resmî olmayan adı',
 'exif-rating' => 'Oylama (5 üzerinden)',
+'exif-rightscertificate' => 'Hak yönetimi sertifikası',
 'exif-copyrighted' => 'Telif hakkı durumu',
 'exif-copyrightowner' => 'Telif hakkı sahibi',
 'exif-usageterms' => 'Kullanım şartları',
 'exif-webstatement' => 'Çevrimiçi telif hakkı bildirimi',
+'exif-originaldocumentid' => 'Özgün belgenin benzersiz kimliği',
 'exif-licenseurl' => 'Telif hakkı lisansı için URL',
 'exif-morepermissionsurl' => 'Alternatif lisans bilgileri',
 'exif-attributionurl' => 'Bu çalışmayı yeniden kullanırken lütfen bağlantı verin',
+'exif-preferredattributionname' => 'Bu çalışmayı yeniden kullanırken, lütfen atıf verin',
 'exif-pngfilecomment' => 'PNG dosyası yorumu',
 'exif-disclaimer' => 'Sorumluluk reddi',
 'exif-contentwarning' => 'İçerik uyarısı',
@@ -3455,6 +3584,9 @@ Diğerleri varsayılan olarak gizlenecektir.
 
 # Exif attributes
 'exif-compression-1' => 'Sıkıştırılmamış',
+'exif-compression-2' => 'CCITT Grup 3 1-Boyutlu Değiştirilmiş Huffman koşu uzunluğu kodlaması',
+'exif-compression-3' => 'CCITT Grup 3 faks kodlaması',
+'exif-compression-4' => 'CCITT Grup 4 faks kodlaması',
 'exif-compression-6' => 'JPEG',
 
 'exif-copyrighted-true' => 'Telif hakkı',
@@ -3641,6 +3773,7 @@ Diğerleri varsayılan olarak gizlenecektir.
 'exif-gpsdirection-m' => 'Manyetik yönü',
 
 'exif-ycbcrpositioning-1' => 'Ortalanmış',
+'exif-ycbcrpositioning-2' => 'Eş-yerleştirilmiş',
 
 'exif-dc-contributor' => 'Katkıda bulunanlar',
 'exif-dc-coverage' => 'Medyanın konumsal ya da zamansal kapsamı',
@@ -3680,7 +3813,7 @@ Diğerleri varsayılan olarak gizlenecektir.
 
 # External editor support
 'edit-externally' => 'Dosyayı harici bir uygulamayla değiştirin.',
-'edit-externally-help' => '(Daha fazla bilgi için metadaki [//www.mediawiki.org/wiki/Manual:External_editors dış uygulama ayarları] (İngilizce) sayfasına bakabilirsiniz)',
+'edit-externally-help' => '(Daha fazla bilgi için metadaki [https://www.mediawiki.org/wiki/Manual:External_editors dış uygulama ayarları] (İngilizce) sayfasına bakabilirsiniz)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Hepsini göster',
@@ -3738,13 +3871,13 @@ iptal etmek için aşağıdaki bağlantıyı takip edin:
 $5
 
 Bu onay kodu $4 tarihine kadar geçerli olacak.',
-'confirmemail_body_set' => 'Birisi $1 IP adresiyle {{SITENAME}} sitesinde "$2" kullanıcı hesabının e-posta adresi olarak bu e-posta adresini belirtti.
+'confirmemail_body_set' => 'Birisi, muhtemelen siz, $1 IP adresiyle {{SITENAME}} sitesinde "$2" kullanıcı hesabının e-posta adresi olarak bu e-posta adresini belirtti.
 
-Eğer bu işlemi yapan sizseniz ve {{SITENAME}} sitesindeki e-posta işlevlerini tekrar aktif etmek istiyorsanız alttaki bağlantıyı tarayıcınızda açmanız gerekiyor:
+Bu hesabın gerçekten size ait olduğunu onaylamak ve {{SITENAME}} sitesindeki e-posta işlevlerini aktif etmek için alttaki bağlantıyı tarayıcınızda açmanız gerekiyor:
 
 $3
 
-Eğer bu işlemi yapan siz değilseniz ve böyle bir üyeliğiniz yoksa e-posta onay işlemini iptal etmek için alttaki bağlantıyı tarayıcınızda açmanız gerekiyor:
+Eğer bu hesap size ait değilse, e-posta adresi onayını iptal etmek için alttaki bağlantıyı takip edin:
 
 $5
 
@@ -3755,6 +3888,7 @@ Bu onay kodu $4 tarihine kadar geçerlidir.',
 # Scary transclusion
 'scarytranscludedisabled' => '[Vikilerarası çapraz ekleme devre dışı]',
 'scarytranscludefailed' => '[$1 için şablon alımı başarısız oldu]',
+'scarytranscludefailed-httpstatus' => '[$1 için şablon alımı başarısız oldu: HTTP $2]',
 'scarytranscludetoolong' => '[URL çok uzun]',
 
 # Delete conflict
@@ -3872,8 +4006,10 @@ Ayrıca [[Special:EditWatchlist|standart düzenleme sayfasını]] da kullanabili
 'version-hook-subscribedby' => 'Abone olan',
 'version-version' => '(Sürüm $1)',
 'version-license' => 'Lisans',
-'version-poweredby-credits' => "Bu wiki '''[//www.mediawiki.org/ MediaWiki]''' programı kullanılarak oluşturulmuştur, telif © 2001-$1 $2.",
+'version-poweredby-credits' => "Bu wiki '''[https://www.mediawiki.org/ MediaWiki]''' programı kullanılarak oluşturulmuştur, telif © 2001-$1 $2.",
 'version-poweredby-others' => 'diğerleri',
+'version-poweredby-translators' => 'translatewiki.net çevirmenleri',
+'version-credits-summary' => "Aşağıdaki kişileri [[Special:Version|MediaWiki]]'ye katkılarından dolayı takdir ediyoruz.",
 'version-license-info' => "MediaWiki özgür bir yazılımdır; MediaWiki'yi, Özgür Yazılım Vakfı tarafından yayımlanmış olan GNU Genel Kamu Lisansının 2. veya (seçeceğiniz) daha sonraki bir sürümünün koşulları altında yeniden dağıtabilir ve/veya değiştirebilirsiniz.
 
 MediaWiki yazılımı faydalı olacağı ümidiyle dağıtılmaktadır; ancak kastedilen SATILABİLİRLİK veya BELİRLİ BİR AMACA UYGUNLUK garantisi hariç HİÇBİR GARANTİSİ YOKTUR. Daha fazla ayrıntı için GNU Genel Kamu Lisansı'na bakınız.
@@ -3889,10 +4025,12 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 # Special:Redirect
 'redirect' => 'Dosya, kullanıcı veya sayfa ID yönlendirme',
 'redirect-legend' => 'Bir dosya veya sayfaya yönlendirme',
-'redirect-summary' => "Bu özel sayfa sizi bir dosya (dosya adı verilen), bir sayfa (bir revizyon ID'si verilen) veya bir kullanıcı sayfasının (sayısal kullanıcı kimliği verilen) adresine yönlendirir.",
+'redirect-summary' => "Bu özel sayfa sizi bir dosya (dosya adı verilen), bir sayfa (bir revizyon ID'si verilen) veya bir kullanıcı sayfasının (sayısal kullanıcı kimliği verilen) adresine yönlendirir. Kullanım: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], ya da  [[{{#Special:Redirect}}/user/101]].",
 'redirect-submit' => 'Git',
+'redirect-lookup' => 'Ara:',
 'redirect-value' => 'Değer:',
 'redirect-user' => 'Kullanıcı kimliği',
+'redirect-revision' => 'Sayfa revizyonu',
 'redirect-file' => 'Dosya adı',
 'redirect-not-exists' => 'Değer bulunamadı',
 
@@ -3909,10 +4047,9 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 
 # Special:SpecialPages
 'specialpages' => 'Özel sayfalar',
-'specialpages-note' => '----
-* Normal özel sayfalar.
-* <span class="mw-specialpagerestricted">Kısıtlı özel sayfalar.</span>
-* <span class="mw-specialpagecached">Önbelleğe alınan özel sayfalar (eskimiş olabilir)</span>',
+'specialpages-note-top' => 'Gösterge',
+'specialpages-note' => '* Normal özel sayfalar.
+* <span class="mw-specialpagerestricted">Kısıtlı özel sayfalar.</span>',
 'specialpages-group-maintenance' => 'Bakım raporları',
 'specialpages-group-other' => 'Diğer özel sayfalar',
 'specialpages-group-login' => 'Oturum aç / hesap edin',
@@ -3944,6 +4081,7 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'tags' => 'Geçerli değişiklik etiketleri',
 'tag-filter' => '[[Special:Tags|Etiket]] süzgeci:',
 'tag-filter-submit' => 'Süzgeç',
+'tag-list-wrapper' => '([[Special:Tags|{{PLURAL:$1|Etiket|Etiketler}}]]: $2)',
 'tags-title' => 'Etiketler',
 'tags-intro' => 'Bu sayfa, yazılımın bir değişikliği işaretleyebileceği etiketleri ve bunların anlamlarını listeler.',
 'tags-tag' => 'Etiket adı',
@@ -3973,6 +4111,7 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'dberr-problems' => 'Üzgünüz! Bu site teknik zorluklar yaşıyor.',
 'dberr-again' => 'Bir kaç dakika bekleyip tekrar yüklemeyi deneyin.',
 'dberr-info' => '(Veritabanı sunucusuyla irtibat kurulamıyor: $1)',
+'dberr-info-hidden' => '(Veritabanı sunucusuna bağlantı kurulamıyor)',
 'dberr-usegoogle' => 'Bu zaman zarfında Google ile aramayı deneyebilirsiniz.',
 'dberr-outofdate' => 'İçeriğimizin onların dizinlerinde güncel olmayabileceğini dikkate alın.',
 'dberr-cachederror' => 'Aşağıdaki istenen sayfanın önbellekteki bir kopyasıdır, ve güncel olmayabilir.',
@@ -3990,18 +4129,24 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'htmlform-selectorother-other' => 'Diğer',
 'htmlform-no' => 'Hayır',
 'htmlform-yes' => 'Evet',
+'htmlform-chosen-placeholder' => 'Bir seçenek seçin',
 
 # SQLite database support
 'sqlite-has-fts' => '$1 tam-metin arama desteği ile',
 'sqlite-no-fts' => '$1 tam-metin arama desteği olmaksızın',
 
 # New logging system
-'logentry-delete-delete' => '$1 $3 sayfasını sildi',
-'logentry-delete-restore' => '$1 $3 sayfasını geri getirdi',
-'logentry-delete-revision' => '$1 $3: $4 sayfasında {{PLURAL:$5|bir sürümün|$5 sürümün}} görünürlüğünü değiştirdi',
-'logentry-delete-revision-legacy' => '$1 $3 sayfasındaki sürümlerin görünürlüğünü değiştirdi',
-'logentry-suppress-revision' => '$1 $3: $4 sayfasında {{PLURAL:$5|bir sürümün|$5 sürümün}} görünürlüğünü gizlice değiştirdi',
-'logentry-suppress-revision-legacy' => '$1 $3 sayfasındaki sürümlerin görünürlüğünü değiştirdi',
+'logentry-delete-delete' => '$1 $3 sayfasını {{GENDER:$2|sildi}}',
+'logentry-delete-restore' => '$1 $3 sayfasını {{GENDER:$2|geri getirdi}}',
+'logentry-delete-event' => '$1, $3 sayfasında {{PLURAL:$5|bir günlük girdisinin |$5 günlük girdisinin}} görünürlüğünü {{GENDER:$2|değiştirdi}}: $4',
+'logentry-delete-revision' => '$1, $3 sayfasında {{PLURAL:$5|bir sürümün|$5 sürümün}} görünürlüğünü {{GENDER:$2|değiştirdi}}: $4',
+'logentry-delete-event-legacy' => '$1, $3 sayfasında günlük girdilerinin görünürlüğünü  {{GENDER:$2|değiştirdi}}',
+'logentry-delete-revision-legacy' => '$1 $3 sayfasındaki sürümlerin görünürlüğünü {{GENDER:$2|değiştirdi}}',
+'logentry-suppress-delete' => '$1, $3 sayfasını {{GENDER:$2|bastırdı}}',
+'logentry-suppress-event' => '$1, $3 sayfasında {{PLURAL:$5|bir günlük girdisinin |$5 günlük girdisinin}} görünürlüğünü gizlice {{GENDER:$2|değiştirdi}}: $4',
+'logentry-suppress-revision' => '$1, $3 sayfasında {{PLURAL:$5|bir sürümün|$5 sürümün}} görünürlüğünü gizlice {{GENDER:$2|değiştirdi}}: $4',
+'logentry-suppress-event-legacy' => '$1, $3 sayfasında günlük girdilerinin görünürlüğünü gizlice {{GENDER:$2|değiştirdi}}',
+'logentry-suppress-revision-legacy' => '$1, $3 sayfasındaki sürümlerin görünürlüğünü {{GENDER:$2|değiştirdi}}',
 'revdelete-content-hid' => 'Gizli içerik',
 'revdelete-summary-hid' => 'değişiklik özeti gizlenmiş',
 'revdelete-uname-hid' => 'kullanıcı adı gizli',
@@ -4010,17 +4155,24 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'revdelete-uname-unhid' => 'kullanıcı adı gösterildi',
 'revdelete-restricted' => 'hizmetliler için uygulanmış kısıtlamalar',
 'revdelete-unrestricted' => 'hizmetliler için kaldırılmış kısıtlamalar',
-'logentry-move-move' => '$1 $3 sayfasını $4 sayfasına taşıdı',
-'logentry-move-move-noredirect' => '$1 $3 sayfasını $4 sayfasına yönlendirme olmaksızın taşıdı',
-'logentry-move-move_redir' => '$1 $3 sayfasını $4 sayfasına yönlendirme üzerinden taşıdı',
-'logentry-patrol-patrol-auto' => '$1 $3 sayfasını $4 sürümü ile kontrol etti',
+'logentry-move-move' => '$1, $3 sayfasını $4 sayfasına {{GENDER:$2|taşıdı}}',
+'logentry-move-move-noredirect' => '$1, $3 sayfasını $4 sayfasına yönlendirme olmaksızın {{GENDER:$2|taşıdı}}',
+'logentry-move-move_redir' => '$1, $3 sayfasını $4 sayfasına yönlendirme üzerinden {{GENDER:$2|taşıdı}}',
+'logentry-move-move_redir-noredirect' => '$1, $3 sayfasını bir yönlendirme üzerine yönlendirme bırakmadan $4 olarak {{GENDER:$2|taşıdı}}',
+'logentry-patrol-patrol' => '$1, $3 sayfasının $4 revizyonunu kontrol edildi olarak {{GENDER:$2|işaretledi}}',
+'logentry-patrol-patrol-auto' => '$1, $3 sayfasının $4 sürümümü otomatik olarak {{GENDER:$2|kontrol etti}}',
 'logentry-newusers-newusers' => 'Kullanıcı hesabı $1 {{GENDER:$2|oluşturuldu}}',
 'logentry-newusers-create' => 'Kullanıcı hesabı $1 {{GENDER:$2|oluşturuldu}}',
 'logentry-newusers-create2' => '$3 kullanıcı hesabı $1 tarafından {{GENDER:$2|oluşturuldu}}',
+'logentry-newusers-byemail' => '$3 kullanıcı hesabı $1 tarafından {{GENDER:$2|oluşturuldu}} ve şifre e-posta ile gönderildi',
 'logentry-newusers-autocreate' => '$1 kullanıcı hesabı otomatik olarak {{GENDER:$2|oluşturuldu}}',
+'logentry-rights-rights' => '$1, $3 için grup üyeliğini $4 iken $5 olarak {{GENDER:$2|değiştirdi}}',
+'logentry-rights-rights-legacy' => '$1, $3 için grup üyeliğini {{GENDER:$2|değiştirdi}}',
+'logentry-rights-autopromote' => '$1, $4 iken $5 olarak otomatik {{GENDER:$2|terfi edildi}}',
 'rightsnone' => '(hiçbiri)',
 
 # Feedback
+'feedback-bugornote' => 'Eğer teknik bir problemi detaylarıyla açıklamaya hazırsanız lütfen [$1 bir hata raporlayın]. Diğer taraftan, aşağıdaki kolay formu kullanabilirsiniz. Yorumunuz, kullanıcı adınızla beraber "[$3 $2]" sayfasına eklenecektir.',
 'feedback-subject' => 'Konu:',
 'feedback-message' => 'Mesaj:',
 'feedback-cancel' => 'İptal',
@@ -4041,15 +4193,20 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 # API errors
 'api-error-badaccess-groups' => 'Bu wiki için dosya yüklemenize izin verilmiyor.',
 'api-error-badtoken' => 'İç hata: Bozuk anahtar.',
+'api-error-copyuploaddisabled' => 'URL ile yükleme bu sunucuda devre dışı bırakılmıştır.',
+'api-error-duplicate' => 'Sitede zaten aynı içerikte başka {{PLURAL:$1|bir [$2 dosya]|[$2 dosyalar]}} var.',
+'api-error-duplicate-archive' => 'Sitede zaten aynı içerikte başka {{PLURAL:$1|bir [$2 dosya]|[$2 dosyalar]}} vardı, ama {{PLURAL:$1|silindi|silindiler}}.',
+'api-error-duplicate-archive-popup-title' => 'Zaten silinmiş çift {{PLURAL:$1|sayfa|sayfalar}}.',
 'api-error-duplicate-popup-title' => 'Çift {{PLURAL:$1|dosya|dosya}}',
 'api-error-empty-file' => 'Gönderdiğiniz dosya boş.',
 'api-error-emptypage' => 'Yeni, boş bir sayfa oluşturmaya izin verilmez.',
 'api-error-fetchfileerror' => 'İç hata: Dosya alınırken bir hata oluştu.',
 'api-error-fileexists-forbidden' => '"$1" adıyla bir dosya zaten mevcut dolayısıyla üzerine yazamazsınız.',
+'api-error-fileexists-shared-forbidden' => '"$1" adında bir dosya ortak havuzda zaten var, ve üzerine yazılamaz.',
 'api-error-file-too-large' => 'Gönderdiğiniz dosya çok büyük.',
 'api-error-filename-tooshort' => 'Dosya adı çok kısa.',
 'api-error-filetype-banned' => 'Bu dosya biçimi yasaklanmıştır.',
-'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|izin verilen bir dosya türü değil|izin verilen bir dosya türü değil}}. İzin verilen {{PLURAL:$3|dosya türü|dosya türleri}} $2.',
+'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|izin verilen bir dosya türü değil|izin verilen dosya türleri değil}}. İzin verilen {{PLURAL:$3|dosya türü|dosya türleri}} $2.',
 'api-error-filetype-missing' => 'Dosya uzantısı eksik.',
 'api-error-hookaborted' => 'Yapmaya çalıştığınız değişiklik bir eklenti tarafından iptal edildi.',
 'api-error-http' => 'İç hata: sunucu ile bağlantı kurulamıyor.',
@@ -4065,6 +4222,7 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'api-error-ok-but-empty' => 'İç hata: Sunucu yanıt vermiyor.',
 'api-error-overwrite' => 'Varolan dosyanın üzerine yazmaya izin verilmiyor.',
 'api-error-stashfailed' => 'İç hata: Sunucu, geçici dosyaları kaybetti.',
+'api-error-publishfailed' => 'İç hata: Sunucu geçici dosyayı yayınlarken başarısız oldu.',
 'api-error-timeout' => 'Sunucu beklenen süre içinde yanıt vermedi.',
 'api-error-unclassified' => 'Bilinmeyen bir hata oluştu.',
 'api-error-unknown-code' => 'Bilinmeyen hata: "$1"',
@@ -4085,17 +4243,37 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'duration-centuries' => '$1 {{PLURAL:$1|yüzyıl|yüzyıl}}',
 'duration-millennia' => '$1 {{PLURAL:$1|bin yıl|bin yıl}}',
 
+# Image rotation
+'rotate-comment' => 'Resim saat yönünde $1 {{PLURAL:$1|derece|derece}} çevrildi',
+
 # Limit report
 'limitreport-title' => 'Ayrıştırıcı profil verileri:',
 'limitreport-cputime' => 'CPU süresi kullanımı',
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|saniye|saniye}}',
 'limitreport-walltime' => 'Gerçek süre kullanımı',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|saniye|saniye}}',
 'limitreport-ppvisitednodes' => 'Önişlemci düğümü ziyaret sayısı',
 'limitreport-ppgeneratednodes' => 'Önişlemcinin ürettiği düğüm sayısı',
 'limitreport-postexpandincludesize' => 'Gönderi genişliği boyutu dahil',
-'limitreport-postexpandincludesize-value' => '$1/$2 bayt',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bayt|bayt}}',
 'limitreport-templateargumentsize' => 'Şablon değişkeni boyutu',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bayt|bayt}}',
 'limitreport-expansiondepth' => 'En yüksek genişleme derinliği',
 'limitreport-expensivefunctioncount' => 'Daha fazla ayrıştırıcı işlev sayısı',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Şablonları genişlet',
+'expand_templates_intro' => 'Bu özel sayfa biraz metni alır ve içindeki tüm şablonları yinelemeli olarak genişletir.
+Ayrıca <code><nowiki>{{</nowiki>#language:…}}</code> gibi desteklenen derleyici fonksiyonlarını ve <code><nowiki>{{</nowiki>CURRENTDAY}}</code> gibi değişkenleri de genişletir.
+Aslında, çift ayraçlı hemen hemen her şeyi genişletir.',
+'expand_templates_title' => 'Durum başlığı, ör {{FULLPAGENAME}} için.:',
+'expand_templates_input' => 'Giriş metni:',
+'expand_templates_output' => 'Sonuç',
+'expand_templates_xml_output' => 'XML üretim',
+'expand_templates_ok' => 'Tamam',
+'expand_templates_remove_comments' => 'Yorumları sil',
+'expand_templates_remove_nowiki' => 'Sonuçlarda <nowiki> etiketlerini bastır',
+'expand_templates_generate_xml' => 'XML derleyici ağacını göster',
+'expand_templates_preview' => 'Önizleme',
+
 );
index 5dd3011..1430a55 100644 (file)
@@ -180,8 +180,6 @@ $messages = array(
 'ok' => 'Tamam',
 'retrievedfrom' => 'men "$1"',
 'youhavenewmessages' => 'Kıtlux $1 ($2) .',
-'newmessageslink' => 'Ṫebe ḥaṭe',
-'newmessagesdifflink' => 'Degoşo ḥaroyo',
 'youhavenewmessagesmulti' => 'Kitlux Ṫebe ḥaṭe b$1',
 'editsection' => 'mşaḥlaf',
 'editold' => 'mşaḥlaf',
@@ -804,7 +802,7 @@ Others will be hidden by default.
 
 # External editor support
 'edit-externally' => 'Edit this file using an external application',
-'edit-externally-help' => '(See the [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)',
+'edit-externally-help' => '(See the [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kulle',
index a468b68..a8e6c4e 100644 (file)
@@ -244,8 +244,6 @@ See [[Special:Version|version page]].',
 'ok' => 'Hiswona',
 'retrievedfrom' => 'ku suka e "$1"',
 'youhavenewmessages' => 'U na $1 ($2).',
-'newmessageslink' => 'Marungula mantswa',
-'newmessagesdifflink' => 'last change',
 'youhavenewmessagesmulti' => 'Una marungula mantswa hi $1',
 'editsection' => 'Lulamisa',
 'editold' => 'Lulamisa',
@@ -877,7 +875,7 @@ Lebyi n'wana vuxokoxoko bya finiso byitumbetiwile.
 
 # External editor support
 'edit-externally' => 'Lulamisa fayili leyi utirhisa xilulamisi xale handle ka wiki leyi',
-'edit-externally-help' => '(Vona [//www.mediawiki.org/wiki/Manual:External_editors swiletelo swo sungurisa] leswaku ukuma vuxokoxoko lebyi engetelekeke)',
+'edit-externally-help' => '(Vona [https://www.mediawiki.org/wiki/Manual:External_editors swiletelo swo sungurisa] leswaku ukuma vuxokoxoko lebyi engetelekeke)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Hinkwawo',
@@ -908,4 +906,8 @@ Lebyi n'wana vuxokoxoko bya finiso byitumbetiwile.
 # Special:Tags
 'tag-filter' => 'Xihluti xa [[Special:Tags|Xi angi]]:',
 
+# Special:ExpandTemplates
+'expand_templates_ok' => 'Hiswona',
+'expand_templates_preview' => 'Ringanisa',
+
 );
index f25aebf..e8f53f2 100644 (file)
@@ -348,8 +348,6 @@ $messages = array(
 'noindex-category' => 'Индексланмаган битләр',
 'broken-file-category' => 'Файлларга эшләми торган сылтамалар булган битләр',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Тасвирлама',
 'article' => 'Мәкалә',
 'newwindow' => '(яңа тәрәзәдә ачыла)',
@@ -485,8 +483,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Чыганагы — "$1"',
 'youhavenewmessages' => 'Сездә $1 бар ($2).',
-'newmessageslink' => 'яңа хәбәрләр',
-'newmessagesdifflink' => 'бәхәс битегезнең соңгы үзгәртүе',
 'youhavenewmessagesfromusers' => 'Сезгә {{PLURAL:$3|$3 кулланучыдан}} $1 килде ($2).',
 'youhavenewmessagesmanyusers' => 'Сез бик күп кулланучыдан $1 алдыгыз ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|яңа хәбәр}}',
@@ -1191,8 +1187,6 @@ $1",
 'preferences' => 'Көйләнмәләр',
 'mypreferences' => 'Көйләнмәләр',
 'prefs-edits' => 'Үзгәртүләр исәбе:',
-'prefsnologin' => 'Кермәгәнсез',
-'prefsnologintext' => 'Кулланучы көйләнмәләрене үзгәртү өчен, сез <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} керергә]</span> тиешсез.',
 'changepassword' => 'Серсүзне үзгәртү',
 'prefs-skin' => 'Күренеш',
 'skin-preview' => 'Алдан карау',
@@ -1377,6 +1371,7 @@ $1",
 'recentchanges-label-minor' => 'Бу кече үзгәртү',
 'recentchanges-label-bot' => 'Бу үзгәртү бот белән эшләнгән иде',
 'recentchanges-label-unpatrolled' => 'Үзгәртүне әлегә тикшермәгәннәр',
+'recentchanges-legend-newpage' => '$1 — яңа бит',
 'rcnote' => 'Аста $4 $5 вакытынна соңгы {{PLURAL:$2|1|$2}} көн эчендә булган соңгы {{PLURAL:$1|1|$1}} үзгәртмә күрсәтелә:',
 'rcnotefrom' => "Астарак '''$2''' башлап ('''$1''' кадәр) үзгәртүләр күрсәтелгән.",
 'rclistfrom' => '$1 башлап яңа үзгәртүләрне күрсәт',
@@ -2052,7 +2047,7 @@ $1',
 'allmessagesname' => 'Исем',
 'allmessagesdefault' => 'Баштан ук куелган текс',
 'allmessagestext' => 'Бу исемлек MediaWiki исемнәр мәйданында булган система хәбәрләренең исемлеге.
-Гомуми MediaWiki локализациясендә катнашырга теләсәгез, зинһар [//www.mediawiki.org/wiki/Localisation MediaWiki Локализациясе] һәм [//translatewiki.net translatewiki.net] сәхифәләрне кулланыгыз.',
+Гомуми MediaWiki локализациясендә катнашырга теләсәгез, зинһар [https://www.mediawiki.org/wiki/Localisation MediaWiki Локализациясе] һәм [//translatewiki.net translatewiki.net] сәхифәләрне кулланыгыз.',
 'allmessages-filter-legend' => 'Фильтр',
 'allmessages-filter-unmodified' => 'Үзгәртелмәгән',
 'allmessages-filter-all' => 'Барысы',
@@ -2378,7 +2373,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'Бу файлны тышкы кушымтаны кулланып үзгәртү',
-'edit-externally-help' => '(тулырак мәгълүмат өчен [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] битен карагыз)',
+'edit-externally-help' => '(тулырак мәгълүмат өчен [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] битен карагыз)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'барлык',
@@ -2454,8 +2449,7 @@ $1',
 
 # Special:SpecialPages
 'specialpages' => 'Махсус битләр',
-'specialpages-note' => '----
-* Гади махсус битләр.
+'specialpages-note' => '* Гади махсус битләр.
 * <strong class="mw-specialpagerestricted">Чикләнелгән махсус битләр.</strong>
 * <span class="mw-specialpagecached">Кешланган махсус битләр.</span>',
 'specialpages-group-maintenance' => 'Техник карау хисапнамәсе',
@@ -2571,4 +2565,8 @@ $1',
 'api-error-uploaddisabled' => 'Бу викидә файллар йөкләү мөмкинлеге сүндерелгән.',
 'api-error-verification-error' => 'Бәлки, бу файл бозылгандыр яки дөрес түгел киңәйтелмәгә ия.',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Үрнәкләрне ачу',
+'expand_templates_ok' => 'OK',
+
 );
index 6d17c36..69f9af2 100644 (file)
@@ -216,8 +216,6 @@ $messages = array(
 'index-category' => 'İndekslanğan bitlär',
 'noindex-category' => 'İndekslanmağan bitlär',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Taswirlama',
 'article' => 'Mäqälä',
 'newwindow' => '(yaña täräzädä açıla)',
@@ -349,8 +347,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Çığanağı — "$1"',
 'youhavenewmessages' => 'Sezdä $1 bar ($2).',
-'newmessageslink' => 'yaña xäbärlär',
-'newmessagesdifflink' => 'bäxäs bitegezneñ soñğı üzgärtüe',
 'youhavenewmessagesmulti' => 'Sezgä monda yaña xäbärlär bar: $1',
 'editsection' => 'üzgärtü',
 'editold' => 'üzgärtü',
@@ -925,8 +921,6 @@ Barlıq alannarda (bäxäs bitläre, ürnäklär, h.b.) ezläw öçen ''all'' s
 'preferences' => 'Köylänmälär',
 'mypreferences' => 'Köylänmälärem',
 'prefs-edits' => 'Üzgärtülär isäbe:',
-'prefsnologin' => 'Kermägänsez',
-'prefsnologintext' => 'Qullanuçı köylänmälärene üzgärtü öçen, sez <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kerergä]</span> tieşsez.',
 'changepassword' => 'Sersüzne üzgärtü',
 'prefs-skin' => 'Küreneş',
 'skin-preview' => 'Aldan qaraw',
@@ -1755,7 +1749,7 @@ Zinhar başqa isem saylağız.',
 'allmessagesdefault' => 'Töpcay yazma',
 'allmessagescurrent' => 'Eligi yazma',
 'allmessagestext' => 'Bu isemlek MediaWiki isemnär mäydanında bulğan sistema xäbärläreneñ isemlege.
-Ğomumi MediaWiki lokalizatsiäsendä qatnaşırğa teläsägez, zinhar [//www.mediawiki.org/wiki/Localisation MediaWiki Lokalizatsiäse] häm [//translatewiki.net translatewiki.net] säxifälärne qullanığız.',
+Ğomumi MediaWiki lokalizatsiäsendä qatnaşırğa teläsägez, zinhar [https://www.mediawiki.org/wiki/Localisation MediaWiki Lokalizatsiäse] häm [//translatewiki.net translatewiki.net] säxifälärne qullanığız.',
 'allmessages-filter-legend' => 'Filtr',
 'allmessages-filter-unmodified' => 'Üzgärtelmägän',
 'allmessages-filter-all' => 'Barısı',
@@ -2040,7 +2034,7 @@ Yulnıñ berençe sıltaması quyma öçen tıyılğan räsemgä sıltama bulır
 
 # External editor support
 'edit-externally' => 'Bu faylnı tışqı quşımtanı qullanıp üzgärtü',
-'edit-externally-help' => '(tulıraq mäğlümat öçen [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] biten qarağız)',
+'edit-externally-help' => '(tulıraq mäğlümat öçen [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] biten qarağız)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'barlıq',
@@ -2104,8 +2098,7 @@ Yulnıñ berençe sıltaması quyma öçen tıyılğan räsemgä sıltama bulır
 
 # Special:SpecialPages
 'specialpages' => 'Maxsus bitlär',
-'specialpages-note' => '----
-* Ğädi maxsus bitlär.
+'specialpages-note' => '* Ğädi maxsus bitlär.
 * <strong class="mw-specialpagerestricted">Çiklänelgän ğädi maxsus bitlär</strong>',
 'specialpages-group-maintenance' => 'Texnik qaraw xisapnamäse',
 'specialpages-group-other' => 'Başqa maxsus bitlär',
index 8a1d47e..03ab388 100644 (file)
@@ -73,7 +73,7 @@ $magicWords = array(
        'pagename'                  => array( '1', 'АРЫННЫҢАДЫ', 'НАЗВАНИЕ_СТРАНИЦЫ', 'PAGENAME' ),
        'namespace'                 => array( '1', 'АТТАРДЕЛГЕМИ', 'ПРОСТРАНСТВО_ИМЁН', 'NAMESPACE' ),
        'namespacee'                => array( '1', 'АТТАРДЕЛГЕМИ2', 'ПРОСТРАНСТВО_ИМЁН_2', 'NAMESPACEE' ),
-       'namespacenumber'           => array( '1', 'АТТАРДЕЛГЕМИНИҢСАНЫ', 'NAMESPACENUMBER' ),
+       'namespacenumber'           => array( '1', 'АТТАРДЕЛГЕМИНИҢСАНЫ', 'НОМЕР_ПРОСТРАНСТВА_ИМЁН', 'NAMESPACENUMBER' ),
        'talkspace'                 => array( '1', 'ЧУГААДЕЛГЕМИ', 'ПРОСТРАНСТВО_ОБСУЖДЕНИЙ', 'TALKSPACE' ),
        'talkspacee'                => array( '1', 'ЧУГААДЕЛГЕМИ2', 'ПРОСТРАНСТВО_ОБСУЖДЕНИЙ_2', 'TALKSPACEE' ),
        'img_right'                 => array( '1', 'оң', 'справа', 'right' ),
@@ -90,9 +90,9 @@ $magicWords = array(
        'tag'                       => array( '0', 'демдек', 'метка', 'тег', 'тэг', 'tag' ),
        'hiddencat'                 => array( '1', '__ЧАЖЫТ_АҢГЫЛАЛ__', '__СКРЫТАЯ_КАТЕГОРИЯ__', '__HIDDENCAT__' ),
        'pagesincategory'           => array( '1', '__АҢГЫЛАЛ_АРЫННАРЫ__', 'СТРАНИЦ_В_КАТЕГОРИИ', 'PAGESINCATEGORY', 'PAGESINCAT' ),
-       'pagesincategory_all'       => array( '0', 'шупту', 'all' ),
-       'pagesincategory_pages'     => array( '0', 'арыннар', 'pages' ),
-       'pagesincategory_files'     => array( '0', 'файлдар', 'files' ),
+       'pagesincategory_all'       => array( '0', 'шупту', 'все', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'арыннар', 'страницы', 'pages' ),
+       'pagesincategory_files'     => array( '0', 'файлдар', 'файлы', 'files' ),
 );
 
 $bookstoreList = array(
@@ -127,7 +127,7 @@ $messages = array(
 'tog-watchlisthidebots' => 'Хайгаарал даңзызындан роботтарның эдиглерин чажыр',
 'tog-watchlisthideminor' => 'Хайгаарал даңзызындан бичии эдиглерни чажыр',
 'tog-watchlisthidepatrolled' => 'Хайгаарал даңзындан истээн өскерлиишкиннерны чажырары',
-'tog-showhiddencats' => 'ЧажÑ\8bÑ\82 Ð±Ó©Ð»Ò¯ÐºÑ\82еÑ\80ни ÐºÓ©Ñ\80гүзеÑ\80и',
+'tog-showhiddencats' => 'ЧажÑ\8bÑ\82 Ð°Ò£Ð³Ñ\8bлалдаÑ\80нÑ\8b ÐºÓ©Ñ\80гүзеÑ\80',
 
 'underline-always' => 'Кезээде',
 'underline-never' => 'Кажан-даа',
@@ -321,8 +321,6 @@ $messages = array(
 'ok' => 'Чөп',
 'retrievedfrom' => '«$1» деп адрестен парлаттынган',
 'youhavenewmessages' => 'Силерде $1 ($2) бар.',
-'newmessageslink' => 'чаа чагаалар',
-'newmessagesdifflink' => 'эрткен өскерлиишкин',
 'youhavenewmessagesmulti' => '«$1» деп арында силерге чаа чагаалар бар.',
 'editsection' => 'эдер',
 'editold' => 'эдер',
@@ -602,7 +600,7 @@ Please check if you want to create/edit this page.',
 'nextn' => 'дараазында {{PLURAL:$1|$1}}',
 'prevn-title' => 'Эрткен $1 {{PLURAL:$1|бижик|бижик}}',
 'nextn-title' => 'Дараазында $1 {{PLURAL:$1|бижик|бижик}}',
-'shown-title' => 'Арынга $1 {{PLURAL:$1|түңнелди|түңнелди}} көргүзери',
+'shown-title' => 'Арынга $1 {{PLURAL:$1|түңнел}} көргүзер',
 'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3) көөрү',
 'searchmenu-exists' => "'''Бо викиде \"[[:\$1]]\" деп арын бар.'''",
 'searchmenu-new' => "'''Бо викиде «[[:$1]]» арынны чогаадыры'''",
@@ -751,20 +749,21 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 'recentchanges-label-minor' => 'Бо өскерлиишкин бичии-дир',
 'recentchanges-label-bot' => 'Бо эдилгени робот күүсеткен.',
 'recentchanges-label-unpatrolled' => 'Бо өскертилге истетинмээн (патрульдаттынмаан)',
+'recentchanges-legend-newpage' => '$1 — чаа арын',
 'rcnote' => "$4 $5 өйде соңгу '''$2''' {{PLURAL:$2|хонуктуң}} {{PLURAL:$1|сөөлгү '''$1''' '''өскерилгелери'''}} .",
 'rcnotefrom' => 'Адаанда <strong>$2</strong> тура (<strong>$1</strong> чедир) өскертилгелерни санаан.',
 'rclistfrom' => '$1 тура чаа өскерилгелерни көргүзер',
 'rcshowhideminor' => 'Бичии өскерлиишкиннерни $1',
-'rcshowhidebots' => 'РобоÑ\82Ñ\82аÑ\80нÑ\83 $1',
-'rcshowhideliu' => 'Ð\9aиÑ\80еÑ\80 Ð°Ð¶Ñ\8bглакÑ\87Ñ\8bлаÑ\80нÑ\8b $1',
-'rcshowhideanons' => 'Ат эвес ажыглакчыларны $1',
+'rcshowhidebots' => 'РобоÑ\82Ñ\82аÑ\80нÑ\8b $1',
+'rcshowhideliu' => 'Ð\9aиÑ\80ген ÐºÐ¸Ñ\80жикÑ\87илеÑ\80ни $1',
+'rcshowhideanons' => 'Ады чок ажыглакчыларны $1',
 'rcshowhidepatr' => 'истээн өскерлиишкиннерни $1',
-'rcshowhidemine' => 'Ð\9cÑ\8dÑ\8dÒ£ Ó©Ñ\81кеÑ\80лииÑ\88кинимни $1',
-'rclinks' => '$2 хүнде эрткен $1 өскерлиишкиннерни көргүзери<br />$3',
+'rcshowhidemine' => 'ЭдиглеÑ\80имни $1',
+'rclinks' => 'Сөөлгү $2 хүн иштинде болган $1 өскерлиишкиннерни көргүзер<br />$3',
 'diff' => 'ылгал',
 'hist' => 'төөгү',
-'hide' => 'чажырары',
-'show' => 'көÑ\80гүзеÑ\80и',
+'hide' => 'Чажырар',
+'show' => 'Ð\9aÓ©Ñ\80гүзеÑ\80',
 'minoreditletter' => 'б',
 'newpageletter' => 'Ч',
 'boteditletter' => 'р',
@@ -873,7 +872,7 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 'brokenredirects-delete' => 'ырадыры',
 
 'withoutinterwiki' => 'Дыл холбаалар эвес арыннар',
-'withoutinterwiki-submit' => 'Көргүзери',
+'withoutinterwiki-submit' => 'Көргүзер',
 
 'fewestrevisions' => 'Эң эвээш үндүрери арыннар',
 
@@ -987,7 +986,7 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 'unwatching' => 'Хайгааравайн турар...',
 
 'enotif_impersonal_salutation' => '{{grammar:genitive|{{SITENAME}}}} ажыглакчызы',
-'enotif_anon_editor' => 'аÑ\82 Ñ\8dвеÑ\81 Ð°Ð¶Ñ\8bглакÑ\87Ñ\8b $1',
+'enotif_anon_editor' => 'аÑ\82 Ñ\87ок ÐºÐ¸Ñ\80жикÑ\87и $1',
 'changed' => 'өскертти',
 
 # Delete
@@ -1095,7 +1094,7 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 'contribslink' => 'салыышкыннар',
 'blocklogpage' => 'Кызыгаарлаашкынның журналы',
 'blocklogentry' => ', [[$1]] $2 дургузунда кызыгаарлаттынган: $3',
-'block-log-flags-anononly' => 'чүгле ат эвес ажыглакчылар',
+'block-log-flags-anononly' => 'чүгле адыжок киржикчилер',
 'block-log-flags-nocreate' => 'Кижилер бүрүткээри хоруглуг',
 'block-log-flags-hiddenname' => 'ажыглакчының ады чажырган',
 
@@ -1199,7 +1198,7 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 'tooltip-summary' => 'Кысказы-биле бижиңер',
 
 # Attribution
-'anonymous' => '{{grammar:genitive|{{SITENAME}}}} ат эвес {{PLURAL:$1|ажыглакчызы|ажыглакчылары}}',
+'anonymous' => '{{grammar:genitive|{{SITENAME}}}} адыжок {{PLURAL:$1|киржикчизи}}',
 
 # Skin names
 'skinname-cologneblue' => 'Cologne Blue',
@@ -1287,7 +1286,7 @@ It must not be more than $1 {{PLURAL:$1|character|characters}} long.',
 
 # External editor support
 'edit-externally' => 'Бо файлды даштыкы капсырылга-биле эдер',
-'edit-externally-help' => '(Улаштыр тодарадырда бо [//www.mediawiki.org/wiki/Manual:External_editors кыстып алыр саавырны] көрүңер)',
+'edit-externally-help' => '(Улаштыр тодарадырда бо [https://www.mediawiki.org/wiki/Manual:External_editors кыстып алыр саавырны] көрүңер)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'шупту',
index 7c16f4a..9900e24 100644 (file)
@@ -44,6 +44,7 @@ $namespaceAliases = array(
 $namespaceGenderAliases = array();
 
 $linkTrail = '/^([a-zа-яёӝӟӥӧӵ“»]+)(.*)$/sDu';
+$linkPrefixCharset = '„«';
 $fallback8bitEncoding = 'windows-1251';
 $separatorTransformTable = array( ',' => "\xc2\xa0", '.' => ',' );
 
@@ -151,8 +152,6 @@ $messages = array(
 'index-category' => 'Индексировать кароно бамъёс',
 'noindex-category' => 'Индексировать каронтэм бамъёс',
 
-'linkprefix' => '/^(.*?)(„|«)$/sDu',
-
 'about' => 'Та сярысь',
 'article' => 'Статья',
 'mypage' => 'Ас бам',
index ab5ee42..e273423 100644 (file)
@@ -13,6 +13,7 @@
  * @author Kaganer
  * @author Reedy
  * @author Sahran
+ * @author Tel'et
  */
 
 $rtl = true;
@@ -55,10 +56,10 @@ $messages = array(
 'tog-extendwatchlist' => 'كۈچەيتىلگەن كۆزەت تىزىملىكىدە يېقىنقى ئۆزگەرتىشنىلا كۆرسەتمەي بەلكى ھەممە ئۆزگەرتىشنى كۆرسەت',
 'tog-usenewrc' => 'بەت گۇرۇپپىلىنىشىغا ئاساسەن يېقىنقى ئۆزگەرتىش ۋە كۆزەت تىزىمى (JavaScript زۆرۈر)',
 'tog-numberheadings' => 'ماۋزۇغا ئۆزلۈكىدىن تەرتىپ نومۇرى قوش',
-'tog-showtoolbar' => 'تەھرىر قورال بالداقنى كۆرسەت (JavaScript زۆرۈر)',
-'tog-editondblclick' => 'قوش چەككەندە بەت تەھرىرلە (JavaScript زۆرۈر)',
+'tog-showtoolbar' => 'تەھرىر قورال بالداقنى كۆرسەت',
+'tog-editondblclick' => 'قوش چەككەندە بەت تەھرىرلە',
 'tog-editsection' => '[تەھرىر] ئۇلانمىسىنى چېكىپ ئابزاس تەھرىرلەشكە يول قوي',
-'tog-editsectiononrightclick' => 'ماۋزۇنى چاشقىنەكتە ئوڭ چېكىپ ئابزاس تەھرىرلەشكە يول قوي (JavaScript زۆرۈر)',
+'tog-editsectiononrightclick' => 'تېمىنى ئوڭ چېكىپ ئابزاس تەھرىرلەشكە يول قوي',
 'tog-showtoc' => 'مەزمۇن جەدۋىلى كۆرسەت (بىر بەتتە 3 تىن ئارتۇق ماۋزۇ بار بەتكە قارىتىلغان)',
 'tog-rememberpassword' => 'بۇ كومپيۇتېردا كىرگىنىمنى ئەستە ساقلا(ئەڭ ئۇزۇن بولغاندا $1 {{PLURAL:$1|كۈن|كۈن}})',
 'tog-watchcreations' => 'مەن قۇرغان بەت ۋە يۈكلىگەن ھۆججەتلەرنى كۆزەت تىزىملىكىمگە قوش',
@@ -76,7 +77,7 @@ $messages = array(
 'tog-shownumberswatching' => 'بۇ بەتنى كۆزىتىۋاتقان ئىشلەتكۈچى سانىنى كۆرسەت',
 'tog-oldsig' => 'نۆۋەتتىكى ئىمزا:',
 'tog-fancysig' => 'ئىمزاغا wiki تېكستى سۈپىتىدە مۇئامىلە قىل (ئۆزلۈكىدىن ئۇلانما ھاسىل بولمايدۇ)',
-'tog-uselivepreview' => 'رÙ\89ئاÙ\84 Û\8bاÙ\82Ù\89تÙ\84Ù\89Ù\82 Ø¦Ø§Ù\84دÙ\89Ù\86 Ù\83Û\86زÙ\89تÙ\89Ø´Ù\86Ù\89 Ø¦Ù\89Ø´Ù\84Û\95ت (JavaScript Ø²Û\86رÛ\88ر) (سىناق)',
+'tog-uselivepreview' => 'جاÙ\86Ù\84Ù\89Ù\82 Ø¦Ø§Ù\84دÙ\89Ù\86 Ù\83Û\86زÙ\89تÙ\89Ø´Ù\86Ù\89 Ø¦Ù\89Ø´Ù\84Û\95ت (سىناق)',
 'tog-forceeditsummary' => 'ئۈزۈندە كىرگۈزمىگەندە مېنى ئەسكەرت',
 'tog-watchlisthideown' => 'كۆزەت تىزىملىكىدىن مېنىڭ تەھرىرلىگىنىمنى يوشۇر',
 'tog-watchlisthidebots' => 'كۆزەت تىزىملىكىدىن ماشىنا ئادەم تەھرىرلىگەننى يوشۇر',
@@ -152,6 +153,18 @@ $messages = array(
 'oct' => 'ئۆكتەبىر',
 'nov' => 'نويابىر',
 'dec' => 'دېكابىر',
+'january-date' => '$1- يانۋار',
+'february-date' => '$1- فېۋرال',
+'march-date' => '$1- مارت',
+'april-date' => '$1- ئاپرىل',
+'may-date' => '$1- ماي',
+'june-date' => '$1- ئىيۇن',
+'july-date' => '$1- ئىيۇل',
+'august-date' => '$1- ئاۋغۇست',
+'september-date' => '$1- سىنتەبىر',
+'october-date' => '$1- ئۆكتەبىر',
+'november-date' => '$1- نويابىر',
+'december-date' => '$1- دىكابىر',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|تۈر|تۈرلەر}}',
@@ -173,14 +186,12 @@ $messages = array(
 'broken-file-category' => 'ھۆججەت ئۇلىنىشى بۇزۇلغان بەتلەر',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'ھەققىدە',
 'article' => 'مۇندەرىجە',
 'newwindow' => '(يېڭى كۆزنەكتە ئاچ)',
 'cancel' => 'ۋاز كەچ',
 'moredotdotdot' => 'تەپسىلىي…',
-'morenotlisted' => 'تÛ\95پسÙ\89Ù\84اتÙ\89 Ù\83Û\86رسÙ\89تÙ\89Ù\84Ù\85Ù\89Ú¯Û\95Ù\86Ù\84Ù\89رÙ\89â\80¦',
+'morenotlisted' => 'بÛ\87 ØªÙ\89زÙ\89Ù\85Ù\84Ù\89Ù\83 ØªÙ\88Ù\84Û\87Ù\82 Ø¦Û\95Ù\85Û\95س.',
 'mypage' => 'بەتىم',
 'mytalk' => 'مۇنازىرە بېتىم',
 'anontalk' => 'بۇ IP نىڭ مۇنازىرە بېتى',
@@ -236,6 +247,7 @@ $messages = array(
 'create-this-page' => 'بۇ بەتنى قۇر',
 'delete' => 'ئۆچۈر',
 'deletethispage' => 'بۇ بەتنى ئۆچۈر',
+'undeletethispage' => ' بۇ بەتنى ئەسلىگە كەلتۈر',
 'undelete_short' => 'ئۆچۈرۈلگەن {{PLURAL:$1|بىر تەھرىر|$1 تەھرىر}} ئەسلىگە كەلتۈرۈلدى',
 'viewdeleted_short' => '{{PLURAL:$1|بىر ئۆچۈرۈلگەن نەشرى|$1 ئۆچۈرۈلگەن نەشرى}}نى كۆرسەت',
 'protect' => 'قوغدا',
@@ -252,7 +264,7 @@ $messages = array(
 'articlepage' => 'مەزمۇن بېتىنى كۆرسەت',
 'talk' => 'مۇنازىرە',
 'views' => 'كۆرۈنۈش',
-'toolbox' => 'قورال ساندۇقى',
+'toolbox' => 'قوراللار',
 'userpage' => 'ئىشلەتكۈچى بېتىنى كۆرسەت',
 'projectpage' => 'قۇرۇلۇش بېتىنى كۆرسەت',
 'imagepage' => 'ھۆججەت بېتىنى كۆرسەت',
@@ -313,8 +325,6 @@ $1',
 'backlinksubtitle' => '← $1',
 'retrievedfrom' => '"$1" دىن ئېرىشكەن',
 'youhavenewmessages' => 'سىزدە $1 ($2) بار.',
-'newmessageslink' => 'يېڭى ئۇچۇر',
-'newmessagesdifflink' => 'ئاخىرقى ئۆزگەرتىش',
 'youhavenewmessagesfromusers' => 'سىزنىڭ {{PLURAL:$3|باشقا ئىشلەتكۈچى|$3 ئىشلەتكۈچى}} $1  ($2)ڭىز بار.',
 'youhavenewmessagesmanyusers' => 'سىزنىڭ نۇرغۇن ئىشلەتكۈچىدىن كەلگەن $1  ($2) بار.',
 'newmessageslinkplural' => '{{PLURAL:$1|بىر يېڭى |يېڭى ئۇچۇر}}ئۇچۇر',
@@ -375,6 +385,8 @@ URL نى خاتا كىرگۈزۈپ قالدىڭىز ياكى خاتا ئۇلان
 # General errors
 'error' => 'خاتالىق',
 'databaseerror' => 'ساندان خاتالىقى',
+'databaseerror-function' => 'فۇنكىسىيە: $1',
+'databaseerror-error' => 'خاتا: $1',
 'laggedslavemode' => 'ئاگاھلاندۇرۇش: بەت يېقىنقى يېڭىلاشنى ئۆز ئىچىگە ئالمىغان بولۇشى مۇمكىن.',
 'readonly' => 'ساندان قۇلۇپلانغان',
 'enterlockreason' => 'قۇلۇپلىنىش سەۋەبىنى كىرگۈزۈڭ، قايتا ئېچىشنىڭ مۆلچەر ۋاقتىنىمۇ ئۆز ئىچىگە ئالىدۇ',
@@ -472,9 +484,19 @@ $2',
 
 [[Special:Preferences|{{SITENAME}} تەڭشىكىڭىزنى تەڭشەشنى ئۇنتۇپ قالماڭ]].',
 'yourname' => 'ئىشلەتكۈچى ئاتى:',
-'yourpassword' => 'ئىم:',
+'userlogin-yourname' => 'ئىشلەتكۈچى نامى',
+'userlogin-yourname-ph' => 'ئىشلەتكۈچى نامىڭىزنى كىرگۈزۈڭ',
+'createacct-another-username-ph' => 'ئىشلەتكۈچى نامىنى كىرگۈزۈڭ',
+'yourpassword' => 'پارول:',
+'userlogin-yourpassword' => 'پارول',
+'userlogin-yourpassword-ph' => 'پارولىڭىزنى كىرگۈزۈڭ',
+'createacct-yourpassword-ph' => 'پارول كىرگۈزۈڭ',
 'yourpasswordagain' => 'ئاچقۇچنى قايتا بەسىڭ:',
+'createacct-yourpasswordagain' => 'پارولنى مۇقىملاشتۇرۇڭ',
+'createacct-yourpasswordagain-ph' => 'پارولنى قايتا كىرگۈزۈڭ',
 'remembermypassword' => 'بۇ كومپيۇتېردا كىرگىنىمنى ئەستە ساقلا(ئەڭ ئۇزۇن بولغاندا $1 {{PLURAL:$1|كۈن|كۈن}})',
+'userlogin-remembermypassword' => 'مېنى ئەستە ساقلا',
+'userlogin-signwithsecure' => 'بىخەتەر ئۇلىنىشنى ئىشلەت',
 'yourdomainname' => 'دائىرە ئاتىڭىز:',
 'password-change-forbidden' => 'بۇ ۋىكىدىكى ئىمنى ئۆزگەرتەلمەيسىز.',
 'externaldberror' => 'بۇ سانداننى دەلىللەش خاتالىقى ياكى سىرتقى ھېساباتىڭىزنى يېڭىلاشنى چەكلىگەنلىكتىن بولغان بولۇشى مۇمكىن.',
@@ -486,18 +508,42 @@ $2',
 'logout' => 'تىزىمدىن چىق',
 'userlogout' => 'تىزىمدىن چىق',
 'notloggedin' => 'تىزىمغا كىرمىدى',
+'userlogin-noaccount' => 'ھېساباتىڭىز يوقمۇ؟',
+'userlogin-joinproject' => '{{SITENAME}} قا ئەزا بولۇش',
 'nologin' => "ھېساباتىڭىز يوقمۇ؟ '''$1'''.",
 'nologinlink' => 'ھېساباتتىن بىرنى قۇر',
 'createaccount' => 'ھېسابات قۇر',
 'gotaccount' => "ھېساباتىم بار؟ '''$1'''.",
 'gotaccountlink' => 'تىزىمغا كىر',
 'userlogin-resetlink' => 'تىزىمغا كىرىش تەپسىلاتىنى ئۇنۇتتىڭىز؟',
+'userlogin-resetpassword-link' => 'پارولىڭىزنى ئۇنتۇپ قالدىڭىزمۇ؟',
+'helplogin-url' => 'Help:تىزىمغا كىرىش',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|تىزىمغا كىرىش ئۈچۈن ياردەم]]',
+'userlogin-loggedin' => 'سىز ئاللىقاچان {{GENDER:$1|$1}} ھالىتىدە تىزىمغا كىرىپ بولدىڭىز. تۆۋەندىكىلەرنى تولدۇرۇپ باشقا ئىشلەتكۈچى ھالىتىدە تىزىمغا كىرىڭ.',
+'userlogin-createanother' => 'باشقا ھېسابات قۇرىمەن',
+'createacct-join' => 'تۆۋەنگە ئۇچۇرلىرىڭىزنى كىرگۈزۈڭ.',
+'createacct-another-join' => 'يېڭى ئىشلەتكۈچىنىڭ ئۇچۇرلىرىنى كىرگۈزۈڭ.',
+'createacct-emailrequired' => 'ئېلخەت ئادرېسى',
+'createacct-emailoptional' => 'ئېلخەت ئادرېسى (ئىختىيارى)',
+'createacct-email-ph' => 'ئېلخەت ئادرېسىڭىزنى كىرگۈزۈڭ',
+'createacct-another-email-ph' => 'ئېلخەت ئادرېسى كىرگۈزۈڭ',
 'createaccountmail' => 'ۋاقىتلىق ئىختىيارىي بىر ئېمنى ئىشلىتىدۇ ھەمدە تۆۋەندىكى بەلگىلەنگەن تورخەت ئادرېسىغا ئەۋەتىدۇ',
+'createacct-realname' => 'ھەقىقى ئىسمىڭىز (ئىختىيارى)',
 'createaccountreason' => 'سەۋەب:',
-'badretype' => 'سىز كىرگۈزگەن ئىم ماس كەلمىدى.',
+'createacct-reason' => 'سەۋەبى',
+'createacct-reason-ph' => 'نېمىشقا باشقا ھېسابات قۇرماقچى بولدىڭىز',
+'createacct-captcha' => 'بىخەتەرلىك تەكشۈرۈشى',
+'createacct-imgcaptcha-ph' => 'ئۈستىدە كۆرگىنىڭىزنى كىرگۈزۈڭ',
+'createacct-submit' => 'ھېساباتىڭىزنى قۇرۇڭ',
+'createacct-another-submit' => 'باشقا ھېسابات قۇرىمەن',
+'createacct-benefit-heading' => '{{SITENAME}} سىزگە ئوخشاش كىشىلەر تەرىپىدىن قۇرۇلغان.',
+'createacct-benefit-body1' => '{{PLURAL:$1|قېتىم}} تەھرىرلەنگەن',
+'createacct-benefit-body2' => '{{PLURAL:$1|بەت}}',
+'badretype' => 'سىز كىرگۈزگەن پارول ماس كەلمىدى.',
 'userexists' => 'كىرگۈزگەن ئىشلەتكۈچى ئاتى ئىشلىتىلىۋاتىدۇ.
 باشقا ئاتنى تاللاڭ.',
 'loginerror' => 'تىزىمغا كىرىش خاتالىقى',
+'createacct-error' => 'ھېسابات قۇرۇش خاتالىقى',
 'createaccounterror' => 'ھېسابات قۇرالمىدى: $1',
 'nocookiesnew' => 'ئىشلەتكۈچى ھېساباتى قۇرۇلدى ئەمما سىز تېخى كىرمىدىڭىز..
 
@@ -524,15 +570,15 @@ cookies نى قوزغاتقانلىقىڭىزنى جەزملەڭ، بۇ بەتن
 كىرگۈزگىنىڭىزنى تەكشۈرۈڭ.',
 'nouserspecified' => 'ئىشلەتكۈچى ئاتىدىن بىرنى بەلگىلەڭ.',
 'login-userblocked' => 'بۇ ئىشلەتكۈچى چەكلەنگەن. تىزىمغا كىرىشكە يول قويۇلمايدۇ.',
-'wrongpassword' => 'كىرگۈزگەن ئىم خاتا.
+'wrongpassword' => 'كىرگۈزگەن پارول خاتا.
 قايتا سىناڭ.',
-'wrongpasswordempty' => 'ئىم كىرگۈزمىدىڭىز
+'wrongpasswordempty' => 'پارول كىرگۈزمىدىڭىز
 قايتا سىناڭ.',
 'passwordtooshort' => 'ئىم ئاز دېگەندە {{PLURAL:$1|1 ھەرپ|$1 ھەرپ}} بولۇشى لازىم.',
-'password-name-match' => 'ئىم ئىشلەتكۈچى ئاتىڭىزدىن پەرقلىنىشى لازىم.',
-'password-login-forbidden' => 'بۇ ئىشلەتكۈچى ئاتى ۋە ئىم چەكلەنگەن.',
+'password-name-match' => 'پارولىڭىز ئىشلەتكۈچى نامىڭىزدىن پەرقلىنىشى لازىم.',
+'password-login-forbidden' => 'بۇ ئىشلەتكۈچى نامى ۋە پارول چەكلەنگەن.',
 'mailmypassword' => 'يېڭى ئىمنى ئېخەتكە ئەۋەت',
-'passwordremindertitle' => '{{SITENAME}} ئۈچۈن يېڭى ۋاقىتلىق ئىم',
+'passwordremindertitle' => '{{SITENAME}} ئۈچۈن يېڭى ۋاقىتلىق پارول',
 'passwordremindertext' => 'باشقىلار (بەلكىم سىز، IP ئادرېسى $1)
 {{SITENAME}} بېكەتنىڭ يېڭى ئىم ($4) نى ئىلتىماس قىلدى .
  "$2" ئىشلەتكۈچىنىڭ يېڭى ۋاقىتلىق ئىمنى "$3" غا تەڭشىدى.
@@ -554,7 +600,7 @@ cookies نى قوزغاتقانلىقىڭىزنى جەزملەڭ، بۇ بەتن
 'mailerror' => 'ئېلخەت يوللىغاندا خاتالىق كۆرۈلدى:$1',
 'acct_creation_throttle_hit' => 'Wiki ئىشلىتىدىغان زىيارەتچى IP ئادرېسىڭىزنى ئىشلىتىپ {{PLURAL:$1|1 ھېسابات|$1 ھېسابات}} قۇردى.
 مۇشۇ پەيتتە يەنە ھېسابات قۇرالمايسىز.',
-'emailauthenticated' => 'ئېلخەت ئادرېسىڭىز $2 $3 ئىناۋەتلىك ئىكەنلىكى دەلىللەندى.',
+'emailauthenticated' => 'ئېلخەت ئادرېسىڭىز $2 سائەت $3 دە دەلىللەندى.',
 'emailnotauthenticated' => 'ئېلخەت ئادرېسىڭىز تېخى دەلىللەنمىدى.
 تۆۋەندىكى ئىقتىدارى ھېچقانداق ئېلخەت ئەۋەتمەيدۇ.',
 'noemailprefs' => 'بۇ ئىقتىدارنى ئىشلىتىش ئۈچۈن مايىللىق تەڭشىكىڭىزدە ئېلخەت ئادرېسى بەلگىلەڭ.',
@@ -583,25 +629,25 @@ cookies نى قوزغاتقانلىقىڭىزنى جەزملەڭ، بۇ بەتن
 'user-mail-no-body' => 'بوش ياكى مەزمۇنى قىسقا مۇۋاپىق بولمىغان تورخەت ئەۋەتىشنى سىنىدى.',
 
 # Change password dialog
-'resetpass' => 'ئىم ئۆزگەرت',
+'resetpass' => 'پارولنى ئۆزگەرتىش',
 'resetpass_announce' => 'سىز ۋاقىتلىق ئېلخەت جەزملەش كودىدا تىزىمغا كىرگەن.
 تىزىمغا كىرىشنى تاماملاشتا، بۇ جايدا يېڭى ئىم بەلگىلىشىڭىز لازىم:',
 'resetpass_text' => '<!-- بۇ يەرگە تېكست قوشۇڭ -->',
 'resetpass_header' => 'ھېسابات ئىمنى ئۆزگەرت',
-'oldpassword' => 'كونا ئىم:',
-'newpassword' => 'يېڭى ئىم:',
-'retypenew' => 'يېڭى ئىمنى قايتا كىرگۈزۈڭ:',
-'resetpass_submit' => 'ئىم بەلگىلەپ تىزىمغا كىرىڭ',
+'oldpassword' => 'كونا پارول:',
+'newpassword' => 'يېڭى پارول:',
+'retypenew' => 'يېڭى پارولنى قايتا كىرگۈزۈڭ:',
+'resetpass_submit' => 'پارول بەلگىلەپ تىزىمغا كىرىڭ',
 'changepassword-success' => 'سىز ئىمنى مۇۋەپپەقىيەتلىك ئۆزگەرتتىڭىز!
  تىزىمغا كىرىۋاتىسىز…',
 'resetpass_forbidden' => 'ئىمنى ئۆزگەرتەلمىدى',
 'resetpass-no-info' => 'سىز تىزىمغا كىرگەندىن كېيىن بىۋاسىتە بۇ بەتكە كىرىشىڭىز لازىم.',
-'resetpass-submit-loggedin' => 'ئىم ئۆزگەرت',
+'resetpass-submit-loggedin' => 'پارولنى ئۆزگەرتىش',
 'resetpass-submit-cancel' => 'ۋاز كەچ',
 'resetpass-wrong-oldpass' => 'ۋاقىتلىق ياكى نۆۋەتتىكى ئىم ئىناۋەتسىز.
 
 ئىمنى ئاللىبۇرۇن ئۆزگەرتىپ بولدىڭىز ياكى يېڭى ۋاقىتلىق ئىم ئىلتىماس قىلدىڭىز.',
-'resetpass-temp-password' => 'ۋاقىتلىق ئىم:',
+'resetpass-temp-password' => 'ۋاقىتلىق پارول:',
 
 # Special:PasswordReset
 'passwordreset' => 'ئىمنى ئەسلىگە قايتۇرماق',
@@ -644,7 +690,7 @@ $2
 'changeemail-oldemail' => 'نۆۋەتتىكى ئېلخەت ئادرېسى:',
 'changeemail-newemail' => 'يېڭى ئېلخەت ئادرېسى:',
 'changeemail-none' => '(يوق)',
-'changeemail-password' => '{{SITENAME}} دىكى ئىم:',
+'changeemail-password' => '{{SITENAME}} دىكى پارولىڭىز:',
 'changeemail-submit' => 'ئېلخەت ئۆزگەرت',
 'changeemail-cancel' => 'ۋاز كەچ',
 
@@ -725,7 +771,7 @@ $2
 'loginreqtitle' => 'تىزىمغا كىرىڭ',
 'loginreqlink' => 'تىزىمغا كىر',
 'loginreqpagetext' => '$1 بولغاندىلا ئاندىن باشقا بەتلەرنى كۆرەلەيسىز.',
-'accmailtitle' => 'ئىم يوللاندى.',
+'accmailtitle' => 'پارول يوللاندى.',
 'accmailtext' => "[[User talk:$1|$1]] ئىختىيارىي قۇرۇلغان ئىم  $2 غا يوللاندى.
 
 يېڭى ھېساباتقا قۇرغان ئىمنى تىزىمغا كىرىپ''[[Special:ChangePassword|ئىم ئۆزگەرت]]'' بېتىدىن ئۆزگەرتەلەيسىز.",
@@ -922,8 +968,8 @@ $3 تەمىنلىگەن چەكلەش سەۋەبى ''$2''",
  '''{{int:minoreditletter}}''' ئازراقلا ئۆزگەرتىش.",
 'history-fieldset-title' => 'كۆز يۈگۈرتۈش تارىخى',
 'history-show-deleted' => 'ئۆچۈرۈلگەنلا',
-'histfirst' => 'تÛ\87Ù\86جÙ\89',
-'histlast' => 'ئاخىرقى',
+'histfirst' => 'ئÛ\95Ú­ Ù\83Ù\88Ù\86ا',
+'histlast' => 'ئەڭ يېڭى',
 'historysize' => '$1 {{PLURAL:$1|بايت|بايت}}',
 'historyempty' => '(بوش)',
 
@@ -989,7 +1035,7 @@ $3 تەمىنلىگەن چەكلەش سەۋەبى ''$2''",
 'revdelete-hide-image' => 'ھۆججەت مەزمۇنىنى يوشۇر',
 'revdelete-hide-name' => 'مەشغۇلات ۋە نىشاننى يوشۇر',
 'revdelete-hide-comment' => 'تەھرىر ئىزاھاتىنى يوشۇر',
-'revdelete-hide-user' => 'تەھرىرلىگۈچىنىڭ ئىشلەتكۈچى ئاتى/IP ئادرېس يوشۇر',
+'revdelete-hide-user' => 'تەھرىرلىگۈچىنىڭ نامى/IP ئادرېسىنى يوشۇر',
 'revdelete-hide-restricted' => 'مەشغۇلاتچى ۋە باشقا ئىشلەتكۈچىنىڭ سانلىق مەلۇمات كۆرۈشىنىمۇ چەكلە',
 'revdelete-radio-same' => '(ئۆزگەرتمە)',
 'revdelete-radio-set' => 'ھەئە',
@@ -1122,7 +1168,7 @@ $1",
 'search-interwiki-default' => '$1 نەتىجە:',
 'search-interwiki-more' => '(تېخىمۇ كۆپ)',
 'search-relatedarticle' => 'ئالاقىدار',
-'mwsuggest-disable' => 'AJAX تەكلىپىنى چەكلە',
+'mwsuggest-disable' => 'ئىزدەش تەكلىپىنى چەكلە',
 'searcheverything-enable' => 'ھەممە ئات بوشلۇقىدىن ئىزدە',
 'searchrelated' => 'ئالاقىدار',
 'searchall' => 'ھەممىسى',
@@ -1148,9 +1194,7 @@ $1",
 'preferences' => 'مايىللىق',
 'mypreferences' => 'مايىللىق',
 'prefs-edits' => 'تەھرىر سانى:',
-'prefsnologin' => 'تىزىمغا كىرمىدى',
-'prefsnologintext' => 'سىز ئالدى بىلەن <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} تىزىمغا كىر]</span>سىڭىز ئاندىن ئىشلەتكۈچى مايىللىقنى تەڭشىيەلەيسىز.',
-'changepassword' => 'ئىم ئۆزگەرت',
+'changepassword' => 'پارولنى ئۆزگەرتىش',
 'prefs-skin' => 'تېرە',
 'skin-preview' => 'ئالدىن كۆزەت',
 'datedefault' => 'مايىللىق يوق',
@@ -1167,7 +1211,7 @@ $1",
 'prefs-watchlist-edits-max' => 'ئەڭ كۆپ سانى: 1000',
 'prefs-watchlist-token' => 'كۆزەت تىزىملىك نىشانى:',
 'prefs-misc' => 'ئارىلاشما تۈر',
-'prefs-resetpass' => 'ئىم ئۆزگەرت',
+'prefs-resetpass' => 'پارولنى ئۆزگەرتىش',
 'prefs-changeemail' => 'ئېلخەت ئۆزگەرت',
 'prefs-setemail' => 'ئېلخەت ئادرېس تەڭشەك',
 'prefs-email' => 'ئېلخەت تاللانما',
@@ -1255,6 +1299,8 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'prefs-dateformat' => 'چېسلا فورماتى',
 'prefs-timeoffset' => 'ۋاقىت پەرقى',
 'prefs-advancedediting' => 'ئالىي تاللانما',
+'prefs-editor' => 'تەھرىرلىگۈچ',
+'prefs-preview' => 'ئالدىن كۆزەت',
 'prefs-advancedrc' => 'ئالىي تاللانما',
 'prefs-advancedrendering' => 'ئالىي تاللانما',
 'prefs-advancedsearchoptions' => 'ئالىي تاللانما',
@@ -1262,6 +1308,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'prefs-displayrc' => 'كۆرسىتىش تاللانما',
 'prefs-displaysearchoptions' => 'كۆرسىتىش تاللانما',
 'prefs-displaywatchlist' => 'كۆرسىتىش تاللانما',
+'prefs-tokenwatchlist' => 'ئاچقۇچ',
 'prefs-diffs' => 'پەرقلەر',
 
 # User preference: email validation using jQuery
@@ -1361,6 +1408,8 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'right-editusercssjs' => 'باشقا ئىشلەتكۈچىنىڭ CSS ۋە JS ھۆججىتىنى تەھرىرلە',
 'right-editusercss' => 'باشقا ئىشلەتكۈچىنىڭ CSS ھۆججىتىنى تەھرىرلە',
 'right-edituserjs' => 'باشقا ئىشلەتكۈچىنىڭ  JS ھۆججىتىنى تەھرىرلە',
+'right-editmyusercss' => 'ئۆزىڭىزنىڭ CSS ھۆججىتىڭىزنى تەھرىرلەڭ',
+'right-editmyuserjs' => 'ئۆزىڭىزنىڭ JavaScript ھۆججىتىڭىزنى تەھرىرلەڭ',
 'right-rollback' => 'ئاخىرقى ئىشلەتكۈچىنىڭ مەلۇم بەتكە ئېلىپ بارغان تەھرىرىنى تېزلىكتە ئەسلىگە كەلتۈر',
 'right-markbotedits' => 'ئەسلىگە كەلتۈرۈلگەن تەھرىرنى ماشىنا ئادەم تەھرىرى دەپ بەلگە قوي',
 'right-noratelimit' => 'چاستوتا چەكلىمىسى ئىشلىتىلمىدى',
@@ -1425,6 +1474,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|ئۆزگەرتىش|ئۆزگەرتىش}}',
+'enhancedrc-history' => 'تارىخ',
 'recentchanges' => 'يېقىنقى ئۆزگەرتىشلەر',
 'recentchanges-legend' => 'يېقىنقى ئۆزگەرتىش تاللانمىسى',
 'recentchanges-summary' => 'بۇ wiki نىڭ يېقىنقى ئۆزگىرىشىنى ئىز قوغلا.',
@@ -1433,6 +1483,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'recentchanges-label-minor' => 'بۇ ئازراقلا تەھرىرلەش',
 'recentchanges-label-bot' => 'بۇ تەھرىرنى ماشىنا ئادەم ئېلىپ بارغان',
 'recentchanges-label-unpatrolled' => 'بۇ تەھرىر تېخى كۆزىتىلمىگەن',
+'recentchanges-legend-newpage' => '$1 - يېڭى بەت',
 'rcnote' => "تۆۋەندىكى $4 $5 يېقىنقى {{PLURAL:$2|كۈن|'''$2''' كۈن}}  ئىچىدىكى {{PLURAL:$1| '''1''' ئۆزگەرتىش| '''$1''' ئۆزگەرتىش}}  خاتىرىسى",
 'rcnotefrom' => "تۆۋەندىكىسى '''$2''' نىڭ ئۆزگەرتىشى (ئەڭ كۆپ بولغاندا '''$1''' كۆرسىتىدۇ )",
 'rclistfrom' => '$1 دىن باشلانغان يېڭى ئۆزگەرتىشنى كۆرسەت',
@@ -1457,7 +1508,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'rc-change-size' => '$1',
 'rc-change-size-new' => 'ئۆزگەرتكەندىن كېيىن $1 {{PLURAL:$1|بايت}}',
 'newsectionsummary' => '* $1 * يېڭى ئابزاس',
-'rc-enhanced-expand' => 'تەپسىلاتىنى كۆرسەت (JavaScript قوللىشى زۆرۈر)',
+'rc-enhanced-expand' => 'تەپسىلاتىنى كۆرسەت',
 'rc-enhanced-hide' => 'تەپسىلاتىنى يوشۇر',
 'rc-old-title' => 'ئەڭ دەسلەپتە "$1" سۈپىتىدە قۇرۇلغان',
 
@@ -1730,6 +1781,9 @@ URL نىڭ توغرىلىقى ۋە تور بېكەتنى زىيارەت قىلى
 'listfiles_size' => 'چوڭلۇقى',
 'listfiles_description' => 'چۈشەندۈرۈش',
 'listfiles_count' => 'نەشرى',
+'listfiles-latestversion' => 'نۆۋەتتىكى نەشرى',
+'listfiles-latestversion-yes' => 'ھەئە',
+'listfiles-latestversion-no' => 'ياق',
 
 # File description page
 'file-anchor-link' => 'ھۆججەت',
@@ -1827,6 +1881,11 @@ URL نىڭ توغرىلىقى ۋە تور بېكەتنى زىيارەت قىلى
 'randompage' => 'ئىختىيارىي بەت',
 'randompage-nopages' => 'تۆۋەندىكى {{PLURAL:$2|ئات بوشلۇقى|ئات بوشلۇقى}}دا بەت يوق: $1.',
 
+# Random page in category
+'randomincategory' => 'تۈردىكى ئىختىيارى بەت',
+'randomincategory-invalidcategory' => '«$1» ئىناۋەتلىك تۈر نامى ئەمەس',
+'randomincategory-nopages' => '[[:Category:$1|$1]] تۈرىدە ھىچقانداق بەت يوق.',
+
 # Random redirect
 'randomredirect' => 'ئىختىيارىي قايتا نىشانلانغان بەت',
 'randomredirect-nopages' => '"$1" ئات بوشلۇقىدا قايتا نىشانلانغان بەت يوق.',
@@ -2343,7 +2402,6 @@ $1',
 $1',
 'undelete-show-file-confirm' => '$2 $3 دىكى \\"<nowiki>$1</nowiki>\\" نىڭ ئۆچۈرۈلگەن تۈزىتىلگەن نەشرىنى راستىنلا كۆرەمسىز؟',
 'undelete-show-file-submit' => 'ھەئە',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'ئات بوشلۇقى',
@@ -2357,9 +2415,9 @@ $1',
 'contributions' => '{{$1:GENDER|ئىشلەتكۈچى}} تۆھپىسى',
 'contributions-title' => '$1 نىڭ ئىشلەتكۈچى تۆھپىسى',
 'mycontris' => 'تۆھپە',
-'contribsub2' => '$1 نىڭ تۆھپىسى ($2)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) ئۈچۈن',
 'nocontribs' => 'بۇ ئۆلچەمگە ماس كېلىدىغان ئۆزگەرتىش تېپىلمىدى.',
-'uctop' => '(ئۈستى)',
+'uctop' => '(نۆۋەتتىكى)',
 'month' => 'ئايدىن بۇيان (ياكى ئىلگىرى):',
 'year' => 'يىلدىن بۇيان (ياكى ئىلگىرى):',
 
@@ -2678,7 +2736,7 @@ $1',
 'allmessagesdefault' => 'كۆڭۈلدىكى ئۇچۇر تېكستى',
 'allmessagescurrent' => 'نۆۋەتتىكى ئۇچۇر تېكستى',
 'allmessagestext' => 'بۇ جايدا تەڭشىگىلى بولىدىغان ھەممە سىستېما كۆرۈنۈش ئۇچۇرلىرى كۆرسىتىلدى.
-ئەگەر ھەقىقىي يەرلەشتۈرۈلگەن MediaWiki غا تۆھپە قوشماقچى بولسىڭىز[//www.mediawiki.org/wiki/Localisation MediaWiki يەرلىكلەشتۈرۈش] ۋە [//translatewiki.net translatewiki.net] نى زىيارەت قىلىڭ.',
+ئەگەر ھەقىقىي يەرلەشتۈرۈلگەن MediaWiki غا تۆھپە قوشماقچى بولسىڭىز[https://www.mediawiki.org/wiki/Localisation MediaWiki يەرلىكلەشتۈرۈش] ۋە [//translatewiki.net translatewiki.net] نى زىيارەت قىلىڭ.',
 'allmessagesnotsupportedDB' => "بۇ بەتنى ئىشلەتكىلى بولمايدۇ، سەۋەبى '''\$wgUseDatabaseMessages''' چەكلەنگەن.",
 'allmessages-filter-legend' => 'سۈزگۈچ',
 'allmessages-filter' => 'ئىختىيارىچە سۈزگۈچ ھالىتى:',
@@ -2908,8 +2966,8 @@ $1',
 'pageinfo-article-id' => 'بەت ID',
 'pageinfo-language' => 'بەت مەزمۇن تىلى',
 'pageinfo-robot-policy' => 'ئىزدەش ماتور ھالىتى',
-'pageinfo-robot-index' => 'ئىندېكىسلاشچان',
-'pageinfo-robot-noindex' => 'ئىندېكىسلانمايدىغان',
+'pageinfo-robot-index' => 'چەكلەنمىگەن',
+'pageinfo-robot-noindex' => 'چەكلەنگەن',
 'pageinfo-views' => 'كۆرۈنۈش سانى',
 'pageinfo-watchers' => 'بەت كۆزەتكۈچىلەر سانى',
 'pageinfo-redirects-name' => 'بۇ بەتكە قايتا نىشانلايدۇ',
@@ -3032,6 +3090,16 @@ $1',
 'ago' => '$1 بۇرۇن',
 'just-now' => 'بايا',
 
+# Human-readable timestamps
+'monday-at' => 'دۈشەنبە $1 دە',
+'tuesday-at' => 'سەيشەنبە $1 دە',
+'wednesday-at' => 'چارشەنبە $1 دە',
+'thursday-at' => 'پەيشەنبە $1 دە',
+'friday-at' => 'جۈمە $1 دە',
+'saturday-at' => 'شەنبە $1 دە',
+'sunday-at' => 'يەكشەنبە $1 دە',
+'yesterday-at' => 'تۈنۈگۈن $1 دە',
+
 # Bad image list
 'bad_image_list' => 'تۆۋەندىكى فورماتتا يېزىڭ:
 
@@ -3279,7 +3347,7 @@ Variants for Chinese language
 'exif-compression-4' => 'CCITT نىڭ 4-گۇرۇپپا فاكس كودلىنىشى',
 
 'exif-copyrighted-true' => 'نەشر ھوقۇقى',
-'exif-copyrighted-false' => 'ئاممىۋى دائىرە',
+'exif-copyrighted-false' => 'نەشىر ھوقۇقى ھالىتى بېكىتىلمىگەن',
 
 'exif-unknowndate' => 'نامەلۇم چېسلا',
 
@@ -3485,7 +3553,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => 'بۇ ھۆججەتنى سىرتقى قوللىنىشچان پروگراممىدا تەھرىرلە',
-'edit-externally-help' => '( [//www.mediawiki.org/wiki/Manual:External_editors تەڭشەك قەدىمى] نى كۆرۈپ تەپسىلاتىنى چۈشىنىڭ)',
+'edit-externally-help' => '( [https://www.mediawiki.org/wiki/Manual:External_editors تەڭشەك قەدىمى] نى كۆرۈپ تەپسىلاتىنى چۈشىنىڭ)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ھەممىسى',
@@ -3669,8 +3737,9 @@ $5
 'version-hook-subscribedby' => 'ئىمزا قويغۇچى',
 'version-version' => '(نەشرى $1)',
 'version-license' => 'ئىجازەتنامە',
-'version-poweredby-credits' => "بۇ ۋىكىنى '''[//www.mediawiki.org/ MediaWiki]''' تېخنىكىلىق قوللايدۇ، نەشر ھوقۇقى © 2001-$1 $2",
+'version-poweredby-credits' => "بۇ ۋىكىنى '''[https://www.mediawiki.org/ MediaWiki]''' تېخنىكىلىق قوللايدۇ، نەشر ھوقۇقى © 2001-$1 $2",
 'version-poweredby-others' => 'باشقا',
+'version-poweredby-translators' => 'translatewiki.net تەرجىمانلىرى',
 'version-credits-summary' => 'تۆۋەندىكى كىشىنىڭ [[Special:Version|MediaWiki]] غا تۆھپە قوشقانلىقىغا رەھمەت ئېيتىمىز.',
 'version-license-info' => 'MediaWiki ئەركىن يۇمشاق دېتال؛ سىز ئەركىن يۇمشاق دېتال ۋەخپىسىنىڭ ئېلان قىلغان GNU ئاممىباپ ئاممىۋى ئىجازەت ماددىلىرىدىكى بەلگىمىلەرگە ئاساسەن، بۇ پىروگراممىنى قايتا تارقىتىپ ياكى ئۆزگەرتەلەيسىز؛ مەيلى سىز مەزكۇر ئىجازەتنامىنىڭ ئىككىنچى نەشرى ياكى (ئۆزىڭىز تاللىغان) خالىغان كۈندە تارقىتىلغان نەشرىنى ئاساس قىلسىڭىز بولۇۋېرىدۇ.
 
@@ -3684,6 +3753,11 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'version-entrypoints-header-entrypoint' => 'كىرىش نۇقتىسى',
 'version-entrypoints-header-url' => 'URL',
 
+# Special:Redirect
+'redirect-value' => 'قىممىتى:',
+'redirect-file' => 'ھۆججەت نامى',
+'redirect-not-exists' => 'قىممىتى تېپىلمىدى',
+
 # Special:FileDuplicateSearch
 'fileduplicatesearch' => 'تەكرار ھۆججەت ئىزدە',
 'fileduplicatesearch-summary' => 'چاچما (hash) قىممىتىگە ئاساسەن تەكرار ھۆججەت ئىزدە.',
@@ -3736,7 +3810,10 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'tags-tag' => 'خەتكۈچ ئاتى',
 'tags-display-header' => 'ئۆزگەرتىش تىزىملىكىدە كۆرسىتىلىش شەكلى',
 'tags-description-header' => 'مەناسىنىڭ تولۇق چۈشەندۈرۈلۈشى',
+'tags-active-header' => 'ئاكتىپمۇ؟',
 'tags-hitcount-header' => 'بەلگە سېلىنغان ئۆزگەرتىش',
+'tags-active-yes' => 'ھەئە',
+'tags-active-no' => 'ياق',
 'tags-edit' => 'ئۆزگەرتىش',
 'tags-hitcount' => '$1 {{PLURAL:$1|ئۆزگەرتىش|ئۆزگەرتىش}}',
 
@@ -3757,6 +3834,7 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'dberr-problems' => 'كەچۈرۈڭ! بۇ بېكەتتە تېخنىكىلىق قىيىنچىلىق كۆرۈلدى.',
 'dberr-again' => 'بىر قانچە مىنۇت كۈتۈپ ئاندىن قايتا يۈكلەڭ.',
 'dberr-info' => '(ساندان مۇلازىمىتىرىغا ئۇلىنالمىدى:  $1)',
+'dberr-info-hidden' => '(ساندان مۇلازىمېتىرىغا ئۇلىنالمىدى)',
 'dberr-usegoogle' => 'بۇ ۋاقىتتا Google ئىزدىگۈچتىن ئىزدەشنى سىناپ بېقىڭ.',
 'dberr-outofdate' => 'دىققەت ئۇلار ئىندىكېسلىغان مەزمۇن ئەڭ يېڭى بولماسلىقى مۇمكىن.',
 'dberr-cachederror' => 'بۇ ئىلتىماس قىلغان بەتنىڭ غەملەنگەن كۆپەيتىلمىسى، ئەڭ يېڭىسى بولماسلىقى مۇمكىن.',
@@ -3772,14 +3850,17 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'htmlform-submit' => 'تاپشۇر',
 'htmlform-reset' => 'ئۆزگەرتىشتىن يېنىۋال',
 'htmlform-selectorother-other' => 'باشقا',
+'htmlform-no' => 'ياق',
+'htmlform-yes' => 'ھەئە',
+'htmlform-chosen-placeholder' => 'بىرنى تاللاڭ',
 
 # SQLite database support
 'sqlite-has-fts' => '$1 پۈتۈن تېكست ئىزدەشنى قوللايدۇ',
 'sqlite-no-fts' => '$1 پۈتۈن تېكست ئىزدەشنى قوللىمايدۇ',
 
 # New logging system
-'logentry-delete-delete' => '$1 $3 بەتنى ئۆچۈرەتتى',
-'logentry-delete-restore' => '$1 $3 بەتنى ئەسلىگە قايتۇردى',
+'logentry-delete-delete' => '$1 $3 بەتنى {{GENDER:$2|ئۆچۈرىۋەتتى}}',
+'logentry-delete-restore' => '$1 $3 بەتنى {{GENDER:$2|ئەسلىگە قايتۇردى}}',
 'logentry-delete-event' => '$1 ئىشلەتكۈچى $3 دىكى {{PLURAL:$5|خاتىرە ھادىسە}}سىنىڭ كۆۈنۈشچانلىقىنى ئۆزگەرتتى: $4',
 'logentry-delete-revision' => '$1 ئىشلەتكۈچى $3 بەتتىكى {{PLURAL:$5|تۈزىتىلگەن نەشرى}}نىڭ كۆرۈنۈشچانلىقىنى ئۆزگەرتتى: $4',
 'logentry-delete-event-legacy' => '$3 دىكى خاتىرە كۆرۈنۈشچانلىقنى $1 ئۆزگەرتتى',
@@ -3885,4 +3966,15 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'duration-centuries' => '$1 {{PLURAL:$1|ئەسىر}}',
 'duration-millennia' => '$1 {{PLURAL:$1|مىڭ يىل}}',
 
+# Limit report
+'limitreport-cputime' => 'CPU ئىشلەتكەن ۋاقىت',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|سېكۇنت}}',
+'limitreport-walltime' => 'ئەمەلىي كەتكەن ۋاقىت',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|سېكۇنت}}',
+
+# Special:ExpandTemplates
+'expand_templates_output' => 'نەتىجە',
+'expand_templates_ok' => 'جەزملە',
+'expand_templates_preview' => 'ئالدىن كۆزەت',
+
 );
index d75a570..de8ce62 100644 (file)
@@ -120,7 +120,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'Помилковий_заголовок' ),
        'Blankpage'                 => array( 'Порожня_сторінка' ),
        'Block'                     => array( 'Заблокувати' ),
-       'Blockme'                   => array( 'Заблокуйте_мене' ),
        'Booksources'               => array( 'Джерела_книг' ),
        'BrokenRedirects'           => array( 'Розірвані_перенаправлення' ),
        'Categories'                => array( 'Категорії' ),
@@ -132,10 +131,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Створити_обліковий_запис' ),
        'Deadendpages'              => array( 'Сторінки_без_посилань' ),
        'DeletedContributions'      => array( 'Вилучений_внесок' ),
-       'Disambiguations'           => array( 'Неоднозначні_посилання' ),
        'DoubleRedirects'           => array( 'Подвійні_перенаправлення' ),
        'EditWatchlist'             => array( 'Редагувати_список_спостереження' ),
        'Emailuser'                 => array( 'Лист_користувачеві' ),
+       'ExpandTemplates'           => array( 'Розгортання_шаблонів' ),
        'Export'                    => array( 'Експорт' ),
        'Fewestrevisions'           => array( 'Найменшредаговані' ),
        'FileDuplicateSearch'       => array( 'Пошук_дублікатів_файлів' ),
@@ -158,6 +157,8 @@ $specialPageAliases = array(
        'MIMEsearch'                => array( 'Пошук_за_MIME' ),
        'Mostcategories'            => array( 'Найбільш_категоризовані' ),
        'Mostimages'                => array( 'Найуживаніші_файли' ),
+       'Mostinterwikis'            => array( 'Найбільше_інтервікі' ),
+       'Mostlinked'                => array( 'Найуживаніші_сторінки', 'Найбільше_посилань' ),
        'Mostlinkedcategories'      => array( 'Найуживаніші_категорії' ),
        'Mostlinkedtemplates'       => array( 'Найуживаніші_шаблони' ),
        'Mostrevisions'             => array( 'Найбільш_редаговані' ),
@@ -278,8 +279,8 @@ $magicWords = array(
        'img_center'                => array( '1', 'центр', 'center', 'centre' ),
        'img_framed'                => array( '1', 'обрамити', 'рамка', 'обрамить', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', 'безрамки', 'frameless' ),
-       'img_page'                  => array( '1', 'сторінка=$1', 'сторінка $1', 'страница=$1', 'страница $1', 'страница $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'зверхуправоруч', 'зверхуправоруч=$1', 'зверхуправоруч $1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа_$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'сторінка=$1', 'сторінка_$1', 'страница=$1', 'страница_$1', 'страница $1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'зверхуправоруч', 'зверхуправоруч=$1', 'зверхуправоруч_$1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа_$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ),
        'img_border'                => array( '1', 'межа', 'граница', 'border' ),
        'img_baseline'              => array( '1', 'основа', 'основание', 'baseline' ),
        'img_sub'                   => array( '1', 'під', 'под', 'sub' ),
@@ -361,6 +362,7 @@ $magicWords = array(
 );
 
 $linkTrail = '/^([a-zабвгґдеєжзиіїйклмнопрстуфхцчшщьєюяёъы“»]+)(.*)$/sDu';
+$linkPrefixCharset = '„«';
 
 $messages = array(
 # User preference toggles
@@ -504,8 +506,6 @@ $messages = array(
 'broken-file-category' => 'Сторінки, що посилаються на неіснуючі файли',
 'categoryviewer-pagedlinks' => '($1) ($2)',
 
-'linkprefix' => '/^(.*?)(„|«)$/sD',
-
 'about' => 'Про',
 'article' => 'Стаття',
 'newwindow' => '(відкривається в новому вікні)',
@@ -642,12 +642,10 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Отримано з $1',
 'youhavenewmessages' => 'Ви отримали $1 ($2).',
-'newmessageslink' => 'нові повідомлення',
-'newmessagesdifflink' => 'остання зміна',
 'youhavenewmessagesfromusers' => 'Ви отримали $1 від {{PLURAL:$3|іншого дописувача|$3 інших дописувачів}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ви отримали $1 від багатьох дописувачів ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлення|нові повідомлення|нових повідомлень}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|остання зміна|останні зміни|останніх змін}}',
+'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлення|999=нові повідомлення}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|остання зміна|999=останні зміни}}',
 'youhavenewmessagesmulti' => 'Ви отримали нові повідомлення на $1',
 'editsection' => 'ред.',
 'editold' => 'ред.',
@@ -775,7 +773,8 @@ $1',
 'invalidtitle-knownnamespace' => 'Неприйнятна назва у просторі імен «$2» і текстом «$3»',
 'invalidtitle-unknownnamespace' => 'Неправильний заголовок з невідомим номером простору імен ($1) і текстом: «$2»',
 'exception-nologin' => 'Не виконано вхід',
-'exception-nologin-text' => 'Ця сторінка чи дія потребує, щоб Ви ввійшли до цієї Вікі.',
+'exception-nologin-text' => 'Необхідно [[Special:Userlogin|увійти]], щоб мати доступ до цієї сторінки або дії.',
+'exception-nologin-text-manual' => 'Потрібно $1, щоб мати доступ до цієї сторінки або дії.',
 
 # Virus scanner
 'virus-badscanner' => "Помилка налаштування: невідомий сканер вірусів: ''$1''",
@@ -822,7 +821,7 @@ $1',
 'gotaccount' => "Ви вже зареєстровані? '''$1'''.",
 'gotaccountlink' => 'Увійдіть',
 'userlogin-resetlink' => 'Забули дані, потрібні для входу?',
-'userlogin-resetpassword-link' => 'СкинÑ\83Ñ\82и Ð¿Ð°Ñ\80олÑ\8c',
+'userlogin-resetpassword-link' => 'Ð\97абÑ\83ли Ð¿Ð°Ñ\80олÑ\8c?',
 'helplogin-url' => 'Help:Вхід до системи',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Допомога в реєстрації]]',
 'userlogin-loggedin' => 'Ви вже увійшли як {{GENDER:$1|$1}}.
@@ -878,7 +877,7 @@ $1',
 'passwordtooshort' => 'Ваш пароль закороткий, він має містити принаймні $1 {{PLURAL:$1|символ|символи|символів}}.',
 'password-name-match' => 'Уведений пароль має відрізнятися від імені користувача.',
 'password-login-forbidden' => 'Використання цього імені користувача і пароля заборонено.',
-'mailmypassword' => 'Ð\9dадÑ\96Ñ\81лаÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ пароль',
+'mailmypassword' => 'Ð\9fеÑ\80евÑ\81Ñ\82ановиÑ\82и пароль',
 'passwordremindertitle' => "Пам'ятка пароля користувача {{grammar:genitive|{{SITENAME}}}}",
 'passwordremindertext' => 'Хтось (можливо, ви, з IP-адреси $1) зробив запит
 на надсилання вам нового пароля користувача {{grammar:genitive|{{SITENAME}}}} ($4). Для користувача
@@ -894,15 +893,15 @@ $1',
 'passwordsent' => 'Новий пароль був надісланий на адресу електронної пошти, зазначену для "$1".
 Будь ласка, ввійдіть до системи після отримання пароля.',
 'blocked-mailpassword' => 'Редагування з вашої IP-адреси заборонено, заблокована також функція відновлення пароля.',
-'eauthentsent' => 'Ð\9dа Ð·Ð°Ð·Ð½Ð°Ñ\87енÑ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð½Ð°Ð´Ñ\96Ñ\81ланий Ð»Ð¸Ñ\81Ñ\82 Ñ\96з Ð·Ð°Ð¿Ð¸Ñ\82ом Ð½Ð° Ð¿Ñ\96дÑ\82веÑ\80дженнÑ\8f Ð·Ð¼Ñ\96ни Ð°Ð´Ñ\80еÑ\81и.
£ Ð»Ð¸Ñ\81Ñ\82Ñ\96 Ñ\82акож Ð¾Ð¿Ð¸Ñ\81анÑ\96 Ð´Ñ\96Ñ\97, Ñ\8fкÑ\96 Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ\82и Ð´Ð»Ñ\8f Ð¿Ñ\96дÑ\82веÑ\80дженнÑ\8f Ñ\82ого, Ñ\89о Ñ\86Ñ\8f Ð°Ð´Ñ\80еÑ\81а ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ñ\81пÑ\80авдÑ\96 належить вам.',
+'eauthentsent' => 'Ð\9dа Ð²ÐºÐ°Ð·Ð°Ð½Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð²Ñ\96дпÑ\80авлено Ð»Ð¸Ñ\81Ñ\82.
©Ð¾Ð± Ð¾Ñ\82Ñ\80имÑ\83ваÑ\82и Ð»Ð¸Ñ\81Ñ\82и Ð½Ð°Ð´Ð°Ð»Ñ\96, Ð´Ð¾Ñ\82Ñ\80имÑ\83йÑ\82еÑ\81Ñ\8c Ð²Ð¸ÐºÐ»Ð°Ð´ÐµÐ½Ð¸Ñ\85 Ñ\82ам Ñ\96нÑ\81Ñ\82Ñ\80Ñ\83кÑ\86Ñ\96й Ð´Ð»Ñ\8f Ð¿Ñ\96дÑ\82веÑ\80дженнÑ\8f Ñ\82ого, Ñ\89о Ñ\86Ñ\8f Ð°Ð´Ñ\80еÑ\81а належить вам.',
 'throttled-mailpassword' => 'Інструкція по відновленню паролю вже була вислана електронною поштою протягом {{PLURAL:$1|останньої години|останніх $1 годин}}.
 Для попередження зловживань дозволено надсилати тільки одну інструкцію за {{PLURAL:$1|годину|$1 години|$1 годин}}.',
 'mailerror' => 'Помилка при відправці пошти: $1',
 'acct_creation_throttle_hit' => 'Відвідувачі з вашої IP-адреси вже створили $1 {{PLURAL:$1|обліковий запис|облікових записи|облікових записів}} за останню добу, що є максимумом для цього відрізка часу.
 Таким чином, користувачі з цієї IP-адреси не можуть на цей момент створювати нових облікових записів.',
-'emailauthenticated' => 'Ð\90дÑ\80еÑ\81Ñ\83 Ð²Ð°Ñ\88оÑ\97 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð¿Ñ\96дÑ\82веÑ\80джено $2 Ð¾ $3.',
-'emailnotauthenticated' => 'Адресу вашої електронної пошти <strong>ще не підтверджено</strong>, функції вікі-двигуна роботи з ел. поштою відключені.',
+'emailauthenticated' => 'Ð\92аÑ\88Ñ\83 Ð°Ð´Ñ\80еÑ\81Ñ\83 ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\97 Ð¿Ð¾Ñ\88Ñ\82и Ð±Ñ\83ло Ð¿Ñ\96дÑ\82веÑ\80джено Ð½Ð°  $2  Ð¾  $3.',
+'emailnotauthenticated' => 'Адресу вашої електронної пошти ще не підтверджено. Жодна лист не буде надіслано для будь-якої з наступних функцій.',
 'noemailprefs' => 'Адресу електронної пошти не вказано, функції вікі роботи з ел. поштою відключені.',
 'emailconfirmlink' => 'Підтвердити адресу вашої електронної пошти',
 'invalidemailaddress' => 'Уведена адреса не може бути прийнята, бо вона не відповідає формату адрес електронної пошти.
@@ -951,7 +950,7 @@ $1',
 # Special:PasswordReset
 'passwordreset' => 'Скинути пароль',
 'passwordreset-text-one' => 'Заповніть цю форму для відновлення пароля.',
-'passwordreset-text-many' => '{{PLURAL:$1|Заповніть одне з полів для скидання пароля.}}',
+'passwordreset-text-many' => '{{PLURAL:$1|Заповніть одне з полів для отримання тимчасового паролю через електронну пошту.}}',
 'passwordreset-legend' => 'Перевстановити пароль',
 'passwordreset-disabled' => 'У цій вікі вимкнена можливість скидання пароля.',
 'passwordreset-emaildisabled' => 'Функції електронної пошти вимкнуто в цій вікі.',
@@ -1340,19 +1339,19 @@ $3 зазначив таку причину: ''$2''",
 крім випадків, коли були встановлені додаткові обмеження власниками сайту.",
 'revdelete-confirm' => 'Будь ласка, підтвердить, що ви справді бажаєте це здійснити, усвідомлюєте наслідки та робите це згідно з [[{{MediaWiki:Policy-url}}|правилами]].',
 'revdelete-suppress-text' => "Приховування може відбуватися '''лише''' в таких випадках:
-
-* Ð\9dепоÑ\82Ñ\80Ñ\96бна особиста інформація
+* Потенційно наклепницькі відомості
+* Ð\9dедоÑ\80еÑ\87на особиста інформація
 *: ''домашні адреси, номери телефонів, номер паспорта тощо.''",
-'revdelete-legend' => 'УÑ\81Ñ\82ановиÑ\82и Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f',
-'revdelete-hide-text' => 'Ð\9fÑ\80иÑ\85ований Ñ\82екÑ\81Ñ\82 Ñ\86Ñ\96Ñ\94Ñ\97 версії сторінки',
+'revdelete-legend' => 'Ð\92Ñ\81Ñ\82ановиÑ\82и Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f Ð²Ð¸Ð´Ð¸Ð¼Ð¾Ñ\81Ñ\82Ñ\96',
+'revdelete-hide-text' => 'ТекÑ\81Ñ\82 версії сторінки',
 'revdelete-hide-image' => 'Приховати вміст файлу',
 'revdelete-hide-name' => "Приховати дію та її об'єкт",
-'revdelete-hide-comment' => 'Ð\9fÑ\80иÑ\85оваÑ\82и ÐºÐ¾Ð¼ÐµÐ½Ñ\82аÑ\80',
-'revdelete-hide-user' => "Ð\9fÑ\80иÑ\85оваÑ\82и Ñ\96м'Ñ\8f Ð°Ð²Ñ\82оÑ\80а",
+'revdelete-hide-comment' => 'Ð\9aоменÑ\82аÑ\80 Ñ\80едагÑ\83ваннÑ\8f',
+'revdelete-hide-user' => "Ð\86м'Ñ\8f Ð°Ð²Ñ\82оÑ\80а/IP Ð°Ð´Ñ\80еÑ\81а",
 'revdelete-hide-restricted' => 'Приховати дані також і від адміністраторів',
 'revdelete-radio-same' => '(не змінювати)',
-'revdelete-radio-set' => 'Так',
-'revdelete-radio-unset' => 'Ð\9dÑ\96',
+'revdelete-radio-set' => 'Ð\92идимо',
+'revdelete-radio-unset' => 'Ð\9fÑ\80иÑ\85овано',
 'revdelete-suppress' => 'Приховувати дані також і від адміністраторів',
 'revdelete-unsuppress' => 'Зняти обмеження з відновлених версій',
 'revdelete-log' => 'Причина:',
@@ -1506,8 +1505,7 @@ $1",
 'preferences' => 'Налаштування',
 'mypreferences' => 'Налаштування',
 'prefs-edits' => 'Кількість редагувань:',
-'prefsnologin' => 'Ви не ввійшли в систему',
-'prefsnologintext' => 'Щоб змінити налаштування користувача, ви повинні <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ввійти до системи]</span>.',
+'prefsnologintext2' => 'Потрібно $1 для налаштування параметрів користувача.',
 'changepassword' => 'Змінити пароль',
 'prefs-skin' => 'Оформлення',
 'skin-preview' => 'Попередній перегляд',
@@ -1810,6 +1808,9 @@ $1",
 'recentchanges-label-minor' => 'Це незначна зміна',
 'recentchanges-label-bot' => 'Це редагування зроблене ботом',
 'recentchanges-label-unpatrolled' => 'Це редагування ще не було відпатрульоване',
+'recentchanges-label-plusminus' => 'Розмір сторінки змінився на таке число байтів',
+'recentchanges-legend-newpage' => '(див. також [[Special:NewPages|список нових сторінок]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "{{PLURAL:$1|Остання '''$1''' зміна|Останні '''$1''' зміни|Останні '''$1''' змін}} за '''$2''' {{PLURAL:$2|день|дні|днів}}, на час $5, $4.",
 'rcnotefrom' => 'Нижче відображені редагування з <strong>$2</strong> (до <strong>$1</strong>).',
 'rclistfrom' => 'Показати редагування починаючи з $1.',
@@ -2552,9 +2553,9 @@ $PAGEINTRO $NEWPAGE
 електронною поштою: $PAGEEDITOR_EMAIL
 через вікі: $PAGEEDITOR_WIKI
 
-Якщо ви не відвідаєте цю сторінку, то в подальшому не будете отримувати сповіщень про наступні редагування. Ви також можете вимкнути налаштування сповіщень для усіх сторінок зі списку спостереження.
+Якщо ви не відвідаєте цю сторінку під своїм обліковим записом, то в подальшому не будете отримувати сповіщень про наступні дії. Ви також можете вимкнути налаштування сповіщень для усіх сторінок зі списку спостереження.
 
-                        Ваша дружня система сповіщення {{grammar:genitive|{{SITENAME}}}}
+Ваша дружня система сповіщення {{grammar:genitive|{{SITENAME}}}}
 
 --
 Зміна налаштувань повідомлень електронною поштою
@@ -2807,9 +2808,11 @@ $1',
 'blockip' => 'Блокування',
 'blockip-title' => 'Блокування користувача',
 'blockip-legend' => 'Блокування користувача',
-'blockiptext' => "Використовуйте форму нижче, щоб заблокувати можливість редагування із зазначеної IP-адреси або або ім'я користувача.
-Це слід робити лише для попередження вандалізму і у відповідності до [[{{MediaWiki:Policy-url}}|правил]].
-Заповніть конкретну причину нижче (наприклад, вкажіть точні сторінки, на яких було зроблено акт вандалізму).",
+'blockiptext' => "Використовуйте форму нижче, щоб заблокувати можливість редагування зазначеній IP-адресі або користувачу.
+Це слід робити лише для запобігання порушенням і у відповідності до [[{{MediaWiki:Policy-url}}|правил]].
+Обов'язково заповніть причину нижче, бажано дати інформативну вичерпну інформацію (наприклад, послатися на конкретні правила, дати посилання на редагування користувача, які призвели до блокування). Можна конкретизувати причину блокування на сторінці обговорення користувача.
+* Якщо ви блокуєте обліковий запис бота, переконайтеся, що ви вимкнули автоблокування (для запобігання автоматичного блокування облікових записів власника бота або інших ботів).
+* Зверніть увагу, що IP-адреси у більшості випадків не варто блокувати на більший за декілька днів термін, щоб під блокування не підпали інші користувачі з таким самим IP. Винятки — частий довготривалий вандалізм.",
 'ipadressorusername' => "IP-адреса або ім'я користувача:",
 'ipbexpiry' => 'Термін:',
 'ipbreason' => 'Причина:',
@@ -3066,7 +3069,7 @@ $1',
 'allmessagesdefault' => 'Стандартний текст',
 'allmessagescurrent' => 'Поточний текст',
 'allmessagestext' => 'Це список усіх системних повідомлень, які доступні в просторі назв «MediaWiki».
-Будь ласка, відвідайте [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] і [//translatewiki.net translatewiki.net], якщо ви хочете зробити внесок до спільної локалізації MediaWiki.',
+Будь ласка, відвідайте [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] і [//translatewiki.net translatewiki.net], якщо ви хочете зробити внесок до спільної локалізації MediaWiki.',
 'allmessagesnotsupportedDB' => "Ця сторінка не може використовуватися, оскільки вимкнена опція '''\$wgUseDatabaseMessages'''.",
 'allmessages-filter-legend' => 'Фільтр',
 'allmessages-filter' => 'Фільтр за внесеними змінами:',
@@ -3227,7 +3230,7 @@ $2',
 'tooltip-undo' => 'Прибрати внесені зміни і показати попередній перегляд. Дозволяє зазначити причину скасування.',
 'tooltip-preferences-save' => 'Зберегти налаштування',
 'tooltip-summary' => 'Введіть короткий опис',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/** Розміщений тут CSS буде застосовуватися до всіх тем оформлення */',
@@ -3278,6 +3281,8 @@ The wiki server can't provide data in a format your client can read.",
 'spam_reverting' => 'Відкинути до останньої версії, що не містить посилання на $1',
 'spam_blanking' => 'Всі версії містять посилання на $1, очистка',
 'spam_deleting' => 'Все версії, що містили посилання на $1, вилучаються',
+'simpleantispam-label' => "Перевірка на спам.
+'''НЕ''' заповнюйте це!",
 
 # Info page
 'pageinfo-title' => 'Інформація про " $1 "',
@@ -3291,6 +3296,7 @@ The wiki server can't provide data in a format your client can read.",
 'pageinfo-length' => 'Довжина сторінки (в байтах)',
 'pageinfo-article-id' => 'ID сторінки',
 'pageinfo-language' => 'Мова вмісту сторінки',
+'pageinfo-content-model' => 'Модель вмісту сторінки',
 'pageinfo-robot-policy' => 'Індексація пошуковими системами',
 'pageinfo-robot-index' => 'Індексується',
 'pageinfo-robot-noindex' => 'Не індексується',
@@ -3939,7 +3945,7 @@ $8',
 
 # External editor support
 'edit-externally' => 'Редагувати цей файл, використовуючи зовнішню програму',
-'edit-externally-help' => '(Подробиці див. на сторінці [//www.mediawiki.org/wiki/Manual:External_editors Інструкції з установки зовнішніх редакторів])',
+'edit-externally-help' => '(Подробиці див. на сторінці [https://www.mediawiki.org/wiki/Manual:External_editors Інструкції з установки зовнішніх редакторів])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'всі',
@@ -4046,6 +4052,7 @@ $5
 'ellipsis' => '...',
 'percent' => '$1%',
 'parentheses' => '($1)',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← попередня сторінка',
@@ -4197,7 +4204,7 @@ $5
 'version-version' => '(Версія $1)',
 'version-svn-revision' => '(r$2)',
 'version-license' => 'Ліцензія',
-'version-poweredby-credits' => "Ця Вікі працює на системі управління вмістом '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ця Вікі працює на системі управління вмістом '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'інші',
 'version-poweredby-translators' => 'перекладачі translatewiki.net',
 'version-credits-summary' => 'Нам хотілося б відзначити наступних осіб, що зробили внесок у [[Special:Version|MediaWiki]].',
@@ -4218,7 +4225,7 @@ MediaWiki поширюється в надії, що вона буде кори
 # Special:Redirect
 'redirect' => 'Перенаправлення за файлом, користувачем або ID версії',
 'redirect-legend' => 'Перенаправити на файл чи сторінку',
-'redirect-summary' => 'Ця спеціальна сторінка перенаправляє на файл (за поданою назвою файлу), сторінку (за поданим ID версії) або сторінку користувача (за поданим числовим ID користувача).',
+'redirect-summary' => 'Ця спеціальна сторінка перенаправляє на файл (за поданою назвою файлу), сторінку (за поданим ID версії) або сторінку користувача (за поданим числовим ID користувача). Використання: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]] або [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Перейти',
 'redirect-lookup' => 'Шукати:',
 'redirect-value' => 'Значення:',
@@ -4240,10 +4247,9 @@ MediaWiki поширюється в надії, що вона буде кори
 
 # Special:SpecialPages
 'specialpages' => 'Спеціальні сторінки',
-'specialpages-note' => '----
-* Звичайні службові сторінки
-* <span class="mw-specialpagerestricted">Сторінки з обмеженим доступом.</span>
-* <span class="mw-specialpagecached">Кешовані сторінки (можуть бути застарілими).</span>',
+'specialpages-note-top' => 'Легенда',
+'specialpages-note' => '* Звичайні службові сторінки
+* <span class="mw-specialpagerestricted">Сторінки з обмеженим доступом.</span>',
 'specialpages-group-maintenance' => 'Технічні звіти',
 'specialpages-group-other' => 'Інші',
 'specialpages-group-login' => 'Вхід до системи / реєстрація',
@@ -4456,4 +4462,21 @@ MediaWiki поширюється в надії, що вона буде кори
 'limitreport-expansiondepth' => 'Найвища глибина розширення',
 'limitreport-expensivefunctioncount' => 'Число дорогої функції аналізатора',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Розгортання шаблонів',
+'expand_templates_intro' => 'Ця спеціальна сторінка перетворює текст, рекурсивно розгортаючи всі шаблони в ньому.
+Також розгортаються всі функції парсера
+<nowiki>{{</nowiki>#language:...}} і змінні типу
+<nowiki>{{</nowiki>CURRENTDAY}}.
+Фактично, усе всередині подвійних фігурних дужок.',
+'expand_templates_title' => 'Заголовок сторінки для {{FULLPAGENAME}} тощо:',
+'expand_templates_input' => 'Вхідний текст:',
+'expand_templates_output' => 'Результат',
+'expand_templates_xml_output' => 'XML-вивід',
+'expand_templates_ok' => 'Гаразд',
+'expand_templates_remove_comments' => 'Вилучити коментарі',
+'expand_templates_remove_nowiki' => 'Ігнорувати теги <nowiki> в результаті',
+'expand_templates_generate_xml' => 'Показати дерево аналізу XML',
+'expand_templates_preview' => 'Попередній перегляд',
+
 );
index cc5d0f7..d59a34d 100644 (file)
@@ -22,6 +22,7 @@
  * @author زكريا
  * @author سمرقندی
  * @author محبوب عالم
+ * @author පසිඳු කාවින්ද
  */
 
 $fallback8bitEncoding = 'windows-1256';
@@ -63,7 +64,6 @@ $specialPageAliases = array(
        'Badtitle'                  => array( 'خراب_عنوان' ),
        'Blankpage'                 => array( 'خالی_صفحہ' ),
        'Block'                     => array( 'پابندی', 'دستور_شبکی_پابندی', 'پابندی_بر_صارف' ),
-       'Blockme'                   => array( 'میری_پابندی' ),
        'Booksources'               => array( 'کتابی_وسائل' ),
        'BrokenRedirects'           => array( 'شکستہ_رجوع_مکررات' ),
        'Categories'                => array( 'زمرہ_جات' ),
@@ -75,7 +75,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'تخلیق_کھاتہ' ),
        'Deadendpages'              => array( 'مردہ_صفحات' ),
        'DeletedContributions'      => array( 'حذف_شدہ_شراکتیں' ),
-       'Disambiguations'           => array( 'ضد_ابہام_صفحات' ),
        'DoubleRedirects'           => array( 'دوہرے_رجوع_مکررات' ),
        'EditWatchlist'             => array( 'ترمیم_زیر_نظر' ),
        'Emailuser'                 => array( 'صارف_ڈاک' ),
@@ -417,8 +416,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => '‘‘$1’’ مستعادہ منجانب',
 'youhavenewmessages' => 'آپکے لیۓ ایک $1 ہے۔ ($2)',
-'newmessageslink' => 'نئے پیغامات',
-'newmessagesdifflink' => 'تـجـدیـد مـاقـبل آخـر سے فـرق',
 'newmessagesdifflinkplural' => 'آخری {{PLURAL:$1|تبدیلی|تبدیلیاں}}',
 'youhavenewmessagesmulti' => 'ء$1 پر آپ کیلئے نئے پیغامات ہیں',
 'editsection' => 'ترمیم',
@@ -958,8 +955,6 @@ $1",
 'preferences' => 'ترجیحات',
 'mypreferences' => 'میری ترجیہات',
 'prefs-edits' => 'تدوینات کی تعداد:',
-'prefsnologin' => 'نا داخل شدہ حالت',
-'prefsnologintext' => 'ترجیحات ترتیب دینے کیلئے <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} داخل نوشتہ]</span> ہونا لازمی ہے.',
 'changepassword' => 'کلمۂ شناخت تبدیل کریں',
 'prefs-skin' => 'جِلد',
 'skin-preview' => 'پیش منظر',
@@ -1644,4 +1639,12 @@ $1 × $2 عکصر (پکسلز)، حجم ملف: $3، MIME قسم: $4',
 # Search suggestions
 'searchsuggest-search' => 'تلاش',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'سانچے کو وسیع کریں',
+'expand_templates_input' => 'ان پٹ متن:',
+'expand_templates_output' => 'نتیجہ',
+'expand_templates_ok' => 'ٹھیک ہے',
+'expand_templates_remove_comments' => 'تبصرے حذف کریں',
+'expand_templates_preview' => 'پیش نظارہ',
+
 );
index e8746b3..608d502 100644 (file)
@@ -107,6 +107,7 @@ $magicWords = array(
 );
 
 $linkTrail = '/^([a-zʻʼ“»]+)(.*)$/sDu';
+$linkPrefixCharset = 'a-zA-Z\\x80-\\xffʻʼ«„';
 
 $messages = array(
 # User preference toggles
@@ -236,8 +237,6 @@ $messages = array(
 'noindex-category' => 'Indekslanmaydigan sahifalar',
 'broken-file-category' => 'Ishlamaydigan fayl havolalari bor sahifalar',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xffʻʼ«„]+)$/sDu',
-
 'about' => 'Haqida',
 'article' => 'Sahifa',
 'newwindow' => '(yangi oynada ochiladi)',
@@ -372,11 +371,9 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => ' "$1" dan olindi',
 'youhavenewmessages' => 'Sizga $1 keldi ($2).',
-'newmessageslink' => 'yangi xabarlar',
-'newmessagesdifflink' => 'soʻnggi oʻzgarish',
 'youhavenewmessagesfromusers' => 'Siz {{PLURAL:$3|boshqa foydalanuvchidan|$3 ta foydalanuvchidan}} $1 oldingiz ($2).',
 'youhavenewmessagesmanyusers' => "Siz ko'p foydalanuvchilardan $1 oldingiz ($2).",
-'newmessageslinkplural' => '{{PLURAL:$1|yangi xabar|yangi xabarlar}}',
+'newmessageslinkplural' => '{{PLURAL:$1|yangi xabar|999=yangi xabarlar}}',
 'newmessagesdifflinkplural' => 'oxirgi {{PLURAL:$1|oʻzgarish|oʻzgarishlar}}',
 'youhavenewmessagesmulti' => 'Siz $1ga yangi xat oldingiz',
 'editsection' => 'tahrirlash',
@@ -801,7 +798,6 @@ Bu yerda: (joriy) = hozirgi koʻrinish bilan farq,
 'preferences' => 'Moslamalar',
 'mypreferences' => 'Moslamalarim',
 'prefs-edits' => 'Tahrirlar soni:',
-'prefsnologin' => "Siz tizimda o'zingizni tanitmadingiz",
 'changepassword' => 'Maxfiy soʻzni oʻzgartirish',
 'prefs-skin' => 'Tashqi ko‘rinishi',
 'skin-preview' => 'Ko‘rib chiqish',
@@ -1658,7 +1654,7 @@ Umumiy omborda [[:$1]] mavjud. Faylning bu nomga qayta nomlanishi faylning umumi
 
 # External editor support
 'edit-externally' => 'Bu faylni tashqi dasturiy ilovalar yordamida tahrirla',
-'edit-externally-help' => "(Batafsil ma'lumotlar uchun [//www.mediawiki.org/wiki/Manual:External_editors bu yerga] qarang)",
+'edit-externally-help' => "(Batafsil ma'lumotlar uchun [https://www.mediawiki.org/wiki/Manual:External_editors bu yerga] qarang)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'Barcha',
index cd96f55..81af497 100644 (file)
@@ -61,12 +61,12 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'UtentiAtivi' ),
        'Allmessages'               => array( 'Messagi' ),
+       'AllMyUploads'              => array( 'TutiIMeCaricamenti' ),
        'Allpages'                  => array( 'TuteLePagine' ),
        'Ancientpages'              => array( 'PagineMancoNove' ),
        'Badtitle'                  => array( 'TitoloSbalià' ),
        'Blankpage'                 => array( 'PaginaVoda' ),
        'Block'                     => array( 'Bloca' ),
-       'Blockme'                   => array( 'BlocaProxy' ),
        'Booksources'               => array( 'SercaISBN' ),
        'BrokenRedirects'           => array( 'RimandiSbalià' ),
        'Categories'                => array( 'Categorie' ),
@@ -78,10 +78,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'CreaUtente' ),
        'Deadendpages'              => array( 'PagineSensaUscita' ),
        'DeletedContributions'      => array( 'ContributiScancelà' ),
-       'Disambiguations'           => array( 'Disanbiguassion' ),
        'DoubleRedirects'           => array( 'DópiRimandi' ),
        'EditWatchlist'             => array( 'CanbiaTegnuiDeOcio' ),
        'Emailuser'                 => array( 'MandaEMail' ),
+       'ExpandTemplates'           => array( 'EspandiModèi' ),
        'Export'                    => array( 'Esporta' ),
        'Fewestrevisions'           => array( 'PagineConMancoRevision' ),
        'FileDuplicateSearch'       => array( 'SercaDopioniDeiFile' ),
@@ -431,8 +431,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Cavà fora da "$1"',
 'youhavenewmessages' => 'Te ghè $1 ($2).',
-'newmessageslink' => 'dei mesagi novi',
-'newmessagesdifflink' => 'ultimo canbiamento',
 'youhavenewmessagesfromusers' => "Te ghè $1 da {{PLURAL:$3|n'altro utente|$3 utenti}} ($2).",
 'youhavenewmessagesmanyusers' => 'Te ghè $1 da vari utenti ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|un messagio novo|dei messagi novi}}',
@@ -1235,8 +1233,6 @@ Prova a métarghe \"all:\" davanti al testo che te serchi par vardar in tuti i n
 'preferences' => 'Prefarense',
 'mypreferences' => 'Prefarense',
 'prefs-edits' => 'Nùmaro de modifiche:',
-'prefsnologin' => 'No te ghè eseguìo el login',
-'prefsnologintext' => 'Te ghè da aver eseguìo el <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} login]</span> par poder personalixare le to preferense.',
 'changepassword' => 'Cànbia ła password',
 'prefs-skin' => 'Aspeto grafico',
 'skin-preview' => 'Anteprima',
@@ -1513,6 +1509,7 @@ Co qualcheduni te scrivarà, nol vedarà mia el to indirizo.',
 'recentchanges-label-minor' => 'Sto qua el xe un canbiamento picenin',
 'recentchanges-label-bot' => 'Sta modifica el la ga fata un bot',
 'recentchanges-label-unpatrolled' => 'Sta modifica no la xe stà gnancora verificà',
+'recentchanges-legend-newpage' => '$1 - pagina nova',
 'rcnote' => "Qua soto se vede {{PLURAL:$1|l'ultimo canbiamento|i ultimi '''$1''' canbiamenti}} {{PLURAL:$2|in te l'ultimo zorno|in tei ultimi '''$2''' zorni}}, fin a le $5 del $4.",
 'rcnotefrom' => "Qui di seguito sono elencate le modifiche da '''$2''' (fino a '''$1''').",
 'rclistfrom' => 'Fà védar i canbiamenti fati dal $1',
@@ -2715,7 +2712,7 @@ Nel secondo caso te poli anca doparar un colegamento, par esenpio [[{{#Special:E
 'allmessagesdefault' => 'Testo predefinìo',
 'allmessagescurrent' => 'Testo come che el xe desso',
 'allmessagestext' => "Sta quà l'è na lista de tuti i messagi disponibili nel namespace MediaWiki.
-Par piaser visita [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se te voli jutarne par la traduzion del software MediaWiki ne le varie lengue.",
+Par piaser visita [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//translatewiki.net translatewiki.net] se te voli jutarne par la traduzion del software MediaWiki ne le varie lengue.",
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:Allmessages''' no'l xè supportà parché '''\$wgUseDatabaseMessages''' no'l xè ativo.",
 'allmessages-filter-legend' => 'Filtro',
 'allmessages-filter' => 'Filtra par stato de personalixassion:',
@@ -2902,6 +2899,8 @@ Questo xe probabilmente dovùo a la presenza de un colegamento a un sito foresto
 'spam_reverting' => "Ripristinà l'ultima version priva de colegamenti a $1",
 'spam_blanking' => 'Pàxena svodà, tute łe version le contegneva cołegamenti a $1',
 'spam_deleting' => 'Pàjina scansełà, tute łe version łe contegneva ligamenti a $1',
+'simpleantispam-label' => "Controlo anti spam.
+'''NO STA''' scrivar gnente qua de soto!",
 
 # Info page
 'pageinfo-title' => 'Informasion par "$1"',
@@ -3468,7 +3467,7 @@ I colegamenti dopo, su la stessa riga, i xe considerai come ecession (cioè, pag
 
 # External editor support
 'edit-externally' => 'Modifega sto file usando on programa foresto',
-'edit-externally-help' => '(Par saverghene de pì consultare łe [//www.mediawiki.org/wiki/Manual:External_editors istrusion])',
+'edit-externally-help' => '(Par saverghene de pì consultare łe [https://www.mediawiki.org/wiki/Manual:External_editors istrusion])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tute',
@@ -3644,7 +3643,7 @@ Nota che te pol anca [[Special:EditWatchlist|modificar la lista con l'interfacia
 'version-hook-subscribedby' => 'Sotoscrizioni',
 'version-version' => '(Version $1)',
 'version-license' => 'Licensa',
-'version-poweredby-credits' => "Sta wiki la va con '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Sta wiki la va con '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'altri',
 'version-poweredby-translators' => 'tradutori de translatewiki.net',
 'version-credits-summary' => "Semo contenti de riconosare łe seguenti persone p' 'ver contribuio a [[Special:Version|MediaWiki]].",
@@ -3685,8 +3684,7 @@ Insieme co sto programa te dovaressi 'ver ricevùo na copia de la Licensa Public
 
 # Special:SpecialPages
 'specialpages' => 'Pagine speciali',
-'specialpages-note' => '----
-* Pàjine speciałi normałi.
+'specialpages-note' => '* Pàjine speciałi normałi.
 * <span class="mw-specialpagerestricted">Pàjine speciałi a aceso limità.</span>',
 'specialpages-group-maintenance' => 'Resoconti de manutenzion',
 'specialpages-group-other' => 'Altre pagine speciali',
@@ -3880,4 +3878,17 @@ Insieme co sto programa te dovaressi 'ver ricevùo na copia de la Licensa Public
 # Image rotation
 'rotate-comment' => 'Imagine girà de $1 {{PLURAL:$1|grado|gradi}} in senso orario',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Espansion dei template',
+'expand_templates_intro' => 'Sta pagina speciale la elabora un testo espandendo tuti i template presenti. La calcola inoltre el risultato de le funzion suportàe dal parser come <nowiki>{{</nowiki>#language:...}} e de le variabili de sistema quali <nowiki>{{</nowiki>CURRENTDAY}}, overo in pratica tuto quel che se cata tra dopie parentesi grafe. La funsiona riciamando le oportune funzion del parser de MediaWiki.',
+'expand_templates_title' => 'Contesto (par {{FULLPAGENAME}} ecc.):',
+'expand_templates_input' => 'Testo da espàndar:',
+'expand_templates_output' => 'Risultato',
+'expand_templates_xml_output' => 'Output in formato XML',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Ignora i comenti',
+'expand_templates_remove_nowiki' => 'Cava i tag <nowiki> dal risultato',
+'expand_templates_generate_xml' => 'Mostra àlbaro sintàtico XML',
+'expand_templates_preview' => 'Anteprima',
+
 );
index a724c1e..45a1497 100644 (file)
@@ -98,9 +98,9 @@ $messages = array(
 'tog-usenewrc' => 'Kävutagat paremboitud tantoižed toižetused (pidab otta radho JavaScript)',
 'tog-numberheadings' => 'Nomeruida avtomatižikš pälkirjutesed',
 'tog-showtoolbar' => "Ozutada azegiden üläpanel' redaktiruindan aigan (JavaScript)",
-'tog-editondblclick' => 'Redaktiruida lehtpoled kaksitadud plokul (JavaScript)',
+'tog-editondblclick' => 'Redaktiruida lehtpoled kaksitadud plokul',
 'tog-editsection' => 'Ozutada "Redaktiruida"-kosketuz kaikuččen sekcijan täht',
-'tog-editsectiononrightclick' => 'Redaktiruida sekcijad hiren oiktal plokul pälkirjutesele (JavaScript)',
+'tog-editsectiononrightclick' => 'Redaktiruida sekcijad hiren oiktal plokul pälkirjutesele',
 'tog-showtoc' => 'Ozutada südäiolend (lehtpoled, kudambil om enamba, mi 3 pälkirjutest)',
 'tog-rememberpassword' => 'Muštta minun kävutajan nimi neciš kompjuteras (enintään $1 {{PLURAL:$1|päivä|päivää}})',
 'tog-watchcreations' => 'Ližata kaik minai sätud lehtpoled minun kaclendkirjuteshe',
@@ -193,6 +193,18 @@ $messages = array(
 'oct' => 'reduku',
 'nov' => 'kül’mku',
 'dec' => 'tal’vku',
+'january-date' => '$1. viluku',
+'february-date' => '$1. uhoku',
+'march-date' => "$1. keväz'ku",
+'april-date' => '$1. sulaku',
+'may-date' => '$1. semendku',
+'june-date' => '$1. kezaku',
+'july-date' => '$1. heinku',
+'august-date' => '$1. eloku',
+'september-date' => "$1. sügüz'ku",
+'october-date' => '$1. reduku',
+'november-date' => "$1. kül'mku",
+'december-date' => "$1. tal'vku",
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Kategorii|Kategorijad}}',
@@ -218,7 +230,7 @@ $messages = array(
 'newwindow' => '(avaidase udes iknas)',
 'cancel' => 'Heitta pätand',
 'moredotdotdot' => 'Edeleze...',
-'mypage' => "Minun lehtpol'",
+'mypage' => "Lehtpol'",
 'mytalk' => 'Lodud',
 'anontalk' => 'Lodud neciš IP-adresas',
 'navigation' => 'Navigacii',
@@ -251,6 +263,7 @@ $messages = array(
 'namespaces' => 'Nimiavaruded',
 'variants' => 'Variantad',
 
+'navigation-heading' => 'Navigacii',
 'errorpagetitle' => 'Petuz',
 'returnto' => 'Pörttas lehtpolele $1.',
 'tagline' => '{{SITENAME}}',
@@ -288,7 +301,7 @@ $messages = array(
 'articlepage' => "Kacu südäimišton lehtpol'",
 'talk' => 'Diskussii',
 'views' => 'Kacundad',
-'toolbox' => 'Azegišt',
+'toolbox' => 'Instrumentad',
 'userpage' => "Kacu kävutajan lehtpol'",
 'projectpage' => "Kacu projektan lehtpol'",
 'imagepage' => "Kacu fajlan lehtpol'",
@@ -346,8 +359,6 @@ Kacu [[Special:Version|informacii kävutadud versijoiš]].',
 'ok' => 'Ka',
 'retrievedfrom' => 'Purde - "$1"',
 'youhavenewmessages' => 'Tö sat $1 ($2).',
-'newmessageslink' => 'uded tedotused',
-'newmessagesdifflink' => "jäl'gmäine toižetuz",
 'youhavenewmessagesmulti' => 'Teil om uzid tedotusid $1-lehtpolel',
 'editsection' => 'redaktiruida',
 'editold' => 'redaktiruida',
@@ -399,6 +410,7 @@ Kc. [[Special:SpecialPages|specialižiden lehtpoliden nimikirj]].",
 # General errors
 'error' => 'Petuz',
 'databaseerror' => 'Andmusiden bazan petuz',
+'databaseerror-error' => 'Petuz: $1',
 'laggedslavemode' => "Varutuz: voib olda, lehtpolen versijal ei ole jäl'gmäižid ližadusid.",
 'readonly' => 'Andmusiden baz om luklostadud',
 'enterlockreason' => 'Kirjutagat sü da pandud blokiruindan strok',
@@ -463,10 +475,18 @@ Sü om "\'\'$2\'\'".',
 
 Sab jatkta rad {{SITENAME}}-saital anonimižikš, vai <span class='plainlinks'>[$1 kirjutagatoiš udes]</span> sil-žo vai toižel kävutajan nimel.
 Otkat sil'mnägubale, miše erasid lehtpolid ozutaškatas mugažo, kut i edel teiden lähtendad sistemaspäi. Miše vajehtada niiden nägu, puhtastagat teiden kaclimen keš.",
+'welcomeuser' => 'Tulgat tervhin, $1!',
 'yourname' => 'Kävutajan nimi:',
+'userlogin-yourname' => 'Kävutajannimi',
+'createacct-another-username-ph' => 'Kirjutagat kävutajannimi',
 'yourpassword' => 'Peitsana:',
+'userlogin-yourpassword' => 'Peitsana',
+'createacct-yourpassword-ph' => 'Kirjutagat peitsana',
 'yourpasswordagain' => 'Kirjutagat peitsana udes:',
+'createacct-yourpasswordagain' => 'Peitsanan vahvištoituz',
+'createacct-yourpasswordagain-ph' => 'Kirjutagat peitsana toškerdan',
 'remembermypassword' => 'Panda muštho minun tulendandmused neciš kompjuteras (enintään $1 {{PLURAL:$1|päivä|päivää}})',
+'userlogin-remembermypassword' => 'Jäda sistemha',
 'yourdomainname' => 'Teiden domen:',
 'externaldberror' => 'Ozaižihe petuz autentifikacijan, kudamb tehtihe andmusiden irdbazan turbiš, aigan, vai teile ei ulotu oiktusid toižetada ičetoi irdregistracijad.',
 'login' => 'Kirjutadas sistemha',
@@ -485,6 +505,12 @@ Otkat sil'mnägubale, miše erasid lehtpolid ozutaškatas mugažo, kut i edel te
 'userlogin-resetlink' => 'Unohtid-ik andmused tulendan täht?',
 'createaccountmail' => 'e-počtaiči',
 'createaccountreason' => 'Sü:',
+'createacct-reason' => 'Sü',
+'createacct-reason-ph' => 'Mikš sädad kävutajanprofilid?',
+'createacct-captcha' => 'Varuitomuden kodvind',
+'createacct-imgcaptcha-ph' => 'Kirjutagat tekst pälpäi',
+'createacct-submit' => "Säta kävutajanprofil'",
+'createacct-another-submit' => "Säta toine kävutajanprofil'",
 'badretype' => 'Teil kirjutadud peitsanad ei kožugoi toine toižhe.',
 'userexists' => 'Kirjutadud kävutajan nimi om jo kävutamižes.
 Olgat hüväd, valikat toine kävutajan nimi.',
@@ -576,6 +602,9 @@ Aigaline peitsana: $2',
 'changeemail-submit' => 'Toižetada e-počtan adres',
 'changeemail-cancel' => 'Heitta',
 
+# Special:ResetTokens
+'resettokens-tokens' => 'Tokenad:',
+
 # Edit page toolbar
 'bold_sample' => 'Lihavoitud tekst',
 'bold_tip' => 'Lihavoitud tekst',
@@ -966,8 +995,6 @@ Otkat sil'mnägubale üks-se, miše {{SITENAME}}-saitan sädäimišt voib olda v
 'preferences' => 'Järgendused',
 'mypreferences' => 'Järgendused',
 'prefs-edits' => 'Redaktiruindoiden lugu:',
-'prefsnologin' => 'Tö et olgoi kirjutanus sistemha.',
-'prefsnologintext' => 'Teile pidab <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kirjutadas sistemha]</span>, miše toižetada järgendusid.',
 'changepassword' => 'Peitsanan toižetuz',
 'prefs-skin' => 'Irdnägu',
 'skin-preview' => 'Ezikaclend',
@@ -1048,7 +1075,7 @@ Kodvgat HTML-virgad.',
 Pidab tehta se $1 {{PLURAL:$1|simvolaspäi|simvoloišpäi}}.",
 'yourgender' => 'Sugu:',
 'gender-unknown' => 'Ei ole ozutadud',
-'gender-male' => 'Mez’',
+'gender-male' => "Mez'",
 'gender-female' => 'Naine',
 'prefs-help-gender' => 'Opcionaline: kävutadas likutimen erasiš tedotusiš, miše ozutada kävutajan sugu oikti. Nece informacii om avoin.',
 'email' => 'E-počt',
@@ -1063,6 +1090,7 @@ Ku tö kirjutat sen, nece nimi kävutadas, miše ozutada lehtpolen toižetajad.'
 'prefs-dateformat' => 'Datan format',
 'prefs-timeoffset' => 'Aigan sirdand',
 'prefs-advancedediting' => 'Ližaopcijad',
+'prefs-preview' => 'Ezikacund',
 'prefs-advancedrc' => 'Ližaopcijad',
 'prefs-advancedrendering' => 'Ližaopcijad',
 'prefs-advancedsearchoptions' => 'Ližaopcijad',
@@ -1070,6 +1098,7 @@ Ku tö kirjutat sen, nece nimi kävutadas, miše ozutada lehtpolen toižetajad.'
 'prefs-displayrc' => 'Nägun opcijad',
 'prefs-displaysearchoptions' => 'Nägun opcijad',
 'prefs-displaywatchlist' => 'Nägun opcijad',
+'prefs-tokenwatchlist' => 'Token',
 'prefs-diffs' => 'Erod',
 
 # User preference: email validation using jQuery
@@ -1220,6 +1249,7 @@ Ku tö kirjutat sen, nece nimi kävutadas, miše ozutada lehtpolen toižetajad.'
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|toižetuz|toižetust}}',
+'enhancedrc-history' => 'istorii',
 'recentchanges' => 'Tantoižed toižetused',
 'recentchanges-legend' => 'Tantoižiden toižetusiden järgendused',
 'recentchanges-summary' => 'Necil lehtpolil om tantoižid toižetusid {{SITENAME}}-saital.',
@@ -1228,6 +1258,7 @@ Ku tö kirjutat sen, nece nimi kävutadas, miše ozutada lehtpolen toižetajad.'
 'recentchanges-label-minor' => 'Nece redakcii om penikaine',
 'recentchanges-label-bot' => 'Necen redakcijan tegi bot',
 'recentchanges-label-unpatrolled' => 'Necidä redakcijad ei völ patruliruinugoi',
+'recentchanges-legend-newpage' => "$1 - uz' lehtpol'",
 'rcnote' => "Alahan om ozutadud {{PLURAL:$1| '''1''' toižetuz|'''$1''' toižetust}} {{PLURAL:$2|jäl'gmäižes päiväs|jäl'gmäižiš '''$2''' päiviš}}, aigal $5, $4.",
 'rcnotefrom' => "Alemba oma anttud toižetused '''$2'''-späi ( '''$1'''-hesai).",
 'rclistfrom' => 'Ozutada uded toižetused dataspäi $1 augotaden',
@@ -1413,6 +1444,7 @@ Ku valitas vaiše ühten kävutajan failad, ka ozutadas vaiše necen kävutajan
 'listfiles_size' => 'Suruz’',
 'listfiles_description' => 'Ümbrikirjutand',
 'listfiles_count' => 'Versijad',
+'listfiles-latestversion-yes' => 'Ka',
 
 # File description page
 'file-anchor-link' => 'Fail',
@@ -1492,6 +1524,9 @@ Informacijad sen [$2 andmusiden lehtpolelpäi] om anttud alemba.',
 'randompage' => "Statjaline lehtpol'",
 'randompage-nopages' => '"$1"-{{PLURAL:$2|Nimiavarudes|Nimiavaruziš}} ei ole lehtpolid.',
 
+# Random page in category
+'randomincategory-selectcategory-submit' => 'Mäne',
+
 # Random redirect
 'randomredirect' => 'Statjaline läbikosketuz',
 'randomredirect-nopages' => '"$1"-nimiavaruses ei ole läbikosketusid.',
@@ -1936,7 +1971,7 @@ $1',
 'contributions' => '{{GENDER:$1|Kävutajan}} tond',
 'contributions-title' => '$1-kävutajan tond',
 'mycontris' => 'Minun tond',
-'contribsub2' => '$1-kävutajan ($2) tond',
+'contribsub2' => '{{GENDER:$3|$1}}-kävutajan ($2) tond',
 'uctop' => '(nügüdläine)',
 'month' => 'Ku:',
 'year' => 'Voz’:',
@@ -2339,6 +2374,8 @@ Voib olda, necil lehtpolel om kosketuz irdsaitale, kudamb om mustas nimikirjutes
 'pageinfo-watchers' => 'Lehtpolen kaclijoiden lugu',
 'pageinfo-edits' => 'Redakcijoiden lugumär',
 'pageinfo-authors' => 'Erazvuiččiden avtoroiden lugu',
+'pageinfo-contentpage-yes' => 'Ka',
+'pageinfo-protect-cascading-yes' => 'Ka',
 
 # Skin names
 'skinname-cologneblue' => "Köl'nan sinine",
@@ -2381,7 +2418,7 @@ $1',
 'file-info-size' => '$1 × $2 pikselad, failan suruz: $3, MIME-tip: $4',
 'file-nohires' => 'Ei ole versijad paremban tarkoiktusenke.',
 'svg-long-desc' => 'SVG-fail, nominaližikš $1 × $2 pikselid, failan suruz: $3',
-'show-big-image' => 'Korgedtarkoiktuseline kuvan versii',
+'show-big-image' => 'Originaline fail',
 'show-big-image-preview' => 'Ezikacundan suruz: $1.',
 'show-big-image-size' => '$1 × $2 pikselid',
 'file-info-gif-looped' => 'toštase',
@@ -2739,6 +2776,9 @@ Ku fail redaktiruidihe sändan polhe, erased parametrad voidas erineda nügüdl
 'exif-dc-publisher' => 'Pästai',
 'exif-dc-rights' => 'Oiktused',
 
+'exif-isospeedratings-overflow' => 'Более 65535',
+
+'exif-iimcategory-ace' => "Čomamaht, kul'tur da bobuštused",
 'exif-iimcategory-clj' => 'Ogerantegend da käskuz',
 'exif-iimcategory-dis' => 'Katastrofad da avarijad',
 'exif-iimcategory-fin' => 'Ekonomik da biznes',
@@ -2762,7 +2802,7 @@ Ku fail redaktiruidihe sändan polhe, erased parametrad voidas erineda nügüdl
 
 # External editor support
 'edit-externally' => 'Redaktiruida nece fail irdprogrammal',
-'edit-externally-help' => '(Kc. [//www.mediawiki.org/wiki/Manual:External_editors seižutamižinstrukcijoid])',
+'edit-externally-help' => '(Kc. [https://www.mediawiki.org/wiki/Manual:External_editors seižutamižinstrukcijoid])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'kaik',
@@ -2819,6 +2859,9 @@ Necen vahvištoitandkodan kävutamižen lopstrok om $4.',
 'confirm-watch-button' => 'OK',
 'confirm-unwatch-button' => 'OK',
 
+# Separators for various lists, etc.
+'quotation-marks' => '«$1»',
+
 # Multipage image navigation
 'imgmultipageprev' => "← edeline lehtpol'",
 'imgmultipagenext' => "jäl'ghine lehtpol' →",
@@ -2934,8 +2977,7 @@ Kävutagat normaline ezikacund.',
 
 # Special:SpecialPages
 'specialpages' => 'Specialižed lehtpoled',
-'specialpages-note' => '----
-* Järgeližed specialižed lehtpoled.
+'specialpages-note' => '* Järgeližed specialižed lehtpoled.
 * <span class="mw-specialpagerestricted">Kaitud specialižed lehtpoled.</span>',
 'specialpages-group-maintenance' => 'Tehnižen holitandan satusenladindad',
 'specialpages-group-other' => 'Toižed specialižed lehtpoled',
@@ -2973,7 +3015,9 @@ Kävutagat normaline ezikacund.',
 'tags-tag' => 'Tegan (virgan) nimi',
 'tags-display-header' => 'Nägu toižetisiden aigkirjoiš',
 'tags-description-header' => "Znamoičendan täuz' ümbrikirjutand",
+'tags-active-header' => 'Aktivine-ik?',
 'tags-hitcount-header' => 'Virgastadud redakcijad',
+'tags-active-yes' => 'Ka',
 'tags-edit' => 'redaktiruida',
 'tags-hitcount' => '$1 {{PLURAL:$1|toižetuz|toižetust}}',
 
@@ -3006,6 +3050,7 @@ Kävutagat normaline ezikacund.',
 'htmlform-submit' => 'Oigeta',
 'htmlform-reset' => 'Tühjitada toižetused',
 'htmlform-selectorother-other' => 'Toine',
+'htmlform-yes' => 'Ka',
 
 # SQLite database support
 'sqlite-has-fts' => " $1 täuz'tekstaižen ecindan tügedamiženke",
@@ -3048,4 +3093,12 @@ Kävutagat normaline ezikacund.',
 'duration-years' => "$1 {{PLURAL:$1|voz'|vot}}",
 'duration-decades' => '$1 {{PLURAL:$1|dekad|dekadad}}',
 
+# Special:ExpandTemplates
+'expand_templates_input' => 'Tekst:',
+'expand_templates_output' => "Rezul'tat",
+'expand_templates_xml_output' => 'XML-lähtmižvend',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => 'Čuta kommentarijad',
+'expand_templates_preview' => 'Ezikacund',
+
 );
index c5803ed..8a3eb58 100644 (file)
@@ -59,12 +59,12 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( 'Người_dùng_tích_cực' ),
        'Allmessages'               => array( 'Mọi_thông_điệp', 'Mọi_thông_báo' ),
+       'AllMyUploads'              => array( 'Mọi_tập_tin_của_tôi', 'Mọi_tập_tin_tôi_tải_lên' ),
        'Allpages'                  => array( 'Mọi_bài' ),
        'Ancientpages'              => array( 'Trang_cũ' ),
        'Badtitle'                  => array( 'Tựa_đề_hỏng' ),
        'Blankpage'                 => array( 'Trang_trắng' ),
        'Block'                     => array( 'Cấm', 'Cấm_IP', 'Cấm_thành_viên', 'Cấm_người_dùng' ),
-       'Blockme'                   => array( 'Khóa_tôi', 'Khoá_tôi' ),
        'Booksources'               => array( 'Nguồn_sách' ),
        'BrokenRedirects'           => array( 'Đổi_hướng_sai' ),
        'Categories'                => array( 'Thể_loại' ),
@@ -76,10 +76,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'Mở_tài_khoản', 'Đăng_ký', 'Đăng_kí' ),
        'Deadendpages'              => array( 'Trang_đường_cùng' ),
        'DeletedContributions'      => array( 'Đóng_góp_bị_xóa', 'Đóng_góp_bị_xoá' ),
-       'Disambiguations'           => array( 'Trang_định_hướng' ),
        'DoubleRedirects'           => array( 'Đổi_hướng_kép' ),
        'EditWatchlist'             => array( 'Sửa_danh_sách_theo_dõi' ),
        'Emailuser'                 => array( 'Gửi_thư', 'Gửi_thư_điện_tử' ),
+       'ExpandTemplates'           => array( 'Bung_bản_mẫu', 'Bung_tiêu_bản' ),
        'Export'                    => array( 'Xuất' ),
        'Fewestrevisions'           => array( 'Ít_phiên_bản_nhất' ),
        'FileDuplicateSearch'       => array( 'Tìm_tập_tin_trùng' ),
@@ -124,9 +124,12 @@ $specialPageAliases = array(
        'Protectedpages'            => array( 'Trang_khóa', 'Trang_khoá' ),
        'Protectedtitles'           => array( 'Tựa_đề_bị_khóa', 'Tựa_đề_bị_khoá' ),
        'Randompage'                => array( 'Ngẫu_nhiên' ),
+       'RandomInCategory'          => array( 'Ngẫu_nhiên_trong_thể_loại' ),
        'Randomredirect'            => array( 'Đổi_hướng_ngẫu_nhiên' ),
        'Recentchanges'             => array( 'Thay_đổi_gần_đây' ),
        'Recentchangeslinked'       => array( 'Thay_đổi_liên_quan' ),
+       'Redirect'                  => array( 'Đổi_hướng' ),
+       'ResetTokens'               => array( 'Đặt_lại_dấu_hiệu' ),
        'Revisiondelete'            => array( 'Xóa_phiên_bản', 'Xoá_phiên_bản' ),
        'Search'                    => array( 'Tìm_kiếm' ),
        'Shortpages'                => array( 'Trang_ngắn' ),
@@ -161,51 +164,53 @@ $specialPageAliases = array(
 
 $magicWords = array(
        'redirect'                  => array( '0', '#đổi', '#REDIRECT' ),
-       'notoc'                     => array( '0', '__KHÔNGMỤCLỤC__', '__NOTOC__' ),
-       'nogallery'                 => array( '0', '__KHÔNGALBUM__', '__NOGALLERY__' ),
-       'forcetoc'                  => array( '0', '__LUÔNMỤCLỤC__', '__FORCETOC__' ),
-       'toc'                       => array( '0', '__MỤCLỤC__', '__TOC__' ),
-       'noeditsection'             => array( '0', '__KHÔNGSỬAMỤC__', '__NOEDITSECTION__' ),
-       'currentmonth'              => array( '1', 'THÁNGNÀY', 'THÁNGNÀY2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
-       'currentmonth1'             => array( '1', 'THÁNGNÀY1', 'CURRENTMONTH1' ),
-       'currentmonthname'          => array( '1', 'TÊNTHÁNGNÀY', 'CURRENTMONTHNAME' ),
-       'currentmonthnamegen'       => array( '1', 'TÊNDÀITHÁNGNÀY', 'CURRENTMONTHNAMEGEN' ),
-       'currentmonthabbrev'        => array( '1', 'TÊNNGẮNTHÁNGNÀY', 'CURRENTMONTHABBREV' ),
-       'currentday'                => array( '1', 'NGÀYNÀY', 'CURRENTDAY' ),
-       'currentday2'               => array( '1', 'NGÀYNÀY2', 'CURRENTDAY2' ),
-       'currentdayname'            => array( '1', 'TÊNNGÀYNÀY', 'CURRENTDAYNAME' ),
-       'currentyear'               => array( '1', 'NĂMNÀY', 'CURRENTYEAR' ),
-       'currenttime'               => array( '1', 'GIỜNÀY', 'CURRENTTIME' ),
-       'localmonth'                => array( '1', 'THÁNGĐỊAPHƯƠNG', 'LOCALMONTH', 'LOCALMONTH2' ),
-       'localmonth1'               => array( '1', 'THÁNGĐỊAPHƯƠNG1', 'LOCALMONTH1' ),
-       'localmonthname'            => array( '1', 'TÊNTHÁNGĐỊAPHƯƠNG', 'LOCALMONTHNAME' ),
-       'localmonthabbrev'          => array( '1', 'THÁNGĐỊAPHƯƠNGTẮT', 'LOCALMONTHABBREV' ),
-       'localday'                  => array( '1', 'NGÀYĐỊAPHƯƠNG', 'LOCALDAY' ),
-       'localday2'                 => array( '1', 'NGÀYĐỊAPHƯƠNG2', 'LOCALDAY2' ),
-       'localdayname'              => array( '1', 'TÊNNGÀYĐỊAPHƯƠNG', 'LOCALDAYNAME' ),
-       'localyear'                 => array( '1', 'NĂMĐỊAPHƯƠNG', 'LOCALYEAR' ),
-       'localtime'                 => array( '1', 'GIỜĐỊAPHƯƠNG', 'LOCALTIME' ),
-       'numberofpages'             => array( '1', 'SỐTRANG', 'NUMBEROFPAGES' ),
-       'numberofarticles'          => array( '1', 'SỐBÀI', 'NUMBEROFARTICLES' ),
-       'numberoffiles'             => array( '1', 'SỐTẬPTIN', 'NUMBEROFFILES' ),
-       'numberofusers'             => array( '1', 'SỐTHÀNHVIÊN', 'NUMBEROFUSERS' ),
-       'numberofactiveusers'       => array( '1', 'SỐTHÀNHVIÊNTÍCHCỰC', 'NUMBEROFACTIVEUSERS' ),
-       'numberofedits'             => array( '1', 'SỐSỬAĐỔI', 'NUMBEROFEDITS' ),
-       'numberofviews'             => array( '1', 'SỐLẦNXEM', 'NUMBEROFVIEWS' ),
-       'pagename'                  => array( '1', 'TÊNTRANG', 'PAGENAME' ),
-       'pagenamee'                 => array( '1', 'TÊNTRANG2', 'PAGENAMEE' ),
-       'namespace'                 => array( '1', 'KHÔNGGIANTÊN', 'NAMESPACE' ),
-       'namespacenumber'           => array( '1', 'SỐKHÔNGGIANTÊN', 'NAMESPACENUMBER' ),
-       'talkspace'                 => array( '1', 'KGTTHẢOLUẬN', 'TALKSPACE' ),
-       'subjectspace'              => array( '1', 'KGTNỘIDUNG', 'SUBJECTSPACE', 'ARTICLESPACE' ),
-       'fullpagename'              => array( '1', 'TÊNTRANGĐỦ', 'FULLPAGENAME' ),
-       'subpagename'               => array( '1', 'TÊNTRANGPHỤ', 'SUBPAGENAME' ),
-       'basepagename'              => array( '1', 'TÊNTRANGGỐC', 'BASEPAGENAME' ),
-       'talkpagename'              => array( '1', 'TÊNTRANGTHẢOLUẬN', 'TALKPAGENAME' ),
-       'subjectpagename'           => array( '1', 'TÊNTRANGNỘIDUNG', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
+       'notoc'                     => array( '0', '__KHÔNG_MỤC_LỤC__', '__KHÔNGMỤCLỤC__', '__NOTOC__' ),
+       'nogallery'                 => array( '0', '__KHÔNG_ALBUM__', '__KHÔNGALBUM__', '__NOGALLERY__' ),
+       'forcetoc'                  => array( '0', '__LUÔN_MỤC_LỤC__', '__LUÔNMỤCLỤC__', '__FORCETOC__' ),
+       'toc'                       => array( '0', '__MỤC_LỤC__', '__MỤCLỤC__', '__TOC__' ),
+       'noeditsection'             => array( '0', '__KHÔNG_NÚT_SỬA_MỤC__', '__KHÔNGNÚTSỬAMỤC__', '__NOEDITSECTION__' ),
+       'currentmonth'              => array( '1', 'THÁNG_NÀY', 'THÁNGNÀY', 'THÁNG_NÀY_2', 'THÁNGNÀY2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'currentmonth1'             => array( '1', 'THÁNG_NÀY_1', 'THÁNGNÀY1', 'CURRENTMONTH1' ),
+       'currentmonthname'          => array( '1', 'TÊN_THÁNG_NÀY', 'TÊNTHÁNGNÀY', 'CURRENTMONTHNAME' ),
+       'currentmonthnamegen'       => array( '1', 'TÊN_DÀI_THÁNG_NÀY', 'TÊNDÀITHÁNGNÀY', 'CURRENTMONTHNAMEGEN' ),
+       'currentmonthabbrev'        => array( '1', 'TÊN_NGẮN_THÁNG_NÀY', 'TÊNNGẮNTHÁNGNÀY', 'CURRENTMONTHABBREV' ),
+       'currentday'                => array( '1', 'NGÀY_NÀY', 'NGÀYNÀY', 'CURRENTDAY' ),
+       'currentday2'               => array( '1', 'NGÀY_NÀY_2', 'NGÀYNÀY2', 'CURRENTDAY2' ),
+       'currentdayname'            => array( '1', 'TÊN_NGÀY_NÀY', 'TÊNNGÀYNÀY', 'CURRENTDAYNAME' ),
+       'currentyear'               => array( '1', 'NĂM_NÀY', 'NĂMNÀY', 'CURRENTYEAR' ),
+       'currenttime'               => array( '1', 'GIỜ_NÀY', 'GIỜNÀY', 'CURRENTTIME' ),
+       'currenthour'               => array( '1', 'GIỜ_HIỆN_TẠI', 'GIỜHIỆNTẠI', 'CURRENTHOUR' ),
+       'localmonth'                => array( '1', 'THÁNG_ĐỊA_PHƯƠNG', 'THÁNGĐỊAPHƯƠNG', 'LOCALMONTH', 'LOCALMONTH2' ),
+       'localmonth1'               => array( '1', 'THÁNG_ĐỊA_PHƯƠNG_1', 'THÁNGĐỊAPHƯƠNG1', 'LOCALMONTH1' ),
+       'localmonthname'            => array( '1', 'TÊN_THÁNG_ĐỊA_PHƯƠNG', 'TÊNTHÁNGĐỊAPHƯƠNG', 'LOCALMONTHNAME' ),
+       'localmonthabbrev'          => array( '1', 'THÁNG_ĐỊA_PHƯƠNG_TẮT', 'THÁNGĐỊAPHƯƠNGTẮT', 'LOCALMONTHABBREV' ),
+       'localday'                  => array( '1', 'NGÀY_ĐỊA_PHƯƠNG', 'NGÀYĐỊAPHƯƠNG', 'LOCALDAY' ),
+       'localday2'                 => array( '1', 'NGÀY_ĐỊA_PHƯƠNG_2', 'NGÀYĐỊAPHƯƠNG2', 'LOCALDAY2' ),
+       'localdayname'              => array( '1', 'TÊN_NGÀY_ĐỊA_PHƯƠNG', 'TÊNNGÀYĐỊAPHƯƠNG', 'LOCALDAYNAME' ),
+       'localyear'                 => array( '1', 'NĂM_ĐỊA_PHƯƠNG', 'NĂMĐỊAPHƯƠNG', 'LOCALYEAR' ),
+       'localtime'                 => array( '1', 'THỜI_GIAN_ĐỊA_PHƯƠNG', 'THỜIGIANĐỊAPHƯƠNG', 'LOCALTIME' ),
+       'localhour'                 => array( '1', 'GIỜ_ĐỊA_PHƯƠNG', 'GIỜĐỊAPHƯƠNG', 'LOCALHOUR' ),
+       'numberofpages'             => array( '1', 'SỐ_TRANG', 'SỐTRANG', 'NUMBEROFPAGES' ),
+       'numberofarticles'          => array( '1', 'SỐ_BÀI', 'SỐBÀI', 'NUMBEROFARTICLES' ),
+       'numberoffiles'             => array( '1', 'SỐ_TẬP_TIN', 'SỐTẬPTIN', 'NUMBEROFFILES' ),
+       'numberofusers'             => array( '1', 'SỐ_THÀNH_VIÊN', 'SỐTHÀNHVIÊN', 'NUMBEROFUSERS' ),
+       'numberofactiveusers'       => array( '1', 'SỐ_THÀNH_VIÊN_TÍCH_CỰC', 'SỐTHÀNHVIÊNTÍCHCỰC', 'NUMBEROFACTIVEUSERS' ),
+       'numberofedits'             => array( '1', 'SỐ_SỬA_ĐỔI', 'SỐSỬAĐỔI', 'NUMBEROFEDITS' ),
+       'numberofviews'             => array( '1', 'SỐ_LẦN_XEM', 'SỐLẦNXEM', 'NUMBEROFVIEWS' ),
+       'pagename'                  => array( '1', 'TÊN_TRANG', 'TÊNTRANG', 'PAGENAME' ),
+       'pagenamee'                 => array( '1', 'TÊN_TRANG_2', 'TÊNTRANG2', 'PAGENAMEE' ),
+       'namespace'                 => array( '1', 'KHÔNG_GIAN_TÊN', 'KHÔNGGIANTÊN', 'NAMESPACE' ),
+       'namespacenumber'           => array( '1', 'SỐ_KHÔNG_GIAN_TÊN', 'SỐKHÔNGGIANTÊN', 'NAMESPACENUMBER' ),
+       'talkspace'                 => array( '1', 'KGT_THẢO_LUẬN', 'KGTTHẢOLUẬN', 'TALKSPACE' ),
+       'subjectspace'              => array( '1', 'KGT_NỘI_DUNG', 'KGTNỘIDUNG', 'SUBJECTSPACE', 'ARTICLESPACE' ),
+       'fullpagename'              => array( '1', 'TÊN_TRANG_ĐỦ', 'TÊNTRANGĐỦ', 'FULLPAGENAME' ),
+       'subpagename'               => array( '1', 'TÊN_TRANG_PHỤ', 'TÊNTRANGPHỤ', 'SUBPAGENAME' ),
+       'basepagename'              => array( '1', 'TÊN_TRANG_GỐC', 'TÊNTRANGGỐC', 'BASEPAGENAME' ),
+       'talkpagename'              => array( '1', 'TÊN_TRANG_THẢO_LUẬN', 'TÊNTRANGTHẢOLUẬN', 'TALKPAGENAME' ),
+       'subjectpagename'           => array( '1', 'TÊN_TRANG_NỘI_DUNG', 'TÊNTRANGNỘIDUNG', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ),
        'msg'                       => array( '0', 'NHẮN:', 'MSG:' ),
        'subst'                     => array( '0', 'THẾ:', 'SUBST:' ),
-       'msgnw'                     => array( '0', 'NHẮNMỚI:', 'MSGNW:' ),
+       'msgnw'                     => array( '0', 'NHẮN_MỚI:', 'NHẮNMỚI:', 'MSGNW:' ),
        'img_thumbnail'             => array( '1', 'nhỏ', 'thumbnail', 'thumb' ),
        'img_manualthumb'           => array( '1', 'nhỏ=$1', 'thumbnail=$1', 'thumb=$1' ),
        'img_right'                 => array( '1', 'phải', 'right' ),
@@ -213,8 +218,9 @@ $magicWords = array(
        'img_none'                  => array( '1', 'không', 'none' ),
        'img_center'                => array( '1', 'giữa', 'center', 'centre' ),
        'img_framed'                => array( '1', 'khung', 'framed', 'enframed', 'frame' ),
-       'img_page'                  => array( '1', 'trang=$1', 'trang $1', 'page=$1', 'page $1' ),
-       'img_upright'               => array( '1', 'đứng', 'đứng=$1', 'đứng $1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_page'                  => array( '1', 'trang=$1', 'trang_$1', 'page=$1', 'page $1' ),
+       'img_upright'               => array( '1', 'đứng', 'đứng=$1', 'đứng_$1', 'upright', 'upright=$1', 'upright $1' ),
+       'img_border'                => array( '1', 'viền', 'border' ),
        'img_baseline'              => array( '1', 'chân-chữ', 'baseline' ),
        'img_sub'                   => array( '1', 'chỉ-số-dưới', 'sub' ),
        'img_super'                 => array( '1', 'chỉ-số-trên', 'super', 'sup' ),
@@ -225,62 +231,68 @@ $magicWords = array(
        'img_link'                  => array( '1', 'liên_kết=$1', 'link=$1' ),
        'img_class'                 => array( '1', 'lớp=$1', 'class=$1' ),
        'int'                       => array( '0', 'NỘI:', 'INT:' ),
-       'sitename'                  => array( '1', 'TÊNMẠNG', 'SITENAME' ),
+       'sitename'                  => array( '1', 'TÊN_MẠNG', 'TÊNMẠNG', 'SITENAME' ),
        'ns'                        => array( '0', 'KGT:', 'NS:' ),
-       'localurl'                  => array( '0', 'URLĐỊAPHƯƠNG:', 'LOCALURL:' ),
-       'articlepath'               => array( '0', 'ĐƯỜNGDẪNBÀI', 'LỐIBÀI', 'ARTICLEPATH' ),
-       'pageid'                    => array( '0', 'IDTRANG', 'PAGEID' ),
-       'server'                    => array( '0', 'MÁYCHỦ', 'SERVER' ),
-       'servername'                => array( '0', 'TÊNMÁYCHỦ', 'SERVERNAME' ),
-       'scriptpath'                => array( '0', 'ĐƯỜNGDẪNKỊCHBẢN', 'ĐƯỜNGDẪNSCRIPT', 'SCRIPTPATH' ),
-       'stylepath'                 => array( '0', 'ĐƯỜNGDẪNKIỂU', 'STYLEPATH' ),
-       'grammar'                   => array( '0', 'NGỮPHÁP:', 'GRAMMAR:' ),
+       'localurl'                  => array( '0', 'URL_ĐỊA_PHƯƠNG:', 'URLĐỊAPHƯƠNG:', 'LOCALURL:' ),
+       'articlepath'               => array( '0', 'ĐƯỜNG_DẪN_BÀI', 'ĐƯỜNGDẪNBÀI', 'LỐI_BÀI', 'LỐIBÀI', 'ARTICLEPATH' ),
+       'pageid'                    => array( '0', 'ID_TRANG', 'IDTRANG', 'PAGEID' ),
+       'server'                    => array( '0', 'MÁY_CHỦ', 'MÁYCHỦ', 'SERVER' ),
+       'servername'                => array( '0', 'TÊN_MÁY_CHỦ', 'TÊNMÁYCHỦ', 'SERVERNAME' ),
+       'scriptpath'                => array( '0', 'ĐƯỜNG_DẪN_KỊCH_BẢN', 'ĐƯỜNGDẪNKỊCHBẢN', 'ĐƯỜNG_DẪN_SCRIPT', 'ĐƯỜNGDẪNSCRIPT', 'SCRIPTPATH' ),
+       'stylepath'                 => array( '0', 'ĐƯỜNG_DẪN_KIỂU', 'ĐƯỜNGDẪNKIỂU', 'STYLEPATH' ),
+       'grammar'                   => array( '0', 'NGỮ_PHÁP:', 'NGỮPHÁP:', 'GRAMMAR:' ),
        'gender'                    => array( '0', 'GIỐNG:', 'GENDER:' ),
-       'notitleconvert'            => array( '0', '__KHÔNGCHUYỂNTÊN__', '__NOTITLECONVERT__', '__NOTC__' ),
-       'nocontentconvert'          => array( '0', '__KHÔNGCHUYỂNNỘIDUNG__', '__NOCONTENTCONVERT__', '__NOCC__' ),
-       'currentweek'               => array( '1', 'TUẦNNÀY', 'CURRENTWEEK' ),
-       'localweek'                 => array( '1', 'TUẦNĐỊAPHƯƠNG', 'LOCALWEEK' ),
-       'revisionid'                => array( '1', 'SỐBẢN', 'REVISIONID' ),
-       'revisionday'               => array( '1', 'NGÀYBẢN', 'REVISIONDAY' ),
-       'revisionday2'              => array( '1', 'NGÀYBẢN2', 'REVISIONDAY2' ),
-       'revisionmonth'             => array( '1', 'THÁNGBẢN', 'REVISIONMONTH' ),
-       'revisionmonth1'            => array( '1', 'THÁNGBẢN1', 'REVISIONMONTH1' ),
-       'revisionyear'              => array( '1', 'NĂMBẢN', 'REVISIONYEAR' ),
-       'revisiontimestamp'         => array( '1', 'MỐCTHỜIGIANBẢN', 'DẤUTHỜIGIANBẢN', 'REVISIONTIMESTAMP' ),
-       'revisionuser'              => array( '1', 'NGƯỜIDÙNGBẢN', 'REVISIONUSER' ),
-       'plural'                    => array( '0', 'SỐNHIỀU:', 'PLURAL:' ),
-       'fullurl'                   => array( '0', 'URLĐỦ:', 'FULLURL:' ),
-       'canonicalurl'              => array( '0', 'URLCHUẨN:', 'CANONICALURL:' ),
-       'lcfirst'                   => array( '0', 'CHỮĐẦUHOA:', 'LCFIRST:' ),
-       'ucfirst'                   => array( '0', 'CHỮĐẦUTHƯỜNG:', 'UCFIRST:' ),
-       'lc'                        => array( '0', 'CHỮHOA:', 'LC:' ),
-       'uc'                        => array( '0', 'CHỮTHƯỜNG:', 'UC:' ),
-       'displaytitle'              => array( '1', 'TÊNHIỂNTHỊ', 'DISPLAYTITLE' ),
-       'newsectionlink'            => array( '1', '__LIÊNKẾTMỤCMỚI__', '__NEWSECTIONLINK__' ),
-       'nonewsectionlink'          => array( '1', '__KHÔNGLIÊNKẾTMỤCMỚI__', '__NONEWSECTIONLINK__' ),
-       'currentversion'            => array( '1', 'BẢNNÀY', 'CURRENTVERSION' ),
-       'urlencode'                 => array( '0', 'MÃHÓAURL:', 'URLENCODE:' ),
-       'anchorencode'              => array( '0', 'MÃHÓANEO', 'ANCHORENCODE' ),
-       'currenttimestamp'          => array( '1', 'MỐCTHỜIGIANNÀY', 'DẤUTHỜIGIANNÀY', 'CURRENTTIMESTAMP' ),
-       'localtimestamp'            => array( '1', 'MỐCTHỜIGIANĐỊAPHƯƠNG', 'DẤUTHỜIGIANĐỊAPHƯƠNG', 'LOCALTIMESTAMP' ),
-       'language'                  => array( '0', '#NGÔNNGỮ:', '#LANGUAGE:' ),
-       'contentlanguage'           => array( '1', 'NGÔNNGỮNỘIDUNG', 'CONTENTLANGUAGE', 'CONTENTLANG' ),
-       'pagesinnamespace'          => array( '1', 'CỠKHÔNGGIANTÊN:', 'CỠKGT:', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
-       'numberofadmins'            => array( '1', 'SỐQUẢNLÝ', 'NUMBEROFADMINS' ),
-       'formatnum'                 => array( '0', 'PHÂNCHIASỐ', 'FORMATNUM' ),
-       'defaultsort'               => array( '1', 'XẾPMẶCĐỊNH:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
-       'filepath'                  => array( '0', 'ĐƯỜNGDẪNTẬPTIN', 'FILEPATH:' ),
+       'notitleconvert'            => array( '0', '__KHÔNG_CHUYỂN_TÊN__', '__KHÔNGCHUYỂNTÊN__', '__NOTITLECONVERT__', '__NOTC__' ),
+       'nocontentconvert'          => array( '0', '__KHÔNG_CHUYỂN_NỘI_DUNG__', '__KHÔNGCHUYỂNNỘIDUNG__', '__NOCONTENTCONVERT__', '__NOCC__' ),
+       'currentweek'               => array( '1', 'TUẦN_NÀY', 'TUẦNNÀY', 'CURRENTWEEK' ),
+       'localweek'                 => array( '1', 'TUẦN_ĐỊA_PHƯƠNG', 'TUẦNĐỊAPHƯƠNG', 'LOCALWEEK' ),
+       'revisionid'                => array( '1', 'SỐ_BẢN', 'SỐBẢN', 'REVISIONID' ),
+       'revisionday'               => array( '1', 'NGÀY_BẢN', 'NGÀYBẢN', 'REVISIONDAY' ),
+       'revisionday2'              => array( '1', 'NGÀY_BẢN_2', 'NGÀYBẢN2', 'REVISIONDAY2' ),
+       'revisionmonth'             => array( '1', 'THÁNG_BẢN', 'THÁNGBẢN', 'REVISIONMONTH' ),
+       'revisionmonth1'            => array( '1', 'THÁNG_BẢN_1', 'THÁNGBẢN1', 'REVISIONMONTH1' ),
+       'revisionyear'              => array( '1', 'NĂM_BẢN', 'NĂMBẢN', 'REVISIONYEAR' ),
+       'revisiontimestamp'         => array( '1', 'MỐC_THỜI_GIAN_BẢN', 'MỐCTHỜIGIANBẢN', 'DẤU_THỜI_GIAN_BẢN', 'DẤUTHỜIGIANBẢN', 'REVISIONTIMESTAMP' ),
+       'revisionuser'              => array( '1', 'NGƯỜI_DÙNG_BẢN', 'NGƯỜIDÙNGBẢN', 'REVISIONUSER' ),
+       'plural'                    => array( '0', 'SỐ_NHIỀU:', 'SỐNHIỀU:', 'PLURAL:' ),
+       'fullurl'                   => array( '0', 'URL_ĐỦ:', 'URLĐỦ:', 'FULLURL:' ),
+       'canonicalurl'              => array( '0', 'URL_CHUẨN:', 'URLCHUẨN:', 'CANONICALURL:' ),
+       'lcfirst'                   => array( '0', 'CHỮ_ĐẦU_HOA:', 'CHỮĐẦUHOA:', 'LCFIRST:' ),
+       'ucfirst'                   => array( '0', 'CHỮ_ĐẦU_THƯỜNG:', 'CHỮĐẦUTHƯỜNG:', 'UCFIRST:' ),
+       'lc'                        => array( '0', 'CHỮ_HOA:', 'CHỮHOA:', 'LC:' ),
+       'uc'                        => array( '0', 'CHỮ_THƯỜNG:', 'CHỮTHƯỜNG:', 'UC:' ),
+       'displaytitle'              => array( '1', 'TÊN_HIỂN_THỊ', 'TÊNHIỂNTHỊ', 'DISPLAYTITLE' ),
+       'newsectionlink'            => array( '1', '__LIÊN_KẾT_MỤC_MỚI__', '__LIÊNKẾTMỤCMỚI__', '__NEWSECTIONLINK__' ),
+       'nonewsectionlink'          => array( '1', '__KHÔNG_LIÊN_KẾT_MỤC_MỚI__', '__KHÔNGLIÊNKẾTMỤCMỚI__', '__NONEWSECTIONLINK__' ),
+       'currentversion'            => array( '1', 'BẢN_NÀY', 'BẢNNÀY', 'CURRENTVERSION' ),
+       'urlencode'                 => array( '0', 'MÃ_HÓA_URL:', 'MÃHÓAURL:', 'MÃ_HOÁ_URL:', 'MÃHOÁURL:', 'URLENCODE:' ),
+       'anchorencode'              => array( '0', 'MÃ_HÓA_NEO', 'MÃHÓANEO', 'MÃ_HOÁ_NEO', 'MÃHOÁNEO', 'ANCHORENCODE' ),
+       'currenttimestamp'          => array( '1', 'MỐC_THỜI_GIAN_NÀY', 'MỐCTHỜIGIANNÀY', 'DẤU_THỜI_GIAN_NÀY', 'DẤUTHỜIGIANNÀY', 'CURRENTTIMESTAMP' ),
+       'localtimestamp'            => array( '1', 'MỐC_THỜI_GIAN_ĐỊA_PHƯƠNG', 'MỐCTHỜIGIANĐỊAPHƯƠNG', 'DẤU_THỜI_GIAN_ĐỊA_PHƯƠNG', 'DẤUTHỜIGIANĐỊAPHƯƠNG', 'LOCALTIMESTAMP' ),
+       'language'                  => array( '0', '#NGÔN_NGỮ:', '#NGÔNNGỮ:', '#LANGUAGE:' ),
+       'contentlanguage'           => array( '1', 'NGÔN_NGỮ_NỘI_DUNG', 'NGÔNNGỮNỘIDUNG', 'CONTENTLANGUAGE', 'CONTENTLANG' ),
+       'pagesinnamespace'          => array( '1', 'CỠ_KHÔNG_GIAN_TÊN:', 'CỠKHÔNGGIANTÊN:', 'CỠ_KGT:', 'CỠKGT:', 'PAGESINNAMESPACE:', 'PAGESINNS:' ),
+       'numberofadmins'            => array( '1', 'SỐ_BẢO_QUẢN_VIÊN', 'SỐBẢOQUẢNVIÊN', 'SỐ_QUẢN_LÝ', 'SỐQUẢNLÝ', 'SỐ_QUẢN_LÍ', 'SỐQUẢNLÍ', 'NUMBEROFADMINS' ),
+       'formatnum'                 => array( '0', 'PHÂN_CHIA_SỐ', 'PHÂNCHIASỐ', 'FORMATNUM' ),
+       'defaultsort'               => array( '1', 'XẾP_MẶC_ĐỊNH:', 'XẾPMẶCĐỊNH:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
+       'filepath'                  => array( '0', 'ĐƯỜNG_DẪN_TẬP_TIN', 'ĐƯỜNGDẪNTẬPTIN', 'FILEPATH:' ),
        'tag'                       => array( '0', 'thẻ', 'tag' ),
-       'hiddencat'                 => array( '1', '__THỂLOẠIẨN__', '__HIDDENCAT__' ),
-       'pagesincategory'           => array( '1', 'CỠTHỂLOẠI', 'PAGESINCATEGORY', 'PAGESINCAT' ),
-       'pagesize'                  => array( '1', 'CỠTRANG', 'PAGESIZE' ),
-       'index'                     => array( '1', '__CHỈMỤC__', '__INDEX__' ),
-       'noindex'                   => array( '1', '__KHÔNGCHỈMỤC__', '__NOINDEX__' ),
-       'numberingroup'             => array( '1', 'CỠNHÓM', 'NUMBERINGROUP', 'NUMINGROUP' ),
-       'staticredirect'            => array( '1', '__ĐỔIHƯỚNGNHẤTĐỊNH__', '__STATICREDIRECT__' ),
-       'protectionlevel'           => array( '1', 'MỨCKHÓA', 'MỨCKHOÁ', 'PROTECTIONLEVEL' ),
-       'url_path'                  => array( '0', 'ĐƯỜNGDẪN', 'PATH' ),
-       'url_query'                 => array( '0', 'TRUYVẤN', 'QUERY' ),
+       'hiddencat'                 => array( '1', '__THỂ_LOẠI_ẨN__', '__THỂLOẠIẨN__', '__HIDDENCAT__' ),
+       'pagesincategory'           => array( '1', 'CỠ_THỂ_LOẠI', 'CỠTHỂLOẠI', 'PAGESINCATEGORY', 'PAGESINCAT' ),
+       'pagesize'                  => array( '1', 'CỠ_TRANG', 'CỠTRANG', 'PAGESIZE' ),
+       'index'                     => array( '1', '__CHỈ_MỤC__', '__CHỈMỤC__', '__INDEX__' ),
+       'noindex'                   => array( '1', '__KHÔNG_CHỈ_MỤC__', '__KHÔNGCHỈMỤC__', '__NOINDEX__' ),
+       'numberingroup'             => array( '1', 'CỠ_NHÓM', 'CỠNHÓM', 'NUMBERINGROUP', 'NUMINGROUP' ),
+       'staticredirect'            => array( '1', '__ĐỔI_HƯỚNG_NHẤT_ĐỊNH__', '__ĐỔIHƯỚNGNHẤTĐỊNH__', '__STATICREDIRECT__' ),
+       'protectionlevel'           => array( '1', 'MỨC_KHÓA', 'MỨCKHÓA', 'MỨC_KHOÁ', 'MỨCKHOÁ', 'PROTECTIONLEVEL' ),
+       'url_path'                  => array( '0', 'ĐƯỜNG_DẪN', 'ĐƯỜNGDẪN', 'PATH' ),
+       'url_query'                 => array( '0', 'TRUY_VẤN', 'TRUYVẤN', 'QUERY' ),
+       'defaultsort_noerror'       => array( '0', 'không_lỗi', 'noerror' ),
+       'defaultsort_noreplace'     => array( '0', 'không_thay_thế', 'noreplace' ),
+       'pagesincategory_all'       => array( '0', 'tất_cả', 'all' ),
+       'pagesincategory_pages'     => array( '0', 'trang', 'pages' ),
+       'pagesincategory_subcats'   => array( '0', 'thể_loại_con', 'subcats' ),
+       'pagesincategory_files'     => array( '0', 'tập_tin', 'files' ),
 );
 
 $datePreferences = array(
@@ -599,12 +611,10 @@ $1',
 'pagetitle' => '$1 – {{SITENAME}}',
 'retrievedfrom' => 'Lấy từ “$1”',
 'youhavenewmessages' => 'Bạn có $1 ($2).',
-'newmessageslink' => 'tin nhắn mới',
-'newmessagesdifflink' => 'thay đổi gần nhất',
 'youhavenewmessagesfromusers' => 'Bạn có $1 từ {{PLURAL:$3|người dùng khác|$3 người dùng}} ($2).',
 'youhavenewmessagesmanyusers' => 'Bạn có $1 từ nhiều người dùng ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1}}tin nhắn mới',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|thay đổi|các thay đổi}} gần đây',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|thay đổi|999=các thay đổi}} gần đây',
 'youhavenewmessagesmulti' => 'Bạn có tin nhắn mới ở $1',
 'editsection' => 'sửa',
 'editold' => 'sửa',
@@ -730,7 +740,8 @@ Bảo quản viên khóa nó đưa lý do là: “$3”.',
 'invalidtitle-knownnamespace' => 'Tựa trang không hợp lệ có không gian tên “$2” và văn bản “$3”',
 'invalidtitle-unknownnamespace' => 'Tựa trang không hợp lệ có không gian tên số $1 không rõ và văn bản “$2”',
 'exception-nologin' => 'Chưa đăng nhập',
-'exception-nologin-text' => 'Bạn cần phải đăng nhập để truy cập trang hoặc thực hiện tác vụ này tại wiki này.',
+'exception-nologin-text' => 'Xin vui lòng [[Special:Userlogin|đăng nhập]] để truy cập trang hoặc tác vụ này.',
+'exception-nologin-text-manual' => 'Xin vui lòng $1 để truy cập trang hoặc tác vụ này.',
 
 # Virus scanner
 'virus-badscanner' => "Cấu hình sau: không nhận ra bộ quét virus: ''$1''",
@@ -777,7 +788,7 @@ Hãy nhớ thay đổi [[Special:Preferences|tùy chọn cá nhân {{SITENAME}}]
 'gotaccount' => "Đã mở tài khoản rồi? '''$1'''.",
 'gotaccountlink' => 'Đăng nhập',
 'userlogin-resetlink' => 'Quên mất thông tin đăng nhập?',
-'userlogin-resetpassword-link' => 'Đặt lại mật khẩu của bạn',
+'userlogin-resetpassword-link' => 'Quên mật khẩu?',
 'helplogin-url' => 'Help:Đăng nhập',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Trợ giúp đăng nhập]]',
 'userlogin-loggedin' => 'Bạn đã đăng nhập với tên {{GENDER:$1}}$1.
@@ -826,7 +837,7 @@ Hãy kiểm tra lại chính tả, hoặc [[Special:UserLogin/signup|mở tài k
 'passwordtooshort' => 'Mật khẩu phải có ít nhất {{PLURAL:$1|1 ký tự|$1 ký tự}}.',
 'password-name-match' => 'Mật khẩu của bạn phải khác với tên người dùng của bạn.',
 'password-login-forbidden' => 'Tên đăng nhập và mật khẩu này đã bị cấm không được sử dụng.',
-'mailmypassword' => 'Gửi mật khẩu mới qua thư điện tử',
+'mailmypassword' => 'Tái tạo mật khẩu',
 'passwordremindertitle' => 'Mật khẩu tạm thời cho {{SITENAME}}',
 'passwordremindertext' => 'Ai đó (có thể là bạn, có địa chỉ IP $1) đã yêu cầu chúng tôi gửi mật khẩu mới của {{SITENAME}} ($4). Chúng tôi đã tạo một mật khẩu tạm “$3” cho thành viên “$2”. Nếu bạn chính là người đã yêu cầu mật khẩu, bạn cần phải đăng nhập và thay đổi mật khẩu ngay bây giờ. Mật khẩu tạm sẽ hết hạn trong vòng {{PLURAL:$5|một ngày|$5 ngày}}.
 
@@ -835,12 +846,12 @@ Nếu bạn không yêu cầu gửi mật khẩu mới, hoặc bạn đã nhớ
 'noemailcreate' => 'Bạn cần cung cấp một địa chỉ thư điện tử hợp lệ',
 'passwordsent' => 'Mật khẩu mới đã được gửi tới thư điện tử của thành viên “$1”. Xin đăng nhập lại sau khi nhận thư.',
 'blocked-mailpassword' => 'Địa chỉ IP của bạn bị cấm không được sửa đổi, do đó cũng không được phép dùng chức năng phục hồi mật khẩu để tránh sai phạm.',
-'eauthentsent' => 'Thư xác nhận đã được gửi. Trước khi dùng chức năng nhận thư, bạn cần thực hiện hướng dẫn trong thư xác nhận, để đảm bảo tài khoản thuộc về bạn.',
+'eauthentsent' => 'Thư xác nhận đã được gửi cho địa chỉ thư điện tử được chỉ định. Trước khi bạn có thể nhận thư, bạn cần thực hiện hướng dẫn trong thư để xác nhận tài khoản thuộc về bạn.',
 'throttled-mailpassword' => 'Mật khẩu đã được gửi đến cho bạn trong vòng {{PLURAL:$1|$1 giờ|$1 giờ}} đồng hồ trở lại. Để tránh lạm dụng, chỉ có thể gửi mật khẩu $1 giờ đồng hồ một lần.',
 'mailerror' => 'Lỗi gửi thư : $1',
 'acct_creation_throttle_hit' => 'Ai đó cùng [[địa chỉ IP]] với bạn đã mở {{PLURAL:$1|một tài khoản|$1 tài khoản}} ở đây trong vòng 24 giờ. Vì quy định hạn chế số tài khoản mở trên một địa chỉ IP nên bạn hiện không thể mở thêm được nữa dùng địa chỉ IP này.',
 'emailauthenticated' => 'Địa chỉ thư điện tử của bạn được xác nhận vào lúc $3 $2.',
-'emailnotauthenticated' => 'Địa chỉ thư điện tử của bạn chưa được xác nhận. Chức năng thư điện tử chưa bật.',
+'emailnotauthenticated' => 'Địa chỉ thư điện tử của bạn chưa được xác nhận. Các chức năng sau sẽ không gửi thư điện tử.',
 'noemailprefs' => 'Hãy ghi một địa chỉ thư điện tử trong tùy chọn cá nhân để có thể sử dụng tính năng này.',
 'emailconfirmlink' => 'Xác nhận địa chỉ thư điện tử',
 'invalidemailaddress' => 'Địa chỉ thư điện tử không được chấp nhận vì định dạng thư có vẻ sai.
@@ -889,7 +900,7 @@ Có thể bạn đã thay đổi thành công mật khẩu của mình hoặc đ
 # Special:PasswordReset
 'passwordreset' => 'Tái tạo mật khẩu',
 'passwordreset-text-one' => 'Hãy điền mẫu đơn này để tái tạo mật khẩu.',
-'passwordreset-text-many' => '{{PLURAL:$1|Điền vào một hộp sau để tái tạo mật khẩu.}}',
+'passwordreset-text-many' => 'Điền vào {{PLURAL:$1}}một hộp sau để nhận một mật khẩu tạm thời qua thư điện tử.',
 'passwordreset-legend' => 'Tái tạo mật khẩu',
 'passwordreset-disabled' => 'Chức năng tái tạo mật khẩu đã bị tắt trên wiki này.',
 'passwordreset-emaildisabled' => 'Tính năng gửi thư điện tử không được kích hoạt trên wiki này.',
@@ -1030,7 +1041,7 @@ Có thể nó đã bị di chuyển hoặc xóa đi trong khi bạn đang xem tr
 'accmailtitle' => 'Đã gửi mật khẩu.',
 'accmailtext' => "Một mật khẩu được tạo ngẫu nhiên cho [[User talk:$1|$1]] đã được gửi đến $2. Có thể đổi mật khẩu tại trang ''[[Special:ChangePassword|đổi mật khẩu]]'' sau khi đã đăng nhập.",
 'newarticle' => '(Mới)',
-'newarticletext' => "Bạn đi đến đây từ một liên kết đến một trang chưa tồn tại. Để tạo trang, hãy bắt đầu gõ vào ô bên dưới (xem [[{{MediaWiki:Helppage}}|trang trợ giúp]] để có thêm thông tin). Nếu bạn đến đây do nhầm lẫn, chỉ cần nhấn vào nút '''Lùi''' (''Back'') trong trình duyệt của bạn.",
+'newarticletext' => "Bạn đi đến đây từ một liên kết đến một trang chưa tồn tại. Để tạo trang, hãy bắt đầu gõ vào ô bên dưới (xem [[{{MediaWiki:Helppage}}|trang trợ giúp]] để có thêm thông tin). Nếu bạn đến đây do nhầm lẫn, chỉ cần nhấn vào nút '''Lùi''' (hoặc Trở lại, Quay lại, Back) trong trình duyệt của bạn.",
 'anontalkpagetext' => "----''Đây là trang thảo luận của một người dùng vô danh chưa tạo tài khoản hoặc có tài khoản nhưng không đăng nhập.
 Do đó chúng ta phải dùng một dãy số gọi là địa chỉ IP để xác định anh/chị ta.
 Một địa chỉ IP như vậy có thể có nhiều người cùng dùng chung.
@@ -1275,17 +1286,17 @@ Các quản lý khác ở {{SITENAME}} vẫn có thể truy nhập vào nội du
 'revdelete-suppress-text' => "Việc ẩn giấu '''chỉ''' nên dùng trong các trường hợp sau:
 * Thông tin có thể phỉ báng
 * Thông tin cá nhân không thích hợp
-*: ''địa chỉ nhà và số điện thoại, số an sinh xã hội, v.v.''",
+*: ''địa chỉ nhà và số điện thoại, số chứng minh nhân dân, số an sinh xã hội, v.v.''",
 'revdelete-legend' => 'Thiết lập hạn chế khả kiến',
-'revdelete-hide-text' => 'Ẩn nội dung phiên bản',
+'revdelete-hide-text' => 'Nội dung phiên bản',
 'revdelete-hide-image' => 'Ẩn nội dung tập tin',
 'revdelete-hide-name' => 'Ẩn tác vụ và đích của tác vụ',
-'revdelete-hide-comment' => 'Ẩn tóm lược sửa đổi',
-'revdelete-hide-user' => 'Ẩn tên người dùng hay địa chỉ IP của người viết trang',
+'revdelete-hide-comment' => 'Tóm lược sửa đổi',
+'revdelete-hide-user' => 'Tên người dùng hay địa chỉ IP của người viết trang',
 'revdelete-hide-restricted' => 'Ẩn giấu thông tin khỏi các Quản lý lẫn thành viên khác',
 'revdelete-radio-same' => '(không đổi)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'Không',
+'revdelete-radio-set' => 'Ẩn',
+'revdelete-radio-unset' => 'Hiện',
 'revdelete-suppress' => 'Che dữ liệu đối với bảo quản viên cũng như các thành viên khác',
 'revdelete-unsuppress' => 'Bỏ các hạn chế trên các phiên bản được phục hồi',
 'revdelete-log' => 'Lý do:',
@@ -1439,8 +1450,7 @@ Xem chi tiết trong [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}
 'preferences' => 'Tùy chọn',
 'mypreferences' => 'Tùy chọn',
 'prefs-edits' => 'Số lần sửa đổi:',
-'prefsnologin' => 'Chưa đăng nhập',
-'prefsnologintext' => 'Bạn phải <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} đăng nhập]</span> để thiết lập tùy chọn cá nhân.',
+'prefsnologintext2' => 'Xin vui lòng $1 để thay đổi tùy chọn.',
 'changepassword' => 'Đổi mật khẩu',
 'prefs-skin' => 'Hình dạng',
 'skin-preview' => 'Xem trước',
@@ -1740,6 +1750,9 @@ Nếu bạn đồng ý cung cấp, nó sẽ dùng để ghi nhận công lao c
 'recentchanges-label-minor' => 'Đây là một sửa đổi nhỏ',
 'recentchanges-label-bot' => 'Sửa đổi này do bot thực hiện',
 'recentchanges-label-unpatrolled' => 'Sửa đổi này chưa được tuần tra',
+'recentchanges-label-plusminus' => 'Kích cỡ trang đã thay đổi bằng số byte này',
+'recentchanges-legend-newpage' => '(xem thêm [[Special:NewPages|danh sách các trang mới]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "Dưới đây là {{PLURAL:$1|thay đổi '''duy nhất'''|'''$1''' thay đổi gần nhất}} trong {{PLURAL:$2|ngày qua|'''$2''' ngày qua}}, tính tới $5 lúc $4.",
 'rcnotefrom' => "Thay đổi từ '''$2''' (hiển thị tối đa '''$1''' thay đổi).",
 'rclistfrom' => 'Hiển thị các thay đổi từ $1.',
@@ -2467,9 +2480,9 @@ Liên lạc với người viết trang qua:
 thư: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Sẽ không có thông báo nào khác nếu có sự thay đổi tiếp theo trừ khi bạn xem trang đó. Bạn cũng có thể thiết lập lại việc nhắc nhở cho tất cả các trang nằm trong danh sách theo dõi của bạn.
+Sẽ không có thông báo nào khác nếu có sự thay đổi tiếp theo trừ khi bạn xem trang đó lúc khi đăng nhập. Bạn cũng có thể thiết lập lại việc nhắc nhở cho tất cả các trang nằm trong danh sách theo dõi của bạn.
 
-              Hệ thống báo tin {{SITENAME}} thân thiện của bạn
+Hệ thống báo tin {{SITENAME}} thân thiện của bạn
 
 --
 Để thay đổi các thiết lập thư điện tử thông báo, mời xem:
@@ -2731,9 +2744,10 @@ $1',
 'ipbreason' => 'Lý do:',
 'ipbreasonotherlist' => 'Lý do khác',
 'ipbreason-dropdown' => '*Một số lý do cấm thường gặp
+** Phá hoại
 ** Thêm thông tin sai lệch
 ** Xóa nội dung trang
-** Đăng liên kết thư rác đến trang Web bên ngoài
+** Đăng liên kết thư rác dẫn đến trang Web bên ngoài
 ** Cho thông tin rác vào trang
 ** Có thái độ dọa dẫm/quấy rối
 ** Lạm dụng nhiều tài khoản
@@ -2979,7 +2993,7 @@ Trong trường hợp sau bạn cũng có thể dùng một liên kết, ví d
 'allmessagesdefault' => 'Nội dung mặc định',
 'allmessagescurrent' => 'Nội dung hiện thời',
 'allmessagestext' => 'Đây là toàn bộ thông điệp hệ thống có trong không gian tên MediaWiki.
-Mời vào [//www.mediawiki.org/wiki/Localisation?uselang=vi Địa phương hóa MediaWiki] và [//translatewiki.net/wiki/?uselang=vi translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.',
+Mời vào [https://www.mediawiki.org/wiki/Localisation?uselang=vi Địa phương hóa MediaWiki] và [//translatewiki.net/wiki/?uselang=vi translatewiki.net] nếu bạn muốn đóng góp dịch chung cả MediaWiki.',
 'allmessagesnotsupportedDB' => "Trang này không dùng được vì biến '''\$wgUseDatabaseMessages''' đã bị tắt.",
 'allmessages-filter-legend' => 'Bộ lọc',
 'allmessages-filter' => 'Lọc theo tình trạng sửa đổi:',
@@ -3141,7 +3155,7 @@ Lưu nó vào máy tính của bạn rồi tải nó lên đây.',
 'tooltip-undo' => '“Lùi lại” sẽ lùi sửa đổi này và mở trang sửa đổi ở chế độ xem trước. Cho phép thêm lý do vào tóm lược.',
 'tooltip-preferences-save' => 'Lưu tùy chọn',
 'tooltip-summary' => 'Hãy nhập câu tóm lược',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* Mã CSS đặt ở đây sẽ áp dụng cho mọi hình dạng */',
@@ -3191,6 +3205,8 @@ Lưu nó vào máy tính của bạn rồi tải nó lên đây.',
 'spam_reverting' => 'Lùi lại đến phiên bản cuối không chứa liên kết đến $1',
 'spam_blanking' => 'Tất cả các phiên bản có liên kết đến $1; tẩy trống',
 'spam_deleting' => 'Tất cả các phiên bản có liên kết đến $1; xóa',
+'simpleantispam-label' => "Hệ thông đang kiểm tra chống spam.
+Xin '''ĐỪNG''' điền gì vào!",
 
 # Info page
 'pageinfo-title' => 'Thông tin về “$1”',
@@ -3204,6 +3220,7 @@ Lưu nó vào máy tính của bạn rồi tải nó lên đây.',
 'pageinfo-length' => 'Chiều dài của trang (byte)',
 'pageinfo-article-id' => 'Mã số trang',
 'pageinfo-language' => 'Ngôn ngữ nội dung trang',
+'pageinfo-content-model' => 'Kiểu nội dung trang',
 'pageinfo-robot-policy' => 'Ghi chỉ mục bởi robot',
 'pageinfo-robot-index' => 'Cho phép',
 'pageinfo-robot-noindex' => 'Không cho phép',
@@ -3291,7 +3308,7 @@ Nếu thực thi nó máy tính của bạn có thể bị tiếm quyền.",
 'svg-long-desc' => 'tập tin SVG, $1×$2 điểm ảnh trên danh nghĩa, kích thước: $3',
 'svg-long-desc-animated' => 'tập tin hình động SVG, $1×$2 điểm ảnh trên danh nghĩa, kích thước: $3',
 'svg-long-error' => 'Tập tin SVG có lỗi: $1',
-'show-big-image' => 'Độ phân giải tối đa',
+'show-big-image' => 'Tập tin gốc',
 'show-big-image-preview' => 'Kích thước của hình xem trước: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Độ phân giải|Các độ phân giải}} khác: $1.',
 'show-big-image-size' => '$1×$2 điểm ảnh',
@@ -3808,7 +3825,7 @@ Những thông tin khác mặc định sẽ được ẩn đi.
 
 # External editor support
 'edit-externally' => 'Sửa bằng phần mềm bên ngoài',
-'edit-externally-help' => '(Xem [//www.mediawiki.org/wiki/Manual:External_editors hướng dẫn cài đặt bằng tiếng Anh] để biết thêm thông tin)',
+'edit-externally-help' => '(Xem [https://www.mediawiki.org/wiki/Manual:External_editors hướng dẫn cài đặt bằng tiếng Anh] để biết thêm thông tin)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'tất cả',
@@ -3911,6 +3928,7 @@ Xin hãy xác nhận bạn thực sự muốn tạo lại trang này.",
 
 # Separators for various lists, etc.
 'ellipsis' => '…',
+'quotation-marks' => '“$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← trang trước',
@@ -4052,7 +4070,7 @@ Bạn cũng có thể [[Special:EditWatchlist|dùng trang sửa đổi bình th
 'version-hook-subscribedby' => 'Được theo dõi bởi',
 'version-version' => '(Phiên bản $1)',
 'version-license' => 'Giấy phép bản quyền',
-'version-poweredby-credits' => "Wiki này chạy trên '''[//www.mediawiki.org/ MediaWiki]''', bản quyền © 2001–$1 $2.",
+'version-poweredby-credits' => "Wiki này chạy trên '''[https://www.mediawiki.org/ MediaWiki]''', bản quyền © 2001–$1 $2.",
 'version-poweredby-others' => 'những người khác',
 'version-poweredby-translators' => 'các biên dịch viên translatewiki.net',
 'version-credits-summary' => 'Chúng tôi muốn công nhận những người sau đã đóng góp vào [[Special:Version|MediaWiki]].',
@@ -4078,7 +4096,7 @@ hoặc [//www.gnu.org/licenses/old-licenses/gpl-2.0.html đọc nó trực tuy
 # Special:Redirect
 'redirect' => 'Đổi hướng đến tập tin, người dùng, hoặc số phiên bản',
 'redirect-legend' => 'Đổi hướng đến tập tin hoặc trang',
-'redirect-summary' => 'Trang đặc biệt này đổi hướng đến một tập tin (theo tên tập tin được cho vào), trang (theo số phiên bản được cho vào), hoặc trang cá nhân (theo số thành viên).',
+'redirect-summary' => 'Trang đặc biệt này đổi hướng đến một tập tin (theo tên tập tin được cho vào), trang (theo số phiên bản được cho vào), hoặc trang cá nhân (theo số thành viên). Cách sử dụng: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], hoặc [[{{#Special:Redirect}}/user/101]].',
 'redirect-submit' => 'Đi',
 'redirect-lookup' => 'Tra cứu:',
 'redirect-value' => 'Giá trị:',
@@ -4100,10 +4118,9 @@ hoặc [//www.gnu.org/licenses/old-licenses/gpl-2.0.html đọc nó trực tuy
 
 # Special:SpecialPages
 'specialpages' => 'Các trang đặc biệt',
-'specialpages-note' => '----
-* Trang đặc biệt thông thường.
-* <strong class="mw-specialpagerestricted">Trang đặc biệt được hạn chế.</strong>
-* <span class="mw-specialpagecached">Trang đặc biệt được lấy từ vùng nhớ đệm (có thể lỗi thời).</span>',
+'specialpages-note-top' => 'Chú giải',
+'specialpages-note' => '* Trang đặc biệt thông thường.
+* <strong class="mw-specialpagerestricted">Trang đặc biệt được hạn chế.</strong>',
 'specialpages-group-maintenance' => 'Báo cáo bảo quản',
 'specialpages-group-other' => 'Trang đặc biệt khác',
 'specialpages-group-login' => 'Đăng nhập / Mở tài khoản',
@@ -4316,4 +4333,17 @@ Nếu không thì bạn có thể điền biểu mẫu đơn giản ở dưới.
 'limitreport-expansiondepth' => 'Độ sâu bung cao nhất',
 'limitreport-expensivefunctioncount' => 'Số lời gọi hàm cú pháp tốn cần mức độ xử lý cao',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'Bung bản mẫu',
+'expand_templates_intro' => 'Trang đặc biệt này sẽ nhận vào văn bản và bung tất cả các bản mẫu trong nó ra một cách đệ quy cho đến hết. Nó cũng bung cả những hàm cú pháp như <code><nowiki>{{</nowiki>#language:…}}</code>, và những biến số như <code><nowiki>{{</nowiki>CURRENTDAY}}</code>. Thực ra nó bung các dữ liệu bình thường đặt trong ngoặc móc.',
+'expand_templates_title' => 'Tên của trang văn cảnh (để phân tích {{FULLPAGENAME}} v.v.):',
+'expand_templates_input' => 'Mã nguồn để bung:',
+'expand_templates_output' => 'Kết quả',
+'expand_templates_xml_output' => 'Xuất XML',
+'expand_templates_ok' => 'Bung',
+'expand_templates_remove_comments' => 'Bỏ các chú thích',
+'expand_templates_remove_nowiki' => 'Bỏ qua thẻ <nowiki> trong kết quả',
+'expand_templates_generate_xml' => 'Xem cây phân tích XML',
+'expand_templates_preview' => 'Xem trước',
+
 );
index 11b0ea3..c7e9ed0 100644 (file)
@@ -278,8 +278,6 @@ $1",
 'ok' => 'In ôrdnung',
 'retrievedfrom' => 'Fon „$1“ ghold',
 'youhavenewmessages' => "S'gajd $1 af dajnâr disghusjoons-sajdn ($2).",
-'newmessageslink' => 'naje middajlunga',
-'newmessagesdifflink' => 'lädschde fârendârung',
 'youhavenewmessagesmulti' => "S'gajd naje middajlungn: $1",
 'editsection' => 'Beärbâdn',
 'editold' => 'Bearbajdn',
@@ -540,8 +538,6 @@ Zu deiner Informadion folchd des Lösch- un Verschäibungs-Logbuch miid der Begr
 'preferences' => 'ajschdelunga',
 'mypreferences' => 'Ajschdelunga',
 'prefs-edits' => 'So ofd umgmoodld:',
-'prefsnologin' => 'Ned ôôgmäld',
-'prefsnologintext' => 'Ärschd wen\'d <span class="plainlinks">[{{fullurl:{{#special:UserLogin}}|returnto=$1}} ôôgmäld]</span> bisch, ghôôsch dâj âjschdelungn ändârn.',
 'changepassword' => "S'bhaswôrd ändârn",
 'prefs-skin' => 'Schaale',
 'skin-preview' => 'Môôl schbign',
@@ -1010,7 +1006,7 @@ Bloos  dsajln, dii mi´m dsajchn * ôôfanga, wärn berigsichdichd. Un dä ärsc
 
 # External editor support
 'edit-externally' => 'Dii dadaj mid an ägsdärna brogram ändârn',
-'edit-externally-help' => '(Määr un genauârs dâdsuu baj den [//www.mediawiki.org/wiki/Manual:External_editors Inschdaladsjoonsanwajsungn])',
+'edit-externally-help' => '(Määr un genauârs dâdsuu baj den [https://www.mediawiki.org/wiki/Manual:External_editors Inschdaladsjoonsanwajsungn])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ale',
index b638e4a..50264c8 100644 (file)
@@ -68,7 +68,6 @@ $specialPageAliases = array(
        'Categories'                => array( 'Klads' ),
        'Confirmemail'              => array( 'Fümedönladeti' ),
        'Contributions'             => array( 'Keblünots' ),
-       'Disambiguations'           => array( 'Telplänovs', 'Telplänovapads' ),
        'DoubleRedirects'           => array( 'Lüodükömstelik', 'Lüodüköms telik' ),
        'Listfiles'                 => array( 'Ragivalised', 'Magodalised' ),
        'Listusers'                 => array( 'Gebanalised' ),
@@ -120,7 +119,7 @@ $messages = array(
 'tog-hidepatrolled' => 'Klänedön redakamis pezepöl in lised votükamas nulik.',
 'tog-newpageshidepatrolled' => 'Klänedön padis pezepöl in lised padas nulik',
 'tog-extendwatchlist' => 'Stäänükön galädalisedi ad jonön votükamis tefik valik, e no te nulikünos',
-'tog-usenewrc' => 'Grupön votükamis pado in votukäms nulik e galädalised (me JavaScript)',
+'tog-usenewrc' => 'Grupön votükamis pado in votukäms nulik e galädalised',
 'tog-numberheadings' => 'Givön itjäfidiko nümis dilädatiädes',
 'tog-showtoolbar' => 'Jonön redakamastumemi',
 'tog-editondblclick' => 'Dälön redakön padis pö drän telik mugaknopa',
@@ -250,6 +249,7 @@ $messages = array(
 'newwindow' => '(maifikon in fenät nulik)',
 'cancel' => 'Stöpädön',
 'moredotdotdot' => 'Plu...',
+'morenotlisted' => 'Lised at no binon lölöfik.',
 'mypage' => 'Pad',
 'mytalk' => 'Bespiks',
 'anontalk' => 'Bespiks ela IP at',
@@ -278,7 +278,7 @@ $messages = array(
 'vector-view-history' => 'Logön jenotemi',
 'vector-view-view' => 'Reidön',
 'vector-view-viewsource' => 'Logön fonäti',
-'actions' => 'Duns',
+'actions' => 'Dunots',
 'namespaces' => 'Nemaspads',
 
 'errorpagetitle' => 'Pöl',
@@ -319,7 +319,7 @@ $messages = array(
 'articlepage' => 'Jonön ninädapadi',
 'talk' => 'Bespik',
 'views' => 'Logams',
-'toolbox' => 'Stumem',
+'toolbox' => 'Stums',
 'userpage' => 'Logön gebanapadi',
 'projectpage' => 'Logön proyegapadi',
 'imagepage' => 'Jonön ragivapad',
@@ -368,8 +368,6 @@ $messages = array(
 'ok' => 'Si!',
 'retrievedfrom' => 'Pekopiedon se „$1“',
 'youhavenewmessages' => 'Su pad ola binons $1 ($2).',
-'newmessageslink' => 'nuns nulik',
-'newmessagesdifflink' => 'votükam lätik',
 'youhavenewmessagesfromusers' => 'Labol $1 de {{PLURAL:$3|geban votik|gebans $3}} ($2).',
 'youhavenewmessagesmanyusers' => 'Labol $1 de gebans mödik ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|nuni nulik|nunis nulik}}',
@@ -419,6 +417,7 @@ Mögos i, das atos sinifon, das dabinon säkädil pö program fa {{SITENAME}} pa
 # General errors
 'error' => 'Pöl',
 'databaseerror' => 'Pöl in nünodem',
+'databaseerror-function' => 'Dunod: $1',
 'databaseerror-error' => 'Pöl: $1',
 'laggedslavemode' => 'Nuned: pad ba labon votükamis brefabüik',
 'readonly' => 'Vük pefärmükon',
@@ -461,7 +460,7 @@ Beg: $2',
 'viewsource-title' => 'Logön fonäti pada: "$1"',
 'actionthrottled' => 'Dun pemiedükon',
 'actionthrottledtext' => 'Ad tadunön reklamami itjäfidik (el „spam“), dunot at no padälon tu suvo dü brefüp. Ya erivol miedi gretikün. Steifülolös nogna pos minuts anik.',
-'protectedpagetext' => 'Pad at pejelon ad neletön redakami.',
+'protectedpagetext' => 'Pad at pejelon ad neletön redakami u dunotis votik.',
 'viewsourcetext' => 'Kanol logön e kopiedön fonätakoti pada at:',
 'protectedinterface' => 'Pad at jafon vödemis sitanünas, ed anu pelökofärmükon ad vitön migebis.',
 'editinginterface' => "'''Nuned:''' redakol padi, kel labükon vödemis bevüik pro programem.
@@ -469,6 +468,10 @@ Votükams pada at oflunons logoti gebanasita pro gebans votik.
 Ad läükön u votükön tradutodis pro els wiki valik, demolös gebi ela [//translatewiki.net/?setlang=vo translatewiki.net]: topükamaproyeg ela MediaWiki.",
 'cascadeprotected' => 'Pad at pejelon ta redakam, bi pakeninükon fa {{PLURAL:$1|pad|pads}} sököl, kels pejelons ma „jänajel“: $2',
 'namespaceprotected' => "No dalol redakön padis in nemaspad: '''$1'''.",
+'mycustomcssprotected' => 'No dalol redakön padi: CSS at.',
+'mycustomjsprotected' => 'No dalol redakön padi: JavaScript at.',
+'myprivateinfoprotected' => 'No dalol redakön nünis privatik ola.',
+'mypreferencesprotected' => 'No dalol votükön buükamis olik.',
 'ns-specialprotected' => 'Pads patik no kanons paredakön.',
 'titleprotected' => "Jaf tiäda at penemögükon fa geban: [[User:$1|$1]].
 Kod binon: ''$2''.",
@@ -568,7 +571,7 @@ Sekü atos, visitans ladeti-IP at geböls no dalons jafön kalis pluik ün atim.
 'invalidemailaddress' => 'Ladet leäktronik no kanon pazepön bi fomät onik jiniko no lonöfon.
 Penolös ladeti labü fomät lonöföl, u vagükolös penamaspadi.',
 'accountcreated' => 'Kal pejafon',
-'accountcreatedtext' => 'Gebanakal pro $1 pejafon.',
+'accountcreatedtext' => 'Gebanakal pro [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|bespik]]) pejafon.',
 'createaccount-title' => 'Kalijafam in {{SITENAME}}',
 'createaccount-text' => 'Ek ejafon kali pro ladet leäktronik ola in {{SITENAME}} ($4) labü nem: „$2“ e letavöd: „$3“. Kanol nunädön oli e votükön letavödi olik anu.
 
@@ -678,7 +681,7 @@ Ladet-IP olik binon $3, e nüm blokama at binon #$5. Mäniotolös nünis löpik
 'nosuchsectiontitle' => 'Diläd no petuvöl',
 'nosuchsectiontext' => 'Esteifülol ad redakön dilädi no dabinöli.',
 'loginreqtitle' => 'Nunädam Paflagon',
-'loginreqlink' => 'nunädolös obi',
+'loginreqlink' => 'nunädön oli',
 'loginreqpagetext' => 'Mutol $1 ad logön padis votik.',
 'accmailtitle' => 'Letavöd pesedon.',
 'accmailtext' => "Letavöd fädik pro [[User talk:$1|$1]] pasedon lü $2.
@@ -747,7 +750,8 @@ If no vilol, das vödems olik poredakons nenmisero, tän no pladolös onis isio.
 Garanol obes, das ol it epenol atosi, u das ekopiedol atosi se räyun notidik u se fon libik sümik (logolös eli $1 pro notets).
 
 '''NO PLADOLÖD ISIO NEN DÄL LAUTANA VÖDEMIS LABÜ KOPIEDAGITÄT!'''",
-'longpageerror' => "'''PÖL: Vödem fa ol pesedöl labon lunoti miljölätas $1, kelos pluon leigodü völad muik pedälöl miljölätas $2. No kanon padakipön.'''",
+'longpageerror' => "'''Pöl: Vödem fa ol pesedöl labon lunoti {{PLURAL:$1|miljöläta bal|miljölätas $1}}, kelos pluon leigodü völad muik pedälöl {{PLURAL:$2|miljöläta bal|miljölätas $2}}.'''
+No kanon padakipön.",
 'readonlywarning' => "'''NUNED: Vük pefärmükon kodü kodididazesüd. No kanol dakipön votükamis olik anu. Kopiedolös vödemi nulik ini program votik e dakipolös oni in nünöm olik. Poso okanol dönu steifülön ad pladön oni isio.'''
 
 Geban, kel efärmükon oni, egevon kodi at: $1",
@@ -806,6 +810,7 @@ Paramet(s) at pemoädon(s).',
 'undo-failure' => 'No eplöpos ad sädunön redakami at sekü konflits vü redakams vüik.',
 'undo-norev' => 'No eplöpos ad sädunön redakami at, bi no dabinon u pämoükon.',
 'undo-summary' => 'Äsädunon votükami $1 fa [[Special:Contributions/$2|$2]] ([[User talk:$2|Bespikapad]])',
+'undo-summary-username-hidden' => 'Sädunön revidi: $1 fa geban peklenädöl',
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Kal no kanon pajafön',
@@ -998,8 +1003,6 @@ Kontrololös, va votükam at okipon fovöfi padajenotema.',
 'preferences' => 'Buükams',
 'mypreferences' => 'Buükams',
 'prefs-edits' => 'Num redakamas:',
-'prefsnologin' => 'No enunädon oki',
-'prefsnologintext' => 'Nedol <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} nunädön oli]</span> büä kanol votükön gebanabuükamis.',
 'changepassword' => 'Votükön letavödi',
 'prefs-skin' => 'Fomät',
 'skin-preview' => 'Büologed',
@@ -1158,7 +1161,7 @@ Muton labön {{PLURAL:$1|malati|malatis}} läs $1.',
 'right-ipblock-exempt' => 'Nedemön blokamis-IP, blokamis itjäfidik e grupiblokamis',
 'right-proxyunbannable' => 'Nedemön blokamis itjäfidik pladulömas',
 'right-protect' => 'Votükön jelanivodis e redakön padis pejelöl',
-'right-editprotected' => 'Bevobön padis pejelöl (nen vatafalajel)',
+'right-editprotected' => 'Bevobön padis pejelöl äs "{{int:protect-level-sysop}}"',
 'right-editinterface' => 'Votükön gebanaloveikömi',
 'right-editusercssjs' => 'Redakön ragivis-CSS e -JS gebanas votik',
 'right-editusercss' => 'Redakön ragivis-CSS gebanas votik',
@@ -1231,6 +1234,7 @@ Muton labön {{PLURAL:$1|malati|malatis}} läs $1.',
 'recentchanges-label-minor' => 'Atos binon redakam pülik',
 'recentchanges-label-bot' => 'Redakam at pädunon fa el bot',
 'recentchanges-label-unpatrolled' => 'Redakam at no nog pekontrolon',
+'recentchanges-legend-newpage' => '$1 - pad nulik',
 'rcnote' => "Dono {{PLURAL:$1|binon votükam '''1'''|binons votükams '''$1'''}} lätikün {{PLURAL:$2|dela|delas '''$2'''}} lätikün, pänumädöls tü $5, $4.",
 'rcnotefrom' => "Is palisedons votükams sis '''$2''' (jü '''$1''').",
 'rclistfrom' => 'Jonön votükamis nulik, primölo tü düp $1',
@@ -1271,7 +1275,7 @@ Pads [[Special:Watchlist|galädaliseda olik]] '''pakazetons'''.",
 'uploadbtn' => 'Löpükön ragivi',
 'reuploaddesc' => 'Nosükon lopükami e geikön lü löpükamafomet.',
 'uploadnologin' => 'No enunädon oki',
-'uploadnologintext' => 'Mutol [[Special:UserLogin|nunädön oli]] ad löpükön ragivis.',
+'uploadnologintext' => 'Mutol $1 ad löpükön ragivis.',
 'upload_directory_missing' => 'Löpükamaragiviär ($1) no dabinon e no ekanon pajafön fa dünanünöm bevüresodik.',
 'upload_directory_read_only' => 'Ragiviär lopükama ($1) no kanon papenön fa dünanünöm bevüresodik.',
 'uploaderror' => 'Pök pö löpükam',
@@ -1585,7 +1589,7 @@ Primanünods: ninädasot/donasot, a.s. <code>image/jpeg</code>.',
 'booksources-invalid-isbn' => 'El ISBN at jiniko no lonöfon; kontrololös pökis po kopiedam se rigafonät.',
 
 # Special:Log
-'specialloguserlabel' => 'Geban:',
+'specialloguserlabel' => 'Dunan:',
 'speciallogtitlelabel' => 'Lükömöp (tiäd u geban):',
 'log' => 'Jenotaliseds',
 'all-logs-page' => 'Jenotaliseds notidik valik',
@@ -1643,7 +1647,7 @@ Protoks pestütöl: <code>$1</code>',
 'listusers-blocked' => '(pebloköl)',
 
 # Special:ActiveUsers
-'activeusers-count' => '{{PLURAL:$1|redakam|redakams}} $1 ün {{PLURAL:$3|del lätik|dels lätik $3}}',
+'activeusers-count' => '{{PLURAL:$1|dunot|dunots}} $1 ün {{PLURAL:$3|del lätik|dels lätik $3}}',
 'activeusers-hidebots' => 'Klänedolöd elis bot',
 'activeusers-hidesysops' => 'Klänedolöd guvanis',
 'activeusers-noresult' => 'Geban nonik petuvon.',
@@ -1778,10 +1782,12 @@ $2 jonon moükamis nulik.',
 'deletecomment' => 'Kod:',
 'deleteotherreason' => 'Kod votik:',
 'deletereasonotherlist' => 'Kod votik',
-'deletereason-dropdown' => '* Kods kösömik moükama
-** Beg lautana
+'deletereason-dropdown' => "* Kods kösömik moükama
+** 'Spam'
+** Vandalim
 ** Kopiedagitäts
-** Vandalim',
+** Beg lautana
+** Lüodüköm dädik",
 'delete-edit-reasonlist' => 'Redakön kodis moükama',
 'delete-toobig' => 'Pad at labon redakamajenotemi lunik ({{PLURAL:$1|revid|revids}} plu $1).
 Moükam padas somik pemiedükon ad vitön däropami pö {{SITENAME}}.',
@@ -1812,7 +1818,7 @@ Välolös knopi: „Geikön“ e dönulodolös padi, de kel ekömol, e tän stei
 Logolös [[Special:ProtectedPages|lisedi padas pejelöl]], kö pajonons padijelams anu lonöföls.',
 'protectedarticle' => 'ejelon padi: „[[$1]]“',
 'modifiedarticleprotection' => 'evotükon jelanivodi pada: „[[$1]]“',
-'unprotectedarticle' => 'Pad: „[[$1]]“ pesäjelon.',
+'unprotectedarticle' => 'esäjelon padi: "[[$1]]"',
 'movedarticleprotection' => 'moved protection settings from „[[$2]]“ to „[[$1]]“',
 'protect-title' => 'lonon jelanivodi pada: „$1“',
 'prot_1movedto2' => '[[$1]] petopätükon lü [[$2]]',
@@ -1924,7 +1930,7 @@ $1',
 'contributions' => '{{GENDER:$1|Gebanakeblünots}}',
 'contributions-title' => 'Gebanakeblünots pro $1',
 'mycontris' => 'Keblünots',
-'contribsub2' => 'Tefü $1 ($2)',
+'contribsub2' => '{{GENDER:$3|Hiela|Jiela|Ela}} $1 ($2)',
 'nocontribs' => 'Votükams nonik petuvons me paramets at.',
 'uctop' => '(anuik)',
 'month' => 'De mul (e büiks):',
@@ -2173,7 +2179,7 @@ Ad seveigön padis, penolös tiädis in penamaspad dono, tiädi bal a kedet, e v
 'allmessagesdefault' => 'Vödem rigädik',
 'allmessagescurrent' => 'Vödem nuik',
 'allmessagestext' => 'Is binon lised sitanunas valik lonöföl in nemaspad: Sitanuns.
-Gebolös [//www.mediawiki.org/wiki/Localisation Topükami ela MediaWiki] ed el [//translatewiki.net translatewiki.net] if vilol keblünön topükame valemik ela MediaWiki.',
+Gebolös [https://www.mediawiki.org/wiki/Localisation Topükami ela MediaWiki] ed el [//translatewiki.net translatewiki.net] if vilol keblünön topükame valemik ela MediaWiki.',
 'allmessagesnotsupportedDB' => "Pad at no kanon pagebön bi el '''\$wgUseDatabaseMessages''' penemögükon.",
 'allmessages-filter-legend' => 'Sul',
 'allmessages-filter-unmodified' => 'Penevotüköl',
@@ -2685,7 +2691,7 @@ Nünabinets votik poklänedons.
 
 # External editor support
 'edit-externally' => 'Votükön ragivi at me nünömaprogram plödik',
-'edit-externally-help' => '(Reidolös eli [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] [in Linglänapük] ad tuvön nünis pluik)',
+'edit-externally-help' => '(Reidolös eli [https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] [in Linglänapük] ad tuvön nünis pluik)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'valikis',
@@ -2834,8 +2840,7 @@ Kanol i [[Special:EditWatchlist|gebön redakametodi kösömik]].',
 
 # Special:SpecialPages
 'specialpages' => 'Pads patik',
-'specialpages-note' => '----
-* Pads patik nomik.
+'specialpages-note' => '* Pads patik nomik.
 * <span class="mw-specialpagerestricted">Pads patik pemiedüköl.</span>',
 'specialpages-group-maintenance' => 'Nunods tefü kiped',
 'specialpages-group-other' => 'Pads patik votik',
@@ -2906,4 +2911,19 @@ Kanol i [[Special:EditWatchlist|gebön redakametodi kösömik]].',
 'duration-centuries' => '{{PLURAL:$1|tumyel|tumyels}} $1',
 'duration-millennia' => '{{PLURAL:$1|milyel|milyels}} $1',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'stäänükön samafomotis',
+'expand_templates_intro' => 'Pad patik at sumon vödemi e stäänükon samafomotis onik valik okvokölo.
+Stäänükon i programasekätis soäs
+<code><nowiki>{{</nowiki>#language:...}}</code> e vödis soäs <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.
+Ibo, stäänükon valikosi vü pärs klämas fridik.',
+'expand_templates_title' => 'Yumedatiäd, pro {{FULLPAGENAME}} e r.:',
+'expand_templates_input' => 'Penolös vödem:',
+'expand_templates_output' => 'Seks',
+'expand_templates_xml_output' => 'Seks fomätü XML',
+'expand_templates_ok' => 'Baiced',
+'expand_templates_remove_comments' => 'Moükön küpetis',
+'expand_templates_generate_xml' => 'Jonön bimi: XML',
+'expand_templates_preview' => 'Büologed',
+
 );
index 3998ef4..1f4be79 100644 (file)
@@ -179,8 +179,6 @@ $messages = array(
 'ok' => 'OK',
 'retrievedfrom' => 'Jälcinnü adresissa "$1"',
 'youhavenewmessages' => 'Teill on $1 ($2).',
-'newmessageslink' => 'Uusiit zapiskoit',
-'newmessagesdifflink' => 'viimõin muutuz',
 'editsection' => 'muuttaa',
 'editold' => 'muuttaa',
 'viewsourceold' => 'lähtekoodi',
@@ -673,7 +671,6 @@ Cüľľellä $2 on spiiska viimeiziss pühcimühsiiss.',
 'undeletecomment' => 'Süü:',
 'undelete-search-submit' => 'Etsi',
 'undelete-show-file-submit' => 'Daa',
-'undelete-revisionrow' => '$1 $2 ($3) $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'Nimiruumi:',
@@ -898,7 +895,7 @@ Kui faili on muutõttu, siiz detaaľid võivad õlla kahõllaizõd muutõtull fa
 
 # External editor support
 'edit-externally' => 'Muuttaa sitä failia ulkopoolizõõ prograammiikaa.',
-'edit-externally-help' => '(Kattsoga [//www.mediawiki.org/wiki/Manual:External_editors praavilõd], kui tahotta lisäinformaattsia.)',
+'edit-externally-help' => '(Kattsoga [https://www.mediawiki.org/wiki/Manual:External_editors praavilõd], kui tahotta lisäinformaattsia.)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'koko istori',
index 7ed5278..9282da1 100644 (file)
@@ -298,8 +298,6 @@ $1",
 'ok' => 'Hää külh',
 'retrievedfrom' => 'Vällä otsit teedüskogost "$1"',
 'youhavenewmessages' => 'Sul om $1 ($2).',
-'newmessageslink' => 'vahtsit sõnomiid',
-'newmessagesdifflink' => 'perämäne muutminõ',
 'youhavenewmessagesmulti' => 'Sullõ om vahtsit sõnomit lehe pääl $1',
 'editsection' => 'toimõndaq',
 'editold' => 'toimõndaq',
@@ -802,8 +800,6 @@ otsisõna iin edejakku ''all:''. Ütest kimmäst nimeruumist otsmisõs pruugiq e
 'preferences' => 'Säädmine',
 'mypreferences' => 'Säädmiseq',
 'prefs-edits' => 'Tõimõndamiisi arv:',
-'prefsnologin' => 'Sa olõ-i nimega sisse lännüq',
-'prefsnologintext' => 'Et säädmiisi tetäq, tulõ sul [[Special:UserLogin|nimega sisse minnäq]].',
 'changepassword' => 'Muudaq salasõnna',
 'prefs-skin' => 'Vällänägemine',
 'skin-preview' => 'Kaeminõ',
@@ -1649,7 +1645,7 @@ Viimädse johtumisõ kõrral võit ka pruukiq linki, nt leht {{MediaWiki:Mainpag
 'allmessagesdefault' => 'Vaikimiisi tekst',
 'allmessagescurrent' => 'Parhillanõ tekst',
 'allmessagestext' => 'Taan nimekirän ommaq kõik MediaWiki nimeruumi tallitusteedüseq.
-Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
+Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "Taad lehte saa-i pruukiq, selle et '''\$wgUseDatabaseMessages'''-säädmine om välän.",
 
 # Thumbnails
@@ -2105,7 +2101,7 @@ Kokkovõttõria pääle või kirotaq tagasivõtmisõ põhjusõ.',
 
 # External editor support
 'edit-externally' => 'Toimõndaq taad teedüstüt välidse programmiga',
-'edit-externally-help' => '(Lisateedüst loeq [//www.mediawiki.org/wiki/Manual:External_editors pruukmisoppusõ lehe päält])',
+'edit-externally-help' => '(Lisateedüst loeq [https://www.mediawiki.org/wiki/Manual:External_editors pruukmisoppusõ lehe päält])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => ', terveq aolugu',
@@ -2207,8 +2203,7 @@ Prooviq harilikku kaehust.',
 
 # Special:SpecialPages
 'specialpages' => 'Tallitusleheküleq',
-'specialpages-note' => '----
-* Hariliguq tallitusleheq.
+'specialpages-note' => '* Hariliguq tallitusleheq.
 * <strong class="mw-specialpagerestricted">Piiredüq tallitusleheq.</strong>',
 'specialpages-group-maintenance' => 'Kõrranpidämisteedüseq',
 'specialpages-group-other' => 'Muuq tallitusleheq',
index 52b3202..ae871a3 100644 (file)
@@ -318,8 +318,6 @@ $1",
 'ok' => "'l est bon",
 'retrievedfrom' => 'Prin del pådje «$1»',
 'youhavenewmessages' => 'Vos avoz des $1 ($2).',
-'newmessageslink' => 'noveas messaedjes',
-'newmessagesdifflink' => 'dierin candjmint',
 'youhavenewmessagesmulti' => 'Vos avoz des noveas messaedjes so $1',
 'editsection' => 'candjî',
 'editold' => 'candjî',
@@ -844,8 +842,6 @@ Vos ploz sayî di mete «all:» pa dvant l' tecse a cweri po cweri dins tot l' c
 'preferences' => 'Preferinces',
 'mypreferences' => 'Mes preferinces',
 'prefs-edits' => 'Nombe di candjmints:',
-'prefsnologin' => "Vos n' estoz nén elodjî",
-'prefsnologintext' => 'I vs fåt esse <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} elodjî]</span> po pleur candjî vos preferinces.',
 'changepassword' => "Candjî l' sicret",
 'prefs-skin' => 'Pea',
 'skin-preview' => 'vey divant',
@@ -1803,7 +1799,7 @@ Dins ç' dierin cas, vos ploz eto eployî ene hårdêye, eg: [[{{#Special:Export
 'allmessagesdefault' => 'Tecse prémetou',
 'allmessagescurrent' => 'Tecse pol moumint',
 'allmessagestext' => "Çouchal est ene djivêye des messaedjes sistinme k' i gn a dins l' espåce di lomaedje ''MediaWiki:''.
-Loukîz les pådjes sol [//www.mediawiki.org/wiki/Localisation Locålijhaedje di MediaWiki] et 
+Loukîz les pådjes sol [https://www.mediawiki.org/wiki/Localisation Locålijhaedje di MediaWiki] et 
 [//translatewiki.net/ translatewiki.net] si vos vloz pårticiper avou l' ratournaeje djenerike di MediaWiki.",
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:AllMessages''' n' est nén sopoirté paski '''\$wgUseDatabaseMessages''' est dismetou.",
 'allmessages-filter-legend' => 'Passete',
@@ -2128,7 +2124,7 @@ est raptiti. Les ôtes seront catchîs.
 
 # External editor support
 'edit-externally' => "Candjî ç' fitchî ci avou on dfoûtrin programe",
-'edit-externally-help' => "(Loukîz les [//www.mediawiki.org/wiki/Manual:External_editors instruccions d' apontiaedje] po pus di racsegnes)",
+'edit-externally-help' => "(Loukîz les [https://www.mediawiki.org/wiki/Manual:External_editors instruccions d' apontiaedje] po pus di racsegnes)",
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'totafwait',
index bd99d85..6cdb3be 100644 (file)
@@ -44,7 +44,6 @@ $specialPageAliases = array(
        'Allpages'                  => array( 'NgatananngaPakli' ),
        'Categories'                => array( 'Mga_kaarangay' ),
        'Contributions'             => array( 'Mga_ámot' ),
-       'Disambiguations'           => array( 'Mga_pansayod' ),
        'Longpages'                 => array( 'HaglabangamgaPakli' ),
        'Mostlinked'                => array( 'Gidamo-iHinSumpay' ),
        'Movepage'                  => array( 'BalhinaAnPakli' ),
@@ -203,8 +202,6 @@ $messages = array(
 'noindex-category' => 'Mga diri nakatudlokan nga pagkli',
 'broken-file-category' => 'Mga pakli nga mayda utod nga mga sumpay hin paypay',
 
-'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
-
 'about' => 'Mahitungod han',
 'article' => 'Pakli hin sulod',
 'newwindow' => '(nabuklad hin bag-o nga tamboan o bintana)',
@@ -341,8 +338,6 @@ $1',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => 'Ginkuha tikang ha "$1"',
 'youhavenewmessages' => 'Mayda ka $1 ($2).',
-'newmessageslink' => 'bag-o nga mga mensahe',
-'newmessagesdifflink' => 'kataposan nga pagbag-o',
 'youhavenewmessagesfromusers' => 'May-ada ka $1 tikang ha {{PLURAL:$3|iba nga gumaramit|$3 mga gumaramit}} ($2).',
 'youhavenewmessagesmanyusers' => 'May-ada ka $1 tikang ha damo nga mga gumaramit ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|uska bag-o nga mensahe|bag-o nga mga mensahe}}',
@@ -1017,7 +1012,6 @@ Ginpapasabot nga an sulod han mga panudlok han {{SITENAME}} in bangin daan an.',
 'preferences' => 'Mga karuyag',
 'mypreferences' => 'Mga akon karuyag',
 'prefs-edits' => 'Ihap han mga pagliwat:',
-'prefsnologin' => 'Diri nakalog-in',
 'changepassword' => 'Igliwan an tigaman-pagsulod',
 'prefs-skin' => 'Panit',
 'skin-preview' => 'Pahiuna nga pagawas',
@@ -2078,7 +2072,7 @@ Makikit-an nimo an ginkuhaaan',
 'tooltip-undo' => '"Igpawara an ginbuhat (undo)" in nagbabalik hinin nga pagliwat ngan nabuklad hin pagliwat nga porma ha pahiuna-nga-paggawas nga kahimtang.  Natugot liwat pagdugang hin katadungan ha dinalikyat nga sumat.',
 'tooltip-preferences-save' => 'Tipiga an mga karuyag',
 'tooltip-summary' => 'Pagbutang hin dalikyat nga sumat',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Attribution
 'siteuser' => '{{SITENAME}} gumaramit $1',
@@ -2343,7 +2337,7 @@ An iba in daan nakatago.
 
 # External editor support
 'edit-externally' => 'Igliwat ini nga fayl gamit han gawas nga aplikasyon',
-'edit-externally-help' => '(Kitaa an [//www.mediawiki.org/wiki/Manual:External_editors mga pagtutdo hin pag-ayad] para han dugang nga pananabutan)',
+'edit-externally-help' => '(Kitaa an [https://www.mediawiki.org/wiki/Manual:External_editors mga pagtutdo hin pag-ayad] para han dugang nga pananabutan)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'ngatanan',
@@ -2444,7 +2438,7 @@ An iba in daan nakatago.
 'version-hook-name' => 'Ngaran han kawil',
 'version-version' => '(Bersion $1)',
 'version-license' => 'Lisensya',
-'version-poweredby-credits' => "Ini nga wiki in pinapaandar han '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Ini nga wiki in pinapaandar han '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'mga iba',
 'version-software-product' => 'Produkto',
 'version-software-version' => 'Bersyon',
index 092ea9d..1f7fc2e 100644 (file)
@@ -327,8 +327,6 @@ $1',
 'ok' => 'waaw',
 'retrievedfrom' => 'Ci « $1 » lañ ko jële',
 'youhavenewmessages' => 'Am nga $1 ($2).',
-'newmessageslink' => 'Bataaxal yu bees',
-'newmessagesdifflink' => 'Coppite gu mujj',
 'youhavenewmessagesmulti' => 'Am nga bataaxal yu yees ci $1',
 'editsection' => 'Soppi',
 'editold' => 'Soppi',
@@ -911,8 +909,6 @@ Jéemala bindaale ''all'' ngir seet ci biir ëmbit gépp (boolewaale ci xëti wa
 'preferences' => 'Tànneef',
 'mypreferences' => 'Samay tànneef',
 'prefs-edits' => 'Limu coppite yi:',
-'prefsnologin' => 'Duggoo',
-'prefsnologintext' => 'Laaj na nga <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} dugg]</span> ngir soppi say tànneef.',
 'changepassword' => 'Coppiteg baatujàll bi',
 'prefs-skin' => 'Melokaan',
 'skin-preview' => 'Wonendil',
@@ -1149,6 +1145,7 @@ Jéemala bindaale ''all'' ngir seet ci biir ëmbit gépp (boolewaale ci xëti wa
 'recentchanges-label-minor' => 'Coppite gu néewal la',
 'recentchanges-label-bot' => 'Coppite bu ab bot def',
 'recentchanges-label-unpatrolled' => 'Coppite bii kenn fugloogu ko',
+'recentchanges-legend-newpage' => '$1 - xët wu bees',
 'rcnote' => '{{PLURAL:$1|Lii mooy coppite bu mujj bees def|Yii ñooy coppite yu mujj yees def}} ci {{PLURAL:$2|bés bu mujj bi|<b>$2</b> bés yu mujj yi}}; njoxe yi ñoo ngi leen yeesal $5 ci $4.',
 'rcnotefrom' => "Yii ñooy coppite yi dalee '''$2''' (ba '''$1''').",
 'rclistfrom' => 'Wone coppite yi mujj yi dooree $1.',
@@ -2097,7 +2094,7 @@ Lëkkalekaay yiy toftal, ci wenn rëdd wi, dees leen di jàppee nikiy sette, maa
 
 # External editor support
 'edit-externally' => 'Soppi xët wii ak ab tëriin bu biti',
-'edit-externally-help' => 'Xoolal [//www.mediawiki.org/wiki/Manual:External_editors tegtali camp gi] ngir yeneeni xamle',
+'edit-externally-help' => 'Xoolal [https://www.mediawiki.org/wiki/Manual:External_editors tegtali camp gi] ngir yeneeni xamle',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'yépp',
index 69a4b97..26ce7e7 100644 (file)
@@ -12,7 +12,9 @@
  * @author O
  * @author Reedy
  * @author Wu-chinese.com
+ * @author Xiaomingyan
  * @author Yfdyh000
+ * @author 乌拉跨氪
  * @author 十弌
  */
 
@@ -140,7 +142,7 @@ $messages = array(
 'december-date' => '12月 $1',
 
 # Categories related messages
-'pagecategories' => '$1个分类',
+'pagecategories' => '{{PLURAL:$1|分类}}',
 'category_header' => '“$1”分類裏個頁',
 'subcategories' => '兒分類',
 'category-media-header' => '"$1"分类里个媒体',
@@ -291,8 +293,6 @@ $1',
 'ok' => '好',
 'retrievedfrom' => '取自“$1”',
 'youhavenewmessages' => '你侬有$1($2)。',
-'newmessageslink' => '新消息',
-'newmessagesdifflink' => '此垡更改',
 'newmessageslinkplural' => '{{PLURAL:$1|新消息}}',
 'newmessagesdifflinkplural' => '此垡̺{{PLURAL:$1|变化}}',
 'youhavenewmessagesmulti' => '爾徠$1裏有新信息',
@@ -839,7 +839,7 @@ $3封禁个原因是''$2''",
 'revdelete-show-file-submit' => '是',
 'revdelete-selected' => "'''选取'''[[:$1]]'''个$2趟修订:'''",
 'logdelete-selected' => "'''选取'''$1'''个日志事件:'''",
-'revdelete-text' => "'''删脱个修订仍然将显示拉页面历史里向不过渠拉个文本内容公众已经弗好访问。'''
+'revdelete-text' => "'''删脱个修订仍然将显示拉页面历史里向不过渠拉个文本内容公众已经弗好访问。'''
 垃拉{{SITENAME}}个其他管理员将仍旧好访问隐藏个内容并通过与此相同个界面恢复删除,除非站点工作者添加了附加限制。",
 'revdelete-confirm' => '假使侬想箇能介做个闲话,请确认侬已经清爽箇能介做个后果,外加箇个程序符合[[{{MediaWiki:Policy-url}}|政策]]。',
 'revdelete-suppress-text' => "'''只有'''出现下头眼情况再应阻止访问:
@@ -992,8 +992,6 @@ $1",
 'preferences' => '偏好',
 'mypreferences' => '偏好设定',
 'prefs-edits' => '编辑数量:',
-'prefsnologin' => '朆登录',
-'prefsnologintext' => '侬必须先<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登录]</span>再好设置个人参数。',
 'changepassword' => '改密码',
 'prefs-skin' => '皮肤',
 'skin-preview' => '预览',
@@ -1342,7 +1340,7 @@ $1",
 
 # Book sources
 'booksources' => '书源',
-'booksources-search-legend' => '搜索网络书源',
+'booksources-search-legend' => '搜索图书来源',
 'booksources-go' => '去',
 
 # Special:Log
@@ -1441,7 +1439,7 @@ $1",
 # Rollback
 'rollback' => '恢复编辑',
 'rollback_short' => '恢复',
-'rollbacklink' => '恢复',
+'rollbacklink' => '回退',
 'rollbackfailed' => '恢复失败',
 'revertpage' => '恢复[[Special:Contributions/$2|$2]] ([[User talk:$2|讲张]])个改动;恢复到[[User:$1|$1]]个上一版本',
 
@@ -1665,7 +1663,7 @@ $1",
 'tooltip-rollback' => '揿一记“回转”就回退到上一位贡献者个编辑状态',
 'tooltip-undo' => '“撤销”可以恢复该编辑并且垃拉预览模式下头打开编辑表单。渠允许垃拉摘要里向说明原因。',
 'tooltip-summary' => '打进短摘要',
-'tooltip-iwiki' => '̩$1 - $2',
+'interlanguage-link-title' => '̩$1 - $2',
 
 # Attribution
 'anonymous' => '{{SITENAME}}浪个匿名用户',
@@ -1739,7 +1737,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => '用外部应用程序来编辑该只文件',
-'edit-externally-help' => '(请参见[//www.mediawiki.org/wiki/Manual:External_editors 设置步骤]了解详细信息)',
+'edit-externally-help' => '(请参见[https://www.mediawiki.org/wiki/Manual:External_editors 设置步骤]了解详细信息)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
index a0edc0c..81275b9 100644 (file)
@@ -306,8 +306,6 @@ $1',
 'ok' => 'Тиим',
 'retrievedfrom' => '"$1" гидг халхас йовулсн',
 'youhavenewmessages' => 'Та $1та бәәнәт ($2).',
-'newmessageslink' => 'шин зәңгс',
-'newmessagesdifflink' => 'шидрә сольлһн',
 'youhavenewmessagesmulti' => 'Таньд $1 деер шин зәңг ирсн бәәнә.',
 'editsection' => 'чиклх',
 'editold' => 'чиклх',
@@ -592,8 +590,6 @@ $1',
 'preferences' => 'Дурллһн',
 'mypreferences' => 'Көгүд',
 'prefs-edits' => 'Чикллһнә то:',
-'prefsnologin' => 'Та харһв биш',
-'prefsnologintext' => 'Та <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} харһх]</span> кергтә,  тегәд көгүдиг сольҗ чаднат.',
 'changepassword' => 'Нууц үгиг сольҗ',
 'prefs-skin' => 'Хувцнь',
 'skin-preview' => 'Хәләвр',
@@ -707,6 +703,7 @@ $1',
 'recentchanges-label-newpage' => 'Тер үүләр шин халх бүтәв',
 'recentchanges-label-minor' => 'Эн баһ чинртә сольлһн',
 'recentchanges-label-bot' => 'Эн сольлһн көдлвр (робот) кехв',
+'recentchanges-legend-newpage' => '$1 — шин халх',
 'rcnote' => "{{PLURAL:$1|'''$1''' шидрә сольлһн|'''$1''' шидрә сольлһн|'''$1''' шидрә сольлһн}}, '''$2''' өдрә,  $5 $4 цагин.",
 'rclistfrom' => 'Тер цагас авн сольлһн үзүлх: $1.',
 'rcshowhideminor' => 'баһ чикллһиг $1',
@@ -1166,7 +1163,7 @@ $2 шидрә һарһлһна төлә хәләтн.',
 
 # External editor support
 'edit-externally' => 'Эн боомгиг һаза заклһар чиклх',
-'edit-externally-help' => '([//www.mediawiki.org/wiki/Manual:External_editors Тәвллһнә заалт]  икәр өггцнә төлә хәләтн)',
+'edit-externally-help' => '([https://www.mediawiki.org/wiki/Manual:External_editors Тәвллһнә заалт]  икәр өггцнә төлә хәләтн)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'цуг',
index d3e036a..97ce03f 100644 (file)
@@ -203,8 +203,6 @@ $messages = array(
 'ok' => 'ჯგირი',
 'retrievedfrom' => 'გორილ რე "$1"-იშე',
 'youhavenewmessages' => 'თქვა გიღუნა $1 ($2).',
-'newmessageslink' => 'ახალი შატყვინაფეფი',
-'newmessagesdifflink' => 'ეკონია თირაფა',
 'editsection' => 'რედაქტირაფა',
 'editold' => 'რედაქტირაფა',
 'viewsourceold' => 'წყუშ ძირაფა',
@@ -883,7 +881,7 @@ $messages = array(
 
 # External editor support
 'edit-externally' => 'თე ფაილიშ ორედაქტირაფალო გიმირინეთ გალენ პროგრამა',
-'edit-externally-help' => '(უმოს ინფორმაციაშო ქოძირით [//www.mediawiki.org/wiki/Manual:External_editors])',
+'edit-externally-help' => '(უმოს ინფორმაციაშო ქოძირით [https://www.mediawiki.org/wiki/Manual:External_editors])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'არძა',
index 22c9ed3..5bf7c1b 100644 (file)
@@ -71,7 +71,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( 'אוראלטע_בלעטער' ),
        'Blankpage'                 => array( 'ליידיגער_בלאט' ),
        'Block'                     => array( 'בלאקירן' ),
-       'Blockme'                   => array( 'בלאקירט_מיך' ),
        'BrokenRedirects'           => array( 'צעבראכענע_ווייטערפירונגען' ),
        'Categories'                => array( 'קאטעגאריעס' ),
        'ChangePassword'            => array( 'ענדערן_פאסווארט' ),
@@ -81,7 +80,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( 'שאפֿן_קאנטע' ),
        'Deadendpages'              => array( 'בלעטער_אן_פארבינדונגען' ),
        'DeletedContributions'      => array( 'אויסגעמעקעטע_בײַשטײַערונגען' ),
-       'Disambiguations'           => array( 'באדייטן' ),
        'DoubleRedirects'           => array( 'פארטאפלטע_ווייטערפירונגען' ),
        'Emailuser'                 => array( 'שיקן_אן_ע-פאסט_צום_באניצער' ),
        'Export'                    => array( 'עקספארט' ),
@@ -162,6 +160,7 @@ $magicWords = array(
        'numberofarticles'          => array( '1', 'צאל_ארטיקלען', 'מספר ערכים', 'NUMBEROFARTICLES' ),
        'numberoffiles'             => array( '1', 'צאל_טעקעס', 'מספר קבצים', 'NUMBEROFFILES' ),
        'numberofusers'             => array( '1', 'צאל_באניצער', 'מספר משתמשים', 'NUMBEROFUSERS' ),
+       'numberofedits'             => array( '1', 'צאל_רעדאקטירונגען', 'מספר עריכות', 'NUMBEROFEDITS' ),
        'pagename'                  => array( '1', 'בלאטנאמען', 'שם הדף', 'PAGENAME' ),
        'namespace'                 => array( '1', 'נאמענטייל', 'מרחב השם', 'NAMESPACE' ),
        'fullpagename'              => array( '1', 'פולבלאטנאמען', 'שם הדף המלא', 'FULLPAGENAME' ),
@@ -178,6 +177,7 @@ $magicWords = array(
        'img_sub'                   => array( '1', 'אונטער', 'תחתי', 'sub' ),
        'img_super'                 => array( '1', 'איבער', 'עילי', 'super', 'sup' ),
        'img_top'                   => array( '1', 'אויבן', 'למעלה', 'top' ),
+       'img_middle'                => array( '1', 'אינמיטן', 'באמצע', 'middle' ),
        'img_bottom'                => array( '1', 'אונטן', 'למטה', 'bottom' ),
        'img_link'                  => array( '1', 'לינק=$1', 'קישור=$1', 'link=$1' ),
        'img_alt'                   => array( '1', 'טעקסט=$1', 'טקסט=$1', 'alt=$1' ),
@@ -192,6 +192,7 @@ $magicWords = array(
        'hiddencat'                 => array( '1', '__באהאלטענע_קאטעגאריע__', '__באהאלטענע_קאט__', '__קטגוריה_מוסתרת__', '__HIDDENCAT__' ),
        'pagesize'                  => array( '1', 'בלאטגרייס', 'גודל דף', 'PAGESIZE' ),
        'url_wiki'                  => array( '0', 'וויקי', 'ויקי', 'WIKI' ),
+       'pagesincategory_pages'     => array( '0', 'בלעטער', 'דפים', 'pages' ),
 );
 
 $messages = array(
@@ -471,12 +472,10 @@ $1',
 'backlinksubtitle' => '→ $1',
 'retrievedfrom' => 'גענומען פֿון "$1"',
 'youhavenewmessages' => 'איר האט $1 ($2).',
-'newmessageslink' => 'נייע מעלדונגען',
-'newmessagesdifflink' => 'לעצטע ענדערונג',
 'youhavenewmessagesfromusers' => 'איר האט $1 פון {{PLURAL:$3|אן אנדער באניצער|$3 באניצער}} ($2).',
 'youhavenewmessagesmanyusers' => 'איר האט $1 פון אסאך באניצער ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|א נייע מעלדונג|נייע מעלדונגען}}',
-'newmessagesdifflinkplural' => 'לעצטע {{PLURAL:$1|ענדערונג|ענדערונגען}}',
+'newmessageslinkplural' => '{{PLURAL:$1|א נייע מעלדונג|999=נייע מעלדונגען}}',
+'newmessagesdifflinkplural' => 'לעצטע {{PLURAL:$1|ענדערונג|999=ענדערונגען}}',
 'youhavenewmessagesmulti' => 'איר האט נייע מעלדונגען אין $1',
 'editsection' => 'באַאַרבעטן',
 'editold' => 'רעדאַקטירן',
@@ -608,7 +607,8 @@ $2',
 'invalidtitle-knownnamespace' => 'אומגילטירער טיטל מיט נאמענטייל "$2" און טעקסט "$3"',
 'invalidtitle-unknownnamespace' => 'אומגילטיקער טיטל מיט אומבאוואוסטן נאמענטייל נומער $1 און טעקסט "$2"',
 'exception-nologin' => 'נישט אַרײַנלאגירט',
-'exception-nologin-text' => 'דער בלאט אדער אקציע פֿאדערט אז איר זענט אריינלאגירט ביי דער וויקי.',
+'exception-nologin-text' => 'איר שאפרט זיין [[Special:Userlogin|אריינלאגירט]] to כדי צו קענען צוקומען צו דעם בלאט אדער דער אקציע.',
+'exception-nologin-text-manual' => 'זייט אזוי גוט $1 כדי צו קענען צוקומען צו דעם בלאט אדער דער אקציע.',
 
 # Virus scanner
 'virus-badscanner' => "שלעכטע קאנפֿיגוראציע: אומבאוואוסטער ווירוס איבערקוקער: ''$1''",
@@ -655,7 +655,7 @@ $2',
 'gotaccount' => "האסטו שוין א קאנטע? '''$1'''.",
 'gotaccountlink' => 'אַרײַנלאגירן',
 'userlogin-resetlink' => 'פארגעסן אײַערע אַרײַנלאָגירן פרטים?',
-'userlogin-resetpassword-link' => 'צ×\95ר×\99קש×\98×¢×\9c×\9f ×\90ײַער ×¤×\90ַס×\95×\95×\90ר×\98',
+'userlogin-resetpassword-link' => 'פֿ×\90ַר×\92עס×\9f ×\90ײַער ×¤×\90ַס×\95×\95×\90ר×\98?',
 'helplogin-url' => 'Help:אריינלאגירן',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|הילף מיט אריינלאגירן]]',
 'userlogin-loggedin' => 'איר זענט שוין אריינלאגירט ווי {{GENDER:$1|$1}}.
@@ -726,14 +726,15 @@ $2',
 'passwordsent' => 'א ניי פאסווארט איז געשיקט געווארן צום ע-פאסט אדרעס רעגיסטרירט פאר "$1".
 ביטע ווידער אריינלאגירן נאך דעם וואס איר באקומט עס.',
 'blocked-mailpassword' => 'אייער איי פי אדרעס איז בלאקירט צו רעדאקטירן, דערוועגן זענט איר נישט ערלויבט צו באניצן מיטן פאסווארט ווידעראויפלעבונג פֿונקציע כדי צו פארמיידן סיסטעם קרומבאניץ.',
-'eauthentsent' => '×\90 ×\91×\90ש×\98×¢×\98×\99×\92×\95× ×\92 ×¢-×\91ר×\99×\95×\95 ×\90×\99×\96 ×\92עש×\99ק×\98 ×\92×¢×\95×\95×\90ר×\9f ×¦×\95 ×\93×¢×\9d ×\91×\90ש×\98×\99×\9e×\98×\9f ×¢-פ×\90ס×\98 ×\90×\93רעס. ×\90×\99×\99×\93ער ×¡×\99×\99 ×\95×\95×\90ס אנדערע ע-פאסט וועט ווערן געשיקט צו דער קאנטע, וועט איר דארפן פאלגן די אנווייזונגען אין דער מעלדונג כדי צו זיין זיכער אז די קאנטע איז טאקע אייערס.',
+'eauthentsent' => '×\90 ×\91×\90ש×\98×¢×\98×\99×\92×\95× ×\92 ×¢-×\91ר×\99×\95×\95 ×\90×\99×\96 ×\92עש×\99ק×\98 ×\92×¢×\95×\95×\90ר×\9f ×¦×\95 ×\93×¢×\9d ×\91×\90ש×\98×\99×\9e×\98×\9f ×¢-פ×\90ס×\98 ×\90×\93רעס. ×\90×\99×\99×\93ער ×¡×\99×\99 ×\95×\95×¢×\9c×\9b×¢ אנדערע ע-פאסט וועט ווערן געשיקט צו דער קאנטע, וועט איר דארפן פאלגן די אנווייזונגען אין דער מעלדונג כדי צו זיין זיכער אז די קאנטע איז טאקע אייערס.',
 'throttled-mailpassword' => "מ'האט שוין געשיקט א בליצבריוו צוריקצושטעלן דאס פאסווארט, אין {{PLURAL:$1|דער לעצטער שעה|די לעצטע $1 שעה'ן}}. כדי צו פארמײַדן שלעכט באניצן, נאר איין פאסווארט צוריקשטעלן בליצבריוו וועט געשיקט ווערן אין {{PLURAL:$1|א שעה |$1 שעה'ן}}.",
 'mailerror' => 'פֿעלער שיקנדיג פאסט: $1',
 'acct_creation_throttle_hit' => 'באַזוכער צו דער וויקי וואס באַניצן אייער IP אַדרעס האָבן שױן באַשאַפֿן {{PLURAL:$1|1 קאנטע|$1 קאנטעס}} במשך דעם לעצטן טאָג, דעם מאַקסימום וואָס מען ערלויבט אין דעם פעריאד.
 
 דערפֿאַר קענען באַזוכער וואס באַניצן דעם  IP אַדרעס נישט מער שאַפֿן נײַע קאָנטעס דערווײַל.',
 'emailauthenticated' => 'אייער ע-פאסט אדרעס איז באשטעטיגט געווארן אום $2, $3.',
-'emailnotauthenticated' => 'אײַער ע-פאסט אדרעס איז נאכנישט באשטעטיגט. קיין ע-פאסט וועט נישט ווערן געשיקט פון קיין איינע פון די פאלגנדע אייגנקייטן.',
+'emailnotauthenticated' => 'אײַער ע-פאסט אדרעס איז נאכנישט באשטעטיגט. 
+קיין ע-פאסט וועט נישט ווערן געשיקט פון קיין איינע פון די פאלגנדע אייגנקייטן.',
 'noemailprefs' => 'ספעציפֿירט אן ע־פאסט אַדרעס אין אײַער פרעפֿערענצן כדי די פֿעאיקייטן זאלן אַרבעטן.',
 'emailconfirmlink' => 'באַשטעטיקט אײַער ע-פאסט אַדרעס',
 'invalidemailaddress' => 'דער ע-פאסט אדרעס קען נישט אקצעפטירט ווערן ווייל ער שיינט צו האבן אן אומגילטיגן פֿארמאט.
@@ -1170,19 +1171,20 @@ $2
 'revdelete-text' => "'''אויסגעמעקטע רעוויזיעס און געשעענישן וועלן בלייבן אין דער בלאט היסטאריע און די לאגביכער, אבער טיילן פון זייער אינהאלט וועט ווערן אומגרייכלעך צום קהל. '''
 אנדערע סיסאפן אויף {{SITENAME}} וועלן נאך האבן צוטריט צום באהאלטענעם אינהאלט און קענען אים צוריקשטעלן דורך דעם זעלבן אייבערפלאך,  אחוץ ווען מען שטעלט נאך באגרענעצונגען.",
 'revdelete-confirm' => 'זייט אזוי גוט און באשטעטיקט אז דאס איז טאקע אייער כוונה, אז איר פארשטייט די קאנסעקווענצן, און אז איר טוט דאס לויט  [[{{MediaWiki:Policy-url}}|דער פאליסי]].',
-'revdelete-suppress-text' => "באהאלטן זאל בלויז גענוצט ווערן '''נאר''' אין די פאלגענדע פעלער:
+'revdelete-suppress-text' => "אונטערדרוקן זאל בלויז גענוצט ווערן '''נאר''' אין די פאלגנדע פעלער:
+* אינפארמאציע וואס קען זיין מוציא שם רע
 * אויפדעקונג פון פריוואטקייט אינפארמאציע
-* ''היים אדרעסן, טעלעפאן נומערן, אדער סאשעל סעקיורעטי, א.א.וו.:'''",
+*: ''היים אדרעסן, טעלעפאן נומערן, נאציאנאלע אידענטיפיקאציע נומערן, א.א.וו.''",
 'revdelete-legend' => 'שטעלט ווייזונג באגרענעצונגען',
-'revdelete-hide-text' => '×\91×\90×\94×\90×\9c×\98 ×\90×\99× ×\94×\90×\9c×\98 ×¤×\95×\9f ×\95×\95ערס×\99×¢',
+'revdelete-hide-text' => '×\95×\95ערס×\99×¢ ×\98עקס×\98',
 'revdelete-hide-image' => 'באהאלט טעקע אינהאלט',
 'revdelete-hide-name' => 'באהאלט אקציע און ציל',
-'revdelete-hide-comment' => '×\91×\90×\94×\90×\9c×\98 ×¢× ×\93ער×\9f ×\94ער×\94',
-'revdelete-hide-user' => "×\91×\90Ö·×\94×\90Ö·×\9c×\98×\9f ×¨×¢×\93×\90ַק×\98×\90ר'ס ×\91×\90× ×\99צער-× ×\90×\9e×¢×\9f/IP-×\90Ö·×\93רעס",
+'revdelete-hide-comment' => 'רע×\93×\90ק×\98×\99ר×\95× ×\92 ×¨×¢×\96×\95×\9e×¢',
+'revdelete-hide-user' => "רעדאַקטאר'ס באניצער-נאמען/IP-אַדרעס",
 'revdelete-hide-restricted' => 'באהאלט אינפארמאציע אויך פון אדמיניסטראטורן פונקט ווי פשוטע באנוצער',
 'revdelete-radio-same' => '(נישט ענדערן)',
-'revdelete-radio-set' => '×\99×\90',
-'revdelete-radio-unset' => '× ×\99×\99×\9f',
+'revdelete-radio-set' => 'פֿ×\90ַר×\91×\90ָר×\92×\9f',
+'revdelete-radio-unset' => '×\96×¢×\91×\90ר',
 'revdelete-suppress' => 'באַהאַלטן אינפֿארמאַציע פון אַדמיניסטראַטארן ווי אויך אנדערע',
 'revdelete-unsuppress' => 'טוה אפ באגרענעצונגן אין גענדערטע רעוויזיעס',
 'revdelete-log' => 'אורזאַך:',
@@ -1340,8 +1342,7 @@ $1",
 'preferences' => 'פרעפֿערענצן',
 'mypreferences' => 'פּרעפֿערענצן',
 'prefs-edits' => 'צאָל ענדערונגען:',
-'prefsnologin' => 'נישט אריינלאגירט',
-'prefsnologintext' => 'איר דארפט זיין  <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} אריינלאגירט]</span> כדי צו ענדערן באניצער פרעפֿערענצן.',
+'prefsnologintext2' => 'זייט אזוי גוט $1 כדי צו שטעלן באניצער פרעפערענצן.',
 'changepassword' => 'טוישן פאַסווארט',
 'prefs-skin' => 'סקין',
 'skin-preview' => 'פארויסדיגע ווייזונג',
@@ -1481,6 +1482,8 @@ $1",
 'userrights-notallowed' => 'איר האט נישט קיין ערלויבניש צוצולייגן אדער אוועקנעמען באַניצער רעכטן.',
 'userrights-changeable-col' => 'גרופעס איר קענט ענדערן',
 'userrights-unchangeable-col' => 'גרופעס איר קענט נישט ענדערן',
+'userrights-conflict' => 'קאנפֿליקט פון באניצער־רעכטן ענדערונגען! זייט אזוי גוט רעצענזירן און באשטעטיקן אײַערע ענדערונגען.',
+'userrights-removed-self' => 'איר האט דערפאלגרייך אראפגענומען אייערע אייגענע רעכטע. אזוי קענט איר מער נישט דערגרייכן דעם בלאט.',
 
 # Groups
 'group' => 'גרופע:',
@@ -1543,6 +1546,7 @@ $1",
 'right-blockemail' => 'בלאקירן א באַניצער פֿון שיקן ע־פאסט',
 'right-hideuser' => 'בלאקירן באַניצער־נאָמען און פֿאַרבארגן אים',
 'right-ipblock-exempt' => 'ארומגיין IP בלאקן, אויטאבלאקן און גרייך־בלאקן',
+'right-proxyunbannable' => 'ארומגיין אויטאמאטישע בלאקירן פון פראקסיס',
 'right-unblockself' => 'זיך אליין אויפֿשפאַרן',
 'right-protect' => 'ענדערן שוץ ניוואען און רעדאַגירן קאסקאד־געשיצטע בלעטער',
 'right-editprotected' => 'רעדאַגירן בלעטער געשיצט ווי "{{int:protect-level-sysop}}"',
@@ -1554,6 +1558,7 @@ $1",
 'right-editmyusercss' => 'רעדאקטירע אײַערע אייגענע באניצער CSS טעקעס',
 'right-editmyuserjs' => 'רעדאקטירן אײַערע אייגענע באניצער JavaScript טעקעס',
 'right-viewmywatchlist' => 'באקוקן אייער אייגענע אויפפאסונג ליסטע',
+'right-editmywatchlist' => 'רעדאקטירן אייער אייגענע אויפפאסונג ליסטער. טייל פעולות וועלן דאך צולייגן בלעטער אפילו אן דעם רעכט.',
 'right-viewmyprivateinfo' => 'באקוקן אײַער אייגענע פריוואטע דאטן (צ"ב ע־פאסט אדרעס, אמתער נאמען)',
 'right-editmyprivateinfo' => 'רעדאקטירן אײַער אייגענע פריוואטע דאטן (צ"ב ע־פאסט אדרעס, אמתער נאמען)',
 'right-editmyoptions' => 'רעדאקטירן אײַערע אייגענע פרעפערענצן',
@@ -1636,6 +1641,8 @@ $1",
 'recentchanges-label-minor' => 'דאָס איז אַ מינערדיקע רעדאַקטירונג',
 'recentchanges-label-bot' => ' די רעדאַקטירונג האט אויסגעפירט א באט',
 'recentchanges-label-unpatrolled' => 'די רעדאקטירונג איז נאך נישט נאכגעקוקט',
+'recentchanges-label-plusminus' => 'בלאט גרייס געענדערט מיט דער אצל בייטן',
+'recentchanges-legend-newpage' => '(זעים אויך [[Special:NewPages|די רשימה פון נייע בלעטער]])',
 'rcnote' => "אונטן {{PLURAL:$1|איז '''1''' ענדערונג|זײַנען די לעצטע '''$1''' ענדערונגען}} אין {{PLURAL:$2|דעם לעצטן טאג|די לעצטע $2 טעג}}, ביז $5, $4.",
 'rcnotefrom' => "פֿאלגנד זענען די ענדערונגען זײַט '''$2''' (ביז '''$1''')",
 'rclistfrom' => 'װײַזן נײַע ענדערונגען פֿון $1',
@@ -2098,6 +2105,7 @@ $1",
 'listusers' => 'באַניצער ליסטע',
 'listusers-editsonly' => 'ווייזן נאר באניצערס מיט רעדאקטירונגען',
 'listusers-creationsort' => 'סארטירן לויט דער שאַפן דאַטע',
+'listusers-desc' => 'סארטירן אין אראפרשטייגעדיקן סדר',
 'usereditcount' => '{{PLURAL:$1|רעדאַקטירונג|$1 רעדאַקטירונגען}}',
 'usercreated' => '{{GENDER:$3|געשאַפֿן}} אום $2, $1',
 'newpages' => 'נייע בלעטער',
@@ -2313,7 +2321,7 @@ $PAGEINTRO $NEWPAGE
 ע-פאסט: $PAGEEDITOR_EMAIL
 וויקי: $PAGEEDITOR_WIKI
 
-עס ×\95×\95×¢×\98 ×\9eער × ×\99ש×\98 ×\96×\99×\99×\9f ×§×\99×\99×\9f ×\9e×¢×\9c×\93×\95× ×\92×¢×\9f ×\90×\99×\9f ×¤×\90×\9c ×¤×\95×\9f × ×\90×\9a ×¢× ×\93ער×\95× ×\92×¢×\9f × ×\90ר ×\90×\95×\99×\91 ×\90×\99ר ×\95×\95×¢×\98 ×\91×\90×\96×\95×\9b×\9f ×\93×¢×\9d ×\91×\9c×\90ט.
+עס ×\95×\95×¢×\98 ×\9eער × ×\99ש×\98 ×\96×\99×\99×\9f ×§×\99×\99×\9f ×\9e×¢×\9c×\93×\95× ×\92×¢×\9f ×\90×\99×\9f ×¤×\90×\9c ×¤×\95×\9f × ×\90×\9a ×\90ק×\98×\99×\95×\95×\99×\98×¢×\98 × ×\90ר ×\90×\95×\99×\91 ×\90×\99ר ×\95×\95×¢×\98 ×\91×\90×\96×\95×\9b×\9f ×\93×¢×\9d ×\91×\9c×\90×\98 ×\95×\95×¢×\9f ×\90ר×\99×\99× ×\9c×\90×\92×\99רט.
 איר קענט אויך צוריקשטעלן די מעלדונגען פאנען פון אלע אייערע אויפֿגעפאסטע בלעטער אין אייער אויפפאסונג ליסטע.
 
 אייער פֿריינטליכע  {{SITENAME}} מעלדונגען סיסטעם
@@ -2502,7 +2510,6 @@ $UNWATCHURL
 $1',
 'undelete-show-file-confirm' => 'צי זענט איר זעכער איר ווילט באַקוקן די אויסגעמעקטע רעוויזיע פון דער טעקע "<nowiki>$1</nowiki>" פון $2 בשעה $3?',
 'undelete-show-file-submit' => 'יא',
-'undelete-revisionrow' => '$1 $2 $3 $4 . . $5 $6 $7',
 
 # Namespace form on various pages
 'namespace' => 'נאמענטייל:',
@@ -2826,7 +2833,7 @@ $1',
 
 סיסאפן קענען ענדערן די מעלדונגען דורך דרוקן אויפן נאמען פון דער מעלדונג.
 
-ביטע באזוכט [//www.mediawiki.org/wiki/Localisation מעדיעוויקי לאקאליזאציע] און [//translatewiki.net בעטאוויקי] אויב איר ווילט ביישטייערן צו דער גענערישער מעדיעוויקי לאקאליזאציע.',
+ביטע באזוכט [https://www.mediawiki.org/wiki/Localisation מעדיעוויקי לאקאליזאציע] און [//translatewiki.net בעטאוויקי] אויב איר ווילט ביישטייערן צו דער גענערישער מעדיעוויקי לאקאליזאציע.',
 'allmessagesnotsupportedDB' => 'מען קען זיך נישט באניצן מיט דעם בלאט וויבאלד די $wgUseDatabseMessages איז געווארן בטל.',
 'allmessages-filter-legend' => 'פילטער',
 'allmessages-filter' => 'פֿילטערן לויטן סטאטוס פון מעלדונג:',
@@ -3120,7 +3127,7 @@ $1',
 'file-nohires' => 'נישטא מיט א העכערער רעזאלוציע.',
 'svg-long-desc' => 'טעקע SVG, נאמינעל: $1 × $2 פיקסעלן, טעקע גרייס: $3',
 'svg-long-error' => 'אומגילטיקע SVG טעקע: $1',
-'show-big-image' => '×\91×\99×\9c×\93 ×\9e×\99×\98 ×\93ער ×\92רעס×\98ער ×¨×¢×\96×\90×\9c×\95צ×\99ע',
+'show-big-image' => '×\90ר×\92×\99× ×¢×\9c×¢ ×\98עקע',
 'show-big-image-preview' => 'גרייס פון דעם פארויסקוק: $1.',
 'show-big-image-other' => '{{PLURAL:$2|אנדער רעזאלוציע|אנדערע רעזאלוציעס}}: $1.',
 'show-big-image-size' => '$1 × $2 פיקצעלן',
@@ -3527,7 +3534,7 @@ $1',
 
 # External editor support
 'edit-externally' => 'רעדאַקטירט די טעקע מיט א דרויסנדיגער אַפליקאַציע',
-'edit-externally-help' => 'זעט די [//www.mediawiki.org/wiki/Manual:External_editors אויפֿשטעל אנווייזונגען] פאר מער אינפארמאציע.',
+'edit-externally-help' => 'זעט די [https://www.mediawiki.org/wiki/Manual:External_editors אויפֿשטעל אנווייזונגען] פאר מער אינפארמאציע.',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'אַלע',
@@ -3766,10 +3773,8 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'ספּעציעלע זײַטן',
-'specialpages-note' => '----
-* נארמאַלע באַזונדערע בלעטער.
-* <strong class="mw-specialpagerestricted">באַגרענעצטע באַזונדערע בלעטער.</strong>
-* <span class="mw-specialpagecached">באַזונדערע בלעטער פֿון זאַפאַס (קענען זײַן פֿאַרעלטערט).</span>',
+'specialpages-note' => '* נארמאַלע באַזונדערע בלעטער.
+* <span class="mw-specialpagerestricted">באַגרענעצטע באַזונדערע בלעטער.</span>',
 'specialpages-group-maintenance' => 'אויפֿהאַלטונג באַריכטן',
 'specialpages-group-other' => 'אַנדערע ספעציעלע בלעטער',
 'specialpages-group-login' => 'ארײַנלאגירן / שאַפֿן קאנטע',
@@ -3977,4 +3982,12 @@ $5
 'limitreport-expansiondepth' => 'גרעסטע אויסשפרייט טיף',
 'limitreport-expensivefunctioncount' => 'צאל פזרנישע פארזער־פֿונקציעס',
 
+# Special:ExpandTemplates
+'expandtemplates' => 'פרואוו מוסטערן',
+'expand_templates_input' => 'אײַנגעבן טעקסט',
+'expand_templates_output' => 'רעזולטאט',
+'expand_templates_xml_output' => 'XML אויסגאָב',
+'expand_templates_ok' => 'אויספֿירן',
+'expand_templates_preview' => 'פֿאראויסשטעלונג',
+
 );
index 1d2c0b2..14a1975 100644 (file)
@@ -60,12 +60,12 @@ $messages = array(
 'tog-hidepatrolled' => 'Ìbòmọ́lẹ̀ àwọn àtúnṣe oníìṣọ́ nínú àwọn àtúnṣe tuntun',
 'tog-newpageshidepatrolled' => 'Ìbòmọ́lẹ̀ àwọn ojúewé oníìṣọ́ lọ́dọ̀ àtòjọ ojúewé tuntun',
 'tog-extendwatchlist' => "Ìfẹ̀ àmójútó láti ṣ'àfihàn gbogbo àtúnṣe, kìí ṣe tuntun nìkan",
-'tog-usenewrc' => 'Ìtò àwọn àtúnṣe gẹ́gẹ́bí ojúewé nínú àwọn àtúnṣe tuntun àti ìmújútó (JavaScript pọndandan)',
+'tog-usenewrc' => 'Ìtò àwọn àtúnṣe gẹ́gẹ́bí ojúewé nínú àwọn àtúnṣe tuntun àti ìmújútó',
 'tog-numberheadings' => 'Àwọn àkọlé nọmba-araẹni',
-'tog-showtoolbar' => 'Ìfihàn pẹpẹ irinṣẹ́ àtúnṣe (JavaScript pọndandan)',
-'tog-editondblclick' => "Ṣ'àtúnṣe àwọn ojúewé ní kíkàn lẹ́mẹjì (JavaScript)",
+'tog-showtoolbar' => 'Ìfihàn pẹpẹ irinṣẹ́ àtúnṣe',
+'tog-editondblclick' => "Ṣ'àtúnṣe àwọn ojúewé ní kíkàn lẹ́mẹjì",
 'tog-editsection' => 'Ìgbàláyè àtúnṣe abala láti inú [àtúnṣe] àwọn àjápọ̀',
-'tog-editsectiononrightclick' => 'Ìgbàláyè àtúnṣe abala nípa klííkì ọ̀tún lórí àkọlé abala (JavaScript pọndandan)',
+'tog-editsectiononrightclick' => 'Ìgbàláyè àtúnṣe abala nípa klííkì ọ̀tún lórí àkọlé abala',
 'tog-showtoc' => 'Ìfihàn tábìlì àkóónú (fún àwọn ojúewé tó ní ju orí ọ̀rọ̀ 3 lọ)',
 'tog-rememberpassword' => "Ṣè'rántí àkọọ́lẹ̀ ìwọlé mi lórí agbétàkùn yìí (fún {{PLURAL:$1|ọjọ́|ọjọ́}} $1 pípẹ́jùlọ)",
 'tog-watchcreations' => "Ṣ'àfikún ojúewé tí mo dá àti àwọn fáìlì tí mo rùsókè mọ́ ìmójútó mi",
@@ -83,7 +83,7 @@ $messages = array(
 'tog-shownumberswatching' => "S'àfihàn iye àwọn oníṣe tí wọn tẹjú mọ́ọ",
 'tog-oldsig' => 'Ìtọwọ́bọ̀wé tówà:',
 'tog-fancysig' => 'Ṣe ìtọwọ́bọ̀wé bíi ìkọ wiki (láìní ìjápọ̀ fúnrararẹ̀)',
-'tog-uselivepreview' => 'Ìlo àkọ́kọ́yẹ̀wò lẹ́ṣẹ̀kẹṣẹ̀ (JavaScript pọndandan) (aládànhánwò)',
+'tog-uselivepreview' => 'Ìlo àkọ́kọ́yẹ̀wò lẹ́ṣẹ̀kẹṣẹ̀ (àdánwò)',
 'tog-forceeditsummary' => 'Kìlọ̀ fún mi tí àkótán àtúnṣe bá jẹ́ òfo',
 'tog-watchlisthideown' => 'Ìbòmọ́lẹ̀ àwọn àtúnṣe mi nínú ìmójútó',
 'tog-watchlisthidebots' => 'Ìbòmọ́lẹ̀ àwọn àtúnṣe bot nínú ìmójútó',
@@ -196,7 +196,7 @@ $messages = array(
 'newwindow' => '(yíò sí nínú fèrèsè tuntun)',
 'cancel' => 'Fagilé',
 'moredotdotdot' => 'Ẹ̀kúnrẹ́rẹ́...',
-'morenotlisted' => 'Àtòjọ kíkúnrẹ́rẹ́ kò sí...',
+'morenotlisted' => 'Àtòjọ yìí kò kúnrẹ́rẹ́.',
 'mypage' => 'Ojúewé',
 'mytalk' => 'Ọ̀rọ̀',
 'anontalk' => 'Ọ̀rọ̀ fún IP yí',
@@ -269,7 +269,7 @@ $messages = array(
 'articlepage' => 'Ìfihàn àkóónú ojúewé',
 'talk' => 'Ìfọ̀rọ̀wérọ̀',
 'views' => 'Àwọn ìwò',
-'toolbox' => 'Àpótí irinṣẹ',
+'toolbox' => 'Àwọn irinṣẹ́',
 'userpage' => 'Wo ojúewé oníṣe',
 'projectpage' => 'Wo ojúewé iṣẹ́ọwọ́',
 'imagepage' => 'Wo ojúewé fáìlì',
@@ -299,7 +299,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Nípa {{SITENAME}}',
 'aboutpage' => 'Project:Nípa',
-'copyright' => 'Gbogbo ohun inú ibí yìí wà lábẹ́  $1.',
+'copyright' => 'Gbogbo ohun inú ibí yìí wà lábẹ́ $1 àyàfi tí a bá sọ pé kò rí bẹ̀ẹ̀.',
 'copyrightpage' => '{{ns:project}}:Ẹ̀tọ́àwòko',
 'currentevents' => 'Ìṣẹ̀lẹ̀ lọ́wọ́lọ́wọ́',
 'currentevents-url' => 'Project:Ìṣẹ̀lẹ̀ lọ́wọ́lọ́wọ́',
@@ -326,8 +326,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => 'Jẹ́ kíkójáde láti "$1"',
 'youhavenewmessages' => 'Ẹ ní $1 ($2).',
-'newmessageslink' => 'ìránṣẹ́ tuntun',
-'newmessagesdifflink' => 'àtúnṣe tógbẹ̀yìn',
 'youhavenewmessagesfromusers' => 'Ẹ ní $1 láti ọ̀dọ̀ {{PLURAL:$3|oníṣe míràn|àwọn oníṣe $3}} ($2).',
 'youhavenewmessagesmanyusers' => 'Ẹ ní $1 láti ọ̀dọ̀ àwọn oníṣe púpọ̀ ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ìránṣẹ́ tuntun kan|àwọn ìránṣẹ́ tuntun}}',
@@ -460,10 +458,9 @@ Olùṣeàmójútó tó típa ṣe àlàyé yìí: "$3".',
 'virus-unknownscanner' => 'ògùn-kòkòrò àìmọ̀:',
 
 # Login and logout pages
-'logouttext' => "'''Ẹ ti bọ́sọ́de.'''
+'logouttext' => "'''Ẹ ti sọ́de.'''
 
-Ẹ le tẹ̀síwájú sí ní lo {{SITENAME}} láìmorúkọ yín, tàbí kí ẹ <span class='plainlinks'>[$1 padà wọlé]</span> bí ẹnikanan tàbí ẹlòmíràn.
-Àkíyèsí wípé àwọn ojúewé kan le hàn b'ígbà tójẹ́pé ẹ sì wọlé títí tí ẹ ó fi jọ̀wọ́ cache browser yín.",
+Àkíyèsí wípé àwọn ojúewé kan le hàn b'ígbà tójẹ́pé ẹ sì wà ní ìjáwọlé títí tí ẹ ó fi jọ̀wọ́ cache browser yín.",
 'welcomeuser' => 'Ẹ kú àbọ̀, $1!',
 'welcomecreation-msg' => "A ti ṣ'èdá àpamọ́ yín.
 Ẹ mọ́ gbàgbé l'áti ṣ'àtúnṣe [[Special:Preferences|{{SITENAME}} àwọn ìfẹ́ràn]] yín.",
@@ -499,7 +496,7 @@ Olùṣeàmójútó tó típa ṣe àlàyé yìí: "$3".',
 'gotaccount' => "Ṣé ẹ ti ní àpamọ́ tẹ́lẹ̀? '''$1'''.",
 'gotaccountlink' => "Ẹ w'ọlé",
 'userlogin-resetlink' => 'À bí ẹ gbàgbé ìwọlé yín?',
-'userlogin-resetpassword-link' => 'Ìtúntò ọ̀rọ̀ìpamọ́ yín',
+'userlogin-resetpassword-link' => 'Ṣé ẹ ti gbàgbé ọ̀rọ̀ìpamọ́ yín?',
 'helplogin-url' => 'Help:Ìwolé',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Ìrànlọ́wọ́ láti ìwọlé]]',
 'createacct-join' => 'Ẹ kọ ìsọ̀rọ̀nípa yín sísàlẹ̀',
@@ -564,16 +561,16 @@ tí ẹ kò sì fẹ́ yípadà mọ́, ẹ mọ́ kọbiara sí ìránṣẹ́
 'passwordsent' => 'A ti fi ọ̀rọ̀ìpamọ́ tuntun ránṣẹ́ sí ojúọ̀nà e-mail tí a fisílẹ̀ fún "$1".
 Ẹ jọ̀wọ́ ẹ padà wọlé tí ẹ bá ti gbàá.',
 'blocked-mailpassword' => 'Àdírẹ́sì IP yín jẹ́ dídèlọ́nà láti ṣàtúnṣe, nípa báyìí kò ní ààyè láti lo ìfigbéṣe ìtúnwárí ọ̀rọ̀ìpamọ́ kó le dínà ìbàjẹ́.',
-'eauthentsent' => 'A ti fi e-mail ìmúdájú ránṣẹ́ sí àdírẹ́ẹ̀sì e-mail tí ẹ fi sílẹ̀.
-Kí á tó fi e-mail mìíràn ránṣẹ́ sí àkópamọ́ yìí, ẹ gbọ́dọ̀ tẹ̀lé àwọn ìlànà inú e-mail ọ̀ún, láti múdájú pé àkópamọ́ ọ̀ún jẹ́ ti yín lóòótọ́.',
+'eauthentsent' => 'A ti fi e-mail ìṣàmúdájú ránṣẹ́ sí àdírẹ́ẹ̀sì e-mail tí ẹ fi sílẹ̀.
+Kí á tó fi e-mail mìíràn ránṣẹ́ sí àkópamọ́ yìí, ẹ gbọ́dọ̀ tẹ̀lé àwọn ìlànà inú e-mail ọ̀ún, láti ṣàmúdájú pé àkópamọ́ ọ̀ún jẹ́ ti yín lóòótọ́.',
 'throttled-mailpassword' => 'Email ìtúntò ọ̀rọ̀ìpamọ́ kan tilẹ̀ ti jẹ́ fífiránṣẹ́, láàrin {{PLURAL:$1|wákàtí kan|wákàtí $1}} ṣẹ́yìn.
 Láti dínà àlòbàjẹ́, email ìtúntò ọ̀rọ̀ìpamọ́ kan péré ni yíò jẹ́ fífiránṣẹ́ láàrin {{PLURAL:$1|wákàtí kọ̀ọ̀kan|wákàtí $1}}.',
 'mailerror' => 'Àsìṣe ìfiránṣẹ́: $1',
 'acct_creation_throttle_hit' => 'Àwọn aṣàbẹ̀wò sí wiki yìí tí wọ́n únlo àdírẹ́sì IP yín ti dá {{PLURAL:$1|àpamọ́ 1|àpamọ́ $1}} láàrin ọjọ́ tókọjá, èyí ni púpọ̀jùlọ tó jẹ́ gbígbà ní ààyè láàrin gbà àsìkò yìí.
 Nítorí èyí, àwọn aṣàbẹ̀wò tí wọ́n únlo àdírẹ́sì IP yìí kò le dá àpamọ́ báyìí.',
-'emailauthenticated' => 'Àdírẹ́ẹ̀sì e-mail yín ti fidájú ní ago $3 ọjọ́ $2.',
-'emailnotauthenticated' => 'Ã\80dírẹÌ\81sì e-mail yín kò Ã¬ jẹÌ\81 fífidájú.
-E-mail kankan kò ní jẹ́ fífiránṣẹ́ fún ìkankan nínú àwọn ìní wọ̀nyí.',
+'emailauthenticated' => 'Àdírẹ́ẹ̀sì e-mail yín ti jẹ́ ìmúdájú ní ago $3 ní ọjọ́ $2.',
+'emailnotauthenticated' => 'Ã\80dírẹÌ\81sì e-mail yín kò Ã­ tíì jẹÌ\81 Ã¬múdájú.
+E-mail kankan kò ní jẹ́ fífiránṣẹ́ fún ìkankan nínú àwọn ojúìní wọ̀nyí.',
 'noemailprefs' => 'Ẹ pèsè àdírẹ́sì e-mail kan nínú àwọn ìfẹ́ràn yín fún àwọn ìní yìí le ba ṣiṣẹ́.',
 'emailconfirmlink' => 'Ìmúdájú àdírẹ́ẹ̀sì e-mail yín',
 'invalidemailaddress' => 'Àdírẹ́sì e-mail náà kò ṣe é gbà torípé ó dà bi pé irú rẹ̀ kò tọ́.
@@ -588,8 +585,8 @@ E-mail kankan kò ní jẹ́ fífiránṣẹ́ fún ìkankan nínú àwọn ìn
 
 Ẹ le fojúfo ìránṣẹ́ yìí, tó bá jẹ́ pé àpamọ́ yìí jẹ́ dídá nítorí àsìṣe.',
 'usernamehasherror' => 'Orúkọ oníṣe yín kò gbọdọ̀ ní àmílẹ́tà hash',
-'login-throttled' => 'Ẹ ti gbìyànjú bó ṣe yẹ lọ láti wọlé.
-Ẹ jọ̀wọ́ ẹ dúró ná kí ẹ tó gbìyànjú lẹ́ẹ̀kan síi.',
+'login-throttled' => 'Ẹ ti gbìyànjú lọ́pọ̀ bó ṣe yẹ lọ láti jáwọlé.
+Ẹ jọ̀wọ́ ẹ dúró fún $1 ná kí ẹ tó tún gbìyànjú lẹ́ẹ̀kan síi.',
 'login-abort-generic' => 'Ìwọlé yín kò yọrísírere - ó ti jẹ́ kíkáwọ́dà',
 'loginlanguagelabel' => 'Èdè: $1',
 'suspicious-userlogout' => 'Ìtọrọ tí ẹ ṣe láti bọ́sóde jẹ̀ kíkọ̀ nítorípé ó dà bí pé ó jẹ́ fífiránṣẹ́ látọ̀dọ̀ awòtakùn (browser) àìdára tàbí ẹ̀rọ-ìwọ̀fà ìmúpamọ́ onígbàdíẹ̀.',
@@ -608,7 +605,7 @@ Láti parí ìmúwọlẹ́, ẹ gbọ́dọ̀ ṣètò ọ̀rọ̀ìpamọ́ tu
 'newpassword' => 'Ọ̀rọ̀ìpamọ́ tuntun:',
 'retypenew' => 'Àtúntẹ̀ ọ̀rọ̀ìpamọ́ tuntun:',
 'resetpass_submit' => 'Ẹ ṣe àtúntò ọ̀rọ̀ìpamọ́ kí ẹ tó wọlé',
-'changepassword-success' => 'Ìyípadà ọ̀rọ̀ìpamọ́ yín ti já sí rere! Ẹ̀ ún wọlé lọ́wọ́...',
+'changepassword-success' => 'Ìyípadà ọ̀rọ̀ìpamọ́ yín ti já sí rere!',
 'resetpass_forbidden' => 'Àwọn ọ̀rọ̀ìpamọ́ kò ṣe é yípadà',
 'resetpass-no-info' => 'Ẹ gbọ́dọ̀ wọlẹ́ láti le lọ sí ojúewé yìí tààrà.',
 'resetpass-submit-loggedin' => 'Ìyípadà ọ̀rọ̀ìpamọ́',
@@ -645,7 +642,7 @@ $2
 Ọ̀rọ̀ìpamọ́ ìgbàdíẹ̀: $2',
 'passwordreset-emailsent' => 'E-mail àtúntò ọ̀rọ̀ìpamọ́ ti jẹ́ fífiránṣẹ́.',
 'passwordreset-emailsent-capture' => 'E-mail àtúntò ọ̀rọ̀ìpamọ́ kan ti jẹ́ fífiránṣẹ́. Òhun nìyí nísàlẹ̀.',
-'passwordreset-emailerror-capture' => 'E-mail ìránlétì jẹ́ dídá, òhun lóhàn nísàlẹ̀ yìí, sùgbọ́n ìfiránṣẹ́ rẹ̀ sí oníṣe náà kùnà: $1',
+'passwordreset-emailerror-capture' => 'E-mail ìyípadà ọ̀rọ̀ìpamọ́ jẹ́ dídá, òhun lóhàn nísàlẹ̀ yìí, sùgbọ́n ìfiránṣẹ́ rẹ̀ sí {{GENDER:$2|oníṣe}} náà kùnà: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'Ìyípadà àdírẹ̀sì E-mail',
@@ -738,9 +735,7 @@ $1 ni ó ṣe ìdínà.
 'loginreqlink' => 'wọlé',
 'loginreqpagetext' => 'Ẹ gbọ́dọ̀ $1 láti wo àwọn ojúewé míràn.',
 'accmailtitle' => 'Ti fi ọ̀rọ̀ìpamọ́ ránṣẹ́.',
-'accmailtext' => "A ti fi ọ̀rọ̀ìpamọ́ àrìnàkò tí a pèsè fún [[User talk:$1|$1]] ránṣẹ́ sí $2.
-
-Ẹ le ṣe àyípadà ọ̀rọ̀ìpamọ́ fún àpamọ́ tuntun yìí ní ''[[Special:ChangePassword|change password]]'' lẹ́yìn tí ẹ bá ti wọlé.",
+'accmailtext' => "A ti fi ọ̀rọ̀ìpamọ́ àrìnàkò tí a pèsè fún [[User talk:$1|$1]] ránṣẹ́ sí $2. Ẹ le ṣe àyípadà ọ̀rọ̀ìpamọ́ fún àpamọ́ tuntun yìí ní ibi ''[[Special:ChangePassword|àyípadà ọ̀rọ̀ìpamọ́]]'' lẹ́yìn tí ẹ bá ti jáwọlé.",
 'newarticle' => '(Tuntun)',
 'newarticletext' => "Ẹ ti tẹ̀lé ìjápọ̀ mọ́ ojúewé tí kò sí.
 Láti dá ojúewé yí ẹ bẹ̀rẹ̀ síní tẹ́kọ sí inú àpótí ìsàlẹ̀ yí (ẹ wo [[{{MediaWiki:Helppage}}|ojúewé ìrànlọ́wọ́ ]] fun ẹ̀kúnrẹ́rẹ́ ).
@@ -1001,15 +996,15 @@ Tó bá jẹ́ pé ẹ ti wọlé, ẹ lè dẹ́kun ìkìlọ̀ yìí nínù ab
 *Ọ̀rọ̀ ẹnìẹlẹ́ni tí kò bójúmu
 *: ''àdírẹ́ẹ̀sì ilé àti nọ́mbà tẹlifóònù, àti bẹ́ẹ̀bẹ́ẹ̀ lọ.''",
 'revdelete-legend' => 'Ìtò àwọn àlà ìhàn',
-'revdelete-hide-text' => 'Ìbòmọ́lẹ̀ ìkọ̀ àtúnyẹ̀wò',
+'revdelete-hide-text' => 'Ìkọ̀rọ̀ àtúnyẹ̀wò',
 'revdelete-hide-image' => 'Ìbòmọ́lẹ̀ àkóónú fáìlì',
 'revdelete-hide-name' => 'Ìbòmọ́lẹ̀ ìgbéṣe àti wíwá',
-'revdelete-hide-comment' => 'Ã\8cbòmá»\8dÌ\81lẹÌ\80 Ã ríwí Ã túná¹£e',
-'revdelete-hide-user' => 'Ìbòmọ́lẹ̀ orúkọ oníṣe/IP olóòtú',
+'revdelete-hide-comment' => 'Ã\80túná¹£e Ã kótán',
+'revdelete-hide-user' => 'Orúkọ oníṣe/àdírẹ́ẹ̀sì IP olùtúnṣe',
 'revdelete-hide-restricted' => 'Ìbòmọ́lẹ̀ àwọn ìpèsè ti àwọn alámùójútó àti ti àwọn yìókù',
 'revdelete-radio-same' => '(láì yípadà)',
-'revdelete-radio-set' => 'Bẹ́ẹ̀ni',
-'revdelete-radio-unset' => 'Bẹ́ẹ̀kọ́',
+'revdelete-radio-set' => 'Híhàn',
+'revdelete-radio-unset' => 'Bíbòmọ́lẹ̀',
 'revdelete-suppress' => 'Ìbòmọ́lẹ̀ àwọn ìpèsè ti àwọn alámùójútó àti ti àwọn yìókù',
 'revdelete-unsuppress' => 'Ìyọkúrò àlà sí àwọn àtúnyẹ̀wò àdápadà',
 'revdelete-log' => 'Ìdíẹ̀:',
@@ -1166,8 +1161,6 @@ Ní báyìí ná ẹ le ṣàwárí lọ́dọ̀ Google.
 'preferences' => 'Àwọn ìfẹ́ràn',
 'mypreferences' => 'Àwọn ìfẹ́ràn',
 'prefs-edits' => 'Iye àwọn àtúnṣe:',
-'prefsnologin' => 'Ẹ kò tíì wọlé',
-'prefsnologintext' => 'Ẹ gbọ́dọ̀ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} wọlé]</span> láti to àwọn ìfẹ́ràn oníṣe.',
 'changepassword' => 'Ìyípadà ọ̀rọ̀ìpamọ́',
 'prefs-skin' => 'Skin (Àwọ̀)',
 'skin-preview' => 'Àkọ́yẹ̀wò',
@@ -1192,7 +1185,7 @@ Ní báyìí ná ẹ le ṣàwárí lọ́dọ̀ Google.
 'prefs-rendering' => 'Wíwò',
 'saveprefs' => 'Ìmúpamọ́',
 'resetprefs' => 'Ìpalẹ̀mọ́ àwọn àyípadà àìmúpamọ́',
-'restoreprefs' => 'Ìdápadà áwọn ìtò àtìbẹ̀rẹ̀',
+'restoreprefs' => 'Ìdápadà gbogbo áwọn ìtò àtìbẹ̀rẹ̀ (nínú gbogbo àwọn abala)',
 'prefs-editing' => 'Àtúnṣe ṣíṣẹ',
 'rows' => 'Àwọn ìtẹ̀lé gbọlọjọ:',
 'columns' => 'Àwọn ìtẹ̀lé gogoro:',
@@ -1249,10 +1242,10 @@ Kò ní ṣeé dápadà mọ́.',
 Ẹ yẹ àwọn àlẹ̀mọ́ HTML wò.',
 'badsiglength' => 'Ìtọwọ́bọ̀ yín ti gùnjù.
 Kò gbodọ̀ ju $1 {{PLURAL:$1|àmìlẹ́tà|àwọn àmìlẹ́tà}} lọ.',
-'yourgender' => 'Akọmbábo:',
-'gender-unknown' => 'Àláìtọ́kasí',
-'gender-male' => 'Akọ',
-'gender-female' => 'Abo',
+'yourgender' => 'Báwo lẹ ṣe fẹ́ kí á ṣe ìjúwe yín?',
+'gender-unknown' => 'Un kò fẹ́ sọ',
+'gender-male' => 'Ó ṣe àtúnṣe àwọn ojúewé wiki',
+'gender-female' => 'Ó ṣe àtúnṣe àwọn ojúewé wiki',
 'prefs-help-gender' => 'Alásàyàn: Lílò fún pípe akọtabo látọwọ́ atòlànà kọ̀mpútà.
 Èyí yíò hàn sí ìgboro.',
 'email' => 'E-mail',
@@ -1444,6 +1437,7 @@ Tí ẹ bá fisílẹ̀ a ó lòó láti tóka iṣẹ́ yín fún yín.',
 'recentchanges-label-minor' => 'Àtùnṣe kékeré nìyí',
 'recentchanges-label-bot' => 'Rọ́bọ́ọ̀tì ni ó ṣe àtúnṣe yìí',
 'recentchanges-label-unpatrolled' => 'Àtúnṣe yìí kò tí ì jẹ́ onísíṣọ́',
+'recentchanges-legend-newpage' => '$1 - ojúewé tuntun',
 'rcnote' => "Lábẹ́ ni {{PLURAL:$1|àtúnṣe '''kan'''|àwọn àtúnṣe '''$1''' tí wọn gbẹ̀yìn}} láàrin {{PLURAL:$2|ọjọ́ kan|ọjọ́ '''$2'''}} sẹ́yìn ní ago $5, lọ́jọ́ $4.",
 'rcnotefrom' => "Àwọn àtúnṣe láti ''''$2''' (títí dé '''$1''' hàn) lábẹ́.",
 'rclistfrom' => 'Àfihàn àwọn àtúnṣe tuntun nípa bíbẹ̀rẹ̀ láti $1',
@@ -1466,7 +1460,7 @@ Tí ẹ bá fisílẹ̀ a ó lòó láti tóka iṣẹ́ yín fún yín.',
 'rc_categories_any' => 'Èyíkéyìí',
 'rc-change-size-new' => '$1 {{PLURAL:$1|byte|bytes}} lẹ́yìn àtúnṣe',
 'newsectionsummary' => '/* $1 */ abala tuntun',
-'rc-enhanced-expand' => 'Ìfihàn ẹ̀kúnrẹ́rẹ́ (JavaScript pọndandan)',
+'rc-enhanced-expand' => 'Ìfihàn ẹ̀kúnrẹ́rẹ́',
 'rc-enhanced-hide' => 'Ìfipamọ́ ẹ̀kúnrẹ́rẹ́',
 'rc-old-title' => 'dídá tẹ́lẹ̀tẹ́lẹ̀ bíi "$1"',
 
@@ -2371,7 +2365,7 @@ $1',
 'contributions' => 'Àwọn àfikún {{GENDER:$1|oníṣe}}',
 'contributions-title' => 'Àwọn àfikún oníṣe fún $1',
 'mycontris' => 'Àwọn àfikún',
-'contribsub2' => 'Fún $1 ($2)',
+'contribsub2' => 'Fún {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Kò sí àtúnṣe tuntun tó bá àwárí mu.',
 'uctop' => '(lówọ́)',
 'month' => 'Láti osù (àti sẹ́yìn):',
@@ -2685,7 +2679,7 @@ Láti ṣàkójáde àwọn ojúewé, ẹ tẹ àkọlé wọn sínú àpótí 
 'allmessagesdefault' => 'Ìkọ ìránṣẹ́ àtìbẹ̀rẹ̀',
 'allmessagescurrent' => 'Ìkọ ìránṣẹ́ lọ́wọ́',
 'allmessagestext' => 'Èyí ni àtòjọ àwọn ìránṣẹ́ sístẹ́mù tó wà nínú orúkọàyè MediaWiki.
-Ẹ lọ sí [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] àti [//translatewiki.net translatewiki.net] tí ẹ bá fẹ́ kópa nínú ìyèdèpadà ìsiṣẹ́ MediaWiki.',
+Ẹ lọ sí [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] àti [//translatewiki.net translatewiki.net] tí ẹ bá fẹ́ kópa nínú ìyèdèpadà ìsiṣẹ́ MediaWiki.',
 'allmessagesnotsupportedDB' => "Ojúewé yìí kò ṣe é lò nítorípé '''\$wgUseDatabaseMessages''' ti jẹ́ dídálẹkun.",
 'allmessages-filter-legend' => 'Ajọ̀',
 'allmessages-filter' => 'Ajọ̀ gẹ́gẹ́bí ipò ìṣàyàn:',
@@ -2966,7 +2960,7 @@ Tí ẹ bá jẹ́ ó ṣiṣẹ́, ẹ̀rọ sístẹ́mù yín le kó sí ewu.
 'svg-long-desc' => 'faili SVG, pẹ̀lú $1 × $2 pixels, ìtòbi faili: $3',
 'svg-long-desc-animated' => 'Fáìlì SVG alámùúrìn, tó jẹ́ $1 × $2 pixels, ìtóbi fáìlì: $3',
 'svg-long-error' => 'Fáìlì SVG àìyẹ: $1',
-'show-big-image' => 'Pẹ̀lú ìgbéhàn gíga',
+'show-big-image' => 'Fáìlì àtìbẹ̀rẹ̀',
 'show-big-image-preview' => 'Ìtóbi ìkọ́yẹ̀wò yìí: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Ìgbéhàn|Àwọn ìgbéhàn}} míràn: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3284,7 +3278,7 @@ Tóbájẹ́pé fáìlì ọ̀hún ti jẹ́ títúnṣe sí bóṣewà ní bẹ
 
 # External editor support
 'edit-externally' => "Ẹ lo ìmúlò òde láti ṣ'àtúnṣe fáìlì yìí",
-'edit-externally-help' => '(Ẹ wo [//www.mediawiki.org/wiki/Manual:External_editors ìlànà ìṣètò] fún ẹ̀kúnrẹ́rẹ́)',
+'edit-externally-help' => '(Ẹ wo [https://www.mediawiki.org/wiki/Manual:External_editors ìlànà ìṣètò] fún ẹ̀kúnrẹ́rẹ́)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'gbogbo',
@@ -3446,7 +3440,7 @@ $5
 'version-hook-name' => 'Orúkọ hook',
 'version-version' => '(Àtẹ̀jáde $1)',
 'version-license' => 'Ìwé àṣẹ',
-'version-poweredby-credits' => "Agbára ìṣiṣẹ́ wiki yìí wá látọwọ́ '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-credits' => "Agbára ìṣiṣẹ́ wiki yìí wá látọwọ́ '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'àwọn mìíràn',
 'version-credits-summary' => 'Ìdùnnú wa ni láti rántí àwọn ẹni wọ̀nyí fún ìdáwọ́lé wọn sí [[Special:Version|MediaWiki]].',
 'version-software' => 'Atòlànà kọ̀mpútà kíkànsínú',
@@ -3469,8 +3463,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Àwọn ojúewé pàtàkì',
-'specialpages-note' => '----
-* Àwọn ojúewé pàtàkì onídéédé.
+'specialpages-note' => '* Àwọn ojúewé pàtàkì onídéédé.
 * <span class="mw-specialpagerestricted">Àwọn ojúewé pàtàkì àìgbàláyè.</span>',
 'specialpages-group-maintenance' => 'Àwọn ìjábọ̀ ìtọ́jú',
 'specialpages-group-other' => 'Àwọn ojúewé pàtàkì míràn',
index f0a9494..e3717c2 100644 (file)
@@ -101,7 +101,6 @@ $specialPageAliases = array(
        'Ancientpages'              => array( '舊版' ),
        'Blankpage'                 => array( '空版' ),
        'Block'                     => array( '封' ),
-       'Blockme'                   => array( '封我' ),
        'Booksources'               => array( '書本來源' ),
        'BrokenRedirects'           => array( '斷鏈' ),
        'Categories'                => array( '分類' ),
@@ -112,7 +111,6 @@ $specialPageAliases = array(
        'CreateAccount'             => array( '開戶' ),
        'Deadendpages'              => array( '掘頭頁' ),
        'DeletedContributions'      => array( '刪咗嘅貢獻' ),
-       'Disambiguations'           => array( '搞清楚頁' ),
        'DoubleRedirects'           => array( '雙重跳轉' ),
        'EditWatchlist'             => array( '改監視清單' ),
        'Emailuser'                 => array( '電郵用戶' ),
@@ -163,7 +161,7 @@ $specialPageAliases = array(
        'Revisiondelete'            => array( '修訂版本刪除' ),
        'Search'                    => array( '搜索' ),
        'Shortpages'                => array( '短版' ),
-       'Specialpages'              => array( '特別頁' ),
+       'Specialpages'              => array( '專門版' ),
        'Statistics'                => array( '統計' ),
        'Tags'                      => array( '標籤' ),
        'Unblock'                   => array( '解封' ),
@@ -492,8 +490,6 @@ $1',
 'ok' => 'OK',
 'retrievedfrom' => '由 "$1" 收',
 'youhavenewmessages' => '你有$1($2)。',
-'newmessageslink' => '新信息',
-'newmessagesdifflink' => '上次更改',
 'youhavenewmessagesmulti' => '你響 $1 有新信',
 'editsection' => '編輯',
 'editold' => '編輯',
@@ -1155,8 +1151,6 @@ $1",
 'preferences' => '喜好設定',
 'mypreferences' => '自訂喜好',
 'prefs-edits' => '編輯數:',
-'prefsnologin' => '重未登入',
-'prefsnologintext' => '你一定要去<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登入]</span>設定好用戶喜好值先。',
 'changepassword' => '改密碼',
 'prefs-skin' => '畫面',
 'skin-preview' => '預覽',
@@ -1421,6 +1415,7 @@ $1",
 'recentchanges-label-minor' => '呢個係一個細編輯',
 'recentchanges-label-bot' => '呢次編輯係由機械人進行',
 'recentchanges-label-unpatrolled' => '呢次編輯重未巡查過',
+'recentchanges-legend-newpage' => '$1 - 新版',
 'rcnote' => "以下係響$4 $5,近'''$2'''日嘅最後'''$1'''次修改。",
 'rcnotefrom' => "以下係自'''$2'''嘅更改(顯示到'''$1''')。",
 'rclistfrom' => '顯示由$1嘅新更改',
@@ -2470,7 +2465,7 @@ $1',
 'allmessagesdefault' => '預設訊息文字',
 'allmessagescurrent' => '現時訊息文字',
 'allmessagestext' => '以下係 MediaWiki 空間名入邊現有系統信息嘅清單。
-如果想貢獻正宗嘅MediaWiki本地化嘅話,請參閱[//www.mediawiki.org/wiki/Localisation MediaWiki本地化]同埋[//translatewiki.net translatewiki.net]。',
+如果想貢獻正宗嘅MediaWiki本地化嘅話,請參閱[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]同埋[//translatewiki.net translatewiki.net]。',
 'allmessagesnotsupportedDB' => "呢一版唔可以用,因為'''\$wgUseDatabaseMessages'''已經閂咗。",
 'allmessages-filter-legend' => '過濾',
 'allmessages-filter' => '以自定狀況過濾:',
@@ -2645,6 +2640,8 @@ $1',
 'spambot_username' => 'MediaWiki垃圾清除',
 'spam_reverting' => '恢復返去最後一個唔包含指去$1嘅連結嘅嗰個修訂。',
 'spam_blanking' => '全部版本都含有指去$1嘅連結,留空',
+'simpleantispam-label' => "反垃圾檢查。
+'''唔好'''加入呢個!",
 
 # Skin names
 'skinname-cologneblue' => '科隆藍',
@@ -3037,7 +3034,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => '用外面程式來改呢個檔案',
-'edit-externally-help' => '(去[//www.mediawiki.org/wiki/Manual:External_editors setup instructions] 睇多啲資料)',
+'edit-externally-help' => '(去[https://www.mediawiki.org/wiki/Manual:External_editors setup instructions] 睇多啲資料)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
@@ -3203,7 +3200,7 @@ $5
 'version-hook-subscribedby' => '利用於',
 'version-version' => '(版本 $1)',
 'version-license' => '牌照',
-'version-poweredby-credits' => "呢個 Wiki 係由 '''[//www.mediawiki.org/ MediaWiki]''' 驅動,版權所有 © 2001-$1 $2。",
+'version-poweredby-credits' => "呢個 Wiki 係由 '''[https://www.mediawiki.org/ MediaWiki]''' 驅動,版權所有 © 2001-$1 $2。",
 'version-poweredby-others' => '其他',
 'version-license-info' => 'MediaWiki係自由軟件;你可以根據Free Software Foundation所發表嘅GNU General Public License條款規定,就本程式再發佈同/或修改;無論你根據嘅係呢個牌照嘅第二版或(任你揀)任一日之後發行嘅版本。
 
@@ -3227,8 +3224,7 @@ MediaWiki是基於使用目的而加以發佈,但係就唔會負上任何嘅
 
 # Special:SpecialPages
 'specialpages' => '特別頁',
-'specialpages-note' => '----
-* 標準特別頁。
+'specialpages-note' => '* 標準特別頁。
 * <strong class="mw-specialpagerestricted">有限制嘅特別頁。</strong>',
 'specialpages-group-maintenance' => '維護報告',
 'specialpages-group-other' => '其它特別頁',
@@ -3316,4 +3312,16 @@ MediaWiki是基於使用目的而加以發佈,但係就唔會負上任何嘅
 # Durations
 'duration-hours' => '$1{{PLURAL:$1|個鐘}}',
 
+# Special:ExpandTemplates
+'expandtemplates' => '展開模',
+'expand_templates_intro' => '呢個特別頁係用於將一啲文字中嘅模展開,包括響個模度引用嘅模。同時亦都展開解譯器函數好似<nowiki>{{</nowiki>#language:...}},以及一啲變數好似<nowiki>{{</nowiki>CURRENTDAY}}&mdash;實際上,幾乎所有響雙括弧中嘅內容都會被展開。呢個特別頁係通過使用MediaWiki嘅相關解釋階段嘅功能完成嘅。',
+'expand_templates_title' => '內容標題,用於 {{FULLPAGENAME}} 等頁面:',
+'expand_templates_input' => '輸入文字:',
+'expand_templates_output' => '結果:',
+'expand_templates_xml_output' => 'XML輸出',
+'expand_templates_ok' => 'OK',
+'expand_templates_remove_comments' => '拎走注釋',
+'expand_templates_generate_xml' => '顯示XML語法樹',
+'expand_templates_preview' => '預覽',
+
 );
index c14af62..682aa6c 100644 (file)
@@ -299,8 +299,6 @@ $1",
 'ok' => 'OK',
 'retrievedfrom' => 'Truggeplekt van "$1"',
 'youhavenewmessages' => 'Je ei $1 ($2).',
-'newmessageslink' => 'nieuw bericht',
-'newmessagesdifflink' => 'de bewerkieng bekieken',
 'youhavenewmessagesmulti' => 'Je ei nieuwe berichen op $1',
 'editsection' => 'bewerken',
 'editold' => 'bewerk',
@@ -829,8 +827,6 @@ De hehevens over {{SITENAME}} zien meuhlijk nie bie'ewerkt.",
 'preferences' => 'Vòkeuren',
 'mypreferences' => 'Mien vòkeuren',
 'prefs-edits' => 'Antal bewerkiengen:',
-'prefsnologin' => 'Nie anemeld',
-'prefsnologintext' => 'Je mò <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} anemeld]</span> zien om je vòkeuren te kunn\'n instell\'n.',
 'changepassword' => 'Wachtwoôrd wiezigen',
 'prefs-skin' => 'Vurmhevieng',
 'skin-preview' => 'Voevertoônienge',
@@ -1319,7 +1315,7 @@ Aorre veld'n worr'n verborr'n.
 
 # External editor support
 'edit-externally' => "Dit bestand in 'n extern programma bewark'n",
-'edit-externally-help' => '(zieë de [//www.mediawiki.org/wiki/Manual:External_editors handleidienge vò instelliengen] vò meê informaosie)',
+'edit-externally-help' => '(zieë de [https://www.mediawiki.org/wiki/Manual:External_editors handleidienge vò instelliengen] vò meê informaosie)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'aol',
index 9d66ede..bf4b8cc 100644 (file)
@@ -25,7 +25,9 @@
  * @author Fantasticfears
  * @author Fengchao
  * @author Franklsf95
+ * @author Gakmo
  * @author Gaoxuewei
+ * @author GeneralNFS
  * @author Gzdavidwong
  * @author Happy
  * @author Hercule
@@ -128,29 +130,29 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( '活跃用户' ),
        'Allmessages'               => array( '所有信息' ),
+       'AllMyUploads'              => array( '我上传的所有文件', '我的所有文件' ),
        'Allpages'                  => array( '所有页面' ),
        'Ancientpages'              => array( '最老页面' ),
-       'Badtitle'                  => array( '无效标题' ),
+       'Badtitle'                  => array( '错误标题', '无效标题' ),
        'Blankpage'                 => array( '空白页面' ),
        'Block'                     => array( '封禁用户' ),
-       'Blockme'                   => array( '自我封禁' ),
        'Booksources'               => array( '网络书源' ),
-       'BrokenRedirects'           => array( '受损重定向' ),
+       'BrokenRedirects'           => array( '受损重定向' ),
        'Categories'                => array( '页面分类' ),
        'ChangeEmail'               => array( '修改邮箱' ),
        'ChangePassword'            => array( '修改密码' ),
-       'ComparePages'              => array( '比较页面' ),
+       'ComparePages'              => array( '对比页面', '比较页面' ),
        'Confirmemail'              => array( '确认电子邮件' ),
        'Contributions'             => array( '用户贡献' ),
        'CreateAccount'             => array( '创建账户' ),
        'Deadendpages'              => array( '断链页面' ),
        'DeletedContributions'      => array( '已删除的用户贡献' ),
-       'Disambiguations'           => array( '消歧义页' ),
-       'DoubleRedirects'           => array( '双重重定向页', '两次重定向页' ),
+       'DoubleRedirects'           => array( '双重重定向', '两次重定向' ),
        'EditWatchlist'             => array( '编辑监视列表' ),
-       'Emailuser'                 => array( '电子邮件用户' ),
+       'Emailuser'                 => array( '电邮联系' ),
+       'ExpandTemplates'           => array( '展开模板' ),
        'Export'                    => array( '导出页面' ),
-       'Fewestrevisions'           => array( '最少修订页面' ),
+       'Fewestrevisions'           => array( '版本最少页面', '最少修订页面' ),
        'FileDuplicateSearch'       => array( '搜索重复文件' ),
        'Filepath'                  => array( '文件路径' ),
        'Import'                    => array( '导入页面' ),
@@ -184,17 +186,21 @@ $specialPageAliases = array(
        'Myuploads'                 => array( '我上传的文件' ),
        'Newimages'                 => array( '新建文件' ),
        'Newpages'                  => array( '新建页面' ),
+       'PagesWithProp'             => array( '带属性的页面' ),
        'PasswordReset'             => array( '重设密码' ),
        'PermanentLink'             => array( '永久链接' ),
        'Popularpages'              => array( '热点页面' ),
-       'Preferences'               => array( '参数设置', '系统设置' ),
+       'Preferences'               => array( '参数设置', '设置' ),
        'Prefixindex'               => array( '前缀索引' ),
        'Protectedpages'            => array( '已保护页面' ),
        'Protectedtitles'           => array( '已保护标题' ),
        'Randompage'                => array( '随机页面' ),
-       'Randomredirect'            => array( '随机重定向页' ),
+       'RandomInCategory'          => array( '分类内随机' ),
+       'Randomredirect'            => array( '随机重定向', '随机重定向页' ),
        'Recentchanges'             => array( '最近更改' ),
-       'Recentchangeslinked'       => array( '链出更改' ),
+       'Recentchangeslinked'       => array( '相关更改', '链出更改' ),
+       'Redirect'                  => array( '重定向' ),
+       'ResetTokens'               => array( '重置权标' ),
        'Revisiondelete'            => array( '删除或恢复修订' ),
        'Search'                    => array( '搜索' ),
        'Shortpages'                => array( '短页面' ),
@@ -214,17 +220,17 @@ $specialPageAliases = array(
        'Unwatchedpages'            => array( '未受监视页面' ),
        'Upload'                    => array( '上传文件' ),
        'UploadStash'               => array( '上传藏匿' ),
-       'Userlogin'                 => array( '用户登录', '用户登入' ),
-       'Userlogout'                => array( '用户退出', '用户登出' ),
+       'Userlogin'                 => array( '用户登录' ),
+       'Userlogout'                => array( '用户退出' ),
        'Userrights'                => array( '用户权限' ),
-       'Version'                   => array( '版本信息' ),
-       'Wantedcategories'          => array( '待撰分类' ),
+       'Version'                   => array( '版本', '版本信息' ),
+       'Wantedcategories'          => array( '需要的分类', '待撰分类' ),
        'Wantedfiles'               => array( '需要的文件' ),
-       'Wantedpages'               => array( '待撰页面' ),
+       'Wantedpages'               => array( '需要的页面', '待撰页面', '受损链接' ),
        'Wantedtemplates'           => array( '需要的模板' ),
        'Watchlist'                 => array( '监视列表' ),
        'Whatlinkshere'             => array( '链入页面' ),
-       'Withoutinterwiki'          => array( '无跨维基链接页面' ),
+       'Withoutinterwiki'          => array( '无跨维基', '无跨维基链接页面' ),
 );
 
 $magicWords = array(
@@ -233,15 +239,26 @@ $magicWords = array(
        'nogallery'                 => array( '0', '__无图库__', '__NOGALLERY__' ),
        'forcetoc'                  => array( '0', '__强显目录__', '__FORCETOC__' ),
        'toc'                       => array( '0', '__目录__', '__TOC__' ),
-       'noeditsection'             => array( '0', '__无段落编辑__', '__NOEDITSECTION__' ),
-       'currentmonth'              => array( '1', '本月', 'CURRENTMONTH', 'CURRENTMONTH2' ),
+       'noeditsection'             => array( '0', '__无编辑段落__', '__无段落编辑__', '__NOEDITSECTION__' ),
+       'currentmonth'              => array( '1', '本月', '本月2', 'CURRENTMONTH', 'CURRENTMONTH2' ),
        'currentmonth1'             => array( '1', '本月1', 'CURRENTMONTH1' ),
-       'currentmonthname'          => array( '1', '本月名称', 'CURRENTMONTHNAME' ),
+       'currentmonthname'          => array( '1', '本月名', '本月名称', 'CURRENTMONTHNAME' ),
+       'currentmonthnamegen'       => array( '1', '本月名属格', '本月名称属格', 'CURRENTMONTHNAMEGEN' ),
        'currentmonthabbrev'        => array( '1', '本月简称', 'CURRENTMONTHABBREV' ),
        'currentday'                => array( '1', '今天', 'CURRENTDAY' ),
        'currentday2'               => array( '1', '今天2', 'CURRENTDAY2' ),
+       'currentdayname'            => array( '1', '星期', '今天名', '今天名称', 'CURRENTDAYNAME' ),
        'currentyear'               => array( '1', '今年', 'CURRENTYEAR' ),
-       'currenttime'               => array( '1', '此时', '当前时间', 'CURRENTTIME' ),
+       'currenttime'               => array( '1', '当前时间', '此时', 'CURRENTTIME' ),
+       'currenthour'               => array( '1', '当前小时', 'CURRENTHOUR' ),
+       'localmonth'                => array( '1', '本地月', 'LOCALMONTH', 'LOCALMONTH2' ),
+       'localmonthname'            => array( '1', '本地月份名', 'LOCALMONTHNAME' ),
+       'localmonthnamegen'         => array( '1', '本地月历', 'LOCALMONTHNAMEGEN' ),
+       'localday'                  => array( '1', '本地日', 'LOCALDAY' ),
+       'localdayname'              => array( '1', '本地日名', 'LOCALDAYNAME' ),
+       'localyear'                 => array( '1', '本地年', 'LOCALYEAR' ),
+       'localtime'                 => array( '1', '本地时间', 'LOCALTIME' ),
+       'localhour'                 => array( '1', '本地小时', 'LOCALHOUR' ),
        'numberofpages'             => array( '1', '页面数', 'NUMBEROFPAGES' ),
        'numberofarticles'          => array( '1', '条目数', 'NUMBEROFARTICLES' ),
        'numberoffiles'             => array( '1', '文件数', 'NUMBEROFFILES' ),
@@ -249,19 +266,19 @@ $magicWords = array(
        'numberofactiveusers'       => array( '1', '活跃用户数', 'NUMBEROFACTIVEUSERS' ),
        'numberofedits'             => array( '1', '编辑数', 'NUMBEROFEDITS' ),
        'numberofviews'             => array( '1', '访问数', 'NUMBEROFVIEWS' ),
-       'pagename'                  => array( '1', '页面名', 'PAGENAME' ),
-       'pagenamee'                 => array( '1', '页面名E', 'PAGENAMEE' ),
+       'pagename'                  => array( '1', '页名', '页面名', '页面名称', 'PAGENAME' ),
+       'pagenamee'                 => array( '1', '页名等同', '页面名等同', '页面名E', 'PAGENAMEE' ),
        'namespace'                 => array( '1', '名字空间', 'NAMESPACE' ),
-       'namespacee'                => array( '1', '名字空间E', 'NAMESPACEE' ),
+       'namespacee'                => array( '1', '名字空间等同', '名字空间E', 'NAMESPACEE' ),
        'namespacenumber'           => array( '1', '名字空间编号', 'NAMESPACENUMBER' ),
-       'talkspace'                 => array( '1', '讨论名字空间', 'TALKSPACE' ),
-       'talkspacee'                => array( '1', '讨论名字空间E', 'TALKSPACEE' ),
-       'fullpagename'              => array( '1', '完整页面名', 'FULLPAGENAME' ),
+       'talkspace'                 => array( '1', '讨论空间', '讨论名字空间', 'TALKSPACE' ),
+       'talkspacee'                => array( '1', '讨论空间等同', '讨论名字空间E', 'TALKSPACEE' ),
+       'fullpagename'              => array( '1', '页面全名', '完整页面名', 'FULLPAGENAME' ),
        'fullpagenamee'             => array( '1', '完整页面名E', 'FULLPAGENAMEE' ),
        'subpagename'               => array( '1', '子页面名', 'SUBPAGENAME' ),
-       'subpagenamee'              => array( '1', '子页面名E', 'SUBPAGENAMEE' ),
+       'subpagenamee'              => array( '1', '子页面名等同', '子页面名E', 'SUBPAGENAMEE' ),
        'talkpagename'              => array( '1', '讨论页面名', 'TALKPAGENAME' ),
-       'talkpagenamee'             => array( '1', '讨论页面名E', 'TALKPAGENAMEE' ),
+       'talkpagenamee'             => array( '1', '讨论页面名等同', '讨论页面名E', 'TALKPAGENAMEE' ),
        'subst'                     => array( '0', '替代:', 'SUBST:' ),
        'safesubst'                 => array( '0', '安全替代:', 'SAFESUBST:' ),
        'img_thumbnail'             => array( '1', '缩略图', 'thumbnail', 'thumb' ),
@@ -274,9 +291,9 @@ $magicWords = array(
        'img_framed'                => array( '1', '有框', 'framed', 'enframed', 'frame' ),
        'img_frameless'             => array( '1', '无框', 'frameless' ),
        'img_page'                  => array( '1', '页数=$1', '$1页', 'page=$1', 'page $1' ),
-       'img_border'                => array( '1', '有边', 'border' ),
+       'img_border'                => array( '1', '边框', 'border' ),
        'img_link'                  => array( '1', '链接=$1', 'link=$1' ),
-       'img_alt'                   => array( '1', '替代文本=$1', 'alt=$1' ),
+       'img_alt'                   => array( '1', '替代=$1', '替代文本=$1', 'alt=$1' ),
        'img_class'                 => array( '1', '类=$1', 'class=$1' ),
        'int'                       => array( '0', '界面:', 'INT:' ),
        'sitename'                  => array( '1', '站点名称', 'SITENAME' ),
@@ -291,9 +308,13 @@ $magicWords = array(
        'scriptpath'                => array( '0', '脚本路径', 'SCRIPTPATH' ),
        'stylepath'                 => array( '0', '样式路径', 'STYLEPATH' ),
        'grammar'                   => array( '0', '语法:', 'GRAMMAR:' ),
-       'gender'                    => array( '0', '性别:', 'GENDER:' ),
+       'gender'                    => array( '0', '性:', '性别:', 'GENDER:' ),
        'notitleconvert'            => array( '0', '__不转换标题__', '__NOTITLECONVERT__', '__NOTC__' ),
        'nocontentconvert'          => array( '0', '__不转换内容__', '__NOCONTENTCONVERT__', '__NOCC__' ),
+       'currentweek'               => array( '1', '本周', 'CURRENTWEEK' ),
+       'plural'                    => array( '0', '复数:', 'PLURAL:' ),
+       'fullurl'                   => array( '0', '完整URL:', 'FULLURL:' ),
+       'fullurle'                  => array( '0', '完整URL等同:', '完整URLE:', 'FULLURLE:' ),
        'lcfirst'                   => array( '0', '小写首字:', 'LCFIRST:' ),
        'ucfirst'                   => array( '0', '大写首字:', 'UCFIRST:' ),
        'lc'                        => array( '0', '小写:', 'LC:' ),
@@ -315,12 +336,12 @@ $magicWords = array(
        'padleft'                   => array( '0', '左填充', 'PADLEFT' ),
        'padright'                  => array( '0', '右填充', 'PADRIGHT' ),
        'special'                   => array( '0', '特殊', 'special' ),
-       'speciale'                  => array( '0', '特殊e', 'speciale' ),
+       'speciale'                  => array( '0', '特殊等同', '特殊e', 'speciale' ),
        'defaultsort'               => array( '1', '默认排序:', '默认排序关键字:', '默认分类排序:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ),
        'filepath'                  => array( '0', '文件路径:', 'FILEPATH:' ),
        'tag'                       => array( '0', '标记', 'tag' ),
        'hiddencat'                 => array( '1', '__隐藏分类__', '__HIDDENCAT__' ),
-       'pagesincategory'           => array( '1', '分类中页面数', 'PAGESINCATEGORY', 'PAGESINCAT' ),
+       'pagesincategory'           => array( '1', '分类中页数', '分类中页面数', 'PAGESINCATEGORY', 'PAGESINCAT' ),
        'pagesize'                  => array( '1', '页面大小', 'PAGESIZE' ),
        'index'                     => array( '1', '__索引__', '__INDEX__' ),
        'noindex'                   => array( '1', '__不索引__', '__NOINDEX__' ),
@@ -365,10 +386,10 @@ $messages = array(
 'tog-hideminor' => '隐藏最近更改中的小编辑',
 'tog-hidepatrolled' => '隐藏最近更改中的已巡查编辑',
 'tog-newpageshidepatrolled' => '隐藏新页面列表中的已巡查页面',
-'tog-extendwatchlist' => 'æ\89©å¤§监视列表以显示所有更改而不仅是最近更改',
-'tog-usenewrc' => '按页面组合最近更改和监视列表中的更改',
+'tog-extendwatchlist' => 'æ\89©å±\95监视列表以显示所有更改而不仅是最近更改',
+'tog-usenewrc' => '按页面合并最近更改和监视列表中的更改',
 'tog-numberheadings' => '自动编号标题',
-'tog-showtoolbar' => 'æ\98¾ç¤ºç¼\96è¾\91å·¥å\85·æ\9d¡',
+'tog-showtoolbar' => 'æ\98¾ç¤ºç¼\96è¾\91å·¥å\85·æ \8f',
 'tog-editondblclick' => '双击编辑页面',
 'tog-editsection' => '启用[编辑]链接编辑段落',
 'tog-editsectiononrightclick' => '启用右击段落标题编辑段落',
@@ -397,7 +418,7 @@ $messages = array(
 'tog-watchlisthideliu' => '隐藏监视列表中的登录用户的编辑',
 'tog-watchlisthideanons' => '隐藏监视列表中的匿名用户的编辑',
 'tog-watchlisthidepatrolled' => '隐藏监视列表中的已巡查编辑',
-'tog-ccmeonemails' => '给我发送我发送给其他用户的电子邮件的副本',
+'tog-ccmeonemails' => '把我给其他用户发送的电子邮件的副本发送给我',
 'tog-diffonly' => '不在差异下面显示页面内容',
 'tog-showhiddencats' => '显示隐藏分类',
 'tog-noconvertlink' => '停用链接文字转换',
@@ -481,12 +502,12 @@ $messages = array(
 'december-date' => '12月$1日',
 
 # Categories related messages
-'pagecategories' => '$1个分类',
+'pagecategories' => '{{PLURAL:$1|分类}}',
 'category_header' => '分类“$1”中的页面',
 'subcategories' => '子分类',
 'category-media-header' => '分类“$1”中的媒体文件',
 'category-empty' => "''本分类目前未包含页面或媒体文件。''",
-'hidden-categories' => '$1个隐藏分类',
+'hidden-categories' => '{{PLURAL:$1|隐藏分类}}',
 'hidden-category-category' => '隐藏分类',
 'category-subcat-count' => '{{PLURAL:$2|本分类只有以下子分类。|本分类有以下$1个子分类,共有$2个子分类。}}',
 'category-subcat-count-limited' => '本分类有以下{{PLURAL:$1|子分类|$1个子分类}}。',
@@ -510,7 +531,7 @@ $messages = array(
 'mytalk' => '讨论',
 'anontalk' => '该IP地址的讨论',
 'navigation' => '导航',
-'and' => '和',
+'and' => '&#32;和',
 
 # Cologne Blue skin
 'qbfind' => '查找',
@@ -527,7 +548,7 @@ $messages = array(
 'vector-action-delete' => '删除',
 'vector-action-move' => '移动',
 'vector-action-protect' => '保护',
-'vector-action-undelete' => '恢复',
+'vector-action-undelete' => '还原',
 'vector-action-unprotect' => '更改保护',
 'vector-simplesearch-preference' => '启用简化的搜索栏(仅Vector皮肤)',
 'vector-view-create' => '创建',
@@ -561,8 +582,8 @@ $messages = array(
 'create-this-page' => '创建本页',
 'delete' => '删除',
 'deletethispage' => '删除本页',
-'undeletethispage' => '恢复本页',
-'undelete_short' => '恢复$1个编辑',
+'undeletethispage' => '还原本页',
+'undelete_short' => '还原{{PLURAL:$1|$1个编辑}}',
 'viewdeleted_short' => '查看$1个被删除的编辑',
 'protect' => '保护',
 'protect_change' => '更改',
@@ -578,7 +599,7 @@ $messages = array(
 'articlepage' => '查看内容页面',
 'talk' => '讨论',
 'views' => '查看',
-'toolbox' => '工具',
+'toolbox' => '工具',
 'userpage' => '查看用户页面',
 'projectpage' => '查看项目页面',
 'imagepage' => '查看文件页面',
@@ -633,12 +654,10 @@ $1',
 'backlinksubtitle' => '←$1',
 'retrievedfrom' => '取自“$1”',
 'youhavenewmessages' => '你有$1($2)。',
-'newmessageslink' => '新信息',
-'newmessagesdifflink' => '最后更改',
 'youhavenewmessagesfromusers' => '你有来自{{PLURAL:$3|其他用户|$3个用户}}的$1($2)。',
 'youhavenewmessagesmanyusers' => '你有来自多个用户的$1($2)。',
-'newmessageslinkplural' => '{{PLURAL:$1|新信息}}',
-'newmessagesdifflinkplural' => '最后{{PLURAL:$1|更改}}',
+'newmessageslinkplural' => '{{PLURAL:$1|新信息|999=新消息}}',
+'newmessagesdifflinkplural' => '最后{{PLURAL:$1|更改|999=更改}}',
 'youhavenewmessagesmulti' => '你在$1有新信息',
 'editsection' => '编辑',
 'editold' => '编辑',
@@ -680,8 +699,8 @@ $1',
 # Main script and global functions
 'nosuchaction' => '无该命令',
 'nosuchactiontext' => 'URL指定的操作无效。你可能输入了错误的URL地址,或是点击了错误的链接。这也可能表明{{SITENAME}}使用的软件的存在漏洞(bug)。',
-'nosuchspecialpage' => 'æ\97 è¯¥ç\89¹æ®\8a页é\9d¢',
-'nospecialpagetext' => '<strong>请求了一个无效的特殊页面。</strong>
+'nosuchspecialpage' => 'æ­¤ç\89¹æ®\8a页é\9d¢ä¸\8då­\98å\9c¨',
+'nospecialpagetext' => '<strong>请求了一个无效的特殊页面。</strong>
 
 有效的特殊页面的列表可以在[[Special:SpecialPages|{{int:specialpages}}]]找到。',
 
@@ -727,10 +746,9 @@ $1',
 'no-null-revision' => '无法创建对"$1"页面新的空白修订',
 'badtitle' => '错误标题',
 'badtitletext' => '所请求页面的标题是无效的、不存在,跨语言或跨wiki链接的标题错误。它可能包含一个或更多的不能用于标题的字符。',
-'perfcached' => '下列数据已缓存,但可能已过时。最高{{PLURAL:$1|一个结果|$1个结果}}在缓存中可用。',
-'perfcachedts' => '下列数据已缓存,最后更新于$1。缓存中最多可有{{PLURAL:$4|1个结果|$4个结果}}。',
-'querypage-no-updates' => '当前禁止对此页面进行更新。
-此处的数据将不能被立即刷新。',
+'perfcached' => '以下是缓存的数据,可能不是最新的数据。缓存中最多有{{PLURAL:$1|$1条结果}}。',
+'perfcachedts' => '以下是缓存的数据,最后更新于$1。缓存中最多有{{PLURAL:$4|$4条结果}}。',
+'querypage-no-updates' => '该页面的更新目前停用。这里的数据不会马上刷新。',
 'wrong_wfQuery_params' => '错误的参数被传递到 wfQuery()<br />
 函数:$1<br />
 查询:$2',
@@ -753,7 +771,7 @@ $2',
 'customjsprotected' => '您没有权限编辑此JavaScript页面,因为它包含另一位用户的个人设置。',
 'mycustomcssprotected' => '您没有权限编辑这个 CSS 页面。',
 'mycustomjsprotected' => '您没有权限编辑这个 JavaScript 页面。',
-'myprivateinfoprotected' => '您没有权限来编辑您的私人信息。',
+'myprivateinfoprotected' => '你没有权限编辑你的私人信息。',
 'mypreferencesprotected' => '您没有权限来编辑您的个人设置。',
 'ns-specialprotected' => '特殊页面不可编辑。',
 'titleprotected' => '此标题已被[[User:$1|$1]]保护以防止创建。理由是“$2”。',
@@ -763,7 +781,8 @@ $2',
 'invalidtitle-knownnamespace' => '使用名字空间“$2”和文本“$3”的无效标题',
 'invalidtitle-unknownnamespace' => '使用未知名字空间编号$1和文本“$2”的无效标题',
 'exception-nologin' => '未登录',
-'exception-nologin-text' => '该页面或操作需要你登录至本wiki。',
+'exception-nologin-text' => '该页面或操作需要你[[Special:Userlogin|登录]]至本Wiki。',
+'exception-nologin-text-manual' => '查看该页面或进行此操作需要您$1。',
 
 # Virus scanner
 'virus-badscanner' => "错误的配置:未知的病毒扫描程序:''$1''",
@@ -809,12 +828,11 @@ $2',
 'gotaccount' => '已经拥有账户?请$1。',
 'gotaccountlink' => '登录',
 'userlogin-resetlink' => '忘记你的登录信息?',
-'userlogin-resetpassword-link' => '重置你的密码',
+'userlogin-resetpassword-link' => '忘记您的密码?',
 'helplogin-url' => 'Help:登录',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|登录帮助]]',
-'userlogin-loggedin' => '您已经作为{{GENDER:$1|$1}}登录。
-使用以下表单以作为另一账户登录。',
-'userlogin-createanother' => '创建另一个帐户',
+'userlogin-loggedin' => '你已经以{{GENDER:$1|$1}}的身份登录。使用下面的表格以其他用户的身份登录。',
+'userlogin-createanother' => '创建另一个账户',
 'createacct-join' => '请在下面输入你的信息。',
 'createacct-another-join' => '在下方输入新帐户信息。',
 'createacct-emailrequired' => '电子邮件地址',
@@ -825,11 +843,11 @@ $2',
 'createacct-realname' => '真实姓名 (可选)',
 'createaccountreason' => '原因:',
 'createacct-reason' => '原因',
-'createacct-reason-ph' => '为ä»\80ä¹\88æ\82¨è¦\81å\88\9b建å\8f¦ä¸\80个å¸\90户',
+'createacct-reason-ph' => '你为ä»\80ä¹\88è¦\81å\88\9b建å\8f¦ä¸\80个账户',
 'createacct-captcha' => '安全检查',
 'createacct-imgcaptcha-ph' => '请输入上图中的文字',
 'createacct-submit' => '创建您的账户',
-'createacct-another-submit' => '创建另一个户',
+'createacct-another-submit' => '创建另一个户',
 'createacct-benefit-heading' => '{{SITENAME}}是由像您这样的人建立的。',
 'createacct-benefit-body1' => '{{PLURAL:$1|编辑}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|页面}}',
@@ -854,7 +872,7 @@ $2',
 'passwordtooshort' => '您的密码至少需要$1个字符。',
 'password-name-match' => '您的密码必须和您的用户名不相同。',
 'password-login-forbidden' => '这个用户名称及密码的使用是被禁止的。',
-'mailmypassword' => '电子邮件发送新密码',
+'mailmypassword' => '重置密码',
 'passwordremindertitle' => '{{SITENAME}}的新临时密码',
 'passwordremindertext' => '有人(可能是您,来自IP地址$1)已请求{{SITENAME}}的新密码($4)。
 用户“$2”的一个新临时密码现在已被设置好为“$3”。
@@ -868,12 +886,14 @@ $2',
 'passwordsent' => '用户"$1"的新密码已经寄往所登记的电子邮件地址。
 请在收到后再登录。',
 'blocked-mailpassword' => '你的IP地址被禁止编辑,为预防滥用,密码恢复功能也被禁止使用。',
-'eauthentsent' => '一封确认信已经发送到推荐的地址。在发送其它邮件到此账户前,您必须首先依照这封信中的指导确认这个电子邮箱真实有效。',
+'eauthentsent' => '一封确认信已经发送至您设定的邮件地址。
+在任何其他邮件发送至您的账户前,您将不得不根据邮件中的指示,确认那个账户确实是您的。',
 'throttled-mailpassword' => '密码提醒已在最近$1小时内发送。为了安全起见,在每$1小时内只能发送一个密码提醒。',
 'mailerror' => '发送邮件错误:$1',
 'acct_creation_throttle_hit' => '使用你的IP地址访问本wiki的访客在过去24小时中创建了{{PLURAL:$1|$1个账户}},达到了这段时间所允许的最大值。因此,使用该IP地址的访客现在不能再创建账户。',
-'emailauthenticated' => '您的电子邮箱地址已经于$2 $3确认有效。',
-'emailnotauthenticated' => '你的电子邮件地址未确认。你不会接收到以下任何特性的电子邮件。',
+'emailauthenticated' => '您的邮箱地址已经于$3在$2确认。',
+'emailnotauthenticated' => '您的邮件地址尚未确认。
+您将不会收到以下任何功能的邮件。',
 'noemailprefs' => '指定一个电子邮箱地址以使用此功能。',
 'emailconfirmlink' => '确认您的邮箱地址',
 'invalidemailaddress' => '邮箱地址格式不正确,请输入正确的邮箱地址或清空该输入框。',
@@ -919,7 +939,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => '重置密码',
 'passwordreset-text-one' => '请输入你要重置的用户名。',
-'passwordreset-text-many' => '{{PLURAL:$1|å¡«å\85\85é\83¨å\88\86å­\97段以é\87\8dç½®æ\82¨ç\9a\84å¯\86ç \81。}}',
+'passwordreset-text-many' => '{{PLURAL:$1|å\9c¨æ­¤é\94®å\85¥æ\82¨å¸\8cæ\9c\9bæ\8e¥æ\94¶ä¸´æ\97¶å¯\86ç \81ç\9a\84é\82®ä»¶å\9c°å\9d\80。}}',
 'passwordreset-legend' => '重置密码',
 'passwordreset-disabled' => '此Wiki已经禁用密码重置。',
 'passwordreset-emaildisabled' => '此Wiki上无法使用邮件功能。',
@@ -929,7 +949,7 @@ $2',
 'passwordreset-capture-help' => '如果您选中此框,电子邮件(包括临时密码)将显示,并发送给用户。',
 'passwordreset-email' => '电子邮件地址:',
 'passwordreset-emailtitle' => '在 {{SITENAME}} 的帐户详细信息',
-'passwordreset-emailtext-ip' => '有人通过IP地址$1(可能是您请求重设{{SITENAME}}($4)上相关账户的密码。{{PLURAL:$3|以下账户|此账户}}与该电子邮件地址关联:
+'passwordreset-emailtext-ip' => '有人(可能是您,来自IP地址$1)请求重设{{SITENAME}}($4)上相关账户的密码。{{PLURAL:$3|以下账户|此账户}}与该电子邮件地址关联:
 
 $2
 
@@ -947,8 +967,8 @@ $2
 
 # Special:ChangeEmail
 'changeemail' => '更改电子邮件地址',
-'changeemail-header' => '更改帐户的电子邮件地址',
-'changeemail-text' => 'å¡«å\86\99此表å\8d\95å\8f¯ä»¥æ\9b´æ\94¹æ\82¨ç\9a\84ç\94µå­\90é\82®ä»¶å\9c°å\9d\80ã\80\82æ\82¨å°\86é\9c\80è¦\81è¾\93å\85¥æ\82¨ç\9a\84å¯\86ç \81以确认此更改。',
+'changeemail-header' => '更改账户电子邮件地址',
+'changeemail-text' => 'å®\8cæ\88\90该表格以æ\9b´æ\94¹ä½ ç\9a\84ç\94µå­\90é\82®ä»¶å\9c°å\9d\80ã\80\82ä½ é\9c\80è¦\81è¾\93å\85¥ä½ ç\9a\84å¯\86ç \81以确认该更改。',
 'changeemail-no-info' => '
 您必须登录以直接访问本页。',
 'changeemail-oldemail' => '当前电子邮件地址:',
@@ -959,17 +979,17 @@ $2
 'changeemail-cancel' => '取消',
 
 # Special:ResetTokens
-'resettokens' => '重置权标',
-'resettokens-text' => '您可以重置权标,其允许访问某些与您的帐户相关联的私人数据
+'resettokens' => '重置密钥',
+'resettokens-text' => '你可以在这里重置允许访问与你的账户有关的特定私人数据的密钥
 
-如果您意外地与他人共享权标,或您的帐户已遭到破坏,您应该重置权标。',
-'resettokens-no-tokens' => '没有可重置得权标。',
-'resettokens-legend' => '重置权标',
-'resettokens-tokens' => '权标:',
+如果你意外将它们分享给他人,或是你的账户已经被入侵,你应该重置它们。',
+'resettokens-no-tokens' => '没有可以重置的密钥。',
+'resettokens-legend' => '重置密钥',
+'resettokens-tokens' => '密钥:',
 'resettokens-token-label' => '$1(当前值:$2)',
-'resettokens-watchlist-token' => '请在[[Special:Watchlist|您的监视列表]]中更改Web订阅(Atom或RSS)的权标',
-'resettokens-done' => '权标已重置。',
-'resettokens-resetbutton' => '重置所选的权标',
+'resettokens-watchlist-token' => '[[Special:Watchlist|对你的监视列表中的页面的更改]]的网页feed(Atom/RSS)的密钥',
+'resettokens-done' => '密钥已重置。',
+'resettokens-resetbutton' => '重置选择的密钥',
 
 # Edit page toolbar
 'bold_sample' => '粗体文字',
@@ -1043,9 +1063,7 @@ $2
 'accmailtitle' => '密码已寄出',
 'accmailtext' => "为[[User talk:$1|$1]]随机生成的密码已送至$2。登录后可以在''[[Special:ChangePassword|更改密码]]''页面中修改。",
 'newarticle' => '(新页面)',
-'newarticletext' => '您进入了一个尚未创建的页面。
-要创建该页面,请在下面的编辑框中输入内容(详情参见[[{{MediaWiki:Helppage}}|帮助页]])。
-如果您误入此页,请点击浏览器中的“返回”按钮。',
+'newarticletext' => "你点击了一个尚不存在的页面的链接。要创建该页面,请在下面的编辑框中输入内容(更多信息请见[[{{MediaWiki:Helppage}}|帮助页面]])。如果你是错误地到达这里,请点击你的浏览器的'''返回'''按钮。",
 'anontalkpagetext' => "---- ''这是一个还未建立账户的匿名用户的讨论页, 因此我们只能用IP地址来与他或她联络。该IP地址可能由几名用户共享。如果您是一名匿名用户并认为此页上的评语与您无关,请[[Special:UserLogin/signup|创建新账户]]或[[Special:UserLogin|登录]]以避免在未来与其他匿名用户混淆。''",
 'noarticletext' => '本页面目前没有内容。你可以在其他页面中[[Special:Search/{{PAGENAME}}|搜索本页标题]]、<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜索相关日志]或[{{fullurl:{{FULLPAGENAME}}|action=edit}} 编辑本页面]。</span>',
 'noarticletext-nopermission' => '本页面目前没有内容。你可以在其他页面中[[Special:Search/{{PAGENAME}}|搜索本页标题]]或<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜索相关日志],但你没有权限创建本页面。',
@@ -1056,10 +1074,10 @@ $2
 'userpage-userdoesnotexist' => '用户账户“$1”没有注册。请在创建/编辑本页前检查。',
 'userpage-userdoesnotexist-view' => '用户账户“$1”未曾创建。',
 'blocked-notice-logextract' => '这位用户目前已被封禁。以下提供最近的封禁日志以供参考:',
-'clearyourcache' => "'''注意:'''保存之后,你必须清除浏览器缓存才能看到做出的更改。
-* '''火狐(Firefox)/Safari:'''按住“Shift”,同时单击“刷新”,或按“Ctrl-F5”或“Ctrl-R”(Mac为“⌘-R”)
+'clearyourcache' => "'''注意:'''在保存之后,你可能需要清除你的浏览器的缓存以查看更改。
+* '''Firefox/Safari:'''按住“Shift”的同时单击“刷新”,或按“Ctrl-F5”或“Ctrl-R”(Mac为“⌘-R”)
 * '''Google Chrome:'''按“Ctrl-Shift-R”(Mac为“⌘-Shift-R”)
-* '''Internet Explorer:'''按住“Ctrl”同时单击“刷新”,或按“Ctrl-F5”
+* '''Internet Explorer:'''按住“Ctrl”同时单击“刷新”,或按“Ctrl-F5”
 * '''Opera:'''在“工具→首选项”中清除缓存",
 'usercssyoucanpreview' => "'''提示:''' 在保存前请用“{{int:showpreview}}”按钮来测试您新的 CSS 。",
 'userjsyoucanpreview' => "'''提示:''' 在保存前请用“{{int:showpreview}}”按钮来测试您新的 JavaScript 。",
@@ -1144,10 +1162,10 @@ $2
 'content-failed-to-parse' => '未能将 $2 内容转换为 $1:$3',
 'invalid-content-data' => '无效的内容数据',
 'content-not-allowed-here' => '[[$2]]页面上不允许“$1”内容',
-'editwarning-warning' => '离开这个页面会令您遗失之前的所有更改。若您已经登入,您可在您参数设置的“编辑”节中关闭此警告。',
+'editwarning-warning' => '离开本页面可能导致你失去任何你已经作出的更改。如果你处于登录状态,你可以在你的设置的“编辑”部分停用该警告。',
 
 # Content models
-'content-model-wikitext' => 'wiki语法',
+'content-model-wikitext' => 'wiki文本',
 'content-model-text' => '纯文本',
 'content-model-javascript' => 'JavaScript',
 'content-model-css' => 'CSS',
@@ -1157,8 +1175,8 @@ $2
 
 它应该少过$2次呼叫,现在有$1次呼叫。',
 'expensive-parserfunction-category' => '页面中有太多耗费的语法功能呼叫',
-'post-expand-template-inclusion-warning' => '警告:包含模板大小过大。
-一些模板将不会包含。',
+'post-expand-template-inclusion-warning' => "'''警告:'''包含模板大小过大。
+一些模板将不会包含。",
 'post-expand-template-inclusion-category' => '模板包含上限已经超过的页面',
 'post-expand-template-argument-warning' => "'''警告:'''本页面包含至少一个模板参数有过大扩展大小。这些参数会被略过。",
 'post-expand-template-argument-category' => '包含着略过模板参数的页面',
@@ -1176,7 +1194,7 @@ $2
 # "Undo" feature
 'undo-success' => '该编辑可以被撤销。请检查下面的对比以核实你想要撤销的内容,然后保存下面的更改以完成撤销。',
 'undo-failure' => '因存在冲突的中间编辑,本编辑不能撤销。',
-'undo-norev' => '由于其修订版本不存在或已删除,此编辑不能撤销。',
+'undo-norev' => '该编辑无法撤消,因为它不存在或已被删除。',
 'undo-summary' => '撤销[[Special:Contributions/$2|$2]]([[User talk:$2|讨论]])的版本$1',
 'undo-summary-username-hidden' => '取消由一匿名用户所作的修订$1',
 
@@ -1236,7 +1254,7 @@ $3的理由是''$2''",
 'rev-suppressed-diff-view' => "差异对比中的一次修订已被'''监督隐藏'''。您可以对比此差异。详细信息可在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中找到。",
 'rev-delundel' => '显示/隐藏',
 'rev-showdeleted' => '显示',
-'revisiondelete' => '删除/恢复版本',
+'revisiondelete' => '删除/还原版本',
 'revdelete-nooldid-title' => '无效目标版本',
 'revdelete-nooldid-text' => '您尚未指定一个目标修订去进行这个功能、
 所指定的修订不存在,或者您尝试去隐藏现时的修订。',
@@ -1252,20 +1270,20 @@ $3的理由是''$2''",
 'revdelete-text' => "'''删除的版本仍将显示在页面历史及日志中,但公众已不能访问其文本内容。'''
 在{{SITENAME}}的其他管理员将仍能访问隐藏的内容并通过该界面恢复删除的版本,除非进行了额外限制。",
 'revdelete-confirm' => '请确认该操作,明白其后果,并确保该操作符合[[{{MediaWiki:Policy-url}}|方针]]。',
-'revdelete-suppress-text' => "阻止应该'''只'''在以下情形使用
-*潜在的诽谤信息
-*不合适的个人信息
-*:''家庭地址、电话号码和社保号码等。''",
+'revdelete-suppress-text' => "阻止应'''仅'''用于以下情况
+* 潜在的诽谤信息
+* 不合适的个人信息
+*: ''家庭地址、电话号码和社保号码等。''",
 'revdelete-legend' => '设置可见性之限制',
-'revdelete-hide-text' => '隐藏版本文字',
+'revdelete-hide-text' => '修订文字',
 'revdelete-hide-image' => '隐藏文件内容',
 'revdelete-hide-name' => '隐藏动作和目标',
-'revdelete-hide-comment' => '隐藏编辑摘要',
-'revdelete-hide-user' => '隐藏编辑者的用户名/IP地址',
+'revdelete-hide-comment' => '编辑摘要',
+'revdelete-hide-user' => '编辑者的用户名/IP地址',
 'revdelete-hide-restricted' => '同时阻止管理员与其他用户查看数据',
-'revdelete-radio-same' => '(不更改)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => '',
+'revdelete-radio-same' => '(不更改)',
+'revdelete-radio-set' => '可见',
+'revdelete-radio-unset' => '隐藏',
 'revdelete-suppress' => '同时阻止管理员与其他用户查看数据',
 'revdelete-unsuppress' => '在已恢复的修订中移除限制',
 'revdelete-log' => '原因:',
@@ -1394,13 +1412,13 @@ $1",
 'searchall' => '所有',
 'showingresults' => "下面显示从第'''$2'''条结果开始的'''$1'''条结果。",
 'showingresultsnum' => "下面显示从第'''$2'''条结果开始的'''$3'''条结果。",
-'showingresultsheader' => "关于'''$4'''的{{PLURAL:$5|第'''$1'''条结果,共'''$3'''条结果|第'''$1-$2'''条结果,共'''$3'''条结果}}",
+'showingresultsheader' => "关于'''$4'''的{{PLURAL:$5|第'''$1'''条结果,共'''$3'''条结果|第'''$1~$2'''条结果,共'''$3'''条结果}}",
 'nonefound' => "'''注意''':只有某些名字空间被默认搜索。请尝试给你的搜索内容添加前缀“all:”以搜索全部内容(包括讨论页面、模板等)或使用期望的名字空间作为前缀。",
 'search-nonefound' => '找不到和查询相匹配的结果。',
 'powersearch' => '高级搜索',
 'powersearch-legend' => '高级搜索',
 'powersearch-ns' => '在以下的名字空间中搜索:',
-'powersearch-redir' => '列出重定向',
+'powersearch-redir' => '列出重定向',
 'powersearch-field' => '搜索',
 'powersearch-togglelabel' => '选择:',
 'powersearch-toggleall' => '全选',
@@ -1413,13 +1431,12 @@ $1",
 'preferences' => '设置',
 'mypreferences' => '设置',
 'prefs-edits' => '编辑数:',
-'prefsnologin' => '未登录',
-'prefsnologintext' => '您必须先<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登录]</span>才能设置个人参数。',
+'prefsnologintext2' => '进行用户设置需要您$1。',
 'changepassword' => '更改密码',
 'prefs-skin' => '皮肤',
 'skin-preview' => '预览',
 'datedefault' => '默认格式',
-'prefs-beta' => '测试特性',
+'prefs-beta' => '测试功能',
 'prefs-datetime' => '日期时间',
 'prefs-labs' => '实验室特性',
 'prefs-user-pages' => '用户页面',
@@ -1428,9 +1445,9 @@ $1",
 'prefs-watchlist' => '监视列表',
 'prefs-watchlist-days' => '监视列表中显示的天数:',
 'prefs-watchlist-days-max' => '最多$1天',
-'prefs-watchlist-edits' => '扩展监视列表中显示的最大更改数:',
-'prefs-watchlist-edits-max' => '最大数:1000',
-'prefs-watchlist-token' => '监视列表权标:',
+'prefs-watchlist-edits' => '在扩展监视列表中显示的更改的最大数目:',
+'prefs-watchlist-edits-max' => '最大数:1000',
+'prefs-watchlist-token' => '监视列表密钥:',
 'prefs-misc' => '其他',
 'prefs-resetpass' => '更改密码',
 'prefs-changeemail' => '更改电子邮件地址',
@@ -1450,10 +1467,8 @@ $1",
 'recentchangesdays' => '最近更改中显示的天数:',
 'recentchangesdays-max' => '最多$1天',
 'recentchangescount' => '默认显示的编辑数:',
-'prefs-help-recentchangescount' => '该项包含最近更改、页面历史和日志。',
-'prefs-help-watchlist-token2' => '这是您的监视列表网络订阅源密钥的关键。
-知道它的人将能够读取您的监视列表,所以不应分享它。
-[[Special:ResetTokens|点击这里以重置它]]。',
+'prefs-help-recentchangescount' => '这包括近更改、页面历史和日志。',
+'prefs-help-watchlist-token2' => '这是你的监视列表网页feed的密钥。任何知道它的人均可以阅读你的监视列表,因此不要分享它。[[Special:ResetTokens|如果需要重置它,请点击这里]]。',
 'savedprefs' => '你的系统设置已保存。',
 'timezonelegend' => '时区:',
 'localtime' => '当地时间:',
@@ -1491,7 +1506,7 @@ $1",
 'yourrealname' => '真实姓名:',
 'yourlanguage' => '语言:',
 'yourvariant' => '内容语言变种:',
-'prefs-help-variant' => '您希望用于显示本站内容的语种或拼写语系。',
+'prefs-help-variant' => '你希望用于显示该wiki的内容页面的语言变种或正字法。',
 'yournick' => '新签名:',
 'prefs-help-signature' => '讨论页面上的评论应该使用“<nowiki>~~~~</nowiki>”签名,它会自动转换为你的签名及时间戳。',
 'badsig' => '错误的原始签名。请检查HTML标签。',
@@ -1500,12 +1515,10 @@ $1",
 'gender-unknown' => '我不愿意指明(被称为“他/她”)',
 'gender-male' => '他',
 'gender-female' => '她',
-'prefs-help-gender' => '这是选填项目。
-软件使用其以显示正确的性别称呼。
-该信息将会公开。',
+'prefs-help-gender' => '该设置为可选项目。软件根据它的值在称呼你及对他人提及你时使用适当的语法性别。该信息会被公开。',
 'email' => '电子邮件',
 'prefs-help-realname' => '真实姓名是选填项目。如果你选择提供它,它将会用于贡献署名。',
-'prefs-help-email' => '电子邮件地址是选填项目,但是当你忘记密码需要重置密码时需要该项信息。',
+'prefs-help-email' => '电子邮件是可选项,但是在您忘记密码时很有用。',
 'prefs-help-email-others' => '你也可以选择让其他用户通过你的用户或讨论页面上的链接用电子邮件联系你。其他用户联系你时你的电子邮件地址不会显示。',
 'prefs-help-email-required' => '电子邮件地址是必填项目。',
 'prefs-info' => '基本信息',
@@ -1523,9 +1536,9 @@ $1",
 'prefs-displayrc' => '显示',
 'prefs-displaysearchoptions' => '显示',
 'prefs-displaywatchlist' => '显示',
-'prefs-tokenwatchlist' => '权标',
+'prefs-tokenwatchlist' => '密钥',
 'prefs-diffs' => '差异对比',
-'prefs-help-prefershttps' => '此首选项将在您下次登录时生效。',
+'prefs-help-prefershttps' => '该设置将在你下次登录时生效。',
 
 # User preference: email validation using jQuery
 'email-address-validity-valid' => '电子邮件地址有效',
@@ -1601,7 +1614,7 @@ $1",
 'right-bot' => '被视为自动过程',
 'right-nominornewtalk' => '不使小编辑在讨论页面引发新信息提示',
 'right-apihighlimits' => '在API查询中使用更高的限制',
-'right-writeapi' => '使用书写API',
+'right-writeapi' => '使用写入API',
 'right-delete' => '删除页面',
 'right-bigdelete' => '删除有大型历史的页面',
 'right-deletelogentry' => '删除和恢复特定的日志项目',
@@ -1609,7 +1622,7 @@ $1",
 'right-deletedhistory' => '查看被删除的历史条目,无其相关文字',
 'right-deletedtext' => '查看被删除的版本间的被删除的文字和更改',
 'right-browsearchive' => '搜索被删除的页面',
-'right-undelete' => '恢复页面',
+'right-undelete' => '还原页面',
 'right-suppressrevision' => '审查和恢复管理员隐藏的版本',
 'right-suppressionlog' => '查看非公开日志',
 'right-block' => '阻止其他用户编辑',
@@ -1625,12 +1638,12 @@ $1",
 'right-editusercssjs' => '编辑其他用户的CSS和JavaScript文件',
 'right-editusercss' => '编辑其他用户的CSS文件',
 'right-edituserjs' => '编辑其他用户的JavaScript文件',
-'right-editmyusercss' => '编辑您自己的用户 CSS 文件',
-'right-editmyuserjs' => '编辑您自己的用户 JavaScript 文件',
+'right-editmyusercss' => '编辑你自己的用户CSS文件',
+'right-editmyuserjs' => '编辑你自己的用户JavaScript文件',
 'right-viewmywatchlist' => '查看你的监视列表',
 'right-editmywatchlist' => '编辑您的监视列表。请注意即使没有这种权利,某些操作仍将添加页面。',
-'right-viewmyprivateinfo' => '查看您自己的私人数据 (如电子邮件地址、 真实姓名)',
-'right-editmyprivateinfo' => '编辑您自己的私人数据 (如电子邮件地址、 真实姓名)',
+'right-viewmyprivateinfo' => '查看你自己的私人数据(如电子邮件地址、真实姓名)',
+'right-editmyprivateinfo' => '编辑你自己的私人数据(如电子邮件地址、真实姓名)',
 'right-editmyoptions' => '编辑您的个人设置',
 'right-rollback' => '快速回退最后编辑特定页面的用户的编辑',
 'right-markbotedits' => '标记回退编辑为机器人编辑',
@@ -1672,12 +1685,12 @@ $1",
 'action-reupload' => '覆盖本文件',
 'action-reupload-shared' => '覆盖共享文件库的本文件',
 'action-upload_by_url' => '从URL上传本文件',
-'action-writeapi' => '使用书写API',
+'action-writeapi' => '使用写入API',
 'action-delete' => '删除本页',
 'action-deleterevision' => '删除本版本',
 'action-deletedhistory' => '查看本页面被删除的历史',
 'action-browsearchive' => '搜索被删除的页面',
-'action-undelete' => '恢复本页',
+'action-undelete' => '还原本页',
 'action-suppressrevision' => '审查和恢复本隐藏版本',
 'action-suppressionlog' => '查看本非公开日志',
 'action-block' => '阻止该用户编辑',
@@ -1696,7 +1709,7 @@ $1",
 'action-editmywatchlist' => '编辑你的监视列表',
 'action-viewmywatchlist' => '查看你的监视列表',
 'action-viewmyprivateinfo' => '查看您的私人信息',
-'action-editmyprivateinfo' => '编辑的私人信息',
+'action-editmyprivateinfo' => '编辑的私人信息',
 
 # Recent changes
 'nchanges' => '$1个更改',
@@ -1711,6 +1724,9 @@ $1",
 'recentchanges-label-minor' => '这是一个小编辑',
 'recentchanges-label-bot' => '该编辑由机器人进行',
 'recentchanges-label-unpatrolled' => '该编辑尚未巡查',
+'recentchanges-label-plusminus' => '页面大小通过该字节数更改',
+'recentchanges-legend-newpage' => '(另见[[Special:NewPages|新页面列表]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "下面是过去'''$2'''天的最后'''$1'''个更改,截至$4 $5。",
 'rcnotefrom' => "下面是'''$2'''之后的更改(最多显示'''$1'''个)。",
 'rclistfrom' => '显示$1之后的新更改',
@@ -1917,8 +1933,7 @@ $1',
 'zip-wrong-format' => '指定的文件不是一个 ZIP 文件。',
 'zip-bad' => '该文件是已损坏或以其它方式无法读取的 ZIP 文件。
 不能正确检查安全。',
-'zip-unsupported' => '该文件是 ZIP 文件,其中使用 MediaWiki 不支持的ZIP功能。
-不能正确检查安全。',
+'zip-unsupported' => '该文件是使用MediaWiki不支持的ZIP特性的ZIP文件。无法正确地检查其安全性。',
 
 # Special:UploadStash
 'uploadstash' => '上传隐藏',
@@ -1969,7 +1984,7 @@ $1',
 'upload_source_file' => '(您计算机上的一个文件)',
 
 # Special:ListFiles
-'listfiles-summary' => '本特殊页面示所有上传的文件。',
+'listfiles-summary' => '本特殊页面示所有上传的文件。',
 'listfiles_search_for' => '按媒体名称搜索:',
 'imgfile' => '文件',
 'listfiles' => '文件列表',
@@ -1977,7 +1992,7 @@ $1',
 'listfiles_date' => '日期',
 'listfiles_name' => '名称',
 'listfiles_user' => '用户',
-'listfiles_size' => '大å°\8f',
+'listfiles_size' => '尺寸',
 'listfiles_description' => '说明',
 'listfiles_count' => '版本',
 'listfiles-show-all' => '包括图片的旧版本',
@@ -2027,11 +2042,11 @@ $1',
 # File reversion
 'filerevert' => '恢复$1',
 'filerevert-legend' => '恢复文件',
-'filerevert-intro' => "您正在将文件'''[[Media:$1|$1]]'''恢复到[$4 于$2 $3的版本]。",
+'filerevert-intro' => "你将要恢复文件'''[[Media:$1|$1]]'''至[$4 $2 $3的版本]。",
 'filerevert-comment' => '原因:',
-'filerevert-defaultcomment' => '已经恢复到于$1 $2的版本',
+'filerevert-defaultcomment' => '恢复至$1 $2的版本',
 'filerevert-submit' => '恢复',
-'filerevert-success' => "'''[[Media:$1|$1]]'''已经恢复到[$4 于$2 $3的版本]。",
+'filerevert-success' => "'''[[Media:$1|$1]]'''已经恢复至[$4 $2 $3的版本]。",
 'filerevert-badversion' => '文件并无所请求时间戳下的早期本地版本。',
 
 # File deletion
@@ -2069,7 +2084,7 @@ $1',
 
 # Unused templates
 'unusedtemplates' => '未使用模板',
-'unusedtemplatestext' => '此页é\9d¢å\88\97å\87º{{ns:template}}å\90\8då­\97空é\97´ä¸\8bæ\89\80æ\9c\89æ\9cªè¢«å\85¶å®\83页é\9d¢ä½¿ç\94¨ç\9a\84页é\9d¢ã\80\82请å\9c¨å\88 é\99¤è¿\99äº\9b模æ\9d¿å\89\8dæ£\80æ\9f¥å\85¶å®\83é\93¾å\85¥è¯¥æ¨¡æ\9d¿ç\9a\84页é\9d¢。',
+'unusedtemplatestext' => 'æ\9c¬é¡µé\9d¢å\88\97å\87º{{ns:template}}å\90\8då­\97空é\97´ä¸­æ\89\80æ\9c\89æ\9cªå\8c\85å\90«äº\8eå\85¶å®\83页é\9d¢ç\9a\84页é\9d¢ã\80\82请记å¾\97å\9c¨å\88 é\99¤è¿\99äº\9b模æ\9d¿å\89\8dæ£\80æ\9f¥å\85¶ä»\96é\93¾è\87³å®\83们ç\9a\84é\93¾æ\8e¥。',
 'unusedtemplateswlh' => '其它链接',
 
 # Random page
@@ -2077,11 +2092,11 @@ $1',
 'randompage-nopages' => '在以下{{PLURAL:$2|名字空间}}中没有页面:$1。',
 
 # Random page in category
-'randomincategory' => '分类中随机页面',
+'randomincategory' => '分类中随机页面',
 'randomincategory-invalidcategory' => '“$1”不是一个有效的分类名称。',
 'randomincategory-nopages' => '[[:Category:$1]]中没有页面。',
-'randomincategory-selectcategory' => '从分类获取随机页面:$1 $2。',
-'randomincategory-selectcategory-submit' => 'æ\98¾ç¤º',
+'randomincategory-selectcategory' => '获取随机页面从分类:$1 $2。',
+'randomincategory-selectcategory-submit' => 'æ\8f\90交',
 
 # Random redirect
 'randomredirect' => '随机重定向',
@@ -2102,41 +2117,41 @@ $1',
 'statistics-edits-average' => '每页平均编辑数',
 'statistics-views-total' => '查看总数',
 'statistics-views-total-desc' => '不存在页面和特殊页面的查看数未计入',
-'statistics-views-peredit' => '每编辑查看数',
+'statistics-views-peredit' => '每编辑查看数',
 'statistics-users' => '注册[[Special:ListUsers|用户]]',
 'statistics-users-active' => '活跃用户',
 'statistics-users-active-desc' => '在前$1天中操作过的用户',
-'statistics-mostpopular' => 'æµ\8fè§\88æ\9c\80å¤\9aç\9a\84页面',
+'statistics-mostpopular' => 'æ\9c\80å¤\9aæ\9f¥ç\9c\8b页面',
 
 'pageswithprop' => '有页面属性的页面',
 'pageswithprop-legend' => '有页面属性的页面',
-'pageswithprop-text' => '此页é\9d¢å\88\97å\87ºäº\86使ç\94¨ç\89¹å®\9a页é\9d¢å±\9eæ\80§ç\9a\84页é\9d¢å\90\8då\8d\95。',
+'pageswithprop-text' => 'æ\9c¬é¡µé\9d¢å\88\97å\87ºä½¿ç\94¨ç\89¹å®\9a页é\9d¢å±\9eæ\80§ç\9a\84页é\9d¢。',
 'pageswithprop-prop' => '属性名称:',
 'pageswithprop-submit' => '提交',
 'pageswithprop-prophidden-long' => '长文本属性值已隐藏($1)',
 'pageswithprop-prophidden-binary' => '已隐藏二进制属性值($1)',
 
 'doubleredirects' => '双重重定向',
-'doubleredirectstext' => '本页面列出重定向至其他重定向页的页面。每行含有第一及第二重定向的链接和第二重定向的目标(通常是第一重定向应该指向的“真实”目标页面)。<del>带删除线的</del>条目已被解决。',
+'doubleredirectstext' => '本页面列出重定向至其他重定向页面的页面。每行含有第一及第二重定向的链接和第二重定向的目标(这通常是第一重定向应该指向的“实际”目标页面)。<del>带删除线的</del>条目已经被解决。',
 'double-redirect-fixed-move' => '[[$1]]已被移动。它现在重定向至[[$2]]。',
 'double-redirect-fixed-maintenance' => '修复双重重定向自[[$1]]至[[$2]]。',
-'double-redirect-fixer' => '重定向修复器',
+'double-redirect-fixer' => '重定向修复器',
 
 'brokenredirects' => '受损重定向',
-'brokenredirectstext' => '以下的重定向页面指向的是不存在的页面:',
+'brokenredirectstext' => '以下重定向链接至不存在的页面:',
 'brokenredirects-edit' => '编辑',
 'brokenredirects-delete' => '删除',
 
 'withoutinterwiki' => '无语言链接页面',
-'withoutinterwiki-summary' => '以下的页面是未有语言链接到其它语言版本。',
+'withoutinterwiki-summary' => '以下页面没有链接至其它语言版本。',
 'withoutinterwiki-legend' => '前缀',
 'withoutinterwiki-submit' => '显示',
 
-'fewestrevisions' => '版本最少页面',
+'fewestrevisions' => '有最少版本的页面',
 
 # Miscellaneous special pages
 'nbytes' => '$1字节',
-'ncategories' => '$1个分类',
+'ncategories' => '$1个{{PLURAL:$1|分类}}',
 'ninterwikis' => '$1个跨语言链接',
 'nlinks' => '$1个链接',
 'nmembers' => '$1个成员',
@@ -2146,7 +2161,7 @@ $1',
 'ntransclusions' => '用于$1个页面中',
 'specialpage-empty' => '无该报告的结果。',
 'lonelypages' => '孤立页面',
-'lonelypagestext' => '以下页面尚未被{{SITENAME}}中的其它页面链接或被之包含。',
+'lonelypagestext' => '以下页面没有被{{SITENAME}}的其它页面链接或包含。',
 'uncategorizedpages' => '未归类页面',
 'uncategorizedcategories' => '未归类分类',
 'uncategorizedimages' => '未归类文件',
@@ -2158,30 +2173,30 @@ $1',
 'wantedpages' => '需要的页面',
 'wantedpages-badtitle' => '在结果组上的无效标题:$1',
 'wantedfiles' => '需要的文件',
-'wantedfiletext-cat' => 'ä¸\8bå\88\97被使ç\94¨ç\9a\84æ\96\87件并ä¸\8då­\98å\9c¨ã\80\82å·²å\88\97å\87ºå\8f¯è\83½å­\98å\9c¨å¤\96é\83¨åª\92ä½\93åº\93中ç\9a\84æ\96\87件ã\80\82ä»»ä½\95此类误æ\8a¥å°\86被<del>å\89\94é\99¤</del>ã\80\82æ­¤å¤\96ï¼\8c[[:$1]]å\88\97å\87ºå\88\97å\87ºäº\86åµ\8cå\85¥ä¸\8då­\98å\9c¨æ\96\87件ç\9a\84页é\9d¢。',
-'wantedfiletext-nocat' => 'ä¸\8bå\88\97被使ç\94¨ç\9a\84æ\96\87件并ä¸\8då­\98å\9c¨ã\80\82å·²å\88\97å\87ºå\8f¯è\83½å­\98å\9c¨å¤\96é\83¨åª\92ä½\93åº\93中ç\9a\84æ\96\87件ã\80\82ä»»ä½\95此类误æ\8a¥å°\86被<del>å\89\94é\99¤</del>。',
+'wantedfiletext-cat' => '以ä¸\8bæ\96\87件被使ç\94¨ï¼\8cä½\86并ä¸\8då­\98å\9c¨ã\80\82æ\9d¥è\87ªå¤\96é\83¨åº\93ç\9a\84æ\96\87件å\8d³ä½¿å­\98å\9c¨ä¹\9få\8f¯è\83½è¢«å\88\97å\87ºã\80\82ä»»ä½\95è¿\99类误æ\8a¥ä¼\9aç\94¨<del>å\88 é\99¤çº¿</del>æ \87è®°ã\80\82å\8f¦å¤\96ï¼\8cæ\8f\92å\85¥ä¸\8då­\98å\9c¨ç\9a\84æ\96\87件ç\9a\84页é\9d¢å\88\97äº\8e[[:$1]]。',
+'wantedfiletext-nocat' => '以ä¸\8bæ\96\87件被使ç\94¨ï¼\8cä½\86并ä¸\8då­\98å\9c¨ã\80\82æ\9d¥è\87ªå¤\96é\83¨åº\93ç\9a\84æ\96\87件å\8d³ä½¿å­\98å\9c¨ä¹\9få\8f¯è\83½è¢«å\88\97å\87ºã\80\82ä»»ä½\95è¿\99类误æ\8a¥ä¼\9aç\94¨<del>å\88 é\99¤çº¿</del>æ \87è®°。',
 'wantedtemplates' => '需要的模板',
 'mostlinked' => '最多链接页面',
 'mostlinkedcategories' => '最多链接分类',
 'mostlinkedtemplates' => '最多链接模板',
-'mostcategories' => 'æ\9c\80å¤\9aå\88\86ç±»页面',
+'mostcategories' => 'æ\9c\89æ\9c\80å¤\9aå\88\86ç±»ç\9a\84页面',
 'mostimages' => '最多链接文件',
-'mostinterwikis' => 'æ\9c\80å¤\9a跨语è¨\80é\93¾æ\8e¥页面',
-'mostrevisions' => 'æ\9c\80å¤\9aç\89\88æ\9c¬页面',
+'mostinterwikis' => 'æ\9c\89æ\9c\80å¤\9aè·¨wikiç\9a\84页面',
+'mostrevisions' => 'æ\9c\89æ\9c\80å¤\9aç\89\88æ\9c¬ç\9a\84页面',
 'prefixindex' => '所有有前缀的页面',
 'prefixindex-namespace' => '所有有前缀的页面($1名字空间)',
-'prefixindex-strip' => '在列表中省略前缀',
+'prefixindex-strip' => '在列表中除去前缀',
 'shortpages' => '短页面',
 'longpages' => '长页面',
 'deadendpages' => '断链页面',
-'deadendpagestext' => '以下页面没有链接到{{SITENAME}}中的其它页面。',
+'deadendpagestext' => '以下页面没有链接至{{SITENAME}}的其它页面。',
 'protectedpages' => '受保护页面',
 'protectedpages-indef' => '仅无限期保护',
 'protectedpages-cascade' => '仅连锁保护',
 'protectedpagestext' => '以下页面受到保护,不能移移或编辑',
 'protectedpagesempty' => '在这些参数下没有页面正在保护。',
 'protectedtitles' => '受保护标题',
-'protectedtitlestext' => '以下的页面已经被保护以防止创建',
+'protectedtitlestext' => '以下标题受到保护,不能创建',
 'protectedtitlesempty' => '在这些参数之下并无标题正在保护。',
 'listusers' => '用户列表',
 'listusers-editsonly' => '只显示有编辑的用户',
@@ -2194,9 +2209,8 @@ $1',
 'ancientpages' => '最老页面',
 'move' => '移动',
 'movethispage' => '移动本页',
-'unusedimagestext' => '下列文件已存在,但并未插入任何页面。
-请注意其它网站可能会直接通过URL链接此文件,因此下面列出的文件依然有可能被使用。',
-'unusedcategoriestext' => '虽然没有被其它页面或者分类所采用,但列表中的分类页依然存在。',
+'unusedimagestext' => '以下文件实际存在,但并没有插入任何页面。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。',
+'unusedcategoriestext' => '以下分类页面实际存在,即使没有其它页面或分类利用它们。',
 'notargettitle' => '无目标',
 'notargettext' => '您还没有指定一个目标页面或用户以进行此项操作。',
 'nopagetitle' => '无目标页面',
@@ -2211,7 +2225,7 @@ $1',
 'booksources-search-legend' => '搜索图书来源',
 'booksources-isbn' => 'ISBN:',
 'booksources-go' => '提交',
-'booksources-text' => '以ä¸\8bæ\98¯ä¸\80äº\9bç½\91ç»\9c书åº\97ç\9a\84é\93¾æ\8e¥å\88\97表ï¼\8cå\85¶ä¸­å\8f¯è\83½æ\9c\89æ\82¨è¦\81æ\89¾ç\9a\84书ç±\8d的更多信息:',
+'booksources-text' => 'ä¸\8bé\9d¢æ\98¯é\94\80å\94®æ\96°ä¹¦å\92\8cäº\8cæ\89\8b书ç\9a\84å\85¶ä»\96ç½\91ç«\99ç\9a\84é\93¾æ\8e¥ç\9a\84å\88\97表ï¼\8cä¹\9få\8f¯è\83½æ\9c\89å\85³äº\8eä½ æ­£å\9c¨å¯»æ\89¾ç\9a\84å\9b¾ä¹¦的更多信息:',
 'booksources-invalid-isbn' => '提供的ISBN号码并不正确,请检查原始复制来源号码是否有误。',
 
 # Special:Log
@@ -2229,18 +2243,18 @@ $1',
 'alphaindexline' => '$1到$2',
 'nextpage' => '下一页($1)',
 'prevpage' => '上一页($1)',
-'allpagesfrom' => '显示从此处开始的页面:',
-'allpagesto' => '显示从此处结束的页面:',
+'allpagesfrom' => '显示页面开始于:',
+'allpagesto' => '显示页面结束于:',
 'allarticles' => '所有页面',
 'allinnamespace' => '所有页面($1名字空间)',
 'allnotinnamespace' => '所有页面(非$1名字空间)',
 'allpagesprev' => '前',
 'allpagesnext' => '后',
 'allpagessubmit' => '提交',
-'allpagesprefix' => '显示具有此前缀(名字空间)的页面:',
+'allpagesprefix' => '显示有该前缀的页面:',
 'allpagesbadtitle' => '给定的页面标题是非法的,或者具有一个内部语言或内部 wiki 的前缀。它可能包含一个或更多的不能用于标题的字符。',
 'allpages-bad-ns' => '在{{SITENAME}}中没有一个叫做"$1"的名字空间。',
-'allpages-hide-redirects' => '隐藏重定向',
+'allpages-hide-redirects' => '隐藏重定向',
 
 # SpecialCachedPage
 'cachedspecial-viewing-cached-ttl' => '你正在查看本页面至少$1前的缓存版本。',
@@ -2249,10 +2263,8 @@ $1',
 
 # Special:Categories
 'categories' => '分类',
-'categoriespagetext' => '以下的{{PLURAL:$1|分类}}中包含了页面或媒体。
-[[Special:UnusedCategories|未用分类]]不会在这里列示。
-请同时参阅[[Special:WantedCategories|需要的分类]]。',
-'categoriesfrom' => '显示由此项起之分类:',
+'categoriespagetext' => '以下{{PLURAL:$1|分类包含}}页面或媒体文件。[[Special:UnusedCategories|未使用分类]]不显示在这里。另请见[[Special:WantedCategories|需要的分类]]。',
+'categoriesfrom' => '显示分类开始于:',
 'special-categories-sort-count' => '按数量排列',
 'special-categories-sort-abc' => '按字母排列',
 
@@ -2288,8 +2300,7 @@ $1',
 
 # Special:ListGroupRights
 'listgrouprights' => '用户组权限',
-'listgrouprights-summary' => '以下面是一个在这个维基中所定义出来的用户权限列表,以及它们的访问权。
-更多有关个别权限的细节可以在[[{{MediaWiki:Listgrouprights-helppage}}|这里]]找到。',
+'listgrouprights-summary' => '以下是在本wiki定义的用户组及它们的相关访问权限的列表。可能有关于单个权限的[[{{MediaWiki:Listgrouprights-helppage}}|附加信息]]。',
 'listgrouprights-key' => '说明:
 * <span class="listgrouprights-granted">被授予的权限</span>
 * <span class="listgrouprights-revoked">被取消的权限</span>',
@@ -2403,7 +2414,7 @@ $PAGEINTRO$NEWPAGE
 电子邮件:$PAGEEDITOR_EMAIL
 用户页面:$PAGEEDITOR_WIKI
 
-在你访问该页面之前,我们不会发送新增更改的通知。
+在你登录并访问该页面之前,我们不会发送新增更改的通知。
 你也可以重设你的监视列表中所有监视页面的通知标志。
 
 {{SITENAME}}通知系统
@@ -2437,16 +2448,16 @@ $UNWATCHURL
 'dellogpage' => '删除日志',
 'dellogpagetext' => '下面是最近的删除的列表。',
 'deletionlog' => '删除记录',
-'reverted' => '恢复到早期版本',
+'reverted' => '恢复到较早的版本',
 'deletecomment' => '原因:',
 'deleteotherreason' => '其他/附加原因:',
 'deletereasonotherlist' => '其他原因',
 'deletereason-dropdown' => '*常见删除原因
-** 广告
-** 破坏行为
-** 侵犯著作权
-** 作者申请
-** 损坏的重定向',
+**广告
+**破坏行为
+**侵犯著作权
+**作者申请
+**受损重定向',
 'delete-edit-reasonlist' => '编辑删除原因',
 'delete-toobig' => '这个页面有一个十分大量的编辑历史,超过$1次修订。删除此类页面的动作已经被限制,以防止在{{SITENAME}}上的意外扰乱。',
 'delete-warning-toobig' => '这个页面有一个十分大量的编辑历史,超过$1次修订。删除它可能会扰乱{{SITENAME}}的数据库操作;在继续此动作前请小心。',
@@ -2458,14 +2469,14 @@ $UNWATCHURL
 'rollbacklinkcount' => '回退$1次编辑',
 'rollbacklinkcount-morethan' => '回退超过$1次的编辑',
 'rollbackfailed' => '回退失败',
-'cantrollback' => '无法恢复编辑。最后的贡献者是本文的唯一作者。',
+'cantrollback' => '无法恢复编辑,最后贡献者是该页面的唯一作者。',
 'alreadyrolled' => '无法回退[[User:$2|$2]]([[User talk:$2|讨论]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])对[[:$1]]的编辑,其他人已经编辑或者回退了该页。
 
 本页最后的编辑者是[[User:$3|$3]]([[User talk:$3|讨论]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]])。',
 'editcomment' => '编辑摘要:"<i>$1</i>"。',
-'revertpage' => '已恢复[[Special:Contributions/$2|$2]]([[User talk:$2|讨论]])的编辑至[[User:$1|$1]]的最后一个修订版本',
+'revertpage' => '恢复[[Special:Contributions/$2|$2]]([[User talk:$2|讨论]])的编辑至[[User:$1|$1]]的最后版本',
 'revertpage-nouser' => '恢复由隐藏用户的编辑到{{GENDER:$1|[[User:$1|$1]]}}的最后一个修订版本',
-'rollback-success' => '已恢复$1的编辑,更改回$2的最后修订版本。',
+'rollback-success' => '已恢复$1的编辑,更改回$2的最后版本。',
 
 # Edit tokens
 'sessionfailure-title' => '会话无效',
@@ -2523,8 +2534,8 @@ $UNWATCHURL
 'protect-expiry-options' => '1小时:1 hour,1天:1 day,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,无限期:infinite',
 'restriction-type' => '权限:',
 'restriction-level' => '限制级别:',
-'minimum-size' => 'æ\9c\80å°\8f大å°\8f',
-'maximum-size' => 'æ\9c\80大大å°\8f:',
+'minimum-size' => 'æ\9c\80å°\8f尺寸',
+'maximum-size' => 'æ\9c\80大尺寸:',
 'pagesize' => '(字节)',
 
 # Restrictions (nouns)
@@ -2554,15 +2565,15 @@ $UNWATCHURL
 'undelete-revision' => '$1由$3(在$4 $5)所编写的已删除修订版本:',
 'undeleterevision-missing' => '无效或丢失的修订版本。您可能使用了错误的链接,或者此修订版本已经被从存档中恢复或移除。',
 'undelete-nodiff' => '找不到先前的修订版本。',
-'undeletebtn' => '恢复',
-'undeletelink' => '查看/恢复',
+'undeletebtn' => '还原',
+'undeletelink' => '查看/还原',
 'undeleteviewlink' => '查看',
 'undeletereset' => '重设',
 'undeleteinvert' => '反向选择',
 'undeletecomment' => '原因:',
-'undeletedrevisions' => '$1个版本已恢复',
-'undeletedrevisions-files' => '$1个版本和$2个文件已恢复',
-'undeletedfiles' => '$1个文件已经被恢复',
+'undeletedrevisions' => '{{PLURAL:$1|$1个版本}}被还原',
+'undeletedrevisions-files' => '{{PLURAL:$1|$1个版本}}和{{PLURAL:$2|$2个文件}}被还原',
+'undeletedfiles' => '{{PLURAL:$1|$1个文件}}被还原',
 'cannotundelete' => '恢复删除失败:
 $1',
 'undeletedpage' => "'''$1已经被恢复'''
@@ -2901,7 +2912,7 @@ $1被封禁的理由是:“$2”',
 'allmessagesdefault' => '默认信息文字',
 'allmessagescurrent' => '当前信息文字',
 'allmessagestext' => '此处列出了MediaWiki名字空间下的所有有效系统消息。
-如果想为MediaWiki的本地化贡献翻译,请访问[//www.mediawiki.org/wiki/Localisation MediaWiki本地化]和[//translatewiki.net translatewiki.net]。',
+如果想为MediaWiki的本地化贡献翻译,请访问[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]和[//translatewiki.net translatewiki.net]。',
 'allmessagesnotsupportedDB' => "此页面无法使用,因为'''\$wgUseDatabaseMessages'''已被设置关闭。",
 'allmessages-filter-legend' => '过滤',
 'allmessages-filter' => '按自定义状态过滤:',
@@ -3007,14 +3018,15 @@ $2',
 'tooltip-ca-talk' => '关于内容页面的讨论',
 'tooltip-ca-edit' => '你可以编辑本页面。请在保存前使用预览按钮',
 'tooltip-ca-addsection' => '开始新段落',
-'tooltip-ca-viewsource' => '本页面受到保护。你可以查看其源代码。',
+'tooltip-ca-viewsource' => '本页面受到保护。
+您可以查看其源代码',
 'tooltip-ca-history' => '本页面过去的版本',
 'tooltip-ca-protect' => '保护本页',
 'tooltip-ca-unprotect' => '更改本页面的保护',
 'tooltip-ca-delete' => '删除本页',
 'tooltip-ca-undelete' => '将这个页面恢复到被删除以前的状态',
 'tooltip-ca-move' => '移动本页',
-'tooltip-ca-watch' => '添加本页面至的监视列表',
+'tooltip-ca-watch' => '添加本页面至的监视列表',
 'tooltip-ca-unwatch' => '从你的监视列表删除本页面',
 'tooltip-search' => '搜索{{SITENAME}}',
 'tooltip-search-go' => '如果相同的标题存在的话便直接前往该页面',
@@ -3051,41 +3063,41 @@ $2',
 'tooltip-save' => '保存你的更改',
 'tooltip-preview' => '预览您的更改,请在保存前使用此功能!',
 'tooltip-diff' => '显示您对该文字所做的更改',
-'tooltip-compareselectedversions' => '查看此页面两个选定的修订版本间的差异。',
+'tooltip-compareselectedversions' => '查看该页面两个选定的版本之间的差异。',
 'tooltip-watch' => '添加本页面至你的监视列表',
 'tooltip-watchlistedit-normal-submit' => '删除标题',
 'tooltip-watchlistedit-raw-submit' => '更新监视列表',
 'tooltip-recreate' => '重建该页面,无论是否被删除。',
 'tooltip-upload' => '开始上传',
-'tooltip-rollback' => '单击“回退”恢复上一位贡献者对本页的编辑',
+'tooltip-rollback' => '单击“回退”恢复最后贡献者对该页面的编辑',
 'tooltip-undo' => '“撤销”可以恢复该编辑并在预览模式下打开编辑表单。它允许在摘要中加入原因。',
 'tooltip-preferences-save' => '保存系统设置',
 'tooltip-summary' => '请输入简短的摘要',
-'tooltip-iwiki' => '$1——$2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
-'common.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86åº\94ç\94¨äº\8eæ\89\80æ\9c\89ç\9a\84皮肤 */',
-'cologneblue.css' => '/* æ­¤å¤\84ç\9a\84 CSS 将影响使用科隆香水蓝皮肤的用户 */',
-'monobook.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å½±å\93\8d使ç\94¨ Monobook 皮肤的用户 */',
-'modern.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å½±å\93\8d使ç\94¨ Modern 皮肤的用户 */',
-'vector.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å½±å\93\8d使ç\94¨ Vector 皮肤的用户 */',
-'print.css' => '/* æ­¤å¤\84ç\9a\84 CSS 将影响打印输出 */',
-'noscript.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å½±å\93\8d没æ\9c\89å\90¯ç\94¨ JavaScript 的用户 */',
-'group-autoconfirmed.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å\8fªä¼\9a影响自动确认用户 */',
-'group-bot.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å\8fªä¼\9a影响机器人 */',
-'group-sysop.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å\8fªä¼\9a影响管理员 */',
-'group-bureaucrat.css' => '/* æ­¤å¤\84ç\9a\84 CSS å°\86å\8fªä¼\9aå½±å\93\8d行政员 */',
+'common.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86åº\94ç\94¨äº\8eæ\89\80æ\9c\89皮肤 */',
+'cologneblue.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSS将影响使用科隆香水蓝皮肤的用户 */',
+'monobook.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å½±å\93\8d使ç\94¨MonoBook皮肤的用户 */',
+'modern.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å½±å\93\8d使ç\94¨ç\8e°ä»£皮肤的用户 */',
+'vector.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å½±å\93\8d使ç\94¨Vector皮肤的用户 */',
+'print.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSS将影响打印输出 */',
+'noscript.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å½±å\93\8då\81\9cç\94¨JavaScript的用户 */',
+'group-autoconfirmed.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å\8fª影响自动确认用户 */',
+'group-bot.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å\8fª影响机器人 */',
+'group-sysop.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å\8fª影响管理员 */',
+'group-bureaucrat.css' => '/* æ\94¾ç½®äº\8eè¿\99é\87\8cç\9a\84CSSå°\86å\8fªå½±å\93\8dæ\9cº行政员 */',
 
 # Scripts
-'common.js' => '/* 此处的JavaScript将加载于所有用户每一个页面。 */',
-'cologneblue.js' => '/* 此处的JavaScript将加载于使用科隆香水蓝皮肤的用户 */',
-'monobook.js' => '/* 此处的JavaScript将加载于使用Monobook皮肤的用户 */',
-'modern.js' => '/* 此处的JavaScript将加载于使用Modern皮肤的用户 */',
-'vector.js' => '/* 此处的JavaScript将加载于使用Vector皮肤的用户 */',
-'group-autoconfirmed.js' => '/* 此处的JavaScript将仅加载于自动确认用户 */',
-'group-bot.js' => '/* 此处的JavaScript将仅加载于机器人 */',
-'group-sysop.js' => '/* 此处的JavaScript将仅加载于管理员 */',
-'group-bureaucrat.js' => '/* 此处的JavaScript将仅加载于行政员 */',
+'common.js' => '/* 这里的任何JavaScript将为所有用户在每一页面载入加载。 */',
+'cologneblue.js' => '/* 这里的任何JavaScript将为使用科隆香水蓝皮肤的用户加载 */',
+'monobook.js' => '/* 这里的任何JavaScript将为使用MonoBook皮肤的用户加载 */',
+'modern.js' => '/* 这里的任何JavaScript将为使用现代皮肤的用户加载 */',
+'vector.js' => '/* 这里的任何JavaScript将为使用Vector皮肤的用户加载 */',
+'group-autoconfirmed.js' => '/* 这里的任何JavaScript将只为自动确认用户加载 */',
+'group-bot.js' => '/* 这里的任何JavaScript将只为机器人加载 */',
+'group-sysop.js' => '/* 这里的任何JavaScript将只为管理员加载 */',
+'group-bureaucrat.js' => '/* 这里的任何JavaScript将只为行政员加载 */',
 
 # Metadata
 'notacceptable' => '该网站服务器不能提供您的客户端能识别的数据格式。',
@@ -3108,9 +3120,11 @@ $2',
 这可能是由于一个链往匹配黑名单的外部站点的链接引起的。',
 'spamprotectionmatch' => '以下文本触发了我们的垃圾链接过滤器:$1',
 'spambot_username' => 'MediaWiki垃圾链接清理器',
-'spam_reverting' => '恢复到不包含链接的最近修订版本$1',
+'spam_reverting' => '恢复至不包含$1的链接的最后版本',
 'spam_blanking' => '消隐所有包含链接至$1的修订',
 'spam_deleting' => '正在删除所有包含至$1的版本',
+'simpleantispam-label' => "反垃圾检查。
+'''不要'''加入这个!",
 
 # Info page
 'pageinfo-title' => '“$1”的信息',
@@ -3124,14 +3138,15 @@ $2',
 'pageinfo-length' => '页面长度(字节)',
 'pageinfo-article-id' => '页面ID',
 'pageinfo-language' => '页面内容语言',
-'pageinfo-robot-policy' => '机器人索引',
+'pageinfo-content-model' => '页面内容模式',
+'pageinfo-robot-policy' => '爬虫索引',
 'pageinfo-robot-index' => '允许',
 'pageinfo-robot-noindex' => '不允许',
 'pageinfo-views' => '查看数',
 'pageinfo-watchers' => '页面监视者数',
 'pageinfo-few-watchers' => '少于$1个监视者',
-'pageinfo-redirects-name' => '重定向到此页的数量',
-'pageinfo-subpages-name' => '本页子页面数',
+'pageinfo-redirects-name' => '至该页面的重定向数',
+'pageinfo-subpages-name' => '该页面的子页面数',
 'pageinfo-subpages-value' => '$1($2个重定向页,$3个非重定向页)',
 'pageinfo-firstuser' => '页面创建者',
 'pageinfo-firsttime' => '页面创建日期',
@@ -3197,17 +3212,17 @@ $1',
 
 # Media information
 'mediawarning' => "'''警告''':该文件类型可能含有恶意代码。执行后你的系统可能受损。",
-'imagemaxsize' => '图像大小限制:<br /><u>(文件描述页)</u>',
-'thumbsize' => '缩ç\95¥å\9b¾å¤§å°\8f:',
+'imagemaxsize' => "图像尺寸限制:<br />''(文件说明页面)''",
+'thumbsize' => '缩ç\95¥å\9b¾å°ºå¯¸:',
 'widthheightpage' => '$1×$2,$3页',
 'file-info' => '文件大小:$1,MIME类型:$2',
-'file-info-size' => '$1×$2像素,文件大小:$3,MIME类型:$4',
-'file-info-size-pages' => '$1×$2像素,文件大小:$3,MIME类型:$4,$5页',
+'file-info-size' => '$1 × $2像素,文件大小:$3,MIME类型:$4',
+'file-info-size-pages' => '$1 × $2像素,文件大小:$3,MIME类型:$4,$5页',
 'file-nohires' => '没有更高的分辨率。',
 'svg-long-desc' => 'SVG文件,尺寸为$1 × $2像素,文件大小:$3',
 'svg-long-desc-animated' => '动画SVG文件,尺寸为$1 × $2像素,文件大小:$3',
 'svg-long-error' => '无效的SVG文件:$1',
-'show-big-image' => 'å®\8cå\85¨å\88\86辨ç\8e\87',
+'show-big-image' => 'å\8e\9få§\8bæ\96\87件',
 'show-big-image-preview' => '本预览的尺寸:$1。',
 'show-big-image-other' => '其他{{PLURAL:$2|分辨率}}:$1。',
 'show-big-image-size' => '$1×$2像素',
@@ -3286,7 +3301,7 @@ Variants for Chinese language
 'variantname-kk-cyrl' => 'kk-cyrl',
 
 # Metadata
-'metadata' => 'å\8e\9få§\8b数据',
+'metadata' => 'å\85\83数据',
 'metadata-help' => '此文件中包含有扩展的信息。这些信息可能是由数码相机或扫描仪在创建或数字化过程中所添加的。
 
 如果此文件的源文件已经被修改,一些信息在修改后的文件中将不能完全反映出来。',
@@ -3700,7 +3715,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => '用外部应用程序编辑本文件',
-'edit-externally-help' => '(更多信息请见[//www.mediawiki.org/wiki/Manual:External_editors 安装说明])',
+'edit-externally-help' => '(更多信息请见[https://www.mediawiki.org/wiki/Manual:External_editors 安装说明])',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '所有',
@@ -3742,8 +3757,7 @@ $5
 确认码会在$4过期。',
 'confirmemail_body_changed' => '拥有IP地址$1的用户(可能是您)在{{SITENAME}}更改了账户“$2”的电子邮箱地址。
 
-请确认这个账户是属于您的,并同时重新激活在{{SITENAME}}上的电子邮件功能。请
-在浏览器中打开下面的链接:
+要确认此账户确实属于您并同时激活在{{SITENAME}}的电子邮件功能,请在浏览器中打开下面的链接:
 
 $3
 
@@ -3784,7 +3798,7 @@ $5
 # action=purge
 'confirm_purge_button' => '确定',
 'confirm-purge-top' => '要清除此页面的缓存吗?',
-'confirm-purge-bottom' => '清理一页将会清除快取以及强迫显示最现时之修订版本。',
+'confirm-purge-bottom' => '清除页面数据会清除缓存并强制显示最近的版本。',
 
 # action=watch/unwatch
 'confirm-watch-button' => '确定',
@@ -3797,6 +3811,7 @@ $5
 'colon-separator' => ':',
 'word-separator' => '',
 'parentheses' => '($1)',
+'quotation-marks' => '“$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← 上一页',
@@ -3883,7 +3898,7 @@ $5
 'version-hook-subscribedby' => '署名',
 'version-version' => '(版本$1)',
 'version-license' => '授权协议',
-'version-poweredby-credits' => "本Wiki由'''[//www.mediawiki.org/ MediaWiki]'''驱动,版权所有 © 2001-$1 $2。",
+'version-poweredby-credits' => "本Wiki由'''[https://www.mediawiki.org/ MediaWiki]'''驱动,版权所有 © 2001-$1 $2。",
 'version-poweredby-others' => '其他',
 'version-poweredby-translators' => 'translatewiki.net上的翻译者',
 'version-credits-summary' => '我们感谢下列人士为[[Special:Version|MediaWiki]]作出的贡献。',
@@ -3904,12 +3919,12 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 # Special:Redirect
 'redirect' => '重定向(按文件、用户或版本ID)',
 'redirect-legend' => '重定向至文件或页面',
-'redirect-summary' => '本特殊页面会重定向到一个文件(给予文件名),一个页面(给予修订版本ID),或一个用户页面(给予用户数字ID)。',
+'redirect-summary' => '本特殊页面可以跳转至一个文件(提供文件名)、页面(提供版本ID)或用户页面(提供数字用户ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/revision/328429]]或[[{{#Special:Redirect}}/user/101]]。',
 'redirect-submit' => '提交',
 'redirect-lookup' => '基于:',
 'redirect-value' => '值:',
 'redirect-user' => '用户ID',
-'redirect-revision' => '页面修订',
+'redirect-revision' => '页面版本ID',
 'redirect-file' => '文件名',
 'redirect-not-exists' => '没找到相应值',
 
@@ -3926,16 +3941,16 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 
 # Special:SpecialPages
 'specialpages' => '特殊页面',
-'specialpages-note' => '----
-*普通特殊页面。
-*<span class="mw-specialpagerestricted">非公开特殊页面。</span>',
+'specialpages-note-top' => '图例',
+'specialpages-note' => '*普通特殊页面。
+*<span class="mw-specialpagerestricted">受限特殊页面。</span>',
 'specialpages-group-maintenance' => '维护报告',
 'specialpages-group-other' => '其它特殊页面',
 'specialpages-group-login' => '登录/创建账户',
 'specialpages-group-changes' => '最近更改与日志',
 'specialpages-group-media' => '媒体文件报告与上传',
 'specialpages-group-users' => '用户与权限',
-'specialpages-group-highuse' => '高使用页面',
+'specialpages-group-highuse' => '高使用页面',
 'specialpages-group-pages' => '页面列表',
 'specialpages-group-pagetools' => '页面工具',
 'specialpages-group-wiki' => '数据与工具',
@@ -4106,7 +4121,7 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 'api-error-unclassified' => '出现未知错误。',
 'api-error-unknown-code' => '未知错误:$1',
 'api-error-unknown-error' => '内部错误:尝试上传文件时出错。',
-'api-error-unknown-warning' => '未知的警告:$1',
+'api-error-unknown-warning' => '未知的警告:“$1”。',
 'api-error-unknownerror' => '未知错误:$1。',
 'api-error-uploaddisabled' => '该wiki停用上传。',
 'api-error-verification-error' => '该文件可能损坏或扩展名错误。',
@@ -4138,6 +4153,21 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 'limitreport-templateargumentsize' => '模板参数大小',
 'limitreport-templateargumentsize-value' => '$1/$2 字节',
 'limitreport-expansiondepth' => '最高扩展深度',
-'limitreport-expensivefunctioncount' => '高级函数分析器',
+'limitreport-expensivefunctioncount' => '高开销函数分析器',
+
+# Special:ExpandTemplates
+'expandtemplates' => '展开模板',
+'expand_templates_intro' => '此特殊页面可以递归地展开所给文本中的模板。
+它同时还可展开诸如<nowiki>{{</nowiki>#language:...}}的解析器函数和诸如<nowiki>{{</nowiki>CURRENTDAY}}的变量。
+实际上,几乎所有在双重花括号中的内容都会被展开。',
+'expand_templates_title' => '上下文标题,用于{{FULLPAGENAME}}等:',
+'expand_templates_input' => '输入文本:',
+'expand_templates_output' => '结果:',
+'expand_templates_xml_output' => 'XML输出',
+'expand_templates_ok' => '确定',
+'expand_templates_remove_comments' => '移除注释',
+'expand_templates_remove_nowiki' => '在结果中隐藏<nowiki>标签',
+'expand_templates_generate_xml' => '显示XML语法树',
+'expand_templates_preview' => '预览',
 
 );
index 992db6b..c9c43cd 100644 (file)
@@ -54,6 +54,7 @@
  * @author Xiaomingyan
  * @author Yfdyh000
  * @author Yuyu
+ * @author 乌拉跨氪
  */
 
 $fallback = 'zh-hans';
@@ -117,12 +118,12 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Activeusers'               => array( '活躍用戶' ),
        'Allmessages'               => array( '所有信息' ),
+       'AllMyUploads'              => array( '所有本人上載', '所有本人文件' ),
        'Allpages'                  => array( '所有頁面' ),
        'Ancientpages'              => array( '最早頁面' ),
        'Badtitle'                  => array( '無效標題' ),
        'Blankpage'                 => array( '空白頁面' ),
        'Block'                     => array( '查封用戶' ),
-       'Blockme'                   => array( '封禁我' ),
        'Booksources'               => array( '網絡書源' ),
        'BrokenRedirects'           => array( '損壞的重定向頁' ),
        'Categories'                => array( '頁面分類' ),
@@ -134,10 +135,10 @@ $specialPageAliases = array(
        'CreateAccount'             => array( '創建賬戶' ),
        'Deadendpages'              => array( '斷鏈頁面' ),
        'DeletedContributions'      => array( '已刪除的用戶貢獻' ),
-       'Disambiguations'           => array( '消歧義頁' ),
        'DoubleRedirects'           => array( '雙重重定向頁面' ),
        'EditWatchlist'             => array( '編輯監視列表' ),
        'Emailuser'                 => array( '電郵用戶' ),
+       'ExpandTemplates'           => array( '展開模板' ),
        'Export'                    => array( '導出頁面' ),
        'Fewestrevisions'           => array( '最少修訂頁面' ),
        'FileDuplicateSearch'       => array( '搜索重複文件' ),
@@ -173,6 +174,7 @@ $specialPageAliases = array(
        'Myuploads'                 => array( '我的上傳' ),
        'Newimages'                 => array( '新建文件' ),
        'Newpages'                  => array( '新頁面' ),
+       'PagesWithProp'             => array( '帶屬性頁面' ),
        'PasswordReset'             => array( '重設密碼' ),
        'PermanentLink'             => array( '永久連結' ),
        'Popularpages'              => array( '熱點頁面' ),
@@ -185,6 +187,7 @@ $specialPageAliases = array(
        'Recentchanges'             => array( '最近更改' ),
        'Recentchangeslinked'       => array( '鏈出更改' ),
        'Redirect'                  => array( '重定向' ),
+       'ResetTokens'               => array( '覆寫令牌' ),
        'Revisiondelete'            => array( '刪除或恢復版本' ),
        'Search'                    => array( '搜索' ),
        'Shortpages'                => array( '短頁面' ),
@@ -387,12 +390,12 @@ $messages = array(
 'december-date' => '12月$1日',
 
 # Categories related messages
-'pagecategories' => '$1 個分類',
+'pagecategories' => '{{PLURAL:$1|分類}}',
 'category_header' => '「$1」分類中的頁面',
 'subcategories' => '子分類',
 'category-media-header' => '「$1」分類中的媒體',
 'category-empty' => "''此分類目前未包含頁面或媒體。''",
-'hidden-categories' => '$1 個隱藏分類',
+'hidden-categories' => '{{PLURAL:$1|隱藏分類}}',
 'hidden-category-category' => '隱藏分類',
 'category-subcat-count' => '{{PLURAL:$2|此分類有以下一個子分類。|此分類有 $2 個子分類,以下列出了 $1 個。}}',
 'category-subcat-count-limited' => '此分類有以下 $1 個子分類。',
@@ -483,7 +486,7 @@ $messages = array(
 'articlepage' => '檢視內容頁面',
 'talk' => '討論',
 'views' => '檢視',
-'toolbox' => '工具',
+'toolbox' => '工具',
 'userpage' => '檢視用戶頁面',
 'projectpage' => '檢視計劃頁面',
 'imagepage' => '檢視檔案頁面',
@@ -538,12 +541,10 @@ $1',
 'ok' => '確定',
 'retrievedfrom' => '取自「$1」',
 'youhavenewmessages' => '您有$1($2)。',
-'newmessageslink' => '新訊息',
-'newmessagesdifflink' => '最新變更',
 'youhavenewmessagesfromusers' => '你有來自{{PLURAL:$3|另一位使用者|$3 位使用者}}的$1($2)。',
 'youhavenewmessagesmanyusers' => '你有來自多位使用者的$1( $2 )。',
-'newmessageslinkplural' => '{{PLURAL:$1|一項新訊息|新訊息}}',
-'newmessagesdifflinkplural' => 'æ\9c\80æ\96°{{PLURAL:$1|變更}}',
+'newmessageslinkplural' => '{{PLURAL:$1|一個新訊息|999=新訊息}}',
+'newmessagesdifflinkplural' => 'æ\96°è¿\91{{PLURAL:$1|變更}}',
 'youhavenewmessagesmulti' => '您在 $1 有新訊息',
 'editsection' => '編輯',
 'editold' => '編輯',
@@ -674,7 +675,8 @@ $2',
 'invalidtitle-knownnamespace' => '使用名字空間「$2」和文本「$3」的無效標題',
 'invalidtitle-unknownnamespace' => '使用未知名字空間編號$1和文本“$2”的無效標題',
 'exception-nologin' => '未登入',
-'exception-nologin-text' => '你需要登錄此wiki查閲此頁或進行操作。',
+'exception-nologin-text' => '你需要[[Special:Userlogin|登錄]]此wiki查閲此頁或進行操作。',
+'exception-nologin-text-manual' => '請$1以便能夠訪問此頁或行動。',
 
 # Virus scanner
 'virus-badscanner' => "損壞設定: 未知的病毒掃瞄器: ''$1''",
@@ -721,7 +723,7 @@ $2',
 'gotaccount' => '已經擁有帳號?$1。',
 'gotaccountlink' => '登入',
 'userlogin-resetlink' => '忘記了您的登入細節?',
-'userlogin-resetpassword-link' => '重設密碼',
+'userlogin-resetpassword-link' => '忘記您的密碼?',
 'helplogin-url' => 'Help:登入',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|登入幫助]]',
 'userlogin-loggedin' => '您已作為{{GENDER:$1|$1}}登錄。
@@ -769,7 +771,7 @@ $2',
 'passwordtooshort' => '您的密碼不能少於$1個字元。',
 'password-name-match' => '您的密碼必須跟您的用戶名不相同。',
 'password-login-forbidden' => '這個用戶名稱及密碼的使用是被禁止的。',
-'mailmypassword' => '將新密碼寄給我',
+'mailmypassword' => '重設密碼',
 'passwordremindertitle' => '{{SITENAME}}的新臨時密碼',
 'passwordremindertext' => '有人(可能是您,來自IP位址$1)已請求{{SITENAME}}的新密碼 ($4)。
 用戶"$2"的一個新臨時密碼現在已被設定好為"$3"。
@@ -783,14 +785,16 @@ $2',
 'passwordsent' => '用戶「$1」的新密碼已經寄往所登記的電子郵件地址。
 請在收到後再登入。',
 'blocked-mailpassword' => '您的IP地址處於查封狀態而不允許編輯,為了安全起見,密碼恢復功能已被禁用。',
-'eauthentsent' => '一封確認信已經發送到所示的地址。在發送其它郵件到此賬戶前,您必須首先依照這封信中的指導確認這個電子郵件信箱真實有效。',
+'eauthentsent' => '一封確認信已遞送至您設定的電郵位址。
+在發送其它郵件到此賬戶前,您必須首先依照這封信中的指導確認這個電子郵件信箱真實有效。',
 'throttled-mailpassword' => '密碼提醒已經在前$1小時內發送。
 為防止濫用,限定在$1小時內僅發送一次密碼提醒。',
 'mailerror' => '發送郵件錯誤: $1',
 'acct_creation_throttle_hit' => '在這個wiki上的訪客利用您的IP地址在昨天創建了$1個賬戶,是在這段時間中的上限。
 結果利用這個IP地址的訪客在這段時間中不能創建更多的賬戶。',
-'emailauthenticated' => '您的電子郵件位址已於 $2 $3 確認有效。',
-'emailnotauthenticated' => '您的郵箱位址<strong>還沒被認証</strong>。以下功能將不會發送任何郵件。',
+'emailauthenticated' => '您的電子郵件位址已於$2在$3確認。',
+'emailnotauthenticated' => '您的電郵位址尚未確認。
+將不會發送與以下功能相關的電郵。',
 'noemailprefs' => '在您的參數設置中指定一個電子郵件地址以使用此功能。',
 'emailconfirmlink' => '確認您的電子郵件位址',
 'invalidemailaddress' => '郵箱地址格式不正確,請輸入正確的郵箱位址或清空該輸入框。',
@@ -838,7 +842,7 @@ $2',
 # Special:PasswordReset
 'passwordreset' => '重新設定密碼',
 'passwordreset-text-one' => '完成此表格以重新設定您的密碼。',
-'passwordreset-text-many' => '{{PLURAL:$1|輸入其中一項以重新設定您的密碼。}}',
+'passwordreset-text-many' => '{{PLURAL:$1|鍵入一個電郵位址以便遞送新密碼。}}',
 'passwordreset-legend' => '重設密碼',
 'passwordreset-disabled' => '此圍記(Wiki)已禁用重設密碼。',
 'passwordreset-emaildisabled' => '此圍記(Wiki)已禁用電子郵件功能。',
@@ -1199,19 +1203,20 @@ $2
 'revdelete-text' => "'''刪除的修訂仍將顯示在頁面歷史中, 但它們的文字內容已不能被公眾訪問。'''
 在{{SITENAME}}的其他管理員將仍能訪問隱藏的內容並透過與此相同的介面恢復刪除,除非網站工作者進行了一些附加的限制。",
 'revdelete-confirm' => '請確認您肯定去做的話,您就要明白到後果,以及這個程序符合[[{{MediaWiki:Policy-url}}|政策]]。',
-'revdelete-suppress-text' => "壓制'''只'''應在以下的情況下進行:
-* 不合適的個人資料
+'revdelete-suppress-text' => "禁制應'''僅'''於下述情形之一時使用:
+* 潛在誹謗性資訊
+* 不合適個人資料
 *: ''住家地址、電話號碼、社群保安號碼等。''",
 'revdelete-legend' => '設定可見性之限制',
-'revdelete-hide-text' => '隱藏修訂文字',
+'revdelete-hide-text' => '修訂文字',
 'revdelete-hide-image' => '隱藏檔案內容',
 'revdelete-hide-name' => '隱藏動作和目標',
-'revdelete-hide-comment' => '隱藏編輯摘要',
-'revdelete-hide-user' => '隱藏編輯者的用戶名/IP地址',
+'revdelete-hide-comment' => '編輯摘要',
+'revdelete-hide-user' => '編輯者的用戶名/IP位址',
 'revdelete-hide-restricted' => '同時廢止由操作員以及其他用戶的資料',
-'revdelete-radio-same' => '(不更改)',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'å\90¦',
+'revdelete-radio-same' => '(不更改)',
+'revdelete-radio-set' => '隱藏',
+'revdelete-radio-unset' => 'å\8f¯è¦\8b',
 'revdelete-suppress' => '同時廢止由操作員以及其他用戶的資料',
 'revdelete-unsuppress' => '在已恢復的修訂中移除限制',
 'revdelete-log' => '理由:',
@@ -1360,13 +1365,12 @@ $1",
 'preferences' => '偏好設定',
 'mypreferences' => '偏好設定',
 'prefs-edits' => '編輯次數:',
-'prefsnologin' => '還未登入',
-'prefsnologintext' => '您必須先<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} 登入]</span>才能設置個人參數。',
+'prefsnologintext2' => '請$1以進入用戶設定。',
 'changepassword' => '變更密碼',
 'prefs-skin' => '外觀',
 'skin-preview' => '預覽',
 'datedefault' => '預設值',
-'prefs-beta' => 'Beta 功能',
+'prefs-beta' => '測試功能',
 'prefs-datetime' => '日期和時間',
 'prefs-labs' => '實驗中的功能',
 'prefs-user-pages' => '使用者頁面',
@@ -1453,7 +1457,7 @@ $1",
 'email' => '電子郵件',
 'prefs-help-realname' => '真實姓名是可選的。
 如果您選擇提供它,它會用於貢獻署名。',
-'prefs-help-email' => 'é\9b»å­\90é\83µä»¶æ\98¯å\8f¯é\81¸ç\9a\84ï¼\8cä½\86ç\95¶æ\82¨å¿\98è¨\98æ\82¨ç\9a\84å¯\86碼æ\99\82é\9c\80è¦\81å°\87æ\96°å¯\86碼é\87\8d設ï¼\8cå°±æ\9c\83ç\94¨é\9b»é\83µå¯\84å\9b\9e給æ\82¨ã\80\82',
+'prefs-help-email' => 'ç\94µå­\90é\82®ä»¶æ\98¯å\8f¯é\80\89项ï¼\8cä½\86æ\98¯å\9c¨æ\82¨å¿\98è®°å¯\86ç \81æ\97¶å¾\88æ\9c\89ç\94¨ã\80\82',
 'prefs-help-email-others' => '您亦可以在您沒有公開自己的用戶身分時透過您的用戶頁或用戶討論頁與您聯繫。',
 'prefs-help-email-required' => '電子郵件地址是必填項目。',
 'prefs-info' => '基本資料',
@@ -1659,6 +1663,9 @@ $1",
 'recentchanges-label-minor' => '這是一個小編輯',
 'recentchanges-label-bot' => '這次編輯是由機器人進行',
 'recentchanges-label-unpatrolled' => '這次編輯尚未巡查過',
+'recentchanges-label-plusminus' => '通過此處位元組的數位以更改頁面大小',
+'recentchanges-legend-newpage' => '(另見[[Special:NewPages|新頁面列表]])',
+'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnote' => "以下是在$4 $5,最近 '''$2''' 天內的 '''$1''' 次最近更改記錄。",
 'rcnotefrom' => "下面是自'''$2'''(最多顯示'''$1'''):",
 'rclistfrom' => '顯示自 $1 以來的新變更',
@@ -2196,7 +2203,7 @@ $1',
 'allpagesprev' => '前',
 'allpagesnext' => '後',
 'allpagessubmit' => '提交',
-'allpagesprefix' => '顯示具有此前綴(名字空間)的頁面:',
+'allpagesprefix' => '顯示有此前綴的頁面:',
 'allpagesbadtitle' => '給定的頁面標題是非法的,或者具有一個內部語言或內部 wiki 的前綴。它可能包含一個或更多的不能用於標題的字元。',
 'allpages-bad-ns' => '在{{SITENAME}}中沒有一個叫做「$1」的名字空間。',
 'allpages-hide-redirects' => '隱藏重定向頁',
@@ -2353,13 +2360,13 @@ $1',
 'enotif_lastvisited' => '請參閱 $1 檢視你上次訪問後的所有更改。',
 'enotif_lastdiff' => '請參閱 $1 檢視該更改。',
 'enotif_anon_editor' => '匿名用戶$1',
-'enotif_body' => '$WATCHINGUSERNAME
+'enotif_body' => '$WATCHINGUSERNAME閣下,
 
 $PAGEINTRO $NEWPAGE
 
 編輯摘要:$PAGESUMMARY $PAGEMINOREDIT
 
\81¯ç¹«此編輯者:
\81¯çµ¡此編輯者:
 
 郵件:$PAGEEDITOR_EMAIL
 本站:$PAGEEDITOR_WIKI
@@ -2877,7 +2884,7 @@ $1被封禁的理由是“$2”',
 'allmessagesdefault' => '預設的訊息文字',
 'allmessagescurrent' => '現時的訊息文字',
 'allmessagestext' => '這裡列出所有可定製的系統界面。
-如果想貢獻正宗的MediaWiki本地化的話,請參閱[//www.mediawiki.org/wiki/Localisation MediaWiki本地化]以及[//translatewiki.net translatewiki.net]。',
+如果想貢獻正宗的MediaWiki本地化的話,請參閱[https://www.mediawiki.org/wiki/Localisation MediaWiki本地化]以及[//translatewiki.net translatewiki.net]。',
 'allmessagesnotsupportedDB' => "這個頁面無法使用,因為'''\$wgUseDatabaseMessages'''已被設定關閉。",
 'allmessages-filter-legend' => '搜尋',
 'allmessages-filter' => '以自定狀況過濾:',
@@ -3039,6 +3046,7 @@ $2',
 'tooltip-undo' => '「復原」可以在編輯模式上開啟編輯表格以便恢復。它容許在摘要中加入原因。',
 'tooltip-preferences-save' => '儲存使用偏好',
 'tooltip-summary' => '輸入一個簡短的摘要',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* 此處的 CSS 將應用於所有的面板 */',
@@ -3084,6 +3092,8 @@ $2',
 'spam_reverting' => '恢復到不包含連結至$1的最近修訂版本',
 'spam_blanking' => '所有包含連結至$1的修訂,清空',
 'spam_deleting' => '所有包含連結至$1的修訂,刪除中',
+'simpleantispam-label' => "反濫發電郵檢查。
+'''不要'''加入這個!",
 
 # Info page
 'pageinfo-title' => '「$1」的信息',
@@ -3097,6 +3107,7 @@ $2',
 'pageinfo-length' => '頁面長度 (以位元組為單位)',
 'pageinfo-article-id' => '頁面編號',
 'pageinfo-language' => '頁面內容語言',
+'pageinfo-content-model' => '頁面內容模型',
 'pageinfo-robot-policy' => '機械人索引',
 'pageinfo-robot-index' => '容許',
 'pageinfo-robot-noindex' => '阻止',
@@ -3181,7 +3192,7 @@ $1',
 'svg-long-desc' => 'SVG 檔案,表面大小:$1 × $2 像素,檔案大小:$3',
 'svg-long-desc-animated' => 'SVG 動畫檔案,表面大小:$1 × $2 像素,檔案大小:$3',
 'svg-long-error' => '無效的SVG檔案:$1',
-'show-big-image' => 'å®\8cæ\95´è§£å\83\8f度',
+'show-big-image' => 'å\8e\9få§\8bæª\94æ¡\88',
 'show-big-image-preview' => '此預覽的大小:$1.',
 'show-big-image-other' => '其他{{PLURAL:$2||}}解析度:$1。',
 'show-big-image-size' => '$1 × $2 像素',
@@ -3669,7 +3680,7 @@ Variants for Chinese language
 
 # External editor support
 'edit-externally' => '用外部程式編輯此檔案',
-'edit-externally-help' => '(請參見[//www.mediawiki.org/wiki/Manual:External_editors 設定步驟]了解詳細資訊)',
+'edit-externally-help' => '(請參見[https://www.mediawiki.org/wiki/Manual:External_editors 設定步驟]了解詳細資訊)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => '全部',
@@ -3767,6 +3778,7 @@ $5
 'colon-separator' => ':',
 'word-separator' => '',
 'parentheses' => '($1)',
+'quotation-marks' => '“$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← 上一頁',
@@ -3853,7 +3865,7 @@ $5
 'version-hook-subscribedby' => '利用於',
 'version-version' => '(版本 $1)',
 'version-license' => '授權',
-'version-poweredby-credits' => "此維基由'''[//www.mediawiki.org/ MediaWiki]'''驅動,版權所有 © 2001-$1 $2。",
+'version-poweredby-credits' => "此維基由'''[https://www.mediawiki.org/ MediaWiki]'''驅動,版權所有 © 2001-$1 $2。",
 'version-poweredby-others' => '其他',
 'version-poweredby-translators' => 'translatewiki.net 上的翻譯者',
 'version-credits-summary' => '我們感謝以下人士為[[Special:Version|MediaWiki]]作出的貢獻。',
@@ -3873,7 +3885,7 @@ MediaWiki是基於使用目的而加以發佈,然而不負任何擔保責任
 # Special:Redirect
 'redirect' => '重定向檔案、用戶ID或頁面修訂ID',
 'redirect-legend' => '重定向到檔案或頁面',
-'redirect-summary' => '此特殊頁面重定向到檔案(指定的檔案名稱)、頁面 (指定的頁面修訂ID) 或用戶頁面(指定的用戶ID數值)。',
+'redirect-summary' => '此特殊頁面重定向到檔案(指定的檔案名稱)、頁面 (指定的頁面修訂ID) 或用戶頁面(指定的用戶ID數值)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/revision/328429]]或[[{{#Special:Redirect}}/user/101]]。',
 'redirect-submit' => '提交',
 'redirect-lookup' => '尋找:',
 'redirect-value' => '值:',
@@ -3895,10 +3907,9 @@ MediaWiki是基於使用目的而加以發佈,然而不負任何擔保責任
 
 # Special:SpecialPages
 'specialpages' => '特殊頁面',
-'specialpages-note' => '----
-* 標準特殊頁面。
-* <strong class="mw-specialpagerestricted">有限制的特殊頁面。</strong>
-* <span class="mw-specialpagecached">用於重新整理的特殊頁面(可能過時)。</span>',
+'specialpages-note-top' => '圖例',
+'specialpages-note' => '* 標準特殊頁面。
+* <span class="mw-specialpagerestricted">用於重新整理的特殊頁面(可能過時)。</span>',
 'specialpages-group-maintenance' => '維護報告',
 'specialpages-group-other' => '其它特殊頁面',
 'specialpages-group-login' => '登入/建立新帳號',
@@ -4110,4 +4121,17 @@ MediaWiki是基於使用目的而加以發佈,然而不負任何擔保責任
 'limitreport-expansiondepth' => '最高展開深度',
 'limitreport-expensivefunctioncount' => '昂貴分析器函數計數',
 
+# Special:ExpandTemplates
+'expandtemplates' => '展開模板',
+'expand_templates_intro' => '本特殊頁面用於將一些文字中的模版展開,包括模版中引用的模版。同時也展開解譯器函數如<nowiki>{{</nowiki>#language:...}},以及變數如<nowiki>{{</nowiki>CURRENTDAY}}&mdash;實際上,幾乎所有在雙括弧中的內容都被展開。',
+'expand_templates_title' => '上下文標題,用於 {{FULLPAGENAME}} 等:',
+'expand_templates_input' => '輸入文字:',
+'expand_templates_output' => '結果:',
+'expand_templates_xml_output' => 'XML輸出',
+'expand_templates_ok' => '確定',
+'expand_templates_remove_comments' => '移除注釋',
+'expand_templates_remove_nowiki' => '在結果中隱藏<nowiki>標記',
+'expand_templates_generate_xml' => '顯示XML語法樹',
+'expand_templates_preview' => '預覽',
+
 );
index 2d9b818..d28642e 100644 (file)
@@ -42,8 +42,6 @@ $namespaceAliases = array(
 $specialPageAliases = array(
        'Ancientpages'              => array( '最舊頁面' ),
        'Block'                     => array( '查封用戶' ),
-       'Blockme'                   => array( '封禁我' ),
-       'Disambiguations'           => array( '消歧義頁' ),
        'FileDuplicateSearch'       => array( '搜索重復文件' ),
        'Invalidateemail'           => array( '無法識別的電郵地址' ),
        'LinkSearch'                => array( '搜索網頁鏈接' ),
index d3a863b..c2aede0 100644 (file)
@@ -29,7 +29,6 @@
  * @file
  * @since 1.20
  */
-
 class CLDRPluralRuleEvaluator {
        /**
         * Evaluate a number against a set of plural rules. If a rule passes,
@@ -48,8 +47,8 @@ class CLDRPluralRuleEvaluator {
         * Convert a set of rules to a compiled form which is optimised for
         * fast evaluation. The result will be an array of strings, and may be cached.
         *
-        * @param $rules The rules to compile
-        * @return An array of compile rules.
+        * @param array $rules The rules to compile
+        * @return array An array of compile rules.
         */
        public static function compile( array $rules ) {
                // We can't use array_map() for this because it generates a warning if
@@ -63,6 +62,10 @@ class CLDRPluralRuleEvaluator {
        /**
         * Evaluate a compiled set of rules returned by compile(). Do not allow
         * the user to edit the compiled form, or else PHP errors may result.
+        *
+        * @param int The number to be evaluated against the rules
+        * @param array The associative array of plural rules in pluralform => rule format.
+        * @return int The index of the plural form which passed the evaluation
         */
        public static function evaluateCompiled( $number, array $rules ) {
                // The compiled form is RPN, with tokens strictly delimited by
@@ -96,11 +99,11 @@ class CLDRPluralRuleEvaluator {
        /**
         * Do a single operation
         *
-        * @param $token string The token string
-        * @param $left The left operand. If it is an object, its state may be destroyed.
-        * @param $right The right operand
+        * @param string $token The token string
+        * @param mixed $left The left operand. If it is an object, its state may be destroyed.
+        * @param mixed $right The right operand
         * @throws CLDRPluralRuleError
-        * @return mixed
+        * @return mixed The operation result
         */
        private static function doOperation( $token, $left, $right ) {
                if ( in_array( $token, array( 'in', 'not-in', 'within', 'not-within' ) ) ) {
@@ -150,8 +153,19 @@ class CLDRPluralRuleEvaluator {
  * Evaluator helper class representing a range list.
  */
 class CLDRPluralRuleEvaluator_Range {
+       /**
+        * The parts
+        *
+        * @var array
+        */
        public $parts = array();
 
+       /**
+        * Initialize a new instance of CLDRPluralRuleEvaluator_Range
+        *
+        * @param int $start The start of the range
+        * @param int|bool $end The end of the range, or false if the range is not bounded.
+        */
        function __construct( $start, $end = false ) {
                if ( $end === false ) {
                        $this->parts[] = $start;
@@ -161,16 +175,18 @@ class CLDRPluralRuleEvaluator_Range {
        }
 
        /**
-        * Determine if the given number is inside the range. If $integerConstraint
-        * is true, the number must additionally be an integer if it is to match
-        * any interval part.
+        * Determine if the given number is inside the range.
+        *
+        * @param int $number The number to check
+        * @param bool $integerConstraint If true, also asserts the number is an integer; otherwise, number simply has to be inside the range.
+        * @return bool True if the number is inside the range; otherwise, false.
         */
        function isNumberIn( $number, $integerConstraint = true ) {
                foreach ( $this->parts as $part ) {
                        if ( is_array( $part ) ) {
                                if ( ( !$integerConstraint || floor( $number ) === (float)$number )
-                                       && $number >= $part[0] && $number <= $part[1] )
-                               {
+                                       && $number >= $part[0] && $number <= $part[1]
+                               {
                                        return true;
                                }
                        } else {
@@ -185,14 +201,18 @@ class CLDRPluralRuleEvaluator_Range {
        /**
         * Readable alias for isNumberIn( $number, false ), and the implementation
         * of the "within" operator.
+        *
+        * @param int $number The number to check
+        * @return bool True if the number is inside the range; otherwise, false.
         */
        function isNumberWithin( $number ) {
                return $this->isNumberIn( $number, false );
        }
 
        /**
-        * Add another part to this range. The supplied new part may either be a
-        * range object itself, or a single number.
+        * Add another part to this range.
+        *
+        * @param mixed The part to add, either a range object itself or a single number.
         */
        function add( $other ) {
                if ( $other instanceof self ) {
@@ -203,7 +223,10 @@ class CLDRPluralRuleEvaluator_Range {
        }
 
        /**
-        * For debugging
+        * Returns the string representation of the rule evaluator range.
+        * The purpose of this method is to help debugging.
+        *
+        * @return string The string representation of the rule evaluator range
         */
        function __toString() {
                $s = 'Range(';
@@ -227,8 +250,39 @@ class CLDRPluralRuleEvaluator_Range {
  * Helper class for converting rules to reverse polish notation (RPN).
  */
 class CLDRPluralRuleConverter {
-       public $rule, $pos, $end;
+       /**
+        * The rule
+        *
+        * @var string
+        */
+       public $rule;
+
+       /**
+        * The position
+        *
+        * @var int
+        */
+       public $pos;
+
+       /**
+        * The last position possible
+        *
+        * @var int
+        */
+       public $end;
+
+       /**
+        * The operators
+        *
+        * @var array
+        */
        public $operators = array();
+
+       /**
+        * The operands
+        *
+        * @var array
+        */
        public $operands = array();
 
        /**
@@ -268,6 +322,9 @@ class CLDRPluralRuleConverter {
 
        /**
         * Convert a rule to RPN. This is the only public entry point.
+        *
+        * @param $rule The rule to convert
+        * @return string The RPN representation of the rule
         */
        public static function convert( $rule ) {
                $parser = new self( $rule );
@@ -285,6 +342,8 @@ class CLDRPluralRuleConverter {
 
        /**
         * Do the operation.
+        *
+        * @return string The RPN representation of the rule (e.g. "5 3 mod n is")
         */
        protected function doConvert() {
                $expectOperator = true;
@@ -341,8 +400,9 @@ class CLDRPluralRuleConverter {
        }
 
        /**
-        * Fetch the next token from the input string. Return it as a
-        * CLDRPluralRuleConverter_Fragment object.
+        * Fetch the next token from the input string.
+        *
+        * @return CLDRPluralRuleConverter_Fragment The next token
         */
        protected function nextToken() {
                if ( $this->pos >= $this->end ) {
@@ -390,8 +450,8 @@ class CLDRPluralRuleConverter {
                        // Look ahead one word
                        $nextTokenPos += strspn( $this->rule, self::WHITESPACE_CLASS, $nextTokenPos );
                        if ( $nextTokenPos < $this->end
-                                       && preg_match( self::WORD_REGEX, $this->rule, $m, 0, $nextTokenPos ) )
-                       {
+                               && preg_match( self::WORD_REGEX, $this->rule, $m, 0, $nextTokenPos )
+                       {
                                $word2 = strtolower( $m[0] );
                                $nextTokenPos += strlen( $word2 );
                        }
@@ -441,6 +501,8 @@ class CLDRPluralRuleConverter {
 
        /**
         * Create a numerical expression object
+        *
+        * @return CLDRPluralRuleConverter_Expression The numerical expression
         */
        protected function newNumber( $text, $pos ) {
                return new CLDRPluralRuleConverter_Expression( $this, 'number', $text, $pos, strlen( $text ) );
@@ -448,6 +510,8 @@ class CLDRPluralRuleConverter {
 
        /**
         * Create a binary operator
+        *
+        * @return CLDRPluralRuleConverter_Operator The operator
         */
        protected function newOperator( $type, $pos, $length ) {
                return new CLDRPluralRuleConverter_Operator( $this, $type, $pos, $length );
@@ -517,6 +581,11 @@ class CLDRPluralRuleConverter_Expression extends CLDRPluralRuleConverter_Fragmen
  * messages), and the binary operator at that location.
  */
 class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment {
+       /**
+        * The name
+        *
+        * @var string
+        */
        public $name;
 
        /**
@@ -527,6 +596,8 @@ class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment
         *   r = range
         *
         * A number is a kind of range.
+        *
+        * @var array
         */
        static $opTypes = array(
                'or' => 'bbb',
@@ -544,6 +615,8 @@ class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment
 
        /**
         * Map converting from the abbrevation to the full form.
+        *
+        * @var array
         */
        static $typeSpecMap = array(
                'b' => 'boolean',
@@ -551,11 +624,26 @@ class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment
                'r' => 'range',
        );
 
+       /**
+        * Initialize a new instance of a CLDRPluralRuleConverter_Operator object
+        *
+        * @param CLDRPluralRuleConverter $parser The parser
+        * @param string $name The operator name
+        * @param int $pos The position
+        * @param int $pos The length
+        */
        function __construct( $parser, $name, $pos, $length ) {
                parent::__construct( $parser, $pos, $length );
                $this->name = $name;
        }
 
+       /**
+        * Compute the operation
+        *
+        * @param CLDRPluralRuleConverter_Expression $left The left part of the expression
+        * @param CLDRPluralRuleConverter_Expression $right The right part of the expression
+        * @return CLDRPluralRuleConverter_Expression The result of the operation
+        */
        public function operate( $left, $right ) {
                $typeSpec = self::$opTypes[$this->name];
 
index 30e93c9..fb2cd8c 100644 (file)
@@ -787,7 +787,6 @@ abstract class Maintenance {
                        $this->output( "\n" );
                }
 
-
                // Script specific parameters not defined on construction by
                // Maintenance::addDefaultParams()
                $scriptSpecificParams = array_diff_key(
@@ -1274,9 +1273,9 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
                $db = $this->getDB( DB_MASTER );
                $key = $this->getUpdateKey();
 
-               if ( !$this->hasOption( 'force' ) &&
-                       $db->selectRow( 'updatelog', '1', array( 'ul_key' => $key ), __METHOD__ ) )
-               {
+               if ( !$this->hasOption( 'force' )
+                       && $db->selectRow( 'updatelog', '1', array( 'ul_key' => $key ), __METHOD__ )
+               {
                        $this->output( "..." . $this->updateSkippedMessage() . "\n" );
                        return true;
                }
@@ -1285,9 +1284,7 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
                        return false;
                }
 
-               if (
-                       $db->insert( 'updatelog', array( 'ul_key' => $key ), __METHOD__, 'IGNORE' ) )
-               {
+               if ( $db->insert( 'updatelog', array( 'ul_key' => $key ), __METHOD__, 'IGNORE' ) ) {
                        return true;
                } else {
                        $this->output( $this->updatelogFailedMessage() . "\n" );
diff --git a/maintenance/archives/patch-rc_source.sql b/maintenance/archives/patch-rc_source.sql
new file mode 100644 (file)
index 0000000..7dedd74
--- /dev/null
@@ -0,0 +1,16 @@
+-- first step of migrating recentchanges rc_type to rc_source
+ALTER TABLE /*$wgDBprefix*/recentchanges
+  ADD rc_source varbinary(16) NOT NULL default '';
+
+-- Populate rc_source field with the data from rc_type
+-- Large wiki's might prefer the PopulateRecentChangeSource maintenance
+-- script to batch updates into groups rather than all at once.
+UPDATE /*$wgDBprefix*/recentchanges
+  SET rc_source = CASE
+    WHEN rc_type = 0 THEN 'mw.edit'
+    WHEN rc_type = 1 THEN 'mw.new'
+    WHEN rc_type = 3 THEN 'mw.log'
+    WHEN rc_type = 5 THEN 'mw.external'
+    ELSE ''
+  END
+WHERE rc_source = '';
diff --git a/maintenance/archives/patch-val_ip.sql b/maintenance/archives/patch-val_ip.sql
deleted file mode 100644 (file)
index 9214218..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
--- Column added 2005-05-24
-
-ALTER TABLE /*$wgDBprefix*/validate
-  ADD COLUMN val_ip varchar(20) NOT NULL default '';
diff --git a/maintenance/archives/patch-validate.sql b/maintenance/archives/patch-validate.sql
deleted file mode 100644 (file)
index 9701083..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
--- For article validation
-
-DROP TABLE IF EXISTS /*$wgDBprefix*/validate;
-CREATE TABLE /*$wgDBprefix*/validate (
-  `val_user` int(11) NOT NULL default '0',
-  `val_page` int(11) unsigned NOT NULL default '0',
-  `val_revision` int(11) unsigned NOT NULL default '0',
-  `val_type` int(11) unsigned NOT NULL default '0',
-  `val_value` int(11) default '0',
-  `val_comment` varchar(255) NOT NULL default '',
-  `val_ip` varchar(20) NOT NULL default '',
-  KEY `val_user` (`val_user`,`val_revision`)
-) /*$wgDBTableOptions*/;
index 3dc94c8..64078b4 100644 (file)
@@ -276,7 +276,7 @@ class BackupDumper {
                }
 
                $this->lb = wfGetLBFactory()->newMainLB();
-               $db = $this->lb->getConnection( DB_SLAVE, 'backup' );
+               $db = $this->lb->getConnection( DB_SLAVE, 'dump' );
 
                // Discourage the server from disconnecting us if it takes a long time
                // to read out the big ol' batch query.
index c515c6f..f16772c 100644 (file)
@@ -82,7 +82,6 @@ class TextPassDumper extends BackupDumper {
         */
        protected $db;
 
-
        /**
         * Drop the database connection $this->db and try to get a new one.
         *
@@ -123,16 +122,14 @@ class TextPassDumper extends BackupDumper {
                        throw new MWException( __METHOD__ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
                }
 
-
                // 2. The Connection, through the load balancer.
                try {
-                       $this->db = $this->lb->getConnection( DB_SLAVE, 'backup' );
+                       $this->db = $this->lb->getConnection( DB_SLAVE, 'dump' );
                } catch ( Exception $e ) {
                        throw new MWException( __METHOD__ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" );
                }
        }
 
-
        function initProgress( $history = WikiExporter::FULL ) {
                parent::initProgress();
                $this->timeOfCheckpoint = $this->startTime;
@@ -420,8 +417,8 @@ class TextPassDumper extends BackupDumper {
                $text = false; // The candidate for a good text. false if no proper value.
                $failures = 0; // The number of times, this invocation of getText already failed.
 
-               static $consecutiveFailedTextRetrievals = 0; // The number of times getText failed without
-                                                            // yielding a good text in between.
+               // The number of times getText failed without yielding a good text in between.
+               static $consecutiveFailedTextRetrievals = 0;
 
                $this->fetchCount++;
 
@@ -556,7 +553,6 @@ class TextPassDumper extends BackupDumper {
                return "";
        }
 
-
        /**
         * May throw a database error if, say, the server dies during query.
         * @param $id
index 1cd2016..76cea2c 100644 (file)
@@ -47,7 +47,7 @@ class bench_wfIsWindows extends Benchmarker {
        }
 
        static function is_win() {
-               return substr( php_uname(), 0, 7 ) == 'Windows' ;
+               return substr( php_uname(), 0, 7 ) == 'Windows';
        }
 
        // bench function 1
index d42f9f7..4590611 100644 (file)
@@ -52,7 +52,7 @@ do {
        $bad = false;
        $showhelp = false;
        $quit = false;
-       static $fileHandle;
+       static $fileHandle = false;
 
        $line = Maintenance::readconsole();
        if ( $line === false ) {
@@ -75,7 +75,10 @@ do {
                        }
                        $file = $args[0];
                        print "Loading cdb file $file...";
-                       $fileHandle = CdbReader::open( $file );
+                       try {
+                               $fileHandle = CdbReader::open( $file );
+                       } catch ( CdbException $e ) {}
+
                        if ( !$fileHandle ) {
                                print "not a cdb file or unable to read it\n";
                        } else {
@@ -91,7 +94,12 @@ do {
                                print "Need to specify a key, Luke\n";
                                break;
                        }
-                       $res = $fileHandle->get( $args[0] );
+                       try {
+                               $res = $fileHandle->get( $args[0] );
+                       } catch ( CdbException $e ) {
+                               print "Unable to read key from file\n";
+                               break;
+                       }
                        if ( $res === false ) {
                                print "No such key/value pair\n";
                        } elseif ( is_string( $res ) ) {
index c2ba555..24b63a8 100644 (file)
@@ -38,6 +38,7 @@ class UploadStashCleanup extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->mDescription = "Clean up abandoned files in temporary uploaded file stash";
+               $this->setBatchSize( 50 );
        }
 
        public function execute() {
@@ -81,10 +82,9 @@ class UploadStashCleanup extends Maintenance {
                                try {
                                        $stash->getFile( $key, true );
                                        $stash->removeFileNoAuth( $key );
-                               } catch ( UploadStashBadPathException $ex ) {
-                                       $this->output( "Failed removing stashed upload with key: $key\n" );
-                               } catch ( UploadStashZeroLengthFileException $ex ) {
-                                       $this->output( "Failed removing stashed upload with key: $key\n" );
+                               } catch ( UploadStashException $ex ) {
+                                       $type = get_class( $ex );
+                                       $this->output( "Failed removing stashed upload with key: $key ($type)\n" );
                                }
                                if ( $i % 100 == 0 ) {
                                        $this->output( "$i\n" );
@@ -95,20 +95,25 @@ class UploadStashCleanup extends Maintenance {
 
                // Delete all the corresponding thumbnails...
                $dir = $tempRepo->getZonePath( 'thumb' );
-               $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir ) );
+               $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir, 'adviseStat' => 1 ) );
                $this->output( "Deleting old thumbnails...\n" );
                $i = 0;
+               $batch = array(); // operation batch
                foreach ( $iterator as $file ) {
                        if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
-                               $status = $tempRepo->quickPurge( "$dir/$file" );
-                               if ( !$status->isOK() ) {
-                                       $this->error( print_r( $status->getErrorsArray(), true ) );
-                               }
-                               if ( ( ++$i % 100 ) == 0 ) {
+                               $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
+                               if ( count( $batch ) >= $this->mBatchSize ) {
+                                       $this->doOperations( $tempRepo, $batch );
+                                       $i += count( $batch );
+                                       $batch = array();
                                        $this->output( "$i\n" );
                                }
                        }
                }
+               if ( count( $batch ) ) {
+                       $this->doOperations( $tempRepo, $batch );
+                       $i += count( $batch );
+               }
                $this->output( "$i done\n" );
 
                // Apparently lots of stash files are not registered in the DB...
@@ -119,24 +124,31 @@ class UploadStashCleanup extends Maintenance {
                        $this->error( "Temp repo is not using the temp container.", 1 ); // die
                }
                $i = 0;
+               $batch = array(); // operation batch
                foreach ( $iterator as $file ) {
-                       // Absolute sanity check for stashed files and file segments
-                       if ( !preg_match( '#(^\d{14}!|\.\d+\.\w+\.\d+$)#', basename( $file ) ) ) {
-                               $this->output( "Skipped non-stash $file\n" );
-                               continue;
-                       }
                        if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
-                               $status = $tempRepo->quickPurge( "$dir/$file" );
-                               if ( !$status->isOK() ) {
-                                       $this->error( print_r( $status->getErrorsArray(), true ) );
-                               }
-                               if ( ( ++$i % 100 ) == 0 ) {
+                               $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
+                               if ( count( $batch ) >= $this->mBatchSize ) {
+                                       $this->doOperations( $tempRepo, $batch );
+                                       $i += count( $batch );
+                                       $batch = array();
                                        $this->output( "$i\n" );
                                }
                        }
                }
+               if ( count( $batch ) ) {
+                       $this->doOperations( $tempRepo, $batch );
+                       $i += count( $batch );
+               }
                $this->output( "$i done\n" );
        }
+
+       protected function doOperations( FileRepo $tempRepo, array $ops ) {
+               $status = $tempRepo->getBackend()->doQuickOperations( $ops );
+               if ( !$status->isOK() ) {
+                       $this->error( print_r( $status->getErrorsArray(), true ) );
+               }
+       }
 }
 
 $maintClass = "UploadStashCleanup";
index 21ef4ff..09b9295 100644 (file)
@@ -35,7 +35,8 @@ require_once __DIR__ . '/Maintenance.php';
  * @ingroup Maintenance
  */
 class CopyFileBackend extends Maintenance {
-       protected $statCache = array();
+       /** @var Array|null (path sha1 => stat) Pre-computed dst stat entries from listings */
+       protected $statCache = null;
 
        public function __construct() {
                parent::__construct();
@@ -98,7 +99,7 @@ class CopyFileBackend extends Maintenance {
                                if ( $dstPathsRel === null ) {
                                        $this->error( "Could not list files in $container.", 1 ); // die
                                }
-                               $this->statCache = array(); // clear
+                               $this->statCache = array();
                                foreach ( $dstPathsRel as $dstPathRel ) {
                                        $path = $dst->getRootStoragePath() . "/$backendRel/$dstPathRel";
                                        $this->statCache[sha1( $path )] = $dst->getFileStat( array( 'src' => $path ) );
@@ -238,8 +239,8 @@ class CopyFileBackend extends Maintenance {
                                $this->error( "$wikiId: Detected illegal (non-UTF8) path for $srcPath." );
                                continue;
                        } elseif ( !$this->hasOption( 'missingonly' )
-                               && $this->filesAreSame( $src, $dst, $srcPath, $dstPath ) )
-                       {
+                               && $this->filesAreSame( $src, $dst, $srcPath, $dstPath )
+                       {
                                $this->output( "\tAlready have $srcPathRel.\n" );
                                continue; // assume already copied...
                        }
@@ -338,9 +339,14 @@ class CopyFileBackend extends Maintenance {
                $skipHash = $this->hasOption( 'skiphash' );
                $srcStat = $src->getFileStat( array( 'src' => $sPath ) );
                $dPathSha1 = sha1( $dPath );
-               $dstStat = isset( $this->statCache[$dPathSha1] )
-                       ? $this->statCache[$dPathSha1]
-                       : $dst->getFileStat( array( 'src' => $dPath ) );
+               if ( $this->statCache !== null ) {
+                       // All dst files are already in stat cache
+                       $dstStat = isset( $this->statCache[$dPathSha1] )
+                               ? $this->statCache[$dPathSha1]
+                               : false;
+               } else {
+                       $dstStat = $dst->getFileStat( array( 'src' => $dPath ) );
+               }
                return (
                        is_array( $srcStat ) // sanity check that source exists
                        && is_array( $dstStat ) // dest exists
index 164b5b0..d35efae 100644 (file)
@@ -2530,9 +2530,7 @@ newheader
 newid
 newimages
 newlen
-newmessagesdifflink
 newmessagesdifflinkplural
-newmessageslink
 newmessageslinkplural
 newname
 newnames
@@ -3126,8 +3124,7 @@ prefixindex
 prefixsearchdisabled
 prefs
 prefsection
-prefsnologin
-prefsnologintext
+prefsnologintext2
 prefsubmit
 preload
 preloads
index 3bd508c..3dcf12c 100644 (file)
@@ -90,15 +90,15 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
        require $maintenance->loadSettings();
 }
 
-if ( $maintenance->getDbType() === Maintenance::DB_ADMIN &&
-       is_readable( "$IP/AdminSettings.php" ) )
-{
+if ( $maintenance->getDbType() === Maintenance::DB_ADMIN
+       && is_readable( "$IP/AdminSettings.php" )
+{
        require "$IP/AdminSettings.php";
 }
 
 if ( $maintenance->getDbType() === Maintenance::DB_NONE ) {
        if ( $wgLocalisationCacheConf['storeClass'] === false && ( $wgLocalisationCacheConf['store'] == 'db' || ( $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory ) ) ) {
-               $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+               $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
        }
 }
 $maintenance->finalSetup();
index dd468a9..73296b7 100644 (file)
@@ -97,7 +97,7 @@ abstract class DumpIterator extends Maintenance {
                if ( $this->getDbType() == Maintenance::DB_NONE ) {
                        global $wgUseDatabaseMessages, $wgLocalisationCacheConf, $wgHooks;
                        $wgUseDatabaseMessages = false;
-                       $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+                       $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
                        $wgHooks['InterwikiLoadPrefix'][] = 'DumpIterator::disableInterwikis';
                }
        }
index 5d783cb..37c2a31 100644 (file)
@@ -29,7 +29,6 @@ $originalDir = getcwd();
 require_once __DIR__ . '/commandLine.inc';
 require_once __DIR__ . '/backupTextPass.inc';
 
-
 $dumper = new TextPassDumper( $argv );
 
 if ( !isset( $options['help'] ) ) {
index 1a9293c..0ec1955 100644 (file)
@@ -64,7 +64,7 @@ By default, outputs relative paths against the parent directory of \$wgUploadDir
                                $this->mSharedSupplement = true;
                        }
                }
-               $this-> { $this->mAction } ( $this->mShared );
+               $this->{ $this->mAction } ( $this->mShared );
                if ( $this->mSharedSupplement ) {
                        $this->fetchUsed( true );
                }
index abedc61..e03763f 100644 (file)
@@ -70,7 +70,7 @@ while ( ( $line = Maintenance::readconsole() ) !== false ) {
                readline_write_history( $historyFile );
        }
        $val = eval( $line . ";" );
-       if ( wfIsHipHop() || is_null( $val ) ) {
+       if ( wfIsHHVM() || is_null( $val ) ) {
                echo "\n";
        } elseif ( is_string( $val ) || is_numeric( $val ) ) {
                echo "$val\n";
index 373170f..52056ea 100644 (file)
@@ -103,8 +103,7 @@ class FindHooks extends Maintenance {
                $this->printArray( 'Documented and not found', $deprecated );
                $this->printArray( 'Unclear hook calls', $bad );
 
-               if ( count( $todo ) == 0 && count( $deprecated ) == 0 && count( $bad ) == 0 )
-               {
+               if ( count( $todo ) == 0 && count( $deprecated ) == 0 && count( $bad ) == 0 ) {
                        $this->output( "Looks good!\n" );
                }
        }
diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php
deleted file mode 100644 (file)
index 548bb2f..0000000
+++ /dev/null
@@ -1,2692 +0,0 @@
-<?php
-/**
- * Performs fuzz-style testing of MediaWiki's parser and forms.
- *
- * Copyright © 2006 Nick Jenkins
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Nick Jenkins ( http://nickj.org/ ).
-
-
-Started: 18 May 2006.
-
-Description:
-  Performs fuzz-style testing of MediaWiki's parser and forms.
-
-How:
-  - Generate lots of nasty wiki text.
-  - Ask the Parser to render that wiki text to HTML, or ask MediaWiki's forms
-       to deal with that wiki text.
-  - Check MediaWiki's output for problems.
-  - Repeat.
-
-Why:
-  - To help find bugs.
-  - To help find security issues, or potential security issues.
-
-What type of problems are being checked for:
-  - Unclosed tags.
-  - Errors or interesting warnings from Tidy.
-  - PHP errors / warnings / notices.
-  - MediaWiki internal errors.
-  - Very slow responses.
-  - No response from apache.
-  - Optionally checking for malformed HTML using the W3C validator.
-
-Background:
-  Many of the wikiFuzz class methods are a modified PHP port,
-  of a "shameless" Python port, of LCAMTUF'S MANGELME:
-  - http://www.securiteam.com/tools/6Z00N1PBFK.html
-  - http://www.securityfocus.com/archive/1/378632/2004-10-15/2004-10-21/0
-
-Video:
-  There's an XviD video discussing this fuzz tester. You can get it from:
-  http://files.nickj.org/MediaWiki/Fuzz-Testing-MediaWiki-xvid.avi
-
-Requirements:
-  To run this, you will need:
-  - Command-line PHP5, with PHP-curl enabled (not all installations have this
-       enabled - try "apt-get install php5-curl" if you're on Debian to install).
-  - the Tidy standalone executable. ("apt-get install tidy").
-
-Optional:
-  - If you want to run the curl scripts, you'll need standalone curl installed
-       ("apt-get install curl")
-  - For viewing the W3C validator output on a command line, the "html2text"
-       program may be useful ("apt-get install html2text")
-
-Saving tests and test results:
-  Any of the fuzz tests which find problems are saved for later review.
-  In order to help track down problems, tests are saved in a number of
-  different formats. The default filename extensions and their meanings are:
-  - ".test.php" : PHP script that reproduces just that one problem using PHP-Curl.
-  - ".curl.sh"  : Shell script that reproduces that problem using standalone curl.
-  - ".data.bin" : The serialized PHP data so that this script can re-run the test.
-  - ".info.txt" : A human-readable text file with details of the field contents.
-
-Wiki configuration for testing:
-  You should make some additions to LocalSettings.php in order to catch the most
-  errors. Note this configuration is for **TESTING PURPOSES ONLY**, and is IN NO
-  WAY, SHAPE, OR FORM suitable for deployment on a hostile network. That said,
-  personally I find these additions to be the most helpful for testing purposes:
-
-  // --------- Start ---------
-  // Everyone can do everything. Very useful for testing, yet useless for deployment.
-  $wgGroupPermissions['*']['autoconfirmed']   = true;
-  $wgGroupPermissions['*']['block']           = true;
-  $wgGroupPermissions['*']['bot']             = true;
-  $wgGroupPermissions['*']['delete']          = true;
-  $wgGroupPermissions['*']['deletedhistory']  = true;
-  $wgGroupPermissions['*']['deleterevision']  = true;
-  $wgGroupPermissions['*']['editinterface']   = true;
-  $wgGroupPermissions['*']['hiderevision']    = true;
-  $wgGroupPermissions['*']['import']          = true;
-  $wgGroupPermissions['*']['importupload']    = true;
-  $wgGroupPermissions['*']['minoredit']       = true;
-  $wgGroupPermissions['*']['move']            = true;
-  $wgGroupPermissions['*']['patrol']          = true;
-  $wgGroupPermissions['*']['protect']         = true;
-  $wgGroupPermissions['*']['proxyunbannable'] = true;
-  $wgGroupPermissions['*']['renameuser']      = true;
-  $wgGroupPermissions['*']['reupload']        = true;
-  $wgGroupPermissions['*']['reupload-shared'] = true;
-  $wgGroupPermissions['*']['rollback']        = true;
-  $wgGroupPermissions['*']['siteadmin']       = true;
-  $wgGroupPermissions['*']['unwatchedpages']  = true;
-  $wgGroupPermissions['*']['upload']          = true;
-  $wgGroupPermissions['*']['userrights']      = true;
-  $wgGroupPermissions['*']['renameuser']      = true;
-  $wgGroupPermissions['*']['makebot']         = true;
-  $wgGroupPermissions['*']['makesysop']       = true;
-
-  // Enable weird and wonderful options:
-                                                         // Increase default error reporting level.
-  error_reporting (E_ALL);    // At a later date could be increased to E_ALL | E_STRICT
-  $wgEnableUploads = true;    // enable uploads.
-  $wgDBerrorLog = "/root/mediawiki-db-error-log.txt";  // log DB errors, replace with suitable path.
-  $wgShowSQLErrors = true;    // Show SQL errors (instead of saying the query was hidden).
-  $wgShowExceptionDetails = true;  // want backtraces.
-  $wgEnableAPI = true;        // enable API.
-  $wgEnableWriteAPI = true;   // enable API.
-
-  // Install & enable Parser Hook extensions to increase code coverage. E.g.:
-  require_once "extensions/ParserFunctions/ParserFunctions.php";
-  require_once "extensions/Cite/Cite.php";
-  require_once "extensions/inputbox/inputbox.php";
-  require_once "extensions/Sort/Sort.php";
-  require_once "extensions/wikihiero/wikihiero.php";
-  require_once "extensions/CharInsert/CharInsert.php";
-  require_once "extensions/FixedImage/FixedImage.php";
-
-  // Install & enable Special Page extensions to increase code coverage. E.g.:
-  require_once "extensions/Cite/SpecialCite.php";
-  require_once "extensions/Renameuser/SpecialRenameuser.php";
-  // --------- End ---------
-
-  If you want to try E_STRICT error logging, add this to the above:
-  // --------- Start ---------
-  error_reporting (E_ALL | E_STRICT);
-  set_error_handler( 'error_handler' );
-  function error_handler ($type, $message, $file=__FILE__, $line=__LINE__) {
-        if ($message == "var: Deprecated. Please use the public/private/protected modifiers") return;
-        print "<br />\n<b>Strict Standards:</b> Type: <b>$type</b>:  $message in <b>$file</b> on line <b>$line</b><br />\n";
-  }
-  // --------- End ---------
-
-  Also add/change this in LocalSettings.php:
-  // --------- Start ---------
-  $wgEnableProfileInfo = true;
-  $wgDBserver = "localhost"; // replace with DB server hostname
-  // --------- End ---------
-
-Usage:
-  Run with "php fuzz-tester.php".
-  To see the various command-line options, run "php fuzz-tester.php --help".
-  To stop the script, press Ctrl-C.
-
-Console output:
-  - If requested, first any previously failed tests will be rerun.
-  - Then new tests will be generated and run. Any tests that fail will be saved,
-       and a brief message about why they failed will be printed on the console.
-  - The console will show the number of tests run, time run, number of tests
-       failed, number of tests being done per minute, and the name of the current test.
-
-TODO:
-  Some known things that could improve this script:
-  - Logging in with cookie jar storage needed for some tests (as there are some
-       pages that cannot be tested without being logged in, and which are currently
-       untested - e.g. Special:Emailuser, Special:Preferences, adding to Watchist).
-  - Testing of Timeline extension (I cannot test as ploticus has/had issues on
-       my architecture).
-
-*/
-
-// ///////////////////////// COMMAND LINE HELP ////////////////////////////////////
-
-// This is a command line script, load MediaWiki env (gives command line options);
-require_once __DIR__ . '/commandLine.inc';
-
-// if the user asked for an explanation of command line options.
-if ( isset( $options["help"] ) ) {
-       print <<<ENDS
-MediaWiki $wgVersion fuzz tester
-Usage: php {$_SERVER["SCRIPT_NAME"]} [--quiet] [--base-url=<url-to-test-wiki>]
-                                                  [--directory=<failed-test-path>] [--include-binary]
-                                                  [--w3c-validate] [--delete-passed-retests] [--help]
-                                                  [--user=<username>] [--password=<password>]
-                                                  [--rerun-failed-tests] [--max-errors=<int>]
-                                                  [--max-runtime=<num-minutes>]
-                                                  [--specific-test=<test-name>]
-
-Options:
-  --quiet                 : Hides passed tests, shows only failed tests.
-  --base-url              : URL to a wiki on which to run the tests.
-                                                       The "http://" is optional and can be omitted.
-  --directory             : Full path to directory for storing failed tests.
-                                                       Will be created if it does not exist.
-  --include-binary        : Includes non-alphanumeric characters in the tests.
-  --w3c-validate          : Validates pages using the W3C's web validator.
-                                                       Slow. Currently many pages fail validation.
-  --user                  : Login name of a valid user on your test wiki.
-  --password              : Password for the valid user on your test wiki.
-  --delete-passed-retests : Will delete retests that now pass.
-                                                       Requires --rerun-failed-tests to be meaningful.
-  --rerun-failed-tests    : Whether to rerun any previously failed tests.
-  --max-errors            : Maximum number of errors to report before exiting.
-                                                       Does not include errors from --rerun-failed-tests
-  --max-runtime           : Maximum runtime, in minutes, to run before exiting.
-                                                       Only applies to new tests, not --rerun-failed-tests
-  --specific-test         : Runs only the specified fuzz test.
-                                                       Only applies to new tests, not --rerun-failed-tests
-  --keep-passed-tests     : Saves all test files, even those that pass.
-  --help                  : Show this help message.
-
-Example:
-  If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour,
-  and only wanted to be informed of errors, and did not want to redo previously
-  failed tests, and wanted a maximum of 100 errors, then you could do:
-  php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60
-
-
-ENDS;
-
-       exit( 0 );
-}
-
-
-// if we got command line options, check they look valid.
-$validOptions = array ( "quiet", "base-url", "directory", "include-binary",
-               "w3c-validate", "user", "password", "delete-passed-retests",
-               "rerun-failed-tests", "max-errors",
-               "max-runtime", "specific-test", "keep-passed-tests", "help" );
-if ( !empty( $options ) ) {
-       $unknownArgs = array_diff ( array_keys( $options ), $validOptions );
-       foreach ( $unknownArgs as $invalidArg ) {
-               print "Ignoring invalid command-line option: --$invalidArg\n";
-       }
-}
-
-
-// /////////////////////////// CONFIGURATION ////////////////////////////////////
-
-// URL to some wiki on which we can run our tests.
-if ( !empty( $options["base-url"] ) ) {
-       define( "WIKI_BASE_URL", $options["base-url"] );
-} else {
-       define( "WIKI_BASE_URL", $wgServer . $wgScriptPath . '/' );
-}
-
-// The directory name where we store the output.
-// Example for Windows: "c:\\temp\\wiki-fuzz"
-if ( !empty( $options["directory"] ) ) {
-       define( "DIRECTORY", $options["directory"] );
-} else {
-       define( "DIRECTORY", "{$wgUploadDirectory}/fuzz-tests" );
-}
-
-// Should our test fuzz data include binary strings?
-define( "INCLUDE_BINARY",  isset( $options["include-binary"] ) );
-
-// Whether we want to validate HTML output on the web.
-// At the moment very few generated pages will validate, so not recommended.
-define( "VALIDATE_ON_WEB", isset( $options["w3c-validate"] ) );
-// URL to use to validate our output:
-define( "VALIDATOR_URL",  "http://validator.w3.org/check" );
-
-// Location of Tidy standalone executable.
-define( "PATH_TO_TIDY",  "/usr/bin/tidy" );
-
-// The name of a user who has edited on your wiki. Used
-// when testing the Special:Contributions and Special:Userlogin page.
-if ( !empty( $options["user"] ) ) {
-       define( "USER_ON_WIKI", $options["user"] );
-} else {
-       define( "USER_ON_WIKI", "nickj" );
-}
-
-// The password of the above user. Used when testing the login page,
-// and to do this we sometimes need to login successfully.
-if ( !empty( $options["password"] ) ) {
-       define( "USER_PASSWORD", $options["password"] );
-} else {
-       // And no, this is not a valid password on any public wiki.
-       define( "USER_PASSWORD", "nickj" );
-}
-
-// If we have a test that failed, and then we run it again, and it passes,
-// do you want to delete it or keep it?
-define( "DELETE_PASSED_RETESTS", isset( $options["delete-passed-retests"] ) );
-
-// Do we want to rerun old saved tests at script startup?
-// Set to true to help catch regressions, or false if you only want new stuff.
-define( "RERUN_OLD_TESTS", isset( $options["rerun-failed-tests"] ) );
-
-// File where the database errors are logged. Should be defined in LocalSettings.php.
-define( "DB_ERROR_LOG_FILE", $wgDBerrorLog );
-
-// Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)?
-define( "QUIET", isset( $options["quiet"] ) );
-
-// Keep all test files, even those that pass. Potentially useful to tracking input that causes something
-// unusual to happen, if you don't know what "unusual" is until later.
-define( "KEEP_PASSED_TESTS", isset( $options["keep-passed-tests"] ) );
-
-// The maximum runtime, if specified.
-if ( !empty( $options["max-runtime"] ) && intval( $options["max-runtime"] ) > 0 ) {
-       define( "MAX_RUNTIME", intval( $options["max-runtime"] ) );
-}
-
-// The maximum number of problems to find, if specified. Excludes retest errors.
-if ( !empty( $options["max-errors"] ) && intval( $options["max-errors"] ) > 0 ) {
-       define( "MAX_ERRORS", intval( $options["max-errors"] ) );
-}
-
-// if the user has requested a specific test (instead of all tests), and the test they asked for looks valid.
-if ( !empty( $options["specific-test"] ) ) {
-       if ( class_exists( $options["specific-test"] ) && get_parent_class( $options["specific-test"] ) == "pageTest" ) {
-               define( "SPECIFIC_TEST", $options["specific-test"] );
-       }
-       else {
-               print "Ignoring invalid --specific-test\n";
-       }
-}
-
-// Define the file extensions we'll use:
-define( "PHP_TEST" , ".test.php" );
-define( "CURL_TEST", ".curl.sh" );
-define( "DATA_FILE", ".data.bin" );
-define( "INFO_FILE", ".info.txt" );
-define( "HTML_FILE", ".wiki_preview.html" );
-
-// If it goes wrong, we want to know about it.
-error_reporting( E_ALL | E_STRICT );
-
-// //////////////  A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS  //////////////////////
-
-class wikiFuzz {
-
-       // Only some HTML tags are understood with params by MediaWiki, the rest are ignored.
-       // List the tags that accept params below, as well as what those params are.
-       public static $data = array(
-                       "B"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "CAPTION"    => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
-                       "CENTER"     => array( "CLASS", "STYLE", "ID", "lang", "dir", "title" ),
-                       "DIV"        => array( "CLASS", "STYLE", "ID", "align", "lang", "dir", "title" ),
-                       "FONT"       => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color" ),
-                       "H1"         => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
-                       "H2"         => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
-                       "HR"         => array( "STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade" ),
-                       "LI"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value" ),
-                       "TABLE"      => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING",
-                                                                  "CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules" ),
-                       "TD"         => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
-                                                                 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
-                                                                 "dir", "title", "char", "charoff" ),
-                       "TH"         => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
-                                                                 "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
-                                                                 "dir", "title", "char", "charoff" ),
-                       "TR"         => array( "CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff" ),
-                       "UL"         => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "type" ),
-                       "P"          => array( "style", "class", "id", "align", "lang", "dir", "title" ),
-                       "blockquote" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "cite" ),
-                       "span"       => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
-                       "code"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "tt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "small"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "big"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "s"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "u"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "del"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
-                       "ins"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
-                       "sub"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "sup"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "ol"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start" ),
-                       "br"         => array( "CLASS", "ID", "STYLE", "title", "clear" ),
-                       "cite"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "var"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "ruby"       => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "rt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "rp"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "dt"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "dl"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "em"         => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "strong"     => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "i"          => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
-                       "thead"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "tfoot"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "tbody"      => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign' ),
-                       "colgroup"   => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign', 'span', 'width' ),
-                       "col"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title",  'align', 'char', 'charoff', 'valign', 'span', 'width' ),
-                       "pre"        => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "width" ),
-
-                       // extension tags that accept parameters:
-                       "sort"         => array( "order", "class" ),
-                       "ref"          => array( "name" ),
-                       "categorytree" => array( "hideroot", "mode", "style" ),
-                       "chemform"     => array( "link", "wikilink", "query" ),
-                       "section"      => array( "begin", "new" ),
-
-                       // older MW transclusion.
-                       "transclude"   => array( "page" ),
-                               );
-
-       // The types of the HTML that we will be testing were defined above
-       // Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data);
-       // as such, it also needs to also be publicly modifiable.
-       public static $types;
-
-
-       // Some attribute values.
-       static private $other = array( "&", "=", ":", "?", "\"", "\n", "%n%n%n%n%n%n%n%n%n%n%n%n", "\\" );
-       static private $ints  = array(
-                       // various numbers
-                       "0", "-1", "127", "-7897", "89000", "808080", "90928345",
-                       "0xfffffff", "ffff",
-
-                       // Different ways of saying: '
-                       "&#0000039;", // Long UTF-8 Unicode encoding
-                       "&#39;",  // dec version.
-                       "&#x27;", // hex version.
-                       "&#xA7;", // malformed hex variant, MSB not zero.
-
-                       // Different ways of saying: "
-                       "&#0000034;", // Long UTF-8 Unicode encoding
-                       "&#34;",
-                       "&#x22;", // hex version.
-                       "&#xA2;", // malformed hex variant, MSB not zero.
-
-                       // Different ways of saying: <
-                       "<",
-                       "&#0000060",  // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon)
-                       "&#0000060;", // Long UTF-8 Unicode encoding with semicolon
-                       "&#60;",
-                       "&#x3C;",     // hex version.
-                       "&#xBC;",     // malformed hex variant, MSB not zero.
-                       "&#x0003C;",  // mid-length hex version
-                       "&#X00003C;", // slightly longer hex version, with capital "X"
-
-                       // Different ways of saying: >
-                       ">",
-                       "&#0000062;", // Long UTF-8 Unicode encoding
-                       "&#62;",
-                       "&#x3E;",     // hex version.
-                       "&#xBE;",     // malformed variant, MSB not zero.
-
-                       // Different ways of saying: [
-                       "&#0000091;", // Long UTF-8 Unicode encoding
-                       "&#91;",
-                       "&#x5B;",     // hex version.
-
-                       // Different ways of saying: {{
-                       "&#0000123;&#0000123;", // Long UTF-8 Unicode encoding
-                       "&#123;&#123;",
-                       "&#x7B;&#x7B;",         // hex version.
-
-                       // Different ways of saying: |
-                       "&#0000124;", // Long UTF-8 Unicode encoding
-                       "&#124;",
-                       "&#x7C;",     // hex version.
-                       "&#xFC;",     // malformed hex variant, MSB not zero.
-
-                       // a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature
-                       // &#8204; == &zwnj;
-                       "&#8204;"
-                               );
-
-       // Defines various wiki-related bits of syntax, that can potentially cause
-       // MediaWiki to do something other than just print that literal text.
-       static private $ext = array(
-                       // links, templates, parameters.
-                       "[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]",
-
-                       // wiki tables.
-                       "\n{|", "\n|}",
-                       "!",
-                       "\n!",
-                       "!!",
-                       "||",
-                       "\n|-", "| ", "\n|",
-
-                       // section headings.
-                       "=", "==", "===", "====", "=====", "======",
-
-                       // lists (ordered and unordered) and indentation.
-                       "\n*", "*", "\n:", ":",
-                       "\n#", "#",
-
-                       // definition lists (dl, dt, dd), newline, and newline with pre, and a tab.
-                       "\n;", ";", "\n ",
-
-                       // Whitespace: newline, tab, space.
-                       "\n", "\t", " ",
-
-                       // Some XSS attack vectors from http://ha.ckers.org/xss.html
-                       "&#x09;", // tab
-                       "&#x0A;", // newline
-                       "&#x0D;", // carriage return
-                       "\0",     // null character
-                       " &#14; ", // spaces and meta characters
-                       "'';!--\"<XSS>=&{()}", // compact injection of XSS & SQL tester
-
-                       // various NULL fields
-                       "%00",
-                       "&#00;",
-                       "\0",
-
-                       // horizontal rule.
-                       "-----", "\n-----",
-
-                       // signature, redirect, bold, italics.
-                       "~~~~", "#REDIRECT [[", "'''", "''",
-
-                       // comments.
-                       "<!--", "-->",
-
-                       // quotes.
-                       "\"", "'",
-
-                       // tag start and tag end.
-                       "<", ">",
-
-                       // implicit link creation on URIs.
-                       "http://",
-                       "https://",
-                       "ftp://",
-                       "irc://",
-                       "news:",
-                       'gopher://',
-                       'telnet://',
-                       'nntp://',
-                       'worldwind://',
-                       'mailto:',
-
-                       // images.
-                       "[[image:",
-                       ".gif",
-                       ".png",
-                       ".jpg",
-                       ".jpeg",
-                       'thumbnail=',
-                       'thumbnail',
-                       'thumb=',
-                       'thumb',
-                       'right',
-                       'none',
-                       'left',
-                       'framed',
-                       'frame',
-                       'enframed',
-                       'centre',
-                       'center',
-                       "Image:",
-                       "[[:Image",
-                       'px',
-                       'upright=',
-                       'border',
-
-                       // misc stuff to throw at the Parser.
-                       '%08X',
-                       '/',
-                       ":x{|",
-                       "\n|+",
-                       "<noinclude>",
-                       "</noinclude>",
-                       " \302\273",
-                       " :",
-                       " !",
-                       " ;",
-                       "\302\253",
-                       "[[category:",
-                       "?=",
-                       "(",
-                       ")",
-                       "]]]",
-                       "../",
-                       "{{{{",
-                       "}}}}",
-                       "[[Special:",
-                       "<includeonly>",
-                       "</includeonly>",
-                       "<!--MWTEMPLATESECTION=",
-                       '<!--MWTOC-->',
-
-                       // implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs)
-                       "ISBN 2",
-                       "RFC 000",
-                       "PMID 000",
-                       "ISBN ",
-                       "RFC ",
-                       "PMID ",
-
-                       // magic words:
-                       '__NOTOC__',
-                       '__FORCETOC__',
-                       '__NOEDITSECTION__',
-                       '__START__',
-                       '__NOTITLECONVERT__',
-                       '__NOCONTENTCONVERT__',
-                       '__END__',
-                       '__TOC__',
-                       '__NOTC__',
-                       '__NOCC__',
-                       "__FORCETOC__",
-                       "__NEWSECTIONLINK__",
-                       "__NOGALLERY__",
-
-                       // more magic words / internal templates.
-                       '{{PAGENAME}}',
-                       '{{PAGENAMEE}}',
-                       '{{NAMESPACE}}',
-                       "{{MSG:",
-                       "}}",
-                       "{{MSGNW:",
-                       "}}",
-                       "{{INT:",
-                       "}}",
-                       '{{SITENAME}}',
-                       "{{NS:",
-                       "}}",
-                       "{{LOCALURL:",
-                       "}}",
-                       "{{LOCALURLE:",
-                       "}}",
-                       "{{SCRIPTPATH}}",
-                       "{{GRAMMAR:gentiv|",
-                       "}}",
-                       "{{REVISIONID}}",
-                       "{{SUBPAGENAME}}",
-                       "{{SUBPAGENAMEE}}",
-                       "{{ns:0}}",
-                       "{{fullurle:",
-                       "}}",
-                       "{{subst::",
-                       "}}",
-                       "{{UCFIRST:",
-                       "}}",
-                       "{{UC:",
-                       '{{SERVERNAME}}',
-                       '{{SERVER}}',
-                       "{{RAW:",
-                       "}}",
-                       "{{PLURAL:",
-                       "}}",
-                       "{{LCFIRST:",
-                       "}}",
-                       "{{LC:",
-                       "}}",
-                       '{{CURRENTWEEK}}',
-                       '{{CURRENTDOW}}',
-                       "{{INT:{{LC:contribs-showhideminor}}|",
-                       "}}",
-                       "{{INT:googlesearch|",
-                       "}}",
-                        "{{ROOTPAGENAME}}",
-                       "{{BASEPAGENAME}}",
-                       "{{CONTENTLANGUAGE}}",
-                       "{{PAGESINNAMESPACE:}}",
-                       "{{#language:",
-                       "}}",
-                       "{{#special:",
-                       "}}",
-                       "{{#special:emailuser",
-                       "}}",
-
-                       // Some raw link for magic words.
-                       "{{NUMBEROFPAGES:R",
-                       "}}",
-                       "{{NUMBEROFUSERS:R",
-                       "}}",
-                       "{{NUMBEROFARTICLES:R",
-                       "}}",
-                       "{{NUMBEROFFILES:R",
-                       "}}",
-                       "{{NUMBEROFADMINS:R",
-                       "}}",
-                       "{{padleft:",
-                       "}}",
-                       "{{padright:",
-                       "}}",
-                       "{{DEFAULTSORT:",
-                       "}}",
-
-                       // internal Math "extension":
-                       "<math>",
-                       "</math>",
-
-                       // Parser extension functions:
-                       "{{#expr:",
-                       "{{#if:",
-                       "{{#ifeq:",
-                       "{{#ifexist:",
-                       "{{#ifexpr:",
-                       "{{#switch:",
-                       "{{#time:",
-                       "}}",
-
-                       // references table for the Cite extension.
-                       "<references/>",
-
-                       // Internal Parser tokens - try inserting some of these.
-                       "UNIQ25f46b0524f13e67NOPARSE",
-                       "UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002",
-                       "\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU",
-
-                       // Inputbox extension:
-                       "<inputbox>\ntype=search\nsearchbuttonlabel=\n",
-                       "</inputbox>",
-
-                       // charInsert extension:
-                       "<charInsert>",
-                       "</charInsert>",
-
-                       // wikiHiero extension:
-                       "<hiero>",
-                       "</hiero>",
-
-                       // Image gallery:
-                       "<gallery>",
-                       "</gallery>",
-
-                       // FixedImage extension.
-                       "<fundraising/>",
-
-                       // Timeline extension: currently untested.
-
-                       // Nowiki:
-                       "<nOwIkI>",
-                       "</nowiki>",
-
-                       // an external image to test the external image displaying code
-                       "http://debian.org/Pics/debian.png",
-
-                       // LabeledSectionTransclusion extension.
-                       "{{#lstx:",
-                       "}}",
-                       "{{#lst:",
-                       "}}",
-                       "{{#lst:Main Page|",
-                       "}}"
-                       );
-
-       /**
-        ** Randomly returns one element of the input array.
-        */
-       public static function chooseInput( array $input ) {
-               $randindex = wikiFuzz::randnum( count( $input ) - 1 );
-               return $input[$randindex];
-       }
-
-       // Max number of parameters for HTML attributes.
-       static private $maxparams = 10;
-
-       /**
-        * Returns random number between finish and start.
-        * @param $finish
-        * @param $start int
-        * @return int
-        */
-       public static function randnum( $finish, $start = 0 ) {
-               return mt_rand( $start, $finish );
-       }
-
-       /**
-        * Returns a mix of random text and random wiki syntax.
-        * @return string
-        */
-       private static function randstring() {
-               $thestring = "";
-
-               for ( $i = 0; $i < 40; $i++ ) {
-                       $what = wikiFuzz::randnum( 1 );
-
-                       if ( $what == 0 ) { // include some random wiki syntax
-                               $which = wikiFuzz::randnum( count( wikiFuzz::$ext ) - 1 );
-                               $thestring .= wikiFuzz::$ext[$which];
-                       }
-                       else { // include some random text
-                               $char = INCLUDE_BINARY
-                                       // Decimal version:
-                                       // "&#" . wikiFuzz::randnum(255) . ";"
-                                       // Hex version:
-                                       ? "&#x" . str_pad( dechex( wikiFuzz::randnum( 255 ) ), wikiFuzz::randnum( 2, 7 ), "0", STR_PAD_LEFT ) . ";"
-                                       // A truly binary version:
-                                       // ? chr(wikiFuzz::randnum(0,255))
-                                       : chr( wikiFuzz::randnum( 126, 32 ) );
-
-                               $length = wikiFuzz::randnum( 8 );
-                               $thestring .= str_repeat ( $char, $length );
-                       }
-               }
-               return $thestring;
-       }
-
-       /**
-        * Returns either random text, or random wiki syntax, or random data from "ints",
-        *        or random data from "other".
-        * @return string
-        */
-       private static function makestring() {
-               $what = wikiFuzz::randnum( 2 );
-               if ( $what == 0 ) {
-                       return wikiFuzz::randstring();
-               } elseif ( $what == 1 ) {
-                       return wikiFuzz::$ints[wikiFuzz::randnum( count( wikiFuzz::$ints ) - 1 )];
-               } else {
-                       return wikiFuzz::$other[wikiFuzz::randnum( count( wikiFuzz::$other ) - 1 )];
-               }
-       }
-
-       /**
-        * Returns the matched character slash-escaped as in a C string
-        * Helper for makeTitleSafe callback
-        * @param $matches
-        * @return string
-        */
-       private static function stringEscape( $matches ) {
-               return sprintf( "\\x%02x", ord( $matches[1] ) );
-       }
-
-       /**
-        ** Strips out the stuff that Mediawiki balks at in a page's title.
-        **        Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
-        * @param $str string
-        * @return string
-        */
-       public static function makeTitleSafe( $str ) {
-               $legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
-               return preg_replace_callback(
-                               "/([^$legalTitleChars])/", 'wikiFuzz::stringEscape',
-                               $str );
-       }
-
-       /**
-        ** Returns a string of fuzz text.
-        * @return string
-        */
-       private static function loop() {
-               switch ( wikiFuzz::randnum( 3 ) ) {
-                       case 1: // an opening tag, with parameters.
-                               $string = "";
-                               $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
-                               $t = wikiFuzz::$types[$i];
-                               $arr = wikiFuzz::$data[$t];
-                               $string .= "<" . $t . " ";
-                               $num_params = min( wikiFuzz::$maxparams, count( $arr ) );
-                               for ( $z = 0; $z < $num_params; $z++ ) {
-                                       $badparam = $arr[wikiFuzz::randnum( count( $arr ) - 1 )];
-                                       $badstring = wikiFuzz::makestring();
-                                       $string .= $badparam . "=" . wikiFuzz::getRandQuote() . $badstring . wikiFuzz::getRandQuote() . " ";
-                               }
-                               $string .= ">\n";
-                               return $string;
-                       case 2: // a closing tag.
-                               $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
-                               return "</" . wikiFuzz::$types[$i] . ">";
-                       case 3: // a random string, between tags.
-                               return wikiFuzz::makeString();
-               }
-               return "";    // catch-all, should never be called.
-       }
-
-       /**
-        * Returns one of the three styles of random quote: ', ", and nothing.
-        * @return string
-        */
-       private static function getRandQuote() {
-               switch ( wikiFuzz::randnum( 3 ) ) {
-                       case 1 : return "'";
-                       case 2 : return "\"";
-                       default: return "";
-               }
-       }
-
-       /**
-        ** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
-        * @param $maxtypes int
-        * @return string
-        */
-       public static function makeFuzz( $maxtypes = 2 ) {
-               $page = "";
-               for ( $k = 0; $k < $maxtypes; $k++ ) {
-                       $page .= wikiFuzz::loop();
-               }
-               return $page;
-       }
-}
-
-
-// //////   MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM  ///////
-
-/**
- ** A page test has just these things:
- **        1) Form parameters.
- **        2) the URL we are going to test those parameters on.
- **        3) Any cookies required for the test.
- **        4) Whether Tidy should validate the page. Defaults to true, but can be turned off.
- **        Declared abstract because it should be extended by a class
- **        that supplies these parameters.
- */
-abstract class pageTest {
-       protected $params;
-       protected $pagePath;
-       protected $cookie = "";
-       protected $tidyValidate = true;
-
-       public function getParams() {
-               return $this->params;
-       }
-
-       public function getPagePath() {
-               return $this->pagePath;
-       }
-
-       public function getCookie() {
-               return $this->cookie;
-       }
-
-       public function tidyValidate() {
-               return $this->tidyValidate;
-       }
-}
-
-
-/**
- ** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
- */
-class editPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=WIKIFUZZ";
-
-               $this->params = array (
-                               "action"        => "submit",
-                               "wpMinoredit"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpPreview"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpSection"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpEdittime"    => wikiFuzz::makeFuzz( 2 ),
-                               "wpSummary"     => wikiFuzz::makeFuzz( 2 ),
-                               "wpScrolltop"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpStarttime"   => wikiFuzz::makeFuzz( 2 ),
-                               "wpAutoSummary" => wikiFuzz::makeFuzz( 2 ),
-                               "wpTextbox1"    => wikiFuzz::makeFuzz( 40 )  // the main wiki text, need lots of this.
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSection"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEdittime"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSummary"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpScrolltop"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpStarttime"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpAutoSummary"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpTextbox1"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Listusers".
- */
-class listusersTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Listusers";
-
-               $this->params = array (
-                               "title"        => wikiFuzz::makeFuzz( 2 ),
-                               "group"        => wikiFuzz::makeFuzz( 2 ),
-                               "username"     => wikiFuzz::makeFuzz( 2 ),
-                               "Go"           => wikiFuzz::makeFuzz( 2 ),
-                               "limit"        => wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "offset"       => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Search".
- */
-class searchTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Search";
-
-               $this->params = array (
-                               "action"        => "index.php?title=Special:Search",
-                               "ns0"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns1"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns2"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns3"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns4"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns5"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns6"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns7"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns8"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns9"           => wikiFuzz::makeFuzz( 2 ),
-                               "ns10"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns11"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns12"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns13"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns14"          => wikiFuzz::makeFuzz( 2 ),
-                               "ns15"          => wikiFuzz::makeFuzz( 2 ),
-                               "redirs"        => wikiFuzz::makeFuzz( 2 ),
-                               "search"        => wikiFuzz::makeFuzz( 2 ),
-                               "offset"        => wikiFuzz::chooseInput( array( "", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "fulltext"      => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "searchx"       => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) )
-                                       );
-       }
-}
-
-
-/**
- ** a page test for "Special:Recentchanges".
- */
-class recentchangesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Recentchanges";
-
-               $this->params = array (
-                               "action"        => wikiFuzz::makeFuzz( 2 ),
-                               "title"         => wikiFuzz::makeFuzz( 2 ),
-                               "namespace"     => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               "Go"            => wikiFuzz::makeFuzz( 2 ),
-                               "invert"        => wikiFuzz::chooseInput( array( "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideanons"     => wikiFuzz::chooseInput( array( "-1", "------'-------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'         => wikiFuzz::chooseInput( array( "0", "-1", "---------'----0", "+1", "81340909772349234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               "days"          => wikiFuzz::chooseInput( array( "-1", "----------'---0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideminor"     => wikiFuzz::chooseInput( array( "-1", "-----------'--0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidebots"      => wikiFuzz::chooseInput( array( "-1", "---------'----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hideliu"       => wikiFuzz::chooseInput( array( "-1", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidepatrolled" => wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "hidemyself"    => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'categories_any' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'categories'    => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'feed'          => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Prefixindex".
- */
-class prefixindexTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Prefixindex";
-
-               $this->params = array (
-                               "title"         => "Special:Prefixindex",
-                               "namespace"     => wikiFuzz::randnum( 101, -10 ),
-                               "Go"            => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $this->params["prefix"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
-                                                                                                wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
-               }
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $this->params["from"]   = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
-                                                                                               wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
-               }
-       }
-}
-
-
-/**
- ** a page test for "Special:MIMEsearch".
- */
-class mimeSearchTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:MIMEsearch";
-
-               $this->params = array (
-                               "action"        => "index.php?title=Special:MIMEsearch",
-                               "mime"          => wikiFuzz::makeFuzz( 3 ),
-                               'limit'         => wikiFuzz::chooseInput( array( "0", "-1", "-------'------0", "+1", "81342321351235325",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'        => wikiFuzz::chooseInput( array( "0", "-1", "-----'--------0", "+1", "81341231235365252234324",  wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Log".
- */
-class specialLogTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Log";
-
-               $this->params = array (
-                               "type"        => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "par"         => wikiFuzz::makeFuzz( 2 ),
-                               "user"        => wikiFuzz::makeFuzz( 2 ),
-                               "page"        => wikiFuzz::makeFuzz( 2 ),
-                               "from"        => wikiFuzz::makeFuzz( 2 ),
-                               "until"       => wikiFuzz::makeFuzz( 2 ),
-                               "title"       => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userlogin", with a successful login.
- */
-class successfulUserLoginTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz::makeFuzz( 2 );
-
-               $this->params = array (
-                               "wpName"          => USER_ON_WIKI,
-                               // sometimes real password, sometimes not:
-                               'wpPassword'      => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), USER_PASSWORD ) ),
-                               'wpRemember'      => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               $this->cookie = "wikidb_session=" .  wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userlogin".
- */
-class userLoginTest extends pageTest {
-       function __construct() {
-
-               $this->pagePath = "index.php?title=Special:Userlogin";
-
-               $this->params = array (
-                               'wpRetype'        => wikiFuzz::makeFuzz( 2 ),
-                               'wpRemember'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpRealName'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpPassword'      => wikiFuzz::makeFuzz( 2 ),
-                               'wpName'          => wikiFuzz::makeFuzz( 2 ),
-                               'wpMailmypassword' => wikiFuzz::makeFuzz( 2 ),
-                               'wpLoginattempt'  => wikiFuzz::makeFuzz( 2 ),
-                               'wpEmail'         => wikiFuzz::makeFuzz( 2 ),
-                               'wpDomain'        => wikiFuzz::chooseInput( array( "", "local", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCreateaccountMail' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCreateaccount' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpCookieCheck'   => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'type'            => wikiFuzz::chooseInput( array( "signup", "login", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'returnto'        => wikiFuzz::makeFuzz( 2 ),
-                               'action'          => wikiFuzz::chooseInput( array( "", "submitlogin", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a page test for "Special:Ipblocklist" (also includes unblocking)
- */
-class ipblocklistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Ipblocklist";
-
-               $this->params = array (
-                               'wpUnblockAddress' => wikiFuzz::makeFuzz( 2 ),
-                               'ip'              => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                        // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                          . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               'id'              => wikiFuzz::makeFuzz( 2 ),
-                               'wpUnblockReason' => wikiFuzz::makeFuzz( 2 ),
-                               'action'          => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "success", "submit", "unblock" ) ),
-                               'wpEditToken'     => wikiFuzz::makeFuzz( 2 ),
-                               'wpBlock'         => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "" ) ),
-                               'limit'           => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1",
-                                                                                                "09700982312351132098234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'          => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1",
-                                                                                                "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["ip"] );
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["id"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpUnblockAddress"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Newimages".
- */
-class newImagesTest extends  pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Newimages";
-
-               $this->params = array (
-                               'hidebots'  => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "1", "", "-1" ) ),
-                               'wpIlMatch' => wikiFuzz::makeFuzz( 2 ),
-                               'until'     => wikiFuzz::makeFuzz( 2 ),
-                               'from'      => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["until"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["from"] );
-       }
-}
-
-
-/**
- ** a page test for the "Special:Imagelist" page.
- */
-class imagelistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Imagelist";
-
-               $this->params = array (
-                               'sort'      => wikiFuzz::chooseInput( array( "bysize", "byname" , "bydate", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'     => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "09700982312351132098234",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpIlMatch' => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Export".
- */
-class specialExportTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Export";
-
-               $this->params = array (
-                               'action'      => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'pages'       => wikiFuzz::makeFuzz( 2 ),
-                               'curonly'     => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'listauthors' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'history'     => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
-
-                               );
-
-               // For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export.
-               if ( $this->params['action'] == 'submit' ) $this->params['action'] = '';
-
-               // Sometimes remove the history field.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["history"] );
-
-               // page does not produce HTML.
-               $this->tidyValidate = false;
-       }
-}
-
-
-/**
- ** a page test for "Special:Booksources".
- */
-class specialBooksourcesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Booksources";
-
-               $this->params = array (
-                               'go'    => wikiFuzz::makeFuzz( 2 ),
-                               // ISBN codes have to contain some semi-numeric stuff or will be ignored:
-                               'isbn'  => "0X0" . wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Allpages".
- */
-class specialAllpagesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special%3AAllpages";
-
-               $this->params = array (
-                               'from'      => wikiFuzz::makeFuzz( 2 ),
-                               'namespace' => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               'go'        => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for the page History.
- */
-class pageHistoryTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page&action=history";
-
-               $this->params = array (
-                               'limit'     => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "go"        => wikiFuzz::chooseInput( array( "first", "last", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "dir"       => wikiFuzz::chooseInput( array( "prev", "next", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "diff"      => wikiFuzz::chooseInput( array( "-1", "--------'-----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "oldid"     => wikiFuzz::chooseInput( array( "prev", "-1", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "feed"      => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for the Special:Contributions".
- */
-class contributionsTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Contributions/" . USER_ON_WIKI;
-
-               $this->params = array (
-                               'target'    => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "newbies", USER_ON_WIKI ) ),
-                               'namespace' => wikiFuzz::chooseInput( array( -1, 15, 1, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'bot'       => wikiFuzz::chooseInput( array( "", "-1", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'go'        => wikiFuzz::chooseInput( array( "-1", 'prev', 'next', wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-
-/**
- ** a page test for viewing a normal page, whilst posting various params.
- */
-class viewPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page";
-
-               $this->params = array (
-                               "useskin"        => wikiFuzz::chooseInput( array( "chick", "cologneblue", "myskin",
-                                                                               "nostalgia", "simple", "standard", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "uselang"        => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ),
-                                               "ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba",
-                                               "bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca",
-                                               "ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en",
-                                               "eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga",
-                                               "gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is",
-                                               "it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la",
-                                               "li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds",
-                                               "nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa",
-                                               "pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc",
-                                               "sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el",
-                                               "su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm",
-                                               "ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za",
-                                               "zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw" ) ),
-                               "returnto"       => wikiFuzz::makeFuzz( 2 ),
-                               "feed"           => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "rcid"           => wikiFuzz::makeFuzz( 2 ),
-                               "action"         => wikiFuzz::chooseInput( array( "view", "raw", "render", wikiFuzz::makeFuzz( 2 ), "markpatrolled" ) ),
-                               "printable"      => wikiFuzz::makeFuzz( 2 ),
-                               "oldid"          => wikiFuzz::makeFuzz( 2 ),
-                               "redirect"       => wikiFuzz::makeFuzz( 2 ),
-                               "diff"           => wikiFuzz::makeFuzz( 2 ),
-                               "search"         => wikiFuzz::makeFuzz( 2 ),
-                               "rdfrom"         => wikiFuzz::makeFuzz( 2 ),  // things from Article.php from here on:
-                               "token"          => wikiFuzz::makeFuzz( 2 ),
-                               "tbid"           => wikiFuzz::makeFuzz( 2 ),
-                               // @todo FIXME: Duplicate array key.
-                               "action"         => wikiFuzz::chooseInput( array( "purge", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"       => wikiFuzz::makeFuzz( 2 ),
-                               "wpEditToken"    => wikiFuzz::makeFuzz( 2 ),
-                               "from"           => wikiFuzz::makeFuzz( 2 ),
-                               "bot"            => wikiFuzz::makeFuzz( 2 ),
-                               "summary"        => wikiFuzz::makeFuzz( 2 ),
-                               "direction"      => wikiFuzz::chooseInput( array( "next", "prev", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "section"        => wikiFuzz::makeFuzz( 2 ),
-                               "preload"        => wikiFuzz::makeFuzz( 2 ),
-
-                               );
-
-               // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
-               if ( $this->params["feed"] == "atom" )     { unset( $this->params["feed"] ); }
-               elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
-
-               // Raw pages cannot really be validated
-               if ( $this->params["action"] == "raw" ) unset( $this->params["action"] );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rcid"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["diff"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rdfrom"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["oldid"] );
-
-               // usually don't want action == purge.
-               if ( wikiFuzz::randnum( 6 ) > 1 ) unset( $this->params["action"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Allmessages".
- */
-class specialAllmessagesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Allmessages";
-
-               // only really has one parameter
-               $this->params = array (
-                               "ot"     => wikiFuzz::chooseInput( array( "php", "html", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-       }
-}
-
-/**
- ** a page test for "Special:Newpages".
- */
-class specialNewpagesPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Newpages";
-
-               $this->params = array (
-                               "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ),
-                               "feed"      => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'limit'     => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'offset'    => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
-               if ( $this->params["feed"] == "atom" )     { unset( $this->params["feed"] ); }
-               elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
-       }
-}
-
-/**
- ** a page test for "redirect.php"
- */
-class redirectTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "redirect.php";
-
-               $this->params = array (
-                               "wpDropdown" => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpDropdown"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Confirmemail"
- */
-class confirmEmail extends pageTest {
-       function __construct() {
-               // sometimes we send a bogus confirmation code, and sometimes we don't.
-               $this->pagePath = "index.php?title=Special:Confirmemail" . wikiFuzz::chooseInput( array( "", "/" . wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 1 ) ) ) );
-
-               $this->params = array (
-                               "token" => wikiFuzz::makeFuzz( 2 )
-                               );
-       }
-}
-
-
-/**
- ** a page test for "Special:Watchlist"
- **        Note: this test would be better if we were logged in.
- */
-class watchlistTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Watchlist";
-
-               $this->params = array (
-                               "remove"   => wikiFuzz::chooseInput( array( "Remove checked items from watchlist", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'days'     => wikiFuzz::chooseInput( array( 0, -1, -230, "--", 3, 9, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'hideOwn'  => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'hideBots' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'namespace' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'action'   => wikiFuzz::chooseInput( array( "submit", "clear", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'id[]'     => wikiFuzz::makeFuzz( 2 ),
-                               'edit'     => wikiFuzz::makeFuzz( 2 ),
-                               'token'    => wikiFuzz::chooseInput( array( "", "1243213", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we specifiy "reset", and sometimes we don't.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) $this->params["reset"] = wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-/**
- ** a page test for "Special:Movepage"
- */
-class specialMovePage extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Movepage";
-
-               $this->params = array (
-                               "action"      => wikiFuzz::chooseInput( array( "success", "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'target'      => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
-                               'wpOldTitle'  => wikiFuzz::chooseInput( array( "z", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpNewTitle'  => wikiFuzz::chooseInput( array( "y", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpReason'    => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpMovetalk'  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpDeleteAndMove'  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpConfirm'   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'talkmoved'   => wikiFuzz::chooseInput( array( "1", wikiFuzz::makeFuzz( 2 ), "articleexists", 'notalkpage' ) ),
-                               'oldtitle'    => wikiFuzz::makeFuzz( 2 ),
-                               'newtitle'    => wikiFuzz::makeFuzz( 2 ),
-                               'wpMovetalk'  => wikiFuzz::chooseInput( array( "1", "0", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpNewTitle"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpOldTitle"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Undelete"
- */
-class specialUndeletePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Undelete";
-
-               $this->params = array (
-                               "action"      => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
-                               'target'      => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
-                               'timestamp'   => wikiFuzz::chooseInput( array( "125223", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'file'        => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'restore'     => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'preview'     => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpComment'   => wikiFuzz::makeFuzz( 2 )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["restore"] );
-               if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["preview"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Unlockdb"
- */
-class specialUnlockdbPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Unlockdb";
-
-               $this->params = array (
-                               "action"        => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Lockdb"
- */
-class specialLockdbPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Lockdb";
-
-               $this->params = array (
-                               "action"       => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'  => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpLockReason' => wikiFuzz::makeFuzz( 2 ),
-                               'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Userrights"
- */
-class specialUserrights extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Userrights";
-
-               $this->params = array (
-                               'wpEditToken'   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'user-editname' => wikiFuzz::chooseInput( array( "Nickj2", "Nickj2\n<xyz>", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'ssearchuser'   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'saveusergroups' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ), "Save User Groups" ),
-                               'member[]'      => wikiFuzz::chooseInput( array( "0", "bot", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "available[]"   => wikiFuzz::chooseInput( array( "0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['ssearchuser'] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['saveusergroups'] );
-       }
-}
-
-
-/**
- ** a test for page protection and unprotection.
- */
-class pageProtectionForm extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page";
-
-               $this->params = array (
-                               "action"               => "protect",
-                               'wpEditToken'          => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtect-level-edit" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtect-level-move" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "mwProtectUnchained"   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               'mwProtect-reason'     => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["mwProtectUnchained"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['mwProtect-reason'] );
-       }
-}
-
-
-/**
- ** a page test for "Special:Blockip".
- */
-class specialBlockip extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Blockip";
-
-               $this->params = array (
-                               "action"          => wikiFuzz::chooseInput( array( "submit", "",  wikiFuzz::makeFuzz( 2 ) ) ),
-                               'wpEditToken'     => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockAddress"  => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                         // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                         . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               "ip"              => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
-                                                                         // something like an IP address, sometimes invalid:
-                                                                        ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
-                                                                         . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
-                               "wpBlockOther"    => wikiFuzz::chooseInput( array( '', 'Nickj2', wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockExpiry"   => wikiFuzz::chooseInput( array( "other", "2 hours", "1 day", "3 days", "1 week", "2 weeks",
-                                                                                 "1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlockReason"   => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpAnonOnly"      => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpCreateAccount" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpBlock"         => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockOther"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockExpiry"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockReason"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpAnonOnly"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpCreateAccount"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockAddress"] );
-               if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["ip"] );
-       }
-}
-
-
-/**
- ** a test for the imagepage.
- */
-class imagepageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Image:Small-email.png";
-
-               $this->params = array (
-                               "image"         => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"      => wikiFuzz::makeFuzz( 2 ),
-                               "oldimage"      => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpEditToken"   => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["image"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldimage"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEditToken"] );
-       }
-}
-
-
-/**
- ** a test for page deletion form.
- */
-class pageDeletion extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Main_Page&action=delete";
-
-               $this->params = array (
-                               "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpReason"    => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "wpConfirm"   => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpEditToken"] );
-               if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpConfirm"] );
-       }
-}
-
-
-
-/**
- ** a test for Revision Deletion.
- */
-class specialRevisionDeletePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Revisiondelete";
-
-               $this->params = array (
-                               "target"               => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "oldid"                => wikiFuzz::makeFuzz( 2 ),
-                               "oldid[]"              => wikiFuzz::makeFuzz( 2 ),
-                               "wpReason"             => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-text"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-comment" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-user"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "revdelete-hide-restricted" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid[]"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-text"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-comment"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-user"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-restricted"] );
-       }
-}
-
-
-/**
- ** a test for Special:Import.
- */
-class specialImportPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Import";
-
-               $this->params = array (
-                               "action"         => "submit",
-                               "source"         => wikiFuzz::chooseInput( array( "upload", "interwiki", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "MAX_FILE_SIZE"  => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "xmlimport"      => wikiFuzz::chooseInput( array( "/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "namespace"      => wikiFuzz::chooseInput( array( wikiFuzz::randnum( 30, -6 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               "interwiki"      => wikiFuzz::makeFuzz( 2 ),
-                               "interwikiHistory" => wikiFuzz::makeFuzz( 2 ),
-                               "frompage"       => wikiFuzz::makeFuzz( 2 ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["action"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["source"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["MAX_FILE_SIZE"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["xmlimport"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwiki"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwikiHistory"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["frompage"] );
-
-               // Note: Need to do a file upload to fully test this Special page.
-       }
-}
-
-
-/**
- ** a test for thumb.php
- */
-class thumbTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "thumb.php";
-
-               $this->params = array (
-                               "f"  => wikiFuzz::chooseInput( array( "..", "\\", "small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "w"  => wikiFuzz::chooseInput( array( "80", wikiFuzz::randnum( 6000, -200 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               "r"  => wikiFuzz::chooseInput( array( "0", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["f"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["w"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["r"] );
-       }
-}
-
-/**
- ** a test for profileinfo.php
- */
-class profileInfo extends pageTest {
-       function __construct() {
-               $this->pagePath = "profileinfo.php";
-
-               $this->params = array (
-                               "expand"  => wikiFuzz::makeFuzz( 2 ),
-                               "sort"    => wikiFuzz::chooseInput( array( "time", "count", "name", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "filter"  => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["sort"] );
-               if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["filter"] );
-       }
-}
-
-
-/**
- ** a test for Special:Cite (extension Special page).
- */
-class specialCitePageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Cite";
-
-               $this->params = array (
-                               "page"    => wikiFuzz::chooseInput( array( "\" onmouseover=\"alert(1);\"", "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
-                               "id"      => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["page"] );
-               if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["id"] );
-       }
-}
-
-
-/**
- ** a test for Special:Filepath (extension Special page).
- */
-class specialFilepathPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Filepath";
-
-               $this->params = array (
-                               "file"    => wikiFuzz::chooseInput( array( "Small-email.png", "Small-email.png" . wikiFuzz::makeFuzz( 1 ), wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-       }
-}
-
-
-/**
- ** a test for Special:Renameuser (extension Special page).
- */
-class specialRenameuserPageTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Renameuser";
-
-               $this->params = array (
-                               "oldusername"   => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
-                               "newusername"   => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
-                               "token"         => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-       }
-}
-
-
-/**
- ** a test for Special:Linksearch (extension Special page).
- */
-class specialLinksearch extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special%3ALinksearch";
-
-               $this->params = array (
-                               "target" => wikiFuzz::makeFuzz( 2 ),
-                               );
-
-               // sometimes we don't want to specify certain parameters.
-               if ( wikiFuzz::randnum( 10 ) == 0 ) unset( $this->params["target"] );
-       }
-}
-
-
-/**
- ** a test for Special:CategoryTree (extension Special page).
- */
-class specialCategoryTree extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:CategoryTree";
-
-               $this->params = array (
-                               "target" => wikiFuzz::makeFuzz( 2 ),
-                               "from"   => wikiFuzz::makeFuzz( 2 ),
-                               "until"  => wikiFuzz::makeFuzz( 2 ),
-                               "showas" => wikiFuzz::makeFuzz( 2 ),
-                               "mode"   => wikiFuzz::chooseInput( array( "pages", "categories", "all", wikiFuzz::makeFuzz( 2 ) ) ),
-                               );
-
-               // sometimes we do want to specify certain parameters.
-               if ( wikiFuzz::randnum( 5 ) == 0 ) $this->params["notree"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-       }
-}
-
-
-/**
- ** a test for "Special:Chemicalsources" (extension Special page).
- */
-class specialChemicalsourcesTest extends pageTest {
-       function __construct() {
-               $this->pagePath = "index.php?title=Special:Chemicalsources";
-
-               // choose an input format to use.
-               $format =  wikiFuzz::chooseInput(
-                                       array(  'go',
-                                                       'CAS',
-                                                       'EINECS',
-                                                       'CHEBI',
-                                                       'PubChem',
-                                                       'SMILES',
-                                                       'InChI',
-                                                       'ATCCode',
-                                                       'KEGG',
-                                                       'RTECS',
-                                                       'ECNumber',
-                                                       'DrugBank',
-                                                       'Formula',
-                                                       'Name'
-                                                )
-                                       );
-
-               // values for different formats usually start with either letters or numbers.
-               switch ( $format ) {
-                       case 'Name'   : $value = "A"; break;
-                       case 'InChI'  :
-                       case 'SMILES' :
-                       case 'Formula': $value = "C"; break;
-                       default       : $value = "0"; break;
-               }
-
-               // and then we append the fuzz input.
-               $this->params = array ( $format => $value . wikiFuzz::makeFuzz( 2 ) );
-       }
-}
-
-
-/**
- ** A test for api.php (programmatic interface to MediaWiki in XML/JSON/RSS/etc formats).
- ** Quite involved to test because there are lots of options/parameters, and because
- ** for a lot of the functionality if all the parameters don't make sense then it just
- ** returns the help screen - so currently a lot of the tests aren't actually doing much
- ** because something wasn't right in the query.
- **
- ** @todo Incomplete / unfinished; Runs too fast (suggests not much testing going on).
- */
-class api extends pageTest {
-
-       // API login mode.
-       private static function loginMode() {
-               $arr =  array ( "lgname"        => wikiFuzz::makeFuzz( 2 ),
-                                               "lgpassword"    => wikiFuzz::makeFuzz( 2 ),
-                                          );
-               // sometimes we want to specify the extra "lgdomain" parameter.
-               if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $arr["lgdomain"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-               }
-
-               return $arr;
-       }
-
-       // API OpenSearch mode.
-       private static function opensearchMode() {
-               return array ( "search"        => wikiFuzz::makeFuzz( 2 ) );
-       }
-
-       // API watchlist feed mode.
-       private static function feedwatchlistMode() {
-               // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible value below?
-               return array ( "feedformat"    => wikiFuzz::chooseInput( array( "rss", "atom" ) ) );
-       }
-
-       // API query mode.
-       private static function queryMode() {
-               // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible params for the elements below?
-               //        Suspect this will stuff up the tests more, but need to check.
-               $params = array (
-                                        // @todo FIXME: More titles.
-                                        "titles"        => wikiFuzz::chooseInput( array( "Main Page" ) ),
-                                        // @todo FIXME: More pageids.
-                                        "pageids"       => 1,
-                                        "prop"          => wikiFuzz::chooseInput( array( "info", "revisions", "watchlist" ) ),
-                                        "list"          => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks" ) ),
-                                        "meta"          => wikiFuzz::chooseInput( array( "siteinfo" ) ),
-                                        "generator"     => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "info", "revisions" ) ),
-                                        "siprop"        => wikiFuzz::chooseInput( array( "general", "namespaces", "general|namespaces" ) ),
-                                  );
-
-                // Add extra parameters based on what list choice we got.
-                switch ( $params["list"] ) {
-                       case "usercontribs" : self::addListParams ( $params, "uc", array( "limit", "start", "end", "user", "dir" ) ); break;
-                       case "allpages"     : self::addListParams ( $params, "ap", array( "from", "prefix", "namespace", "filterredir", "limit" ) ); break;
-                       case "watchlist"    : self::addListParams ( $params, "wl", array( "allrev", "start", "end", "namespace", "dir", "limit", "prop" ) ); break;
-                       case "logevents"    : self::addListParams ( $params, "le", array( "limit", "type", "start", "end", "user", "dir" ) ); break;
-                       case "recentchanges": self::addListParams ( $params, "rc", array( "limit", "prop", "show", "namespace", "start", "end", "dir" ) ); break;
-                       case "backlinks"    : self::addListParams ( $params, "bl", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                       case "embeddedin"   : self::addListParams ( $params, "ei", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                       case "imagelinks"   : self::addListParams ( $params, "il", array( "continue", "namespace", "redirect", "limit" ) ); break;
-                }
-
-                if ( $params["prop"] == "revisions" ) {
-                       self::addListParams ( $params, "rv", array( "prop", "limit", "startid", "endid", "end", "dir" ) );
-                }
-
-                // Sometimes we want redirects, sometimes we don't.
-                if ( wikiFuzz::randnum( 3 ) == 0 ) {
-                       $params["redirects"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-                }
-
-                return $params;
-       }
-
-       // Adds all the elements to the array, using the specified prefix.
-       private static function addListParams( &$array, $prefix, $elements ) {
-               foreach ( $elements as $element ) {
-                       $array[$prefix . $element] = self::getParamDetails( $element );
-               }
-       }
-
-       // For a given element name, returns the data for that element.
-       private static function getParamDetails( $element ) {
-               switch ( $element ) {
-                       case 'startid'    :
-                       case 'endid'      :
-                       case 'start'      :
-                       case 'end'        :
-                       case 'limit'      : return wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz::randnum( 9000, -100 ), wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'dir'        : return wikiFuzz::chooseInput( array( "newer", "older", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'user'       : return wikiFuzz::chooseInput( array( USER_ON_WIKI, wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'namespace'  : return wikiFuzz::chooseInput( array( -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 200000, wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'filterredir': return wikiFuzz::chooseInput( array( "all", "redirects", "nonredirectsallpages", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'allrev'     : return wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'prop'       : return wikiFuzz::chooseInput( array( "user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'type'       : return wikiFuzz::chooseInput( array( "block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'hide'       : return wikiFuzz::chooseInput( array( "minor", "bots", "anons", "liu", "liu|bots|", wikiFuzz::makeFuzz( 2 ) ) );
-                       case 'show'       : return wikiFuzz::chooseInput( array( 'minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikiFuzz::makeFuzz( 2 ) ) );
-                       default           : return wikiFuzz::makeFuzz( 2 );
-               }
-       }
-
-       // Entry point.
-       function __construct() {
-               $this->pagePath = "api.php";
-
-               $modes = array ( "help",
-                                               "login",
-                                               "opensearch",
-                                               "feedwatchlist",
-                                               "query" );
-               $action = wikiFuzz::chooseInput( array_merge ( $modes, array( wikiFuzz::makeFuzz( 2 ) ) ) );
-
-               switch ( $action ) {
-                       case "login"         : $this->params = self::loginMode();
-                                                                  break;
-                       case "opensearch"    : $this->params = self::opensearchMode();
-                                                                  break;
-                       case "feedwatchlist" : $this->params = self::feedwatchlistMode();
-                                                                  break;
-                       case "query"         : $this->params = self::queryMode();
-                                                                  break;
-                       case "help"         :
-                       default             :  // Do something random - "Crazy Ivan" mode.
-                                                                  $random_mode = wikiFuzz::chooseInput( $modes ) . "Mode";
-                                                                  // There is no "helpMode".
-                                                                  if ( $random_mode == "helpMode" ) $random_mode = "queryMode";
-                                                                  $this->params = self::$random_mode();
-                                                                  break;
-               }
-
-               // Save the selected action.
-               $this->params["action"] = $action;
-
-               // Set the cookie:
-               // @todo FIXME: Need to get this cookie dynamically set, rather than hard-coded.
-               $this->cookie = "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540";
-
-               // Output format
-               $this->params["format"] = wikiFuzz::chooseInput( array( "json", "jsonfm", "php", "phpfm",
-                                                                                                                          "wddx", "wddxfm", "xml", "xmlfm",
-                                                                                                                          "yaml", "yamlfm", "raw", "rawfm",
-                                                                                                                          wikiFuzz::makeFuzz( 2 ) ) );
-
-               // Page does not produce HTML (sometimes).
-               $this->tidyValidate = false;
-       }
-}
-
-
-/**
- ** a page test for the GeSHi extension.
- */
-class GeSHi_Test extends pageTest {
-
-       private function getGeSHiContent() {
-               return "<source lang=\"" . $this->getLang() . "\" "
-                          . ( wikiFuzz::randnum( 2 ) == 0 ? "line " : "" )
-                          . ( wikiFuzz::randnum( 2 ) == 0 ? "strict " : "" )
-                          . "start=" . wikiFuzz::chooseInput( array( wikiFuzz::randnum( 6000, -6000 ), wikiFuzz::makeFuzz( 2 ) ) )
-                          . ">"
-                          . wikiFuzz::makeFuzz( 2 )
-                          . "</source>";
-       }
-
-       private function getLang() {
-       return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp",
-                               "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl",
-                               "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas",
-                               "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty",
-                               "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikiFuzz::makeFuzz( 1 ) ) );
-       }
-
-       function __construct() {
-               $this->pagePath = "index.php?title=WIKIFUZZ";
-
-               $this->params = array (
-                               "action"        => "submit",
-                               "wpMinoredit"   => "test",
-                               "wpPreview"     => "test",
-                               "wpSection"     => "test",
-                               "wpEdittime"    => "test",
-                               "wpSummary"     => "test",
-                               "wpScrolltop"   => "test",
-                               "wpStarttime"   => "test",
-                               "wpAutoSummary" => "test",
-                               "wpTextbox1"    => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content.
-                               );
-       }
-}
-
-/**
- ** selects a page test to run.
- * @param $count
- * @return \api|\confirmEmail|\contributionsTest|\editPageTest|\imagelistTest|\imagepageTest|\ipblocklistTest|\listusersTest|\mimeSearchTest|\newImagesTest|\pageDeletion|\pageHistoryTest|\pageProtectionForm|\prefixindexTest|\profileInfo|\recentchangesTest|\redirectTest|\searchTest|\specialAllmessagesTest|\specialAllpagesTest|\specialBlockip|\specialBooksourcesTest|\specialCategoryTree|\specialChemicalsourcesTest|\specialCitePageTest|\specialExportTest|\specialFilepathPageTest|\specialImportPageTest|\specialLinksearch|\specialLockdbPageTest|\specialLogTest|\specialMovePage|\specialNewpagesPageTest|\specialRenameuserPageTest|\specialRevisionDeletePageTest|\specialUndeletePageTest|\specialUnlockdbPageTest|\specialUserrights|\successfulUserLoginTest|\thumbTest|\userLoginTest|\viewPageTest|\watchlistTest
- */
-function selectPageTest( $count ) {
-
-       // if the user only wants a specific test, then only ever give them that.
-       if ( defined( "SPECIFIC_TEST" ) ) {
-               $testType = SPECIFIC_TEST;
-               return new $testType ();
-       }
-
-       // Some of the time we test Special pages, the remaining
-       // time we test using the standard edit page.
-       switch ( $count % 100 ) {
-               case 0 : return new successfulUserLoginTest();
-               case 1 : return new listusersTest();
-               case 2 : return new searchTest();
-               case 3 : return new recentchangesTest();
-               case 4 : return new prefixindexTest();
-               case 5 : return new mimeSearchTest();
-               case 6 : return new specialLogTest();
-               case 7 : return new userLoginTest();
-               case 8 : return new ipblocklistTest();
-               case 9 : return new newImagesTest();
-               case 10: return new imagelistTest();
-               case 11: return new specialExportTest();
-               case 12: return new specialBooksourcesTest();
-               case 13: return new specialAllpagesTest();
-               case 14: return new pageHistoryTest();
-               case 15: return new contributionsTest();
-               case 16: return new viewPageTest();
-               case 17: return new specialAllmessagesTest();
-               case 18: return new specialNewpagesPageTest();
-               case 19: return new searchTest();
-               case 20: return new redirectTest();
-               case 21: return new confirmEmail();
-               case 22: return new watchlistTest();
-               case 24: return new specialUndeletePageTest();
-               case 25: return new specialMovePage();
-               case 26: return new specialUnlockdbPageTest();
-               case 27: return new specialLockdbPageTest();
-               case 28: return new specialUserrights();
-               case 29: return new pageProtectionForm();
-               case 30: return new specialBlockip();
-               case 31: return new imagepageTest();
-               case 32: return new pageDeletion();
-               case 33: return new specialRevisionDeletePageTest();
-               case 34: return new specialImportPageTest();
-               case 35: return new thumbTest();
-               case 37: return new profileInfo();
-               case 38: return new specialCitePageTest();
-               case 39: return new specialFilepathPageTest();
-               case 40: return new specialRenameuserPageTest();
-               case 41: return new specialLinksearch();
-               case 42: return new specialCategoryTree();
-               case 43: return new api();
-               case 44: return new specialChemicalsourcesTest();
-               default: return new editPageTest();
-       }
-}
-
-
-// /////////////////////  SAVING OUTPUT  /////////////////////////
-
-/**
- ** Utility function for saving a file. Currently has no error checking.
- */
-function saveFile( $data, $name ) {
-       file_put_contents( $name, $data );
-}
-
-/**
- ** Returns a test as an experimental GET-to-POST URL.
- **        This doesn't seem to always work though, and sometimes the output is too long
- **        to be a valid GET URL, so we also save in other formats.
- * @param $test pageTest
- * @return string
- */
-function getAsURL( pageTest $test ) {
-       $used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false );
-       $retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL . $test->getPagePath();
-       foreach ( $test->getParams() as $param => $value ) {
-               if ( !$used_question_mark ) {
-                       $retval .= "?";
-                       $used_question_mark = true;
-               }
-               else {
-                       $retval .= "&";
-               }
-               $retval .= $param . "=" . urlencode( $value );
-       }
-       return $retval;
-}
-
-
-/**
- ** Saves a plain-text human-readable version of a test.
- */
-function saveTestAsText( pageTest $test, $filename ) {
-       $str = "Test: " . $test->getPagePath();
-       foreach ( $test->getParams() as $param => $value ) {
-               $str .= "\n$param: $value";
-       }
-       $str .= "\nGet-to-post URL: " . getAsURL( $test ) . "\n";
-       saveFile( $str, $filename );
-}
-
-
-/**
- ** Saves a test as a standalone basic PHP script that shows this one problem.
- **        Resulting script requires PHP-Curl be installed in order to work.
- */
-function saveTestAsPHP( pageTest $test, $filename ) {
-       $str = "<?php\n"
-               . "\$params = " . var_export( escapeForCurl( $test->getParams() ), true ) . ";\n"
-               . "\$ch = curl_init();\n"
-               . "curl_setopt(\$ch, CURLOPT_POST, 1);\n"
-               . "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n"
-               . "curl_setopt(\$ch, CURLOPT_URL, " . var_export( WIKI_BASE_URL . $test->getPagePath(), true ) . ");\n"
-               . "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n"
-               .  ( $test->getCookie() ? "curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export( $test->getCookie(), true ) . ");\n" : "" )
-               . "\$result=curl_exec(\$ch);\n"
-               . "curl_close (\$ch);\n"
-               . "print \$result;\n"
-               . "\n";
-       saveFile( $str, $filename );
-}
-
-/**
- * Escapes a value so that it can be used on the command line by Curl.
- *        Specifically, "<" and "@" need to be escaped if they are the first character,
- *        otherwise  curl interprets these as meaning that we want to insert a file.
- * @param $input_params array
- * @return array
- */
-function escapeForCurl( array $input_params ) {
-       $output_params = array();
-       foreach ( $input_params as $param => $value ) {
-               if ( strlen( $value ) > 0 && ( $value[0] == "@" || $value[0] == "<" ) ) {
-                       $value = "\\" . $value;
-               }
-               $output_params[$param] = $value;
-       }
-       return $output_params;
-}
-
-
-/**
- ** Saves a test as a standalone CURL shell script that shows this one problem.
- **        Resulting script requires standalone Curl be installed in order to work.
- */
-function saveTestAsCurl( pageTest $test, $filename ) {
-       $str = "#!/bin/bash\n"
-               . "curl --silent --include --globoff \\\n"
-               . ( $test->getCookie() ? " --cookie " . escapeshellarg( $test->getCookie() ) . " \\\n" : "" );
-       foreach ( escapeForCurl( $test->getParams() ) as $param => $value ) {
-               $str .= " -F " . escapeshellarg( $param ) . "=" . escapeshellarg( $value ) . " \\\n";
-       }
-       $str .= " " . escapeshellarg( WIKI_BASE_URL . $test->getPagePath() ); // beginning space matters.
-       $str .= "\n";
-       saveFile( $str, $filename );
-       chmod( $filename, 0755 ); // make executable
-}
-
-
-/**
- ** Saves the internal data structure to file.
- */
-function saveTestData ( pageTest $test, $filename ) {
-       saveFile( serialize( $test ),  $filename );
-}
-
-
-/**
- ** saves a test in the various formats.
- */
-function saveTest( pageTest $test, $testname ) {
-       $base_name = DIRECTORY . "/" . $testname;
-       saveTestAsText( $test, $base_name . INFO_FILE );
-       saveTestAsPHP ( $test, $base_name . PHP_TEST );
-       saveTestAsCurl( $test, $base_name . CURL_TEST );
-       saveTestData  ( $test, $base_name . DATA_FILE );
-}
-
-// ////////////////// MEDIAWIKI OUTPUT /////////////////////////
-
-/**
- * Asks MediaWiki for the HTML output of a test.
- * @param $test pageTest
- * @return string
- */
-function wikiTestOutput( pageTest $test ) {
-
-       $ch = curl_init();
-
-       // specify the cookie, if required.
-       if ( $test->getCookie() ) {
-               curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() );
-       }
-       curl_setopt( $ch, CURLOPT_POST, 1 );                          // save form using a POST
-
-       $params = escapeForCurl( $test->getParams() );
-       curl_setopt( $ch, CURLOPT_POSTFIELDS, $params );             // load the POST variables
-
-       curl_setopt( $ch, CURLOPT_URL, WIKI_BASE_URL . $test->getPagePath() );  // set url to post to
-       curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );                 // return into a variable
-
-       $result = curl_exec ( $ch );
-
-       // if we encountered an error, then say so, and return an empty string.
-       if ( curl_error( $ch ) ) {
-               print "\nCurl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch );
-               $result = "";
-       }
-
-       curl_close ( $ch );
-
-       return $result;
-}
-
-
-// ////////////////// HTML VALIDATION /////////////////////////
-
-/**
- * Asks the validator whether this is valid HTML, or not.
- * @param $text string
- * @return array
- */
-function validateHTML( $text ) {
-
-       $params = array ( "fragment"   => $text );
-
-       $ch = curl_init();
-
-       curl_setopt( $ch, CURLOPT_POST, 1 );                    // save form using a POST
-       curl_setopt( $ch, CURLOPT_POSTFIELDS, $params );        // load the POST variables
-       curl_setopt( $ch, CURLOPT_URL, VALIDATOR_URL );         // set url to post to
-       curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );           // return into a variable
-
-       $result = curl_exec ( $ch );
-
-       // if we encountered an error, then log it, and exit.
-       if ( curl_error( $ch ) ) {
-               trigger_error( "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) );
-               print "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) . " - exiting.\n";
-               exit( 1 );
-       }
-
-       curl_close ( $ch );
-
-       $valid = ( strpos( $result, "Failed validation" ) === false );
-
-       return array( $valid, $result );
-}
-
-/**
- * Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
- * @param $name
- * @return bool
- */
-function tidyCheckFile( $name ) {
-       $file = DIRECTORY . "/" . $name;
-       $command = PATH_TO_TIDY . " -output /tmp/out.html -quiet $file 2>&1";
-       $x = `$command`;
-
-       // Look for the most interesting Tidy errors and warnings.
-       if (   strpos( $x, "end of file while parsing attributes" ) !== false
-                       || strpos( $x, "attribute with missing trailing quote mark" ) !== false
-                       || strpos( $x, "missing '>' for end of tag" ) !== false
-                       || strpos( $x, "Error:" ) !== false ) {
-               print "\nTidy found something - view details with: $command";
-               return false;
-       } else {
-               return true;
-       }
-}
-
-/**
- ** Returns whether or not an database error log file has changed in size since
- **        the last time this was run. This is used to tell if a test caused a DB error.
- * @return bool
- */
-function dbErrorLogged() {
-       static $filesize;
-
-       // first time running this function
-       if ( !isset( $filesize ) ) {
-               // create log if it does not exist
-               if ( DB_ERROR_LOG_FILE && !file_exists( DB_ERROR_LOG_FILE ) ) {
-                       saveFile( '', DB_ERROR_LOG_FILE );
-               }
-               $filesize = filesize( DB_ERROR_LOG_FILE );
-               return false;
-       }
-
-       $newsize = filesize( DB_ERROR_LOG_FILE );
-       // if the log has grown, then assume the current test caused it.
-       if ( $newsize != $filesize ) {
-               $filesize = $newsize;
-               return true;
-       }
-
-       return false;
-}
-
-// //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
-
-/**
- * takes a page test, and runs it and tests it for problems in the output.
- *        Returns: False on finding a problem, or True on no problems being found.
- * @param $test pageTest
- * @param $testname
- * @param $can_overwrite bool
- * @return bool
- */
-function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) {
-
-       // by default don't overwrite a previous test of the same name.
-       while ( ! $can_overwrite && file_exists( DIRECTORY . "/" . $testname . DATA_FILE ) ) {
-               $testname .= "-" . mt_rand( 0, 9 );
-       }
-
-       $filename = DIRECTORY . "/" . $testname . DATA_FILE;
-
-       // Store the time before and after, to find slow pages.
-       $before = microtime( true );
-
-       // Get MediaWiki to give us the output of this test.
-       $wiki_preview = wikiTestOutput( $test );
-
-       $after = microtime( true );
-
-       // if we received no response, then that's interesting.
-       if ( $wiki_preview == "" ) {
-               print "\nNo response received for: $filename";
-               return false;
-       }
-
-       // save output HTML to file.
-       $html_file = DIRECTORY . "/" . $testname . HTML_FILE;
-       saveFile( $wiki_preview,  $html_file );
-
-       // if there were PHP errors in the output, then that's interesting too.
-       if (       strpos( $wiki_preview, "<b>Warning</b>: "        ) !== false
-                       || strpos( $wiki_preview, "<b>Fatal error</b>: "    ) !== false
-                       || strpos( $wiki_preview, "<b>Notice</b>: "         ) !== false
-                       || strpos( $wiki_preview, "<b>Error</b>: "          ) !== false
-                       || strpos( $wiki_preview, "<b>Strict Standards:</b>" ) !== false
-                       ) {
-               $error = substr( $wiki_preview, strpos( $wiki_preview, "</b>:" ) + 7, 50 );
-               // Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224
-               if ( $error != "Unknown: The session id contains illegal character" ) {
-                       print "\nPHP error/warning/notice in HTML output: $html_file ; $error";
-                       return false;
-               }
-       }
-
-       // if there was a MediaWiki Backtrace message in the output, then that's also interesting.
-       if ( strpos( $wiki_preview, "Backtrace:" ) !== false ) {
-               print "\nInternal MediaWiki error in HTML output: $html_file";
-               return false;
-       }
-
-       // if there was a Parser error comment in the output, then that's potentially interesting.
-       if ( strpos( $wiki_preview, "!-- ERR" ) !== false ) {
-               print "\nParser Error comment in HTML output: $html_file";
-               return false;
-       }
-
-       // if a database error was logged, then that's definitely interesting.
-       if ( dbErrorLogged() ) {
-               print "\nDatabase Error logged for: $filename";
-               return false;
-       }
-
-       // validate result
-       $valid = true;
-       if ( VALIDATE_ON_WEB ) {
-               list ( $valid, $validator_output ) = validateHTML( $wiki_preview );
-               if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html";
-       }
-
-       // Get tidy to check the page, unless we already know it produces non-(X)HTML output.
-       if ( $test->tidyValidate() ) {
-               $valid = tidyCheckFile( $testname . HTML_FILE ) && $valid;
-       }
-
-       // if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?)
-       if ( ( $after - $before ) >= 2 ) {
-               print "\nParticularly slow to render (" . round( $after - $before, 2 ) . " seconds): $filename";
-               return false;
-       }
-
-       if ( $valid ) {
-               // Remove temp HTML file if test was valid:
-               unlink( $html_file );
-       } elseif ( VALIDATE_ON_WEB ) {
-               saveFile( $validator_output,   DIRECTORY . "/" . $testname . ".validator_output.html" );
-       }
-
-       return $valid;
-}
-
-
-// ///////////////// RERUNNING OLD TESTS ///////////////////
-
-/**
- ** We keep our failed tests so that they can be rerun.
- **        This function does that retesting.
- */
-function rerunPreviousTests() {
-       print "Retesting previously found problems.\n";
-
-       $dir_contents = scandir ( DIRECTORY );
-
-       // sort file into the order a normal person would use.
-       natsort ( $dir_contents );
-
-       foreach ( $dir_contents as $file ) {
-
-               // if file is not a test, then skip it.
-               // Note we need to escape any periods or will be treated as "any character".
-               $matches = array();
-               if ( !preg_match( "/(.*)" . str_replace( ".", "\.", DATA_FILE ) . "$/", $file, $matches ) ) continue;
-
-               // reload the test.
-               $full_path = DIRECTORY . "/" . $file;
-               $test = unserialize( file_get_contents( $full_path ) );
-
-               // if this is not a valid test, then skip it.
-               if ( ! $test instanceof pageTest ) {
-                       print "\nSkipping invalid test - $full_path";
-                       continue;
-               }
-
-               // The date format is in Apache log format, which makes it easier to locate
-               // which retest caused which error in the Apache logs (only happens usually if
-               // apache segfaults).
-               if ( !QUIET ) print "[" . date ( "D M d H:i:s Y" ) . "] Retesting $file (" . get_class( $test ) . ")";
-
-               // run test
-               $testname = $matches[1];
-               $valid = runWikiTest( $test, $testname, true );
-
-               if ( !$valid ) {
-                       saveTest( $test, $testname );
-                       if ( QUIET ) {
-                               print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
-                       } else {
-                               print "\n";
-                       }
-               }
-               else {
-                       if ( !QUIET ) print "\r";
-                       if ( DELETE_PASSED_RETESTS ) {
-                               $prefix = DIRECTORY . "/" . $testname;
-                               if ( is_file( $prefix . DATA_FILE ) ) unlink( $prefix . DATA_FILE );
-                               if ( is_file( $prefix . PHP_TEST ) ) unlink( $prefix . PHP_TEST );
-                               if ( is_file( $prefix . CURL_TEST ) ) unlink( $prefix . CURL_TEST );
-                               if ( is_file( $prefix . INFO_FILE ) ) unlink( $prefix . INFO_FILE );
-                       }
-               }
-       }
-
-       print "\nDone retesting.\n";
-}
-
-
-// ////////////////////  MAIN LOOP  ////////////////////////
-
-
-// first check whether CURL is installed, because sometimes it's not.
-if ( ! function_exists( 'curl_init' ) ) {
-       die( "Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n" );
-}
-
-// Initialization of types. wikiFuzz doesn't have a constructor because we want to
-// access it staticly and not have any globals.
-wikiFuzz::$types = array_keys( wikiFuzz::$data );
-
-// Make directory if doesn't exist
-if ( !is_dir( DIRECTORY ) ) {
-       mkdir ( DIRECTORY, 0700 );
-}
-// otherwise, we first retest the things that we have found in previous runs
-elseif ( RERUN_OLD_TESTS ) {
-       rerunPreviousTests();
-}
-
-// main loop.
-$start_time = date( "U" );
-$num_errors = 0;
-if ( !QUIET ) {
-       print "Beginning main loop. Results are stored in the " . DIRECTORY . " directory.\n";
-       print "Press CTRL+C to stop testing.\n";
-}
-
-for ( $count = 0; true; $count++ ) {
-       if ( !QUIET ) {
-               // spinning progress indicator.
-               switch( $count % 4 ) {
-                       case '0': print "\r/";  break;
-                       case '1': print "\r-";  break;
-                       case '2': print "\r\\"; break;
-                       case '3': print "\r|";  break;
-               }
-               print " $count";
-       }
-
-       // generate a page test to run.
-       $test = selectPageTest( $count );
-
-       $mins = ( date( "U" ) - $start_time ) / 60;
-       if ( !QUIET && $mins > 0 ) {
-               print ".  $num_errors poss errors. "
-                       . floor( $mins ) . " mins. "
-                       . round ( $count / $mins, 0 ) . " tests/min. "
-                       . get_class( $test ); // includes the current test name.
-       }
-
-       // run this test against MediaWiki, and see if the output was valid.
-       $testname = $count;
-       $valid = runWikiTest( $test, $testname, false );
-
-       // save the failed test
-       if ( ! $valid ) {
-               if ( QUIET ) {
-                       print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
-               } else {
-                       print "\n";
-               }
-               saveTest( $test, $testname );
-               $num_errors += 1;
-       } elseif ( KEEP_PASSED_TESTS ) {
-               // print current time, with microseconds (matches "strace" format), and the test name.
-               print " " . date( "H:i:s." ) . substr( current( explode( " ", microtime() ) ), 2 ) . " " . $testname;
-               saveTest( $test, $testname );
-       }
-
-       // stop if we have reached max number of errors.
-       if ( defined( "MAX_ERRORS" ) && $num_errors >= MAX_ERRORS ) {
-               break;
-       }
-
-       // stop if we have reached max number of mins runtime.
-       if ( defined( "MAX_RUNTIME" ) && $mins >= MAX_RUNTIME ) {
-               break;
-       }
-}
index 0b21a1f..ab28c8b 100644 (file)
@@ -125,7 +125,6 @@ class GenerateSitemap extends Maintenance {
         */
        public $findex;
 
-
        /**
         * A resource pointing to a sitemap file
         *
index e081c20..dadc84a 100644 (file)
@@ -36,7 +36,7 @@ if ( count( $args ) < 1 || isset( $options['help'] ) ) {
        if ( is_file( $filename ) ) {
 
                $title = isset( $options['title'] ) ? $options['title'] : titleFromFilename( $filename );
-               $title = Title::newFromURL( $title );
+               $title = Title::newFromText( $title );
 
                if ( is_object( $title ) ) {
 
index f96902d..c595980 100644 (file)
@@ -9,6 +9,7 @@
                                        "mw.Map",
                                        "mw.Message",
                                        "mw.loader",
+                                       "mw.loader.store",
                                        "mw.log",
                                        "mw.html",
                                        "mw.html.Cdata",
index 12458ee..e6e0f65 100644 (file)
@@ -21,6 +21,7 @@
                "../../resources/mediawiki.action/mediawiki.action.view.postEdit.js",
                "../../resources/mediawiki.page/mediawiki.page.startup.js",
                "../../resources/mediawiki.api",
-               "../../resources/jquery/jquery.localize.js"
+               "../../resources/jquery/jquery.localize.js",
+               "../../resources/jquery/jquery.spinner.js"
        ]
 }
index 7910ec8..4bb8369 100644 (file)
@@ -5,6 +5,7 @@
 
 /**
  * @method ajax
+ * @static
  * @source <http://api.jquery.com/jQuery.ajax/>
  * @return {jqXHR}
  */
index e9d8c86..f9390f6 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-if ( !defined( 'MEDIAWIKI' ) ) {
-       die();
-}
 /**
  * Statistic output classes.
  *
@@ -27,57 +24,77 @@ if ( !defined( 'MEDIAWIKI' ) ) {
  */
 
 /** A general output object. Need to be overriden */
-class statsOutput {
+class StatsOutput {
        function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
-               return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
+               wfSuppressWarnings();
+               $return = sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
+               wfRestoreWarnings();
+               return $return;
        }
 
        # Override the following methods
        function heading() {
        }
+
        function footer() {
        }
+
        function blockstart() {
        }
+
        function blockend() {
        }
+
        function element( $in, $heading = false ) {
        }
 }
 
 /** Outputs WikiText */
-class wikiStatsOutput extends statsOutput {
+class WikiStatsOutput extends StatsOutput {
        function heading() {
                global $wgDummyLanguageCodes;
                $version = SpecialVersion::getVersion( 'nodb' );
                echo "'''Statistics are based on:''' <code>" . $version . "</code>\n\n";
-               echo "'''Note:''' These statistics can be generated by running <code>php maintenance/language/transstat.php</code>.\n\n";
-               echo "For additional information on specific languages (the message names, the actual problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n";
+               echo "'''Note:''' These statistics can be generated by running " .
+                       "<code>php maintenance/language/transstat.php</code>.\n\n";
+               echo "For additional information on specific languages (the message names, the actual " .
+                       "problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n";
                echo 'English (en) is excluded because it is the default localization';
                if ( is_array( $wgDummyLanguageCodes ) ) {
                        $dummyCodes = array();
                        foreach ( $wgDummyLanguageCodes as $dummyCode => $correctCode ) {
                                $dummyCodes[] = Language::fetchLanguageName( $dummyCode ) . ' (' . $dummyCode . ')';
                        }
-                       echo ', as well as the following languages that are not intended for system message translations, usually because they redirect to other language codes: ' . implode( ', ', $dummyCodes );
+                       echo ', as well as the following languages that are not intended for ' .
+                               'system message translations, usually because they redirect to other ' .
+                               'language codes: ' . implode( ', ', $dummyCodes );
                }
                echo ".\n\n"; # dot to end sentence
-               echo '{| class="sortable wikitable" border="2" style="background-color: #F9F9F9; border: 1px #AAAAAA solid; border-collapse: collapse; clear:both; width:100%;"' . "\n";
+               echo '{| class="sortable wikitable" border="2" style="background-color: #F9F9F9; ' .
+                       'border: 1px #AAAAAA solid; border-collapse: collapse; clear:both; width:100%;"' . "\n";
        }
+
        function footer() {
                echo "|}\n";
        }
+
        function blockstart() {
                echo "|-\n";
        }
+
        function blockend() {
                echo '';
        }
+
        function element( $in, $heading = false ) {
                echo ( $heading ? '!' : '|' ) . "$in\n";
        }
+
        function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
-               $v = @round( 255 * $subset / $total );
+               wfSuppressWarnings();
+               $v = round( 255 * $subset / $total );
+               wfRestoreWarnings();
+
                if ( $revert ) {
                        # Weigh reverse with factor 20 so coloring takes effect more quickly as
                        # this option is used solely for reporting 'bad' percentages.
@@ -100,25 +117,28 @@ class wikiStatsOutput extends statsOutput {
                $color = $red . $green . $blue;
 
                $percent = parent::formatPercent( $subset, $total, $revert, $accuracy );
+
                return 'style="background-color:#' . $color . ';"|' . $percent;
        }
 }
 
 /** Output text. To be used on a terminal for example. */
-class textStatsOutput extends statsOutput {
+class TextStatsOutput extends StatsOutput {
        function element( $in, $heading = false ) {
                echo $in . "\t";
        }
+
        function blockend() {
                echo "\n";
        }
 }
 
 /** csv output. Some people love excel */
-class csvStatsOutput extends statsOutput {
+class CsvStatsOutput extends StatsOutput {
        function element( $in, $heading = false ) {
                echo $in . ";";
        }
+
        function blockend() {
                echo "\n";
        }
index 381ddae..5d48244 100644 (file)
@@ -67,8 +67,7 @@ if ( $runTest ) {
        $messagesFileC = $messagesDir . 'Messages' . $langCodeFC . '.php';
        if ( file_exists( $messagesFile ) && file_exists( $messagesFileC ) ) {
                $run = true;
-       }
-       else {
+       } else {
                echo "Messages file(s) could not be found.\nMake sure both files are exists.\n";
        }
 }
index 4b49ada..ac70ead 100644 (file)
@@ -89,7 +89,7 @@ class CheckLanguageCLI {
                        $this->output = $options['output'];
                }
 
-               $this->L = new languages( $this->includeExif );
+               $this->L = new Languages( $this->includeExif );
        }
 
        /**
@@ -182,21 +182,25 @@ class CheckLanguageCLI {
                return array(
                        'untranslated' => '$1 message(s) of $2 are not translated to $3, but exist in en:',
                        'duplicate' => '$1 message(s) of $2 are translated the same in en and $3:',
-                       'obsolete' => '$1 message(s) of $2 do not exist in en or are in the ignore list, but exist in $3:',
+                       'obsolete' =>
+                               '$1 message(s) of $2 do not exist in en or are in the ignore list, but exist in $3:',
                        'variables' => '$1 message(s) of $2 in $3 don\'t match the variables used in en:',
                        'plural' => '$1 message(s) of $2 in $3 don\'t use {{plural}} while en uses:',
                        'empty' => '$1 message(s) of $2 in $3 are empty or -:',
                        'whitespace' => '$1 message(s) of $2 in $3 have trailing whitespace:',
                        'xhtml' => '$1 message(s) of $2 in $3 contain illegal XHTML:',
-                       'chars' => '$1 message(s) of $2 in $3 include hidden chars which should not be used in the messages:',
+                       'chars' =>
+                               '$1 message(s) of $2 in $3 include hidden chars which should not be used in the messages:',
                        'links' => '$1 message(s) of $2 in $3 have problematic link(s):',
                        'unbalanced' => '$1 message(s) of $2 in $3 have unbalanced {[]}:',
                        'namespace' => '$1 namespace name(s) of $2 are not translated to $3, but exist in en:',
-                       'projecttalk' => '$1 namespace name(s) and alias(es) in $3 are project talk namespaces without the parameter:',
+                       'projecttalk' =>
+                               '$1 namespace name(s) and alias(es) in $3 are project talk namespaces without the parameter:',
                        'magic' => '$1 magic word(s) of $2 are not translated to $3, but exist in en:',
                        'magic-old' => '$1 magic word(s) of $2 do not exist in en, but exist in $3:',
                        'magic-over' => '$1 magic word(s) of $2 in $3 do not contain the original en word(s):',
-                       'magic-case' => '$1 magic word(s) of $2 in $3 change the case-sensitivity of the original en word:',
+                       'magic-case' =>
+                               '$1 magic word(s) of $2 in $3 change the case-sensitivity of the original en word:',
                        'special' => '$1 special page alias(es) of $2 are not translated to $3, but exist in en:',
                        'special-old' => '$1 special page alias(es) of $2 do not exist in en, but exist in $3:',
                );
@@ -216,35 +220,49 @@ Parameters:
        --all: Check all customized languages.
        --level: Show the following display level (default: 2):
                * 0: Skip the checks (useful for checking syntax).
-               * 1: Show only the stub headers and number of wrong messages, without list of messages.
-               * 2: Show only the headers and the message keys, without the message values.
-               * 3: Show both the headers and the complete messages, with both keys and values.
+               * 1: Show only the stub headers and number of wrong messages, without
+                    list of messages.
+               * 2: Show only the headers and the message keys, without the message
+                    values.
+               * 3: Show both the headers and the complete messages, with both keys and
+                    values.
        --links: Link the message values (default off).
        --prefix: prefix to add to links.
-       --wikilang: For the links, what is the content language of the wiki to display the output in (default en).
-       --noexif: Do not check for Exif messages (a bit hard and boring to translate), if you know
-               that they are currently not translated and want to focus on other problems (default off).
+       --wikilang: For the links, what is the content language of the wiki to
+           display the output in (default en).
+       --noexif: Do not check for Exif messages (a bit hard and boring to
+           translate), if you know what they are currently not translated and want
+           to focus on other problems (default off).
        --whitelist: Do only the following checks (form: code,code).
        --blacklist: Do not do the following checks (form: code,code).
-       --easy: Do only the easy checks, which can be treated by non-speakers of the language.
-
-Check codes (ideally, all of them should result 0; all the checks are executed by default (except language-specific check blacklists in checkLanguage.inc):
-       * untranslated: Messages which are required to translate, but are not translated.
-       * duplicate: Messages which translation equal to fallback
-       * obsolete: Messages which are untranslatable or do not exist, but are translated.
-       * variables: Messages without variables which should be used, or with variables which should not be used.
+       --easy: Do only the easy checks, which can be treated by non-speakers of
+           the language.
+
+Check codes (ideally, all of them should result 0; all the checks are executed
+by default (except language-specific check blacklists in checkLanguage.inc):
+       * untranslated: Messages which are required to translate, but are not
+         translated.
+       * duplicate: Messages which translation equal to fallback.
+       * obsolete: Messages which are untranslatable or do not exist, but are
+         translated.
+       * variables: Messages without variables which should be used, or with
+         variables which should not be used.
        * empty: Empty messages and messages that contain only -.
        * whitespace: Messages which have trailing whitespace.
-       * xhtml: Messages which are not well-formed XHTML (checks only few common errors).
+       * xhtml: Messages which are not well-formed XHTML (checks only few common
+         errors).
        * chars: Messages with hidden characters.
        * links: Messages which contains broken links to pages (does not find all).
-       * unbalanced: Messages which contains unequal numbers of opening {[ and closing ]}.
+       * unbalanced: Messages which contains unequal numbers of opening {[ and
+         closing ]}.
        * namespace: Namespace names that were not translated.
-       * projecttalk: Namespace names and aliases where the project talk does not contain $1.
+       * projecttalk: Namespace names and aliases where the project talk does not
+         contain $1.
        * magic: Magic words that were not translated.
        * magic-old: Magic words which do not exist.
        * magic-over: Magic words that override the original English word.
-       * magic-case: Magic words whose translation changes the case-sensitivity of the original English word.
+       * magic-case: Magic words whose translation changes the case-sensitivity of
+         the original English word.
        * special: Special page names that were not translated.
        * special-old: Special page names which do not exist.
 
@@ -291,6 +309,17 @@ ENDS;
                                $this->results[$this->code] = $this->checkLanguage( $this->code );
                        }
                }
+
+               $results = $this->results;
+               foreach ( $results as $code => $checks ) {
+                       foreach ( $checks as $check => $messages ) {
+                               foreach ( $messages as $key => $details ) {
+                                       if ( $this->isCheckBlacklisted( $check, $code, $key ) ) {
+                                               unset( $this->results[$code][$check][$key] );
+                                       }
+                               }
+                       }
+               }
        }
 
        /**
@@ -298,9 +327,53 @@ ENDS;
         * @return array The list of checks which should not be executed.
         */
        protected function getCheckBlacklist() {
+               static $blacklist = null;
+
+               if ( $blacklist !== null ) {
+                       return $blacklist;
+               }
+
+               // @codingStandardsIgnoreStart Ignore that globals should have a "wg" prefix.
                global $checkBlacklist;
+               // @codingStandardsIgnoreEnd
+
+               $blacklist = $checkBlacklist;
+
+               wfRunHooks( 'LocalisationChecksBlacklist', array( &$blacklist ) );
+
+               return $blacklist;
+       }
+
+       /**
+        * Verify whether a check is blacklisted.
+        *
+        * @param string $check Check name
+        * @param string $code Language code
+        * @param string|bool $message Message name, or False for a whole language
+        * @return bool Whether the check is blacklisted
+        */
+       protected function isCheckBlacklisted( $check, $code, $message ) {
+               $blacklist = $this->getCheckBlacklist();
+
+               foreach ( $blacklist as $item ) {
+                       if ( isset( $item['check'] ) && $check !== $item['check'] ) {
+                               continue;
+                       }
 
-               return $checkBlacklist;
+                       if ( isset( $item['code'] ) && !in_array( $code, $item['code'] ) ) {
+                               continue;
+                       }
+
+                       if ( isset( $item['message'] ) &&
+                               ( $message === false || !in_array( $message, $item['message'] ) )
+                       ) {
+                               continue;
+                       }
+
+                       return true;
+               }
+
+               return false;
        }
 
        /**
@@ -319,11 +392,8 @@ ENDS;
                }
 
                $checkFunctions = $this->getChecks();
-               $checkBlacklist = $this->getCheckBlacklist();
                foreach ( $this->checks as $check ) {
-                       if ( isset( $checkBlacklist[$code] ) &&
-                               in_array( $check, $checkBlacklist[$code] )
-                       ) {
+                       if ( $this->isCheckBlacklisted( $check, $code, false ) ) {
                                $results[$check] = array();
                                continue;
                        }
@@ -407,7 +477,8 @@ ENDS;
         */
        function outputWiki() {
                $detailText = '';
-               $rows[] = '! Language !! Code !! Total !! ' . implode( ' !! ', array_diff( $this->checks, $this->nonMessageChecks() ) );
+               $rows[] = '! Language !! Code !! Total !! ' .
+                       implode( ' !! ', array_diff( $this->checks, $this->nonMessageChecks() ) );
                foreach ( $this->results as $code => $results ) {
                        $detailTextForLang = "==$code==\n";
                        $numbers = array();
@@ -447,6 +518,7 @@ ENDS;
                $tableRows = implode( "\n|-\n", $rows );
 
                $version = SpecialVersion::getVersion( 'nodb' );
+               // @codingStandardsIgnoreStart Long line.
                echo <<<EOL
 '''Check results are for:''' <code>$version</code>
 
@@ -458,6 +530,7 @@ $tableRows
 $detailText
 
 EOL;
+               // @codingStandardsIgnoreEnd
        }
 
        /**
@@ -539,19 +612,19 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
                if ( $extension == 'all' ) {
                        foreach ( MessageGroups::singleton()->getGroups() as $group ) {
                                if ( strpos( $group->getId(), 'ext-' ) === 0 && !$group->isMeta() ) {
-                                       $this->extensions[] = new extensionLanguages( $group );
+                                       $this->extensions[] = new ExtensionLanguages( $group );
                                }
                        }
                } elseif ( $extension == 'wikimedia' ) {
                        $wikimedia = MessageGroups::getGroup( 'ext-0-wikimedia' );
                        foreach ( $wikimedia->wmfextensions() as $extension ) {
                                $group = MessageGroups::getGroup( $extension );
-                               $this->extensions[] = new extensionLanguages( $group );
+                               $this->extensions[] = new ExtensionLanguages( $group );
                        }
                } elseif ( $extension == 'flaggedrevs' ) {
                        foreach ( MessageGroups::singleton()->getGroups() as $group ) {
                                if ( strpos( $group->getId(), 'ext-flaggedrevs-' ) === 0 && !$group->isMeta() ) {
-                                       $this->extensions[] = new extensionLanguages( $group );
+                                       $this->extensions[] = new ExtensionLanguages( $group );
                                }
                        }
                } else {
@@ -559,7 +632,7 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
                        foreach ( $extensions as $extension ) {
                                $group = MessageGroups::getGroup( 'ext-' . $extension );
                                if ( $group ) {
-                                       $extension = new extensionLanguages( $group );
+                                       $extension = new ExtensionLanguages( $group );
                                        $this->extensions[] = $extension;
                                } else {
                                        print "No such extension $extension.\n";
@@ -603,34 +676,50 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
         */
        protected function help() {
                return <<<ENDS
-Run this script to check the status of a specific language in extensions, or all of them.
-Command line settings are in form --parameter[=value], except for the first one.
+Run this script to check the status of a specific language in extensions, or
+all of them. Command line settings are in form --parameter[=value], except for
+the first one.
 Parameters:
-       * First parameter (mandatory): Extension name, multiple extension names (separated by commas), "all" for all the extensions, "wikimedia" for extensions used by Wikimedia or "flaggedrevs" for all FLaggedRevs extension messages.
+       * First parameter (mandatory): Extension name, multiple extension names
+         (separated by commas), "all" for all the extensions, "wikimedia" for
+         extensions used by Wikimedia or "flaggedrevs" for all FLaggedRevs
+         extension messages.
        * lang: Language code (default: the installation default language).
        * help: Show this help.
        * level: Show the following display level (default: 2).
        * links: Link the message values (default off).
-       * wikilang: For the links, what is the content language of the wiki to display the output in (default en).
+       * wikilang: For the links, what is the content language of the wiki to
+         display the output in (default en).
        * whitelist: Do only the following checks (form: code,code).
        * blacklist: Do not perform the following checks (form: code,code).
-       * easy: Do only the easy checks, which can be treated by non-speakers of the language.
-Check codes (ideally, all of them should result 0; all the checks are executed by default (except language-specific check blacklists in checkLanguage.inc):
-       * untranslated: Messages which are required to translate, but are not translated.
-       * duplicate: Messages which translation equal to fallback
+       * easy: Do only the easy checks, which can be treated by non-speakers of
+         the language.
+
+Check codes (ideally, all of them should result 0; all the checks are executed
+by default (except language-specific check blacklists in checkLanguage.inc):
+       * untranslated: Messages which are required to translate, but are not
+         translated.
+       * duplicate: Messages which translation equal to fallback.
        * obsolete: Messages which are untranslatable, but translated.
-       * variables: Messages without variables which should be used, or with variables which should not be used.
+       * variables: Messages without variables which should be used, or with
+         variables which should not be used.
        * empty: Empty messages.
        * whitespace: Messages which have trailing whitespace.
-       * xhtml: Messages which are not well-formed XHTML (checks only few common errors).
+       * xhtml: Messages which are not well-formed XHTML (checks only few common
+         errors).
        * chars: Messages with hidden characters.
        * links: Messages which contains broken links to pages (does not find all).
-       * unbalanced: Messages which contains unequal numbers of opening {[ and closing ]}.
+       * unbalanced: Messages which contains unequal numbers of opening {[ and
+         closing ]}.
+
 Display levels (default: 2):
        * 0: Skip the checks (useful for checking syntax).
-       * 1: Show only the stub headers and number of wrong messages, without list of messages.
-       * 2: Show only the headers and the message keys, without the message values.
-       * 3: Show both the headers and the complete messages, with both keys and values.
+       * 1: Show only the stub headers and number of wrong messages, without list
+         of messages.
+       * 2: Show only the headers and the message keys, without the message
+         values.
+       * 3: Show both the headers and the complete messages, with both keys and
+         values.
 
 ENDS;
        }
@@ -675,52 +764,21 @@ ENDS;
        }
 }
 
-# Blacklist some checks for some languages
+// Blacklist some checks for some languages or some messages
+// Possible keys of the sub arrays are: 'check', 'code' and 'message'.
 $checkBlacklist = array(
-#'code'        => array( 'check1', 'check2' ... )
-       'az' => array( 'plural' ),
-       'bo' => array( 'plural' ),
-       'cdo' => array( 'plural' ),
-       'dz' => array( 'plural' ),
-       'id' => array( 'plural' ),
-       'fa' => array( 'plural' ),
-       'gan' => array( 'plural' ),
-       'gan-hans' => array( 'plural' ),
-       'gan-hant' => array( 'plural' ),
-       'gn' => array( 'plural' ),
-       'hak' => array( 'plural' ),
-       'hu' => array( 'plural' ),
-       'ja' => array( 'plural' ), // Does not use plural
-       'jv' => array( 'plural' ),
-       'ka' => array( 'plural' ),
-       'kk-arab' => array( 'plural' ),
-       'kk-cyrl' => array( 'plural' ),
-       'kk-latn' => array( 'plural' ),
-       'km' => array( 'plural' ),
-       'kn' => array( 'plural' ),
-       'ko' => array( 'plural' ),
-       'lzh' => array( 'plural' ),
-       'mn' => array( 'plural' ),
-       'ms' => array( 'plural' ),
-       'my' => array( 'plural', 'chars' ), // Uses a lot zwnj
-       'sah' => array( 'plural' ),
-       'sq' => array( 'plural' ),
-       'tet' => array( 'plural' ),
-       'th' => array( 'plural' ),
-       'to' => array( 'plural' ),
-       'tr' => array( 'plural' ),
-       'vi' => array( 'plural' ),
-       'wuu' => array( 'plural' ),
-       'xmf' => array( 'plural' ),
-       'yo' => array( 'plural' ),
-       'yue' => array( 'plural' ),
-       'zh' => array( 'plural' ),
-       'zh-classical' => array( 'plural' ),
-       'zh-cn' => array( 'plural' ),
-       'zh-hans' => array( 'plural' ),
-       'zh-hant' => array( 'plural' ),
-       'zh-hk' => array( 'plural' ),
-       'zh-sg' => array( 'plural' ),
-       'zh-tw' => array( 'plural' ),
-       'zh-yue' => array( 'plural' ),
+       array(
+               'check' => 'plural',
+               'code' => array( 'az', 'bo', 'cdo', 'dz', 'id', 'fa', 'gan', 'gan-hans',
+                       'gan-hant', 'gn', 'hak', 'hu', 'ja', 'jv', 'ka', 'kk-arab',
+                       'kk-cyrl', 'kk-latn', 'km', 'kn', 'ko', 'lzh', 'mn', 'ms',
+                       'my', 'sah', 'sq', 'tet', 'th', 'to', 'tr', 'vi', 'wuu', 'xmf',
+                       'yo', 'yue', 'zh', 'zh-classical', 'zh-cn', 'zh-hans',
+                       'zh-hant', 'zh-hk', 'zh-sg', 'zh-tw', 'zh-yue'
+               ),
+       ),
+       array(
+               'check' => 'chars',
+               'code' => array( 'my' ),
+       ),
 );
index 95a7154..1cb24ab 100644 (file)
@@ -50,7 +50,7 @@ class CountMessages extends Maintenance {
                        // print "$code: $numMessages\n";
                        $total += $numMessages;
                        if ( $numMessages > 0 ) {
-                               $nonZero ++;
+                               $nonZero++;
                        }
                }
                $this->output( "\nTotal: $total\n" );
index fcf2c96..db6c315 100644 (file)
@@ -158,7 +158,8 @@ class GenerateCollationData extends Maintenance {
                // people like to use that as a fake no header symbol.
                $category = substr( $data['gc'], 0, 1 );
                if ( strpos( 'LNPS', $category ) === false
-                       && $data['cp'] !== '0020' ) {
+                       && $data['cp'] !== '0020'
+               ) {
                        return;
                }
                $cp = hexdec( $data['cp'] );
@@ -178,8 +179,8 @@ class GenerateCollationData extends Maintenance {
                // Calculate implicit weight per UTS #10 v6.0.0, sec 7.1.3
                if ( $data['UIdeo'] === 'Y' ) {
                        if ( $data['block'] == 'CJK Unified Ideographs'
-                               || $data['block'] == 'CJK Compatibility Ideographs' )
-                       {
+                               || $data['block'] == 'CJK Compatibility Ideographs'
+                       {
                                $base = 0xFB40;
                        } else {
                                $base = 0xFB80;
@@ -248,8 +249,8 @@ class GenerateCollationData extends Maintenance {
                        }
                        $this->weights[$cp] = $primary;
                        if ( $tertiary === '.0008'
-                               || $tertiary === '.000E' )
-                       {
+                               || $tertiary === '.000E'
+                       {
                                $goodTertiaryChars[$cp] = true;
                        }
                }
@@ -325,7 +326,7 @@ class GenerateCollationData extends Maintenance {
                        $char = codepointToUtf8( $cp );
                        $headerChars[] = $char;
                        if ( $primaryCollator->compare( $char, $prevChar ) <= 0 ) {
-                               $numOutOfOrder ++;
+                               $numOutOfOrder++;
                                /*
                                printf( "Out of order: U+%05X > U+%05X\n",
                                        utf8ToCodepoint( $prevChar ),
@@ -390,6 +391,7 @@ class UcdXmlReader {
                }
                while ( $this->xml->name !== 'ucd' && $this->xml->read() );
                $this->xml->read();
+
                return $this->xml;
        }
 
@@ -403,6 +405,7 @@ class UcdXmlReader {
                while ( $this->xml->moveToNextAttribute() ) {
                        $attrs[$this->xml->name] = $this->xml->value;
                }
+
                return $attrs;
        }
 
@@ -460,9 +463,9 @@ class UcdXmlReader {
                        }
                }
                $xml->close();
+
                return $this->blocks;
        }
-
 }
 
 $maintClass = 'GenerateCollationData';
index 216445e..b638b63 100644 (file)
@@ -44,7 +44,8 @@ class GenerateNormalizerData extends Maintenance {
                if ( !$this->hasOption( 'unicode-data-file' ) ) {
                        $this->dataFile = 'UnicodeData.txt';
                        if ( !file_exists( $this->dataFile ) ) {
-                               $this->error( "Unable to find UnicodeData.txt. Please specify its location with --unicode-data-file=<FILE>" );
+                               $this->error( "Unable to find UnicodeData.txt. Please specify " .
+                                       "its location with --unicode-data-file=<FILE>" );
                                exit( 1 );
                        }
                } else {
@@ -104,15 +105,15 @@ class GenerateNormalizerData extends Maintenance {
 
                        $code = base_convert( $data['Code'], 16, 10 );
                        if ( ( $code >= 0xFB50 && $code <= 0xFDFF ) # Arabic presentation forms A
-                               || ( $code >= 0xFE70 && $code <= 0xFEFF ) # Arabic presentation forms B
-                       {
+                               || ( $code >= 0xFE70 && $code <= 0xFEFF ) # Arabic presentation forms B
+                       {
                                if ( $data['Decomposition_Type_Mapping'] === '' ) {
                                        // No decomposition
                                        continue;
                                }
                                if ( !preg_match( '/^ *(<\w*>) +([0-9A-F ]*)$/',
-                                       $data['Decomposition_Type_Mapping'], $m ) )
-                               {
+                                       $data['Decomposition_Type_Mapping'], $m )
+                               {
                                        $this->error( "Can't parse Decomposition_Type/Mapping on line $lineNum" );
                                        $this->error( $line );
                                        continue;
index 14485f9..32cfcd7 100644 (file)
@@ -43,7 +43,7 @@ class LangMemUsage extends Maintenance {
                        $this->error( "You must compile PHP with --enable-memory-limit", true );
                }
 
-               $langtool = new languages();
+               $langtool = new Languages();
                $memlast = $memstart = memory_get_usage();
 
                $this->output( "Base memory usage: $memstart\n" );
index 6070f4a..61ee424 100644 (file)
 /**
  * @ingroup MaintenanceLanguage
  */
-class languages {
-       protected $mLanguages; # List of languages
+class Languages {
+       /** @var array List of languages */
+       protected $mLanguages; #
 
-       protected $mRawMessages; # Raw list of the messages in each language
-       protected $mMessages; # Messages in each language (except for English), divided to groups
-       protected $mFallback; # Fallback language in each language
-       protected $mGeneralMessages; # General messages in English, divided to groups
-       protected $mIgnoredMessages; # All the messages which should be exist only in the English file
-       protected $mOptionalMessages; # All the messages which may be translated or not, depending on the language
+       /** @var array Raw list of the messages in each language  */
+       protected $mRawMessages;
 
-       protected $mNamespaceNames; # Namespace names
-       protected $mNamespaceAliases; # Namespace aliases
-       protected $mMagicWords; # Magic words
-       protected $mSpecialPageAliases; # Special page aliases
+       /** @var array Messages in each language (except for English), divided to groups */
+       protected $mMessages;
+
+       /** @var array Fallback language in each language */
+       protected $mFallback;
+
+       /** @var array General messages in English, divided to groups */
+       protected $mGeneralMessages;
+
+       /** @var array All the messages which should be exist only in the English file */
+       protected $mIgnoredMessages;
+
+       /** @var array All the messages which may be translated or not, depending on the language */
+       protected $mOptionalMessages;
+
+       /** @var array Namespace names */
+       protected $mNamespaceNames;
+
+       /** @var array Namespace aliases */
+       protected $mNamespaceAliases;
+
+       /** @var array Magic words */
+       protected $mMagicWords;
+
+       /** @var  array Special page aliases */
+       protected $mSpecialPageAliases;
 
        /**
         * Load the list of languages: all the Messages*.php
@@ -96,7 +115,8 @@ class languages {
                        isset( $this->mNamespaceNames[$code] ) &&
                        isset( $this->mNamespaceAliases[$code] ) &&
                        isset( $this->mMagicWords[$code] ) &&
-                       isset( $this->mSpecialPageAliases[$code] ) ) {
+                       isset( $this->mSpecialPageAliases[$code] )
+               ) {
                        return;
                }
                $this->mRawMessages[$code] = array();
@@ -130,12 +150,16 @@ class languages {
        }
 
        /**
-        * Load the messages for a specific language (which is not English) and divide them to groups:
+        * Load the messages for a specific language (which is not English) and divide them to
+        * groups:
         * all - all the messages.
         * required - messages which should be translated in order to get a complete translation.
-        * optional - messages which can be translated, the fallback translation is used if not translated.
-        * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
-        * translated - messages which are either required or optional, but translated from English and needed.
+        * optional - messages which can be translated, the fallback translation is used if not
+        *   translated.
+        * obsolete - messages which should not be translated, either because they do not exist,
+        *   or they are ignored messages.
+        * translated - messages which are either required or optional, but translated from
+        *   English and needed.
         *
         * @param $code string The language code.
         */
@@ -166,10 +190,13 @@ class languages {
        /**
         * Load the messages for English and divide them to groups:
         * all - all the messages.
-        * required - messages which should be translated to other languages in order to get a complete translation.
-        * optional - messages which can be translated to other languages, but it's not required for a complete translation.
+        * required - messages which should be translated to other languages in order to get a
+        *   complete translation.
+        * optional - messages which can be translated to other languages, but it's not required
+        *   for a complete translation.
         * ignored - messages which should not be translated to other languages.
-        * translatable - messages which are either required or optional, but can be translated from English.
+        * translatable - messages which are either required or optional, but can be translated
+        *   from English.
         */
        private function loadGeneralMessages() {
                if ( isset( $this->mGeneralMessages ) ) {
@@ -199,9 +226,12 @@ class languages {
         * fallback language messages, divided to groups:
         * all - all the messages.
         * required - messages which should be translated in order to get a complete translation.
-        * optional - messages which can be translated, the fallback translation is used if not translated.
-        * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
-        * translated - messages which are either required or optional, but translated from English and needed.
+        * optional - messages which can be translated, the fallback translation is used if not
+        *   translated.
+        * obsolete - messages which should not be translated, either because they do not exist,
+        *   or they are ignored messages.
+        * translated - messages which are either required or optional, but translated from
+        *   English and needed.
         *
         * @param $code string The language code.
         *
@@ -209,21 +239,26 @@ class languages {
         */
        public function getMessages( $code ) {
                $this->loadMessages( $code );
+
                return $this->mMessages[$code];
        }
 
        /**
         * Get all the general English messages, divided to groups:
         * all - all the messages.
-        * required - messages which should be translated to other languages in order to get a complete translation.
-        * optional - messages which can be translated to other languages, but it's not required for a complete translation.
+        * required - messages which should be translated to other languages in
+        *   order to get a complete translation.
+        * optional - messages which can be translated to other languages, but it's
+        *   not required for a complete translation.
         * ignored - messages which should not be translated to other languages.
-        * translatable - messages which are either required or optional, but can be translated from English.
+        * translatable - messages which are either required or optional, but can be
+        *   translated from English.
         *
         * @return array The general English messages.
         */
        public function getGeneralMessages() {
                $this->loadGeneralMessages();
+
                return $this->mGeneralMessages;
        }
 
@@ -236,6 +271,7 @@ class languages {
         */
        public function getFallback( $code ) {
                $this->loadFile( $code );
+
                return $this->mFallback[$code];
        }
 
@@ -248,6 +284,7 @@ class languages {
         */
        public function getNamespaceNames( $code ) {
                $this->loadFile( $code );
+
                return $this->mNamespaceNames[$code];
        }
 
@@ -260,6 +297,7 @@ class languages {
         */
        public function getNamespaceAliases( $code ) {
                $this->loadFile( $code );
+
                return $this->mNamespaceAliases[$code];
        }
 
@@ -272,6 +310,7 @@ class languages {
         */
        public function getMagicWords( $code ) {
                $this->loadFile( $code );
+
                return $this->mMagicWords[$code];
        }
 
@@ -284,6 +323,7 @@ class languages {
         */
        public function getSpecialPageAliases( $code ) {
                $this->loadFile( $code );
+
                return $this->mSpecialPageAliases[$code];
        }
 
@@ -297,6 +337,7 @@ class languages {
        public function getUntranslatedMessages( $code ) {
                $this->loadGeneralMessages();
                $this->loadMessages( $code );
+
                return array_diff_key( $this->mGeneralMessages['required'], $this->mMessages[$code]['required'] );
        }
 
@@ -316,6 +357,7 @@ class languages {
                                $duplicateMessages[$key] = $value;
                        }
                }
+
                return $duplicateMessages;
        }
 
@@ -329,6 +371,7 @@ class languages {
        public function getObsoleteMessages( $code ) {
                $this->loadGeneralMessages();
                $this->loadMessages( $code );
+
                return $this->mMessages[$code]['obsolete'];
        }
 
@@ -348,11 +391,13 @@ class languages {
                        $missing = false;
                        foreach ( $variables as $var ) {
                                if ( preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
-                                       !preg_match( "/$var/sU", $value ) ) {
+                                       !preg_match( "/$var/sU", $value )
+                               ) {
                                        $missing = true;
                                }
                                if ( !preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
-                                       preg_match( "/$var/sU", $value ) ) {
+                                       preg_match( "/$var/sU", $value )
+                               ) {
                                        $missing = true;
                                }
                        }
@@ -360,6 +405,7 @@ class languages {
                                $mismatchMessages[$key] = $value;
                        }
                }
+
                return $mismatchMessages;
        }
 
@@ -375,10 +421,13 @@ class languages {
                $this->loadMessages( $code );
                $messagesWithoutPlural = array();
                foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
-                       if ( stripos( $this->mGeneralMessages['translatable'][$key], '{{plural:' ) !== false && stripos( $value, '{{plural:' ) === false ) {
+                       if ( stripos( $this->mGeneralMessages['translatable'][$key], '{{plural:' ) !== false &&
+                               stripos( $value, '{{plural:' ) === false
+                       ) {
                                $messagesWithoutPlural[$key] = $value;
                        }
                }
+
                return $messagesWithoutPlural;
        }
 
@@ -398,6 +447,7 @@ class languages {
                                $emptyMessages[$key] = $value;
                        }
                }
+
                return $emptyMessages;
        }
 
@@ -417,6 +467,7 @@ class languages {
                                $messagesWithWhitespace[$key] = $value;
                        }
                }
+
                return $messagesWithWhitespace;
        }
 
@@ -445,6 +496,7 @@ class languages {
                                $nonXHTMLMessages[$key] = $value;
                        }
                }
+
                return $nonXHTMLMessages;
        }
 
@@ -482,6 +534,7 @@ class languages {
                                $wrongCharsMessages[$key] = $value;
                        }
                }
+
                return $wrongCharsMessages;
        }
 
@@ -500,17 +553,18 @@ class languages {
                foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
                        $matches = array();
                        preg_match_all( "/\[\[([{$tc}]+)(?:\\|(.+?))?]]/sDu", $value, $matches );
-                       for ( $i = 0; $i < count( $matches[0] ); $i++ ) {
+                       $numMatches = count( $matches[0] );
+                       for ( $i = 0; $i < $numMatches; $i++ ) {
                                if ( preg_match( "/.*project.*/isDu", $matches[1][$i] ) ) {
                                        $messages[$key][] = $matches[0][$i];
                                }
                        }
 
-
                        if ( isset( $messages[$key] ) ) {
                                $messages[$key] = implode( $messages[$key], ", " );
                        }
                }
+
                return $messages;
        }
 
@@ -547,8 +601,8 @@ class languages {
                        if ( $a !== $b || $c !== $d ) {
                                $messages[$key] = "$a, $b, $c, $d";
                        }
-
                }
+
                return $messages;
        }
 
@@ -566,6 +620,7 @@ class languages {
                if ( isset( $namespacesDiff[NS_MAIN] ) ) {
                        unset( $namespacesDiff[NS_MAIN] );
                }
+
                return $namespacesDiff;
        }
 
@@ -614,6 +669,7 @@ class languages {
                                $magicWords[$key] = $value[1];
                        }
                }
+
                return $magicWords;
        }
 
@@ -633,6 +689,7 @@ class languages {
                                $magicWords[$key] = $value[1];
                        }
                }
+
                return $magicWords;
        }
 
@@ -662,6 +719,7 @@ class languages {
                                }
                        }
                }
+
                return $magicWords;
        }
 
@@ -685,6 +743,7 @@ class languages {
                                $magicWords[$key] = $local[0];
                        }
                }
+
                return $magicWords;
        }
 
@@ -704,6 +763,7 @@ class languages {
                                $specialPageAliases[$key] = $value[0];
                        }
                }
+
                return $specialPageAliases;
        }
 
@@ -723,12 +783,12 @@ class languages {
                                $specialPageAliases[$key] = $value[0];
                        }
                }
+
                return $specialPageAliases;
        }
 }
 
-class extensionLanguages extends languages {
-
+class ExtensionLanguages extends Languages {
        /**
         * @var MessageGroup
         */
index 8676d74..b06c11f 100644 (file)
@@ -262,11 +262,11 @@ $wgIgnoredMessages = array(
        'edithelppage',
        'autocomment-prefix',
        'move-redirect-text',
+       'interlanguage-link-title-langonly',
 );
 
 /** Optional messages, which may be translated only if changed in the target language. */
 $wgOptionalMessages = array(
-       'linkprefix',
        'feed-atom',
        'feed-rss',
        'unit-pixel',
@@ -477,7 +477,7 @@ $wgOptionalMessages = array(
        'version-entrypoints-scriptpath',
        'mergehistory-revisionrow',
        'categoryviewer-pagedlinks',
-       'undelete-revisionrow',
+       'undelete-revision-row',
        'pageinfo-redirects-value',
        'created', // @deprecated. Remove in MediaWiki 1.23.
        'changed', // @deprecated. Remove in MediaWiki 1.23.
@@ -485,7 +485,7 @@ $wgOptionalMessages = array(
        'limitreport-ppgeneratednodes-value',
        'limitreport-expansiondepth-value',
        'limitreport-expensivefunctioncount-value',
-       'tooltip-iwiki',
+       'interlanguage-link-title',
 );
 
 /** Exif messages, which may be set as optional in several checks, but are generally mandatory */
index a94b6d5..947dfe9 100644 (file)
@@ -169,9 +169,6 @@ $wgMessageStructure = array(
                'broken-file-category',
                'categoryviewer-pagedlinks',
        ),
-       'mainpage' => array(
-               'linkprefix',
-       ),
        'miscellaneous1' => array(
                'about',
                'article',
@@ -191,7 +188,6 @@ $wgMessageStructure = array(
                'qbedit',
                'qbpageoptions',
                'qbmyoptions',
-               'qbspecialpages',
                'faq',
                'faqpage',
                'sitetitle',
@@ -290,7 +286,6 @@ $wgMessageStructure = array(
                'disclaimerpage',
                'edithelp',
                'edithelppage',
-               'help',
                'helppage',
                'mainpage',
                'mainpage-description',
@@ -316,8 +311,6 @@ $wgMessageStructure = array(
                'backlinksubtitle',
                'retrievedfrom',
                'youhavenewmessages',
-               'newmessageslink',
-               'newmessagesdifflink',
                'youhavenewmessagesfromusers',
                'youhavenewmessagesmanyusers',
                'newmessageslinkplural',
@@ -412,7 +405,6 @@ $wgMessageStructure = array(
                'perfcached',
                'perfcachedts',
                'querypage-no-updates',
-               'wrong_wfQuery_params',
                'viewsource',
                'viewsource-title',
                'actionthrottled',
@@ -437,6 +429,7 @@ $wgMessageStructure = array(
                'invalidtitle-unknownnamespace',
                'exception-nologin',
                'exception-nologin-text',
+               'exception-nologin-text-manual',
        ),
        'virus' => array(
                'virus-badscanner',
@@ -1030,8 +1023,7 @@ $wgMessageStructure = array(
                'preferences-summary',
                'mypreferences',
                'prefs-edits',
-               'prefsnologin',
-               'prefsnologintext',
+               'prefsnologintext2',
                'changepassword',
                'changepassword-summary',
                'prefs-skin',
@@ -1093,7 +1085,6 @@ $wgMessageStructure = array(
                'prefs-namespaces',
                'defaultns',
                'default',
-               'defaultns',
                'prefs-files',
                'prefs-custom-css',
                'prefs-custom-js',
@@ -1335,6 +1326,9 @@ $wgMessageStructure = array(
                'recentchanges-label-minor',
                'recentchanges-label-bot',
                'recentchanges-label-unpatrolled',
+               'recentchanges-label-plusminus',
+               'recentchanges-legend-newpage',
+               'recentchanges-legend-plusminus',
                'rcnote',
                'rcnotefrom',
                'rclistfrom',
@@ -1520,7 +1514,6 @@ $wgMessageStructure = array(
                'lockmanager-fail-deletelock',
                'lockmanager-fail-acquirelock',
                'lockmanager-fail-openlock',
-               'lockmanager-fail-acquirelock',
                'lockmanager-fail-releaselock',
                'lockmanager-fail-db-bucket',
                'lockmanager-fail-db-release',
@@ -1772,7 +1765,6 @@ $wgMessageStructure = array(
                'nmembers',
                'nrevisions',
                'nviews',
-               'nchanges',
                'nimagelinks',
                'ntransclusions',
                'specialpage-empty',
@@ -2213,7 +2205,7 @@ $wgMessageStructure = array(
                'undelete-error-long',
                'undelete-show-file-confirm',
                'undelete-show-file-submit',
-               'undelete-revisionrow',
+               'undelete-revision-row',
        ),
        'nsform' => array(
                'namespace',
@@ -2727,7 +2719,8 @@ $wgMessageStructure = array(
                'tooltip-undo',
                'tooltip-preferences-save',
                'tooltip-summary',
-               'tooltip-iwiki',
+               'interlanguage-link-title',
+               'interlanguage-link-title-langonly',
        ),
        'stylesheets' => array(
                'common.css',
@@ -2776,6 +2769,7 @@ $wgMessageStructure = array(
                'spam_reverting',
                'spam_blanking',
                'spam_deleting',
+               'simpleantispam-label',
        ),
        'info' => array(
                'pageinfo-header',
@@ -2790,6 +2784,7 @@ $wgMessageStructure = array(
                'pageinfo-length',
                'pageinfo-article-id',
                'pageinfo-language',
+               'pageinfo-content-model',
                'pageinfo-robot-policy',
                'pageinfo-robot-index',
                'pageinfo-robot-noindex',
@@ -3456,10 +3451,6 @@ $wgMessageStructure = array(
                'exif-urgency-high',
                'exif-urgency-other',
        ),
-       'edit-externally' => array(
-               'edit-externally',
-               'edit-externally-help',
-       ),
        'all' => array(
                'watchlistall2',
                'namespacesall',
@@ -3524,6 +3515,7 @@ $wgMessageStructure = array(
                'percent',
                'parentheses',
                'brackets',
+               'quotation-marks',
        ),
        'imgmulti' => array(
                'imgmultipageprev',
@@ -3584,9 +3576,6 @@ $wgMessageStructure = array(
                'lag-warn-normal',
                'lag-warn-high',
        ),
-       'watch' => array(
-               'confirm-watch-button',
-       ),
        'watchlisteditor' => array(
                'editwatchlist-summary',
                'watchlistedit-numitems',
@@ -3741,6 +3730,7 @@ $wgMessageStructure = array(
        'special-specialpages' => array(
                'specialpages',
                'specialpages-summary',
+               'specialpages-note-top',
                'specialpages-note',
                'specialpages-group-maintenance',
                'specialpages-group-other',
@@ -3822,9 +3812,6 @@ $wgMessageStructure = array(
                'sqlite-has-fts',
                'sqlite-no-fts',
        ),
-       'unwatch' => array(
-               'confirm-unwatch-button',
-       ),
        'logging' => array(
                'logentry-delete-delete',
                'logentry-delete-restore',
@@ -3883,8 +3870,6 @@ $wgMessageStructure = array(
                'newuserlog-create-entry',
                'newuserlog-create2-entry',
                'newuserlog-autocreate-entry',
-               'suppressedarticle',
-               'deletedarticle',
                // 'uploadedimage',
                // 'overwroteimage',
                'rightslogentry',
@@ -3984,248 +3969,264 @@ $wgMessageStructure = array(
                'limitreport-expensivefunctioncount',
                'limitreport-expensivefunctioncount-value',
        ),
+       'expandtemplates' => array(
+               'expandtemplates',
+               'expand_templates_intro',
+               'expand_templates_title',
+               'expand_templates_input',
+               'expand_templates_output',
+               'expand_templates_xml_output',
+               'expand_templates_ok',
+               'expand_templates_remove_comments',
+               'expand_templates_remove_nowiki',
+               'expand_templates_generate_xml',
+               'expand_templates_preview',
+       ),
 );
 
 /** Comments for each block */
 $wgBlockComments = array(
-       'sidebar'             => "The sidebar for MonoBook is generated from this message, lines that do not
+       'sidebar' => "The sidebar for MonoBook is generated from this message, lines that do not
 begin with * or ** are discarded, furthermore lines that do begin with ** and
 do not contain | are also discarded, but do not depend on this behavior for
 future releases. Also note that since each list value is wrapped in a unique
 (X)HTML id it should only appear once and include characters that are legal
 (X)HTML id names.",
-       'toggles'             => 'User preference toggles',
-       'underline'           => '',
-       'editfont'            => 'Font style option in Special:Preferences',
-       'dates'               => 'Dates',
-       'categorypages'       => 'Categories related messages',
-       'mainpage'            => '',
-       'miscellaneous1'      => '',
-       'cologneblue'         => 'Cologne Blue skin',
-       'vector'              => 'Vector skin',
-       'miscellaneous2'      => '',
-       'links'               => 'All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).',
-       'badaccess'           => '',
-       'versionrequired'     => '',
-       'miscellaneous3'      => '',
-       'nstab'               => "Short words for each namespace, by default used in the namespace tab in monobook",
-       'main'                => 'Main script and global functions',
-       'errors'              => 'General errors',
-       'virus'               => 'Virus scanner',
-       'login'               => 'Login and logout pages',
-       'mail'                => 'Email sending',
-       'passwordstrength'    => 'JavaScript password checks',
-       'resetpass'           => 'Change password dialog',
-       'passwordreset'       => 'Special:PasswordReset',
-       'changeemail'         => 'Special:ChangeEmail',
-       'resettokens'         => 'Special:ResetTokens',
-       'toolbar'             => 'Edit page toolbar',
-       'edit'                => 'Edit pages',
-       'parserwarnings'      => 'Parser/template warnings',
-       'contentmodels'       => 'Content models',
-       'undo'                => '"Undo" feature',
-       'cantcreateaccount'   => 'Account creation failure',
-       'history'             => 'History pages',
-       'history-feed'        => 'Revision feed',
-       'revdelete'           => 'Revision deletion',
-       'suppression'         => 'Suppression log',
-       'mergehistory'        => 'History merging',
-       'mergelog'            => 'Merge log',
-       'diffs'               => 'Diffs',
-       'search'              => 'Search results',
-       'opensearch'          => 'OpenSearch description',
-       'preferences'         => 'Preferences page',
-       'preferences-email'   => 'User preference: email validation using jQuery',
-       'userrights'          => 'User rights',
-       'group'               => 'Groups',
-       'group-member'        => '',
-       'grouppage'           => '',
-       'right'               => 'Rights',
-       'action'              => 'Associated actions - in the sentence "You do not have permission to X"',
-       'rightslog'           => 'User rights log',
-       'recentchanges'       => 'Recent changes',
+       'toggles' => 'User preference toggles',
+       'underline' => '',
+       'editfont' => 'Font style option in Special:Preferences',
+       'dates' => 'Dates',
+       'categorypages' => 'Categories related messages',
+       'mainpage' => '',
+       'miscellaneous1' => '',
+       'cologneblue' => 'Cologne Blue skin',
+       'vector' => 'Vector skin',
+       'miscellaneous2' => '',
+       'links' => 'All link text and link target definitions of links into project namespace ' .
+               'that get used by other message strings, with the exception of user group pages (see grouppage).',
+       'badaccess' => '',
+       'versionrequired' => '',
+       'miscellaneous3' => '',
+       'nstab' => "Short words for each namespace, by default used in the namespace tab in monobook",
+       'main' => 'Main script and global functions',
+       'errors' => 'General errors',
+       'virus' => 'Virus scanner',
+       'login' => 'Login and logout pages',
+       'mail' => 'Email sending',
+       'passwordstrength' => 'JavaScript password checks',
+       'resetpass' => 'Change password dialog',
+       'passwordreset' => 'Special:PasswordReset',
+       'changeemail' => 'Special:ChangeEmail',
+       'resettokens' => 'Special:ResetTokens',
+       'toolbar' => 'Edit page toolbar',
+       'edit' => 'Edit pages',
+       'parserwarnings' => 'Parser/template warnings',
+       'contentmodels' => 'Content models',
+       'undo' => '"Undo" feature',
+       'cantcreateaccount' => 'Account creation failure',
+       'history' => 'History pages',
+       'history-feed' => 'Revision feed',
+       'revdelete' => 'Revision deletion',
+       'suppression' => 'Suppression log',
+       'mergehistory' => 'History merging',
+       'mergelog' => 'Merge log',
+       'diffs' => 'Diffs',
+       'search' => 'Search results',
+       'opensearch' => 'OpenSearch description',
+       'preferences' => 'Preferences page',
+       'preferences-email' => 'User preference: email validation using jQuery',
+       'userrights' => 'User rights',
+       'group' => 'Groups',
+       'group-member' => '',
+       'grouppage' => '',
+       'right' => 'Rights',
+       'action' => 'Associated actions - in the sentence "You do not have permission to X"',
+       'rightslog' => 'User rights log',
+       'recentchanges' => 'Recent changes',
        'recentchangeslinked' => 'Recent changes linked',
-       'upload'              => 'Upload',
-       'zip'                 => 'ZipDirectoryReader',
-       'upload-errors'       => '',
-       'filebackend-errors'  => 'File backend',
-       'filejournal-errors'  => 'File journal errors',
-       'lockmanager-errors'  => 'Lock manager',
-       'uploadstash'         => 'Special:UploadStash',
-       'img-auth'            => 'img_auth script messages',
-       'http-errors'         => 'HTTP errors',
-       'upload-curl-errors'  => 'Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>',
-       'licenses'            => '',
-       'filelist'            => 'Special:ListFiles',
-       'filedescription'     => 'File description page',
-       'filerevert'          => 'File reversion',
-       'filedelete'          => 'File deletion',
-       'mimesearch'          => 'MIME search',
-       'unwatchedpages'      => 'Unwatched pages',
-       'listredirects'       => 'List redirects',
-       'unusedtemplates'     => 'Unused templates',
-       'randompage'          => 'Random page',
-       'randomincategory'    => 'Random page in category',
-       'randomredirect'      => 'Random redirect',
-       'statistics'          => 'Statistics',
-       'pageswithprop'       => '',
-       'doubleredirects'     => '',
-       'brokenredirects'     => '',
-       'withoutinterwiki'    => '',
-       'fewestrevisions'     => '',
-       'specialpages'        => 'Miscellaneous special pages',
-       'booksources'         => 'Book sources',
-       'magicwords'          => 'Magic words',
-       'logpages'            => 'Special:Log',
-       'allpages'            => 'Special:AllPages',
-       'categories'          => 'Special:Categories',
-       'deletedcontribs'     => 'Special:DeletedContributions',
-       'linksearch'          => 'Special:LinkSearch',
-       'listusers'           => 'Special:ListUsers',
-       'activeusers'         => 'Special:ActiveUsers',
-       'newuserlog'          => 'Special:Log/newusers',
-       'listgrouprights'     => 'Special:ListGroupRights',
-       'emailuser'           => 'Email user',
-       'usermessage'         => 'User Messenger',
-       'watchlist'           => 'Watchlist',
-       'watching'            => 'Displayed when you click the "watch" button and it is in the process of watching',
-       'enotif'              => '',
-       'delete'              => 'Delete',
-       'rollback'            => 'Rollback',
-       'edittokens'          => 'Edit tokens',
-       'protect'             => 'Protect',
-       'restrictions'        => 'Restrictions (nouns)',
-       'restriction-levels'  => 'Restriction levels',
-       'undelete'            => 'Undelete',
-       'nsform'              => 'Namespace form on various pages',
-       'contributions'       => 'Contributions',
-       'sp-contributions'    => '',
-       'whatlinkshere'       => 'What links here',
-       'block'               => 'Block/unblock',
-       'developertools'      => 'Developer tools',
-       'movepage'            => 'Move page',
-       'export'              => 'Export',
-       'allmessages'         => 'Namespace 8 related',
-       'thumbnails'          => 'Thumbnails',
-       'import'              => 'Special:Import',
-       'importlog'           => 'Import log',
-       'javaccripttest'      => 'JavaScriptTest',
-       'accesskeys'          => 'Keyboard access keys for power users',
-       'tooltips'            => 'Tooltip help for the actions',
-       'stylesheets'         => 'Stylesheets',
-       'scripts'             => 'Scripts',
-       'metadata_cc'         => 'Metadata',
-       'attribution'         => 'Attribution',
-       'spamprotection'      => 'Spam protection',
-       'info'                => 'Info page',
-       'skin'                => 'Skin names',
-       'patrolling'          => 'Patrolling',
-       'patrol-log'          => 'Patrol log',
-       'imagedeletion'       => 'Image deletion',
-       'browsediffs'         => 'Browsing diffs',
-       'newfiles'            => 'Special:NewFiles',
-       'video-info'          => 'Video information, used by Language::formatTimePeriod() to format lengths in the above messages',
-       'human-timestamps'    => 'Human-readable timestamps',
-       'badimagelist'        => 'Bad image list',
-       'variantname-zh'      => "Short names for language variants used for language conversion links.
+       'upload' => 'Upload',
+       'zip' => 'ZipDirectoryReader',
+       'upload-errors' => '',
+       'filebackend-errors' => 'File backend',
+       'filejournal-errors' => 'File journal errors',
+       'lockmanager-errors' => 'Lock manager',
+       'uploadstash' => 'Special:UploadStash',
+       'img-auth' => 'img_auth script messages',
+       'http-errors' => 'HTTP errors',
+       'upload-curl-errors' => 'Some likely curl errors. More could be added from ' .
+               '<http://curl.haxx.se/libcurl/c/libcurl-errors.html>',
+       'licenses' => '',
+       'filelist' => 'Special:ListFiles',
+       'filedescription' => 'File description page',
+       'filerevert' => 'File reversion',
+       'filedelete' => 'File deletion',
+       'mimesearch' => 'MIME search',
+       'unwatchedpages' => 'Unwatched pages',
+       'listredirects' => 'List redirects',
+       'unusedtemplates' => 'Unused templates',
+       'randompage' => 'Random page',
+       'randomincategory' => 'Random page in category',
+       'randomredirect' => 'Random redirect',
+       'statistics' => 'Statistics',
+       'pageswithprop' => '',
+       'doubleredirects' => '',
+       'brokenredirects' => '',
+       'withoutinterwiki' => '',
+       'fewestrevisions' => '',
+       'specialpages' => 'Miscellaneous special pages',
+       'booksources' => 'Book sources',
+       'magicwords' => 'Magic words',
+       'logpages' => 'Special:Log',
+       'allpages' => 'Special:AllPages',
+       'categories' => 'Special:Categories',
+       'deletedcontribs' => 'Special:DeletedContributions',
+       'linksearch' => 'Special:LinkSearch',
+       'listusers' => 'Special:ListUsers',
+       'activeusers' => 'Special:ActiveUsers',
+       'newuserlog' => 'Special:Log/newusers',
+       'listgrouprights' => 'Special:ListGroupRights',
+       'emailuser' => 'Email user',
+       'usermessage' => 'User Messenger',
+       'watchlist' => 'Watchlist',
+       'watching' => 'Displayed when you click the "watch" button and it is in the process of watching',
+       'enotif' => '',
+       'delete' => 'Delete',
+       'rollback' => 'Rollback',
+       'edittokens' => 'Edit tokens',
+       'protect' => 'Protect',
+       'restrictions' => 'Restrictions (nouns)',
+       'restriction-levels' => 'Restriction levels',
+       'undelete' => 'Undelete',
+       'nsform' => 'Namespace form on various pages',
+       'contributions' => 'Contributions',
+       'sp-contributions' => '',
+       'whatlinkshere' => 'What links here',
+       'block' => 'Block/unblock',
+       'developertools' => 'Developer tools',
+       'movepage' => 'Move page',
+       'export' => 'Export',
+       'allmessages' => 'Namespace 8 related',
+       'thumbnails' => 'Thumbnails',
+       'import' => 'Special:Import',
+       'importlog' => 'Import log',
+       'javaccripttest' => 'JavaScriptTest',
+       'accesskeys' => 'Keyboard access keys for power users',
+       'tooltips' => 'Tooltip help for the actions',
+       'stylesheets' => 'Stylesheets',
+       'scripts' => 'Scripts',
+       'metadata_cc' => 'Metadata',
+       'attribution' => 'Attribution',
+       'spamprotection' => 'Spam protection',
+       'info' => 'Info page',
+       'skin' => 'Skin names',
+       'patrolling' => 'Patrolling',
+       'patrol-log' => 'Patrol log',
+       'imagedeletion' => 'Image deletion',
+       'browsediffs' => 'Browsing diffs',
+       'newfiles' => 'Special:NewFiles',
+       'video-info' => 'Video information, used by Language::formatTimePeriod() to ' .
+               'format lengths in the above messages',
+       'human-timestamps' => 'Human-readable timestamps',
+       'badimagelist' => 'Bad image list',
+       'variantname-zh' => "Short names for language variants used for language conversion links.
 Variants for Chinese language",
-       'variantname-gan'      => 'Variants for Gan language',
-       'variantname-sr'      => 'Variants for Serbian language',
-       'variantname-kk'      => 'Variants for Kazakh language',
-       'variantname-ku'      => 'Variants for Kurdish language',
-       'variantname-tg'      => 'Variants for Tajiki language',
-       'variantname-iu'      => 'Variants for Inuktitut language',
-       'variantname-shi'     => 'Variants for Tachelhit language',
-       'media-info'          => 'Media information',
-       'metadata'            => 'Metadata',
-       'exif'                           => 'Exif tags',
-       'exif-values'                    => 'Make & model, can be wikified in order to link to the camera and model name',
-       'exif-compression'               => 'Exif attributes',
-       'exif-copyrighted'               => '',
-       'exif-unknowndate'               => '',
+       'variantname-gan' => 'Variants for Gan language',
+       'variantname-sr' => 'Variants for Serbian language',
+       'variantname-kk' => 'Variants for Kazakh language',
+       'variantname-ku' => 'Variants for Kurdish language',
+       'variantname-tg' => 'Variants for Tajiki language',
+       'variantname-iu' => 'Variants for Inuktitut language',
+       'variantname-shi' => 'Variants for Tachelhit language',
+       'media-info' => 'Media information',
+       'metadata' => 'Metadata',
+       'exif' => 'Exif tags',
+       'exif-values' => 'Make & model, can be wikified in order to link to the camera and model name',
+       'exif-compression' => 'Exif attributes',
+       'exif-copyrighted' => '',
+       'exif-unknowndate' => '',
        'exif-photometricinterpretation' => '',
-       'exif-orientation'               => '',
-       'exif-planarconfiguration'       => '',
-       'exif-xyresolution'              => '',
-       'exif-colorspace'                => '',
-       'exif-componentsconfiguration'   => '',
-       'exif-exposureprogram'           => '',
-       'exif-subjectdistance-value'     => '',
-       'exif-meteringmode'              => '',
-       'exif-lightsource'               => '',
-       'exif-flash'                     => 'Flash modes',
-       'exif-focalplaneresolutionunit'  => '',
-       'exif-sensingmethod'             => '',
-       'exif-filesource'                => '',
-       'exif-scenetype'                 => '',
-       'exif-customrendered'            => '',
-       'exif-exposuremode'              => '',
-       'exif-whitebalance'              => '',
-       'exif-scenecapturetype'          => '',
-       'exif-gaincontrol'               => '',
-       'exif-contrast'                  => '',
-       'exif-saturation'                => '',
-       'exif-sharpness'                 => '',
-       'exif-subjectdistancerange'      => '',
-       'exif-gpslatitude'               => 'Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef',
-       'exif-gpslongitude'              => 'Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef',
-       'exif-altituderef'               => 'Pseudotags used for GPSAltitudeRef',
-       'exif-gpsstatus'                 => '',
-       'exif-gpsmeasuremode'            => '',
-       'exif-gpsspeed'                  => 'Pseudotags used for GPSSpeedRef',
-       'exif-gpsdestdistanceref'        => 'Pseudotags used for GPSDestDistanceRef',
-       'exif-gdop'                      => '',
-       'exif-objectcycle'               => '',
-       'exif-gpsdirection'              => 'Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef',
-       'exif-ycbcrpositioning'          => '',
-       'exif-dc'                        => '',
-       'exif-rating'                    => '',
-       'exif-isospeedratings'           => '',
-       'exif-maxaperturevalue'          => '',
-       'exif-iimcategory'               => '',
-       'exif-urgency'                   => '',
-       'edit-externally'       => 'External editor support',
-       'all'                   => "'all' in various places, this might be different for inflected languages",
-       'confirmemail'          => 'Email address confirmation',
-       'scarytransclusion'     => 'Scary transclusion',
-       'deleteconflict'        => 'Delete conflict',
-       'unit-pixel'            => '',
-       'purge'                 => 'action=purge',
-       'watch-unwatch'         => 'action=watch/unwatch',
-       'separators'            => 'Separators for various lists, etc.',
-       'imgmulti'              => 'Multipage image navigation',
-       'tablepager'            => 'Table pager',
-       'autosumm'              => 'Auto-summaries',
-       'autoblock_whitelist'   => 'Autoblock whitelist',
-       'sizeunits'             => 'Size units',
-       'bitrateunits'          => 'Bitrate units',
-       'livepreview'           => 'Live preview',
-       'lagwarning'            => 'Friendlier slave lag warnings',
-       'watchlisteditor'       => 'Watchlist editor',
-       'watchlisttools'        => 'Watchlist editing tools',
-       'iranian-dates'         => 'Iranian month names',
-       'hijri-dates'           => 'Hijri month names',
-       'hebrew-dates'          => 'Hebrew month names',
-       'signatures'            => 'Signatures',
-       'CoreParserFunctions'   => 'Core parser functions',
-       'version'               => 'Special:Version',
-       'redirect'              => 'Special:Redirect',
-       'fileduplicatesearch'   => 'Special:FileDuplicateSearch',
-       'special-specialpages'  => 'Special:SpecialPages',
-       'special-blank'         => 'Special:BlankPage',
-       'external_images'       => 'External image whitelist',
-       'special-tags'          => 'Special:Tags',
-       'comparepages'          => 'Special:ComparePages',
-       'db-error-messages'     => 'Database error messages',
-       'html-forms'            => 'HTML forms',
-       'sqlite'                => 'SQLite database support',
-       'logging'               => 'New logging system',
-       'logging-irc'           => 'For IRC, see bug 34508. Do not change',
-       'feedback'              => 'Feedback',
-       'searchsuggestions'     => 'Search suggestions',
-       'apierrors'             => 'API errors',
-       'duration'              => 'Durations',
-       'cachedspecial'         => 'SpecialCachedPage',
-       'rotation'              => 'Image rotation',
-       'limitreport'           => 'Limit report',
+       'exif-orientation' => '',
+       'exif-planarconfiguration' => '',
+       'exif-xyresolution' => '',
+       'exif-colorspace' => '',
+       'exif-componentsconfiguration' => '',
+       'exif-exposureprogram' => '',
+       'exif-subjectdistance-value' => '',
+       'exif-meteringmode' => '',
+       'exif-lightsource' => '',
+       'exif-flash' => 'Flash modes',
+       'exif-focalplaneresolutionunit' => '',
+       'exif-sensingmethod' => '',
+       'exif-filesource' => '',
+       'exif-scenetype' => '',
+       'exif-customrendered' => '',
+       'exif-exposuremode' => '',
+       'exif-whitebalance' => '',
+       'exif-scenecapturetype' => '',
+       'exif-gaincontrol' => '',
+       'exif-contrast' => '',
+       'exif-saturation' => '',
+       'exif-sharpness' => '',
+       'exif-subjectdistancerange' => '',
+       'exif-gpslatitude' => 'Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef',
+       'exif-gpslongitude' => 'Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef',
+       'exif-altituderef' => 'Pseudotags used for GPSAltitudeRef',
+       'exif-gpsstatus' => '',
+       'exif-gpsmeasuremode' => '',
+       'exif-gpsspeed' => 'Pseudotags used for GPSSpeedRef',
+       'exif-gpsdestdistanceref' => 'Pseudotags used for GPSDestDistanceRef',
+       'exif-gdop' => '',
+       'exif-objectcycle' => '',
+       'exif-gpsdirection' => 'Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef',
+       'exif-ycbcrpositioning' => '',
+       'exif-dc' => '',
+       'exif-rating' => '',
+       'exif-isospeedratings' => '',
+       'exif-maxaperturevalue' => '',
+       'exif-iimcategory' => '',
+       'exif-urgency' => '',
+       'all' => "'all' in various places, this might be different for inflected languages",
+       'confirmemail' => 'Email address confirmation',
+       'scarytransclusion' => 'Scary transclusion',
+       'deleteconflict' => 'Delete conflict',
+       'unit-pixel' => '',
+       'purge' => 'action=purge',
+       'watch-unwatch' => 'action=watch/unwatch',
+       'separators' => 'Separators for various lists, etc.',
+       'imgmulti' => 'Multipage image navigation',
+       'tablepager' => 'Table pager',
+       'autosumm' => 'Auto-summaries',
+       'autoblock_whitelist' => 'Autoblock whitelist',
+       'sizeunits' => 'Size units',
+       'bitrateunits' => 'Bitrate units',
+       'livepreview' => 'Live preview',
+       'lagwarning' => 'Friendlier slave lag warnings',
+       'watchlisteditor' => 'Watchlist editor',
+       'watchlisttools' => 'Watchlist editing tools',
+       'iranian-dates' => 'Iranian month names',
+       'hijri-dates' => 'Hijri month names',
+       'hebrew-dates' => 'Hebrew month names',
+       'signatures' => 'Signatures',
+       'CoreParserFunctions' => 'Core parser functions',
+       'version' => 'Special:Version',
+       'redirect' => 'Special:Redirect',
+       'fileduplicatesearch' => 'Special:FileDuplicateSearch',
+       'special-specialpages' => 'Special:SpecialPages',
+       'special-blank' => 'Special:BlankPage',
+       'external_images' => 'External image whitelist',
+       'special-tags' => 'Special:Tags',
+       'comparepages' => 'Special:ComparePages',
+       'db-error-messages' => 'Database error messages',
+       'html-forms' => 'HTML forms',
+       'sqlite' => 'SQLite database support',
+       'logging' => 'New logging system',
+       'logging-irc' => 'For IRC, see bug 34508. Do not change',
+       'feedback' => 'Feedback',
+       'searchsuggestions' => 'Search suggestions',
+       'apierrors' => 'API errors',
+       'duration' => 'Durations',
+       'cachedspecial' => 'SpecialCachedPage',
+       'rotation' => 'Image rotation',
+       'limitreport' => 'Limit report',
+       'expandtemplates' => 'Special:ExpandTemplates'
 );
index 66948ae..6b506b8 100644 (file)
@@ -38,13 +38,22 @@ require_once 'writeMessagesArray.inc';
  * @param $dupeMsgSource string The source file intended to remove from the array.
  * @param $messagesFolder String: path to a folder to store the MediaWiki messages.
  */
-function rebuildLanguage( $languages, $code, $write, $listUnknown, $removeUnknown, $removeDupes, $dupeMsgSource, $messagesFolder ) {
+function rebuildLanguage( $languages, $code, $write, $listUnknown, $removeUnknown,
+       $removeDupes, $dupeMsgSource, $messagesFolder
+) {
        $messages = $languages->getMessages( $code );
        $messages = $messages['all'];
        if ( $removeDupes ) {
                $messages = removeDupes( $messages, $dupeMsgSource );
        }
-       MessageWriter::writeMessagesToFile( $messages, $code, $write, $listUnknown, $removeUnknown, $messagesFolder );
+       MessageWriter::writeMessagesToFile(
+               $messages,
+               $code,
+               $write,
+               $listUnknown,
+               $removeUnknown,
+               $messagesFolder
+       );
 }
 
 /**
@@ -71,15 +80,18 @@ function removeDupes( $oldMsgArray, $dupeMsgSource ) {
                        unset( $newMsgArray[$key] );
                }
        }
+
        return $newMsgArray;
 }
 
 # Show help
 if ( isset( $options['help'] ) ) {
        echo <<<TEXT
-Run this script to rewrite the messages array in the files languages/messages/MessagesXX.php.
+Run this script to rewrite the messages array in the files
+languages/messages/MessagesXX.php.
 Parameters:
-       * lang: Language code (default: the installation default language). You can also specify "all" to check all the languages.
+       * lang: Language code (default: the installation default language).
+         You can also specify "all" to check all the languages.
        * help: Show this help.
 Options:
        * dry-run: Do not write the array to the file.
@@ -114,13 +126,31 @@ $wgRemoveDuplicateMessages = isset( $options['remove-duplicates'] );
 $messagesFolder = isset( $options['messages-folder'] ) ? $options['messages-folder'] : false;
 
 # Get language objects
-$languages = new languages();
+$languages = new Languages();
 
 # Write all the language
 if ( $wgCode == 'all' ) {
        foreach ( $languages->getLanguages() as $languageCode ) {
-               rebuildLanguage( $languages, $languageCode, $wgWriteToFile, $wgListUnknownMessages, $wgRemoveUnknownMessages, $wgRemoveDuplicateMessages, $wgDupeMessageSource, $messagesFolder );
+               rebuildLanguage(
+                       $languages,
+                       $languageCode,
+                       $wgWriteToFile,
+                       $wgListUnknownMessages,
+                       $wgRemoveUnknownMessages,
+                       $wgRemoveDuplicateMessages,
+                       $wgDupeMessageSource,
+                       $messagesFolder
+               );
        }
 } else {
-       rebuildLanguage( $languages, $wgCode, $wgWriteToFile, $wgListUnknownMessages, $wgRemoveUnknownMessages, $wgRemoveDuplicateMessages, $wgDupeMessageSource, $messagesFolder );
+       rebuildLanguage(
+               $languages,
+               $wgCode,
+               $wgWriteToFile,
+               $wgListUnknownMessages,
+               $wgRemoveUnknownMessages,
+               $wgRemoveDuplicateMessages,
+               $wgDupeMessageSource,
+               $messagesFolder
+       );
 }
index 61b84a0..6a538e6 100644 (file)
@@ -32,7 +32,6 @@ require_once __DIR__ . '/../commandLine.inc';
 require_once 'languages.inc';
 require_once __DIR__ . '/StatOutputs.php';
 
-
 if ( isset( $options['help'] ) ) {
        showUsage();
 }
@@ -57,25 +56,23 @@ TEXT;
        exit( 1 );
 }
 
-
-
 # Select an output engine
 switch ( $options['output'] ) {
        case 'wiki':
-               $output = new wikiStatsOutput();
+               $output = new WikiStatsOutput();
                break;
        case 'text':
-               $output = new textStatsOutput();
+               $output = new TextStatsOutput();
                break;
        case 'csv':
-               $output = new csvStatsOutput();
+               $output = new CsvStatsOutput();
                break;
        default:
                showUsage();
 }
 
 # Languages
-$wgLanguages = new languages();
+$wgLanguages = new Languages();
 
 # Header
 $output->heading();
@@ -97,7 +94,8 @@ $wgRequiredMessagesNumber = count( $wgGeneralMessages['required'] );
 foreach ( $wgLanguages->getLanguages() as $code ) {
        # Don't check English, RTL English or dummy language codes
        if ( $code == 'en' || $code == 'enRTL' || ( is_array( $wgDummyLanguageCodes ) &&
-               isset( $wgDummyLanguageCodes[$code] ) ) ) {
+                       isset( $wgDummyLanguageCodes[$code] ) )
+       ) {
                continue;
        }
 
@@ -107,16 +105,33 @@ foreach ( $wgLanguages->getLanguages() as $code ) {
        $messages = $wgLanguages->getMessages( $code );
        $messagesNumber = count( $messages['translated'] );
        $requiredMessagesNumber = count( $messages['required'] );
-       $requiredMessagesPercent = $output->formatPercent( $requiredMessagesNumber, $wgRequiredMessagesNumber );
+       $requiredMessagesPercent = $output->formatPercent(
+               $requiredMessagesNumber,
+               $wgRequiredMessagesNumber
+       );
        $obsoleteMessagesNumber = count( $messages['obsolete'] );
-       $obsoleteMessagesPercent = $output->formatPercent( $obsoleteMessagesNumber, $messagesNumber, true );
+       $obsoleteMessagesPercent = $output->formatPercent(
+               $obsoleteMessagesNumber,
+               $messagesNumber,
+               true
+       );
        $messagesWithMismatchVariables = $wgLanguages->getMessagesWithMismatchVariables( $code );
        $emptyMessages = $wgLanguages->getEmptyMessages( $code );
        $messagesWithWhitespace = $wgLanguages->getMessagesWithWhitespace( $code );
        $nonXHTMLMessages = $wgLanguages->getNonXHTMLMessages( $code );
        $messagesWithWrongChars = $wgLanguages->getMessagesWithWrongChars( $code );
-       $problematicMessagesNumber = count( array_unique( array_merge( $messagesWithMismatchVariables, $emptyMessages, $messagesWithWhitespace, $nonXHTMLMessages, $messagesWithWrongChars ) ) );
-       $problematicMessagesPercent = $output->formatPercent( $problematicMessagesNumber, $messagesNumber, true );
+       $problematicMessagesNumber = count( array_unique( array_merge(
+               $messagesWithMismatchVariables,
+               $emptyMessages,
+               $messagesWithWhitespace,
+               $nonXHTMLMessages,
+               $messagesWithWrongChars
+       ) ) );
+       $problematicMessagesPercent = $output->formatPercent(
+               $problematicMessagesNumber,
+               $messagesNumber,
+               true
+       );
 
        # Output them
        $output->blockstart();
index 63d9b84..f1b4079 100644 (file)
@@ -60,5 +60,6 @@ function getVars( $filename ) {
        require $filename;
        $vars = get_defined_vars();
        unset( $vars['filename'] );
+
        return $vars;
 }
index fc0da3f..7c880b2 100644 (file)
  * @ingroup MaintenanceLanguage
  */
 class MessageWriter {
-       static $optionalComment = 'only translate this message to other languages if you have to change it';
-       static $ignoredComment = "do not translate or duplicate this message to other languages";
+       protected static $optionalComment =
+               'only translate this message to other languages if you have to change it';
+       protected static $ignoredComment = "do not translate or duplicate this message to other languages";
 
-       static $messageStructure;
-       static $blockComments;
-       static $ignoredMessages;
-       static $optionalMessages;
+       protected static $messageStructure;
+       protected static $blockComments;
+       protected static $ignoredMessages;
+       protected static $optionalMessages;
 
        /**
         * Write a messages array as a PHP text and write it to the messages file.
@@ -41,9 +42,12 @@ class MessageWriter {
         * @param $write Boolean: write to the messages file?
         * @param $listUnknown Boolean: list the unknown messages?
         * @param $removeUnknown Boolean: whether to remove unkown messages
-        * @param $messagesFolder String: path to a folder to store the MediaWiki messages. Defaults to the current install.
+        * @param $messagesFolder String: path to a folder to store the MediaWiki messages.
+        *        Defaults to the current install.
         */
-       public static function writeMessagesToFile( $messages, $code, $write, $listUnknown, $removeUnknown, $messagesFolder = false ) {
+       public static function writeMessagesToFile( $messages, $code, $write, $listUnknown,
+               $removeUnknown, $messagesFolder = false
+       ) {
                # Rewrite the messages array
                $messages = self::writeMessagesArray( $messages, $code == 'en', false, $removeUnknown );
                $messagesText = $messages[0];
@@ -76,14 +80,20 @@ $messages = array(
                                        file_put_contents( $filename, $new );
                                        echo "Generated and wrote messages for language $code.\n";
                                } else {
-                                       echo "Generated messages for language $code. Please run the script again (without the parameter \"dry-run\") to write the array to the file.\n";
+                                       echo "Generated messages for language $code.\n" .
+                                               "Please run the script again (without the parameter \"dry-run\") " .
+                                               "to write the array to the file.\n";
                                }
                        }
-                       if ( $listUnknown && isset( $sortedMessages['unknown'] ) && !empty( $sortedMessages['unknown'] ) ) {
+                       if ( $listUnknown && isset( $sortedMessages['unknown'] ) &&
+                               !empty( $sortedMessages['unknown'] )
+                       ) {
                                if ( $removeUnknown ) {
-                                       echo "\nThe following " . count( $sortedMessages['unknown'] ) . " unknown messages have been removed:\n";
+                                       echo "\nThe following " . count( $sortedMessages['unknown'] ) .
+                                               " unknown messages have been removed:\n";
                                } else {
-                                       echo "\nThere are " . count( $sortedMessages['unknown'] ) . " unknown messages, please check them:\n";
+                                       echo "\nThere are " . count( $sortedMessages['unknown'] ) .
+                                               " unknown messages, please check them:\n";
                                }
                                foreach ( $sortedMessages['unknown'] as $key => $value ) {
                                        echo "* " . $key . "\n";
@@ -106,7 +116,9 @@ $messages = array(
         *
         * @return Array of the PHP text and the sorted messages array.
         */
-       public static function writeMessagesArray( $messages, $ignoredComments = false, $prefix = false, $removeUnknown = false ) {
+       public static function writeMessagesArray( $messages, $ignoredComments = false,
+               $prefix = false, $removeUnknown = false
+       ) {
                # Load messages
                $dir = $prefix ? $prefix : __DIR__;
 
@@ -162,6 +174,7 @@ $messages = array(
                }
                $messagesText .= ");
 ";
+
                return array( $messagesText, $sortedMessages );
        }
 
@@ -247,12 +260,22 @@ $blockComment
                        if ( strpos( $value, $single ) === false ) {
                                # Nothing ugly, just use '
                                $blockText .= $single . $value . $single;
-                       } elseif ( strpos( $value, $double ) === false && !preg_match( '/\$[a-zA-Z_\x7f-\xff]/', $value ) ) {
+                       } elseif ( strpos( $value, $double ) === false &&
+                               !preg_match( '/\$[a-zA-Z_\x7f-\xff]/', $value )
+                       ) {
                                # No "-quotes, no variables that need quoting, use "
                                $blockText .= $double . $value . $double;
                        } else {
                                # Something needs quoting, pick the quote which causes less quoting
-                               $quote = substr_count( $value, $double ) + substr_count( $value, '$' ) >= substr_count( $value, $single ) ? $single : $double;
+
+                               if ( substr_count( $value, $double ) + substr_count( $value, '$' ) >=
+                                       substr_count( $value, $single )
+                               ) {
+                                       $quote = $single;
+                               } else {
+                                       $quote = $double;
+                               }
+
                                if ( $quote === $double ) {
                                        $extra = '$';
                                } else {
diff --git a/maintenance/language/zhtable/trad2simp_supp_unset.manual b/maintenance/language/zhtable/trad2simp_supp_unset.manual
deleted file mode 100644 (file)
index e69de29..0000000
index 01fbac7..d98654e 100644 (file)
@@ -149,7 +149,7 @@ class LockServerDaemon {
                $socketArray->addSocket( $this->sock ); // add listening socket
                do {
                        list( $read, $write ) = $socketArray->socketsForSelect();
-                       if ( socket_select( $read, $write, $except = NULL, NULL ) < 1 ) {
+                       if ( socket_select( $read, $write, $except = null, null ) < 1 ) {
                                continue; // wait
                        }
                        // Check if there is a client trying to connect...
index eda101e..243f97c 100644 (file)
@@ -30,7 +30,7 @@ require_once __DIR__ . '/Maintenance.php';
  *
  * @ingroup Maintenance
  */
-class mcTest extends Maintenance {
+class McTest extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every"
@@ -111,5 +111,5 @@ class mcTest extends Maintenance {
        }
 }
 
-$maintClass = "mcTest";
+$maintClass = "McTest";
 require_once RUN_MAINTENANCE_IF_MAIN;
index e918337..5bf04c6 100644 (file)
@@ -148,7 +148,7 @@ foreach ( $mmfl['setupFiles'] as $fileName ) {
                fwrite( STDERR, "Loading data from $fileName\n" );
        }
        // Include the extension to update $wgExtensionMessagesFiles
-       if ( !( include_once( $fileName ) ) ) {
+       if ( !( include_once $fileName ) ) {
                fwrite( STDERR, "Unable to read $fileName\n" );
                exit( 1 );
        }
index 34e6428..5171b17 100644 (file)
@@ -21,7 +21,7 @@
  * @ingroup Maintenance
  * @author Tim Starling
  *
- * USAGE: php moveBatch.php [-u <user>] [-r <reason>] [-i <interval>] [listfile]
+ * USAGE: php moveBatch.php [-u <user>] [-r <reason>] [-i <interval>] [-noredirects] [listfile]
  *
  * [listfile] - file with two titles per line, separated with pipe characters;
  * the first title is the source, the second is the destination.
@@ -29,6 +29,7 @@
  * <user> - username to perform moves as
  * <reason> - reason to be given for moves
  * <interval> - number of seconds to sleep after each move
+ * <noredirects> - suppress creation of redirects
  *
  * This will print out error codes from Title::moveTo() if something goes wrong,
  * e.g. immobile_namespace for namespaces which can't be moved
@@ -48,6 +49,7 @@ class MoveBatch extends Maintenance {
                $this->addOption( 'u', "User to perform move", false, true );
                $this->addOption( 'r', "Reason to move page", false, true );
                $this->addOption( 'i', "Interval to sleep between moves" );
+               $this->addOption( 'noredirects', "Suppress creation of redirects" );
                $this->addArg( 'listfile', 'List of pages to move, newline delimited', false );
        }
 
@@ -62,6 +64,7 @@ class MoveBatch extends Maintenance {
                $user = $this->getOption( 'u', 'Move page script' );
                $reason = $this->getOption( 'r', '' );
                $interval = $this->getOption( 'i', 0 );
+               $noredirects = $this->getOption( 'noredirects', false );
                if ( $this->hasArg() ) {
                        $file = fopen( $this->getArg(), 'r' );
                } else {
@@ -96,10 +99,9 @@ class MoveBatch extends Maintenance {
                                continue;
                        }
 
-
                        $this->output( $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText() );
                        $dbw->begin( __METHOD__ );
-                       $err = $source->moveTo( $dest, false, $reason );
+                       $err = $source->moveTo( $dest, false, $reason, !$noredirects );
                        if ( $err !== true ) {
                                $msg = array_shift( $err[0] );
                                $this->output( "\nFAILED: " . wfMessage( $msg, $err[0] )->text() );
index 7356c38..8a565d5 100644 (file)
@@ -674,13 +674,13 @@ CREATE UNIQUE INDEX /*$wgDBprefix*/qcc_titletwo ON /*$wgDBprefix*/querycachetwo(
 
 --- Used for storing page restrictions (i.e. protection levels)
 CREATE TABLE /*$wgDBprefix*/page_restrictions (
+   pr_id INT UNIQUE IDENTITY,
    pr_page INT NOT NULL REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE,
    pr_type NVARCHAR(200) NOT NULL,
    pr_level NVARCHAR(200) NOT NULL,
    pr_cascade SMALLINT NOT NULL,
    pr_user INT NULL,
    pr_expiry DATETIME NULL,
-   pr_id INT UNIQUE IDENTITY,
    CONSTRAINT /*$wgDBprefix*/pr_pagetype PRIMARY KEY(pr_page,pr_type),
 );
 CREATE INDEX /*$wgDBprefix*/pr_page      ON /*$wgDBprefix*/page_restrictions(pr_page);
index bc10bc2..622712e 100755 (executable)
@@ -6,7 +6,7 @@ then
        JSDUCK_MWVERSION="$2"
 elif [[ "$*" != "" ]]
 then
-       echo "Usage $0: [--version <mediawiki version>]"
+       echo "Usage: $0 [--version <mediawiki version>]"
        echo
        exit 1
 fi
index 219b5d8..06ccccb 100644 (file)
@@ -28,7 +28,7 @@ require_once __DIR__ . '/Maintenance.php';
  *
  * @ingroup Maintenance
  */
-class nextJobDB extends Maintenance {
+class NextJobDB extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->mDescription = "Pick a database that has pending jobs";
@@ -115,5 +115,5 @@ class nextJobDB extends Maintenance {
        }
 }
 
-$maintClass = "nextJobDb";
+$maintClass = "NextJobDb";
 require_once RUN_MAINTENANCE_IF_MAIN;
index 64c2848..cd99f7c 100644 (file)
@@ -67,7 +67,7 @@ CREATE TABLE &mw_prefix.msg_resource (
   mr_lang varchar2(32) NOT NULL,
   mr_blob BLOB NOT NULL,
   mr_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL
-) ;
+);
 CREATE UNIQUE INDEX &mw_prefix.msg_resource_u01 ON &mw_prefix.msg_resource (mr_resource, mr_lang);
 
 ALTER TABLE &mw_prefix.oldimage MODIFY oi_name DEFAULT 0;
index acfabc3..2395bc5 100644 (file)
@@ -2,7 +2,7 @@
 define mw_prefix='{$wgDBprefix}';
 
 
-CREATE SEQUENCE user_user_id_seq MINVALUE 0 START WITH 0;
+CREATE SEQUENCE user_user_id_seq;
 CREATE TABLE &mw_prefix.mwuser ( -- replace reserved word 'user'
   user_id                   NUMBER  NOT NULL,
   user_name                 VARCHAR2(255)     NOT NULL,
@@ -27,7 +27,7 @@ CREATE INDEX &mw_prefix.mwuser_i02 ON &mw_prefix.mwuser (user_email, user_name);
 
 -- Create a dummy user to satisfy fk contraints especially with revisions
 INSERT INTO &mw_prefix.mwuser
-  VALUES (user_user_id_seq.nextval,'Anonymous',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, '', current_timestamp, current_timestamp, 0);
+  VALUES (0,'Anonymous',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, '', current_timestamp, current_timestamp, 0);
 
 CREATE TABLE &mw_prefix.user_groups (
   ug_user   NUMBER      DEFAULT 0 NOT NULL,
@@ -663,7 +663,7 @@ CREATE TABLE &mw_prefix.msg_resource (
   mr_lang varchar2(32) NOT NULL,
   mr_blob BLOB NOT NULL,
   mr_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL
-) ;
+);
 CREATE UNIQUE INDEX &mw_prefix.msg_resource_u01 ON &mw_prefix.msg_resource (mr_resource, mr_lang);
 
 CREATE TABLE &mw_prefix.msg_resource_links (
index 3ac7a28..7765784 100644 (file)
@@ -123,9 +123,9 @@ class CLIParser extends Maintenance {
         */
        protected function parse( $wikitext ) {
                return $this->parser->parse(
-                       $wikitext
-                       , $this->getTitle()
-                       new ParserOptions()
+                       $wikitext,
+                       $this->getTitle(),
+                       new ParserOptions()
                );
        }
 }
diff --git a/maintenance/populateRecentChangesSource.php b/maintenance/populateRecentChangesSource.php
new file mode 100644 (file)
index 0000000..0e8e501
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Upgrade script to populate the rc_source field
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once dirname( __FILE__ ) . '/Maintenance.php';
+
+/**
+ * Maintenance script to populate the rc_source field.
+ *
+ * @ingroup Maintenance
+ * @since 1.22
+ */
+class PopulateRecentChangesSource extends LoggedUpdateMaintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Populates rc_source field of the recentchanges table with the data in rc_type.";
+               $this->setBatchSize( 100 );
+       }
+
+       protected function doDBUpdates() {
+               $dbw = $this->getDB( DB_MASTER );
+               if ( !$dbw->fieldExists( 'recentchanges', 'rc_source' ) ) {
+                       $this->error( 'rc_source field in recentchanges table does not exist.' );
+               }
+
+               $start = $dbw->selectField( 'recentchanges', 'MIN(rc_id)', false, __METHOD__ );
+               if ( !$start ) {
+                       $this->output( "Nothing to do.\n" );
+                       return true;
+               }
+               $end = $dbw->selectField( 'recentchanges', 'MAX(rc_id)', false, __METHOD__ );
+               $end += $this->mBatchSize - 1;
+               $blockStart = $start;
+               $blockEnd = $start + $this->mBatchSize - 1;
+
+               $updatedValues = $this->buildUpdateCondition( $dbw );
+
+               while ( $blockEnd <= $end ) {
+                       $cond = "rc_id BETWEEN $blockStart AND $blockEnd";
+
+                       $dbw->update(
+                               'recentchanges',
+                               array( $updatedValues ),
+                               array(
+                                       "rc_source = ''",
+                                       "rc_id BETWEEN $blockStart AND $blockEnd"
+                               ),
+                               __METHOD__
+                       );
+
+                       $this->output( "." );
+                       wfWaitForSlaves();
+
+                       $blockStart += $this->mBatchSize;
+                       $blockEnd += $this->mBatchSize;
+               }
+
+               $this->output( "\nDone.\n" );
+       }
+
+       protected function getUpdateKey() {
+               return __CLASS__;
+       }
+
+       protected function buildUpdateCondition( DatabaseBase $dbw ) {
+               $rcNew = $dbw->addQuotes( RC_NEW );
+               $rcSrcNew = $dbw->addQuotes( RecentChange::SRC_NEW );
+               $rcEdit = $dbw->addQuotes( RC_EDIT );
+               $rcSrcEdit = $dbw->addQuotes( RecentChange::SRC_EDIT );
+               $rcLog = $dbw->addQuotes( RC_LOG );
+               $rcSrcLog = $dbw->addQuotes( RecentChange::SRC_LOG );
+               $rcExternal = $dbw->addQuotes( RC_EXTERNAL );
+               $rcSrcExternal = $dbw->addQuotes( RecentChange::SRC_EXTERNAL );
+
+               return "rc_source = CASE
+                                       WHEN rc_type = $rcNew THEN $rcSrcNew
+                                       WHEN rc_type = $rcEdit THEN $rcSrcEdit
+                                       WHEN rc_type = $rcLog THEN $rcSrcLog
+                                       WHEN rc_type = $rcExternal THEN $rcSrcExternal
+                                       ELSE ''
+                               END";
+       }
+}
+
+$maintClass = "PopulateRecentChangesSource";
+require_once RUN_MAINTENANCE_IF_MAIN;
index 3c69125..042790f 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 /**
- * Populates the rev_len field for old revisions created before MW 1.10.
+ * Populates the rev_len and ar_len fields for old revisions created
+ * before MW 1.10.
  *
  * 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
 require_once __DIR__ . '/Maintenance.php';
 
 /**
- * Maintenance script that populates the rev_len field for old revisions
- * created before MW 1.10.
+ * Maintenance script that populates the rev_len and ar_len fields
+ * for old revisions created before MW 1.10.
  *
  * @ingroup Maintenance
  */
 class PopulateRevisionLength extends LoggedUpdateMaintenance {
        public function __construct() {
                parent::__construct();
-               $this->mDescription = "Populates the rev_len field";
+               $this->mDescription = "Populates the rev_len and ar_len fields";
                $this->setBatchSize( 200 );
        }
 
        protected function getUpdateKey() {
-               return 'populate rev_len';
-       }
-
-       protected function updateSkippedMessage() {
-               return 'rev_len column of revision table already populated.';
+               return 'populate rev_len and ar_len';
        }
 
        public function doDBUpdates() {
                $db = $this->getDB( DB_MASTER );
                if ( !$db->tableExists( 'revision' ) ) {
                        $this->error( "revision table does not exist", true );
+               } elseif ( !$db->tableExists( 'archive' ) ) {
+                       $this->error( "archive table does not exist", true );
                } elseif ( !$db->fieldExists( 'revision', 'rev_len', __METHOD__ ) ) {
                        $this->output( "rev_len column does not exist\n\n", true );
                        return false;
                }
 
                $this->output( "Populating rev_len column\n" );
+               $rev = $this->doLenUpdates( 'revision', 'rev_id', 'rev', Revision::selectFields() );
+
+               $this->output( "Populating ar_len column\n" );
+               $ar = $this->doLenUpdates( 'archive', 'ar_id', 'ar', Revision::selectArchiveFields() );
+
+               $this->output( "rev_len and ar_len population complete [$rev revision rows, $ar archive rows].\n" );
+               return true;
+       }
 
-               $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __METHOD__ );
-               $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __METHOD__ );
+       /**
+        * @param string $table
+        * @param string $idCol
+        * @param string $prefix
+        * @param array $fields
+        * @return int
+        */
+       protected function doLenUpdates( $table, $idCol, $prefix, $fields ) {
+               $db = $this->getDB( DB_MASTER );
+               $start = $db->selectField( $table, "MIN($idCol)", false, __METHOD__ );
+               $end = $db->selectField( $table, "MAX($idCol)", false, __METHOD__ );
                if ( !$start || !$end ) {
-                       $this->output( "...revision table seems to be empty.\n" );
-                       return true;
+                       $this->output( "...$table table seems to be empty.\n" );
+                       return 0;
                }
 
                # Do remaining chunks
                $blockStart = intval( $start );
                $blockEnd = intval( $start ) + $this->mBatchSize - 1;
                $count = 0;
-               $missing = 0;
-               $fields = Revision::selectFields();
+
                while ( $blockStart <= $end ) {
-                       $this->output( "...doing rev_id from $blockStart to $blockEnd\n" );
+                       $this->output( "...doing $idCol from $blockStart to $blockEnd\n" );
                        $res = $db->select(
-                               'revision',
+                               $table,
                                $fields,
                                array(
-                                       "rev_id >= $blockStart",
-                                       "rev_id <= $blockEnd",
-                                       "rev_len IS NULL"
+                                       "$idCol >= $blockStart",
+                                       "$idCol <= $blockEnd",
+                                       "{$prefix}_len IS NULL"
                                ),
                                __METHOD__
                        );
+
+                       $db->begin( __METHOD__ );
                        # Go through and update rev_len from these rows.
                        foreach ( $res as $row ) {
-                               $rev = new Revision( $row );
-                               $content = $rev->getContent();
-                               if ( !$content ) {
-                                       # This should not happen, but sometimes does (bug 20757)
-                                       $this->output( "Content of revision {$row->rev_id} unavailable!\n" );
-                                       $missing++;
-                               }
-                               else {
-                                       # Update the row...
-                                       $db->update( 'revision',
-                                                        array( 'rev_len' => $content->getSize() ),
-                                                        array( 'rev_id' => $row->rev_id ),
-                                                        __METHOD__ );
+                               if ( $this->upgradeRow( $row, $table, $idCol, $prefix ) ) {
                                        $count++;
                                }
                        }
+                       $db->commit( __METHOD__ );
+
                        $blockStart += $this->mBatchSize;
                        $blockEnd += $this->mBatchSize;
                        wfWaitForSlaves();
                }
 
-               $this->output( "rev_len population complete ... {$count} rows changed ({$missing} missing)\n" );
+               return $count;
+       }
+
+       /**
+        * @param $row
+        * @param string $table
+        * @param string $idCol
+        * @param string $prefix
+        * @return bool
+        */
+       protected function upgradeRow( $row, $table, $idCol, $prefix ) {
+               $db = $this->getDB( DB_MASTER );
+
+               $rev = ( $table === 'archive' )
+                       ? Revision::newFromArchiveRow( $row )
+                       : new Revision( $row );
+
+               $content = $rev->getContent();
+               if ( !$content ) {
+                       # This should not happen, but sometimes does (bug 20757)
+                       $id = $row->$idCol;
+                       $this->output( "Content of $table $id unavailable!\n" );
+                       return false;
+               }
+
+               # Update the row...
+               $db->update( $table,
+                       array( "{$prefix}_len" => $content->getSize() ),
+                       array( $idCol => $row->$idCol ),
+                       __METHOD__
+               );
+
                return true;
        }
 }
index 8f170ab..34837e1 100644 (file)
@@ -1,7 +1,6 @@
 #!/usr/bin/perl
 
 ## Convert data from a MySQL mediawiki database into a Postgres mediawiki database
-## svn: $Id$
 
 ## NOTE: It is probably easier to dump your wiki using maintenance/dumpBackup.php
 ## and then import it with maintenance/importDump.php
@@ -181,7 +180,7 @@ $MYSQLSOCKET and $conninfo .= "\n--   socket    $MYSQLSOCKET";
 print qq{
 -- Dump of MySQL Mediawiki tables for import into a Postgres Mediawiki schema
 -- Performed by the program: $0
--- Version: $VERSION (subversion }.q{$LastChangedRevision$}.qq{)
+-- Version: $VERSION
 -- Author: Greg Sabino Mullane <greg\@turnstep.com> Comments welcome
 --
 -- This file was created: $now
index bc2428e..d0d1e92 100644 (file)
@@ -411,6 +411,7 @@ CREATE TABLE recentchanges (
   rc_this_oldid      INTEGER      NOT NULL,
   rc_last_oldid      INTEGER      NOT NULL,
   rc_type            SMALLINT     NOT NULL  DEFAULT 0,
+  rc_source          TEXT         NOT NULL,
   rc_patrolled       SMALLINT     NOT NULL  DEFAULT 0,
   rc_ip              CIDR,
   rc_old_len         INTEGER,
index 48d3897..01bd09a 100644 (file)
@@ -95,8 +95,8 @@ class PruneFileCache extends Maintenance {
                                        // Sanity check the file extension against known cache types
                                        if ( $mts < $this->minSurviveTimestamp
                                                && preg_match( '/\.(?:html|cache)(?:\.gz)?$/', $file )
-                                               && unlink( $path ) )
-                                       {
+                                               && unlink( $path )
+                                       {
                                                $daysOld = round( ( $tsNow - $mts ) / 86400, 2 );
                                                $this->output( "Deleted `$path` [days=$daysOld]\n" );
                                        }
index 9f83ee7..91c36f2 100644 (file)
@@ -69,7 +69,9 @@ class PurgeChangedFiles extends Maintenance {
                        implode( ',', array_keys( self::$typeMappings ) ) . ',all)', false, true );
                $this->addOption( 'htcp-dest', 'HTCP announcement destination (IP:port)', false, true );
                $this->addOption( 'dry-run', 'Do not send purge requests' );
+               $this->addOption( 'sleep-per-batch', 'Milliseconds to sleep between batches', false, true );
                $this->addOption( 'verbose', 'Show more output', false, false, 'v' );
+               $this->setBatchSize( 100 );
        }
 
        public function execute() {
@@ -119,7 +121,7 @@ class PurgeChangedFiles extends Maintenance {
                        $this->mOptions['verbose'] = 1;
                }
 
-               $this->verbose( 'Purging files that were: ' . implode( ', ', $typeList ) . "\n");
+               $this->verbose( 'Purging files that were: ' . implode( ', ', $typeList ) . "\n" );
                foreach ( $typeList as $type ) {
                        $this->verbose( "Checking for {$type} files...\n" );
                        $this->purgeFromLogType( $type );
@@ -154,6 +156,7 @@ class PurgeChangedFiles extends Maintenance {
                                __METHOD__
                        );
 
+                       $bSize = 0;
                        foreach ( $res as $row ) {
                                $file = $repo->newFile( Title::makeTitle( NS_FILE, $row->log_title ) );
 
@@ -183,7 +186,7 @@ class PurgeChangedFiles extends Maintenance {
                                        // Purge items from fileachive table (rows are likely here)
                                        $this->purgeFromArchiveTable( $repo, $file );
 
-                               } else if ( $logType === 'move' ) {
+                               } elseif ( $logType === 'move' ) {
                                        // Purge the target file as well
 
                                        $params = unserialize( $row->log_params );
@@ -197,6 +200,12 @@ class PurgeChangedFiles extends Maintenance {
                                }
 
                                $this->verbose( "Purged file {$row->log_title}; {$type} @{$row->log_timestamp}.\n" );
+
+                               if ( $this->hasOption( 'sleep-per-batch' ) && ++$bSize > $this->mBatchSize ) {
+                                       $bSize = 0;
+                                       // sleep-per-batch is milliseconds, usleep wants micro seconds.
+                                       usleep( 1000 * (int)$this->getOption( 'sleep-per-batch' ) );
+                               }
                        }
                }
        }
index 7e15c09..ee3f709 100644 (file)
@@ -174,8 +174,6 @@ class ReassignEdits extends Maintenance {
                $user->load();
                return $user;
        }
-
-
 }
 
 $maintClass = "ReassignEdits";
index 53bf823..ed67ccd 100644 (file)
@@ -205,9 +205,16 @@ class ImageBuilder extends Maintenance {
                }
                if ( !$this->dryrun ) {
                        $file = wfLocalFile( $filename );
-                       if ( !$file->recordUpload( '', '(recovered file, missing upload log entry)', '', '', '',
-                               false, $timestamp ) )
-                       {
+                       if ( !$file->recordUpload(
+                                       '',
+                                       '(recovered file, missing upload log entry)',
+                                       '',
+                                       '',
+                                       '',
+                                       false,
+                                       $timestamp
+                               )
+                       ) {
                                $this->output( "Error uploading file $fullpath\n" );
                                return;
                        }
index b7f306b..5833f8c 100644 (file)
@@ -90,7 +90,7 @@ class RebuildLocalisationCache extends Maintenance {
                if ( $this->hasOption( 'outdir' ) ) {
                        $conf['storeDirectory'] = $this->getOption( 'outdir' );
                }
-               $lc = new LocalisationCache_BulkLoad( $conf );
+               $lc = new LocalisationCacheBulkLoad( $conf );
 
                $allCodes = array_keys( Language::fetchLanguageNames( null, 'mwfile' ) );
                if ( $this->hasOption( 'lang' ) ) {
@@ -149,7 +149,7 @@ class RebuildLocalisationCache extends Maintenance {
         * Helper function to rebuild list of languages codes. Prints the code
         * for each language which is rebuilt.
         * @param $codes array List of language codes to rebuild.
-        * @param $lc LocalisationCache Instance of LocalisationCache_BulkLoad (?)
+        * @param $lc LocalisationCache Instance of LocalisationCacheBulkLoad (?)
         * @param $force bool Rebuild up-to-date languages
         * @return int Number of rebuilt languages
         */
index 1834825..b9eb809 100644 (file)
@@ -70,7 +70,6 @@ class RebuildRecentchanges extends Maintenance {
                $dbw->insertSelect( 'recentchanges', array( 'page', 'revision' ),
                        array(
                                'rc_timestamp'  => 'rev_timestamp',
-                               'rc_cur_time'   => 'rev_timestamp',
                                'rc_user'       => 'rev_user',
                                'rc_user_text'  => 'rev_user_text',
                                'rc_namespace'  => 'page_namespace',
@@ -83,6 +82,7 @@ class RebuildRecentchanges extends Maintenance {
                                'rc_this_oldid' => 'rev_id',
                                'rc_last_oldid' => 0, // is this ok?
                                'rc_type'       => $dbw->conditional( 'page_is_new != 0', RC_NEW, RC_EDIT ),
+                               'rc_source'     => $dbw->conditional( 'page_is_new != 0', $dbw->addQuotes( RecentChange::SRC_NEW ), $dbw->addQuotes( RecentChange::SRC_EDIT ) ),
                                'rc_deleted'    => 'rev_deleted'
                        ), array(
                                'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) ),
@@ -184,7 +184,6 @@ class RebuildRecentchanges extends Maintenance {
                $dbw->insertSelect( 'recentchanges', array( 'user', "$logging LEFT JOIN $page ON (log_namespace=page_namespace AND log_title=page_title)" ),
                        array(
                                'rc_timestamp'  => 'log_timestamp',
-                               'rc_cur_time'   => 'log_timestamp',
                                'rc_user'       => 'log_user',
                                'rc_user_text'  => 'user_name',
                                'rc_namespace'  => 'log_namespace',
index 7fe5c4c..9f73e49 100644 (file)
@@ -207,6 +207,5 @@ class RefreshImageMetadata extends Maintenance {
        }
 }
 
-
 $maintClass = 'RefreshImageMetadata';
 require_once RUN_MAINTENANCE_IF_MAIN;
index 93ba24a..76340cd 100644 (file)
@@ -60,6 +60,5 @@ class BatchedQueryRunner extends Maintenance {
        }
 }
 
-
 $maintClass = "BatchedQueryRunner";
 require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/runScript.php b/maintenance/runScript.php
new file mode 100644 (file)
index 0000000..385db15
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Convenience maintenance script wrapper, useful for scripts
+ * or extensions located outside of standard locations.
+ *
+ * To use, give the maintenance script as a relative or full path.
+ *
+ * Example usage:
+ *
+ *  If your pwd is mediawiki base folder:
+ *   php maintenance/runScript.php extensions/Wikibase/lib/maintenance/dispatchChanges.php
+ *
+ * If your pwd is maintenance folder:
+ *  php runScript.php ../extensions/Wikibase/lib/maintenance/dispatchChanges.php
+ *
+ * Or full path:
+ *  php /var/www/mediawiki/maintenance/runScript.php maintenance/runJobs.php
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ * @file
+ * @ingroup Maintenance
+ */
+$IP = getenv( 'MW_INSTALL_PATH' );
+
+if ( $IP === false ) {
+       $IP = dirname( __DIR__ );
+
+       putenv( "MW_INSTALL_PATH=$IP" );
+}
+
+require_once "$IP/maintenance/Maintenance.php";
+
+if ( !isset( $argv[1] ) ) {
+       fwrite( STDERR, "This script requires a maintainance script as an argument.\n"
+               . "Usage: runScript.php extensions/Wikibase/lib/maintenance/dispatchChanges\n" );
+       exit( 1 );
+}
+
+$scriptFilename = $argv[1];
+array_shift( $argv );
+
+$scriptFile = realpath( $scriptFilename );
+
+if ( !$scriptFile ) {
+       fwrite( STDERR, "The MediaWiki script file \"{$scriptFilename}\" does not exist.\n" );
+       exit( 1 );
+}
+
+require_once $scriptFile;
index cd9768d..9168d6f 100644 (file)
@@ -57,7 +57,6 @@ class ShowCacheStats extends Maintenance {
                $this->output( sprintf( "without session:   %-10d %6.2f%%\n", $noSession, $noSession / $total * 100 ) );
                $this->output( sprintf( "total:             %-10d %6.2f%%\n", $total, 100 ) );
 
-
                $this->output( "\nParser cache\n" );
                $hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_hit' ) ) );
                $expired = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_expired' ) ) );
index 1a59be5..954c85d 100644 (file)
@@ -237,13 +237,13 @@ CREATE UNIQUE INDEX /*i*/iw_prefix ON /*_*/interwiki_tmp (iw_prefix);
 
 
 CREATE TABLE /*_*/page_restrictions_tmp (
+  pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
   pr_page int NOT NULL,
   pr_type varbinary(60) NOT NULL,
   pr_level varbinary(60) NOT NULL,
   pr_cascade tinyint NOT NULL,
   pr_user int NULL,
-  pr_expiry varbinary(14) NULL,
-  pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT
+  pr_expiry varbinary(14) NULL
 );
 
 CREATE UNIQUE INDEX /*i*/pr_pagetype ON /*_*/page_restrictions_tmp (pr_page,pr_type);
index 03dc113..9174d12 100644 (file)
@@ -34,7 +34,6 @@ if ( !defined( 'MEDIAWIKI' ) ) {
        $cs->check( $fix, $xml );
 }
 
-
 // ----------------------------------------------------------------------------------
 
 /**
@@ -331,7 +330,6 @@ class CheckStorage {
                }
        }
 
-
        function error( $type, $msg, $ids ) {
                if ( is_array( $ids ) && count( $ids ) == 1 ) {
                        $ids = reset( $ids );
index 8cb5548..3b59f1d 100644 (file)
@@ -177,8 +177,8 @@ class CompressOld extends Maintenance {
         * @return bool
         */
        private function compressWithConcat( $startId, $maxChunkSize, $beginDate,
-               $endDate, $extdb = "", $maxPageId = false )
-       {
+               $endDate, $extdb = "", $maxPageId = false
+       {
                $loadStyle = self::LS_CHUNKED;
 
                $dbr = wfGetDB( DB_SLAVE );
index 101aa06..e832b4e 100644 (file)
@@ -58,8 +58,8 @@ class FixBug20757 extends Maintenance {
                $totalRevs = $dbr->selectField( 'text', 'MAX(old_id)', false, __METHOD__ );
 
                if ( $dbr->getType() == 'mysql'
-                       && version_compare( $dbr->getServerVersion(), '4.1.0', '>=' ) )
-               {
+                       && version_compare( $dbr->getServerVersion(), '4.1.0', '>=' )
+               {
                        // In MySQL 4.1+, the binary field old_text has a non-working LOWER() function
                        $lowerLeft = 'LOWER(CONVERT(LEFT(old_text,22) USING latin1))';
                } else {
index fdc28d9..d693986 100644 (file)
@@ -45,7 +45,6 @@ if ( isset( $options['limit'] ) ) {
 }
 $type = isset( $options['type'] ) ? $options['type'] : 'ConcatenatedGzipHistoryBlob';
 
-
 $dbr = wfGetDB( DB_SLAVE );
 $res = $dbr->select(
        array( 'page', 'revision', 'text' ),
index 7857dd9..c2df0dd 100644 (file)
@@ -24,7 +24,6 @@
 
 require __DIR__ . '/../commandLine.inc';
 
-
 if ( count( $args ) < 1 ) {
        echo "Usage: php trackBlobs.php <cluster> [... <cluster>]\n";
        echo "Adds blobs from a given ES cluster to the blob_tracking table\n";
index de92ef5..18139b2 100644 (file)
@@ -1026,6 +1026,8 @@ CREATE TABLE /*_*/recentchanges (
   rc_timestamp varbinary(14) NOT NULL default '',
 
   -- This is no longer used
+  -- Field kept in database for downgrades
+  -- @todo: add drop patch with 1.24
   rc_cur_time varbinary(14) NOT NULL default '',
 
   -- As in revision
@@ -1062,6 +1064,10 @@ CREATE TABLE /*_*/recentchanges (
   -- The type of change entry (RC_EDIT,RC_NEW,RC_LOG,RC_EXTERNAL)
   rc_type tinyint unsigned NOT NULL default 0,
 
+  -- The source of the change entry (replaces rc_type)
+  -- default of '' is temporary, needed for initial migration
+  rc_source varchar(16) binary not null default '',
+
   -- If the Recent Changes Patrol option is enabled,
   -- users may mark edits as having been reviewed to
   -- remove a warning flag on the RC list.
@@ -1109,8 +1115,9 @@ CREATE TABLE /*_*/watchlist (
   wl_namespace int NOT NULL default 0,
   wl_title varchar(255) binary NOT NULL default '',
 
-  -- Timestamp when user was last sent a notification e-mail;
-  -- cleared when the user visits the page.
+  -- Timestamp used to send notification e-mails and show "updated since last visit" markers on
+  -- history and recent changes / watchlist. Set to NULL when the user visits the latest revision
+  -- of the page, which means that they should be sent an e-mail on the next change.
   wl_notificationtimestamp varbinary(14)
 
 ) /*$wgDBTableOptions*/;
@@ -1369,6 +1376,8 @@ CREATE INDEX /*i*/qcc_titletwo ON /*_*/querycachetwo (qcc_type,qcc_namespacetwo,
 
 -- Used for storing page restrictions (i.e. protection levels)
 CREATE TABLE /*_*/page_restrictions (
+  -- Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)
+  pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
   -- Page to apply restrictions to (Foreign Key to page).
   pr_page int NOT NULL,
   -- The protection type (edit, move, etc)
@@ -1380,9 +1389,7 @@ CREATE TABLE /*_*/page_restrictions (
   -- Field for future support of per-user restriction.
   pr_user int NULL,
   -- Field for time-limited protection.
-  pr_expiry varbinary(14) NULL,
-  -- Field for an ID for this restrictions row (sort-key for Special:ProtectedPages)
-  pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT
+  pr_expiry varbinary(14) NULL
 ) /*$wgDBTableOptions*/;
 
 CREATE UNIQUE INDEX /*i*/pr_pagetype ON /*_*/page_restrictions (pr_page,pr_type);
@@ -1514,7 +1521,7 @@ CREATE UNIQUE INDEX /*i*/md_module_skin ON /*_*/module_deps (md_module, md_skin)
 
 -- Holds all the sites known to the wiki.
 CREATE TABLE /*_*/sites (
--- Numeric id of the site
+  -- Numeric id of the site
   site_id                    INT UNSIGNED        NOT NULL PRIMARY KEY AUTO_INCREMENT,
 
   -- Global identifier for the site, ie 'enwiktionary'
index 378217f..51bbd6f 100644 (file)
@@ -132,6 +132,8 @@ class UpdateMediaWiki extends Maintenance {
                        wfCountDown( 5 );
                }
 
+               $time1 = new MWTimestamp();
+
                $shared = $this->hasOption( 'doshared' );
 
                $updates = array( 'core', 'extensions' );
@@ -164,8 +166,10 @@ class UpdateMediaWiki extends Maintenance {
                if ( !$this->hasOption( 'nopurge' ) ) {
                        $updater->purgeCache();
                }
+               $time2 = new MWTimestamp();
 
                $this->output( "\nDone.\n" );
+               $this->output( "\nThe job took " . $time2->diff( $time1 )->format( "%i:%S" ) . ".\n" );
        }
 
        function afterFinalSetup() {
@@ -176,7 +180,7 @@ class UpdateMediaWiki extends Maintenance {
                # cache from $wgExtensionFunctions (bug 20471)
                $wgLocalisationCacheConf = array(
                        'class' => 'LocalisationCache',
-                       'storeClass' => 'LCStore_Null',
+                       'storeClass' => 'LCStoreNull',
                        'storeDirectory' => false,
                        'manualRecache' => false,
                );
index 964b313..7ca04b4 100644 (file)
@@ -47,7 +47,7 @@ class UpdateCollation extends Maintenance {
                $this->mDescription = <<<TEXT
 This script will find all rows in the categorylinks table whose collation is
 out-of-date (cl_collation != '$wgCategoryCollation') and repopulate cl_sortkey
-using the page title and cl_sortkey_prefix.  If everything's collation is
+using the page title and cl_sortkey_prefix.  If all collations are
 up-to-date, it will do nothing.
 TEXT;
 
@@ -188,15 +188,14 @@ TEXT;
                                                __METHOD__
                                        );
                                }
+                               if ( $row ) {
+                                       $batchConds = array( $this->getBatchCondition( $row, $dbw ) );
+                               }
                        }
                        if ( !$dryRun ) {
                                $dbw->commit( __METHOD__ );
                        }
 
-                       if ( $row ) {
-                               $batchConds = array( $this->getBatchCondition( $row ) );
-                       }
-
                        $count += $res->numRows();
                        $this->output( "$count done.\n" );
 
@@ -219,8 +218,7 @@ TEXT;
         * Return an SQL expression selecting rows which sort above the given row,
         * assuming an ordering of cl_to, cl_type, cl_from
         */
-       function getBatchCondition( $row ) {
-               $dbw = $this->getDB( DB_MASTER );
+       function getBatchCondition( $row, $dbw ) {
                $fields = array( 'cl_to', 'cl_type', 'cl_from' );
                $first = true;
                $cond = false;
index 8bd80c9..44a1aab 100644 (file)
@@ -184,7 +184,7 @@ class UserDupes {
        function getDupes() {
                $user = $this->db->tableName( 'user' );
                $result = $this->db->query(
-                        "SELECT user_name,COUNT(*) AS n
+                       "SELECT user_name,COUNT(*) AS n
                                FROM $user
                        GROUP BY user_name
                          HAVING n > 1", __METHOD__ );
index 51da80d..f497f2a 100644 (file)
@@ -30,7 +30,7 @@ require_once __DIR__ . '/commandLine.inc';
 /**
  * @ingroup Maintenance
  */
-class userOptions {
+class UserOptions {
        public $mQuick;
        public $mQuiet;
        public $mDry;
@@ -43,13 +43,12 @@ class userOptions {
        /** Constructor. Will show usage and exit if script options are not correct */
        function __construct( $opts, $args ) {
                if ( !$this->checkOpts( $opts, $args ) ) {
-                       userOptions::showUsageAndExit();
+                       UserOptions::showUsageAndExit();
                } else {
                        $this->mReady = $this->initializeOpts( $opts, $args );
                }
        }
 
-
        /**
         * This is used to check options. Only needed on construction
         *
@@ -179,7 +178,6 @@ class userOptions {
                }
        }
 
-
        /** Change our users options */
        private function CHANGER() {
                $this->warn();
index e0de357..53db48c 100644 (file)
@@ -28,7 +28,7 @@
 require_once 'userOptions.inc';
 
 // Load up our tool system, exit with usage() if options are not fine
-$uo = new userOptions( $options, $args );
+$uo = new UserOptions( $options, $args );
 
 $uo->run();
 
index 2c02de8..a022c6d 100644 (file)
@@ -87,7 +87,7 @@ return array(
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
        ),
        'skins.vector' => array(
-               // Keep in sync with WebInstallerOutput::getCSS()
+               // Used in the web installer. Test it after modifying this definition!
                'styles' => array(
                        'common/commonElements.css' => array( 'media' => 'screen' ),
                        'common/commonContent.css' => array( 'media' => 'screen' ),
@@ -103,7 +103,7 @@ return array(
                        'common/commonElements.css' => array( 'media' => 'screen' ),
                        'common/commonContent.css' => array( 'media' => 'screen' ),
                        'common/commonInterface.css' => array( 'media' => 'screen' ),
-                       'vector/styles-beta.less' => array( 'media' => 'screen' ),
+                       'vector/styles-beta.less',
                ),
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
@@ -158,6 +158,7 @@ return array(
        'jquery.autoEllipsis' => array(
                'scripts' => 'resources/jquery/jquery.autoEllipsis.js',
                'dependencies' => 'jquery.highlightText',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.badge' => array(
                'scripts' => 'resources/jquery/jquery.badge.js',
@@ -171,6 +172,7 @@ return array(
        'jquery.byteLimit' => array(
                'scripts' => 'resources/jquery/jquery.byteLimit.js',
                'dependencies' => 'jquery.byteLength',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.checkboxShiftClick' => array(
                'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js',
@@ -225,6 +227,7 @@ return array(
        'jquery.highlightText' => array(
                'scripts' => 'resources/jquery/jquery.highlightText.js',
                'dependencies' => 'jquery.mwExtension',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'jquery.hoverIntent' => array(
                'scripts' => 'resources/jquery/jquery.hoverIntent.js',
@@ -605,6 +608,7 @@ return array(
        'mediawiki.api' => array(
                'scripts' => 'resources/mediawiki.api/mediawiki.api.js',
                'dependencies' => 'mediawiki.util',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.api.category' => array(
                'scripts' => 'resources/mediawiki.api/mediawiki.api.category.js',
@@ -637,9 +641,6 @@ return array(
                        'user.tokens',
                ),
        ),
-       'mediawiki.icon' => array(
-               'styles' => 'resources/mediawiki/mediawiki.icon.css',
-       ),
        'mediawiki.debug' => array(
                'scripts' => 'resources/mediawiki/mediawiki.debug.js',
                'styles' => 'resources/mediawiki/mediawiki.debug.css',
@@ -653,14 +654,6 @@ return array(
                // must be loaded on the bottom
                'position' => 'bottom',
        ),
-       'mediawiki.inspect' => array(
-               'scripts' => 'resources/mediawiki/mediawiki.inspect.js',
-               'dependencies' => array(
-                       'jquery.byteLength',
-                       'jquery.json',
-               ),
-               'targets' => array( 'desktop', 'mobile' ),
-       ),
        'mediawiki.feedback' => array(
                'scripts' => 'resources/mediawiki/mediawiki.feedback.js',
                'styles' => 'resources/mediawiki/mediawiki.feedback.css',
@@ -693,16 +686,35 @@ return array(
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
+       'mediawiki.hlist' => array(
+               'styles' => 'resources/mediawiki/mediawiki.hlist.css',
+               'scripts' => 'resources/mediawiki/mediawiki.hlist.js',
+               'dependencies' => array(
+                       'jquery.client',
+               ),
+       ),
        'mediawiki.htmlform' => array(
                'scripts' => 'resources/mediawiki/mediawiki.htmlform.js',
                'messages' => array( 'htmlform-chosen-placeholder' ),
        ),
+       'mediawiki.icon' => array(
+               'styles' => 'resources/mediawiki/mediawiki.icon.css',
+       ),
+       'mediawiki.inspect' => array(
+               'scripts' => 'resources/mediawiki/mediawiki.inspect.js',
+               'dependencies' => array(
+                       'jquery.byteLength',
+                       'jquery.json',
+               ),
+               'targets' => array( 'desktop', 'mobile' ),
+       ),
        'mediawiki.notification' => array(
                'styles' => 'resources/mediawiki/mediawiki.notification.css',
                'scripts' => 'resources/mediawiki/mediawiki.notification.js',
                'dependencies' => array(
                        'mediawiki.page.startup',
                ),
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.notify' => array(
                'scripts' => 'resources/mediawiki/mediawiki.notify.js',
@@ -729,9 +741,11 @@ return array(
                        'jquery.byteLength',
                        'mediawiki.util',
                ),
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.Uri' => array(
                'scripts' => 'resources/mediawiki/mediawiki.Uri.js',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.user' => array(
                'scripts' => 'resources/mediawiki/mediawiki.user.js',
@@ -741,6 +755,7 @@ return array(
                        'user.options',
                        'user.tokens',
                ),
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.util' => array(
                'scripts' => 'resources/mediawiki/mediawiki.util.js',
@@ -793,6 +808,7 @@ return array(
        'mediawiki.action.history.diff' => array(
                'styles' => 'resources/mediawiki.action/mediawiki.action.history.diff.css',
                'group' => 'mediawiki.action.history',
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.action.view.dblClickEdit' => array(
                'scripts' => 'resources/mediawiki.action/mediawiki.action.view.dblClickEdit.js',
@@ -1011,6 +1027,9 @@ return array(
                'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
                'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
                'position' => 'top',
+               'skinStyles' => array(
+                       'vector' => 'skins/vector/special.preferences.less',
+               ),
        ),
        'mediawiki.special.recentchanges' => array(
                'scripts' => 'resources/mediawiki.special/mediawiki.special.recentchanges.js',
@@ -1040,7 +1059,10 @@ return array(
                        'size-gigabytes',
                        'largefileserver',
                ),
-               'dependencies' => array( 'mediawiki.libs.jpegmeta', 'mediawiki.util' ),
+               'dependencies' => array(
+                       'mediawiki.libs.jpegmeta',
+                       'mediawiki.util',
+               ),
        ),
        'mediawiki.special.userlogin' => array(
                'styles' => array(
@@ -1109,14 +1131,9 @@ return array(
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
        ),
        'mediawiki.legacy.config' => array(
+               // Used in the web installer. Test it after modifying this definition!
                'scripts' => 'common/config.js',
-               'styles' => array( 'common/config.css', 'common/config-cc.css' ),
-               'remoteBasePath' => $GLOBALS['wgStylePath'],
-               'localBasePath' => $GLOBALS['wgStyleDirectory'],
-               'dependencies' => 'mediawiki.legacy.wikibits',
-       ),
-       'mediawiki.legacy.IEFixes' => array(
-               'scripts' => 'common/IEFixes.js',
+               'styles' => array( 'common/config.css' ),
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
                'dependencies' => 'mediawiki.legacy.wikibits',
@@ -1126,12 +1143,12 @@ return array(
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
                'dependencies' => array(
-                       'mediawiki.legacy.wikibits',
                        'jquery.byteLimit',
                ),
                'position' => 'top',
        ),
        'mediawiki.legacy.shared' => array(
+               // Used in the web installer. Test it after modifying this definition!
                'styles' => array( 'common/shared.css' => array( 'media' => 'screen' ) ),
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
@@ -1146,9 +1163,9 @@ return array(
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
                'dependencies' => array(
+                       'jquery.spinner',
                        'mediawiki.api',
                        'mediawiki.Title',
-                       'mediawiki.legacy.wikibits',
                        'mediawiki.util',
                ),
        ),
@@ -1163,8 +1180,8 @@ return array(
        ),
        'mediawiki.ui' => array(
                'skinStyles' => array(
-                       'default' => 'resources/mediawiki.ui/mediawiki.ui.default.css',
-                       'vector' => 'resources/mediawiki.ui/mediawiki.ui.vector.css',
+                       'default' => 'resources/mediawiki.ui/default.less',
+                       'vector' => 'resources/mediawiki.ui/vector.less',
                ),
                'position' => 'top',
        ),
index 993fa8c..38938ab 100644 (file)
@@ -3,6 +3,11 @@
        float: right;
 }
 
+/* collapse links in captions should be inline */
+caption .mw-collapsible-toggle {
+       float: none;
+}
+
 /* list-items go as wide as their parent element, don't float them inside list items */
 li .mw-collapsible-toggle {
        float: none;
index 0cd6417..60c0afc 100644 (file)
@@ -15,8 +15,6 @@
  * @license GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
  */
 ( function ( $, mw ) {
-       var lpx = 'jquery.makeCollapsible> ';
-
        /**
         * Handler for a click on a collapsible toggler.
         *
 
                if ( !options.plainMode && $collapsible.is( 'table' ) ) {
                        // Tables
-                       $containers = $collapsible.find( '> tbody > tr' );
+                       // If there is a caption, hide all rows; otherwise, only hide body rows
+                       if ( $collapsible.find( '> caption' ).length ) {
+                               $containers = $collapsible.find( '> * > tr' );
+                       } else {
+                               $containers = $collapsible.find( '> tbody > tr' );
+                       }
                        if ( $defaultToggle ) {
                                // Exclude table row containing togglelink
                                $containers = $containers.not( $defaultToggle.closest( 'tr' ) );
                }
 
                return this.each( function () {
-                       var $collapsible, collapseText, expandText, $toggle, actionHandler, buildDefaultToggleLink,
+                       var $collapsible, collapseText, expandText, $caption, $toggle, actionHandler, buildDefaultToggleLink,
                                premadeToggleHandler, $toggleLink, $firstItem, collapsibleId, $customTogglers, firstval;
 
                        // Ensure class "mw-collapsible" is present in case .makeCollapsible()
                        } else {
                                collapsibleId = $collapsible.attr( 'id' ) || '';
                                if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
-                                       mw.log( lpx + 'Found custom collapsible: #' + collapsibleId );
                                        $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
-
-                                       // Double check that there is actually a customtoggle link
-                                       if ( !$customTogglers.length ) {
-                                               mw.log( lpx + '#' + collapsibleId + ': Missing toggler!' );
-                                       }
                                }
                        }
 
-                       // Bind the togglers
+                       // Add event handlers to custom togglers or create our own ones
                        if ( $customTogglers && $customTogglers.length ) {
                                actionHandler = function ( e, opts ) {
                                        var defaultOpts = {};
                                // contents and add the toggle link. Different elements are
                                // treated differently.
                                if ( $collapsible.is( 'table' ) ) {
-                                       // The toggle-link will be in one the the cells (td or th) of the first row
-                                       $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
-                                       $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
 
-                                       // If theres no toggle link, add it to the last cell
-                                       if ( !$toggle.length ) {
-                                               $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
+                                       // If the table has a caption, collapse to the caption
+                                       // as opposed to the first row
+                                       $caption = $collapsible.find( '> caption' );
+                                       if ( $caption.length ) {
+                                               $toggle = $caption.find( '> .mw-collapsible-toggle' );
+
+                                               // If there is no toggle link, add it to the end of the caption
+                                               if ( !$toggle.length ) {
+                                                       $toggleLink = buildDefaultToggleLink().appendTo( $caption );
+                                               } else {
+                                                       actionHandler = premadeToggleHandler;
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               }
                                        } else {
-                                               actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               // The toggle-link will be in one the the cells (td or th) of the first row
+                                               $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
+                                               $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
+
+                                               // If theres no toggle link, add it to the last cell
+                                               if ( !$toggle.length ) {
+                                                       $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
+                                               } else {
+                                                       actionHandler = premadeToggleHandler;
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               }
                                        }
 
                                } else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
index 8044d88..5020b37 100644 (file)
  *
  * This will automatically use the HTML5 placeholder attribute if supported, or emulate this behavior if not.
  *
+ * This is a fork from Mathias Bynens' jquery.placeholder as of this commit
+ * https://github.com/mathiasbynens/jquery-placeholder/blob/47f05d400e2dd16b59d144141a2cf54a9a77c502/jquery.placeholder.js
+ *
+ * @author Mathias Bynens <http://mathiasbynens.be/>
  * @author Trevor Parscal <tparscal@wikimedia.org>, 2012
  * @author Krinkle <krinklemail@gmail.com>, 2012
- * @version 0.2.0
- * @license GPL v2
+ * @author Alex Ivanov <alexivanov97@gmail.com>, 2013
+ * @version 2.1.0
+ * @license MIT
  */
-( function ( $ ) {
+(function($) {
 
-       $.fn.placeholder = function ( text ) {
-               var hasArg = arguments.length;
+       var isInputSupported = 'placeholder' in document.createElement('input'),
+               isTextareaSupported = 'placeholder' in document.createElement('textarea'),
+               prototype = $.fn,
+               valHooks = $.valHooks,
+               propHooks = $.propHooks,
+               hooks,
+               placeholder;
 
-               return this.each( function () {
-                       var placeholder, $input;
+       if (isInputSupported && isTextareaSupported) {
 
-                       if ( hasArg ) {
-                               this.setAttribute( 'placeholder', text );
-                       }
+               placeholder = prototype.placeholder = function(text) {
+                       var hasArgs = arguments.length;
 
-                       // If the HTML5 placeholder attribute is supported, use it
-                       if ( this.placeholder && 'placeholder' in document.createElement( this.tagName ) ) {
-                               return;
+                       if( hasArgs ) {
+                               changePlaceholder.call(this, text);
                        }
 
-                       placeholder = hasArg ? text : this.getAttribute( 'placeholder' );
-                       $input = $(this);
+                       return this;
+               };
+
+               placeholder.input = placeholder.textarea = true;
+
+       } else {
 
-                       // Show initially, if empty
-                       if ( this.value === '' || this.value === placeholder ) {
-                               $input.addClass( 'placeholder' ).val( placeholder );
+               placeholder = prototype.placeholder = function(text) {
+                       var $this = this,
+                               hasArgs = arguments.length;
+
+                       if(hasArgs) {
+                               changePlaceholder.call(this, text);
                        }
 
-                       $input
-                               // Show on blur if empty
-                               .blur( function () {
-                                       if ( this.value === '' ) {
-                                               this.value = placeholder;
-                                               $input.addClass( 'placeholder' );
-                                       }
-                               } )
-
-                               // Hide on focus
-                               // Also listen for other events in case $input was
-                               // already focused when the events were bound
-                               .on( 'focus drop keydown paste', function ( e ) {
-                                       if ( $input.hasClass( 'placeholder' ) ) {
-                                               if ( e.type === 'drop' && e.originalEvent.dataTransfer ) {
-                                                       // Support for drag&drop. Instead of inserting the dropped
-                                                       // text somewhere in the middle of the placeholder string,
-                                                       // we want to set the contents of the search box to the
-                                                       // dropped text.
-
-                                                       // IE wants getData( 'text' ) but Firefox wants getData( 'text/plain' )
-                                                       // Firefox fails gracefully with an empty string, IE barfs with an error
-                                                       try {
-                                                               // Try the Firefox way
-                                                               this.value = e.originalEvent.dataTransfer.getData( 'text/plain' );
-                                                       } catch ( exception ) {
-                                                               // Got an exception, so use the IE way
-                                                               this.value = e.originalEvent.dataTransfer.getData( 'text' );
-                                                       }
-
-                                                       // On Firefox, drop fires after the dropped text has been inserted,
-                                                       // but on IE it fires before. If we don't prevent the default action,
-                                                       // IE will insert the dropped text twice.
-                                                       e.preventDefault();
-                                               } else {
-                                                       this.value = '';
-                                               }
-                                               $input.removeClass( 'placeholder' );
+
+                       $this
+                               .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
+                               .filter(function() {
+                                       return !$(this).data('placeholder-enabled');
+                               })
+                               .bind({
+                                       'focus.placeholder drop.placeholder': clearPlaceholder,
+                                       'blur.placeholder': setPlaceholder
+                               })
+                               .data('placeholder-enabled', true)
+                               .trigger('blur.placeholder');
+                       return $this;
+               };
+
+               placeholder.input = isInputSupported;
+               placeholder.textarea = isTextareaSupported;
+
+               hooks = {
+                       'get': function(element) {
+                               var $element = $(element),
+                                       $passwordInput = $element.data('placeholder-password');
+                               if ($passwordInput) {
+                                       return $passwordInput[0].value;
+                               }
+
+                               return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
+                       },
+                       'set': function(element, value) {
+                               var $element = $(element),
+                                       $passwordInput = $element.data('placeholder-password');
+                               if ($passwordInput) {
+                                       $passwordInput[0].value = value;
+                                       return value;
+                               }
+
+                               if (!$element.data('placeholder-enabled')) {
+                                       element.value = value;
+                                       return value;
+                               }
+                               if (!value) {
+                                       element.value = value;
+                                       // Issue #56: Setting the placeholder causes problems if the element continues to have focus.
+                                       if (element !== safeActiveElement()) {
+                                               // We can't use `triggerHandler` here because of dummy text/password inputs :(
+                                               setPlaceholder.call(element);
                                        }
-                               } );
-
-                       // Blank on submit -- prevents submitting with unintended value
-                       if ( this.form ) {
-                               $( this.form ).submit( function () {
-                                       // $input.trigger( 'focus' ); would be problematic
-                                       // because it actually focuses $input, leading
-                                       // to nasty behavior in mobile browsers
-                                       if ( $input.hasClass( 'placeholder' ) ) {
-                                               $input
-                                                       .val( '' )
-                                                       .removeClass( 'placeholder' );
+                               } else if ($element.hasClass('placeholder')) {
+                                       if(!clearPlaceholder.call(element, true, value)) {
+                                               element.value = value;
                                        }
-                               });
+                               } else {
+                                       element.value = value;
+                               }
+                               // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
+                               return $element;
                        }
+               };
+
+               if (!isInputSupported) {
+                       valHooks.input = hooks;
+                       propHooks.value = hooks;
+               }
+               if (!isTextareaSupported) {
+                       valHooks.textarea = hooks;
+                       propHooks.value = hooks;
+               }
+
+               $(function() {
+                       // Look for forms
+                       $(document).delegate('form', 'submit.placeholder', function() {
+                               // Clear the placeholder values so they don't get submitted
+                               var $inputs = $('.placeholder', this).each(clearPlaceholder);
+                               setTimeout(function() {
+                                       $inputs.each(setPlaceholder);
+                               }, 10);
+                       });
+               });
 
+               // Clear placeholder values upon page reload
+               $(window).bind('beforeunload.placeholder', function() {
+                       $('.placeholder').each(function() {
+                               this.value = '';
+                       });
                });
-       };
 
-}( jQuery ) );
+       }
+
+       function args(elem) {
+               // Return an object of element attributes
+               var newAttrs = {},
+                       rinlinejQuery = /^jQuery\d+$/;
+               $.each(elem.attributes, function(i, attr) {
+                       if (attr.specified && !rinlinejQuery.test(attr.name)) {
+                               newAttrs[attr.name] = attr.value;
+                       }
+               });
+               return newAttrs;
+       }
+
+       function clearPlaceholder(event, value) {
+               var input = this,
+                       $input = $(input);
+               if (input.value === $input.attr('placeholder') && $input.hasClass('placeholder')) {
+                       if ($input.data('placeholder-password')) {
+                               $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
+                               // If `clearPlaceholder` was called from `$.valHooks.input.set`
+                               if (event === true) {
+                                       $input[0].value = value;
+                                       return value;
+                               }
+                               $input.focus();
+                       } else {
+                               input.value = '';
+                               $input.removeClass('placeholder');
+                               if(input === safeActiveElement()) {
+                                       input.select();
+                               }
+                       }
+               }
+       }
+
+       function setPlaceholder() {
+               var $replacement,
+                       input = this,
+                       $input = $(input),
+                       id = this.id;
+               if (!input.value) {
+                       if (input.type === 'password') {
+                               if (!$input.data('placeholder-textinput')) {
+                                       try {
+                                               $replacement = $input.clone().attr({ 'type': 'text' });
+                                       } catch(e) {
+                                               $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
+                                       }
+                                       $replacement
+                                               .removeAttr('name')
+                                               .data({
+                                                       'placeholder-password': $input,
+                                                       'placeholder-id': id
+                                               })
+                                               .bind('focus.placeholder drop.placeholder', clearPlaceholder);
+                                       $input
+                                               .data({
+                                                       'placeholder-textinput': $replacement,
+                                                       'placeholder-id': id
+                                               })
+                                               .before($replacement);
+                               }
+                               $input = $input.removeAttr('id').hide().prev().attr('id', id).show();
+                               // Note: `$input[0] != input` now!
+                       }
+                       $input.addClass('placeholder');
+                       $input[0].value = $input.attr('placeholder');
+               } else {
+                       $input.removeClass('placeholder');
+               }
+       }
+
+       function safeActiveElement() {
+               // Avoid IE9 `document.activeElement` of death
+               // https://github.com/mathiasbynens/jquery-placeholder/pull/99
+               try {
+                       return document.activeElement;
+               } catch (err) {}
+       }
+
+       function changePlaceholder(text) {
+               var hasArgs = arguments.length,
+                       $input = this;
+               if(hasArgs) {
+                       if($input.attr('placeholder') !== text) {
+                               $input.prop('placeholder', text);
+                               if($input.hasClass('placeholder')) {
+                                       $input[0].value = text;
+                               }
+                       }
+               }
+       }
+
+}(jQuery));
index 93e30b9..073fb3d 100644 (file)
@@ -1,7 +1,9 @@
 /**
- * jQuery spinner
+ * jQuery Spinner
  *
  * Simple jQuery plugin to create, inject and remove spinners.
+ *
+ * @class jQuery.plugin.spinner
  */
 ( function ( $ ) {
 
 
        $.extend({
                /**
-                * Creates a spinner element.
+                * Create a spinner element
                 *
-                * The argument is an object with options used to construct the spinner. These can be:
+                * The argument is an object with options used to construct the spinner (see below).
                 *
-                * It is a good practice to keep a reference to the created spinner to be able to remove it later.
-                * Alternatively one can use the id option and removeSpinner() (but make sure to choose an id
-                * that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
+                * It is a good practice to keep a reference to the created spinner to be able to remove it
+                * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
+                * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
                 *
                 * CSS classes used:
-                *   .mw-spinner for every spinner
-                *   .mw-spinner-small / .mw-spinner-large for size
-                *   .mw-spinner-block / .mw-spinner-inline for display types
                 *
-                * @example
-                *   // Create a large spinner reserving all available horizontal space.
-                *   var $spinner = $.createSpinner({ size: 'large', type: 'block' });
-                *   // Insert above page content.
-                *   $( '#mw-content-text' ).prepend( $spinner );
-                * @example
-                *   // Place a small inline spinner next to the "Save" button
-                *   var $spinner = $.createSpinner({ size: 'small', type: 'inline' });
-                *   // Alternatively, just `$.createSpinner();` as these are the default options.
-                *   $( '#wpSave' ).after( $spinner );
-                * @example
-                *   // The following two are equivalent:
-                *   $.createSpinner( 'magic' );
-                *   $.createSpinner({ id: 'magic' });
+                * - .mw-spinner for every spinner
+                * - .mw-spinner-small / .mw-spinner-large for size
+                * - .mw-spinner-block / .mw-spinner-inline for display types
+                *
+                * Example:
+                *
+                *     // Create a large spinner reserving all available horizontal space.
+                *     var $spinner = $.createSpinner({ size: 'large', type: 'block' });
+                *     // Insert above page content.
+                *     $( '#mw-content-text' ).prepend( $spinner );
+                *
+                *     // Place a small inline spinner next to the "Save" button
+                *     var $spinner = $.createSpinner({ size: 'small', type: 'inline' });
+                *     // Alternatively, just `$.createSpinner();` as these are the default options.
+                *     $( '#wpSave' ).after( $spinner );
+                *
+                *     // The following two are equivalent:
+                *     $.createSpinner( 'magic' );
+                *     $.createSpinner({ id: 'magic' });
                 *
-                * @param {Object|String} opts [optional] ID string or options:
-                *  - id: If given, spinner will be given an id of "mw-spinner-<id>"
-                *  - size: 'small' (default) or 'large' for a 20-pixel or 32-pixel spinner
-                *  - type: 'inline' (default) or 'block'. Inline creates an inline-block with width and
-                *    height equal to spinner size. Block is a block-level element with width 100%, height
-                *    equal to spinner size.
+                * @static
+                * @inheritable
+                * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
+                *   of the `id` option. If an object is given, the possible option keys are:
+                * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
+                * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
+                * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
+                *   width and height equal to spinner size. Block is a block-level element with width 100%,
+                *   height equal to spinner size.
                 * @return {jQuery}
                 */
                createSpinner: function ( opts ) {
                },
 
                /**
-                * Removes a spinner element.
+                * Remove a spinner element
                 *
-                * @param {String} id [optional] Id of the spinner, as passed to createSpinner.
-                * @return {jQuery} The (now detached) spinner.
+                * @static
+                * @inheritable
+                * @param {string} id Id of the spinner, as passed to #createSpinner
+                * @return {jQuery} The (now detached) spinner element
                 */
                removeSpinner: function ( id ) {
                        return $( '#mw-spinner-' + id ).remove();
        });
 
        /**
-        * Injects a spinner after the elements in the jQuery collection
-        * (as siblings, not children). Collection contents remain unchanged.
+        * Inject a spinner after each element in the collection
         *
-        * @param {Object|String} opts See createSpinner() for description.
+        * Inserts spinner as siblings (not children) of the target elements.
+        * Collection contents remain unchanged.
+        *
+        * @param {Object|string} [opts] See #createSpinner
         * @return {jQuery}
         */
        $.fn.injectSpinner = function ( opts ) {
                return this.after( $.createSpinner( opts ) );
        };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.spinner
+        */
+
 }( jQuery ) );
index ba711aa..299fabd 100644 (file)
        };
 
        // Legacy (for compatibility with the code previously in skins/common.edit.js)
-       window.addButton = toolbar.addButton;
-       window.insertTags = toolbar.insertTags;
+       mw.log.deprecate( window, 'addButton', toolbar.addButton, 'Use mw.toolbar.addButton instead' );
+       mw.log.deprecate( window, 'insertTags', toolbar.insertTags, 'Use mw.toolbar.insertTags instead' );
 
-       // Explose API publicly
+       // Expose API publicly
        mw.toolbar = toolbar;
 
        $( function () {
index fb44a76..3c93de0 100644 (file)
@@ -4,28 +4,57 @@
  * PDF and DjVu files
  */
 ( function (mw, $) {
+
+       // Initialize ajax request variable
+       var xhr;
+
        // Use jQuery's load function to specifically select and replace table.multipageimage's child
        // tr with the new page's table.multipageimage's tr element.
        // table.multipageimage always has only one row.
-       function loadPage( page ) {
+       function loadPage( page, hist ) {
+               if ( xhr ) {
+                       // Abort previous requests to prevent backlog created by
+                       // repeatedly pressing back/forwards buttons
+                       xhr.abort();
+               }
+
                var $multipageimage = $( 'table.multipageimage' ),
+                       $spinner;
+
+               // Add a new spinner if one doesn't already exist
+               if ( !$multipageimage.find( '.mw-spinner' ).length ) {
+
                        $spinner = $.createSpinner( {
                                size: 'large',
                                type: 'block'
-                       } );
-
-               // Set the spinner's dimensions equal to the table's dimensions so that
-               // the current scroll position is not lost after the table is emptied prior to
-               // its contents being updated
-               $spinner.css( {
-                       height: $multipageimage.find( 'tr' ).height(),
-                       width: $multipageimage.find( 'tr' ).width()
-               } );
+                       } )
+                               // Set the spinner's dimensions equal to the table's dimensions so that
+                               // the current scroll position is not lost after the table is emptied prior to
+                               // its contents being updated
+                               .css( {
+                                       height: $multipageimage.find( 'tr' ).height(),
+                                       width: $multipageimage.find( 'tr' ).width()
+                               } );
+
+                       $multipageimage.empty().append( $spinner );
+               }
 
-               $multipageimage.empty().append( $spinner ).load(
-                       page + ' table.multipageimage tr',
-                       ajaxifyPageNavigation
-               );
+               xhr = $.ajax( {
+                       url: page,
+                       success: function ( data ) {
+                               // Load the page
+                               $multipageimage.empty().append( $( data ).find( 'table.multipageimage tr' ) );
+                               // Fire hook because the page's content has changed
+                               mw.hook( 'wikipage.content' ).fire( $multipageimage );
+                               // Set up the new page for pagination
+                               ajaxifyPageNavigation();
+                               // Add new page of image to history.  To preserve the back-forwards chain in the browser,
+                               // if the user gets here via the back/forward button, don't update the history.
+                               if ( window.history && history.pushState && !hist ) {
+                                       history.pushState( { url: page }, document.title, page );
+                               }
+                       }
+               } );
        }
 
        function ajaxifyPageNavigation() {
 
        $( document ).ready( function() {
                // The presence of table.multipageimage signifies that this file is a multi-page image
-               if( mw.config.get( 'wgNamespaceNumber' ) === 6 && $( 'table.multipageimage' ).length !== 0 ) {
+               if ( mw.config.get( 'wgNamespaceNumber' ) === 6 && $( 'table.multipageimage' ).length !== 0 ) {
                        ajaxifyPageNavigation();
+
+                       // Set up history.pushState (if available), so that when the user browses to a new page of
+                       // the same file, the browser's history is updated. If the user clicks the back/forward button
+                       // in the midst of navigating a file's pages, load the page inline.
+                       if ( window.history && history.pushState && history.replaceState ) {
+                               history.replaceState( { url: window.location.href }, '' );
+                               $( window ).on( 'popstate', function ( e ) {
+                                       var state = e.originalEvent.state;
+                                       if ( state ) {
+                                               loadPage( state.url, true );
+                                       }
+                               });
+                       }
                }
        } );
-}( mediaWiki, jQuery ) );
+}( mediaWiki, jQuery ) );
\ No newline at end of file
index 545cd07..e9afa4a 100644 (file)
                                        cleanTitle = title.replace( /_/g, ' ' );
                                        link = mw.html.element(
                                                'a', {
-                                                       href: mw.util.wikiGetlink( title ),
+                                                       href: mw.util.getUrl( title ),
                                                        title: cleanTitle
                                                }, cleanTitle
                                        );
index 2d22bad..bc2a0a2 100644 (file)
@@ -9,6 +9,12 @@
                var isValid = mw.util.validateEmail( mail ),
                        $label = $( '#mw-emailaddress-validity' );
 
+               // Set up the validity notice if it doesn't already exist
+               if ( $label.length === 0 ) {
+                       $label = $( '<label for="wpNewEmail" id="mw-emailaddress-validity"></label>' )
+                               .insertAfter( '#wpNewEmail' );
+               }
+
                // We allow empty address
                if ( isValid === null ) {
                        $label.text( '' ).removeClass( 'valid invalid' );
        }
 
        $( function () {
-               // Lame tip to let user know if its email is valid. See bug 22449.
-               // Only bind once for 'blur' so that the user can fill it in without errors;
-               // after that, look at every keypress for immediate feedback.
-               $( '#wpNewEmail' ).one( 'blur', function () {
-                       var $this = $( this );
-                       if ( $( '#mw-emailaddress-validity' ).length === 0 ) {
-                               $this.after( '<label for="wpNewEmail" id="mw-emailaddress-validity"></label>' );
-                       }
-
-                       updateMailValidityLabel( $this.val() );
-                       $this.keyup( function () {
+               $( '#wpNewEmail' )
+                       // Lame tip to let user know if its email is valid. See bug 22449.
+                       // Only bind once for 'blur' so that the user can fill it in without errors;
+                       // after that, look at every keypress for immediate feedback.
+                       .one( 'blur', function () {
+                               var $this = $( this );
                                updateMailValidityLabel( $this.val() );
+                               $this.keyup( function () {
+                                       updateMailValidityLabel( $this.val() );
+                               } );
+                       } )
+                       // Supress built-in validation notice and just call updateMailValidityLabel(),
+                       // to avoid double notice. See bug 40909.
+                       .on( 'invalid', function ( e ) {
+                               e.preventDefault();
+                               updateMailValidityLabel( $( this ).val() );
                        } );
-               } );
        } );
 }( mediaWiki, jQuery ) );
index 5e4af7b..b96a26e 100644 (file)
@@ -5,3 +5,27 @@
 .mw-changeslist-line-watched .mw-title {
        font-weight: bold;
 }
+
+.mw-changeslist-legend {
+       float: right;
+       margin-left: 1em;
+       margin-bottom: 0.5em;
+       clear: right;
+       font-size: 85%;
+       line-height: 1.2em;
+       padding: 0.5em;
+       border: 1px solid #ddd;
+}
+
+.mw-changeslist-legend dt {
+       float: left;
+}
+
+.mw-changeslist-legend dd {
+       margin-left: 1.5em;
+       line-height: 1.3em;
+}
+
+.mw-changeslist-legend dd.mw-changeslist-legend-plusminus {
+       margin-left: 3.5em;
+}
index 5cbb1ee..609b2dd 100644 (file)
@@ -2,7 +2,6 @@
  * JavaScript for Create account form (Special:UserLogin?type=signup).
  */
 ( function ( mw, $ ) {
-
        // When sending password by email, hide the password input fields.
        // This function doesn't need to be loaded early by ResourceLoader, but is tiny.
        function hidePasswordOnEmail() {
@@ -34,9 +33,8 @@
 
        // Move the FancyCaptcha image into a more attractive container.
        // This function does need to be run early by ResourceLoader.
-       function adjustFancyCaptcha() {
-               var $content = $( '#mw-content-text' ),
-                       $submit = $content.find( '#wpCreateaccount' ),
+       function adjustFancyCaptcha( $content, buttonSubmit ) {
+               var $submit = $content.find( buttonSubmit ),
                        tabIndex,
                        $captchaStuff,
                        $captchaImageContainer,
        }
 
        $( function () {
-               adjustFancyCaptcha();
-               hidePasswordOnEmail();
+               // Checks if the current page is Special:UserLogin
+               var isLogin = false,
+                       $content = $( '#mw-content-text' ),
+                       buttonSubmit = '#wpCreateaccount';
+
+               if ( $content.find( buttonSubmit ).length === 0 ) {
+                       buttonSubmit = '#wpLoginAttempt';
+                       isLogin = true;
+               }
+
+               adjustFancyCaptcha( $content, buttonSubmit );
+
+               if ( !isLogin ) {
+                       hidePasswordOnEmail();
+               }
+
        } );
 
 }( mediaWiki, jQuery ) );
index 24c8d77..cf9eaa0 100644 (file)
        width: auto;
        display: inline-block;
 }
+
+/**** shuffled CAPTCHA ****/
+#wpCaptchaWord {
+       margin-top: 6px;
+}
+
+.mw-createacct-captcha-container {
+       background-color: #f8f8f8;
+       border: 1px solid #c9c9c9;
+       padding: 10px;
+       text-align: center;
+}
+
+.mw-createacct-captcha-assisted {
+       display: block;
+       margin-top: 0.5em;
+}
+
+/* Put a border around the fancycaptcha-image-container. */
+.mw-createacct-captcha-and-reload {
+       border: 1px solid #c9c9c9;
+       display: table-cell; /* Other display formats end up too wide */
+       width: 270px;
+       background-color: #FFF;
+}
+
+/* Make the fancycaptcha-image-container full-width within its parent.  */
+.fancycaptcha-image-container
+{
+       width: 100%;
+}
index 9ffe11c..768a9c6 100644 (file)
@@ -33,28 +33,9 @@ section.mw-form-header {
        font-size: 0.9em;
        margin: 0 0 1em 0;
        padding: 0.5em;
-       border: 1px solid;
        word-wrap: break-word;
 }
 
-.mw-ui-vform .errorbox {
-       color: #cc0000;
-       border-color: #fac5c5;
-       background-color: #fae3e3;
-}
-
-.mw-ui-vform .warningbox {
-       color: #705000;
-       border-color: #fde29b;
-       background-color: #fdf1d1;
-}
-
-.mw-ui-vform .successbox {
-       color: #009000;
-       border-color: #b7fdb5;
-       background-color: #e1fddf;
-}
-
 /*
  * Override the right margin of the form to give space in case a benefits
  * column appears to the side.
diff --git a/resources/mediawiki.ui/components/default/buttons.less b/resources/mediawiki.ui/components/default/buttons.less
new file mode 100644 (file)
index 0000000..a931756
--- /dev/null
@@ -0,0 +1,70 @@
+@import "../../settings/typography";
+@import "../../mixins/effects";
+
+@buttonBorderRadius: 3px;
+
+// Button styling
+.mw-ui-button {
+       // Container layout
+       display: inline-block;
+       padding: 0.4em 1em 0.4em 1em;
+       margin: 0;
+
+       // IE6/IE7 hack
+       // http://stackoverflow.com/a/5838575/365238
+       *display: inline;
+       zoom: 1;
+
+       // Container styling
+       .buttonColors();
+       border-radius: @buttonBorderRadius;
+
+       // Ensure that buttons and inputs are nicely aligned when they have differing heights
+       vertical-align: middle;
+
+       // Content styling
+       text-align: center;
+       text-decoration: none;
+
+       font-weight: bold;
+
+       // Interaction styling
+       cursor: pointer;
+
+       &:disabled,
+       &.mw-ui-disabled {
+               cursor: default;
+       }
+
+       // Button sizes and displays
+       // -----------------------------------------
+       &.mw-ui-big {
+               font-size: @baseFontSize * 1.3;
+       }
+       &.mw-ui-block {
+               display: block;
+               width: 100%;
+       }
+}
+
+// This overrides an underline declaration on a:hover and a:focus in commonElements.css, which the
+// class alone isn't specific enough to do
+a.mw-ui-button {
+       text-decoration: none;
+}
+
+// Button groups
+.mw-ui-button-group > * {
+       border-radius: 0;
+       float: left;
+
+       &:first-child{
+               border-top-left-radius: @buttonBorderRadius;
+               border-bottom-left-radius: @buttonBorderRadius;
+       }
+
+       &:last-child{
+               border-top-right-radius: @buttonBorderRadius;
+               border-bottom-right-radius: @buttonBorderRadius;
+       }
+}
diff --git a/resources/mediawiki.ui/components/default/forms.less b/resources/mediawiki.ui/components/default/forms.less
new file mode 100644 (file)
index 0000000..d2554c6
--- /dev/null
@@ -0,0 +1,115 @@
+// Form elements and layouts
+
+@import "../../mixins/utilities";
+@import "../../mixins/forms";
+
+// --------------------------------------------------------------------------
+// Layouts
+// --------------------------------------------------------------------------
+
+// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
+// 'VForm' design, the form can't be narrower than this.
+@captchaContainerWidth: 290px;
+@defaultFormWidth: @captchaContainerWidth;
+
+// Style a compact vertical stacked form ("VForm") and the elements in divs
+// within it.
+.mw-ui-vform {
+       .box-sizing(border-box);
+
+       width: @defaultFormWidth;
+
+       // Immediate divs in a vform are block and spaced-out.
+       & > div {
+               display: block;
+               margin: 0 0 15px 0;
+               padding: 0;
+               width: 100%;
+
+               // MW currently doesn't use the type attribute everywhere on inputs.
+               input,
+               .mw-ui-button {
+                       display: block;
+                       .box-sizing(border-box);
+                       margin: 0;
+                       width: 100%;
+               }
+
+               // We exclude these because they'll generally use mw-ui-button.
+               // Otherwise, we'll unintentionally override that.
+               input:not([type=button]):not([type=submit]):not([type=file]), {
+                       .agora-field-styling(); // mixins/forms.less
+               }
+
+               label {
+                       display: block;
+                       .box-sizing(border-box);
+                       .agora-label-styling();
+                       width: auto;
+                       margin: 0 0 0.2em 0;
+                       padding: 0;
+               }
+
+               // Override input styling just for checkboxes and radio inputs.
+               input[type="checkbox"],
+               input[type="radio"] {
+                       display: inline;
+                       .box-sizing(content-box);
+                       width: auto;
+               }
+
+       }
+
+       // HTMLForm uses error, SpecialUserlogin (login and create account) uses
+       // errorbox.
+       // TODO move errorbox from mediawiki.special.vforms.css into here.
+       .error {
+               .box-sizing(border-box);
+               font-size: 0.9em;
+               margin: 0 0 1em 0;
+               padding: 0.5em;
+               color: #cc0000;
+               border: 1px solid #fac5c5;
+               background-color: #fae3e3;
+               text-shadow: 0 1px #fae3e3;
+               word-wrap: break-word;
+       }
+}
+
+// --------------------------------------------------------------------------
+// Elements
+// --------------------------------------------------------------------------
+
+// Apply this to individual elements to style them.
+// You generally don't need to use this class on divs within an Agora
+// form container such as mw-ui-vform
+// XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
+.mw-ui-vform-div {
+       display: block;
+       margin: 0 0 15px 0;
+       padding: 0;
+       width: 100%;
+}
+
+// Apply mw-ui-input to individual input fields to style them.
+// You generally don't need to use this class if <input> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-input {
+       .agora-field-styling(); // mixins/forms.less
+}
+
+// Apply mw-ui-label to individual elements to style them.
+// You generally don't need to use this class if <label> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-label {
+       .agora-label-styling(); // mixins/forms.less
+}
+
+// Nesting an input checkbox or radio button inside a label with this class
+// improves alignment, e.g.
+//     <label class="mw-ui-checkbox-label">
+//             <input type="checkbox">The label text
+//     </label>
+.mw-ui-checkbox-label, .mw-ui-radio-label {
+       .agora-inline-label-styling();
+}
diff --git a/resources/mediawiki.ui/components/utilities.less b/resources/mediawiki.ui/components/utilities.less
new file mode 100644 (file)
index 0000000..9aea429
--- /dev/null
@@ -0,0 +1,19 @@
+// Generic helper classes that could be used in many elements/layouts
+
+// --------------------------------------------------------------------------
+// Positioning
+// --------------------------------------------------------------------------
+
+@import "../mixins/utilities";
+
+.mw-ui-flush-left {
+       .agora-flush-left();
+}
+
+.mw-ui-flush-right {
+       .agora-flush-right();
+}
+
+.mw-ui-center-block {
+       .agora-center-block();
+}
diff --git a/resources/mediawiki.ui/components/vector/buttons.less b/resources/mediawiki.ui/components/vector/buttons.less
new file mode 100644 (file)
index 0000000..a49721d
--- /dev/null
@@ -0,0 +1,20 @@
+@import "../default/buttons"; // Layer Vector on top of the default settings.
+@import "../../mixins/type";
+
+.mw-ui-button {
+       // Button colors determined by function.
+       // -----------------------------------------
+       &.mw-ui-primary {
+               .buttonColors(@agoraBlue);
+       }
+
+       &.mw-ui-constructive {
+               .buttonColors(@agoraGreen);
+       }
+
+       &.mw-ui-destructive {
+               .buttonColors(@agoraRed);
+       }
+
+       .vector-type();
+}
diff --git a/resources/mediawiki.ui/components/vector/containers.less b/resources/mediawiki.ui/components/vector/containers.less
new file mode 100644 (file)
index 0000000..1e9ec05
--- /dev/null
@@ -0,0 +1,6 @@
+// No default settings for containers yet.
+@import "../../mixins/type";
+
+.mw-ui-container {
+       .vector-type();
+}
diff --git a/resources/mediawiki.ui/components/vector/forms.less b/resources/mediawiki.ui/components/vector/forms.less
new file mode 100644 (file)
index 0000000..ebb175b
--- /dev/null
@@ -0,0 +1,8 @@
+@import "../default/forms"; // Layer Vector on top of the default settings.
+@import "../../mixins/type";
+
+.mw-ui-vform,
+.mw-ui-vform > div input,
+.mw-ui-input {
+       .vector-type();
+}
diff --git a/resources/mediawiki.ui/default.less b/resources/mediawiki.ui/default.less
new file mode 100644 (file)
index 0000000..036db5f
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+ * Provide Agora appearance for mw-ui-* classes when using a skin other than
+ * Vector.
+ */
+
+@import "components/utilities";
+@import "components/default/buttons";
+@import "components/default/forms";
diff --git a/resources/mediawiki.ui/mediawiki.ui.default.css b/resources/mediawiki.ui/mediawiki.ui.default.css
deleted file mode 100644 (file)
index b072616..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-@charset "UTF-8";
-/**
- * Provide Agora appearance for mw-ui-* classes when using a skin other than
- * Vector.
- * Compass builds these Agora styles from source Sass files in
- * extensions/Agora/modules/scss
- */
-/* _effects.scss */
-/* Mixins for visual effects in CSS3 */
-/* line 7, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-flush-left {
-  float: left;
-  margin-left: 0;
-  padding-left: 0;
-}
-
-/* line 11, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-flush-right {
-  float: right;
-  margin-right: 0;
-  padding-right: 0;
-}
-
-/* line 15, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-center-block {
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-/* line 4, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button {
-  display: -moz-inline-stack;
-  display: inline-block;
-  vertical-align: middle;
-  *vertical-align: auto;
-  zoom: 1;
-  *display: inline;
-  padding: 0.4em 1em 0.4em 1em;
-  margin: 0;
-  background-color: #c9c9c9;
-  *background-color: #c9c9c9;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDCDCDC', endColorstr='#FFC9C9C9');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dcdcdc), color-stop(100%, #c9c9c9));
-  background-image: -webkit-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: -moz-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: -o-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: linear-gradient(top, #dcdcdc, #c9c9c9);
-  color: black;
-  text-shadow: 0 1px 1px rgba(201, 201, 201, 0.3);
-  border: 1px solid #c4c4c4;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  -ms-border-radius: 3px;
-  -o-border-radius: 3px;
-  border-radius: 3px;
-  vertical-align: middle;
-  text-align: center;
-  text-decoration: none;
-  font-weight: bold;
-  cursor: pointer;
-}
-/* line 38, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:hover, .mw-ui-button.mw-ui-hover {
-  background-color: gainsboro;
-  *background-color: gainsboro;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFE9E9E9', endColorstr='#FFDCDCDC');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e9e9e9), color-stop(100%, #dcdcdc));
-  background-image: -webkit-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: -moz-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: -o-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: linear-gradient(top, #e9e9e9, #dcdcdc);
-  text-decoration: none;
-}
-/* line 44, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:active, .mw-ui-button.mw-ui-active {
-  background-image: none;
-  background-color: #c1c1c1;
-  text-shadow: none;
-}
-/* line 54, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:disabled, .mw-ui-button.mw-ui-disabled {
-  background-image: none;
-  background-color: #c9c9c9;
-  opacity: 0.5;
-  text-shadow: none;
-}
-/* line 30, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button:disabled, .mw-ui-button.mw-ui-disabled {
-  cursor: default;
-}
-/* line 36, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button.mw-ui-big {
-  font-size: 1.3em;
-}
-/* line 41, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button.mw-ui-block {
-  display: block;
-  width: 100%;
-}
-
-/* line 49, sourcefiles/scss/components/default/_buttons.scss */
-a.mw-ui-button {
-  text-decoration: none;
-}
-
-/* line 56, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > * {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  -ms-border-radius: 0;
-  -o-border-radius: 0;
-  border-radius: 0;
-  float: left;
-}
-/* line 60, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > *:first-child {
-  -moz-border-radius-topleft: 3px;
-  -webkit-border-top-left-radius: 3px;
-  border-top-left-radius: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  border-bottom-left-radius: 3px;
-}
-/* line 65, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > *:last-child {
-  -moz-border-radius-topright: 3px;
-  -webkit-border-top-right-radius: 3px;
-  border-top-right-radius: 3px;
-  -moz-border-radius-bottomright: 3px;
-  -webkit-border-bottom-right-radius: 3px;
-  border-bottom-right-radius: 3px;
-}
-
-/* line 14, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform {
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  width: 290px;
-}
-/* line 20, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div {
-  display: block;
-  margin: 0 0 15px 0;
-  padding: 0;
-  width: 100%;
-}
-/* line 28, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input,
-.mw-ui-vform > div .mw-ui-button {
-  display: block;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  margin: 0;
-  width: 100%;
-}
-/* line 37, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]) {
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  color: #252525;
-  padding: 0.35em 0 0.35em 0.5em;
-}
-/* line 11, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus {
-  box-shadow: #4091ed 0px 0px 5px;
-  border-color: #4091ed;
-}
-/* line 13, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus:not([type=checkbox]):not([type=radio]) {
-  outline: 0;
-}
-/* line 41, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div label {
-  display: block;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  font-size: 0.9em;
-  color: #4a4a4a;
-  width: auto;
-  margin: 0 0 0.2em 0;
-  padding: 0;
-}
-/* line 38, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div label * {
-  font-weight: normal;
-}
-/* line 52, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input[type="checkbox"],
-.mw-ui-vform > div input[type="radio"] {
-  display: inline;
-  -webkit-box-sizing: content-box;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-  width: auto;
-}
-/* line 63, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform .error {
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  font-size: 0.9em;
-  margin: 0 0 1em 0;
-  padding: 0.5em;
-  color: #cc0000;
-  border: 1px solid #fac5c5;
-  background-color: #fae3e3;
-  text-shadow: 0 1px #fae3e3;
-  word-wrap: break-word;
-}
-
-/* line 86, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform-div {
-  display: block;
-  margin: 0 0 15px 0;
-  padding: 0;
-  width: 100%;
-}
-
-/* line 96, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-input {
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  color: #252525;
-  padding: 0.35em 0 0.35em 0.5em;
-}
-/* line 11, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-input:focus {
-  box-shadow: #4091ed 0px 0px 5px;
-  border-color: #4091ed;
-}
-/* line 13, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-input:focus:not([type=checkbox]):not([type=radio]) {
-  outline: 0;
-}
-
-/* line 103, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-label {
-  font-size: 0.9em;
-  color: #4a4a4a;
-}
-/* line 38, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-label * {
-  font-weight: normal;
-}
-
-/* line 112, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-checkbox-label, .mw-ui-radio-label {
-  margin-bottom: 0.5em;
-  cursor: pointer;
-  vertical-align: bottom;
-  line-height: normal;
-  font-weight: normal;
-}
-/* line 54, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-checkbox-label > input[type="checkbox"], .mw-ui-checkbox-label > input[type="radio"], .mw-ui-radio-label > input[type="checkbox"], .mw-ui-radio-label > input[type="radio"] {
-  width: auto;
-  height: auto;
-  margin: 0 0.1em 0em 0;
-  padding: 0;
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  cursor: pointer;
-}
diff --git a/resources/mediawiki.ui/mediawiki.ui.vector.css b/resources/mediawiki.ui/mediawiki.ui.vector.css
deleted file mode 100644 (file)
index fd9e091..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-@charset "UTF-8";
-/**
- * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
- * Compass builds these Agora styles from source Sass files in
- * extensions/Agora/modules/scss
- */
-/* _effects.scss */
-/* Mixins for visual effects in CSS3 */
-/* line 7, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-flush-left {
-  float: left;
-  margin-left: 0;
-  padding-left: 0;
-}
-
-/* line 11, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-flush-right {
-  float: right;
-  margin-right: 0;
-  padding-right: 0;
-}
-
-/* line 15, sourcefiles/scss/components/_utilities.scss */
-.mw-ui-center-block {
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-/* line 4, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button {
-  display: -moz-inline-stack;
-  display: inline-block;
-  vertical-align: middle;
-  *vertical-align: auto;
-  zoom: 1;
-  *display: inline;
-  padding: 0.4em 1em 0.4em 1em;
-  margin: 0;
-  background-color: #c9c9c9;
-  *background-color: #c9c9c9;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDCDCDC', endColorstr='#FFC9C9C9');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dcdcdc), color-stop(100%, #c9c9c9));
-  background-image: -webkit-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: -moz-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: -o-linear-gradient(top, #dcdcdc, #c9c9c9);
-  background-image: linear-gradient(top, #dcdcdc, #c9c9c9);
-  color: black;
-  text-shadow: 0 1px 1px rgba(201, 201, 201, 0.3);
-  border: 1px solid #c4c4c4;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  -ms-border-radius: 3px;
-  -o-border-radius: 3px;
-  border-radius: 3px;
-  vertical-align: middle;
-  text-align: center;
-  text-decoration: none;
-  font-weight: bold;
-  cursor: pointer;
-}
-/* line 38, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:hover, .mw-ui-button.mw-ui-hover {
-  background-color: gainsboro;
-  *background-color: gainsboro;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFE9E9E9', endColorstr='#FFDCDCDC');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e9e9e9), color-stop(100%, #dcdcdc));
-  background-image: -webkit-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: -moz-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: -o-linear-gradient(top, #e9e9e9, #dcdcdc);
-  background-image: linear-gradient(top, #e9e9e9, #dcdcdc);
-  text-decoration: none;
-}
-/* line 44, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:active, .mw-ui-button.mw-ui-active {
-  background-image: none;
-  background-color: #c1c1c1;
-  text-shadow: none;
-}
-/* line 54, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button:disabled, .mw-ui-button.mw-ui-disabled {
-  background-image: none;
-  background-color: #c9c9c9;
-  opacity: 0.5;
-  text-shadow: none;
-}
-/* line 30, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button:disabled, .mw-ui-button.mw-ui-disabled {
-  cursor: default;
-}
-/* line 36, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button.mw-ui-big {
-  font-size: 1.3em;
-}
-/* line 41, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button.mw-ui-block {
-  display: block;
-  width: 100%;
-}
-
-/* line 49, sourcefiles/scss/components/default/_buttons.scss */
-a.mw-ui-button {
-  text-decoration: none;
-}
-
-/* line 56, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > * {
-  -webkit-border-radius: 0;
-  -moz-border-radius: 0;
-  -ms-border-radius: 0;
-  -o-border-radius: 0;
-  border-radius: 0;
-  float: left;
-}
-/* line 60, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > *:first-child {
-  -moz-border-radius-topleft: 3px;
-  -webkit-border-top-left-radius: 3px;
-  border-top-left-radius: 3px;
-  -moz-border-radius-bottomleft: 3px;
-  -webkit-border-bottom-left-radius: 3px;
-  border-bottom-left-radius: 3px;
-}
-/* line 65, sourcefiles/scss/components/default/_buttons.scss */
-.mw-ui-button-group > *:last-child {
-  -moz-border-radius-topright: 3px;
-  -webkit-border-top-right-radius: 3px;
-  border-top-right-radius: 3px;
-  -moz-border-radius-bottomright: 3px;
-  -webkit-border-bottom-right-radius: 3px;
-  border-bottom-right-radius: 3px;
-}
-
-/* line 3, sourcefiles/scss/components/vector/_buttons.scss */
-.mw-ui-button {
-  font-size: 1em;
-  line-height: 1.4em;
-}
-/* line 6, sourcefiles/scss/components/vector/_buttons.scss */
-.mw-ui-button.mw-ui-primary {
-  background-color: #3366bb;
-  *background-color: #3366bb;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF4779CD', endColorstr='#FF3366BB');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4779cd), color-stop(100%, #3366bb));
-  background-image: -webkit-linear-gradient(top, #4779cd, #3366bb);
-  background-image: -moz-linear-gradient(top, #4779cd, #3366bb);
-  background-image: -o-linear-gradient(top, #4779cd, #3366bb);
-  background-image: linear-gradient(top, #4779cd, #3366bb);
-  color: white;
-  text-shadow: 0 1px 1px rgba(51, 102, 187, 0.75);
-  border: 1px solid #3162b3;
-}
-/* line 38, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-primary:hover, .mw-ui-button.mw-ui-primary.mw-ui-hover {
-  background-color: #4779cd;
-  *background-color: #4779cd;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF5B88D2', endColorstr='#FF4779CD');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5b88d2), color-stop(100%, #4779cd));
-  background-image: -webkit-linear-gradient(top, #5b88d2, #4779cd);
-  background-image: -moz-linear-gradient(top, #5b88d2, #4779cd);
-  background-image: -o-linear-gradient(top, #5b88d2, #4779cd);
-  background-image: linear-gradient(top, #5b88d2, #4779cd);
-  text-decoration: none;
-}
-/* line 44, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-primary:active, .mw-ui-button.mw-ui-primary.mw-ui-active {
-  background-image: none;
-  background-color: #305faf;
-  text-shadow: none;
-}
-/* line 54, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-primary:disabled, .mw-ui-button.mw-ui-primary.mw-ui-disabled {
-  background-image: none;
-  background-color: #3366bb;
-  opacity: 0.5;
-  text-shadow: none;
-}
-/* line 10, sourcefiles/scss/components/vector/_buttons.scss */
-.mw-ui-button.mw-ui-constructive {
-  background-color: #27aa65;
-  *background-color: #27aa65;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF2EC977', endColorstr='#FF27AA65');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2ec977), color-stop(100%, #27aa65));
-  background-image: -webkit-linear-gradient(top, #2ec977, #27aa65);
-  background-image: -moz-linear-gradient(top, #2ec977, #27aa65);
-  background-image: -o-linear-gradient(top, #2ec977, #27aa65);
-  background-image: linear-gradient(top, #2ec977, #27aa65);
-  color: white;
-  text-shadow: 0 1px 1px rgba(39, 170, 101, 0.75);
-  border: 1px solid #25a260;
-}
-/* line 38, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-constructive:hover, .mw-ui-button.mw-ui-constructive.mw-ui-hover {
-  background-color: #2ec977;
-  *background-color: #2ec977;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF3ED384', endColorstr='#FF2EC977');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #3ed384), color-stop(100%, #2ec977));
-  background-image: -webkit-linear-gradient(top, #3ed384, #2ec977);
-  background-image: -moz-linear-gradient(top, #3ed384, #2ec977);
-  background-image: -o-linear-gradient(top, #3ed384, #2ec977);
-  background-image: linear-gradient(top, #3ed384, #2ec977);
-  text-decoration: none;
-}
-/* line 44, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-constructive:active, .mw-ui-button.mw-ui-constructive.mw-ui-active {
-  background-image: none;
-  background-color: #249e5e;
-  text-shadow: none;
-}
-/* line 54, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-constructive:disabled, .mw-ui-button.mw-ui-constructive.mw-ui-disabled {
-  background-image: none;
-  background-color: #27aa65;
-  opacity: 0.5;
-  text-shadow: none;
-}
-/* line 14, sourcefiles/scss/components/vector/_buttons.scss */
-.mw-ui-button.mw-ui-destructive {
-  background-color: #cc0000;
-  *background-color: #cc0000;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFF20000', endColorstr='#FFCC0000');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f20000), color-stop(100%, #cc0000));
-  background-image: -webkit-linear-gradient(top, #f20000, #cc0000);
-  background-image: -moz-linear-gradient(top, #f20000, #cc0000);
-  background-image: -o-linear-gradient(top, #f20000, #cc0000);
-  background-image: linear-gradient(top, #f20000, #cc0000);
-  color: white;
-  text-shadow: 0 1px 1px rgba(204, 0, 0, 0.75);
-  border: 1px solid #c20000;
-}
-/* line 38, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-destructive:hover, .mw-ui-button.mw-ui-destructive.mw-ui-hover {
-  background-color: #f20000;
-  *background-color: #f20000;
-  *zoom: 1;
-  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFF0D0D', endColorstr='#FFF20000');
-  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff0d0d), color-stop(100%, #f20000));
-  background-image: -webkit-linear-gradient(top, #ff0d0d, #f20000);
-  background-image: -moz-linear-gradient(top, #ff0d0d, #f20000);
-  background-image: -o-linear-gradient(top, #ff0d0d, #f20000);
-  background-image: linear-gradient(top, #ff0d0d, #f20000);
-  text-decoration: none;
-}
-/* line 44, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-destructive:active, .mw-ui-button.mw-ui-destructive.mw-ui-active {
-  background-image: none;
-  background-color: #bd0000;
-  text-shadow: none;
-}
-/* line 54, sourcefiles/scss/mixins/_effects.scss */
-.mw-ui-button.mw-ui-destructive:disabled, .mw-ui-button.mw-ui-destructive.mw-ui-disabled {
-  background-image: none;
-  background-color: #cc0000;
-  opacity: 0.5;
-  text-shadow: none;
-}
-
-/* line 14, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform {
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  width: 290px;
-}
-/* line 20, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div {
-  display: block;
-  margin: 0 0 15px 0;
-  padding: 0;
-  width: 100%;
-}
-/* line 28, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input,
-.mw-ui-vform > div .mw-ui-button {
-  display: block;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  margin: 0;
-  width: 100%;
-}
-/* line 37, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]) {
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  color: #252525;
-  padding: 0.35em 0 0.35em 0.5em;
-}
-/* line 11, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus {
-  box-shadow: #4091ed 0px 0px 5px;
-  border-color: #4091ed;
-}
-/* line 13, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus:not([type=checkbox]):not([type=radio]) {
-  outline: 0;
-}
-/* line 41, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div label {
-  display: block;
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  font-size: 0.9em;
-  color: #4a4a4a;
-  width: auto;
-  margin: 0 0 0.2em 0;
-  padding: 0;
-}
-/* line 38, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-vform > div label * {
-  font-weight: normal;
-}
-/* line 52, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform > div input[type="checkbox"],
-.mw-ui-vform > div input[type="radio"] {
-  display: inline;
-  -webkit-box-sizing: content-box;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-  width: auto;
-}
-/* line 63, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform .error {
-  -webkit-box-sizing: border-box;
-  -moz-box-sizing: border-box;
-  box-sizing: border-box;
-  font-size: 0.9em;
-  margin: 0 0 1em 0;
-  padding: 0.5em;
-  color: #cc0000;
-  border: 1px solid #fac5c5;
-  background-color: #fae3e3;
-  text-shadow: 0 1px #fae3e3;
-  word-wrap: break-word;
-}
-
-/* line 86, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-vform-div {
-  display: block;
-  margin: 0 0 15px 0;
-  padding: 0;
-  width: 100%;
-}
-
-/* line 96, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-input {
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  color: #252525;
-  padding: 0.35em 0 0.35em 0.5em;
-}
-/* line 11, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-input:focus {
-  box-shadow: #4091ed 0px 0px 5px;
-  border-color: #4091ed;
-}
-/* line 13, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-input:focus:not([type=checkbox]):not([type=radio]) {
-  outline: 0;
-}
-
-/* line 103, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-label {
-  font-size: 0.9em;
-  color: #4a4a4a;
-}
-/* line 38, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-label * {
-  font-weight: normal;
-}
-
-/* line 112, sourcefiles/scss/components/default/_forms.scss */
-.mw-ui-checkbox-label, .mw-ui-radio-label {
-  margin-bottom: 0.5em;
-  cursor: pointer;
-  vertical-align: bottom;
-  line-height: normal;
-  font-weight: normal;
-}
-/* line 54, sourcefiles/scss/mixins/_forms.scss */
-.mw-ui-checkbox-label > input[type="checkbox"], .mw-ui-checkbox-label > input[type="radio"], .mw-ui-radio-label > input[type="checkbox"], .mw-ui-radio-label > input[type="radio"] {
-  width: auto;
-  height: auto;
-  margin: 0 0.1em 0em 0;
-  padding: 0;
-  border-style: solid;
-  border-width: 1px;
-  border-color: #c9c9c9;
-  cursor: pointer;
-}
-
-/* line 5, sourcefiles/scss/components/vector/_forms.scss */
-.mw-ui-vform,
-.mw-ui-vform > div input,
-.mw-ui-input {
-  font-size: 1em;
-  line-height: 1.4em;
-}
-
-/* line 3, sourcefiles/scss/components/vector/_containers.scss */
-.mw-ui-container {
-  font-size: 1em;
-  line-height: 1.4em;
-}
diff --git a/resources/mediawiki.ui/mixins/effects.less b/resources/mediawiki.ui/mixins/effects.less
new file mode 100644 (file)
index 0000000..d168e5f
--- /dev/null
@@ -0,0 +1,52 @@
+/* Mixins for visual effects in CSS3 */
+
+@import "../settings/colors";
+
+// ----------------------------------------------------------------------------
+// Gradients
+// ----------------------------------------------------------------------------
+.vertical-gradient(@startColor: lighten(@agoraGray, 95%), @endColor: @agoraGray, @startPos: 0, @endPos: 100%) {
+       background-color: @endColor;
+       background-image: -moz-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Firefox 3.6+
+       background-image: -webkit-gradient( linear, left top, left bottom, color-stop( @startPos, @startColor ), color-stop( @endPos, @endColor ) ); // Safari 4+, Chrome 2+
+       background-image: -webkit-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Safari 5.1+, Chrome 10+
+       background-image: linear-gradient( @startColor @startPos, @endColor @endPos ); // Standard
+}
+
+// ----------------------------------------------------------------------------
+// Button styling
+// ----------------------------------------------------------------------------
+
+.buttonColors(@baseColor: @agoraGray) {
+       // Background color
+       .vertical-gradient(lighten(@baseColor, 7.5%), @baseColor);
+
+       border: 1px solid darken(@baseColor, 2%);
+
+       &:hover,
+       &.mw-ui-hover {
+               .vertical-gradient(lighten(@baseColor, 12.5%), lighten(@baseColor, 7.5%));
+               text-decoration: none;
+       }
+
+       &:active,
+       &.mw-ui-active {
+               background-image: none;
+               background-color: darken(@baseColor, 3%);
+       }
+
+       &:disabled,
+       &.mw-ui-disabled {
+               background-image: none;
+               background-color: @baseColor;
+               opacity: 0.5;
+       }
+}
+
+.buttonColors(@baseColor: @agoraGray) when (lightness(@baseColor) >= 50%) {
+       color: #000;
+}
+
+.buttonColors(@baseColor: @agoraGray) when (lightness(@baseColor) < 50%) {
+       color: #fff;
+}
diff --git a/resources/mediawiki.ui/mixins/forms.less b/resources/mediawiki.ui/mixins/forms.less
new file mode 100644 (file)
index 0000000..1b177ee
--- /dev/null
@@ -0,0 +1,54 @@
+@import "../settings/colors";
+
+// Font is not included.
+// For Vector, that should be layered on top with vector-type
+.agora-field-styling() {
+
+       border: 1px solid @agoraGray;
+
+       &:focus {
+               // Styling focus of native checkboxes etc on Mac is almost impossible.
+               &:not([type=checkbox]):not([type=radio]) {
+                       outline: 0; // Removes OS field focus
+               }
+
+               box-shadow: @agoraBlueShadow 0px 0px 5px;
+
+               border-color: @agoraBlueShadow;
+       }
+
+       color: @agoraTextColor;
+       padding: 0.35em 0.5em 0.35em 0.5em;
+
+       // Ensure that buttons and inputs are nicely aligned when they have differing heights
+       vertical-align: middle;
+}
+
+.agora-label-styling() {
+       //font-weight: bold;
+       font-size: 0.9em;
+       color: darken(@agoraGray, 50%);
+
+       * {
+               font-weight: normal;
+       }
+}
+
+.agora-inline-label-styling() {
+       margin-bottom: 0.5em;
+       cursor: pointer;
+       vertical-align: bottom;
+       line-height: normal;
+
+       font-weight: normal;
+
+       & > input[type="checkbox"],
+       & > input[type="radio"] {
+               width: auto;
+               height: auto;
+               margin: 0 0.1em 0em 0;
+               padding: 0;
+               border: 1px solid @agoraGray;
+               cursor: pointer;
+       }
+}
diff --git a/resources/mediawiki.ui/mixins/type.less b/resources/mediawiki.ui/mixins/type.less
new file mode 100644 (file)
index 0000000..4a01168
--- /dev/null
@@ -0,0 +1,6 @@
+@import "../settings/typography";
+
+.vector-type() {
+       font-size: @baseFontSize;
+       line-height: @baseLineHeight;
+}
diff --git a/resources/mediawiki.ui/mixins/utilities.less b/resources/mediawiki.ui/mixins/utilities.less
new file mode 100644 (file)
index 0000000..a201a4e
--- /dev/null
@@ -0,0 +1,23 @@
+.box-sizing(@value) {
+       -moz-box-sizing: @value;
+       -webkit-box-sizing: @value;
+       box-sizing: @value;
+}
+
+.agora-flush-left() {
+       float: left;
+       margin-left: 0;
+       padding-left: 0;
+}
+
+.agora-flush-right() {
+       float: right;
+       margin-right: 0;
+       padding-right: 0;
+}
+
+.agora-center-block() {
+       display: block;
+       margin-left: auto;
+       margin-right: auto;
+}
diff --git a/resources/mediawiki.ui/settings/colors.less b/resources/mediawiki.ui/settings/colors.less
new file mode 100644 (file)
index 0000000..208d6f6
--- /dev/null
@@ -0,0 +1,17 @@
+// Grays
+// -----------------------------------------
+@agoraGray: #c9c9c9;
+@agoraTextColor: #252525;
+
+// Blues
+// -----------------------------------------
+@agoraBlue: #3366bb;
+@agoraBlueShadow: #4091ed;
+
+// Greens
+// -----------------------------------------
+@agoraGreen: #27aa65;
+
+// Reds
+// -----------------------------------------
+@agoraRed: #cc0000;
diff --git a/resources/mediawiki.ui/settings/typography.less b/resources/mediawiki.ui/settings/typography.less
new file mode 100644 (file)
index 0000000..76c398c
--- /dev/null
@@ -0,0 +1,5 @@
+@baseFontSize: 1em;
+@baseLineHeight: 1.4 * @baseFontSize;
+@baseFontColor: @agoraTextColor;
+
+@smallFontSize: 0.75em;
diff --git a/resources/mediawiki.ui/sourcefiles/Makefile b/resources/mediawiki.ui/sourcefiles/Makefile
deleted file mode 100644 (file)
index dea9013..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-DATE=$(shell date +%I:%M%p)
-CHECK=\033[32m✔\033[39m
-HR=\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#
-
-build:
-       @echo "\n${HR}"
-       @echo "Building Agora..."
-       @echo "${HR}\n"
-       @compass compile
-       @echo "Compiling Compass project...            ${CHECK} Done"
-       @rm -rf .sass-cache
-       @echo "Removing .sass-cache...                 ${CHECK} Done"
-       @echo "\n${HR}"
-       @echo "Agora successfully built at ${DATE}."
-       @echo "${HR}\n"
-
-all: build
-
-watch:
-       @echo "\n${HR}"
-       @echo "Watching SCSS files for Agora..."
-       @echo "${HR}\n"
-       @compass watch
-       @echo "Started watching modules/scss at ${DATE}..."
diff --git a/resources/mediawiki.ui/sourcefiles/config.rb b/resources/mediawiki.ui/sourcefiles/config.rb
deleted file mode 100644 (file)
index 28c6524..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-# Require any additional compass plugins here.
-
-# Set this to the root of your project when deployed:
-# (unused so far): http_path = "/"
-
-# Output to parent of build directory
-css_dir = ".."
-sass_dir = "scss"
-# (unused so far): images_dir = "modules/img"
-# (unused so far): javascripts_dir = "modules/js"
-
-# You can select your preferred output style here (can be overridden via the command line):
-# output_style = :expanded or :nested or :compact or :compressed
-output_style = :expanded
-
-# To enable relative paths to assets via compass helper functions. Uncomment:
-relative_assets = true
-
-# To disable debugging comments that display the original location of your selectors. Uncomment:
-line_comments = true
-
-
-# If you prefer the indented syntax, you might want to regenerate this
-# project again passing --syntax sass, or you can uncomment this:
-# preferred_syntax = :sass
-# and then run:
-# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/_default.scss b/resources/mediawiki.ui/sourcefiles/scss/components/_default.scss
deleted file mode 100644 (file)
index e7090eb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-@import "utilities";
-@import "default/buttons";
-@import "default/forms";
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/_utilities.scss b/resources/mediawiki.ui/sourcefiles/scss/components/_utilities.scss
deleted file mode 100644 (file)
index 4f1dba2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Generic helper classes that could be used in many elements/layouts
-
-// --------------------------------------------------------------------------
-// Positioning
-// --------------------------------------------------------------------------
-
-.mw-ui-flush-left {
-    @include agora-flush-left;
-}
-
-.mw-ui-flush-right {
-    @include agora-flush-right;
-}
-
-.mw-ui-center-block {
-    @include agora-center-block;
-}
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/_vector.scss b/resources/mediawiki.ui/sourcefiles/scss/components/_vector.scss
deleted file mode 100644 (file)
index d7cb34a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-@import "utilities";
-@import "vector/buttons";
-@import "vector/forms";
-@import "vector/containers";
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/default/_buttons.scss b/resources/mediawiki.ui/sourcefiles/scss/components/default/_buttons.scss
deleted file mode 100644 (file)
index d67810f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-$buttonBorderRadius: 3px;
-
-// Button styling
-.mw-ui-button {
-    // Container layout
-    @include inline-block;
-    padding: 0.4em 1em 0.4em 1em;
-    margin: 0;
-
-    // Container styling
-    @include buttonColors($agoraGray);
-    @include border-radius($buttonBorderRadius);
-
-    // Content styling
-    vertical-align: middle;
-
-    text: {
-        align: center;
-        decoration: none;
-    }
-
-    font: {
-        weight: bold;
-    }
-
-    // Interaction styling
-    cursor: pointer;
-
-    &:disabled,
-    &.mw-ui-disabled {
-        cursor: default;
-    }
-
-    // Button sizes and displays
-    // -----------------------------------------
-    &.mw-ui-big {
-        font: {
-            size: $baseFontSize * 1.3;
-        }
-    }
-    &.mw-ui-block {
-        display: block;
-        width: 100%;
-    }
-}
-
-// This overrides an underline declaration on a:hover and a:focus in commonElements.css, which the
-// class alone isn't specific enough to do
-a.mw-ui-button {
-    text: {
-        decoration: none;
-    }
-}
-
-// Button groups
-.mw-ui-button-group > * {
-  @include border-radius(0);
-  float: left;
-
-  &:first-child{
-    @include border-top-left-radius($buttonBorderRadius);
-    @include border-bottom-left-radius($buttonBorderRadius);
-  }
-
-  &:last-child{
-    @include border-top-right-radius($buttonBorderRadius);
-    @include border-bottom-right-radius($buttonBorderRadius);
-  }
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/default/_forms.scss b/resources/mediawiki.ui/sourcefiles/scss/components/default/_forms.scss
deleted file mode 100644 (file)
index a9cec39..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// Form elements and layouts
-
-// --------------------------------------------------------------------------
-// Layouts
-// --------------------------------------------------------------------------
-
-// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
-// 'VForm' design, the form can't be narrower than this.
-$captchaContainerWidth: 290px;
-$defaultFormWidth: $captchaContainerWidth;
-
-// Style a compact vertical stacked form ("VForm") and the elements in divs
-// within it.
-.mw-ui-vform {
-    @include box-sizing(border-box);
-
-    width: $defaultFormWidth;
-
-    // Immediate divs in a vform are block and spaced-out.
-    & > div {
-        display: block;
-        margin: 0 0 15px 0;
-        padding: 0;
-        width: 100%;
-
-        // MW currently doesn't use the type attribute everywhere on inputs.
-        input,
-        .mw-ui-button {
-            display: block;
-            @include box-sizing(border-box);
-            margin: 0;
-            width: 100%;
-        }
-
-        // We exclude these because they'll generally use mw-ui-button.
-        // Otherwise, we'll unintentionally override that.
-        input:not([type=button]):not([type=submit]):not([type=file]), {
-            @include agora-field-styling; // mixins/_forms.scss
-        }
-
-        label {
-            display: block;
-            @include box-sizing(border-box);
-            @include agora-label-styling;
-            width: auto;
-            margin: 0 0 0.2em 0;
-            padding: 0;
-        }
-
-        // Override input styling just for checkboxes and radio inputs.
-        input[type="checkbox"],
-        input[type="radio"] {
-            display: inline;
-            @include box-sizing(content-box);
-            width: auto;
-        }
-
-    }
-
-    // HTMLForm uses error, SpecialUserlogin (login and create account) uses
-    // errorbox.
-    // TODO move errorbox from mediawiki.special.vforms.css into here.
-    .error {
-        -webkit-box-sizing: border-box;
-        -moz-box-sizing: border-box;
-        box-sizing: border-box;
-        font-size: 0.9em;
-        margin: 0 0 1em 0;
-        padding: 0.5em;
-        color: #cc0000;
-        border: 1px solid #fac5c5;
-        background-color: #fae3e3;
-        text-shadow: 0 1px #fae3e3;
-        word-wrap: break-word;
-    }
-}
-
-// --------------------------------------------------------------------------
-// Elements
-// --------------------------------------------------------------------------
-
-// Apply this to individual elements to style them.
-// You generally don't need to use this class on divs within an Agora
-// form container such as mw-ui-vform
-// XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
-.mw-ui-vform-div {
-       display: block;
-       margin: 0 0 15px 0;
-       padding: 0;
-       width: 100%;
-}
-
-// Apply mw-ui-input to individual input fields to style them.
-// You generally don't need to use this class if <input> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-input {
-    @include agora-field-styling; // mixins/_forms.scss
-}
-
-// Apply mw-ui-label to individual elements to style them.
-// You generally don't need to use this class if <label> is within an Agora
-// form container such as mw-ui-vform
-.mw-ui-label {
-    @include agora-label-styling; // mixins/_forms.scss
-}
-
-// Nesting an input checkbox or radio button inside a label with this class
-// improves alignment, e.g.
-//   <label class="mw-ui-checkbox-label">
-//       <input type="checkbox">The label text
-//   </label>
-.mw-ui-checkbox-label, .mw-ui-radio-label {
-    @include agora-inline-label-styling;
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/vector/_buttons.scss b/resources/mediawiki.ui/sourcefiles/scss/components/vector/_buttons.scss
deleted file mode 100644 (file)
index 8d5f0b6..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-@import "../default/buttons"; // Layer Vector on top of the default settings.
-
-.mw-ui-button {
-    // Button colors determined by function.
-    // -----------------------------------------
-    &.mw-ui-primary {
-        @include buttonColors($agoraBlue);
-    }
-
-    &.mw-ui-constructive {
-        @include buttonColors($agoraGreen);
-    }
-
-    &.mw-ui-destructive {
-        @include buttonColors($agoraRed);
-    }
-
-    @include vector-type;
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/vector/_containers.scss b/resources/mediawiki.ui/sourcefiles/scss/components/vector/_containers.scss
deleted file mode 100644 (file)
index ed01603..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// No default settings for containers yet.
-
-.mw-ui-container {
-    @include vector-type;
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/components/vector/_forms.scss b/resources/mediawiki.ui/sourcefiles/scss/components/vector/_forms.scss
deleted file mode 100644 (file)
index 73ea24e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@import "../default/forms"; // Layer Vector on top of the default settings.
-
-.mw-ui-vform,
-.mw-ui-vform > div input,
-.mw-ui-input {
-    @include vector-type;
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.default.scss b/resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.default.scss
deleted file mode 100644 (file)
index e6db523..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Provide Agora appearance for mw-ui-* classes when using a skin other than
- * Vector.
- * Compass builds these Agora styles from source Sass files in
- * extensions/Agora/modules/scss
- */
-
-@charset "UTF-8";
-
-@import "compass";
-
-@import "settings/all";
-
-@import "mixins/all";
-
-@import "components/default";
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.vector.scss b/resources/mediawiki.ui/sourcefiles/scss/mediawiki.ui.vector.scss
deleted file mode 100644 (file)
index ac113ee..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
- * Compass builds these Agora styles from source Sass files in
- * extensions/Agora/modules/scss
- */
-
-@charset "UTF-8";
-
-@import "compass";
-
-@import "settings/all";
-
-@import "mixins/all";
-
-@import "components/vector";
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mixins/_all.scss b/resources/mediawiki.ui/sourcefiles/scss/mixins/_all.scss
deleted file mode 100644 (file)
index adc48cd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-@import "utilities";
-@import "type";
-@import "effects";
-@import "forms";
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mixins/_effects.scss b/resources/mediawiki.ui/sourcefiles/scss/mixins/_effects.scss
deleted file mode 100644 (file)
index 2efff82..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* _effects.scss */
-
-/* Mixins for visual effects in CSS3 */
-
-// ----------------------------------------------------------------------------
-// Gradients
-// ----------------------------------------------------------------------------
-@mixin vertical-gradient ($startColor: lighten($agoraGray, 95%), $endColor: $agoraGray) {
-       // Fallback
-    background-color: $endColor;
-    *background-color: $endColor; // IE7
-
-    // IE6-8
-    @include filter-gradient($startColor, $endColor, vertical);
-
-    // IE9+, Opera, Gecko, WebKit
-    @include background-image(linear-gradient(top, $startColor, $endColor));
-}
-
-// ----------------------------------------------------------------------------
-// Button styling
-// ----------------------------------------------------------------------------
-@mixin buttonColors ($baseColor: $agoraGray) {
-       // Background color
-       @include vertical-gradient(lighten($baseColor, 7.5%), $baseColor);
-
-       @if $baseColor == $agoraGray {
-               color: black;
-               @include text-shadow(0 1px 1px rgba($baseColor, 0.3));
-       } @else {
-               color: white;
-               @include text-shadow(0 1px 1px rgba($baseColor, 0.75));
-       }
-
-       border: 1px solid darken($baseColor, 2%);
-
-       &:hover,
-       &.mw-ui-hover {
-               @include vertical-gradient(lighten($baseColor, 12.5%), lighten($baseColor, 7.5%));
-               text-decoration: none;
-       }
-
-       &:active,
-       &.mw-ui-active {
-               background: {
-                       image: none;
-                       color: darken($baseColor, 3%);
-               }
-
-               text-shadow: none;
-       }
-
-       &:disabled,
-       &.mw-ui-disabled {
-               background: {
-                       image: none;
-                       color: $baseColor;
-               }
-               opacity: 0.5;
-               text-shadow: none;
-       }
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mixins/_forms.scss b/resources/mediawiki.ui/sourcefiles/scss/mixins/_forms.scss
deleted file mode 100644 (file)
index 0f3f6ad..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// Font is not included.
-// For Vector, that should be layered on top with vector-type
-@mixin agora-field-styling() {
-
-       border: {
-               style: solid;
-               width: 1px;
-               color: $agoraGray;
-       };
-
-       &:focus {
-               // Styling focus of native checkboxes etc on Mac is almost impossible.
-               &:not([type=checkbox]):not([type=radio]) {
-                       @include reset-focus;  // Removes OS field focus
-               };
-
-               // @include box-shadow generates unneeded prefixes
-               // https://github.com/chriseppstein/compass/issues/1054 , so specify
-               // directly.
-               box-shadow: $agoraBlueShadow 0px 0px 5px;
-
-               border: {
-                       color: $agoraBlueShadow;
-               };
-       }
-
-       color: $agoraTextColor;
-       padding: 0.35em 0 0.35em 0.5em;
-}
-
-@mixin agora-label-styling() {
-       font: {
-               //weight: bold;
-               size: 0.9em;
-       };
-       color: darken($agoraGray, 50%);
-
-       & * {
-               font-weight: normal;
-       }
-}
-
-@mixin agora-inline-label-styling() {
-       margin-bottom: 0.5em;
-       cursor: pointer;
-       vertical-align: bottom;
-       line-height: normal;
-
-       font: {
-               weight: normal;
-       };
-
-       & > input[type="checkbox"],
-       & > input[type="radio"] {
-               width: auto;
-               height: auto;
-               margin: 0 0.1em 0em 0;
-               padding: 0;
-               border: {
-                       style: solid;
-                       width: 1px;
-                       color: $agoraGray;
-               }
-               cursor: pointer;
-       }
-}
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mixins/_type.scss b/resources/mediawiki.ui/sourcefiles/scss/mixins/_type.scss
deleted file mode 100644 (file)
index 8a93a08..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-@mixin vector-type {
-    font: {
-        size: $baseFontSize;
-    }
-    line-height: $baseLineHeight;
-}
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/mixins/_utilities.scss b/resources/mediawiki.ui/sourcefiles/scss/mixins/_utilities.scss
deleted file mode 100644 (file)
index 71a93b6..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-@mixin agora-flush-left() {
-    float: left;
-    margin-left: 0;
-    padding-left: 0;
-}
-
-@mixin agora-flush-right() {
-    float: right;
-    margin-right: 0;
-    padding-right: 0;
-}
-
-@mixin agora-center-block() {
-    display: block;
-    margin: {
-        left: auto;
-        right: auto;
-    };
-}
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/settings/_all.scss b/resources/mediawiki.ui/sourcefiles/scss/settings/_all.scss
deleted file mode 100644 (file)
index 21ac292..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-@import "colors";
-@import "typography";
\ No newline at end of file
diff --git a/resources/mediawiki.ui/sourcefiles/scss/settings/_colors.scss b/resources/mediawiki.ui/sourcefiles/scss/settings/_colors.scss
deleted file mode 100644 (file)
index 0c18bdb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Grays
-// -----------------------------------------
-$agoraGray: #c9c9c9;
-$agoraTextColor: #252525;
-
-// Blues
-// -----------------------------------------
-$agoraBlue: #3366bb;
-$agoraBlueShadow: #4091ed;
-
-// Greens
-// -----------------------------------------
-$agoraGreen: #27aa65;
-
-// Reds
-// -----------------------------------------
-$agoraRed: #cc0000;
diff --git a/resources/mediawiki.ui/sourcefiles/scss/settings/_typography.scss b/resources/mediawiki.ui/sourcefiles/scss/settings/_typography.scss
deleted file mode 100644 (file)
index 013d12b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-$baseFontSize: 1em;
-$baseLineHeight: 1.4 * $baseFontSize;
-$baseFontColor: $agoraTextColor;
-
-$smallFontSize: 0.75em;
\ No newline at end of file
diff --git a/resources/mediawiki.ui/vector.less b/resources/mediawiki.ui/vector.less
new file mode 100644 (file)
index 0000000..a347562
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+ * Provide Agora appearance for mw-ui-* classes when using the Vector skin.
+ */
+
+@import "components/utilities";
+@import "components/vector/buttons";
+@import "components/vector/forms";
+@import "components/vector/containers";
index b236019..de2d013 100644 (file)
                                title.indexOf( '../' ) === 0 ||
                                title.indexOf( '/./' ) !== -1 ||
                                title.indexOf( '/../' ) !== -1 ||
-                               title.substr( -2 ) === '/.' ||
-                               title.substr( -3 ) === '/..'
+                               title.substr( title.length - 2 ) === '/.' ||
+                               title.substr( title.length - 3 ) === '/..'
                        )
                ) {
                        return false;
 
                        // thumb.php-generated thumbnails
                        thumbPhpRegex = /thumb\.php/,
-
                        regexes = [
                                // Thumbnails
-                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)\/[0-9]+px-\1[^\s\/]*$/,
+                               /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
 
                                // Thumbnails in non-hashed upload directories
-                               /\/([^\s\/]+)\/[0-9]+px-\1[^\s\/]*$/,
+                               /\/([^\s\/]+)\/[^\s\/]+-(?:\1|thumbnail)[^\s\/]*$/,
 
                                // Full size images
                                /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s\/]+)$/,
                /**
                 * Get the URL to this title
                 *
-                * @see mw.util#wikiGetlink
+                * @see mw.util#getUrl
+                * @param {Object} [params] A mapping of query parameter names to values,
+                *     e.g. `{ action: 'edit' }`.
                 * @return {string}
                 */
-               getUrl: function () {
-                       return mw.util.wikiGetlink( this.toString() );
+               getUrl: function ( params ) {
+                       return mw.util.getUrl( this.toString(), params );
                },
 
                /**
diff --git a/resources/mediawiki/mediawiki.hlist.css b/resources/mediawiki/mediawiki.hlist.css
new file mode 100644 (file)
index 0000000..0bd86fe
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+       Stylesheet for mediawiki.hlist module
+       @author [[User:Edokter]]
+ */
+.skin-monobook .hlist dl,
+.skin-modern .hlist dl,
+.skin-vector .hlist dl {
+       line-height: 1.5em;
+}
+.hlist dl,
+.hlist ol,
+.hlist ul {
+       margin: 0;
+       padding: 0;
+}
+/* Display list items inline */
+.hlist dd,
+.hlist dt,
+.hlist li {
+       margin: 0;
+       display: inline;
+}
+/* Display nested lists inline */
+.hlist dl dl, .hlist dl ol, .hlist dl ul,
+.hlist ol dl, .hlist ol ol, .hlist ol ul,
+.hlist ul dl, .hlist ul ol, .hlist ul ul {
+       display: inline;
+}
+/* Generate interpuncts */
+.hlist dt:after {
+       content: ":";
+}
+.hlist dd:after,
+.hlist li:after {
+       content: " ·";
+       font-weight: bold;
+}
+.hlist dd:last-child:after,
+.hlist dt:last-child:after,
+.hlist li:last-child:after {
+       content: none;
+}
+/* For IE8 */
+.hlist dd.hlist-last-child:after,
+.hlist dt.hlist-last-child:after,
+.hlist li.hlist-last-child:after {
+       content: none;
+}
+/* Add parentheses around nested lists */
+.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before,
+.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before,
+.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before {
+       content: "(";
+       font-weight: normal;
+}
+.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after,
+.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after,
+.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after {
+       content: ")";
+       font-weight: normal;
+}
+/* For IE8 */
+.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after,
+.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after,
+.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after {
+       content: ")";
+       font-weight: normal;
+}
+/* Put ordinals in front of ordered list items */
+.hlist ol {
+       counter-reset: list-item;
+}
+.hlist ol > li {
+       counter-increment: list-item;
+}
+.hlist ol > li:before {
+       content: counter(list-item) " ";
+}
+.hlist dd ol > li:first-child:before,
+.hlist dt ol > li:first-child:before,
+.hlist li ol > li:first-child:before {
+       content: "(" counter(list-item) " ";
+}
diff --git a/resources/mediawiki/mediawiki.hlist.js b/resources/mediawiki/mediawiki.hlist.js
new file mode 100644 (file)
index 0000000..ef98136
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+       IE 8: Add pseudo-selector class to last-child list items
+       @author [[User:Edokter]]
+*/
+jQuery( function( $ ) {
+       if ( $.client.profile().name === 'msie' ) {
+               if ( $.client.profile().versionNumber === 8 ) {
+                       $( '.hlist' ).find( 'dd:last-child, dt:last-child, li:last-child' )
+                               .addClass( 'hlist-last-child' );
+               }
+                       /* IE 7 and below: Generate interpuncts and parentheses */
+               if ( $.client.profile().versionNumber <= 7 ) {
+                       var $hlists = $( '.hlist' );
+                       $hlists.find( 'dt:not(:last-child)' )
+                               .append( ': ' );
+                       $hlists.find( 'dd:not(:last-child)' )
+                               .append( '<b>·</b> ' );
+                       $hlists.find( 'li:not(:last-child)' )
+                               .append( '<b>·</b> ' );
+                       $hlists.find( 'dl dl, dl ol, dl ul, ol dl, ol ol, ol ul, ul dl, ul ol, ul ul' )
+                               .prepend( '( ' ).append( ') ' );
+               }
+       }
+} );
index c895adf..d93254b 100644 (file)
                } );
        }
 
+       function humanSize( bytes ) {
+               if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
+               var i = 0, units = [ '', ' kB', ' MB', ' GB', ' TB', ' PB' ];
+               for ( ; bytes >= 1024; bytes /= 1024 ) { i++; }
+               return bytes.toFixed( 1 ) + units[i];
+       }
+
        /**
         * @class mw.inspect
         * @singleton
         */
        var inspect = {
 
+               /**
+                * Return a map of all dependency relationships between loaded modules.
+                *
+                * @return {Object} Maps module names to objects. Each sub-object has
+                *  two properties, 'requires' and 'requiredBy'.
+                */
+               getDependencyGraph: function () {
+                       var modules = inspect.getLoadedModules(), graph = {};
+
+                       $.each( modules, function ( moduleIndex, moduleName ) {
+                               var dependencies = mw.loader.moduleRegistry[moduleName].dependencies || [];
+
+                               graph[moduleName] = graph[moduleName] || { requiredBy: [] };
+                               graph[moduleName].requires = dependencies;
+
+                               $.each( dependencies, function ( depIndex, depName ) {
+                                       graph[depName] = graph[depName] || { requiredBy: [] };
+                                       graph[depName].requiredBy.push( moduleName );
+                               } );
+                       } );
+                       return graph;
+               },
+
                /**
                 * Calculate the byte size of a ResourceLoader module.
                 *
                 */
                auditSelectors: function ( css ) {
                        var selectors = { total: 0, matched: 0 },
-                               style = document.createElement( 'style' );
+                               style = document.createElement( 'style' ),
+                               sheet, rules;
 
                        style.textContent = css;
                        document.body.appendChild( style );
-                       $.each( style.sheet.cssRules, function ( index, rule ) {
+                       // Standards-compliant browsers use .sheet.cssRules, IE8 uses .styleSheet.rules…
+                       sheet = style.sheet || style.styleSheet;
+                       rules = sheet.cssRules || sheet.rules;
+                       $.each( rules, function ( index, rule ) {
                                selectors.total++;
                                if ( document.querySelector( rule.selectorText ) !== null ) {
                                        selectors.matched++;
                                // Use Function.prototype#call to force an exception on Firefox,
                                // which doesn't define console#table but doesn't complain if you
                                // try to invoke it.
-                               console.table.call( console.table, data );
+                               console.table.call( console, data );
                                return;
                        } catch (e) {}
                        try {
 
                                // Convert size to human-readable string.
                                $.each( modules, function ( i, module ) {
-                                       module.size = module.size > 1024 ?
-                                               ( module.size / 1024 ).toFixed( 2 ) + ' KB' :
-                                               ( module.size !== null ? module.size + ' B' : null );
+                                       module.size = humanSize( module.size );
                                } );
 
                                return modules;
                                sortByProperty( modules, 'allSelectors', true );
                                return modules;
                        },
+
+                       /**
+                        * Report stats on mw.loader.store: the number of localStorage
+                        * cache hits and misses, the number of items purged from the
+                        * cache, and the total size of the module blob in localStorage.
+                        */
+                       store: function () {
+                               var raw, stats = { enabled: mw.loader.store.enabled };
+                               if ( stats.enabled ) {
+                                       $.extend( stats, mw.loader.store.stats );
+                                       try {
+                                               raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+                                               stats.totalSize = humanSize( $.byteLength( raw ) );
+                                       } catch (e) {}
+                               }
+                               return [stats];
+                       }
                }
        };
 
index b634917..70b9be9 100644 (file)
                        var page, anchor, url;
 
                        page = nodes[0];
-                       url = mw.util.wikiGetlink( page );
+                       url = mw.util.getUrl( page );
 
                        // [[Some Page]] or [[Namespace:Some Page]]
                        if ( nodes.length === 1 ) {
index cc996e5..724ca5e 100644 (file)
@@ -1,5 +1,9 @@
-/*
- * Core MediaWiki JavaScript Library
+/**
+ * Base library for MediaWiki.
+ *
+ * @class mw
+ * @alternateClassName mediaWiki
+ * @singleton
  */
 
 var mw = ( function ( $, undefined ) {
@@ -10,6 +14,31 @@ var mw = ( function ( $, undefined ) {
        var hasOwn = Object.prototype.hasOwnProperty,
                slice = Array.prototype.slice;
 
+       /**
+        * Log a message to window.console, if possible. Useful to force logging of some
+        * errors that are otherwise hard to detect (I.e., this logs also in production mode).
+        * Gets console references in each invocation, so that delayed debugging tools work
+        * fine. No need for optimization here, which would only result in losing logs.
+        *
+        * @private
+        * @method log_
+        * @param {string} msg text for the log entry.
+        * @param {Error} [e]
+        */
+       function log( msg, e ) {
+               var console = window.console;
+               if ( console && console.log ) {
+                       console.log( msg );
+                       // If we have an exception object, log it through .error() to trigger
+                       // proper stacktraces in browsers that support it. There are no (known)
+                       // browsers that don't support .error(), that do support .log() and
+                       // have useful exception handling through .log().
+                       if ( e && console.error ) {
+                               console.error( String( e ), e );
+                       }
+               }
+       }
+
        /* Object constructors */
 
        /**
@@ -46,11 +75,11 @@ var mw = ( function ( $, undefined ) {
         * @class mw.Map
         *
         * @constructor
-        * @param {boolean} [global=false] Whether to store the values in the global window
-        *  object or a exclusively in the object property 'values'.
+        * @param {Object|boolean} [values] Value-bearing object to map, or boolean
+        *  true to map over the global object. Defaults to an empty object.
         */
-       function Map( global ) {
-               this.values = global === true ? window : {};
+       function Map( values ) {
+               this.values = values === true ? window : ( values || {} );
                return this;
        }
 
@@ -197,7 +226,7 @@ var mw = ( function ( $, undefined ) {
                },
 
                /**
-                * Converts message object to it's string form based on the state of format.
+                * Converts message object to its string form based on the state of format.
                 *
                 * @return {string} Message as a string in the current form or `<key>` if key does not exist.
                 */
@@ -291,11 +320,7 @@ var mw = ( function ( $, undefined ) {
        };
 
        /**
-        * Base library for MediaWiki.
-        *
         * @class mw
-        * @alternateClassName mediaWiki
-        * @singleton
         */
        return {
                /* Public Members */
@@ -592,7 +617,7 @@ var mw = ( function ( $, undefined ) {
                                                        try {
                                                                styleEl.styleSheet.cssText += cssText; // IE
                                                        } catch ( e ) {
-                                                               log( 'addEmbeddedCSS fail\ne.message: ' + e.message, e );
+                                                               log( 'addEmbeddedCSS fail', e );
                                                        }
                                                } else {
                                                        styleEl.appendChild( document.createTextNode( String( cssText ) ) );
@@ -770,30 +795,6 @@ var mw = ( function ( $, undefined ) {
                                return filter( 'ready', dependencies ).length === dependencies.length;
                        }
 
-                       /**
-                        * Log a message to window.console, if possible. Useful to force logging of some
-                        * errors that are otherwise hard to detect (I.e., this logs also in production mode).
-                        * Gets console references in each invocation, so that delayed debugging tools work
-                        * fine. No need for optimization here, which would only result in losing logs.
-                        *
-                        * @private
-                        * @param {string} msg text for the log entry.
-                        * @param {Error} [e]
-                        */
-                       function log( msg, e ) {
-                               var console = window.console;
-                               if ( console && console.log ) {
-                                       console.log( msg );
-                                       // If we have an exception object, log it through .error() to trigger
-                                       // proper stacktraces in browsers that support it. There are no (known)
-                                       // browsers that don't support .error(), that do support .log() and
-                                       // have useful exception handling through .log().
-                                       if ( e && console.error ) {
-                                               console.error( e );
-                                       }
-                               }
-                       }
-
                        /**
                         * A module has entered state 'ready', 'error', or 'missing'. Automatically update pending jobs
                         * and modules that depend upon this module. if the given module failed, propagate the 'error'
@@ -834,29 +835,26 @@ var mw = ( function ( $, undefined ) {
                                                j -= 1;
                                                try {
                                                        if ( hasErrors ) {
-                                                               throw new Error( 'Module ' + module + ' failed.');
+                                                               if ( $.isFunction( job.error ) ) {
+                                                                       job.error( new Error( 'Module ' + module + ' has failed dependencies' ), [module] );
+                                                               }
                                                        } else {
                                                                if ( $.isFunction( job.ready ) ) {
                                                                        job.ready();
                                                                }
                                                        }
                                                } catch ( e ) {
-                                                       if ( $.isFunction( job.error ) ) {
-                                                               try {
-                                                                       job.error( e, [module] );
-                                                               } catch ( ex ) {
-                                                                       // A user-defined operation raised an exception. Swallow to protect
-                                                                       // our state machine!
-                                                                       log( 'Exception thrown by job.error()', ex );
-                                                               }
-                                                       }
+                                                       // A user-defined callback raised an exception.
+                                                       // Swallow it to protect our state machine!
+                                                       log( 'Exception thrown by job.error', e );
                                                }
                                        }
                                }
 
                                if ( registry[module].state === 'ready' ) {
-                                       // The current module became 'ready'. Recursively execute all dependent modules that are loaded
-                                       // and now have all dependencies satisfied.
+                                       // The current module became 'ready'. Set it in the module store, and recursively execute all
+                                       // dependent modules that are loaded and now have all dependencies satisfied.
+                                       mw.loader.store.set( module, registry[module] );
                                        for ( m in registry ) {
                                                if ( registry[m].state === 'loaded' && allReady( registry[m].dependencies ) ) {
                                                        execute( m );
@@ -1009,7 +1007,7 @@ var mw = ( function ( $, undefined ) {
                                        } catch ( e ) {
                                                // This needs to NOT use mw.log because these errors are common in production mode
                                                // and not in debug mode, such as when a symbol that should be global isn't exported
-                                               log( 'Exception thrown by ' + module + ': ' + e.message, e );
+                                               log( 'Exception thrown by ' + module, e );
                                                registry[module].state = 'error';
                                                handlePending( module );
                                        }
@@ -1210,7 +1208,7 @@ var mw = ( function ( $, undefined ) {
                                addScript( sourceLoadScript + '?' + $.param( request ) + '&*', null, async );
                        }
 
-                       /* Public Methods */
+                       /* Public Members */
                        return {
                                /**
                                 * The module registry is exposed as an aid for debugging and inspecting page
@@ -1233,7 +1231,7 @@ var mw = ( function ( $, undefined ) {
                                 */
                                work: function () {
                                        var     reqBase, splits, maxQueryLength, q, b, bSource, bGroup, bSourceGroup,
-                                               source, group, g, i, modules, maxVersion, sourceLoadScript,
+                                               source, concatSource, group, g, i, modules, maxVersion, sourceLoadScript,
                                                currReqBase, currReqBaseLength, moduleMap, l,
                                                lastDotIndex, prefix, suffix, bytesAdded, async;
 
@@ -1259,6 +1257,21 @@ var mw = ( function ( $, undefined ) {
                                                        }
                                                }
                                        }
+
+                                       mw.loader.store.init();
+                                       if ( mw.loader.store.enabled ) {
+                                               concatSource = [];
+                                               batch = $.grep( batch, function ( module ) {
+                                                       var source = mw.loader.store.get( module );
+                                                       if ( source ) {
+                                                               concatSource.push( source );
+                                                               return false;
+                                                       }
+                                                       return true;
+                                               } );
+                                               $.globalEval( concatSource.join( ';' ) );
+                                       }
+
                                        // Early exit if there's nothing to load...
                                        if ( !batch.length ) {
                                                return;
@@ -1453,16 +1466,19 @@ var mw = ( function ( $, undefined ) {
                                 * @param {Function|Array} script Function with module code or Array of URLs to
                                 *  be used as the src attribute of a new `<script>` tag.
                                 * @param {Object} style Should follow one of the following patterns:
+                                *
                                 *     { "css": [css, ..] }
                                 *     { "url": { <media>: [url, ..] } }
+                                *
                                 * And for backwards compatibility (needs to be supported forever due to caching):
+                                *
                                 *     { <media>: css }
                                 *     { <media>: [url, ..] }
                                 *
                                 * The reason css strings are not concatenated anymore is bug 31676. We now check
                                 * whether it's safe to extend the stylesheet (see #canExpandStylesheetWith).
                                 *
-                                * @param {Object} msgs List of key/value pairs to be added to {@link mw#messages}.
+                                * @param {Object} msgs List of key/value pairs to be added to mw#messages.
                                 */
                                implement: function ( module, script, style, msgs ) {
                                        // Validate input
@@ -1710,8 +1726,242 @@ var mw = ( function ( $, undefined ) {
                                        mw.loader.using( 'mediawiki.inspect', function () {
                                                mw.inspect.runReports.apply( mw.inspect, args );
                                        } );
-                               }
+                               },
+
+                               /**
+                                * On browsers that implement the localStorage API, the module store serves as a
+                                * smart complement to the browser cache. Unlike the browser cache, the module store
+                                * can slice a concatenated response from ResourceLoader into its constituent
+                                * modules and cache each of them separately, using each module's versioning scheme
+                                * to determine when the cache should be invalidated.
+                                *
+                                * @singleton
+                                * @class mw.loader.store
+                                */
+                               store: {
+                                       // Whether the store is in use on this page.
+                                       enabled: null,
+
+                                       // The contents of the store, mapping '[module name]@[version]' keys
+                                       // to module implementations.
+                                       items: {},
+
+                                       // Cache hit stats
+                                       stats: { hits: 0, misses: 0, expired: 0 },
+
+                                       /**
+                                        * Construct a JSON-serializable object representing the content of the store.
+                                        * @return {Object} Module store contents.
+                                        */
+                                       toJSON: function () {
+                                               return { items: mw.loader.store.items, vary: mw.loader.store.getVary() };
+                                       },
+
+                                       /**
+                                        * Get the localStorage key for the entire module store. The key references
+                                        * $wgDBname to prevent clashes between wikis which share a common host.
+                                        *
+                                        * @return {string} localStorage item key
+                                        */
+                                       getStoreKey: function () {
+                                               return 'MediaWikiModuleStore:' + mw.config.get( 'wgDBname' );
+                                       },
+
+                                       /**
+                                        * Get a string key on which to vary the module cache.
+                                        * @return {string} String of concatenated vary conditions.
+                                        */
+                                       getVary: function () {
+                                               return [
+                                                       mw.config.get( 'skin' ),
+                                                       mw.config.get( 'wgResourceLoaderStorageVersion' ),
+                                                       mw.config.get( 'wgUserLanguage' )
+                                               ].join(':');
+                                       },
+
+                                       /**
+                                        * Get a string key for a specific module. The key format is '[name]@[version]'.
+                                        *
+                                        * @param {string} module Module name
+                                        * @return {string|null} Module key or null if module does not exist
+                                        */
+                                       getModuleKey: function ( module ) {
+                                               return typeof registry[module] === 'object' ?
+                                                       ( module + '@' + registry[module].version ) : null;
+                                       },
+
+                                       /**
+                                        * Initialize the store by retrieving it from localStorage and (if successfully
+                                        * retrieved) decoding the stored JSON value to a plain object.
+                                        *
+                                        * The try / catch block is used for JSON & localStorage feature detection.
+                                        * See the in-line documentation for Modernizr's localStorage feature detection
+                                        * code for a full account of why we need a try / catch: <http://git.io/4NEwKg>.
+                                        */
+                                       init: function () {
+                                               var raw, data;
+
+                                               if ( mw.loader.store.enabled !== null ) {
+                                                       // #init already ran.
+                                                       return;
+                                               }
 
+                                               if ( !mw.config.get( 'wgResourceLoaderStorageEnabled' ) || mw.config.get( 'debug' ) ) {
+                                                       // Disabled by configuration, or because debug mode is set.
+                                                       mw.loader.store.enabled = false;
+                                                       return;
+                                               }
+
+                                               try {
+                                                       raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+                                                       // If we get here, localStorage is available; mark enabled.
+                                                       mw.loader.store.enabled = true;
+                                                       data = JSON.parse( raw );
+                                                       if ( data && typeof data.items === 'object' && data.vary === mw.loader.store.getVary() ) {
+                                                               mw.loader.store.items = data.items;
+                                                               return;
+                                                       }
+                                               } catch (e) {}
+
+                                               if ( raw === undefined ) {
+                                                       mw.loader.store.enabled = false;  // localStorage failed; disable store.
+                                               } else {
+                                                       mw.loader.store.update();
+                                               }
+                                       },
+
+                                       /**
+                                        * Retrieve a module from the store and update cache hit stats.
+                                        *
+                                        * @param {string} module Module name
+                                        * @return {string|boolean} Module implementation or false if unavailable
+                                        */
+                                       get: function ( module ) {
+                                               var key;
+
+                                               if ( mw.loader.store.enabled !== true ) {
+                                                       return false;
+                                               }
+
+                                               key = mw.loader.store.getModuleKey( module );
+                                               if ( key in mw.loader.store.items ) {
+                                                       mw.loader.store.stats.hits++;
+                                                       return mw.loader.store.items[key];
+                                               }
+                                               mw.loader.store.stats.misses++;
+                                               return false;
+                                       },
+
+                                       /**
+                                        * Stringify a module and queue it for storage.
+                                        *
+                                        * @param {string} module Module name
+                                        * @param {Object} descriptor The module's descriptor as set in the registry
+                                        */
+                                       set: function ( module, descriptor ) {
+                                               var args, key;
+
+                                               if ( mw.loader.store.enabled !== true ) {
+                                                       return false;
+                                               }
+
+                                               key = mw.loader.store.getModuleKey( module );
+
+                                               if ( key in mw.loader.store.items ) {
+                                                       // Already set; decline to store.
+                                                       return false;
+                                               }
+
+                                               if ( descriptor.state !== 'ready' ) {
+                                                       // Module failed to load; decline to store.
+                                                       return false;
+                                               }
+
+                                               if ( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user', 'site' ] ) !== -1 ) {
+                                                       // Unversioned, private, or site-/user-specific; decline to store.
+                                                       return false;
+                                               }
+
+                                               if ( $.inArray( undefined, [ descriptor.script, descriptor.style, descriptor.messages ] ) !== -1 ) {
+                                                       // Partial descriptor; decline to store.
+                                                       return false;
+                                               }
+
+                                               try {
+                                                       args = [
+                                                               JSON.stringify( module ),
+                                                               typeof descriptor.script === 'function' ?
+                                                                       String( descriptor.script ) : JSON.stringify( descriptor.script ),
+                                                               JSON.stringify( descriptor.style ),
+                                                               JSON.stringify( descriptor.messages )
+                                                       ];
+                                               } catch (e) {
+                                                       return;
+                                               }
+                                               mw.loader.store.items[key] = 'mw.loader.implement(' + args.join(',') + ');';
+                                               mw.loader.store.update();
+                                       },
+
+                                       /**
+                                        * Iterate through the module store, removing any item that does not correspond
+                                        * (in name and version) to an item in the module registry.
+                                        */
+                                       prune: function () {
+                                               var key, module;
+
+                                               if ( mw.loader.store.enabled !== true ) {
+                                                       return false;
+                                               }
+
+                                               for ( key in mw.loader.store.items ) {
+                                                       module = key.substring( 0, key.indexOf( '@' ) );
+                                                       if ( mw.loader.store.getModuleKey( module ) !== key ) {
+                                                               mw.loader.store.stats.expired++;
+                                                               delete mw.loader.store.items[key];
+                                                       }
+                                               }
+                                       },
+
+                                       /**
+                                        * Sync modules to localStorage.
+                                        *
+                                        * This function debounces localStorage updates. When called multiple times in
+                                        * quick succession, the calls are coalesced into a single update operation.
+                                        * This allows us to call #update without having to consider the module load
+                                        * queue; the call to localStorage.setItem will be naturally deferred until the
+                                        * page is quiescent.
+                                        *
+                                        * Because localStorage is shared by all pages with the same origin, if multiple
+                                        * pages are loaded with different module sets, the possibility exists that
+                                        * modules saved by one page will be clobbered by another. But the impact would
+                                        * be minor and the problem would be corrected by subsequent page views.
+                                        */
+                                       update: ( function () {
+                                               var timer;
+
+                                               function flush() {
+                                                       var data, key = mw.loader.store.getStoreKey();
+                                                       if ( mw.loader.store.enabled !== true ) {
+                                                               return false;
+                                                       }
+                                                       mw.loader.store.prune();
+                                                       try {
+                                                               // Replacing the content of the module store might fail if the new
+                                                               // contents would exceed the browser's localStorage size limit. To
+                                                               // avoid clogging the browser with stale data, always remove the old
+                                                               // value before attempting to set the new one.
+                                                               localStorage.removeItem( key );
+                                                               data = JSON.stringify( mw.loader.store );
+                                                               localStorage.setItem( key, data );
+                                                       } catch (e) {}
+                                               }
+
+                                               return function () {
+                                                       clearTimeout( timer );
+                                                       timer = setTimeout( flush, 2000 );
+                                               };
+                                       }() )
+                               }
                        };
                }() ),
 
index 3e375fb..78febd2 100644 (file)
@@ -4,7 +4,7 @@
  */
 ( function ( mw, $ ) {
        var user,
-               callbacks = {},
+               deferreds = {},
                // Extend the skeleton mw.user from mediawiki.js
                // This is kind of ugly but we're stuck with this for b/c reasons
                options = mw.user.options || new mw.Map(),
         *
         * @private
         * @param {string} info One of 'groups' or 'rights'
-        * @param {Function} callback
+        * @param {Function} [callback]
+        * @return {jQuery.Promise}
         */
        function getUserInfo( info, callback ) {
                var api;
-               if ( callbacks[info] ) {
-                       callbacks[info].add( callback );
-                       return;
+               if ( !deferreds[info] ) {
+
+                       deferreds.rights = $.Deferred();
+                       deferreds.groups = $.Deferred();
+
+                       api = new mw.Api();
+                       api.get( {
+                               action: 'query',
+                               meta: 'userinfo',
+                               uiprop: 'rights|groups'
+                       } ).always( function ( data ) {
+                               var rights, groups;
+                               if ( data.query && data.query.userinfo ) {
+                                       rights = data.query.userinfo.rights;
+                                       groups = data.query.userinfo.groups;
+                               }
+                               deferreds.rights.resolve( rights || [] );
+                               deferreds.groups.resolve( groups || [] );
+                       } );
+
                }
-               callbacks.rights = $.Callbacks('once memory');
-               callbacks.groups = $.Callbacks('once memory');
-               callbacks[info].add( callback );
-               api = new mw.Api();
-               api.get( {
-                       action: 'query',
-                       meta: 'userinfo',
-                       uiprop: 'rights|groups'
-               } ).always( function ( data ) {
-                       var rights, groups;
-                       if ( data.query && data.query.userinfo ) {
-                               rights = data.query.userinfo.rights;
-                               groups = data.query.userinfo.groups;
-                       }
-                       callbacks.rights.fire( rights || [] );
-                       callbacks.groups.fire( groups || [] );
-               } );
+
+               return deferreds[info].done( callback ).promise();
        }
 
        mw.user = user = {
                /**
                 * Get the current user's groups
                 *
-                * @param {Function} callback
+                * @param {Function} [callback]
+                * @return {jQuery.Promise}
                 */
                getGroups: function ( callback ) {
-                       getUserInfo( 'groups', callback );
+                       return getUserInfo( 'groups', callback );
                },
 
                /**
                 * Get the current user's rights
                 *
-                * @param {Function} callback
+                * @param {Function} [callback]
+                * @return {jQuery.Promise}
                 */
                getRights: function ( callback ) {
-                       getUserInfo( 'rights', callback );
+                       return getUserInfo( 'rights', callback );
                }
        };
 
index 4334a9f..86f06b8 100644 (file)
                 * Get the link to a page name (relative to `wgServer`),
                 *
                 * @param {string} str Page name to get the link for.
-                * @param {Object} params A mapping of query parameter names to values,
-                *     e.g. { action: 'edit' }. Optional.
+                * @param {Object} [params] A mapping of query parameter names to values,
+                *     e.g. `{ action: 'edit' }`.
                 * @return {string} Location for a page with name of `str` or boolean false on error.
                 */
-               wikiGetlink: function ( str, params ) {
+               getUrl: function ( str, params ) {
                        var url = mw.config.get( 'wgArticlePath' ).replace( '$1',
                                util.wikiUrlencode( typeof str === 'string' ? str : mw.config.get( 'wgPageName' ) ) );
                        if ( params && !$.isEmptyObject( params ) ) {
                 */
                addCSS: function ( text ) {
                        var s = mw.loader.addStyleTag( text );
-                       return s.sheet || s;
+                       return s.sheet || s.styleSheet || s;
                },
 
                /**
                                        // nextnode is a DOM element (was the only option before MW 1.17, in wikibits.js)
                                        // or nextnode is a CSS selector for jQuery
                                        nextnode = $ul.find( nextnode );
-                               } else if ( !nextnode.jquery || nextnode[0].parentNode !== $ul[0] ) {
+                               } else if ( !nextnode.jquery || ( nextnode.length && nextnode[0].parentNode !== $ul[0] ) ) {
                                        // Fallback
                                        $ul.append( $item );
                                        return $item[0];
                }
        };
 
+       /**
+        * @method wikiGetlink
+        * @inheritdoc #getUrl
+        * @deprecated since 1.23 Use #getUrl instead.
+        */
+       mw.log.deprecate( util, 'wikiGetlink', util.getUrl, 'Use mw.util.getUrl instead.' );
+
        mw.util = util;
 
 }( mediaWiki, jQuery ) );
diff --git a/skins/.gitignore b/skins/.gitignore
new file mode 100644 (file)
index 0000000..143a107
--- /dev/null
@@ -0,0 +1,11 @@
+*
+!cologneblue
+!CologneBlue.php
+!common
+!modern
+!Modern.php
+!monobook
+!MonoBook.php
+!vector
+!Vector.php
+!.gitignore
index 0370e05..142cb8d 100644 (file)
@@ -169,7 +169,6 @@ class CologneBlueTemplate extends BaseTemplate {
 
                        $lines[] = $this->getSkin()->getLanguage()->pipeList( array_filter( $element ) );
 
-
                        // Second row. Privileged actions.
                        $element = array();
 
@@ -183,7 +182,6 @@ class CologneBlueTemplate extends BaseTemplate {
 
                        $lines[] = $this->getSkin()->getLanguage()->pipeList( array_filter( $element ) );
 
-
                        // Third row. Language links.
                        $lines[] = $this->otherLanguages();
                }
@@ -467,7 +465,6 @@ class CologneBlueTemplate extends BaseTemplate {
                        $bar = $this->sidebarAdditions( $bar );
                }
 
-
                // Fill out special sidebar items with content
                $orig_bar = $bar;
                $bar = array();
@@ -481,7 +478,6 @@ class CologneBlueTemplate extends BaseTemplate {
                        }
                }
 
-
                // Output the sidebar
                // CologneBlue uses custom messages for some portlets, but we should keep the ids for consistency
                $idToMessage = array(
index 6d66cac..f7fb0d8 100644 (file)
@@ -321,5 +321,3 @@ echo $footerEnd;
 <?php
        }
 } // end of class
-
-
index 09f0910..e35fcd1 100644 (file)
@@ -1,9 +1,12 @@
-// IE fixes javascript
+// IE fixes javascript loaded by wikibits.js for IE <= 6.0
 ( function ( mw, $ ) {
 
 var doneIEAlphaFix, doneIETransform, expandedURLs, fixalpha, isMSIE55,
-       relativeforfloats, setrelative;
+       relativeforfloats, setrelative, hasClass;
 
+// Also returns true for IE6, 7, 8, 9 and 10. createPopup is removed in IE11.
+// Good thing this is only loaded for IE <= 6 by wikibits.
+// Might as well set it to true.
 isMSIE55 = window.isMSIE55 = ( window.showModalDialog && window.clipboardData && window.createPopup );
 doneIETransform = window.doneIETransform = undefined;
 doneIEAlphaFix = window.doneIEAlphaFix = undefined;
@@ -99,8 +102,8 @@ setrelative = window.setrelative = function ( nodes ) {
 };
 
 // Expand links for printing
-String.prototype.hasClass = function ( classWanted ) {
-       var i = 0, classArr = this.split(/\s/);
+hasClass = function ( classText, classWanted ) {
+       var i = 0, classArr = classText.split(/\s/);
        for ( i = 0; i < classArr.length; i++ ) {
                if ( classArr[i].toLowerCase() === classWanted.toLowerCase() ) {
                        return true;
@@ -121,7 +124,7 @@ window.onbeforeprint = function () {
                allLinks = contentEl.getElementsByTagName( 'a' );
 
                for ( i = 0; i < allLinks.length; i++ ) {
-                       if ( allLinks[i].className.hasClass( 'external' ) && !allLinks[i].className.hasClass( 'free' ) ) {
+                       if ( hasClass( allLinks[i].className, 'external' ) && !hasClass( allLinks[i].className, 'free' ) ) {
                                expandedLink = document.createElement( 'span' );
                                expandedText = document.createTextNode( ' (' + allLinks[i].href + ')' );
                                expandedLink.appendChild( expandedText );
index 76ec4af..742f839 100644 (file)
@@ -157,15 +157,12 @@ dd {
        margin-bottom: .1em;
 }
 
+/* IE 6 and 7 lack support for quotes aroud the <q> element ('::before' and '::after'
+   pseudoelements, 'quotes' property). Let's italicize it instead (using the star hack). */
 q {
-       font-family: Times, "Times New Roman", serif;
-       font-style: italic;
-}
-/* Disabled for now
-blockquote {
-       font-family: Times, "Times New Roman", serif;
-       font-style: italic;
-}*/
+       *font-style: italic;
+}
+
 pre, code, tt, kbd, samp, .mw-code {
        /*
         * Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
index 5862877..c7804a0 100644 (file)
@@ -112,6 +112,7 @@ div.top,
 div#column-one,
 #colophon,
 .mw-editsection,
+.mw-editsection-like,
 .toctoggle,
 .tochidden,
 div#f-poweredbyico,
diff --git a/skins/common/images/feed-icon.svg b/skins/common/images/feed-icon.svg
new file mode 100644 (file)
index 0000000..0aa76f5
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="128px" id="RSSicon" viewBox="0 0 256 256">\r
+<defs>\r
+<linearGradient x1="0.085" y1="0.085" x2="0.915" y2="0.915" id="RSSg">\r
+<stop  offset="0.0" stop-color="#E3702D"/><stop  offset="0.1071" stop-color="#EA7D31"/>\r
+<stop  offset="0.3503" stop-color="#F69537"/><stop  offset="0.5" stop-color="#FB9E3A"/>\r
+<stop  offset="0.7016" stop-color="#EA7C31"/><stop  offset="0.8866" stop-color="#DE642B"/>\r
+<stop  offset="1.0" stop-color="#D95B29"/>\r
+</linearGradient>\r
+</defs>\r
+<rect width="256" height="256" rx="55" ry="55" x="0"  y="0"  fill="#CC5D15"/>\r
+<rect width="246" height="246" rx="50" ry="50" x="5"  y="5"  fill="#F49C52"/>\r
+<rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#RSSg)"/>\r
+<circle cx="68" cy="189" r="24" fill="#FFF"/>\r
+<path d="M160 213h-34a82 82 0 0 0 -82 -82v-34a116 116 0 0 1 116 116z" fill="#FFF"/>\r
+<path d="M184 213A140 140 0 0 0 44 73 V 38a175 175 0 0 1 175 175z" fill="#FFF"/>\r
+</svg>\r
index 462fa9c..dc142ca 100644 (file)
@@ -38,15 +38,16 @@ var ProtectionForm = window.ProtectionForm = {
                        check = document.createElement( 'input' );
                        check.id = 'mwProtectUnchained';
                        check.type = 'checkbox';
-                       cell.appendChild( check );
-                       window.addClickHandler( check, function () {
+                       $( check ).click( function () {
                                ProtectionForm.onChainClick();
                        } );
 
-                       cell.appendChild( document.createTextNode( ' ' ) );
                        label = document.createElement( 'label' );
                        label.htmlFor = 'mwProtectUnchained';
                        label.appendChild( document.createTextNode( opts.labelText ) );
+
+                       cell.appendChild( check );
+                       cell.appendChild( document.createTextNode( ' ' ) );
                        cell.appendChild( label );
 
                        check.checked = !this.areAllTypesMatching();
index 7cc58e3..2e61f63 100644 (file)
@@ -485,7 +485,11 @@ a.new {
 /* feed links */
 a.feedlink {
        /* @embed */
-       background: url(images/feed-icon.png) center left no-repeat;
+       background-image: url(images/feed-icon.png);
+       background-image: linear-gradient(transparent, transparent), url(images/feed-icon.svg);
+       background-position: center left;
+       background-repeat: no-repeat;
+       background-size: 12px 12px;
        padding-left: 16px;
 }
 
@@ -535,52 +539,57 @@ table.collapsed tr.collapsable {
 }
 
 /* success and error messages */
+.error,
+.warning,
 .success {
-       color: green;
        font-size: larger;
 }
+.error {
+       color: #cc0000;
+}
 .warning {
-       color: #FFA500; /* orange */
-       font-size: larger;
+       color: #705000;
 }
-.error {
-       color: red;
-       font-size: larger;
+.success {
+       color: #009000;
 }
+
 .errorbox,
 .warningbox,
 .successbox {
-       font-size: larger;
-       border: 2px solid;
+       border: 1px solid;
        padding: .5em 1em;
-       margin-bottom: 2em;
-       color: #000;
+       margin-bottom: 1em;
        display: -moz-inline-block;
        display: inline-block;
        zoom: 1;
        *display: inline;
 }
-.errorbox {
-       border-color: red;
-       background-color: #fff2f2;
-}
-.warningbox {
-       border-color: #FF8C00; /* darkorange */
-       background-color: #FFFFC0;
-}
-.successbox {
-       border-color: green;
-       background-color: #dfd;
-}
 .errorbox h2,
 .warningbox h2,
 .successbox h2 {
        font-size: 1em;
+       color: inherit;
        font-weight: bold;
        display: inline;
        margin: 0 .5em 0 0;
        border: none;
 }
+.errorbox {
+       color: #cc0000;
+       border-color: #fac5c5;
+       background-color: #fae3e3;
+}
+.warningbox {
+       color: #705000;
+       border-color: #fde29b;
+       background-color: #fdf1d1;
+}
+.successbox {
+       color: #009000;
+       border-color: #b7fdb5;
+       background-color: #e1fddf;
+}
 
 /* general info/warning box for SP */
 .mw-infobox {
@@ -1178,7 +1187,8 @@ table.floatleft {
 }
 
 /* Display editsection links smaller and next to headings */
-.mw-editsection {
+.mw-editsection,
+.mw-editsection-like {
        font-size: small;
        font-weight: normal;
        margin-left: 1em;
index 580cf25..d639f63 100644 (file)
@@ -2,7 +2,8 @@
 ( function ( mw, $ ) {
 var    licenseSelectorCheck, wgUploadWarningObj, wgUploadLicenseObj, fillDestFilename,
        ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
-       fileExtensions = mw.config.get( 'wgFileExtensions' );
+       fileExtensions = mw.config.get( 'wgFileExtensions' ),
+       $spinnerDestCheck, $spinnerLicense;
 
 licenseSelectorCheck = window.licenseSelectorCheck = function () {
        var selector = document.getElementById( 'wpLicense' ),
@@ -151,7 +152,7 @@ wgUploadWarningObj = window.wgUploadWarningObj = {
                if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
                        return;
                }
-               window.injectSpinner( document.getElementById( 'wpDestFile' ), 'destcheck' );
+               $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
 
                var uploadWarningObj = this;
                ( new mw.Api() ).get( {
@@ -170,7 +171,8 @@ wgUploadWarningObj = window.wgUploadWarningObj = {
        },
 
        processResult: function ( result, fileName ) {
-               window.removeSpinner( 'destcheck' );
+               $spinnerDestCheck.remove();
+               $spinnerDestCheck = undefined;
                this.setWarning( result.html );
                this.responseCache[fileName] = result.html;
        },
@@ -179,7 +181,7 @@ wgUploadWarningObj = window.wgUploadWarningObj = {
                var warningElt = document.getElementById( 'wpDestFile-warning' ),
                        ackElt = document.getElementsByName( 'wpDestFileWarningAck' );
 
-               this.setInnerHTML(warningElt, warning);
+               this.setInnerHTML( warningElt, warning );
 
                // Set a value in the form indicating that the warning is acknowledged and
                // doesn't need to be redisplayed post-upload
@@ -314,7 +316,8 @@ wgUploadLicenseObj = window.wgUploadLicenseObj = {
                                return;
                        }
                }
-               window.injectSpinner( document.getElementById( 'wpLicense' ), 'license' );
+
+               $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
 
                title = document.getElementById( 'wpDestFile' ).value;
                if ( !title ) {
@@ -333,7 +336,8 @@ wgUploadLicenseObj = window.wgUploadLicenseObj = {
        },
 
        processResult: function ( result, license ) {
-               window.removeSpinner( 'license' );
+               $spinnerLicense.remove();
+               $spinnerLicense = undefined;
                this.responseCache[license] = result.parse.text['*'];
                this.showPreview( this.responseCache[license] );
        },
index 7dc4a95..d28ca0a 100644 (file)
 /**
  * MediaWiki legacy wikibits
  */
-/*jshint quotmark:false, onevar:false */
 ( function ( mw, $ ) {
-       var isIE6, isGecko,
+       var msg,
+               win = window,
                ua = navigator.userAgent.toLowerCase(),
-               uaMsg = 'Use feature detection or module jquery.client instead.';
-
-/**
- * User-agent sniffing.
- * To be removed in MediaWiki 1.23.
- *
- * @deprecated since 1.17 Use jquery.client instead.
- */
-mw.log.deprecate( window, 'clientPC', ua, uaMsg );
-$.each([
-               'is_gecko',
-               'is_chrome_mac',
-               'is_chrome',
-               'webkit_version',
-               'is_safari_win',
-               'is_safari',
-               'webkit_match',
-               'is_ff2',
-               'ff2_bugs',
-               'is_ff2_win',
-               'is_ff2_x11',
-               'opera95_bugs',
-               'opera7_bugs',
-               'opera6_bugs',
-               'is_opera_95',
-               'is_opera_preseven',
-               'is_opera',
-               'ie6_bugs'
-       ],
-       function ( i, key ) {
-               mw.log.deprecate( window, key, false, uaMsg );
-       }
-);
-if ( /msie ([0-9]{1,}[\.0-9]{0,})/.exec( ua ) && parseFloat( RegExp.$1 ) <= 6.0 ) {
-       isIE6 = true;
-}
-isGecko = /gecko/.test( ua ) && !/khtml|spoofer|netscape\/7\.0/.test( ua );
-
-// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
-window.doneOnloadHook = undefined;
-
-if ( !window.onloadFuncts ) {
-       window.onloadFuncts = [];
-}
-
-window.addOnloadHook = function( hookFunct ) {
-       // Allows add-on scripts to add onload functions
-       if( !window.doneOnloadHook ) {
-               window.onloadFuncts[window.onloadFuncts.length] = hookFunct;
-       } else {
-               hookFunct(); // bug in MSIE script loading
-       }
-};
-
-window.importScript = function( page ) {
-       var uri = mw.config.get( 'wgScript' ) + '?title=' +
-               mw.util.wikiUrlencode( page ) +
-               '&action=raw&ctype=text/javascript';
-       return window.importScriptURI( uri );
-};
-
-window.loadedScripts = {}; // included-scripts tracker
-window.importScriptURI = function( url ) {
-       if ( window.loadedScripts[url] ) {
-               return null;
-       }
-       window.loadedScripts[url] = true;
-       var s = document.createElement( 'script' );
-       s.setAttribute( 'src', url );
-       s.setAttribute( 'type', 'text/javascript' );
-       document.getElementsByTagName('head')[0].appendChild( s );
-       return s;
-};
-
-window.importStylesheet = function( page ) {
-       return window.importStylesheetURI( mw.config.get( 'wgScript' ) + '?action=raw&ctype=text/css&title=' + mw.util.wikiUrlencode( page ) );
-};
-
-window.importStylesheetURI = function( url, media ) {
-       var l = document.createElement( 'link' );
-       l.rel = 'stylesheet';
-       l.href = url;
-       if ( media ) {
-               l.media = media;
-       }
-       document.getElementsByTagName('head')[0].appendChild( l );
-       return l;
-};
-
-window.appendCSS = function( text ) {
-       var s = document.createElement( 'style' );
-       s.type = 'text/css';
-       s.rel = 'stylesheet';
-       if ( s.styleSheet ) {
-               s.styleSheet.cssText = text; // IE
-       } else {
-               s.appendChild( document.createTextNode( text + '' ) ); // Safari sometimes borks on null
-       }
-       document.getElementsByTagName('head')[0].appendChild( s );
-       return s;
-};
+               isIE6 = ( /msie ([0-9]{1,}[\.0-9]{0,})/.exec( ua ) && parseFloat( RegExp.$1 ) <= 6.0 ),
+               isGecko = /gecko/.test( ua ) && !/khtml|spoofer|netscape\/7\.0/.test( ua ),
+               onloadFuncts = [];
 
 if ( mw.config.get( 'wgBreakFrames' ) ) {
        // Note: In IE < 9 strict comparison to window is non-standard (the standard didn't exist yet)
        // it works only comparing to window.self or window.window (http://stackoverflow.com/q/4850978/319266)
-       if ( window.top !== window.self ) {
+       if ( win.top !== win.self ) {
                // Un-trap us from framesets
-               window.top.location = window.location;
+               win.top.location = win.location;
        }
 }
 
-window.changeText = function( el, newText ) {
-       // Safari work around
-       if ( el.innerText ) {
-               el.innerText = newText;
-       } else if ( el.firstChild && el.firstChild.nodeValue ) {
-               el.firstChild.nodeValue = newText;
-       }
-};
-
-window.killEvt = function( evt ) {
-       evt = evt || window.event || window.Event; // W3C, IE, Netscape
-       if ( typeof evt.preventDefault !== 'undefined' ) {
-               evt.preventDefault(); // Don't follow the link
-               evt.stopPropagation();
-       } else {
-               evt.cancelBubble = true; // IE
-       }
-       return false; // Don't follow the link (IE)
-};
-
-window.mwEditButtons = [];
-mw.log.deprecate( window, 'mwCustomEditButtons', [], 'Use mw.toolbar.addButton instead.' );
-
-window.escapeQuotes = function( text ) {
-       var re = new RegExp( "'", "g" );
-       text = text.replace( re, "\\'" );
-       re = new RegExp( "\\n", "g" );
-       text = text.replace( re, "\\n" );
-       return window.escapeQuotesHTML( text );
-};
-
-window.escapeQuotesHTML = function( text ) {
-       var re = new RegExp( '&', "g" );
-       text = text.replace( re, "&amp;" );
-       re = new RegExp( '"', "g" );
-       text = text.replace( re, "&quot;" );
-       re = new RegExp( '<', "g" );
-       text = text.replace( re, "&lt;" );
-       re = new RegExp( '>', "g" );
-       text = text.replace( re, "&gt;" );
-       return text;
-};
-
-/**
- * Accesskey prefix utilities.
- * To be removed in MediaWiki 1.23.
- *
- * @deprecated since 1.17 Use mediawiki.util instead.
- */
-mw.log.deprecate( window, 'tooltipAccessKeyPrefix', 'alt-', 'Use mediawiki.util instead.' );
-mw.log.deprecate( window, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, 'Use mediawiki.util instead.' );
-mw.log.deprecate( window, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, 'Use mediawiki.util instead.' );
-
-/**
- * Add a link to one of the portlet menus on the page, including:
- *
- * p-cactions: Content actions (shown as tabs above the main content in Monobook)
- * p-personal: Personal tools (shown at the top right of the page in Monobook)
- * p-navigation: Navigation
- * p-tb: Toolbox
- *
- * This function exists for the convenience of custom JS authors.  All
- * but the first three parameters are optional, though providing at
- * least an id and a tooltip is recommended.
- *
- * By default the new link will be added to the end of the list.  To
- * add the link before a given existing item, pass the DOM node of
- * that item (easily obtained with document.getElementById()) as the
- * nextnode parameter; to add the link _after_ an existing item, pass
- * the node's nextSibling instead.
- *
- * @param portlet String id of the target portlet ("p-cactions", "p-personal", "p-navigation" or "p-tb")
- * @param href String link URL
- * @param text String link text (will be automatically lowercased by CSS for p-cactions in Monobook)
- * @param id String id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
- * @param tooltip String text to show when hovering over the link, without accesskey suffix
- * @param accesskey String accesskey to activate this link (one character, try to avoid conflicts)
- * @param nextnode Node the DOM node before which the new item should be added, should be another item in the same list
- *
- * @return Node -- the DOM node of the new item (an LI element) or null
- */
-window.addPortletLink = function( portlet, href, text, id, tooltip, accesskey, nextnode ) {
-       var root = document.getElementById( portlet );
-       if ( !root ) {
-               return null;
-       }
-       var uls = root.getElementsByTagName( 'ul' );
-       var node;
-       if ( uls.length > 0 ) {
-               node = uls[0];
-       } else {
-               node = document.createElement( 'ul' );
-               var lastElementChild = null;
-               for ( var i = 0; i < root.childNodes.length; ++i ) { /* get root.lastElementChild */
-                       if ( root.childNodes[i].nodeType === 1 ) {
-                               lastElementChild = root.childNodes[i];
-                       }
-               }
-               if ( lastElementChild && lastElementChild.nodeName.match( /div/i ) ) {
-                       /* Insert into the menu divs */
-                       lastElementChild.appendChild( node );
-               } else {
-                       root.appendChild( node );
-               }
-       }
-       if ( !node ) {
-               return null;
-       }
-
-       // unhide portlet if it was hidden before
-       root.className = root.className.replace( /(^| )emptyPortlet( |$)/, "$2" );
-
-       var link = document.createElement( 'a' );
-       link.appendChild( document.createTextNode( text ) );
-       link.href = href;
-
-       // Wrap in a span - make it work with vector tabs and has no effect on any other portlets
-       var span = document.createElement( 'span' );
-       span.appendChild( link );
-
-       var item = document.createElement( 'li' );
-       item.appendChild( span );
-       if ( id ) {
-               item.id = id;
-       }
-
-       if ( accesskey ) {
-               link.setAttribute( 'accesskey', accesskey );
-               tooltip += ' [' + accesskey + ']';
-       }
-       if ( tooltip ) {
-               link.setAttribute( 'title', tooltip );
-       }
-       if ( accesskey && tooltip ) {
-               mw.util.updateTooltipAccessKeys( [link] );
-       }
-
-       if ( nextnode && nextnode.parentNode === node ) {
-               node.insertBefore( item, nextnode );
-       } else {
-               node.appendChild( item );  // IE compatibility (?)
-       }
-
-       return item;
-};
-
-window.getInnerText = function( el ) {
-       if ( typeof el === 'string' ) {
-               return el;
-       }
-       if ( typeof el === 'undefined' ) {
-               return el;
-       }
-       // Custom sort value through 'data-sort-value' attribute
-       // (no need to prepend hidden text to change sort value)
-       if ( el.nodeType && el.getAttribute( 'data-sort-value' ) !== null ) {
-               // Make sure it's a valid DOM element (.nodeType) and that the attribute is set (!null)
-               return el.getAttribute( 'data-sort-value' );
-       }
-       if ( el.textContent ) {
-               return el.textContent; // not needed but it is faster
-       }
-       if ( el.innerText ) {
-               return el.innerText; // IE doesn't have textContent
-       }
-       var str = '';
-
-       var cs = el.childNodes;
-       var l = cs.length;
-       for ( var i = 0; i < l; i++ ) {
-               switch ( cs[i].nodeType ) {
-                       case 1: // ELEMENT_NODE
-                               str += window.getInnerText( cs[i] );
-                               break;
-                       case 3: // TEXT_NODE
-                               str += cs[i].nodeValue;
-                               break;
-               }
-       }
-       return str;
-};
-
-/**
- * Toggle checkboxes with shift selection.
- * To be removed in MediaWiki 1.23.
- *
- * @deprecated since 1.17 Use jquery.checkboxShiftClick instead.
- */
-$.each({
-       checkboxes: [],
-       lastCheckbox: null,
-       setupCheckboxShiftClick: $.noop,
-       addCheckboxClickHandlers: $.noop,
-       checkboxClickHandler: $.noop
-}, function ( key, val ) {
-       mw.log.deprecate( window, key, val, 'Use jquery.checkboxShiftClick instead.' );
-} );
-
-/*
-       Written by Jonathan Snook, http://www.snook.ca/jonathan
-       Add-ons by Robert Nyman, http://www.robertnyman.com
-       Author says "The credit comment is all it takes, no license. Go crazy with it!:-)"
-       From http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
-*/
-window.getElementsByClassName = function( oElm, strTagName, oClassNames ) {
-       var arrReturnElements = [];
-       if ( typeof oElm.getElementsByClassName === 'function' ) {
-               /* Use a native implementation where possible FF3, Saf3.2, Opera 9.5 */
-               var arrNativeReturn = oElm.getElementsByClassName( oClassNames );
-               if ( strTagName === '*' ) {
-                       return arrNativeReturn;
-               }
-               for ( var h = 0; h < arrNativeReturn.length; h++ ) {
-                       if( arrNativeReturn[h].tagName.toLowerCase() === strTagName.toLowerCase() ) {
-                               arrReturnElements[arrReturnElements.length] = arrNativeReturn[h];
-                       }
-               }
-               return arrReturnElements;
-       }
-       var arrElements = ( strTagName === '*' && oElm.all ) ? oElm.all : oElm.getElementsByTagName( strTagName );
-       var arrRegExpClassNames = [];
-       if( typeof oClassNames === 'object' ) {
-               for( var i = 0; i < oClassNames.length; i++ ) {
-                       arrRegExpClassNames[arrRegExpClassNames.length] =
-                               new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)");
-               }
-       } else {
-               arrRegExpClassNames[arrRegExpClassNames.length] =
-                       new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)");
-       }
-       var oElement;
-       var bMatchesAll;
-       for( var j = 0; j < arrElements.length; j++ ) {
-               oElement = arrElements[j];
-               bMatchesAll = true;
-               for( var k = 0; k < arrRegExpClassNames.length; k++ ) {
-                       if( !arrRegExpClassNames[k].test( oElement.className ) ) {
-                               bMatchesAll = false;
-                               break;
-                       }
-               }
-               if( bMatchesAll ) {
-                       arrReturnElements[arrReturnElements.length] = oElement;
-               }
-       }
-       return ( arrReturnElements );
-};
-
-window.redirectToFragment = function( fragment ) {
+win.redirectToFragment = function ( fragment ) {
        var webKitVersion,
-               match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
+               match = navigator.userAgent.match( /AppleWebKit\/(\d+)/ );
        if ( match ) {
                webKitVersion = parseInt( match[1], 10 );
                if ( webKitVersion < 420 ) {
@@ -375,8 +29,8 @@ window.redirectToFragment = function( fragment ) {
                        return;
                }
        }
-       if ( !window.location.hash ) {
-               window.location.hash = fragment;
+       if ( !win.location.hash ) {
+               win.location.hash = fragment;
 
                // Mozilla needs to wait until after load, otherwise the window doesn't
                // scroll.  See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
@@ -386,8 +40,8 @@ window.redirectToFragment = function( fragment ) {
                // well.
                if ( isGecko ) {
                        $( function () {
-                               if ( window.location.hash === fragment ) {
-                                       window.location.hash = fragment;
+                               if ( win.location.hash === fragment ) {
+                                       win.location.hash = fragment;
                                }
                        } );
                }
@@ -395,107 +49,200 @@ window.redirectToFragment = function( fragment ) {
 };
 
 /**
- * Add a cute little box at the top of the screen to inform the user of
- * something, replacing any preexisting message.
+ * User-agent sniffing.
+ * To be removed in MediaWiki 1.23.
  *
- * @deprecated since 1.17 Use the 'mediawiki.notify' module instead.
- * @param {string|HTMLElement} message To be put inside the message box.
+ * @deprecated since 1.17 Use jquery.client instead
  */
-mw.log.deprecate( window, 'jsMsg', mw.util.jsMessage, 'Use mediawiki.notify instead.' );
+
+msg = 'Use feature detection or module jquery.client instead';
+
+mw.log.deprecate( win, 'clientPC', ua, msg );
+
+// Ignored dummy values
+mw.log.deprecate( win, 'is_gecko', false, msg );
+mw.log.deprecate( win, 'is_chrome_mac', false, msg );
+mw.log.deprecate( win, 'is_chrome', false, msg );
+mw.log.deprecate( win, 'webkit_version', false, msg );
+mw.log.deprecate( win, 'is_safari_win', false, msg );
+mw.log.deprecate( win, 'is_safari', false, msg );
+mw.log.deprecate( win, 'webkit_match', false, msg );
+mw.log.deprecate( win, 'is_ff2', false, msg );
+mw.log.deprecate( win, 'ff2_bugs', false, msg );
+mw.log.deprecate( win, 'is_ff2_win', false, msg );
+mw.log.deprecate( win, 'is_ff2_x11', false, msg );
+mw.log.deprecate( win, 'opera95_bugs', false, msg );
+mw.log.deprecate( win, 'opera7_bugs', false, msg );
+mw.log.deprecate( win, 'opera6_bugs', false, msg );
+mw.log.deprecate( win, 'is_opera_95', false, msg );
+mw.log.deprecate( win, 'is_opera_preseven', false, msg );
+mw.log.deprecate( win, 'is_opera', false, msg );
+mw.log.deprecate( win, 'ie6_bugs', false, msg );
 
 /**
- * Inject a cute little progress spinner after the specified element
+ * DOM utilities for handling of events, text nodes and selecting elements
+ *
+ * To be removed in MediaWiki 1.23.
  *
- * @param element Element to inject after
- * @param id Identifier string (for use with removeSpinner(), below)
+ * @deprecated since 1.17 Use jQuery instead
  */
-window.injectSpinner = function( element, id ) {
-       var spinner = document.createElement( 'img' );
-       spinner.id = 'mw-spinner-' + id;
-       spinner.src = mw.config.get( 'stylepath' ) + '/common/images/spinner.gif';
-       spinner.alt = spinner.title = '...';
-       if( element.nextSibling ) {
-               element.parentNode.insertBefore( spinner, element.nextSibling );
+msg = 'Use jQuery instead';
+
+// Ignored dummy values
+mw.log.deprecate( win, 'doneOnloadHook', undefined, msg );
+mw.log.deprecate( win, 'onloadFuncts', [], msg );
+mw.log.deprecate( win, 'runOnloadHook', $.noop, msg );
+mw.log.deprecate( win, 'changeText', $.noop, msg );
+mw.log.deprecate( win, 'killEvt', $.noop, msg );
+mw.log.deprecate( win, 'addHandler', $.noop, msg );
+mw.log.deprecate( win, 'hookEvent', $.noop, msg );
+mw.log.deprecate( win, 'addClickHandler', $.noop, msg );
+mw.log.deprecate( win, 'removeHandler', $.noop, msg );
+mw.log.deprecate( win, 'getElementsByClassName', function () { return []; }, msg );
+mw.log.deprecate( win, 'getInnerText', function () { return ''; }, msg );
+
+// Run a function after the window onload event is fired
+mw.log.deprecate( win, 'addOnloadHook', function ( hookFunct ) {
+       if ( onloadFuncts ) {
+               onloadFuncts.push(hookFunct);
        } else {
-               element.parentNode.appendChild( spinner );
+               // If func queue is gone the event has happened already,
+               // run immediately instead of queueing.
+               hookFunct();
        }
-};
+}, msg );
 
-/**
- * Remove a progress spinner added with injectSpinner()
- *
- * @param id Identifier string
- */
-window.removeSpinner = function( id ) {
-       var spinner = document.getElementById( 'mw-spinner-' + id );
-       if( spinner ) {
-               spinner.parentNode.removeChild( spinner );
-       }
-};
+$( win ).on( 'load', function () {
+       var i, functs;
 
-window.runOnloadHook = function() {
-       // don't run anything below this for non-dom browsers
-       if ( window.doneOnloadHook || !( document.getElementById && document.getElementsByTagName ) ) {
+       // Don't run twice
+       if ( !onloadFuncts ) {
                return;
        }
 
-       // set this before running any hooks, since any errors below
-       // might cause the function to terminate prematurely
-       window.doneOnloadHook = true;
+       // Deference and clear onloadFuncts before running any
+       // hooks to make sure we don't miss any addOnloadHook
+       // calls.
+       functs = onloadFuncts.slice();
+       onloadFuncts = undefined;
 
-       // Run any added-on functions
-       for ( var i = 0; i < window.onloadFuncts.length; i++ ) {
-               window.onloadFuncts[i]();
+       // Execute the queued functions
+       for ( i = 0; i < functs.length; i++ ) {
+               functs[i]();
        }
-};
+} );
 
 /**
- * Add an event handler to an element
+ * Toggle checkboxes with shift selection
  *
- * @param element Element to add handler to
- * @param attach String Event to attach to
- * @param handler callable Event handler callback
+ * To be removed in MediaWiki 1.23.
+ *
+ * @deprecated since 1.17 Use jquery.checkboxShiftClick instead
  */
-window.addHandler = function( element, attach, handler ) {
-       if( element.addEventListener ) {
-               element.addEventListener( attach, handler, false );
-       } else if( element.attachEvent ) {
-               element.attachEvent( 'on' + attach, handler );
-       }
-};
+msg = 'Use jquery.checkboxShiftClick instead';
+mw.log.deprecate( win, 'checkboxes', [], msg );
+mw.log.deprecate( win, 'lastCheckbox', null, msg );
+mw.log.deprecate( win, 'setupCheckboxShiftClick', $.noop, msg );
+mw.log.deprecate( win, 'addCheckboxClickHandlers', $.noop, msg );
+mw.log.deprecate( win, 'checkboxClickHandler', $.noop, msg );
 
-window.hookEvent = function( hookName, hookFunct ) {
-       window.addHandler( window, hookName, hookFunct );
-};
+/**
+ * Add a button to the default editor toolbar
+ *
+ * To be removed in MediaWiki 1.23.
+ *
+ * @deprecated since 1.17 Use mw.toolbar instead
+ */
+mw.log.deprecate( win, 'mwEditButtons', [], 'Use mw.toolbar instead' );
+mw.log.deprecate( win, 'mwCustomEditButtons', [], 'Use mw.toolbar instead' );
 
 /**
- * Add a click event handler to an element
+ * Spinner creation, injection and removal
+ *
+ * To be removed in MediaWiki 1.23.
  *
- * @param element Element to add handler to
- * @param handler callable Event handler callback
+ * @deprecated since 1.18 Use jquery.spinner instead
  */
-window.addClickHandler = function( element, handler ) {
-       window.addHandler( element, 'click', handler );
-};
+mw.log.deprecate( win, 'injectSpinner', $.noop, 'Use jquery.spinner instead' );
+mw.log.deprecate( win, 'removeSpinner', $.noop, 'Use jquery.spinner instead' );
 
 /**
- * Removes an event handler from an element
+ * Escape utilities
+ *
+ * To be removed in MediaWiki 1.23.
  *
- * @param element Element to remove handler from
- * @param remove String Event to remove
- * @param handler callable Event handler callback to remove
+ * @deprecated since 1.18 Use mw.html instead
  */
-window.removeHandler = function( element, remove, handler ) {
-       if( window.removeEventListener ) {
-               element.removeEventListener( remove, handler, false );
-       } else if( window.detachEvent ) {
-               element.detachEvent( 'on' + remove, handler );
+mw.log.deprecate( win, 'escapeQuotes', $.noop,'Use mw.html instead' );
+mw.log.deprecate( win, 'escapeQuotesHTML', $.noop,'Use mw.html instead' );
+
+/**
+ * Display a message to the user
+ *
+ * To be removed in MediaWiki 1.23.
+ *
+ * @deprecated since 1.17 Use mediawiki.notify instead
+ * @param {string|HTMLElement} message To be put inside the message box
+ */
+mw.log.deprecate( win, 'jsMsg', mw.util.jsMessage, 'Use mediawiki.notify instead' );
+
+/**
+ * Misc. utilities
+ *
+ * To be removed in MediaWiki 1.23.
+ *
+ * @deprecated since 1.17 Use mediawiki.util instead
+ */
+msg = 'Use mediawiki.util instead';
+mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
+mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
+mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
+mw.log.deprecate( win, 'addPortletLink', mw.util.addPortletLink, msg );
+mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
+
+/**
+ * Wikipage import methods
+ */
+
+// included-scripts tracker
+win.loadedScripts = {};
+
+win.importScript = function ( page ) {
+       var uri = mw.config.get( 'wgScript' ) + '?title=' +
+               mw.util.wikiUrlencode( page ) +
+               '&action=raw&ctype=text/javascript';
+       return win.importScriptURI( uri );
+};
+
+win.importScriptURI = function ( url ) {
+       if ( win.loadedScripts[url] ) {
+               return null;
        }
+       win.loadedScripts[url] = true;
+       var s = document.createElement( 'script' );
+       s.setAttribute( 'src', url );
+       s.setAttribute( 'type', 'text/javascript' );
+       document.getElementsByTagName( 'head' )[0].appendChild( s );
+       return s;
+};
+
+win.importStylesheet = function( page ) {
+       return win.importStylesheetURI( mw.config.get( 'wgScript' ) + '?action=raw&ctype=text/css&title=' + mw.util.wikiUrlencode( page ) );
+};
+
+win.importStylesheetURI = function( url, media ) {
+       var l = document.createElement( 'link' );
+       l.rel = 'stylesheet';
+       l.href = url;
+       if ( media ) {
+               l.media = media;
+       }
+       document.getElementsByTagName('head')[0].appendChild( l );
+       return l;
 };
-window.hookEvent( 'load', window.runOnloadHook );
 
 if ( isIE6 ) {
-       window.importScriptURI( mw.config.get( 'stylepath' ) + '/common/IEFixes.js' );
+       win.importScriptURI( mw.config.get( 'stylepath' ) + '/common/IEFixes.js' );
 }
 
 }( mediaWiki, jQuery ) );
index e97bbdb..150d2d2 100644 (file)
@@ -4,6 +4,7 @@
 #jump-to-nav,
 #footer,
 .mw-editsection,
+.mw-editsection-like,
 .noprint {
        display: none;
 }
index 3462795..08e662d 100644 (file)
@@ -1,10 +1,10 @@
 @html-font-size: 90%;
 
 @body-font-size: inherit;
-@body-font-color: inherit;
 
 // Page content
 @content-font-family: "Helvetica Neue", "Helvetica", "Nimbus Sans L", "Arial", "Liberation Sans", sans-serif;
+@content-font-color: #252525;
 @content-font-size: 0.9em;
 @content-line-height: inherit;
 @content-padding: 1em;
index 67313c9..45258e5 100644 (file)
@@ -7,17 +7,28 @@
 
        // Use the same function for all navigation headings - don't repeat
        function toggle( $element ) {
+               var isCollapsed = $element.parent().is( '.collapsed' );
+
                $.cookie(
                        'vector-nav-' + $element.parent().attr( 'id' ),
-                       $element.parent().is( '.collapsed' ),
+                       isCollapsed,
                        { 'expires': 30, 'path': '/' }
                );
+
                $element
                        .parent()
                        .toggleClass( 'expanded' )
                        .toggleClass( 'collapsed' )
                        .find( '.body' )
                        .slideToggle( 'fast' );
+               isCollapsed = !isCollapsed;
+
+               $element
+                       .find( '> a' )
+                       .attr( {
+                               'aria-pressed': isCollapsed ? 'false' : 'true',
+                               'aria-expanded': isCollapsed ? 'false' : 'true'
+                       } );
        }
 
        /* Browser Support */
                        .each( function ( i ) {
                                var id = $(this).attr( 'id' ),
                                        state = $.cookie( 'vector-nav-' + id );
+                               $(this).find( 'ul:first' ).attr( 'id', id + '-list' );
                                // Add anchor tag to heading for better accessibility
-                               $( this ).find( 'h3' ).wrapInner( $( '<a href="#"></a>' ).click( false ) );
+                               $( this ).find( 'h3' ).wrapInner(
+                                       $( '<a>' )
+                                               .attr( {
+                                                       href: '#',
+                                                       'aria-haspopup': 'true',
+                                                       'aria-controls': id + '-list',
+                                                       role: 'button'
+                                               } )
+                                               .click( false )
+                               );
                                // In the case that we are not showing the new version, let's show the languages by default
                                if (
                                        state === 'true' ||
                                                .find( '.body' )
                                                .hide() // bug 34450
                                                .show();
+                                       $(this).find( 'h3 > a' )
+                                               .attr( {
+                                                       'aria-pressed': 'true',
+                                                       'aria-expanded': 'true'
+                                               } );
                                } else {
                                        $(this)
                                                .addClass( 'collapsed' )
                                                .removeClass( 'expanded' );
+                                       $(this).find( 'h3 > a' )
+                                               .attr( {
+                                                       'aria-pressed': 'false',
+                                                       'aria-expanded': 'false'
+                                               } );
                                }
                                // Re-save cookie
                                if ( state !== null ) {
index e3c2c51..83d043e 100644 (file)
@@ -82,7 +82,7 @@
                },
                addData: function ( $collapsible ) {
                        var $settings = $collapsible.parent().data( 'collapsibleTabsSettings' );
-                       if ( $settings !== null ) {
+                       if ( $settings ) {
                                $collapsible.data( 'collapsibleTabsSettings', {
                                        expandedContainer: $settings.expandedContainer,
                                        collapsedContainer: $settings.collapsedContainer,
@@ -93,7 +93,7 @@
                },
                getSettings: function ( $collapsible ) {
                        var $settings = $collapsible.data( 'collapsibleTabsSettings' );
-                       if ( $settings === undefined ) {
+                       if ( !$settings ) {
                                $.collapsibleTabs.addData( $collapsible );
                                $settings = $collapsible.data( 'collapsibleTabsSettings' );
                        }
                        } );
                },
                moveToCollapsed: function ( ele ) {
-                       var data, expContainerSettings, target,
+                       var outerData, expContainerSettings, target,
                                $moving = $( ele );
 
-                       data = $.collapsibleTabs.getSettings( $moving );
-                       if ( !data ) {
+                       outerData = $.collapsibleTabs.getSettings( $moving );
+                       if ( !outerData ) {
                                return;
                        }
-                       expContainerSettings = $.collapsibleTabs.getSettings( $( data.expandedContainer ) );
+                       expContainerSettings = $.collapsibleTabs.getSettings( $( outerData.expandedContainer ) );
                        if ( !expContainerSettings ) {
                                return;
                        }
                        expContainerSettings.shifting = true;
 
                        // Remove the element from where it's at and put it in the dropdown menu
-                       target = data.collapsedContainer;
+                       target = outerData.collapsedContainer;
                        $moving.css( 'position', 'relative' )
                                .css( ( rtl ? 'left' : 'right' ), 0 )
                                .animate( { width: '1px' }, 'normal', function () {
                                        $( this ).hide();
                                        // add the placeholder
                                        $( '<span class="placeholder" style="display: none;"></span>' ).insertAfter( this );
-                                       // XXX: 'data' is undefined here, should the 'data' from the outer scope have
-                                       // a different name?
-                                       $( this ).detach().prependTo( target ).data( 'collapsibleTabsSettings', data );
+                                       $( this ).detach().prependTo( target ).data( 'collapsibleTabsSettings', outerData );
                                        $( this ).attr( 'style', 'display: list-item;' );
                                        data = $.collapsibleTabs.getSettings( $( ele ) );
                                        if ( data ) {
diff --git a/skins/vector/images/preferences-break.png b/skins/vector/images/preferences-break.png
deleted file mode 100644 (file)
index b529308..0000000
Binary files a/skins/vector/images/preferences-break.png and /dev/null differ
diff --git a/skins/vector/images/preferences-fade.png b/skins/vector/images/preferences-fade.png
deleted file mode 100644 (file)
index 638084d..0000000
Binary files a/skins/vector/images/preferences-fade.png and /dev/null differ
diff --git a/skins/vector/images/preferences/break.png b/skins/vector/images/preferences/break.png
new file mode 100644 (file)
index 0000000..b529308
Binary files /dev/null and b/skins/vector/images/preferences/break.png differ
diff --git a/skins/vector/images/preferences/fade.png b/skins/vector/images/preferences/fade.png
new file mode 100644 (file)
index 0000000..638084d
Binary files /dev/null and b/skins/vector/images/preferences/fade.png differ
index f5cf5e5..4651b48 100644 (file)
@@ -37,7 +37,7 @@ div#content {
        /* Merge the border with tabs' one (in their background image) */
        margin-top: -1px;
        background-color: white;
-       color: @body-font-color;
+       color: @content-font-color;
        direction: ltr;
 }
 /* Hide, but keep accessible for screen-readers */
@@ -183,7 +183,7 @@ div.vectorTabs li.icon a {
        background-repeat: no-repeat;
 }
 /* OVERRIDDEN BY COMPLIANT BROWSERS */
-div.vectorTabs span a  {
+div.vectorTabs span a {
        display: inline-block;
        padding-top: 1.25em;
 }
@@ -378,6 +378,9 @@ div#simpleSearch {
 div#simpleSearch input:focus {
        outline: none;
 }
+div#simpleSearch input {
+       color: black;
+}
 div#simpleSearch input.placeholder {
        color: #999;
 }
@@ -407,7 +410,6 @@ div#simpleSearch input#searchInput {
         * this from ever being shown anyways.
        */
        font-size: 13px;
-       color: black;
        background-color: transparent;
        direction: ltr;
 }
@@ -547,104 +549,6 @@ div#footer #footer-places li {
        text-decoration: none;
 }
 
-/*
- *
- * The following code is highly modified from monobook. It would be nice if the
- * preftoc id was more human readable like preferences-toc for instance,
- * howerver this would require backporting the other skins.
- */
-
-/* Preferences */
-#preftoc {
-       /* Tabs */
-       width: 100%;
-       float: left;
-       clear: both;
-       margin: 0 !important;
-       padding: 0 !important;
-       .background-image('images/preferences-break.png');
-       background-position: bottom left;
-       background-repeat: no-repeat;
-}
-       #preftoc li {
-               /* Tab */
-               float: left;
-               margin: 0;
-               padding: 0;
-               padding-right: 1px;
-               height: 2.25em;
-               white-space: nowrap;
-               list-style-type: none;
-               list-style-image: none;
-               .background-image('images/preferences-break.png');
-               background-position: bottom right;
-               background-repeat: no-repeat;
-       }
-       /* Sadly, IE6 won't understand this */
-       #preftoc li:first-child {
-               margin-left: 1px;
-       }
-       #preftoc a,
-       #preftoc a:active {
-               display: inline-block;
-               position: relative;
-               color: @menu-link-color;
-               padding: 0.5em;
-               text-decoration: none;
-               background-image: none;
-               font-size: 0.9em;
-       }
-       #preftoc a:hover,
-       #preftoc a:focus {
-               text-decoration: underline;
-       }
-       #preftoc li.selected a {
-               .background-image('images/preferences-fade.png');
-               background-position: bottom;
-               background-repeat: repeat-x;
-               color: #333;
-               text-decoration: none;
-       }
-#preferences {
-       float: left;
-       width: 100%;
-       margin: 0;
-       margin-top: -2px;
-       clear: both;
-       border: solid 1px #ccc;
-       background-color: #fafafa;
-}
-#preferences fieldset {
-       border: none;
-       border-top: solid 1px #ccc;
-}
-#preferences fieldset.prefsection {
-       border: none;
-       padding: 0;
-       margin: 1em;
-}
-#preferences legend {
-       color: #666;
-}
-#preferences fieldset.prefsection legend.mainLegend {
-       display: none;
-}
-#preferences td {
-       padding-left: 0.5em;
-       padding-right: 0.5em;
-}
-.htmlform-tip {
-       font-size: x-small;
-       padding: .2em 2em;
-       color: #666;
-}
-#preferences div.mw-prefs-buttons {
-       padding: 1em;
-}
-#preferences div.mw-prefs-buttons input {
-       margin-right: 0.25em;
-}
-
 ul {
        list-style-type: disc;
        .list-style-image('images/bullet-icon.png');
diff --git a/skins/vector/special.preferences.less b/skins/vector/special.preferences.less
new file mode 100644 (file)
index 0000000..a9b1006
--- /dev/null
@@ -0,0 +1,114 @@
+@import "mediawiki.mixins";
+@import "variables";
+
+/**
+ * The following code is highly modified from monobook. It would be nice if the
+ * preftoc id was more human readable like preferences-toc for instance,
+ * howerver this would require backporting the other skins.
+ */
+
+#preftoc {
+       /* Tabs */
+       width: 100%;
+       float: left;
+       clear: both;
+       margin: 0 !important;
+       padding: 0 !important;
+       .background-image('images/preferences/break.png');
+       background-position: bottom left;
+       background-repeat: no-repeat;
+
+       li {
+               /* Tab */
+               float: left;
+               margin: 0;
+               padding: 0;
+               padding-right: 1px;
+               height: 2.25em;
+               white-space: nowrap;
+               list-style-type: none;
+               list-style-image: none;
+               .background-image('images/preferences/break.png');
+               background-position: bottom right;
+               background-repeat: no-repeat;
+
+               /* Sadly, IE6 won't understand this */
+               &:first-child {
+                       margin-left: 1px;
+               }
+
+               &.selected {
+                       a {
+                               .background-image('images/preferences/fade.png');
+                               background-position: bottom;
+                               background-repeat: repeat-x;
+                               color: #333;
+                               text-decoration: none;
+                       }
+               }
+       }
+
+       a,
+       a:active {
+               display: inline-block;
+               position: relative;
+               color: @menu-link-color;
+               padding: 0.5em;
+               text-decoration: none;
+               background-image: none;
+               font-size: 0.9em;
+       }
+
+       a:hover,
+       a:focus {
+               text-decoration: underline;
+       }
+}
+
+#preferences {
+       float: left;
+       width: 100%;
+       margin: 0;
+       margin-top: -2px;
+       clear: both;
+       border: solid 1px #ccc;
+       background-color: #fafafa;
+
+       fieldset {
+               border: none;
+               border-top: solid 1px #ccc;
+
+               &.prefsection {
+                       border: none;
+                       padding: 0;
+                       margin: 1em;
+
+                       legend.mainLegend {
+                               display: none;
+                       }
+               }
+       }
+
+       legend {
+               color: #666;
+       }
+
+       td {
+               padding-left: 0.5em;
+               padding-right: 0.5em;
+       }
+
+       div.mw-prefs-buttons {
+               padding: 1em;
+
+               input {
+                       margin-right: 0.25em;
+               }
+       }
+}
+
+.htmlform-tip {
+       font-size: x-small;
+       padding: .2em 2em;
+       color: #666;
+}
index 62e3d55..a76b639 100644 (file)
@@ -1,9 +1,13 @@
 @import "variables.less";
 @import "beta/variables.less";
-@import "screen.less";
-@import "beta/screen.less";
-@import "externalLinks.less";
-@import "collapsibleNav.less";
+
+@media screen {
+       @import "screen.less";
+       @import "beta/screen.less";
+       @import "externalLinks.less";
+       @import "collapsibleNav.less";
+}
+
 @media screen and (min-width: 982px) {
        @import "screen-hd.less";
 }
index a5db63c..bd45851 100644 (file)
@@ -1,7 +1,10 @@
 @import "variables.less";
-@import "screen.less";
-@import "externalLinks.less";
-@import "collapsibleNav.less";
+
+@media screen {
+       @import "screen.less";
+       @import "externalLinks.less";
+       @import "collapsibleNav.less";
+}
 
 @media screen and (min-width: 982px) {
        @import "screen-hd.less";
index fac7f82..691e0fd 100644 (file)
@@ -1,10 +1,10 @@
 @html-font-size: 1em;
 
 @body-font-size: 1em;
-@body-font-color: #252525;
 
 // Page content
 @content-font-family: sans-serif;
+@content-font-color: black;
 @content-font-size: 0.8em;
 @content-line-height: 1.5em;
 @content-padding: 1.5em 1.5em 1.5em 1.75em;
index cd9a93e..46a894c 100644 (file)
@@ -55,10 +55,10 @@ $wgAutoloadClasses += array(
        # tests/phpunit/includes/api
        'ApiFormatTestBase' => "$testDir/phpunit/includes/api/format/ApiFormatTestBase.php",
        'ApiTestCase' => "$testDir/phpunit/includes/api/ApiTestCase.php",
-       'ApiTestContext' => "$testDir/phpunit/includes/api/ApiTestCase.php",
-       'MockApi' => "$testDir/phpunit/includes/api/ApiTestCase.php",
+       'ApiTestContext' => "$testDir/phpunit/includes/api/ApiTestContext.php",
+       'MockApi' => "$testDir/phpunit/includes/api/MockApi.php",
+       'UserWrapper' => "$testDir/phpunit/includes/api/UserWrapper.php",
        'RandomImageGenerator' => "$testDir/phpunit/includes/api/RandomImageGenerator.php",
-       'UserWrapper' => "$testDir/phpunit/includes/api/ApiTestCase.php",
 
        # tests/phpunit/includes/content
        'DummyContentHandlerForTesting' => "$testDir/phpunit/includes/content/ContentHandlerTest.php",
@@ -78,6 +78,9 @@ $wgAutoloadClasses += array(
        # tests/phpunit/includes/libs
        'GenericArrayObjectTest' => "$testDir/phpunit/includes/libs/GenericArrayObjectTest.php",
 
+       # tests/phpunit/media
+       'FakeDimensionFile' => "$testDir/phpunit/includes/media/FakeDimensionFile.php",
+
        # tests/phpunit/includes/site
        'SiteTest' => "$testDir/phpunit/includes/site/SiteTest.php",
        'TestSites' => "$testDir/phpunit/includes/site/TestSites.php",
@@ -86,8 +89,8 @@ $wgAutoloadClasses += array(
        'MockFSFile' => "$testDir/phpunit/mocks/filebackend/MockFSFile.php",
        'MockFileBackend' => "$testDir/phpunit/mocks/filebackend/MockFileBackend.php",
        'MockBitmapHandler' => "$testDir/phpunit/mocks/media/MockBitmapHandler.php",
-       'MockImageHandler' => "$testDir/phpunit/mocks/media/MockBitmapHandler.php",
-       'MockSvgHandler' => "$testDir/phpunit/mocks/media/MockBitmapHandler.php",
+       'MockImageHandler' => "$testDir/phpunit/mocks/media/MockImageHandler.php",
+       'MockSvgHandler' => "$testDir/phpunit/mocks/media/MockSvgHandler.php",
 
        # tests/phpunit/languages
        'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
index 5036a51..58ea1ed 100644 (file)
@@ -494,6 +494,9 @@ class ParserTest {
 
        /**
         * Get a Parser object
+        *
+        * @param string $preprocessor
+        * @return Parser
         */
        function getParser( $preprocessor = null ) {
                global $wgParserConf;
@@ -566,6 +569,7 @@ class ParserTest {
                        $out = $parser->getPreloadText( $input, $title, $options );
                } else {
                        $output = $parser->parse( $input, $title, $options, true, true, 1337 );
+                       $output->setTOCEnabled( !isset( $opts['notoc'] ) );
                        $out = $output->getText();
 
                        if ( isset( $opts['showtitle'] ) ) {
@@ -618,7 +622,7 @@ class ParserTest {
        /**
         * Use a regex to find out the value of an option
         * @param $key String: name of option val to retrieve
-        * @param $opts Options array to look in
+        * @param $opts array: Options array to look in
         * @param $default Mixed: default value returned if not found
         */
        private static function getOptionValue( $key, $opts, $default ) {
index 3882185..cc935da 100644 (file)
@@ -26,6 +26,7 @@
 # showtitle     make the first line the title
 # comment       run through Linker::formatComment() instead of main parser
 # local         format section links in edit comment text as local links
+# notoc         disable table of contents
 #
 # You can also set the following parser properties via test options:
 #  wgEnableUploads, wgAllowExternalImages, wgMaxTocLevel,
@@ -1418,11 +1419,21 @@ Bug 52763: Preformatted in <blockquote>
 !! input
 <blockquote>
  Blah
+{|
+|
+ indented cell (no pre-wrapping!)
+|}
 </blockquote>
 !! result
 <blockquote>
 <p> Blah
 </p>
+<table>
+<tr>
+<td>
+<p> indented cell (no pre-wrapping!)
+</p>
+</td></tr></table>
 </blockquote>
 
 !! end
@@ -1892,7 +1903,7 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 !! end
 
 !! test
-Templates: Dont escape already nowiki-escaped text in template parameters
+Templates: Don't escape already nowiki-escaped text in template parameters
 !! options
 parsoid=html2wt,wt2wt
 !! input
@@ -2171,9 +2182,9 @@ parsoid=wt2html,wt2wt
  [[Category:foo]] <!-- No pre-wrapping -->
 {{echo| [[Category:foo]]}} <!-- No pre-wrapping -->
 !! result
- <link rel="mw:WikiLink/Category" href="./Category:Foo"> <!-- No pre-wrapping -->
+ <link rel="mw:PageProp/Category" href="./Category:Foo"> <!-- No pre-wrapping -->
 <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":" [[Category:foo]]"}},"i":0}}]}'> </span>
-<link rel="mw:WikiLink/Category" href="./Category:Foo" about="#mwt1"> <!-- No pre-wrapping -->
+<link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1"> <!-- No pre-wrapping -->
 !! end
 
 !! test
@@ -2185,9 +2196,9 @@ parsoid=wt2html,wt2wt
  [[Category:foo]] {{echo|b}}
 !! result
 <pre>
-<link rel="mw:WikiLink/Category" href="./Category:Foo"> a
+<link rel="mw:PageProp/Category" href="./Category:Foo"> a
 
-<link rel="mw:WikiLink/Category" href="./Category:Foo"> <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b"}},"i":0}}]}'>b</span></pre>
+<link rel="mw:PageProp/Category" href="./Category:Foo"> <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b"}},"i":0}}]}'>b</span></pre>
 !! end
 
 ###
@@ -3639,6 +3650,8 @@ External links: link text with spaces
 
 !! test
 External links: wiki links within external link (Bug 3695)
+!! options
+php
 !! input
 [http://example.com [[wikilink]] embedded in ext link]
 !! result
@@ -3646,6 +3659,16 @@ External links: wiki links within external link (Bug 3695)
 </p>
 !! end
 
+!! test
+Parsoid: External links: wiki links within external link (Bug 3695)
+!! options
+parsoid
+!! input
+[http://example.com [[wikilink]] embedded in ext link]
+!! result
+<p><a rel="mw:ExtLink" href="http://example.com"></a><a rel="mw:WikiLink" href="./Wikilink">wikilink</a><span> embedded in ext link</span></p>
+!! end
+
 !! test
 BUG 787: Links with one slash after the url protocol are invalid
 !! input
@@ -3790,6 +3813,8 @@ External link containing double-single-quotes in text embedded in italics (bug 4
 
 !! test
 External link containing double-single-quotes with no space separating the url from text in italics
+!! options
+php
 !! input
 [http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].]
 !! result
@@ -3797,6 +3822,16 @@ External link containing double-single-quotes with no space separating the url f
 </p>
 !! end
 
+!! test
+Parsoid:External link containing double-single-quotes with no space separating the url from text in italics
+!! options
+parsoid
+!! input
+[http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm''La muerte de Casagemas'' (1901) en el sitio de [[Museo Picasso (París)|Museo Picasso]].]
+!! result
+<p><a rel="mw:ExtLink" href="http://www.musee-picasso.fr/pages/page_id18528_u1l2.htm"><i>La muerte de Casagemas</i> (1901) en el sitio de </a><a rel="mw:WikiLink" href="./Museo_Picasso_(París)">Museo Picasso</a><span>.</span></p>
+!! end
+
 !! test
 External link with comments in link text
 !! input
@@ -4898,6 +4933,19 @@ Namespace takes precedence over interwiki link (bug 51680)
 </p>
 !! end
 
+# The previous test doesn't work correctly in html2*, due to not recognizing the
+# link as an internal one. This one checks for the correct behavior.
+!! test
+Link to namespace preferred over interwiki with correct rel attribute
+!! options
+parsoid=html2wt,html2html
+!! input
+[[MemoryAlpha:AlphaTest]]
+!! result
+<p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
+</p>
+!! end
+
 !! test
 Piped link to namespace
 !! input
@@ -5331,6 +5379,16 @@ Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
 </p>
 !! end
 
+!! test
+Parsoid: Scoped parsing should handle mixed transclusions and plain text
+!! options
+parsoid
+!! input
+[[Foo|{{echo|a}} b {{echo|c}}]]
+!! result
+<p data-parsoid='{"dsr":[0,20,0,0]}'><a rel="mw:WikiLink" href="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
+!! end
+
 ###
 ### Interwiki links (see maintenance/interwiki.sql)
 ###
@@ -5377,6 +5435,22 @@ Interwiki link with fragment (bug 2130)
 </p>
 !! end
 
+# Ideally the wikipedia: prefix here should be proto-relative too
+!! test
+Different interwiki prefixes mapping to the same URL
+!! options
+parsoid
+!! input
+[[wikipedia:Foo]]
+
+[[:en:Foo]]
+!! result
+<p data-parsoid='{"dsr":[0,17,0,0]}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"dsr":[0,17,null,1]}'>wikipedia:Foo</a></p>
+
+
+<p data-parsoid='{"dsr":[19,30,0,0]}'><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true,"dsr":[19,30,null,1]}'>en:Foo</a></p>
+!! end
+
 
 ###
 ### Interlanguage links
@@ -5476,7 +5550,7 @@ parsoid
 [[ko:]]
 !! result
 <p>
-<link rel="mw:WikiLink/Language" href="http://ko.wikipedia.org/wiki/"></p>
+<link rel="mw:PageProp/Language" href="http://ko.wikipedia.org/wiki/"></p>
 !! end
 
 !! test
@@ -5486,7 +5560,7 @@ parsoid
 !! input
 [[:ko:]]
 !! result
-<p><a rel="mw:WikiLink/Interwiki" href="http://ko.wikipedia.org/wiki/">ko:</a></p>
+<p><a rel="mw:ExtLink" href="//ko.wikipedia.org/wiki/">ko:</a></p>
 !! end
 
 ###
@@ -5549,7 +5623,7 @@ parsoid=wt2html
 !! input
 #REDIRECT [[Category:Foo]]
 !! result
-<link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:WikiLink/Category" href="./Category:Foo">
+<link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:PageProp/Category" href="./Category:Foo">
 !! end
 
 !! test
@@ -5559,7 +5633,7 @@ parsoid=wt2html
 !! input
 #REDIRECT [[Category%3AFoo]]
 !! result
-<link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:WikiLink/Category" href="./Category:Foo">
+<link rel="mw:PageProp/redirect" href="./Category:Foo"><link rel="mw:PageProp/Category" href="./Category:Foo">
 !! end
 
 !! test
@@ -8277,9 +8351,9 @@ parsoid=wt2html,wt2wt
 <!--Two categories (Bug 50330)-->
 <table>[[Category:bar1]][[Category:bar2]]<tr><td>foo</td></tr></table>
 !!result
-<link rel="mw:WikiLink/Category" href="./Category:Foo1"><table><tbody><tr><td>foo</td></tr></tbody></table>
+<link rel="mw:PageProp/Category" href="./Category:Foo1"><table><tbody><tr><td>foo</td></tr></tbody></table>
 <!--Two categories (Bug 50330)-->
-<link rel="mw:WikiLink/Category" href="./Category:Bar1"><link rel="mw:WikiLink/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
+<link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
 !!end
 
 !!test
@@ -10133,6 +10207,30 @@ parsoid
 #</span>
 #</p>
 
+!! test
+Caption with a template in it
+!! options
+parsoid
+!! input
+[[Image:Foobar.jpg|thumb|200px|This caption has a {{echo|transclusion}} in it.]]
+!! result
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
+!! end
+
+!! test
+Caption with unbalanced tags in it
+!! options
+parsoid
+!! input
+foo
+[[Image:Foobar.jpg|thumb|200px|This caption has a <center>unbalanced tag in it.]]
+bar
+!! result
+<p>foo</p>
+<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
+<p>bar</p>
+!! end
+
 
 ###
 ### Subpages
@@ -10403,7 +10501,7 @@ language=is
 !! input
 x[[Category:Foo]]y
 !! result
-<p>x<link rel="mw:WikiLink/Category" href="Category:Foo">y</p>
+<p>x<link rel="mw:PageProp/Category" href="Category:Foo">y</p>
 !! end
 
 !! test
@@ -10429,8 +10527,8 @@ parsoid
 [[Category:Foo]]
 [[Category:Foo|Bar]]
 !! result
-<link rel="mw:WikiLink/Category" href="Category:Foo">
-<link rel="mw:WikiLink/Category" href="Category:Foo#Bar">
+<link rel="mw:PageProp/Category" href="Category:Foo">
+<link rel="mw:PageProp/Category" href="Category:Foo#Bar">
 !! end
 
 ###
@@ -10520,6 +10618,7 @@ Some text
 </li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Headline_1">Headline 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="Subheadline_1">Subheadline 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Subheadline 1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h5><span class="mw-headline" id="Skipping_a_level">Skipping a level</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Skipping a level">edit</a><span class="mw-editsection-bracket">]</span></span></h5>
@@ -10575,6 +10674,7 @@ Handling of sections up to level 6 and beyond
 </li>
 </ul>
 </div>
+
 <h1><span class="mw-headline" id="Level_1_Heading">Level 1 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Level 1 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
 <h2><span class="mw-headline" id="Level_2_Heading">Level 2 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Level 2 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="Level_3_Heading">Level 3 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Level 3 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
@@ -10617,6 +10717,7 @@ TOC regression (bug 9764)
 </li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="title_1">title 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: title 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="title_1.1">title 1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: title 1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h4><span class="mw-headline" id="title_1.1.1">title 1.1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: title 1.1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h4>
@@ -10653,6 +10754,7 @@ wgMaxTocLevel=3
 </li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="title_1">title 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: title 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="title_1.1">title 1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: title 1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h4><span class="mw-headline" id="title_1.1.1">title 1.1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: title 1.1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h4>
@@ -10683,6 +10785,7 @@ wgMaxTocLevel=3
 <li class="toclevel-1 tocsection-5"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="Section_1.1">Section 1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Section 1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h4><span class="mw-headline" id="Section_1.1.1">Section 1.1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Section 1.1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h4>
@@ -10775,6 +10878,7 @@ __TOC__
 <li class="toclevel-1 tocsection-3"><a href="#title_2"><span class="tocnumber">2</span> <span class="toctext">title 2</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="title_1">title 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: title 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h3><span class="mw-headline" id="title_1.1">title 1.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: title 1.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
 <h2><span class="mw-headline" id="title_2">title 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: title 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -10838,6 +10942,7 @@ section 5
 <li class="toclevel-1 tocsection-5"><a href="#text_.22_text"><span class="tocnumber">5</span> <span class="toctext">text " text</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="text_.3E_text">text &gt; text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: text > text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <p>section 1
 </p>
@@ -10872,6 +10977,7 @@ Headers with excess '=' characters
 <li class="toclevel-1 tocsection-4"><a href="#.3Ditalic_heading"><span class="tocnumber">4</span> <span class="toctext">=<i>italic</i> heading</span></a></li>
 </ul>
 </div>
+
 <h1><span class="mw-headline" id="foo.3D">foo=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: foo=">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
 <h1><span class="mw-headline" id=".3Dfoo">=foo</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: =foo">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
 <h1><span class="mw-headline" id="italic_heading.3D"><i>italic</i> heading=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: italic heading=">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
@@ -10909,6 +11015,7 @@ __NOEDITSECTION__
 </li>
 </ul>
 </div>
+
 <h1><span class="mw-headline" id="Header_1">Header 1</span></h1>
 <h2><span class="mw-headline" id="Header_1.1">Header 1.1</span></h2>
 <h2><span class="mw-headline" id="Header_1.2">Header 1.2</span></h2>
@@ -11602,6 +11709,70 @@ MSIE CSS safety test: comment in expression
 
 !! end
 
+!! test
+CSS safety test: vertical tab
+!! input
+<p style="font-size: 100px; background-image:url\b(https://www.google.com/images/srpr/logo6w.png)">A</p>
+!! result
+<p style="/* invalid control char */">A</p>
+
+!! end
+
+!! test
+MSIE CSS safety test: Fullwidth
+!! input
+<p style="font-size: 100px; color: expression((title='XSSed'),'red')">A</p>
+<div style="top:EXPRESSION(alert())">B</div>
+!! result
+<p style="/* insecure input */">A</p>
+<div style="/* insecure input */">B</div>
+
+!! end
+
+!! test
+MSIE CSS safety test: IPA extensions
+!! input
+<div style="background-image:uʀʟ(javascript:alert())">A</div>
+<p style="font-size: 100px; color: expʀessɪoɴ((title='XSSed'),'red')">B</p>
+!! result
+<div style="/* insecure input */">A</div>
+<p style="/* insecure input */">B</p>
+
+!! end
+
+!! test
+MSIE CSS safety test: sup/sub script
+!! input
+<div style="background-image:url⁽javascript:alert())">A</div>
+<div style="background-image:url₍javascript:alert())">B</div>
+<p style="font-size: 100px; color: expressioⁿ((title='XSSed'),'red')">C</p>
+!! result
+<div style="/* insecure input */">A</div>
+<div style="/* insecure input */">B</div>
+<p style="/* insecure input */">C</p>
+
+!! end
+
+!! test
+MSIE CSS safety test: Repetition markers
+!! input
+<p style="font-size: 100px; color: expres〱ion((title='XSSed'),'red')">A</p>
+<p style="font-size: 100px; color: expresゝion((title='XSSed'),'red')">B</p>
+<p style="font-size: 100px; color: expresーion((title='XSSed'),'red')">C</p>
+<p style="font-size: 100px; color: expresヽion((title='XSSed'),'red')">D</p>
+<p style="font-size: 100px; color: expresﹽion((title='XSSed'),'red')">E</p>
+<p style="font-size: 100px; color: expresﹼion((title='XSSed'),'red')">F</p>
+<p style="font-size: 100px; color: expresーion((title='XSSed'),'red')">G</p>
+!! result
+<p style="/* insecure input */">A</p>
+<p style="/* insecure input */">B</p>
+<p style="/* insecure input */">C</p>
+<p style="/* insecure input */">D</p>
+<p style="/* insecure input */">E</p>
+<p style="/* insecure input */">F</p>
+<p style="/* insecure input */">G</p>
+
+!! end
 
 !! test
 Table attribute legitimate extension
@@ -12297,6 +12468,7 @@ http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 </ul>
 </div>
 
+
 !! end
 
 !! test
@@ -14226,6 +14398,7 @@ Out-of-order TOC heading levels
 </li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="2">2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h6><span class="mw-headline" id="6">6</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: 6">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
 <h3><span class="mw-headline" id="3">3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: 3">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
@@ -14813,6 +14986,64 @@ language=sr
 </p>
 !!end
 
+!! test
+Don't break link parsing if language converter markup is in the caption.
+!! options
+language=sr variant=sr-ec
+!! input
+[[Main Page|-{R|main page}-]]
+!! result
+<p><a href="/wiki/Main_Page" title="Маин Паге">main page</a>
+</p>
+!! end
+
+# This test is currently broken in the PHP parser (bug 52661)
+!! test
+Don't break image parsing if language converter markup is in the caption.
+!! options
+language=sr
+disabled
+!! input
+[[File:Foobar.jpg|-{R|caption}-]]
+!! result
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+!! end
+
+# This test is currently broken in the PHP parser (bug 52661)
+!! test
+Don't break list handling if language converter markup is in the item.
+!! options
+language=zh variant=zh-cn
+disabled
+!! input
+;-{zh-cn:AAA;zh-tw:BBB}-
+!! result
+<dl><dt>AAA
+</dt></dl>
+
+!! end
+
+# This test is currently broken in the PHP parser (bug 52661)
+!! test
+Don't break table handling if language converter markup is in the cell.
+!! options
+language=sr variant=sr-ec
+disabled
+!! input
+{|
+|-
+| -{R|B}-
+|}
+!! result
+<table>
+
+<tr>
+<td> B
+</td></tr></table>
+
+!! end
+
 !! test
 Bug 529: Uncovered bullet
 !! input
@@ -15824,6 +16055,7 @@ __TOC__
 <li class="toclevel-1 tocsection-1"><a href="#Lost_episodes"><span class="tocnumber">1</span> <span class="toctext"><i>Lost</i> episodes</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Lost_episodes"><i>Lost</i> episodes</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Lost episodes">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15841,6 +16073,7 @@ __TOC__
 <li class="toclevel-1 tocsection-1"><a href="#should_be_bold_then_normal_text"><span class="tocnumber">1</span> <span class="toctext"><b>should be bold</b> then normal text</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="should_be_bold_then_normal_text"><b>should be bold</b> then normal text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: should be bold then normal text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15858,6 +16091,7 @@ __TOC__
 <li class="toclevel-1 tocsection-1"><a href="#Image"><span class="tocnumber">1</span> <span class="toctext">Image</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Image">Image <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Image">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15875,6 +16109,7 @@ __TOC__
 <li class="toclevel-1 tocsection-1"><a href="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Quote"><blockquote>Quote</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
 !! end
@@ -15894,6 +16129,7 @@ QED
 <li class="toclevel-1 tocsection-1"><a href="#Proof:_2_.3C_3"><span class="tocnumber">1</span> <span class="toctext">Proof: 2 &lt; 3</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Proof:_2_.3C_3">Proof: 2 &lt; 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Proof: 2 &lt; 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <p><small>Hanc marginis exiguitas non caperet.</small>
 QED
@@ -15914,6 +16150,7 @@ __TOC__
 <li class="toclevel-1 tocsection-2"><a href="#Foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext"><i>Foo</i> Bar</span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Foo_Bar"><i>Foo</i> <b>Bar</b></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i> <blockquote>Bar</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -15933,6 +16170,7 @@ __TOC__
 <li class="toclevel-1 tocsection-2"><a href="#b.22.3EEvilbye"><span class="tocnumber">2</span> <span class="toctext"><sup> b"&gt;Evilbye</sup></span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="Hello"><sup class="in-h2">Hello</sup></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Hello">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="b.22.3EEvilbye"><sup> b"&gt;Evilbye</sup></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: b&quot;>Evilbye">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -15961,6 +16199,7 @@ __TOC__
 <li class="toclevel-1 tocsection-5"><a href="#Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC"><span class="tocnumber">5</span> <span class="toctext"><span dir="ltr">Attributes after dir on these span tags must be deleted from the TOC</span></span></a></li>
 </ul>
 </div>
+
 <h2><span class="mw-headline" id="C.2B.2B"><span dir="ltr">C++</span></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: C++">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id=".D7.96.D7.91.D7.A0.D7.92.21"><span dir="rtl">זבנג!</span></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: זבנג!">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <h2><span class="mw-headline" id="The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC"><span style="font-style: italic">The attributes on these span tags must be deleted from the TOC</span></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: The attributes on these span tags must be deleted from the TOC">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
@@ -16250,6 +16489,29 @@ HttP://MediaWiki.Org/
 </p>
 !! end
 
+!!test
+Disable TOC
+!! options
+notoc
+!! input
+Lead
+== Section 1 ==
+== Section 2 ==
+== Section 3 ==
+== Section 4 ==
+== Section 5 ==
+!! result
+<p>Lead
+</p>
+
+<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Section_4">Section 4</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Section 4">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Section_5">Section 5</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: Section 5">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! end
+
 
 ###
 ### Parsoids-specific tests
@@ -16343,10 +16605,10 @@ A <ref>
 
 <references />
 !!result
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"This is a <b data-parsoid=\"{&amp;quot;dsr&amp;quot;:[19,40,3,3]}\"><a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=\"{&amp;quot;stx&amp;quot;:&amp;quot;simple&amp;quot;,&amp;quot;a&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;./Bolded_link&amp;quot;},&amp;quot;sa&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;bolded link&amp;quot;},&amp;quot;dsr&amp;quot;:[22,37,2,2]}\">bolded link</a></b> and this is a <span about=\"#mwt5\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;transclusion&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[55,76,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">transclusion</span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt5\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"dsr\":[55,76,null,null],\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link">bolded link</a></b> and this is a <span about="#mwt5" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
 </li>
 </ol>
 !!end
@@ -16420,10 +16682,9 @@ A <ref> foo {{echo|</ref> B C}}
 
 <references />
 !!result
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo <span typeof=\"mw:Nowiki\" data-parsoid=\"{&amp;quot;src&amp;quot;:&amp;quot;{{&amp;quot;,&amp;quot;dsr&amp;quot;:[12,14,0,0]}\">{{</span>echo|"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C<span typeof="mw:Nowiki">}}</span></p>
-
-<ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo <span typeof="mw:Nowiki">{{</span>echo|</li>
+<p>A <span class="reference" data-mw="{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;foo <span typeof=\&quot;mw:Nowiki\&quot; data-parsoid='{\&quot;src\&quot;:\&quot;{{\&quot;,\&quot;dsr\&quot;:[12,14,0,0]}'>{{</span>echo|&quot;},&quot;attrs&quot;:{}}" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C<span typeof="mw:Nowiki">}}</span></p>
+<ol class="references" typeof="mw:Extension/references" data-mw="{&quot;name&quot;:&quot;references&quot;,&quot;attrs&quot;:{}}">
+<li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo <span typeof="mw:Nowiki">{{</span>echo|</li>
 </ol>
 !!end
 
@@ -16433,13 +16694,11 @@ Ref: 9. unclosed comments should not leak out of ref-body
 parsoid
 !!input
 A <ref> foo <!--</ref> B C
-
 <references />
 !!result
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo <!---->"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C</p>
-
-<ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo <!----></li>
+<p>A <span class="reference" data-mw='{"name":"ref","body":{"html":"foo &lt;!---->"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C</p>
+<ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
+<li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo </li>
 </ol>
 !!end
 
@@ -16452,10 +16711,11 @@ A <ref> <b> foo </ref> B C
 
 <references />
 !!result
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"<b data-parsoid=\"{&amp;quot;stx&amp;quot;:&amp;quot;html&amp;quot;,&amp;quot;autoInsertedEnd&amp;quot;:true,&amp;quot;dsr&amp;quot;:[8,16,3,0]}\"> foo </b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C</p>
+<p data-parsoid='{"dsr":[0,26,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;b data-parsoid=&#39;{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[8,16,3,0]}&#39;> foo &lt;/b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref> &lt;b> foo &lt;/ref>","dsr":[2,22,5,6]}'><a href="#cite_note-1">[1]</a></span> B C</p>
 
-<ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> <b> foo </b></li>
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references />","dsr":[28,42,2,2]}' data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> <b data-parsoid='{"stx":"html","autoInsertedEnd":true,"dsr":[8,16,3,0]}'> foo </b></li>
 </ol>
 !!end
 
@@ -16467,8 +16727,8 @@ parsoid
 A <ref>foo</ref> B
 C <ref>bar</ref> D
 !!result
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B
-C <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[2]</a></span> D</p>
+<p data-parsoid='{"dsr":[0,37,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>","dsr":[2,16,5,6]}'><a href="#cite_note-1">[1]</a></span> B
+C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>bar&lt;/ref>","dsr":[21,35,5,6]}'><a href="#cite_note-2">[2]</a></span> D</p>
 !!end
 
 !!test
@@ -16515,10 +16775,10 @@ parsoid
 
 <references />
 !!result
-<p><span about="#mwt1" class="reference" data-mw="{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;foo &amp;lt;ref&amp;gt;bar&amp;lt;/ref&amp;gt; baz&quot;},&quot;attrs&quot;:{}}" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p data-parsoid='{"dsr":[0,33,0,0]}'><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo &amp;lt;ref>bar&amp;lt;/ref> baz"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo &lt;ref>bar&lt;/ref> baz&lt;/ref>","dsr":[0,33,5,6]}'><a href="#cite_note-1">[1]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw="{&quot;name&quot;:&quot;references&quot;,&quot;attrs&quot;:{}}">
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo &lt;ref&gt;bar&lt;/ref&gt; baz</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-parsoid='{"src":"&lt;references />","dsr":[35,49,2,2]}' data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo &lt;ref>bar&lt;/ref> baz</li>
 </ol>
 !!end
 
@@ -16629,10 +16889,13 @@ B <ref name="b">bar</ref>
 This should just get lost.
 </references>
 !!result
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-a-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span></p>
+<p data-parsoid='{"dsr":[0,57,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"a\" />","dsr":[2,18,16,0]}'><a href="#cite_note-a-1">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\">bar&lt;/ref>","dsr":[21,44,14,6]}'><a href="#cite_note-b-2">[2]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","body":{"extsrc":"<ref name=\"a\">foo</ref>\nThis should just get lost.","html":"\n<span about=\"#mwt8\" class=\"reference\" data-mw=\"{&amp;quot;name&amp;quot;:&amp;quot;ref&amp;quot;,&amp;quot;body&amp;quot;:{&amp;quot;html&amp;quot;:&amp;quot;foo&amp;quot;},&amp;quot;attrs&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;a&amp;quot;}}\" rel=\"dc:references\" typeof=\"mw:Extension/ref\"><a href=\"#cite_note-a-1\">[1]</a></span>\n"},"attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="#cite_ref-a-1-0">↑</a></span> foo</li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> bar</li>
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.\n&lt;/references>","dsr":[46,123,2,2]}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.","html":"\n&lt;span about=\"#mwt8\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"a\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-a-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
+<li about="#cite_note-a-1" id="cite_note-a-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-a-1-0">↑</a></span> foo</li>
+<li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> bar</li>
 </ol>
 !!end
 
@@ -16660,16 +16923,17 @@ B <ref name="b" />
 <ref name="b">foo</ref>
 </references>
 !! result
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span></p>
+<p data-parsoid='{"dsr":[0,45,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>","dsr":[2,26,5,6]}'><a href="#cite_note-1">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" />","dsr":[29,45,16,0]}'><a href="#cite_note-b-2">[2]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo bar for a</li>
-<li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> </li>
-</ol>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","body":{"extsrc":"<ref name=\"b\">foo</ref>","html":"\n<span about=\"#mwt10\" class=\"reference\" data-mw=\"{&amp;quot;name&amp;quot;:&amp;quot;ref&amp;quot;,&amp;quot;body&amp;quot;:{&amp;quot;html&amp;quot;:&amp;quot;foo&amp;quot;},&amp;quot;attrs&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;b&amp;quot;}}\" rel=\"dc:references\" typeof=\"mw:Extension/ref\"><a href=\"#cite_note-b-1\">[1]</a></span>\n"},"attrs":{}}'>
-<li about="#cite_note-b-1" id="cite_note-b-1"><span rel="mw:referencedBy">↑</span> foo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />","dsr":[47,61,2,2]}' data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo bar for a</li>
+<li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> </li></ol>
+
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","dsr":[63,113,2,2]}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
+<li about="#cite_note-b-1" id="cite_note-b-1" data-parsoid="{}"><span rel="mw:referencedBy">↑</span> foo</li>
 </ol>
 !! end
 
@@ -18313,6 +18577,63 @@ parsoid=html2wt
 </ul>
 !! end
 
+!! test
+Don't strip leading whitespace when handling indent-pre suppressing tags
+!! options
+parsoid=html2wt
+!! input
+{|
+  | indented row
+|}
+<blockquote>
+ '''This is very bold of you!'''
+
+{|
+|
+ indented cell (no pre-wrapping!)
+|}
+</blockquote>
+foo
+ <div>bar</div>
+!! result
+<table>
+  <tr><td> indented row</td></tr>
+</table>
+<blockquote><p>
+ <b>This is very bold of you!</b>
+</p>
+<table><tr><td>
+ indented cell (no pre-wrapping!)
+</td></tr></table>
+</blockquote>
+<p>foo</p>
+ <div>bar</div>
+!! end
+
+!! test
+Strip leading whitespace when handling indent-pre inducing tags
+!! options
+parsoid=html2wt
+!! input
+foo
+<span>bar</span>
+
+<span>foo2
+</span>bar2
+
+<div>foo</div>
+<span>bar</span>
+!! result
+<p>foo</p>
+ <span>bar</span>
+
+<span>foo2
+ </span>bar2
+
+<div>foo</div>
+ <span>bar</span>
+!! end
+
 # Wacky -- the leading newline in input is required because
 # that is what the serializer emits. To be fixed. Not fixing
 # the test because this test is required to test serialization of
@@ -18460,6 +18781,16 @@ parsoid=html2wt
 <p><i>A</i><b data-parsoid='{}'><i data-parsoid='{}'>B</i></b></p>
 !! end
 
+!!test
+5. Bug 54262: New entities
+!! options
+parsoid=html2wt
+!! input
+foo
+!! result
+<span typeof="mw:Entity">foo</span>
+!! end
+
 # -----------------------------------------------------------------
 # End of section for Parsoid-only html2wt tests for serialization
 # of new content
index 042956a..cc49fde 100644 (file)
@@ -100,17 +100,14 @@ class MediaWikiPHPUnitCommand extends PHPUnit_TextUI_Command {
                print <<<EOT
 
 ParserTest-specific options:
-
   --regex="<regex>"        Only run parser tests that match the given regex
   --file="<filename>"      File describing parser tests
   --keep-uploads           Re-use the same upload directory for each test, don't delete it
 
-
 Database options:
   --use-normal-tables      Use normal DB tables.
   --reuse-db               Init DB only if tables are missing and keep after finish.
 
-
 Debugging options:
   --debug-tests            Log testing activity to the PHPUnitCommand log channel.
 
index 8c849bc..7a7ec8f 100644 (file)
@@ -35,6 +35,13 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        private static $dbSetup = false;
        private static $oldTablePrefix = false;
 
+       /**
+        * Original value of PHP's error_reporting setting.
+        *
+        * @var int
+        */
+       private $phpErrorLevel;
+
        /**
         * Holds the paths of temporary files/directories created through getNewTempFile,
         * and getNewTempDirectory
@@ -172,6 +179,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                parent::setUp();
                $this->called['setUp'] = 1;
 
+               $this->phpErrorLevel = intval( ini_get( 'error_reporting' ) );
+
                /*
                // @todo global variables to restore for *every* test
                array(
@@ -233,6 +242,18 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
                $this->mwGlobals = array();
 
+               $phpErrorLevel = intval( ini_get( 'error_reporting' ) );
+
+               if ( $phpErrorLevel !== $this->phpErrorLevel ) {
+                       ini_set( 'error_reporting', $this->phpErrorLevel );
+
+                       $oldHex = strtoupper( dechex( $this->phpErrorLevel ) );
+                       $newHex = strtoupper( dechex( $phpErrorLevel ) );
+                       $message = "PHP error_reporting setting was left dirty: was 0x$oldHex before test, 0x$newHex after test!";
+
+                       $this->fail( $message );
+               }
+
                parent::tearDown();
                wfProfileOut( __METHOD__ );
        }
@@ -537,6 +558,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                global $wgDBprefix;
 
                $tables = $db->listTables( $wgDBprefix, __METHOD__ );
+
+               if ( $db->getType() === 'mysql' ) {
+                       # bug 43571: cannot clone VIEWs under MySQL
+                       $views = $db->listViews( $wgDBprefix, __METHOD__ );
+                       $tables = array_diff( $tables, $views );
+               }
                $tables = array_map( array( __CLASS__, 'unprefixTable' ), $tables );
 
                // Don't duplicate test tables from the previous fataled run
diff --git a/tests/phpunit/data/autoloader/TestAutoloadedCamlClass.php b/tests/phpunit/data/autoloader/TestAutoloadedCamlClass.php
new file mode 100644 (file)
index 0000000..6dfce7a
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+class TestAutoloadedCamlClass {
+}
diff --git a/tests/phpunit/data/autoloader/TestAutoloadedClass.php b/tests/phpunit/data/autoloader/TestAutoloadedClass.php
new file mode 100644 (file)
index 0000000..9ceedf6
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+class TestAutoloadedClass {
+}
diff --git a/tests/phpunit/data/autoloader/TestAutoloadedLocalClass.php b/tests/phpunit/data/autoloader/TestAutoloadedLocalClass.php
new file mode 100644 (file)
index 0000000..1b397cd
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+class TestAutoloadedLocalClass {
+}
diff --git a/tests/phpunit/data/autoloader/TestAutoloadedSerializedClass.php b/tests/phpunit/data/autoloader/TestAutoloadedSerializedClass.php
new file mode 100644 (file)
index 0000000..80b9d58
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+class TestAutoloadedSerializedClass {
+}
diff --git a/tests/phpunit/data/cssmin/green.gif b/tests/phpunit/data/cssmin/green.gif
new file mode 100644 (file)
index 0000000..f9e7531
Binary files /dev/null and b/tests/phpunit/data/cssmin/green.gif differ
diff --git a/tests/phpunit/data/cssmin/large.png b/tests/phpunit/data/cssmin/large.png
new file mode 100644 (file)
index 0000000..64bf48a
Binary files /dev/null and b/tests/phpunit/data/cssmin/large.png differ
diff --git a/tests/phpunit/data/cssmin/red.gif b/tests/phpunit/data/cssmin/red.gif
new file mode 100644 (file)
index 0000000..13c43e9
Binary files /dev/null and b/tests/phpunit/data/cssmin/red.gif differ
index 66847ab..2efb7a0 100644 (file)
@@ -50,12 +50,12 @@ CREATE TABLE /*$wgDBprefix*/revision (
   rev_minor_edit tinyint  default '0',
   rev_deleted tinyint  default '0',
   rev_len int,
-  rev_parent_id INTEGER default NULL) /*$wgDBTableOptions*/  ;
+  rev_parent_id INTEGER default NULL) /*$wgDBTableOptions*/;
 
 CREATE TABLE /*$wgDBprefix*/text (
   old_id INTEGER  PRIMARY KEY AUTOINCREMENT,
   old_text mediumblob ,
-  old_flags tinyblob ) /*$wgDBTableOptions*/  ;
+  old_flags tinyblob ) /*$wgDBTableOptions*/;
 
 CREATE TABLE /*$wgDBprefix*/archive (
   ar_namespace INTEGER  default '0',
@@ -124,7 +124,7 @@ CREATE TABLE /*$wgDBprefix*/site_stats (
 
 CREATE TABLE /*$wgDBprefix*/hitcounter (
   hc_id INTEGER
-)  ;
+);
 
 CREATE TABLE /*$wgDBprefix*/ipblocks (
   ipb_id INTEGER  PRIMARY KEY AUTOINCREMENT,
@@ -245,7 +245,7 @@ CREATE TABLE /*$wgDBprefix*/math (
 CREATE TABLE /*$wgDBprefix*/searchindex (
   si_page INTEGER ,
   si_title varchar(255)  default '',
-  si_text mediumtext ) ;
+  si_text mediumtext );
 
 CREATE TABLE /*$wgDBprefix*/interwiki (
   iw_prefix varchar(32) ,
index fe3bc68..4b489a9 100644 (file)
@@ -36,3 +36,8 @@ http://commons.wikimedia.org/wiki/File:Animated_PNG_example_bouncing_beach_ball.
 Public Domain
 Holger Will
 
+Tux.svg
+https://commons.wikimedia.org/wiki/File:Tux.svg
+Larry Ewing, Simon Budig, Anja Gerwinski
+"The copyright holder of this file allows anyone to use it for any purpose, provided that the copyright holder is properly attributed. Redistribution, derivative work, commercial use, and all other use is permitted."
+
diff --git a/tests/phpunit/data/media/Tux.svg b/tests/phpunit/data/media/Tux.svg
new file mode 100644 (file)
index 0000000..3956107
--- /dev/null
@@ -0,0 +1,902 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 349.46883 405.12272">\r
+ <title>Tux</title>\r
+ <desc>For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg</desc>\r
+ <radialGradient id="ag" gradientUnits="userSpaceOnUse" cy="-551.04" cx="274.822" gradientTransform="matrix(.5671 0 0 -.2835 81.263 201.645)" r="165.384">\r
+  <stop stop-opacity=".502" offset="0"/>\r
+  <stop stop-opacity="0" offset="1"/>\r
+ </radialGradient>\r
+ <path fill="url(#ag)" d="m330.892 357.885c0 25.898-41.989 46.893-93.785 46.893-51.795 0-93.784-20.994-93.784-46.893s41.989-46.893 93.784-46.893c51.795 0.001 93.785 20.995 93.785 46.893z"/>\r
+ <radialGradient id="ak" gradientUnits="userSpaceOnUse" cy="-551.042" cx="268.794" gradientTransform="matrix(.5823 0 0 -.2835 -61.6052 201.14)" r="165.383">\r
+  <stop stop-opacity=".502" offset="0"/>\r
+  <stop stop-opacity="0" offset="1"/>\r
+ </radialGradient>\r
+ <path fill="url(#ak)" d="m191.223 357.381c0 25.897-43.117 46.892-96.306 46.892-53.188 0-96.305-20.994-96.305-46.892s43.117-46.893 96.305-46.893c53.188 0.001 96.306 20.995 96.306 46.893z"/>\r
+ <g transform="translate(8.99996 9.00046)">\r
+  <path d="m292.327 256.606c-4.752 19.584-28.872 60.48-41.688 78.48-12.815 18.072-11.231 34.344-34.92 28.008-23.616-6.336-30.24-5.184-54.647-3.744-24.265 1.439-19.009-0.721-34.2 6.12-15.12 6.84-65.88-82.944-69.984-99.647-4.031-16.705-5.976-14.689 4.536-32.761 10.513-18.071 12.024-35.928 25.92-57.816 13.896-21.96 29.952-33.12 28.8-49.896-4.535-62.28-8.136-93.384 19.513-107.784 26.352-13.68 48.384-5.544 57.096-0.864 3.744 2.016 11.376 5.904 17.064 12.744 5.688 6.696 10.8 16.848 13.68 29.664 5.904 25.704-2.448 17.208 4.248 46.656 6.624 29.375 20.088 43.775 36.504 67.031 16.414 23.257 33.55 61.633 28.078 83.809z"/>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#666" d="m148.47 94.049c4.319-1.728 3.592-1.958 6.472-8.222 2.304-4.824 4.328-6.898 4.256-14.242 0-7.2-2.232-9.648-5.616-14.328-3.24-4.464-8.424-4.68-11.664-4.104-1.872 0.288-4.319 2.664-5.976 6.192-1.08 2.376-1.944 5.4-2.017 8.568-0.216 8.496 0.505 11.736 2.448 17.496 2.305 6.769 7.921 10.297 12.097 8.64z"/>\r
+   <path fill="#6d6d6d" d="m148.47 94.023c4.293-1.717 3.563-1.954 6.425-8.178 2.289-4.793 4.312-6.861 4.271-14.164 0.027-7.152-2.162-9.702-5.488-14.201-3.296-4.345-8.376-4.509-11.593-3.953-1.916 0.283-4.354 2.569-6.038 5.968-1.159 2.31-2.016 5.353-2.087 8.535-0.212 8.438 0.547 11.691 2.46 17.417 2.268 6.731 7.901 10.221 12.05 8.576z"/>\r
+   <path fill="#757575" d="m148.471 93.996c4.264-1.706 3.533-1.95 6.377-8.133 2.273-4.762 4.296-6.823 4.288-14.085 0.053-7.105-2.093-9.756-5.363-14.075-3.35-4.225-8.327-4.338-11.52-3.801-1.961 0.278-4.389 2.474-6.099 5.744-1.242 2.245-2.089 5.305-2.16 8.501-0.207 8.38 0.591 11.647 2.473 17.34 2.231 6.691 7.881 10.144 12.004 8.509z"/>\r
+   <path fill="#7c7c7c" d="m148.471 93.969c4.235-1.694 3.506-1.946 6.329-8.089 2.26-4.731 4.28-6.786 4.304-14.006 0.081-7.058-2.021-9.811-5.236-13.948-3.403-4.105-8.278-4.167-11.446-3.649-2.006 0.273-4.424 2.379-6.16 5.519-1.322 2.179-2.161 5.257-2.232 8.468-0.202 8.323 0.636 11.603 2.486 17.261 2.191 6.654 7.859 10.068 11.955 8.444z"/>\r
+   <path fill="#848484" d="m148.471 93.943c4.209-1.684 3.477-1.942 6.282-8.045 2.245-4.7 4.266-6.749 4.319-13.928 0.107-7.01-1.95-9.864-5.109-13.821-3.458-3.985-8.23-3.996-11.375-3.498-2.049 0.268-4.458 2.284-6.222 5.295-1.403 2.114-2.233 5.21-2.303 8.435-0.198 8.265 0.679 11.559 2.498 17.183 2.156 6.615 7.842 9.992 11.91 8.379z"/>\r
+   <path fill="#8c8c8c" d="m148.471 93.916c4.181-1.672 3.448-1.938 6.235-8 2.23-4.668 4.249-6.711 4.335-13.85 0.134-6.962-1.88-9.918-4.982-13.695-3.513-3.865-8.183-3.825-11.303-3.347-2.094 0.263-4.492 2.189-6.283 5.07-1.484 2.049-2.306 5.163-2.375 8.401-0.193 8.207 0.723 11.515 2.511 17.105 2.118 6.58 7.821 9.919 11.862 8.316z"/>\r
+   <path fill="#939393" d="m148.472 93.889c4.152-1.661 3.419-1.934 6.188-7.956 2.215-4.638 4.233-6.674 4.35-13.771 0.161-6.915-1.809-9.972-4.854-13.568-3.567-3.746-8.134-3.654-11.23-3.195-2.138 0.259-4.527 2.094-6.345 4.847-1.564 1.983-2.378 5.115-2.447 8.368-0.188 8.149 0.767 11.47 2.523 17.026 2.079 6.54 7.8 9.841 11.815 8.249z"/>\r
+   <path fill="#9b9b9b" d="m148.472 93.863c4.125-1.65 3.391-1.93 6.141-7.912 2.2-4.607 4.217-6.637 4.366-13.693 0.188-6.868-1.739-10.026-4.729-13.441-3.621-3.626-8.085-3.484-11.157-3.044-2.183 0.253-4.562 1.999-6.406 4.622-1.646 1.918-2.45 5.068-2.52 8.335-0.185 8.091 0.811 11.426 2.535 16.948 2.044 6.502 7.782 9.766 11.77 8.185z"/>\r
+   <path fill="#a3a3a3" d="m148.472 93.836c4.097-1.639 3.361-1.926 6.094-7.867 2.185-4.576 4.201-6.599 4.382-13.614 0.214-6.82-1.669-10.081-4.603-13.315-3.676-3.506-8.036-3.313-11.084-2.893-2.229 0.249-4.598 1.904-6.47 4.398-1.726 1.852-2.521 5.021-2.591 8.301-0.18 8.034 0.854 11.382 2.548 16.87 2.008 6.465 7.763 9.691 11.724 8.12z"/>\r
+   <path fill="#aaa" d="m148.472 93.809c4.069-1.628 3.334-1.922 6.047-7.823 2.17-4.544 4.185-6.562 4.396-13.536 0.242-6.772-1.597-10.134-4.475-13.188-3.73-3.387-7.989-3.142-11.013-2.741-2.271 0.243-4.632 1.809-6.53 4.173-1.808 1.787-2.594 4.974-2.662 8.268-0.176 7.976 0.897 11.337 2.56 16.792 1.97 6.427 7.743 9.615 11.677 8.055z"/>\r
+   <path fill="#b2b2b2" d="m148.473 93.782c4.041-1.617 3.304-1.918 5.999-7.778 2.154-4.514 4.169-6.524 4.412-13.458 0.269-6.725-1.526-10.188-4.349-13.062-3.784-3.267-7.939-2.971-10.939-2.589-2.316 0.238-4.666 1.714-6.592 3.949-1.888 1.721-2.667 4.926-2.734 8.234-0.171 7.918 0.941 11.293 2.572 16.713 1.933 6.391 7.723 9.541 11.631 7.991z"/>\r
+   <path fill="#bababa" d="m148.473 93.756c4.014-1.606 3.275-1.914 5.951-7.734 2.141-4.482 4.153-6.487 4.43-13.379 0.295-6.678-1.457-10.243-4.223-12.935-3.839-3.147-7.892-2.8-10.867-2.438-2.36 0.233-4.701 1.619-6.653 3.725-1.969 1.656-2.739 4.879-2.806 8.201-0.167 7.86 0.984 11.249 2.585 16.636 1.895 6.35 7.702 9.462 11.583 7.924z"/>\r
+   <path fill="#c1c1c1" d="m148.473 93.729c3.985-1.595 3.247-1.91 5.904-7.69 2.125-4.451 4.138-6.45 4.445-13.3 0.321-6.63-1.387-10.297-4.096-12.808-3.894-3.028-7.844-2.629-10.795-2.287-2.405 0.229-4.735 1.524-6.716 3.5-2.049 1.59-2.811 4.831-2.878 8.167-0.161 7.802 1.029 11.205 2.599 16.557 1.859 6.314 7.683 9.389 11.537 7.861z"/>\r
+   <path fill="#c9c9c9" d="m148.473 93.702c3.958-1.583 3.219-1.906 5.857-7.646 2.11-4.42 4.121-6.412 4.46-13.222 0.35-6.583-1.315-10.351-3.969-12.682-3.947-2.908-7.794-2.458-10.722-2.135-2.45 0.224-4.771 1.429-6.777 3.276-2.13 1.525-2.883 4.784-2.95 8.135-0.157 7.745 1.073 11.16 2.611 16.479 1.821 6.276 7.663 9.313 11.49 7.795z"/>\r
+   <path fill="#d1d1d1" d="m148.474 93.676c3.93-1.573 3.188-1.902 5.809-7.601 2.097-4.389 4.107-6.375 4.477-13.144 0.375-6.535-1.245-10.404-3.842-12.555-4.002-2.788-7.747-2.287-10.65-1.984-2.493 0.219-4.805 1.334-6.837 3.052-2.213 1.459-2.957 4.736-3.022 8.101-0.153 7.687 1.116 11.116 2.623 16.401 1.782 6.237 7.642 9.237 11.442 7.73z"/>\r
+   <path fill="#d8d8d8" d="m148.474 93.649c3.901-1.562 3.16-1.898 5.762-7.557 2.082-4.358 4.091-6.338 4.493-13.065 0.401-6.487-1.176-10.458-3.716-12.428-4.057-2.668-7.698-2.116-10.578-1.832-2.538 0.214-4.839 1.239-6.899 2.827-2.292 1.394-3.029 4.689-3.094 8.068-0.148 7.629 1.16 11.072 2.636 16.322 1.746 6.2 7.623 9.161 11.396 7.665z"/>\r
+   <path fill="#e0e0e0" d="m148.474 93.622c3.875-1.55 3.132-1.894 5.715-7.512 2.066-4.327 4.075-6.3 4.508-12.987 0.429-6.44-1.104-10.513-3.588-12.302-4.111-2.549-7.65-1.945-10.506-1.681-2.582 0.209-4.874 1.144-6.961 2.604-2.373 1.328-3.102 4.642-3.165 8.034-0.145 7.571 1.204 11.027 2.647 16.244 1.709 6.162 7.604 9.086 11.35 7.6z"/>\r
+   <path fill="#e8e8e8" d="m148.474 93.596c3.847-1.54 3.104-1.89 5.668-7.468 2.052-4.296 4.059-6.263 4.523-12.908 0.456-6.393-1.034-10.567-3.462-12.175-4.165-2.429-7.601-1.774-10.433-1.529-2.627 0.204-4.908 1.049-7.023 2.379-2.453 1.263-3.173 4.594-3.236 8.001-0.141 7.514 1.247 10.983 2.659 16.166 1.673 6.123 7.585 9.008 11.304 7.534z"/>\r
+   <path fill="#efefef" d="m148.475 93.569c3.817-1.528 3.073-1.886 5.62-7.424 2.036-4.265 4.043-6.226 4.539-12.83 0.482-6.345-0.964-10.621-3.336-12.048-4.219-2.31-7.552-1.604-10.359-1.378-2.672 0.199-4.943 0.954-7.084 2.155-2.535 1.197-3.246 4.546-3.311 7.967-0.135 7.456 1.292 10.939 2.673 16.087 1.636 6.087 7.565 8.935 11.258 7.471z"/>\r
+   <path fill="#f7f7f7" d="m148.475 93.542c3.791-1.517 3.046-1.882 5.572-7.379 2.022-4.234 4.027-6.188 4.556-12.751 0.51-6.297-0.894-10.675-3.208-11.921-4.274-2.19-7.505-1.433-10.289-1.227-2.715 0.194-4.978 0.859-7.146 1.93-2.614 1.132-3.317 4.5-3.381 7.935-0.131 7.398 1.335 10.895 2.686 16.009 1.597 6.047 7.544 8.858 11.21 7.404z"/>\r
+   <path fill="#fff" d="m148.475 93.516c3.763-1.506 3.017-1.878 5.525-7.335 2.007-4.203 4.012-6.151 4.571-12.673 0.536-6.25-0.823-10.729-3.082-11.795-4.328-2.07-7.456-1.262-10.216-1.075-2.76 0.189-5.012 0.764-7.207 1.706-2.696 1.066-3.39 4.452-3.453 7.901-0.126 7.34 1.379 10.85 2.698 15.931 1.561 6.01 7.525 8.782 11.164 7.34z"/>\r
+  </g>\r
+  <path d="m132.033 74.7465c2.16 0 4.896 1.44 6.191 3.384 1.368 1.944 2.376 4.68 2.376 7.776 0 4.608-0.504 9.72-3.239 11.304-0.864 0.504-2.736 0.936-3.816 0.936-2.448 0-2.664-1.584-4.968-3.96-0.792-0.864-3.168-5.04-3.168-8.496 0-2.16-0.504-5.256 1.368-7.992 1.296-2.016 2.952-2.952 5.256-2.952z"/>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m143.862 68.608c0.844-1.305 4.222-0.69 5.45 1.996 1.229 2.687 0.998 8.522 0.153 8.829-2.226 0.691-1.535-2.534-3.454-5.451-1.919-2.762-2.994-4.067-2.149-5.374z"/>\r
+   <path fill="#070707" d="m143.916 68.664c0.833-1.289 4.169-0.681 5.381 1.971 1.215 2.653 0.985 8.414 0.152 8.717-2.198 0.682-1.516-2.502-3.411-5.382-1.895-2.728-2.956-4.017-2.122-5.306z"/>\r
+   <path fill="#0f0f0f" d="m143.97 68.719c0.822-1.272 4.114-0.673 5.312 1.945 1.198 2.619 0.973 8.306 0.15 8.605-2.169 0.673-1.497-2.47-3.367-5.313-1.871-2.692-2.918-3.964-2.095-5.237z"/>\r
+   <path fill="#161616" d="m144.024 68.774c0.812-1.255 4.062-0.664 5.243 1.92 1.182 2.585 0.96 8.198 0.147 8.493-2.141 0.665-1.477-2.438-3.323-5.244-1.846-2.657-2.88-3.913-2.067-5.169z"/>\r
+   <path fill="#1e1e1e" d="m144.078 68.829c0.801-1.239 4.008-0.655 5.174 1.895 1.167 2.551 0.947 8.09 0.146 8.381-2.113 0.656-1.458-2.405-3.28-5.174-1.821-2.623-2.842-3.863-2.04-5.102z"/>\r
+   <path fill="#262626" d="m144.132 68.884c0.791-1.222 3.955-0.646 5.105 1.87 1.151 2.517 0.935 7.982 0.144 8.27-2.085 0.647-1.438-2.374-3.235-5.105-1.798-2.589-2.805-3.812-2.014-5.035z"/>\r
+   <path fill="#2d2d2d" d="m144.186 68.939c0.779-1.206 3.9-0.638 5.036 1.844 1.135 2.483 0.922 7.874 0.142 8.158-2.057 0.639-1.419-2.341-3.192-5.037-1.773-2.552-2.766-3.758-1.986-4.965z"/>\r
+   <path fill="#353535" d="m144.24 68.994c0.769-1.189 3.848-0.629 4.967 1.819 1.12 2.449 0.909 7.766 0.141 8.046-2.028 0.629-1.399-2.31-3.148-4.967-1.75-2.518-2.73-3.708-1.96-4.898z"/>\r
+   <path fill="#3d3d3d" d="m144.294 69.049c0.76-1.172 3.794-0.621 4.898 1.793 1.104 2.415 0.896 7.658 0.138 7.934-2 0.621-1.38-2.277-3.104-4.898-1.725-2.482-2.691-3.655-1.932-4.829z"/>\r
+   <path fill="#444" d="m144.348 69.104c0.748-1.156 3.74-0.612 4.829 1.768 1.088 2.38 0.884 7.55 0.136 7.822-1.973 0.612-1.36-2.245-3.062-4.829-1.699-2.448-2.651-3.604-1.903-4.761z"/>\r
+   <path fill="#4c4c4c" d="m144.402 69.16c0.737-1.14 3.687-0.603 4.76 1.743 1.073 2.347 0.871 7.442 0.134 7.71-1.943 0.604-1.341-2.213-3.017-4.76-1.676-2.414-2.614-3.554-1.877-4.693z"/>\r
+   <path fill="#545454" d="m144.456 69.215c0.727-1.123 3.634-0.595 4.691 1.717 1.057 2.313 0.857 7.334 0.132 7.598-1.916 0.595-1.321-2.181-2.973-4.691-1.652-2.378-2.577-3.501-1.85-4.624z"/>\r
+   <path fill="#5b5b5b" d="m144.51 69.27c0.717-1.106 3.58-0.585 4.622 1.692 1.041 2.278 0.847 7.226 0.131 7.486-1.888 0.586-1.303-2.149-2.93-4.622-1.628-2.343-2.539-3.45-1.823-4.556z"/>\r
+   <path fill="#636363" d="m144.564 69.325c0.705-1.09 3.526-0.577 4.553 1.667 1.026 2.245 0.833 7.118 0.128 7.375-1.858 0.577-1.282-2.117-2.885-4.553-1.604-2.309-2.501-3.399-1.796-4.489z"/>\r
+   <path fill="#6b6b6b" d="m144.618 69.38c0.694-1.073 3.473-0.568 4.483 1.642 1.011 2.21 0.82 7.01 0.127 7.263-1.831 0.568-1.264-2.084-2.842-4.484-1.578-2.274-2.462-3.347-1.768-4.421z"/>\r
+   <path fill="#727272" d="m144.672 69.435c0.685-1.057 3.42-0.56 4.414 1.617 0.995 2.176 0.81 6.902 0.125 7.15-1.803 0.56-1.243-2.053-2.798-4.415-1.554-2.238-2.425-3.295-1.741-4.352z"/>\r
+   <path fill="#7a7a7a" d="m144.726 69.49c0.673-1.041 3.365-0.551 4.345 1.591 0.979 2.143 0.796 6.794 0.123 7.039-1.775 0.551-1.224-2.021-2.754-4.346-1.53-2.203-2.387-3.244-1.714-4.284z"/>\r
+   <path fill="#828282" d="m144.78 69.545c0.662-1.023 3.313-0.542 4.276 1.566 0.964 2.108 0.782 6.686 0.121 6.926-1.746 0.542-1.204-1.988-2.711-4.276-1.505-2.167-2.348-3.192-1.686-4.216z"/>\r
+   <path fill="#898989" d="m144.834 69.6c0.652-1.007 3.259-0.533 4.207 1.541s0.771 6.578 0.119 6.815c-1.718 0.534-1.185-1.956-2.666-4.207-1.482-2.134-2.311-3.142-1.66-4.149z"/>\r
+   <path fill="#919191" d="m144.888 69.655c0.641-0.99 3.206-0.524 4.138 1.516 0.933 2.04 0.758 6.47 0.117 6.703-1.69 0.525-1.165-1.924-2.623-4.138-1.457-2.098-2.273-3.09-1.632-4.081z"/>\r
+   <path fill="#999" d="m144.942 69.71c0.63-0.974 3.152-0.516 4.069 1.49s0.744 6.362 0.114 6.591c-1.662 0.516-1.146-1.892-2.579-4.069-1.432-2.062-2.234-3.037-1.604-4.012z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#666" d="m193.11 94.985c10.8-1.152 14.616-5.328 16.56-12.6 1.729-6.48 1.801-13.68-3.023-22.104-4.536-8.063-7.128-9.36-13.681-9.864-10.079-0.864-14.832 6.192-17.063 11.232-2.376 5.472-1.872 4.68-1.729 11.592 0.145 7.272 4.245 9.299 6.766 13.835 2.519 4.465 10.946 7.982 12.17 7.909z"/>\r
+   <path fill="#6d6d6d" d="m193.115 94.944c10.759-1.131 14.618-5.354 16.515-12.569 1.701-6.525 1.785-13.686-3.002-21.912-4.434-7.797-7.038-9.081-13.512-9.581-10.049-0.861-14.941 5.873-17.181 10.874-2.304 5.28-1.878 4.718-1.726 11.539 0.16 7.268 4.268 9.223 6.784 13.76 2.521 4.475 10.898 7.962 12.122 7.889z"/>\r
+   <path fill="#757575" d="m193.12 94.902c10.718-1.11 14.62-5.379 16.469-12.538 1.676-6.57 1.771-13.692-2.979-21.721-4.331-7.53-6.947-8.801-13.344-9.297-10.018-0.858-15.05 5.553-17.298 10.516-2.229 5.087-1.885 4.757-1.722 11.487 0.176 7.264 4.289 9.146 6.803 13.686 2.52 4.485 10.848 7.942 12.071 7.867z"/>\r
+   <path fill="#7c7c7c" d="m193.126 94.861c10.675-1.09 14.621-5.405 16.423-12.507 1.648-6.616 1.756-13.698-2.958-21.529-4.229-7.263-6.856-8.522-13.176-9.014-9.985-0.854-15.158 5.234-17.414 10.158-2.156 4.895-1.891 4.795-1.719 11.434 0.193 7.26 4.31 9.07 6.822 13.611 2.52 4.495 10.798 7.922 12.022 7.847z"/>\r
+   <path fill="#848484" d="m193.131 94.82c10.635-1.069 14.623-5.431 16.377-12.476 1.622-6.661 1.741-13.704-2.936-21.337-4.126-6.996-6.767-8.242-13.008-8.73-9.955-0.852-15.267 4.915-17.53 9.8-2.084 4.703-1.896 4.833-1.716 11.38 0.209 7.256 4.332 8.995 6.841 13.537 2.52 4.505 10.748 7.902 11.972 7.826z"/>\r
+   <path fill="#8c8c8c" d="m193.136 94.778c10.593-1.048 14.625-5.457 16.331-12.445 1.596-6.706 1.726-13.709-2.913-21.145-4.025-6.729-6.678-7.963-12.841-8.447-9.924-0.848-15.375 4.595-17.647 9.441-2.01 4.51-1.903 4.872-1.712 11.328 0.225 7.251 4.354 8.918 6.858 13.462 2.521 4.517 10.7 7.883 11.924 7.806z"/>\r
+   <path fill="#939393" d="m193.141 94.737c10.552-1.027 14.627-5.482 16.286-12.414 1.568-6.751 1.711-13.715-2.893-20.954-3.922-6.462-6.586-7.683-12.672-8.163-9.892-0.845-15.483 4.276-17.764 9.083-1.938 4.318-1.909 4.91-1.709 11.275 0.24 7.247 4.375 8.842 6.878 13.387 2.521 4.528 10.651 7.863 11.874 7.786z"/>\r
+   <path fill="#9b9b9b" d="m193.146 94.695c10.51-1.007 14.63-5.508 16.241-12.382 1.542-6.796 1.694-13.721-2.87-20.762-3.82-6.195-6.496-7.404-12.504-7.879-9.861-0.842-15.592 3.956-17.882 8.725-1.863 4.126-1.915 4.949-1.706 11.223 0.258 7.243 4.397 8.766 6.897 13.313 2.521 4.535 10.601 7.841 11.824 7.762z"/>\r
+   <path fill="#a3a3a3" d="m193.151 94.654c10.469-0.986 14.632-5.534 16.196-12.351 1.515-6.842 1.68-13.727-2.85-20.57-3.717-5.928-6.405-7.125-12.335-7.596-9.83-0.839-15.7 3.637-17.998 8.367-1.791 3.933-1.922 4.987-1.703 11.169 0.273 7.239 4.419 8.689 6.916 13.238 2.521 4.547 10.551 7.822 11.774 7.743z"/>\r
+   <path fill="#aaa" d="m193.157 94.612c10.427-0.965 14.633-5.56 16.149-12.32 1.488-6.887 1.666-13.733-2.826-20.379-3.615-5.661-6.316-6.845-12.168-7.313-9.799-0.835-15.809 3.317-18.114 8.009-1.718 3.741-1.928 5.025-1.7 11.117 0.29 7.235 4.44 8.613 6.936 13.163 2.519 4.558 10.499 7.804 11.723 7.723z"/>\r
+   <path fill="#b2b2b2" d="m193.162 94.571c10.386-0.944 14.635-5.585 16.104-12.289 1.462-6.932 1.649-13.739-2.806-20.188-3.512-5.394-6.225-6.565-11.999-7.029-9.768-0.833-15.917 2.998-18.23 7.651-1.646 3.549-1.935 5.064-1.697 11.064 0.306 7.231 4.462 8.537 6.954 13.088 2.52 4.569 10.451 7.784 11.674 7.703z"/>\r
+   <path fill="#bababa" d="m193.167 94.529c10.345-0.923 14.638-5.611 16.059-12.258 1.436-6.977 1.636-13.744-2.782-19.995-3.41-5.127-6.135-6.286-11.832-6.746-9.736-0.829-16.025 2.679-18.347 7.293-1.572 3.356-1.941 5.103-1.694 11.011 0.322 7.227 4.484 8.461 6.973 13.014 2.519 4.579 10.4 7.764 11.623 7.681z"/>\r
+   <path fill="#c1c1c1" d="m193.172 94.488c10.304-0.903 14.64-5.637 16.014-12.227 1.409-7.022 1.62-13.75-2.762-19.804-3.308-4.86-6.044-6.006-11.662-6.462-9.705-0.826-16.135 2.359-18.466 6.935-1.498 3.164-1.945 5.141-1.689 10.958 0.338 7.223 4.506 8.385 6.991 12.939 2.519 4.59 10.351 7.744 11.574 7.661z"/>\r
+   <path fill="#c9c9c9" d="m193.177 94.447c10.262-0.882 14.641-5.663 15.967-12.196 1.383-7.068 1.605-13.756-2.738-19.612-3.206-4.593-5.954-5.727-11.496-6.179-9.673-0.823-16.242 2.04-18.581 6.577-1.425 2.972-1.952 5.179-1.687 10.906 0.354 7.219 4.526 8.308 7.01 12.865 2.52 4.598 10.302 7.723 11.525 7.639z"/>\r
+   <path fill="#d1d1d1" d="m193.182 94.405c10.221-0.861 14.643-5.688 15.922-12.165 1.355-7.113 1.591-13.762-2.717-19.42-3.104-4.326-5.864-5.448-11.327-5.895-9.644-0.82-16.352 1.721-18.698 6.219-1.353 2.779-1.959 5.217-1.684 10.853 0.369 7.214 4.549 8.232 7.028 12.79 2.521 4.609 10.254 7.703 11.476 7.618z"/>\r
+   <path fill="#d8d8d8" d="m193.187 94.364c10.179-0.841 14.645-5.714 15.876-12.133 1.33-7.158 1.576-13.768-2.694-19.229-3.001-4.059-5.773-5.168-11.16-5.612-9.61-0.817-16.459 1.401-18.813 5.861-1.279 2.586-1.965 5.256-1.682 10.8 0.387 7.21 4.571 8.156 7.049 12.715 2.519 4.619 10.202 7.684 11.424 7.598z"/>\r
+   <path fill="#e0e0e0" d="m193.193 94.322c10.137-0.82 14.646-5.74 15.83-12.103 1.303-7.203 1.561-13.773-2.673-19.037-2.898-3.792-5.684-4.889-10.991-5.328-9.58-0.813-16.568 1.082-18.931 5.502-1.206 2.395-1.972 5.294-1.679 10.747 0.403 7.207 4.592 8.08 7.067 12.641 2.521 4.631 10.154 7.666 11.377 7.578z"/>\r
+   <path fill="#e8e8e8" d="m193.198 94.281c10.096-0.799 14.648-5.766 15.785-12.071 1.275-7.249 1.545-13.779-2.651-18.845-2.796-3.525-5.593-4.609-10.823-5.044-9.549-0.81-16.677 0.762-19.048 5.145-1.133 2.202-1.978 5.333-1.675 10.694 0.419 7.202 4.614 8.003 7.086 12.566 2.52 4.638 10.103 7.643 11.326 7.555z"/>\r
+   <path fill="#efefef" d="m193.203 94.239c10.055-0.778 14.65-5.792 15.739-12.04 1.25-7.293 1.531-13.785-2.629-18.653-2.694-3.258-5.502-4.33-10.655-4.761-9.517-0.807-16.785 0.443-19.165 4.786-1.059 2.01-1.983 5.372-1.671 10.642 0.435 7.198 4.636 7.928 7.104 12.492 2.52 4.649 10.055 7.624 11.277 7.534z"/>\r
+   <path fill="#f7f7f7" d="m193.208 94.198c10.014-0.757 14.652-5.817 15.694-12.009 1.223-7.339 1.516-13.792-2.607-18.462-2.592-2.991-5.413-4.05-10.486-4.478-9.487-0.804-16.895 0.124-19.282 4.428-0.986 1.817-1.989 5.41-1.668 10.589 0.451 7.194 4.657 7.851 7.123 12.417 2.519 4.661 10.004 7.605 11.226 7.515z"/>\r
+   <path fill="#fff" d="m193.213 94.156c9.973-0.737 14.654-5.843 15.648-11.978 1.197-7.384 1.501-13.797-2.585-18.27-2.489-2.724-5.322-3.771-10.319-4.194-9.455-0.801-17.002-0.196-19.397 4.07-0.913 1.625-1.996 5.448-1.665 10.536 0.467 7.19 4.679 7.775 7.142 12.342 2.519 4.671 9.954 7.586 11.176 7.494z"/>\r
+  </g>\r
+  <path d="m179.841 74.4585c5.4 0 8.568 4.824 9.648 11.016 0.432 2.808-0.216 6.048-1.944 8.28-1.944 2.592-5.4 4.176-8.208 4.176-2.664 0-5.688 0.432-7.271-1.728-1.584-2.232-1.944-7.2-1.944-10.728 0-3.96 1.152-6.768 3.168-9 1.511-1.657 4.247-2.016 6.551-2.016z"/>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m192.591 66.68c0.98-0.653 2.612 0 4.489 2.122 2.039 2.285 2.938 4.08 0.489 5.385-1.877 0.98-2.448-1.958-3.59-3.182-1.795-1.959-3.346-3.02-1.388-4.325z"/>\r
+   <path fill="#070707" d="m192.631 66.738c0.96-0.649 2.573 0 4.423 2.09 2.009 2.251 2.864 4.02 0.481 5.305-1.837 0.977-2.403-1.929-3.525-3.135-1.768-1.925-3.296-2.965-1.379-4.26z"/>\r
+   <path fill="#0f0f0f" d="m192.671 66.797c0.939-0.645 2.534 0 4.356 2.059 1.978 2.217 2.792 3.958 0.474 5.225-1.798 0.974-2.357-1.9-3.46-3.087-1.742-1.895-3.247-2.913-1.37-4.197z"/>\r
+   <path fill="#161616" d="m192.711 66.855c0.919-0.641 2.495 0 4.289 2.027 1.948 2.184 2.721 3.898 0.467 5.146-1.759 0.971-2.313-1.871-3.396-3.041-1.715-1.861-3.197-2.858-1.36-4.132z"/>\r
+   <path fill="#1e1e1e" d="m192.751 66.914c0.899-0.637 2.457 0 4.223 1.996 1.918 2.149 2.647 3.838 0.46 5.065-1.72 0.968-2.269-1.842-3.331-2.993-1.689-1.83-3.148-2.805-1.352-4.068z"/>\r
+   <path fill="#262626" d="m192.791 66.973c0.878-0.633 2.418 0 4.155 1.964 1.888 2.116 2.576 3.777 0.453 4.986-1.68 0.965-2.224-1.813-3.267-2.946-1.661-1.798-3.097-2.752-1.341-4.004z"/>\r
+   <path fill="#2d2d2d" d="m192.831 67.031c0.858-0.629 2.379 0 4.089 1.933 1.857 2.082 2.503 3.717 0.445 4.906-1.641 0.961-2.178-1.784-3.201-2.898-1.636-1.767-3.048-2.7-1.333-3.941z"/>\r
+   <path fill="#353535" d="m192.87 67.09c0.838-0.625 2.341 0 4.023 1.902 1.827 2.047 2.431 3.656 0.438 4.826-1.601 0.958-2.133-1.755-3.137-2.852-1.608-1.735-2.998-2.646-1.324-3.876z"/>\r
+   <path fill="#3d3d3d" d="m192.91 67.148c0.818-0.621 2.302 0 3.956 1.87 1.797 2.014 2.359 3.596 0.431 4.746-1.562 0.956-2.088-1.726-3.071-2.804-1.583-1.702-2.95-2.592-1.316-3.812z"/>\r
+   <path fill="#444" d="m192.95 67.207c0.798-0.617 2.263 0 3.889 1.839 1.768 1.98 2.287 3.535 0.425 4.666-1.523 0.952-2.043-1.697-3.008-2.757-1.556-1.671-2.899-2.539-1.306-3.748z"/>\r
+   <path fill="#4c4c4c" d="m192.99 67.266c0.777-0.614 2.224 0 3.823 1.807 1.735 1.946 2.214 3.474 0.416 4.586-1.483 0.949-1.998-1.667-2.942-2.709-1.529-1.639-2.85-2.486-1.297-3.684z"/>\r
+   <path fill="#545454" d="m193.03 67.325c0.757-0.61 2.185 0 3.756 1.775 1.706 1.912 2.143 3.414 0.409 4.506-1.444 0.946-1.953-1.639-2.878-2.663-1.502-1.606-2.799-2.431-1.287-3.618z"/>\r
+   <path fill="#5b5b5b" d="m193.07 67.383c0.736-0.605 2.146 0 3.688 1.744 1.677 1.878 2.07 3.353 0.402 4.426-1.405 0.943-1.908-1.609-2.813-2.615-1.475-1.575-2.749-2.378-1.277-3.555z"/>\r
+   <path fill="#636363" d="m193.11 67.442c0.716-0.602 2.106 0 3.622 1.712 1.646 1.844 1.998 3.293 0.395 4.347-1.364 0.94-1.862-1.581-2.748-2.568-1.449-1.543-2.701-2.326-1.269-3.491z"/>\r
+   <path fill="#6b6b6b" d="m193.15 67.5c0.696-0.598 2.069 0 3.556 1.681 1.615 1.811 1.925 3.232 0.387 4.267-1.325 0.937-1.818-1.552-2.683-2.521-1.423-1.511-2.651-2.272-1.26-3.427z"/>\r
+   <path fill="#727272" d="m193.19 67.559c0.675-0.594 2.03 0 3.489 1.649 1.585 1.777 1.853 3.172 0.38 4.187-1.287 0.935-1.774-1.522-2.619-2.473-1.396-1.48-2.601-2.219-1.25-3.363z"/>\r
+   <path fill="#7a7a7a" d="m193.23 67.618c0.654-0.59 1.991 0 3.422 1.618 1.555 1.743 1.781 3.111 0.373 4.107-1.247 0.931-1.729-1.494-2.554-2.426-1.369-1.448-2.551-2.166-1.241-3.299z"/>\r
+   <path fill="#828282" d="m193.269 67.677c0.635-0.586 1.953 0 3.355 1.586 1.525 1.708 1.709 3.05 0.366 4.026-1.208 0.928-1.684-1.464-2.489-2.378-1.342-1.416-2.501-2.112-1.232-3.234z"/>\r
+   <path fill="#898989" d="m193.309 67.735c0.614-0.582 1.914 0 3.29 1.555 1.493 1.675 1.636 2.99 0.357 3.947-1.169 0.925-1.639-1.435-2.424-2.332-1.316-1.384-2.452-2.058-1.223-3.17z"/>\r
+   <path fill="#919191" d="m193.349 67.794c0.595-0.578 1.875 0 3.223 1.523 1.464 1.641 1.564 2.93 0.351 3.867-1.129 0.922-1.594-1.406-2.359-2.284-1.29-1.352-2.403-2.005-1.215-3.106z"/>\r
+   <path fill="#999" d="m193.389 67.853c0.573-0.574 1.836 0 3.155 1.492 1.435 1.607 1.492 2.869 0.345 3.787-1.091 0.919-1.55-1.377-2.295-2.237-1.263-1.32-2.353-1.953-1.205-3.042z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m165.498 69.906c1.693-0.654 3.012-0.69 5.63 1.036 3.166 2.088 1.705 5.245-0.779 4.601-2.146-0.556-2.417-0.681-4.391-1.086-3.101-0.648-3.641-3.322-0.46-4.551z"/>\r
+   <path fill="#050505" d="m165.564 70.033c1.658-0.629 2.973-0.656 5.555 1.026 3.066 2.009 1.654 5.012-0.805 4.38-2.131-0.547-2.345-0.656-4.284-1.052-3.055-0.634-3.587-3.173-0.466-4.354z"/>\r
+   <path fill="#0a0a0a" d="m165.63 70.16c1.623-0.604 2.935-0.622 5.481 1.015 2.965 1.93 1.602 4.779-0.83 4.159-2.119-0.539-2.274-0.63-4.179-1.018-3.009-0.618-3.533-3.022-0.472-4.156z"/>\r
+   <path fill="#0f0f0f" d="m165.696 70.287c1.587-0.579 2.895-0.587 5.406 1.005 2.864 1.851 1.551 4.546-0.855 3.938-2.105-0.53-2.203-0.605-4.073-0.983-2.963-0.604-3.48-2.873-0.478-3.96z"/>\r
+   <path fill="#141414" d="m165.761 70.413c1.553-0.553 2.856-0.553 5.331 0.995 2.766 1.772 1.5 4.313-0.88 3.717-2.092-0.521-2.131-0.58-3.967-0.949-2.916-0.588-3.425-2.723-0.484-3.763z"/>\r
+   <path fill="#191919" d="m165.827 70.54c1.519-0.528 2.818-0.519 5.258 0.984 2.664 1.693 1.448 4.079-0.905 3.497-2.079-0.513-2.06-0.554-3.861-0.915-2.873-0.573-3.373-2.573-0.492-3.566z"/>\r
+   <path fill="#1e1e1e" d="m165.893 70.667c1.482-0.503 2.778-0.484 5.183 0.974 2.564 1.614 1.397 3.846-0.93 3.276-2.067-0.504-1.989-0.529-3.756-0.88-2.826-0.559-3.319-2.425-0.497-3.37z"/>\r
+   <path fill="#232323" d="m165.959 70.793c1.447-0.478 2.74-0.45 5.108 0.964 2.464 1.535 1.345 3.613-0.955 3.055-2.053-0.496-1.917-0.503-3.651-0.846-2.779-0.543-3.264-2.274-0.502-3.173z"/>\r
+   <path fill="#282828" d="m166.025 70.92c1.412-0.453 2.701-0.416 5.034 0.954 2.362 1.456 1.293 3.38-0.981 2.834-2.04-0.487-1.845-0.478-3.545-0.812-2.733-0.528-3.21-2.125-0.508-2.976z"/>\r
+   <path fill="#2d2d2d" d="m166.09 71.047c1.378-0.428 2.663-0.382 4.96 0.943 2.264 1.377 1.242 3.146-1.006 2.613-2.026-0.478-1.773-0.453-3.438-0.777-2.688-0.513-3.158-1.974-0.516-2.779z"/>\r
+   <path fill="#333" d="m166.156 71.173c1.343-0.402 2.624-0.347 4.885 0.933 2.163 1.298 1.191 2.914-1.029 2.392-2.015-0.47-1.703-0.428-3.334-0.743-2.642-0.498-3.104-1.824-0.522-2.582z"/>\r
+   <path fill="#383838" d="m166.222 71.3c1.307-0.377 2.585-0.313 4.81 0.922 2.063 1.219 1.14 2.681-1.055 2.171-2.001-0.461-1.631-0.402-3.229-0.708-2.594-0.483-3.048-1.674-0.526-2.385z"/>\r
+   <path fill="#3d3d3d" d="m166.288 71.427c1.272-0.352 2.546-0.279 4.736 0.913 1.962 1.14 1.088 2.447-1.081 1.95-1.988-0.452-1.56-0.377-3.122-0.674-2.55-0.469-2.995-1.526-0.533-2.189z"/>\r
+   <path fill="#424242" d="m166.354 71.554c1.236-0.327 2.507-0.245 4.661 0.902 1.861 1.061 1.037 2.214-1.106 1.729-1.974-0.444-1.488-0.352-3.016-0.64-2.504-0.453-2.942-1.375-0.539-1.991z"/>\r
+   <path fill="#474747" d="m166.419 71.68c1.203-0.302 2.469-0.21 4.587 0.892 1.762 0.982 0.986 1.98-1.13 1.508-1.962-0.435-1.417-0.326-2.911-0.606-2.458-0.437-2.888-1.224-0.546-1.794z"/>\r
+   <path fill="#4c4c4c" d="m166.485 71.807c1.167-0.276 2.429-0.176 4.513 0.882 1.66 0.903 0.935 1.748-1.156 1.288-1.948-0.426-1.345-0.301-2.805-0.572-2.412-0.423-2.834-1.076-0.552-1.598z"/>\r
+   <path fill="#515151" d="m166.551 71.934c1.133-0.251 2.391-0.142 4.438 0.871 1.56 0.824 0.883 1.515-1.181 1.067-1.936-0.417-1.274-0.275-2.699-0.537-2.366-0.408-2.781-0.926-0.558-1.401z"/>\r
+   <path fill="#565656" d="m166.617 72.061c1.097-0.227 2.351-0.108 4.363 0.861 1.46 0.745 0.831 1.281-1.206 0.846-1.922-0.409-1.202-0.25-2.594-0.503-2.319-0.393-2.726-0.777-0.563-1.204z"/>\r
+   <path fill="#5b5b5b" d="m166.683 72.187c1.062-0.201 2.312-0.073 4.289 0.851 1.358 0.666 0.778 1.048-1.231 0.625-1.91-0.4-1.131-0.225-2.489-0.469-2.274-0.377-2.672-0.626-0.569-1.007z"/>\r
+   <path fill="#606060" d="m166.748 72.314c1.027-0.176 2.274-0.04 4.215 0.84 1.26 0.587 0.729 0.815-1.256 0.404-1.896-0.392-1.06-0.2-2.383-0.435-2.228-0.361-2.619-0.475-0.576-0.809z"/>\r
+   <path fill="#666" d="m166.814 72.44c0.992-0.151 2.234-0.005 4.14 0.83 1.159 0.508 0.677 0.582-1.281 0.183-1.883-0.383-0.987-0.174-2.276-0.4-2.183-0.346-2.566-0.325-0.583-0.613z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#666" d="m159.99 128.249c-9.36 0.36-24.192-25.848-24.552-14.976-0.288 9.216 0.216 9.072 0.216 18 0 5.976-2.736 6.408-8.64 15.408-3.024 4.752-5.4 9.864-7.272 15.048-1.152 3.096-2.232 6.336-3.096 9.504-0.36 1.584-1.008 3.24-1.368 4.824-2.952 10.872-13.464 24.264-15.912 35.136-2.448 10.8-5.328 17.712-4.968 32.185 0.36 14.472 0.504 10.295 4.896 13.896 4.32 3.601 8.784 6.983 15.624 13.032 7.2 6.264 22.177 17.208 24.192 20.592 2.16 3.456 2.088 11.232 0.792 13.752-1.296 2.448-12.6 3.816-12.528 3.816-0.071 0 9.864 13.68 11.809 15.623 1.872 1.873 9.936 10.873 42.768 4.752 18.504-3.455 32.832-13.823 43.2-23.832 13.392-13.031 6.624-16.775 8.352-23.327 2.521-9.433 10.729-12.96 12.601-23.616 0.216-1.512 0.72-2.664 2.088-4.896 2.088-3.168 1.584-9.432 1.584-15.191 0-14.977-1.729-30.24-5.185-41.472-3.168-10.512-8.208-17.856-12.527-27.36-8.641-18.936-8.208-27.432-15.912-39.528-8.784-13.968-4.464-23.256-16.128-22.68-14.546 0.79-26.282 20.734-40.034 21.31z"/>\r
+   <path fill="#6d6d6d" d="m159.973 129.334c-9.281 0.353-23.746-25.511-24.242-15.179-0.316 8.755 0.1 8.678 0.03 17.247-0.15 5.87-2.953 6.637-8.727 15.481-3.013 4.763-5.273 9.812-6.993 14.877-0.968 3.253-1.56 6.422-2.43 9.526-0.415 1.642-1.497 3.187-2.185 5.042-3.254 10.78-13.545 24.182-15.961 34.877-2.466 10.81-5.37 17.694-4.961 32.141 0.366 14 0.395 10.177 4.773 13.816 4.283 3.616 8.839 7.069 15.662 13.103 7.183 6.248 22.237 17.216 24.243 20.588 2.149 3.444 2.131 11.317 0.844 13.823-1.284 2.439-12.579 3.875-12.508 3.875-0.071 0 9.815 13.566 11.757 15.508 1.87 1.87 9.902 10.809 42.678 4.704 18.524-3.455 33.124-13.753 43.078-23.856 12.789-12.762 6.107-16.773 7.826-23.291 2.513-9.416 11.277-12.961 13.143-23.602 0.216-1.508 0.754-2.654 2.113-4.876 2.096-3.202 1.561-9.447 1.582-15.185 0.067-15.027-1.705-30.234-5.159-41.434-3.171-10.483-8.204-17.817-12.515-27.305-8.624-18.906-8.221-27.415-15.933-39.474-8.586-13.613-4.601-22.583-16.011-21.99-14.374 0.826-26.375 21.016-40.104 21.584z"/>\r
+   <path fill="#757575" d="m159.955 130.419c-9.201 0.346-23.299-25.175-23.931-15.383-0.344 8.295-0.017 8.284-0.156 16.494-0.301 5.764-3.17 6.867-8.812 15.555-3.002 4.774-5.148 9.76-6.714 14.706-0.784 3.41-0.889 6.508-1.764 9.548-0.471 1.699-1.986 3.133-3.003 5.259-3.554 10.688-13.624 24.1-16.009 34.619-2.483 10.82-5.411 17.678-4.954 32.097 0.373 13.528 0.285 10.058 4.651 13.739 4.244 3.632 8.893 7.154 15.699 13.171 7.167 6.233 22.299 17.224 24.294 20.585 2.142 3.432 2.175 11.404 0.896 13.896-1.271 2.428-12.558 3.932-12.486 3.932-0.071 0 9.768 13.453 11.705 15.392 1.867 1.867 9.867 10.744 42.588 4.655 18.545-3.453 33.415-13.682 42.956-23.879 12.187-12.492 5.591-16.771 7.3-23.258 2.507-9.398 11.826-12.959 13.687-23.586 0.215-1.5 0.788-2.643 2.138-4.854 2.104-3.235 1.538-9.462 1.58-15.178 0.133-15.076-1.681-30.228-5.135-41.394-3.173-10.455-8.199-17.779-12.501-27.25-8.609-18.877-8.234-27.399-15.952-39.42-8.389-13.258-4.739-21.911-15.895-21.301-14.21 0.859-26.474 21.295-40.182 21.855z"/>\r
+   <path fill="#7c7c7c" d="m159.938 131.504c-9.122 0.338-22.854-24.838-23.622-15.586-0.37 7.833-0.131 7.89-0.341 15.741-0.452 5.657-3.388 7.096-8.899 15.628-2.99 4.785-5.021 9.708-6.433 14.535-0.602 3.566-0.218 6.594-1.099 9.57-0.526 1.756-2.475 3.08-3.82 5.477-3.854 10.596-13.703 24.016-16.057 34.361-2.501 10.829-5.453 17.66-4.948 32.052 0.38 13.059 0.177 9.939 4.529 13.66 4.208 3.648 8.948 7.239 15.739 13.242 7.149 6.217 22.358 17.232 24.345 20.581 2.13 3.42 2.216 11.489 0.946 13.968-1.259 2.417-12.538 3.99-12.466 3.99-0.072 0 9.718 13.34 11.653 15.275 1.865 1.864 9.833 10.681 42.498 4.607 18.565-3.453 33.706-13.609 42.834-23.902 11.583-12.223 5.074-16.771 6.774-23.223 2.499-9.382 12.375-12.959 14.229-23.57 0.215-1.496 0.821-2.633 2.162-4.834 2.111-3.271 1.516-9.478 1.578-15.173 0.199-15.125-1.657-30.221-5.109-41.354-3.177-10.427-8.196-17.741-12.488-27.195-8.594-18.848-8.247-27.383-15.972-39.366-8.192-12.903-4.877-21.239-15.779-20.612-14.041 0.894-26.569 21.576-40.254 22.128z"/>\r
+   <path fill="#848484" d="m159.921 132.589c-9.043 0.331-22.406-24.502-23.312-15.79-0.398 7.373-0.247 7.496-0.527 14.988-0.602 5.551-3.604 7.326-8.984 15.702-2.98 4.796-4.896 9.656-6.154 14.364-0.417 3.723 0.455 6.679-0.432 9.592-0.582 1.813-2.964 3.026-4.639 5.694-4.153 10.504-13.782 23.936-16.104 34.104-2.519 10.838-5.495 17.643-4.941 32.008 0.387 12.586 0.067 9.819 4.407 13.582 4.171 3.664 9.002 7.324 15.777 13.311 7.132 6.201 22.419 17.24 24.396 20.576 2.12 3.41 2.259 11.578 0.998 14.041-1.247 2.408-12.517 4.049-12.446 4.049-0.07 0 9.67 13.227 11.604 15.16 1.861 1.861 9.798 10.615 42.409 4.558 18.584-3.45 33.996-13.538 42.711-23.926 10.979-11.952 4.557-16.769 6.248-23.187 2.491-9.367 12.924-12.959 14.771-23.557 0.215-1.49 0.856-2.622 2.188-4.813 2.118-3.305 1.491-9.494 1.575-15.166 0.267-15.174-1.635-30.215-5.086-41.314-3.179-10.399-8.19-17.703-12.473-27.141-8.579-18.818-8.262-27.366-15.994-39.312-7.993-12.547-5.013-20.565-15.661-19.922-13.876 0.927-26.669 21.855-40.331 22.399z"/>\r
+   <path fill="#8c8c8c" d="m159.903 133.674c-8.963 0.323-21.961-24.165-23.001-15.994-0.426 6.912-0.363 7.102-0.713 14.236-0.753 5.445-3.821 7.554-9.071 15.775-2.969 4.807-4.768 9.604-5.875 14.192-0.232 3.881 1.128 6.766 0.234 9.615-0.638 1.87-3.452 2.972-5.455 5.911-4.455 10.413-13.862 23.853-16.153 33.845-2.537 10.849-5.537 17.625-4.935 31.963 0.393 12.115-0.042 9.701 4.285 13.505 4.133 3.68 9.057 7.409 15.814 13.38 7.116 6.188 22.48 17.248 24.447 20.574 2.109 3.398 2.301 11.662 1.049 14.113-1.235 2.396-12.496 4.104-12.425 4.104-0.071 0 9.622 13.114 11.552 15.045 1.86 1.858 9.763 10.552 42.319 4.509 18.604-3.449 34.288-13.467 42.589-23.949 10.377-11.682 4.04-16.766 5.721-23.15 2.486-9.35 13.474-12.959 15.316-23.542 0.214-1.483 0.89-2.611 2.213-4.793 2.126-3.339 1.468-9.507 1.573-15.158 0.333-15.224-1.611-30.208-5.062-41.276-3.181-10.37-8.186-17.664-12.459-27.085-8.563-18.789-8.275-27.35-16.014-39.258-7.796-12.192-5.151-19.893-15.545-19.233-13.707 0.961-26.763 22.134-40.404 22.671z"/>\r
+   <path fill="#939393" d="m159.886 134.759c-8.885 0.316-21.516-23.829-22.691-16.197-0.454 6.451-0.479 6.708-0.899 13.482-0.903 5.339-4.038 7.784-9.157 15.849-2.957 4.818-4.642 9.552-5.595 14.021-0.05 4.037 1.799 6.852 0.9 9.637-0.693 1.928-3.941 2.919-6.273 6.129-4.756 10.32-13.941 23.77-16.201 33.587-2.555 10.858-5.579 17.608-4.928 31.92 0.399 11.644-0.151 9.581 4.162 13.424 4.096 3.697 9.111 7.494 15.854 13.451 7.099 6.17 22.541 17.256 24.498 20.569 2.1 3.387 2.344 11.75 1.101 14.186-1.223 2.387-12.476 4.163-12.404 4.163-0.071 0 9.573 13.001 11.5 14.929 1.857 1.856 9.729 10.488 42.229 4.461 18.625-3.449 34.579-13.396 42.467-23.973 9.774-11.412 3.523-16.764 5.195-23.115 2.479-9.334 14.022-12.959 15.858-23.527 0.214-1.479 0.924-2.601 2.238-4.772 2.134-3.373 1.445-9.522 1.571-15.151 0.399-15.273-1.587-30.201-5.036-41.237-3.185-10.342-8.184-17.625-12.446-27.03-8.548-18.76-8.288-27.333-16.034-39.204-7.598-11.837-5.289-19.221-15.428-18.544-13.543 0.994-26.863 22.413-40.481 22.942z"/>\r
+   <path fill="#9b9b9b" d="m159.868 135.844c-8.805 0.308-21.068-23.492-22.381-16.401-0.481 5.991-0.594 6.314-1.085 12.73-1.053 5.232-4.253 8.013-9.243 15.922-2.946 4.829-4.515 9.5-5.314 13.85 0.133 4.194 2.471 6.937 1.565 9.658-0.749 1.986-4.43 2.866-7.091 6.347-5.056 10.229-14.021 23.689-16.249 33.329-2.572 10.868-5.621 17.591-4.921 31.876 0.405 11.172-0.261 9.463 4.04 13.346 4.058 3.713 9.166 7.58 15.892 13.521 7.082 6.155 22.601 17.265 24.548 20.567 2.092 3.373 2.388 11.834 1.152 14.256-1.21 2.377-12.454 4.222-12.383 4.222-0.071 0 9.523 12.888 11.45 14.813 1.854 1.854 9.692 10.424 42.138 4.412 18.645-3.447 34.871-13.324 42.345-23.996 9.171-11.143 3.007-16.762 4.669-23.08 2.472-9.317 14.572-12.959 16.401-23.514 0.214-1.473 0.958-2.588 2.265-4.75 2.142-3.408 1.421-9.539 1.568-15.145 0.466-15.324-1.564-30.196-5.012-41.198-3.187-10.313-8.179-17.587-12.433-26.976-8.533-18.73-8.301-27.316-16.054-39.149-7.401-11.482-5.426-18.548-15.313-17.855-13.373 1.029-26.958 22.694-40.554 23.215z"/>\r
+   <path fill="#a3a3a3" d="m159.851 136.929c-8.727 0.301-20.622-23.156-22.071-16.604-0.509 5.529-0.71 5.919-1.271 11.976-1.203 5.126-4.47 8.243-9.328 15.996-2.936 4.84-4.39 9.448-5.036 13.679 0.316 4.351 3.143 7.023 2.231 9.68-0.804 2.043-4.919 2.812-7.908 6.563-5.356 10.137-14.101 23.607-16.298 33.072-2.589 10.877-5.661 17.574-4.913 31.832 0.412 10.699-0.37 9.342 3.918 13.268 4.021 3.729 9.221 7.664 15.93 13.59 7.064 6.139 22.661 17.271 24.599 20.563 2.081 3.363 2.43 11.922 1.204 14.33-1.198 2.365-12.434 4.278-12.363 4.278-0.07 0 9.477 12.774 11.399 14.697 1.851 1.851 9.659 10.36 42.048 4.364 18.666-3.447 35.162-13.254 42.223-24.021 8.568-10.873 2.49-16.761 4.144-23.045 2.464-9.301 15.121-12.958 16.943-23.498 0.215-1.467 0.992-2.579 2.29-4.729 2.148-3.441 1.398-9.553 1.566-15.139 0.532-15.373-1.541-30.189-4.987-41.158-3.188-10.285-8.174-17.549-12.419-26.921-8.518-18.701-8.313-27.3-16.073-39.096-7.204-11.126-5.564-17.875-15.196-17.165-13.21 1.064-27.058 22.975-40.632 23.488z"/>\r
+   <path fill="#aaa" d="m159.834 138.014c-8.646 0.293-20.176-22.819-21.761-16.808-0.536 5.069-0.826 5.526-1.457 11.224-1.354 5.02-4.687 8.472-9.416 16.069-2.924 4.851-4.262 9.396-4.756 13.508 0.501 4.507 3.814 7.109 2.897 9.702-0.858 2.1-5.406 2.759-8.725 6.782-5.657 10.045-14.181 23.524-16.347 32.812-2.606 10.888-5.703 17.557-4.906 31.787 0.418 10.229-0.479 9.225 3.795 13.189 3.984 3.745 9.275 7.749 15.968 13.66 7.048 6.124 22.723 17.279 24.651 20.559 2.07 3.352 2.472 12.008 1.255 14.402-1.186 2.355-12.414 4.337-12.343 4.337-0.071 0 9.428 12.66 11.348 14.581 1.85 1.848 9.624 10.297 41.958 4.314 18.687-3.444 35.453-13.18 42.102-24.043 7.965-10.602 1.973-16.758 3.616-23.01 2.457-9.283 15.67-12.957 17.487-23.482 0.214-1.461 1.026-2.568 2.315-4.709 2.155-3.477 1.375-9.568 1.563-15.131 0.6-15.424-1.518-30.184-4.963-41.119-3.192-10.257-8.17-17.511-12.405-26.866-8.502-18.672-8.328-27.284-16.095-39.042-7.005-10.771-5.701-17.203-15.078-16.476-13.04 1.098-27.152 23.255-40.703 23.76z"/>\r
+   <path fill="#b2b2b2" d="m159.816 139.099c-8.567 0.286-19.729-22.483-21.45-17.012-0.563 4.608-0.942 5.132-1.643 10.471-1.506 4.914-4.904 8.701-9.502 16.143-2.913 4.862-4.137 9.344-4.477 13.336 0.685 4.665 4.486 7.195 3.564 9.725-0.915 2.157-5.897 2.705-9.543 6.999-5.958 9.953-14.262 23.443-16.396 32.554-2.624 10.898-5.745 17.54-4.9 31.744 0.426 9.757-0.588 9.105 3.674 13.111 3.945 3.761 9.33 7.834 16.006 13.729 7.032 6.109 22.783 17.288 24.702 20.557 2.06 3.338 2.515 12.094 1.306 14.473-1.173 2.346-12.392 4.395-12.321 4.395-0.07 0 9.379 12.549 11.296 14.465 1.847 1.848 9.591 10.234 41.868 4.268 18.706-3.444 35.745-13.11 41.979-24.066 7.361-10.332 1.456-16.757 3.091-22.974 2.45-9.269 16.219-12.958 18.03-23.47 0.213-1.455 1.06-2.557 2.34-4.688 2.164-3.509 1.352-9.583 1.562-15.124 0.665-15.473-1.494-30.177-4.938-41.08-3.195-10.228-8.166-17.472-12.393-26.811-8.486-18.642-8.341-27.267-16.114-38.987-6.809-10.416-5.838-16.531-14.962-15.787-12.873 1.129-27.25 23.531-40.779 24.029z"/>\r
+   <path fill="#bababa" d="m159.799 140.184c-8.487 0.279-19.282-22.146-21.141-17.215-0.591 4.147-1.057 4.737-1.828 9.717-1.656 4.808-5.121 8.931-9.588 16.217-2.902 4.873-4.01 9.292-4.197 13.165 0.868 4.822 5.158 7.281 4.23 9.747-0.971 2.215-6.385 2.651-10.361 7.216-6.258 9.861-14.339 23.36-16.442 32.297-2.643 10.906-5.787 17.521-4.894 31.699 0.432 9.285-0.697 8.986 3.552 13.032 3.908 3.776 9.384 7.919 16.043 13.799 7.016 6.093 22.845 17.296 24.753 20.552 2.051 3.328 2.559 12.18 1.358 14.547-1.161 2.334-12.372 4.451-12.301 4.451-0.071 0 9.33 12.436 11.245 14.35 1.844 1.844 9.555 10.17 41.777 4.219 18.727-3.443 36.036-13.039 41.857-24.09 6.759-10.063 0.939-16.756 2.565-22.939 2.442-9.25 16.768-12.957 18.572-23.453 0.213-1.451 1.095-2.547 2.365-4.668 2.171-3.543 1.329-9.599 1.56-15.117 0.732-15.522-1.471-30.172-4.913-41.042-3.197-10.2-8.161-17.433-12.379-26.756-8.471-18.612-8.354-27.25-16.135-38.933-6.609-10.061-5.976-15.858-14.845-15.098-12.706 1.165-27.347 23.813-40.853 24.303z"/>\r
+   <path fill="#c1c1c1" d="m159.781 141.269c-8.408 0.271-18.837-21.81-20.83-17.419-0.619 3.687-1.173 4.344-2.014 8.965-1.808 4.701-5.338 9.16-9.674 16.29-2.892 4.884-3.885 9.24-3.918 12.994 1.052 4.978 5.829 7.367 4.896 9.769-1.026 2.272-6.874 2.598-11.178 7.434-6.56 9.769-14.419 23.277-16.491 32.039-2.66 10.916-5.829 17.504-4.887 31.656 0.438 8.813-0.807 8.867 3.43 12.953 3.87 3.793 9.438 8.004 16.082 13.868 6.997 6.077 22.904 17.304 24.803 20.55 2.041 3.314 2.601 12.266 1.409 14.617-1.149 2.324-12.351 4.51-12.28 4.51-0.07 0 9.282 12.321 11.194 14.233 1.841 1.842 9.521 10.106 41.688 4.17 18.746-3.44 36.326-12.967 41.734-24.112 6.156-9.793 0.423-16.754 2.038-22.904 2.438-9.235 17.318-12.957 19.117-23.438 0.212-1.444 1.128-2.536 2.39-4.647 2.18-3.578 1.306-9.613 1.558-15.11 0.799-15.571-1.447-30.165-4.889-41.002-3.2-10.172-8.156-17.395-12.364-26.701-8.456-18.583-8.367-27.234-16.155-38.88-6.413-9.705-6.114-15.185-14.729-14.408-12.541 1.197-27.445 24.091-40.93 24.573z"/>\r
+   <path fill="#c9c9c9" d="m159.764 142.354c-8.329 0.264-18.392-21.473-20.521-17.622-0.646 3.225-1.289 3.949-2.2 8.211-1.957 4.596-5.555 9.39-9.761 16.364-2.879 4.895-3.757 9.188-3.638 12.823 1.235 5.135 6.502 7.453 5.562 9.791-1.081 2.329-7.362 2.544-11.995 7.651-6.859 9.677-14.499 23.195-16.54 31.78-2.677 10.927-5.87 17.488-4.879 31.611 0.444 8.344-0.916 8.748 3.307 12.875 3.834 3.81 9.492 8.09 16.121 13.939 6.98 6.061 22.965 17.311 24.854 20.545 2.031 3.303 2.643 12.352 1.461 14.69-1.137 2.313-12.33 4.567-12.26 4.567-0.07 0 9.233 12.209 11.143 14.117 1.839 1.84 9.486 10.043 41.599 4.122 18.767-3.44 36.618-12.896 41.612-24.137 5.554-9.522-0.094-16.751 1.513-22.868 2.43-9.219 17.866-12.957 19.659-23.424 0.213-1.439 1.162-2.525 2.415-4.627 2.188-3.612 1.282-9.629 1.556-15.104 0.865-15.621-1.424-30.158-4.864-40.962-3.202-10.144-8.153-17.357-12.351-26.646-8.441-18.554-8.381-27.218-16.176-38.826-6.216-9.35-6.251-14.513-14.612-13.719-12.374 1.235-27.543 24.375-41.005 24.849z"/>\r
+   <path fill="#d1d1d1" d="m159.747 143.439c-8.25 0.256-17.944-21.137-20.21-17.826-0.675 2.765-1.406 3.555-2.386 7.459-2.108 4.489-5.772 9.619-9.847 16.437-2.869 4.906-3.631 9.136-3.358 12.652 1.419 5.292 7.174 7.538 6.228 9.812-1.137 2.387-7.852 2.491-12.813 7.869-7.161 9.586-14.579 23.114-16.588 31.522-2.695 10.938-5.912 17.471-4.873 31.568 0.451 7.871-1.025 8.629 3.185 12.797 3.796 3.824 9.547 8.174 16.158 14.008 6.964 6.047 23.026 17.32 24.905 20.541 2.021 3.292 2.686 12.439 1.513 14.764-1.125 2.303-12.31 4.625-12.239 4.625-0.07 0 9.186 12.094 11.092 14.002 1.836 1.836 9.45 9.978 41.509 4.072 18.786-3.439 36.909-12.824 41.49-24.16 4.948-9.252-0.611-16.748 0.985-22.832 2.423-9.203 18.415-12.957 20.203-23.41 0.212-1.434 1.196-2.514 2.44-4.605 2.193-3.646 1.259-9.645 1.553-15.098 0.932-15.67-1.4-30.151-4.84-40.922-3.205-10.115-8.148-17.319-12.336-26.592-8.427-18.524-8.396-27.201-16.197-38.771-6.017-8.995-6.388-13.84-14.495-13.03-12.207 1.266-27.64 24.652-41.079 25.118z"/>\r
+   <path fill="#d8d8d8" d="m159.729 144.524c-8.17 0.249-17.498-20.8-19.9-18.03-0.702 2.304-1.521 3.162-2.571 6.706-2.259 4.383-5.988 9.848-9.933 16.511-2.858 4.917-3.504 9.084-3.079 12.48 1.604 5.449 7.846 7.625 6.895 9.835-1.193 2.444-8.342 2.438-13.631 8.087-7.461 9.493-14.658 23.031-16.637 31.262-2.712 10.947-5.953 17.455-4.865 31.524 0.458 7.399-1.135 8.511 3.063 12.718 3.758 3.842 9.601 8.26 16.196 14.078 6.946 6.031 23.087 17.328 24.956 20.538 2.011 3.28 2.729 12.524 1.563 14.835-1.112 2.293-12.289 4.684-12.218 4.684-0.071 0 9.136 11.981 11.04 13.886 1.834 1.834 9.417 9.913 41.419 4.024 18.807-3.438 37.2-12.752 41.368-24.184 4.346-8.982-1.128-16.747 0.46-22.798 2.416-9.187 18.964-12.956 20.746-23.394 0.211-1.429 1.229-2.504 2.465-4.586 2.202-3.681 1.236-9.658 1.551-15.091 0.998-15.72-1.377-30.146-4.814-40.884-3.208-10.086-8.145-17.28-12.323-26.536-8.411-18.495-8.408-27.185-16.217-38.717-5.82-8.64-6.526-13.168-14.38-12.341-12.04 1.303-27.736 24.934-41.154 25.393z"/>\r
+   <path fill="#e0e0e0" d="m159.712 145.609c-8.091 0.241-17.052-20.464-19.59-18.233-0.729 1.843-1.637 2.767-2.757 5.953-2.409 4.276-6.206 10.077-10.02 16.584-2.847 4.928-3.378 9.032-2.8 12.309 1.787 5.606 8.519 7.711 7.561 9.857-1.248 2.502-8.829 2.384-14.448 8.304-7.761 9.402-14.738 22.95-16.684 31.006-2.731 10.955-5.996 17.436-4.859 31.48 0.464 6.928-1.244 8.389 2.939 12.639 3.722 3.857 9.656 8.344 16.234 14.148 6.932 6.014 23.148 17.336 25.008 20.533 2 3.268 2.771 12.611 1.615 14.907-1.1 2.282-12.268 4.741-12.198 4.741-0.069 0 9.089 11.867 10.989 13.77 1.831 1.831 9.382 9.85 41.329 3.977 18.827-3.438 37.492-12.683 41.246-24.207 3.743-8.715-1.646-16.746-0.066-22.762 2.409-9.171 19.514-12.957 21.289-23.381 0.211-1.422 1.265-2.494 2.49-4.564 2.21-3.715 1.213-9.674 1.549-15.084 1.065-15.77-1.354-30.139-4.791-40.844-3.21-10.058-8.14-17.241-12.309-26.481-8.396-18.466-8.421-27.168-16.237-38.664-5.622-8.284-6.663-12.495-14.262-11.651-11.872 1.335-27.833 25.212-41.228 25.663z"/>\r
+   <path fill="#e8e8e8" d="m159.694 146.694c-8.012 0.234-16.605-20.127-19.279-18.437-0.757 1.383-1.753 2.373-2.943 5.2-2.56 4.171-6.423 10.307-10.105 16.658-2.835 4.939-3.251 8.979-2.52 12.138 1.97 5.763 9.189 7.796 8.226 9.879-1.303 2.559-9.318 2.33-15.265 8.521-8.063 9.31-14.818 22.867-16.733 30.748-2.748 10.967-6.037 17.419-4.853 31.436 0.472 6.457-1.353 8.271 2.818 12.562 3.685 3.873 9.711 8.429 16.273 14.218 6.913 6 23.207 17.344 25.058 20.529 1.991 3.257 2.814 12.697 1.666 14.98-1.087 2.271-12.247 4.799-12.177 4.799-0.07 0 9.04 11.755 10.938 13.654 1.829 1.828 9.349 9.785 41.239 3.926 18.847-3.435 37.783-12.609 41.124-24.229 3.14-8.444-2.161-16.743-0.592-22.728 2.401-9.152 20.062-12.955 21.831-23.364 0.211-1.417 1.298-2.483 2.516-4.544 2.217-3.748 1.19-9.689 1.547-15.076 1.132-15.82-1.331-30.133-4.766-40.806-3.213-10.03-8.136-17.203-12.296-26.427-8.38-18.436-8.435-27.151-16.257-38.609-5.425-7.929-6.802-11.822-14.146-10.962-11.706 1.368-27.931 25.491-41.304 25.934z"/>\r
+   <path fill="#efefef" d="m159.677 147.779c-7.934 0.226-16.16-19.791-18.97-18.64-0.785 0.921-1.869 1.979-3.13 4.447-2.71 4.064-6.639 10.536-10.19 16.731-2.824 4.95-3.125 8.928-2.24 11.967 2.152 5.919 9.86 7.882 8.892 9.901-1.358 2.616-9.808 2.277-16.083 8.739-8.363 9.218-14.896 22.784-16.781 30.489-2.766 10.977-6.079 17.402-4.846 31.393 0.478 5.984-1.462 8.152 2.696 12.482 3.646 3.889 9.765 8.514 16.311 14.287 6.896 5.983 23.269 17.352 25.109 20.526 1.98 3.245 2.855 12.782 1.718 15.052-1.076 2.262-12.227 4.857-12.156 4.857-0.07 0 8.991 11.641 10.887 13.537 1.826 1.826 9.313 9.723 41.148 3.879 18.868-3.434 38.074-12.538 41.002-24.254 2.537-8.174-2.678-16.741-1.119-22.69 2.396-9.138 20.612-12.957 22.375-23.351 0.212-1.412 1.332-2.473 2.541-4.523 2.226-3.783 1.166-9.704 1.545-15.07 1.197-15.869-1.307-30.125-4.741-40.766-3.215-10.002-8.131-17.165-12.282-26.372-8.365-18.407-8.447-27.135-16.277-38.555-5.228-7.574-6.938-11.15-14.029-10.272-11.541 1.402-28.029 25.771-41.38 26.206z"/>\r
+   <path fill="#f7f7f7" d="m159.66 148.864c-7.854 0.219-15.714-19.454-18.66-18.844-0.812 0.461-1.983 1.585-3.314 3.694-2.86 3.958-6.856 10.766-10.278 16.805-2.813 4.961-2.998 8.876-1.96 11.796 2.337 6.076 10.533 7.968 9.558 9.923-1.415 2.673-10.296 2.223-16.899 8.956-8.664 9.126-14.978 22.702-16.83 30.23-2.783 10.986-6.121 17.386-4.839 31.349 0.484 5.515-1.571 8.033 2.573 12.403 3.609 3.906 9.82 8.6 16.35 14.357 6.88 5.969 23.329 17.36 25.16 20.523 1.971 3.232 2.898 12.869 1.77 15.124-1.063 2.252-12.206 4.915-12.136 4.915-0.07 0 8.942 11.527 10.835 13.422 1.824 1.822 9.279 9.658 41.059 3.83 18.889-3.434 38.366-12.467 40.881-24.278 1.934-7.903-3.195-16.739-1.646-22.655 2.388-9.121 21.161-12.955 22.918-23.336 0.211-1.404 1.366-2.461 2.566-4.502 2.232-3.816 1.143-9.719 1.542-15.063 1.265-15.92-1.283-30.12-4.717-40.727-3.219-9.974-8.128-17.127-12.269-26.317-8.349-18.378-8.461-27.119-16.298-38.501-5.029-7.219-7.075-10.478-13.912-9.584-11.373 1.438-28.126 26.053-41.454 26.48z"/>\r
+   <path fill="#fff" d="m159.642 149.949c-7.774 0.211-15.268-19.118-18.35-19.048-0.84 0-2.1 1.191-3.501 2.941-3.011 3.852-7.072 10.995-10.363 16.878-2.803 4.972-2.872 8.824-1.682 11.625 2.521 6.233 11.205 8.054 10.225 9.945-1.471 2.731-10.785 2.17-17.719 9.174-8.964 9.034-15.056 22.621-16.877 29.973-2.801 10.995-6.163 17.368-4.832 31.304 0.49 5.043-1.681 7.914 2.451 12.325 3.571 3.923 9.874 8.685 16.387 14.427 6.863 5.953 23.391 17.368 25.211 20.521 1.962 3.221 2.942 12.954 1.821 15.196-1.051 2.24-12.185 4.972-12.115 4.972-0.069 0 8.895 11.416 10.784 13.307 1.821 1.82 9.244 9.595 40.97 3.781 18.907-3.431 38.656-12.396 40.758-24.302 1.331-7.633-3.712-16.736-2.171-22.619 2.381-9.104 21.71-12.956 23.461-23.321 0.21-1.399 1.399-2.45 2.591-4.481 2.24-3.852 1.12-9.734 1.54-15.057 1.331-15.968-1.26-30.113-4.692-40.688-3.221-9.945-8.123-17.088-12.255-26.262-8.334-18.348-8.474-27.102-16.318-38.447-4.832-6.863-7.213-9.805-13.796-8.894-11.205 1.469-28.222 26.33-41.528 26.75z"/>\r
+  </g>\r
+  <path fill="#995900" d="m152.553 88.8575c5.256-0.648 12.456 0.648 15.769 3.096 3.096 2.304 5.256 3.528 8.063 4.464 9.433 3.096 21.816 4.536 21.24 13.032-0.648 10.151-3.6 14.688-12.024 17.351-6.768 2.088-18.863 13.824-28.224 13.824-4.176 0-10.008 0.216-13.392-1.008-3.24-1.152-7.776-6.624-13.104-11.016-5.328-4.32-10.296-8.928-10.439-14.976-0.217-6.407 3.96-8.496 9.863-13.607 3.097-2.736 8.712-7.272 12.601-9.288 3.599-1.799 5.903-1.439 9.647-1.872z"/>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#9e5f00" d="m165.068 78.951c5.225-0.644 12.384 0.645 15.677 3.079 3.078 2.29 5.227 3.51 8.018 4.438 9.375 3.078 21.729 4.529 21.159 12.973-0.641 10.09-3.669 14.581-12.041 17.223-6.723 2.073-18.768 13.589-28.07 13.64-4.21 0.032-9.926 0.234-13.287-0.977-3.215-1.142-7.737-6.608-13.031-10.969-5.291-4.292-10.26-8.774-10.317-14.765-0.153-6.252 3.912-8.411 9.773-13.488 3.071-2.71 8.594-7.303 12.463-9.333 3.563-1.803 5.933-1.392 9.656-1.821z"/>\r
+   <path fill="#a36400" d="m165.177 79.044c5.195-0.641 12.313 0.64 15.587 3.06 3.06 2.278 5.194 3.494 7.971 4.413 9.317 3.06 21.641 4.522 21.078 12.914-0.634 10.027-3.737 14.474-12.058 17.094-6.678 2.057-18.673 13.352-27.919 13.454-4.241 0.064-9.842 0.252-13.18-0.945-3.19-1.133-7.7-6.592-12.96-10.921-5.254-4.264-10.222-8.622-10.192-14.555-0.093-6.099 3.863-8.329 9.681-13.369 3.048-2.685 8.478-7.335 12.328-9.379 3.526-1.804 5.963-1.338 9.664-1.766z"/>\r
+   <path fill="#a86a00" d="m165.287 79.138c5.165-0.637 12.241 0.637 15.496 3.043 3.042 2.264 5.165 3.476 7.924 4.387 9.26 3.042 21.556 4.515 20.998 12.854-0.627 9.968-3.805 14.368-12.074 16.967-6.633 2.042-18.576 13.117-27.766 13.27-4.276 0.096-9.759 0.27-13.075-0.914-3.165-1.123-7.661-6.577-12.887-10.874-5.217-4.236-10.187-8.468-10.069-14.345-0.03-5.943 3.815-8.244 9.589-13.249 3.023-2.66 8.36-7.366 12.191-9.424 3.49-1.808 5.993-1.291 9.673-1.715z"/>\r
+   <path fill="#ad7000" d="m165.396 79.23c5.135-0.633 12.17 0.633 15.404 3.025 3.025 2.251 5.137 3.46 7.88 4.361 9.201 3.025 21.467 4.508 20.917 12.796-0.62 9.905-3.874 14.26-12.093 16.837-6.586 2.027-18.479 12.882-27.611 13.086-4.311 0.127-9.677 0.287-12.971-0.883-3.14-1.113-7.622-6.561-12.814-10.826-5.18-4.208-10.148-8.315-9.945-14.135 0.031-5.789 3.768-8.16 9.497-13.129 2.999-2.635 8.244-7.398 12.055-9.47 3.454-1.808 6.023-1.24 9.681-1.662z"/>\r
+   <path fill="#b27600" d="m165.506 79.325c5.105-0.63 12.099 0.629 15.314 3.007 3.007 2.237 5.104 3.442 7.832 4.335 9.145 3.007 21.38 4.501 20.837 12.737-0.614 9.844-3.943 14.154-12.109 16.709-6.541 2.011-18.385 12.645-27.46 12.9-4.342 0.16-9.592 0.306-12.862-0.851-3.115-1.103-7.584-6.545-12.743-10.779-5.144-4.18-10.112-8.162-9.821-13.924 0.092-5.634 3.718-8.076 9.405-13.009 2.975-2.609 8.126-7.429 11.919-9.514 3.416-1.812 6.052-1.192 9.688-1.611z"/>\r
+   <path fill="#b77b00" d="m165.615 79.417c5.075-0.626 12.026 0.626 15.224 2.989 2.989 2.225 5.075 3.425 7.786 4.31 9.087 2.989 21.292 4.494 20.756 12.678-0.606 9.781-4.012 14.046-12.126 16.581-6.496 1.997-18.289 12.41-27.307 12.716-4.376 0.191-9.51 0.323-12.758-0.82-3.09-1.094-7.546-6.53-12.671-10.732-5.106-4.152-10.074-8.008-9.697-13.713 0.155-5.479 3.67-7.992 9.313-12.889 2.951-2.585 8.011-7.461 11.783-9.56 3.38-1.814 6.083-1.143 9.697-1.56z"/>\r
+   <path fill="#bc8100" d="m165.725 79.511c5.044-0.622 11.954 0.622 15.133 2.972 2.971 2.211 5.045 3.408 7.739 4.284 9.029 2.971 21.205 4.487 20.675 12.619-0.6 9.719-4.079 13.939-12.143 16.451-6.45 1.982-18.192 12.175-27.153 12.532-4.41 0.223-9.428 0.341-12.653-0.789-3.065-1.084-7.507-6.514-12.598-10.684-5.069-4.124-10.038-7.855-9.574-13.504 0.217-5.324 3.622-7.908 9.222-12.77 2.926-2.559 7.894-7.492 11.646-9.605 3.344-1.816 6.113-1.092 9.706-1.506z"/>\r
+   <path fill="#c18700" d="m165.834 79.604c5.015-0.618 11.883 0.619 15.043 2.954 2.953 2.198 5.015 3.391 7.693 4.259 8.972 2.953 21.118 4.48 20.594 12.559-0.593 9.66-4.147 13.833-12.159 16.324-6.405 1.967-18.098 11.94-27.002 12.347-4.441 0.255-9.343 0.359-12.546-0.757-3.04-1.074-7.469-6.498-12.526-10.637-5.032-4.096-10-7.701-9.45-13.293 0.278-5.169 3.574-7.823 9.13-12.649 2.903-2.534 7.776-7.524 11.511-9.651 3.306-1.821 6.141-1.044 9.712-1.456z"/>\r
+   <path fill="#c68d00" d="m165.944 79.697c4.984-0.615 11.811 0.614 14.952 2.936 2.935 2.184 4.983 3.374 7.646 4.233 8.915 2.935 21.031 4.473 20.515 12.5-0.586 9.597-4.218 13.726-12.177 16.195-6.36 1.951-18.002 11.703-26.849 12.162-4.476 0.287-9.261 0.377-12.441-0.726-3.015-1.064-7.431-6.482-12.453-10.589-4.995-4.068-9.965-7.549-9.326-13.083 0.34-5.015 3.524-7.741 9.038-12.531 2.878-2.508 7.658-7.555 11.374-9.696 3.269-1.82 6.171-0.992 9.721-1.401z"/>\r
+   <path fill="#cc9200" d="m166.054 79.791c4.952-0.61 11.738 0.611 14.86 2.918 2.918 2.172 4.954 3.357 7.601 4.207 8.857 2.918 20.942 4.466 20.432 12.442-0.578 9.536-4.285 13.62-12.192 16.066-6.314 1.936-17.906 11.468-26.696 11.978-4.509 0.319-9.178 0.394-12.335-0.696-2.989-1.054-7.393-6.466-12.382-10.541-4.959-4.04-9.928-7.395-9.202-12.873 0.401-4.859 3.477-7.655 8.945-12.411 2.854-2.482 7.542-7.586 11.239-9.741 3.233-1.824 6.201-0.943 9.73-1.349z"/>\r
+   <path fill="#d19800" d="m166.163 79.883c4.923-0.606 11.668 0.608 14.771 2.901 2.9 2.158 4.924 3.339 7.554 4.181 8.801 2.9 20.855 4.459 20.352 12.383-0.571 9.474-4.353 13.512-12.21 15.938-6.269 1.921-17.81 11.233-26.543 11.793-4.542 0.351-9.094 0.413-12.229-0.664-2.965-1.044-7.354-6.45-12.311-10.494-4.921-4.012-9.89-7.241-9.079-12.662 0.465-4.705 3.431-7.571 8.855-12.29 2.83-2.458 7.425-7.618 11.102-9.787 3.197-1.827 6.231-0.893 9.738-1.299z"/>\r
+   <path fill="#d69e00" d="m166.273 79.978c4.893-0.603 11.596 0.603 14.679 2.882 2.883 2.145 4.895 3.323 7.507 4.156 8.744 2.882 20.77 4.452 20.272 12.324-0.565 9.412-4.422 13.406-12.228 15.81-6.224 1.905-17.714 10.996-26.39 11.608-4.576 0.383-9.012 0.431-12.124-0.633-2.94-1.034-7.316-6.434-12.237-10.446-4.884-3.984-9.854-7.089-8.955-12.452 0.525-4.551 3.382-7.489 8.764-12.171 2.805-2.432 7.307-7.649 10.965-9.832 3.16-1.829 6.261-0.845 9.747-1.246z"/>\r
+   <path fill="#dba300" d="m166.382 80.07c4.863-0.599 11.525 0.6 14.59 2.865 2.864 2.131 4.862 3.305 7.461 4.13 8.686 2.864 20.682 4.445 20.19 12.264-0.559 9.352-4.491 13.299-12.244 15.681-6.179 1.89-17.619 10.761-26.237 11.423-4.608 0.415-8.929 0.449-12.018-0.601-2.915-1.024-7.277-6.418-12.166-10.399-4.847-3.956-9.815-6.935-8.831-12.241 0.587-4.396 3.333-7.404 8.671-12.051 2.782-2.407 7.191-7.681 10.83-9.878 3.123-1.829 6.29-0.793 9.754-1.193z"/>\r
+   <path fill="#e0a900" d="m166.492 80.164c4.832-0.595 11.453 0.596 14.498 2.847 2.847 2.118 4.833 3.289 7.414 4.104 8.629 2.846 20.595 4.438 20.111 12.205-0.553 9.29-4.56 13.193-12.262 15.553-6.134 1.875-17.522 10.526-26.085 11.239-4.642 0.447-8.845 0.467-11.912-0.57-2.89-1.015-7.238-6.402-12.093-10.351-4.81-3.928-9.78-6.782-8.708-12.032 0.649-4.241 3.285-7.32 8.58-11.932 2.757-2.381 7.073-7.712 10.693-9.923 3.088-1.831 6.321-0.743 9.764-1.14z"/>\r
+   <path fill="#e5af00" d="m166.601 80.257c4.803-0.592 11.382 0.592 14.407 2.829 2.829 2.105 4.804 3.271 7.368 4.079 8.571 2.828 20.507 4.431 20.029 12.146-0.544 9.228-4.627 13.085-12.277 15.423-6.089 1.861-17.427 10.29-25.932 11.055-4.676 0.478-8.763 0.484-11.807-0.539-2.865-1.005-7.2-6.387-12.021-10.304-4.772-3.9-9.742-6.629-8.583-11.821 0.711-4.085 3.236-7.236 8.487-11.812 2.732-2.357 6.957-7.744 10.557-9.968 3.052-1.834 6.351-0.694 9.772-1.088z"/>\r
+   <path fill="#eab500" d="m166.711 80.351c4.772-0.588 11.31 0.589 14.317 2.811 2.811 2.092 4.771 3.254 7.321 4.054 8.514 2.81 20.42 4.424 19.948 12.087-0.538 9.165-4.695 12.979-12.294 15.295-6.044 1.845-17.332 10.054-25.779 10.869-4.708 0.511-8.68 0.503-11.7-0.507-2.84-0.995-7.163-6.371-11.949-10.257-4.736-3.872-9.706-6.475-8.46-11.61 0.773-3.931 3.188-7.152 8.396-11.692 2.709-2.331 6.839-7.775 10.421-10.013 3.013-1.839 6.38-0.645 9.779-1.037z"/>\r
+   <path fill="#efba00" d="m166.82 80.443c4.742-0.584 11.238 0.585 14.226 2.794 2.794 2.078 4.743 3.237 7.276 4.027 8.456 2.793 20.332 4.417 19.868 12.029-0.531 9.104-4.766 12.872-12.313 15.167-5.997 1.83-17.234 9.819-25.626 10.685-4.742 0.542-8.596 0.52-11.595-0.476-2.815-0.985-7.124-6.355-11.877-10.209-4.699-3.844-9.668-6.322-8.336-11.4 0.835-3.778 3.14-7.068 8.304-11.573 2.686-2.306 6.724-7.807 10.285-10.059 2.978-1.84 6.411-0.595 9.788-0.985z"/>\r
+   <path fill="#f4c000" d="m166.93 80.537c4.711-0.58 11.166 0.582 14.135 2.776 2.775 2.066 4.713 3.22 7.229 4.002 8.399 2.775 20.246 4.41 19.787 11.969-0.522 9.043-4.832 12.765-12.328 15.039-5.952 1.815-17.139 9.584-25.473 10.501-4.776 0.574-8.513 0.538-11.49-0.445-2.79-0.976-7.085-6.34-11.804-10.162-4.662-3.816-9.632-6.168-8.213-11.189 0.896-3.623 3.092-6.984 8.213-11.454 2.66-2.281 6.604-7.838 10.147-10.104 2.942-1.844 6.441-0.547 9.797-0.933z"/>\r
+   <path fill="#f9c600" d="m167.039 80.63c4.683-0.577 11.095 0.577 14.045 2.758 2.758 2.052 4.683 3.203 7.184 3.976 8.341 2.757 20.157 4.403 19.706 11.91-0.518 8.981-4.901 12.659-12.346 14.911-5.906 1.799-17.044 9.347-25.32 10.315-4.809 0.606-8.431 0.556-11.384-0.413-2.765-0.966-7.048-6.324-11.732-10.114-4.625-3.788-9.594-6.016-8.088-10.98 0.958-3.467 3.043-6.9 8.12-11.333 2.637-2.256 6.488-7.87 10.013-10.15 2.902-1.844 6.468-0.495 9.802-0.88z"/>\r
+  </g>\r
+  <path fill="#fc0" d="m154.744 90.7245c4.65-0.573 11.022 0.574 13.954 2.74 2.739 2.039 4.651 3.186 7.136 3.951 8.284 2.739 20.071 4.396 19.626 11.851-0.51 8.919-4.97 12.551-12.362 14.781-5.861 1.784-16.947 9.112-25.168 10.131-4.842 0.638-8.347 0.574-11.277-0.382-2.74-0.956-7.01-6.308-11.66-10.067-4.588-3.76-9.559-5.862-7.965-10.769 1.02-3.313 2.995-6.816 8.028-11.213 2.612-2.23 6.371-7.901 9.876-10.195 2.867-1.847 6.499-0.447 9.812-0.828z"/>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m167.982 83.609c1.008 2.088 3.6 2.376 5.328 3.312 1.655 0.936 2.592 1.152 3.239 0.792 1.44-0.792 0.36-3.384-1.079-4.32-1.368-0.935-8.064-1.151-7.488 0.216z"/>\r
+   <path fill="#f9c600" d="m168.125 83.631c0.982 2.035 3.508 2.316 5.193 3.229 1.614 0.912 2.526 1.123 3.158 0.771 1.402-0.771 0.35-3.298-1.054-4.21-1.332-0.913-7.859-1.123-7.297 0.21z"/>\r
+   <path fill="#f4c000" d="m168.267 83.653c0.957 1.982 3.418 2.255 5.058 3.144 1.572 0.889 2.461 1.094 3.076 0.752 1.367-0.752 0.342-3.213-1.025-4.101-1.299-0.889-7.656-1.094-7.109 0.205z"/>\r
+   <path fill="#efba00" d="m168.409 83.674c0.932 1.929 3.327 2.195 4.924 3.06 1.53 0.865 2.395 1.064 2.993 0.732 1.331-0.732 0.333-3.127-0.998-3.992-1.264-0.864-7.451-1.064-6.919 0.2z"/>\r
+   <path fill="#eab500" d="m168.552 83.696c0.905 1.876 3.234 2.135 4.787 2.977 1.488 0.841 2.329 1.035 2.912 0.711 1.294-0.711 0.323-3.041-0.971-3.882-1.228-0.841-7.246-1.036-6.728 0.194z"/>\r
+   <path fill="#e5af00" d="m168.694 83.718c0.881 1.823 3.144 2.075 4.653 2.892 1.446 0.818 2.264 1.006 2.83 0.692 1.257-0.692 0.313-2.956-0.943-3.773-1.195-0.818-7.043-1.007-6.54 0.189z"/>\r
+   <path fill="#e0a900" d="m168.837 83.739c0.855 1.771 3.053 2.015 4.519 2.809 1.403 0.793 2.198 0.977 2.747 0.671 1.221-0.671 0.306-2.87-0.916-3.664-1.161-0.793-6.839-0.976-6.35 0.184z"/>\r
+   <path fill="#dba300" d="m168.979 83.761c0.829 1.718 2.962 1.955 4.383 2.725 1.363 0.77 2.132 0.948 2.666 0.651 1.184-0.651 0.296-2.784-0.889-3.554-1.125-0.77-6.634-0.948-6.16 0.178z"/>\r
+   <path fill="#d69e00" d="m169.121 83.782c0.804 1.665 2.871 1.895 4.249 2.641 1.32 0.747 2.066 0.918 2.583 0.631 1.148-0.631 0.287-2.698-0.861-3.444-1.091-0.746-6.43-0.919-5.971 0.172z"/>\r
+   <path fill="#d19800" d="m169.264 83.804c0.777 1.612 2.778 1.834 4.112 2.557 1.279 0.723 2.001 0.889 2.501 0.611 1.112-0.611 0.278-2.612-0.834-3.335-1.055-0.722-6.224-0.889-5.779 0.167z"/>\r
+   <path fill="#cc9200" d="m169.406 83.826c0.753 1.559 2.688 1.774 3.979 2.473 1.236 0.699 1.936 0.86 2.42 0.591 1.074-0.591 0.269-2.527-0.808-3.226-1.021-0.699-6.021-0.86-5.591 0.162z"/>\r
+   <path fill="#c68c00" d="m169.549 83.847c0.728 1.506 2.597 1.714 3.844 2.389 1.194 0.675 1.869 0.831 2.337 0.571 1.039-0.571 0.26-2.441-0.779-3.116-0.988-0.675-5.818-0.831-5.402 0.156z"/>\r
+   <path fill="#c18700" d="m169.691 83.869c0.702 1.453 2.506 1.654 3.709 2.305 1.152 0.652 1.803 0.802 2.254 0.551 1.002-0.551 0.251-2.355-0.751-3.006-0.953-0.652-5.613-0.802-5.212 0.15z"/>\r
+   <path fill="#bc8100" d="m169.833 83.89c0.677 1.4 2.415 1.594 3.574 2.221 1.111 0.628 1.738 0.772 2.173 0.531 0.965-0.531 0.241-2.27-0.725-2.897-0.917-0.627-5.408-0.772-5.022 0.145z"/>\r
+   <path fill="#b77b00" d="m169.976 83.912c0.65 1.347 2.322 1.533 3.438 2.137 1.069 0.604 1.673 0.743 2.091 0.511 0.93-0.511 0.233-2.184-0.696-2.788-0.884-0.603-5.205-0.743-4.833 0.14z"/>\r
+   <path fill="#b27500" d="m170.118 83.934c0.626 1.294 2.232 1.473 3.304 2.053 1.027 0.581 1.606 0.714 2.009 0.491 0.893-0.491 0.224-2.098-0.669-2.678-0.85-0.58-5.001-0.715-4.644 0.134z"/>\r
+   <path fill="#ad7000" d="m170.261 83.955c0.6 1.242 2.14 1.413 3.168 1.97 0.984 0.557 1.541 0.685 1.927 0.47 0.855-0.47 0.214-2.012-0.644-2.569-0.812-0.555-4.794-0.684-4.451 0.129z"/>\r
+   <path fill="#a86a00" d="m170.403 83.977c0.574 1.189 2.05 1.353 3.034 1.886 0.942 0.533 1.475 0.656 1.844 0.45 0.82-0.45 0.205-1.926-0.615-2.459-0.779-0.533-4.591-0.656-4.263 0.123z"/>\r
+   <path fill="#a36400" d="m170.545 83.998c0.55 1.136 1.959 1.292 2.899 1.802 0.901 0.509 1.41 0.626 1.762 0.43 0.783-0.43 0.197-1.841-0.587-2.35-0.745-0.508-4.387-0.626-4.074 0.118z"/>\r
+   <path fill="#9e5e00" d="m170.688 84.02c0.522 1.083 1.867 1.232 2.764 1.718 0.859 0.486 1.343 0.597 1.68 0.41 0.746-0.41 0.188-1.755-0.561-2.241-0.709-0.484-4.182-0.597-3.883 0.113z"/>\r
+   <path fill="#995900" d="m170.83 84.042c0.498 1.03 1.776 1.172 2.629 1.634 0.817 0.462 1.278 0.568 1.599 0.39 0.71-0.39 0.178-1.669-0.533-2.131-0.676-0.461-3.979-0.568-3.695 0.107z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m152.875 86.29c-0.325 0.813 1.952 2.359 3.091 1.301 1.222-1.057 2.686-2.033 3.175-2.359 2.195-1.465 1.383-2.522-2.278-1.871-3.663 0.651-3.663 2.115-3.988 2.929z"/>\r
+   <path fill="#f9c600" d="m152.934 86.279c-0.318 0.794 1.906 2.304 3.019 1.271 1.193-1.033 2.623-1.986 3.102-2.305 2.145-1.431 1.351-2.463-2.226-1.828-3.578 0.637-3.578 2.067-3.895 2.862z"/>\r
+   <path fill="#f4c000" d="m152.993 86.269c-0.31 0.775 1.861 2.25 2.948 1.241 1.164-1.008 2.56-1.939 3.026-2.25 2.095-1.397 1.319-2.405-2.173-1.784-3.491 0.62-3.491 2.017-3.801 2.793z"/>\r
+   <path fill="#efba00" d="m153.051 86.258c-0.302 0.757 1.817 2.195 2.878 1.211 1.136-0.984 2.497-1.892 2.952-2.195 2.044-1.363 1.287-2.347-2.118-1.741-3.409 0.606-3.409 1.968-3.712 2.725z"/>\r
+   <path fill="#eab500" d="m153.11 86.248c-0.295 0.738 1.771 2.141 2.805 1.181 1.108-0.959 2.437-1.845 2.88-2.141 1.993-1.329 1.255-2.289-2.066-1.698-3.324 0.591-3.324 1.92-3.619 2.658z"/>\r
+   <path fill="#e5af00" d="m153.169 86.238c-0.287 0.719 1.727 2.086 2.733 1.151 1.08-0.935 2.374-1.798 2.807-2.086 1.942-1.296 1.224-2.23-2.015-1.655s-3.238 1.87-3.525 2.59z"/>\r
+   <path fill="#e0a900" d="m153.228 86.228c-0.28 0.7 1.681 2.032 2.661 1.121 1.052-0.91 2.312-1.751 2.732-2.031 1.893-1.262 1.191-2.172-1.961-1.611-3.152 0.559-3.152 1.82-3.432 2.521z"/>\r
+   <path fill="#dba300" d="m153.286 86.217c-0.271 0.681 1.636 1.977 2.591 1.09 1.023-0.886 2.25-1.704 2.659-1.977 1.84-1.228 1.159-2.114-1.909-1.568-3.068 0.547-3.068 1.773-3.341 2.455z"/>\r
+   <path fill="#d69e00" d="m153.345 86.207c-0.265 0.662 1.591 1.922 2.519 1.061 0.995-0.862 2.188-1.657 2.586-1.922 1.789-1.194 1.127-2.055-1.855-1.525-2.985 0.53-2.985 1.723-3.25 2.386z"/>\r
+   <path fill="#d19800" d="m153.404 86.197c-0.257 0.643 1.546 1.868 2.447 1.03 0.967-0.837 2.126-1.61 2.512-1.868 1.739-1.16 1.095-1.997-1.803-1.481-2.899 0.516-2.899 1.674-3.156 2.319z"/>\r
+   <path fill="#cc9200" d="m153.463 86.187c-0.25 0.625 1.5 1.813 2.375 1 0.939-0.813 2.064-1.563 2.439-1.813 1.688-1.126 1.063-1.938-1.75-1.438-2.814 0.5-2.814 1.625-3.064 2.251z"/>\r
+   <path fill="#c68c00" d="m153.521 86.176c-0.242 0.605 1.456 1.758 2.304 0.97 0.911-0.788 2.002-1.516 2.366-1.758 1.637-1.092 1.031-1.88-1.698-1.395-2.729 0.486-2.729 1.576-2.972 2.183z"/>\r
+   <path fill="#c18700" d="m153.58 86.166c-0.233 0.587 1.41 1.704 2.233 0.939 0.882-0.763 1.938-1.469 2.292-1.704 1.586-1.058 0.999-1.822-1.646-1.352-2.644 0.472-2.644 1.529-2.879 2.117z"/>\r
+   <path fill="#bc8100" d="m153.639 86.156c-0.228 0.568 1.364 1.649 2.16 0.91 0.854-0.739 1.878-1.422 2.219-1.649 1.536-1.024 0.967-1.764-1.593-1.308s-2.559 1.477-2.786 2.047z"/>\r
+   <path fill="#b77b00" d="m153.698 86.146c-0.22 0.549 1.32 1.594 2.089 0.879 0.825-0.715 1.815-1.375 2.146-1.595 1.484-0.99 0.935-1.705-1.54-1.265s-2.475 1.43-2.695 1.981z"/>\r
+   <path fill="#b27500" d="m153.756 86.135c-0.211 0.53 1.275 1.54 2.019 0.85 0.797-0.69 1.753-1.328 2.072-1.54 1.434-0.957 0.902-1.646-1.487-1.221s-2.391 1.38-2.604 1.911z"/>\r
+   <path fill="#ad7000" d="m153.815 86.125c-0.204 0.512 1.229 1.486 1.946 0.82 0.769-0.666 1.69-1.281 1.997-1.486 1.385-0.922 0.871-1.588-1.434-1.178s-2.304 1.331-2.509 1.844z"/>\r
+   <path fill="#a86a00" d="m153.874 86.114c-0.196 0.493 1.185 1.431 1.875 0.79 0.74-0.642 1.628-1.234 1.924-1.431 1.332-0.889 0.84-1.53-1.381-1.135s-2.221 1.283-2.418 1.776z"/>\r
+   <path fill="#a36400" d="m153.933 86.104c-0.189 0.474 1.139 1.376 1.803 0.759 0.712-0.617 1.566-1.187 1.851-1.376 1.281-0.855 0.808-1.472-1.329-1.092-2.135 0.38-2.135 1.234-2.325 1.709z"/>\r
+   <path fill="#9e5e00" d="m153.991 86.094c-0.181 0.455 1.095 1.322 1.732 0.729 0.684-0.592 1.504-1.14 1.776-1.321 1.231-0.821 0.775-1.414-1.274-1.048-2.051 0.364-2.051 1.184-2.234 1.64z"/>\r
+   <path fill="#995900" d="m154.05 86.083c-0.174 0.436 1.05 1.267 1.66 0.699 0.656-0.568 1.442-1.093 1.704-1.267 1.181-0.787 0.743-1.355-1.223-1.005s-1.966 1.136-2.141 1.573z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m156.951 107.887c-0.229 2.858 6.343-4.286 6.743-4.915 0.856-1.543 3.715-5.886 4.172-7.715 0.857-3.2 2.401-5.543 1.429-8.915-0.343-1.086-2.742-1.372-3.829-0.687-3.086 1.829-2.629 4.058-2.972 6.115-1.143 5.831-5.143 11.717-5.543 16.117z"/>\r
+   <path fill="#ffcc02" d="m157.22 107.441c-0.22 2.787 6.178-4.188 6.566-4.802 0.833-1.506 3.614-5.745 4.056-7.529 0.831-3.122 2.333-5.408 1.382-8.695-0.337-1.058-2.678-1.333-3.735-0.663-3.006 1.788-2.557 3.96-2.889 5.967-1.105 5.685-4.997 11.431-5.38 15.722z"/>\r
+   <path fill="#ffcc05" d="m157.488 106.995c-0.209 2.715 6.014-4.091 6.392-4.69 0.811-1.469 3.513-5.603 3.941-7.342 0.804-3.043 2.264-5.273 1.331-8.474-0.329-1.031-2.61-1.295-3.64-0.64-2.927 1.747-2.486 3.863-2.806 5.818-1.068 5.541-4.851 11.146-5.218 15.328z"/>\r
+   <path fill="#ffcc07" d="m157.757 106.548c-0.198 2.645 5.85-3.993 6.217-4.577 0.785-1.431 3.409-5.461 3.824-7.156 0.779-2.964 2.196-5.138 1.282-8.253-0.322-1.003-2.543-1.257-3.545-0.618-2.847 1.706-2.414 3.766-2.722 5.67-1.031 5.398-4.706 10.862-5.056 14.934z"/>\r
+   <path fill="#ffcd0a" d="m158.026 106.102c-0.189 2.573 5.684-3.896 6.04-4.465 0.762-1.394 3.309-5.32 3.709-6.969 0.753-2.886 2.129-5.004 1.233-8.033-0.315-0.976-2.478-1.219-3.45-0.595-2.768 1.665-2.343 3.668-2.64 5.522-0.993 5.254-4.558 10.577-4.892 14.54z"/>\r
+   <path fill="#ffcd0c" d="m158.294 105.655c-0.179 2.503 5.52-3.798 5.865-4.351 0.738-1.357 3.207-5.179 3.594-6.783 0.727-2.807 2.061-4.869 1.185-7.813-0.309-0.948-2.411-1.18-3.356-0.572-2.687 1.623-2.271 3.571-2.556 5.374-0.958 5.11-4.414 10.291-4.732 14.145z"/>\r
+   <path fill="#ffcd0f" d="m158.563 105.209c-0.169 2.431 5.354-3.701 5.688-4.239 0.715-1.319 3.106-5.037 3.479-6.596 0.7-2.728 1.992-4.734 1.135-7.592-0.301-0.92-2.344-1.142-3.261-0.549-2.608 1.583-2.199 3.474-2.473 5.226-0.919 4.965-4.267 10.005-4.568 13.75z"/>\r
+   <path fill="#ffcd11" d="m158.831 104.762c-0.159 2.361 5.19-3.602 5.515-4.126 0.69-1.282 3.004-4.896 3.361-6.409 0.674-2.649 1.924-4.599 1.087-7.372-0.295-0.893-2.277-1.104-3.167-0.526-2.527 1.541-2.128 3.376-2.389 5.077-0.883 4.822-4.122 9.721-4.407 13.356z"/>\r
+   <path fill="#ffce14" d="m159.1 104.316c-0.149 2.289 5.024-3.505 5.338-4.014 0.667-1.244 2.901-4.754 3.247-6.223 0.646-2.571 1.854-4.464 1.037-7.151-0.287-0.865-2.211-1.065-3.072-0.504-2.448 1.5-2.056 3.279-2.306 4.929-0.845 4.679-3.976 9.437-4.244 12.963z"/>\r
+   <path fill="#ffce16" d="m159.369 103.869c-0.139 2.219 4.86-3.407 5.162-3.9 0.643-1.208 2.801-4.613 3.131-6.037 0.622-2.492 1.787-4.329 0.988-6.93-0.28-0.838-2.146-1.027-2.978-0.481-2.368 1.459-1.983 3.182-2.223 4.781-0.807 4.533-3.829 9.151-4.08 12.567z"/>\r
+   <path fill="#ffce19" d="m159.637 103.423c-0.13 2.147 4.695-3.31 4.986-3.788 0.62-1.17 2.699-4.471 3.016-5.85 0.596-2.414 1.719-4.195 0.939-6.71-0.273-0.81-2.079-0.989-2.883-0.458-2.289 1.418-1.913 3.084-2.139 4.632-0.77 4.391-3.684 8.866-3.919 12.174z"/>\r
+   <path fill="#ffce1c" d="m159.906 102.977c-0.119 2.076 4.531-3.213 4.811-3.676 0.597-1.133 2.599-4.33 2.899-5.664 0.57-2.335 1.651-4.06 0.891-6.49-0.267-0.782-2.012-0.95-2.787-0.435-2.21 1.377-1.842 2.987-2.057 4.484-0.734 4.247-3.539 8.582-3.757 11.781z"/>\r
+   <path fill="#ffcf1e" d="m160.174 102.53c-0.108 2.005 4.366-3.115 4.637-3.563 0.571-1.096 2.496-4.189 2.784-5.478 0.543-2.256 1.581-3.925 0.841-6.269-0.26-0.754-1.945-0.912-2.693-0.412-2.129 1.336-1.77 2.889-1.973 4.336-0.697 4.103-3.394 8.297-3.596 11.386z"/>\r
+   <path fill="#ffcf21" d="m160.443 102.084c-0.099 1.934 4.201-3.018 4.46-3.45 0.548-1.059 2.394-4.047 2.668-5.291 0.517-2.178 1.514-3.79 0.793-6.049-0.253-0.727-1.879-0.874-2.599-0.39-2.051 1.295-1.698 2.792-1.891 4.188-0.658 3.959-3.246 8.012-3.431 10.992z"/>\r
+   <path fill="#ffcf23" d="m160.712 101.637c-0.089 1.863 4.036-2.919 4.283-3.337 0.526-1.021 2.294-3.905 2.553-5.104 0.491-2.099 1.447-3.655 0.744-5.828-0.246-0.699-1.813-0.835-2.505-0.367-1.969 1.253-1.625 2.694-1.805 4.04-0.623 3.814-3.101 7.726-3.27 10.596z"/>\r
+   <path fill="#ffcf26" d="m160.98 101.191c-0.079 1.792 3.872-2.822 4.107-3.225 0.502-0.984 2.192-3.764 2.438-4.918 0.464-2.02 1.378-3.52 0.694-5.607-0.238-0.672-1.746-0.797-2.41-0.344-1.89 1.212-1.555 2.597-1.723 3.891-0.583 3.671-2.953 7.442-3.106 10.203z"/>\r
+   <path fill="#ffd028" d="m161.249 100.744c-0.068 1.721 3.707-2.724 3.933-3.112 0.478-0.947 2.091-3.623 2.321-4.731 0.439-1.942 1.311-3.386 0.646-5.387-0.232-0.645-1.68-0.758-2.316-0.321-1.81 1.171-1.481 2.5-1.639 3.743-0.548 3.527-2.809 7.156-2.945 9.808z"/>\r
+   <path fill="#ffd02b" d="m161.517 100.298c-0.06 1.65 3.543-2.627 3.757-2.999 0.454-0.91 1.989-3.481 2.206-4.545 0.413-1.863 1.242-3.25 0.597-5.167-0.225-0.617-1.613-0.72-2.221-0.298-1.73 1.13-1.411 2.402-1.557 3.595-0.509 3.383-2.662 6.871-2.782 9.414z"/>\r
+   <path fill="#ffd02d" d="m161.786 99.852c-0.049 1.579 3.377-2.529 3.581-2.887 0.431-0.872 1.887-3.34 2.091-4.359 0.387-1.784 1.173-3.116 0.547-4.946-0.217-0.589-1.546-0.682-2.126-0.275-1.649 1.089-1.339 2.305-1.472 3.446-0.474 3.24-2.518 6.587-2.621 9.021z"/>\r
+   <path fill="#ffd030" d="m162.055 99.405c-0.039 1.508 3.212-2.432 3.404-2.773 0.407-0.835 1.786-3.199 1.976-4.172 0.359-1.706 1.104-2.981 0.499-4.726-0.211-0.562-1.481-0.644-2.032-0.253-1.571 1.048-1.268 2.208-1.389 3.298-0.436 3.096-2.372 6.302-2.458 8.626z"/>\r
+   <path fill="#ffd133" d="m162.323 98.958c-0.029 1.437 3.048-2.334 3.23-2.661 0.383-0.798 1.684-3.057 1.858-3.986 0.334-1.627 1.037-2.846 0.45-4.505-0.204-0.534-1.414-0.605-1.938-0.23-1.49 1.007-1.195 2.11-1.306 3.15-0.397 2.953-2.224 6.018-2.294 8.232z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m179.646 95.994c-3.168 3.456-5.4 6.767-7.2 9-1.872 2.304-6.48 5.04-4.176 7.704 1.943 2.376 9.936-1.944 16.128-6.552 6.12-4.608 15.696-8.711 11.016-13.967-2.448-2.664-8.208-2.088-10.439-0.648-1.729 1.078-2.737 1.655-5.329 4.463z"/>\r
+   <path fill="#ffcc02" d="m179.782 96.147c-3.118 3.378-5.313 6.628-7.086 8.809-1.841 2.249-6.375 4.945-4.13 7.534 1.893 2.31 9.724-1.943 15.795-6.469 6.001-4.525 15.38-8.574 10.82-13.682-2.387-2.588-8.022-1.998-10.209-0.584-1.692 1.062-2.665 1.67-5.19 4.392z"/>\r
+   <path fill="#ffcc05" d="m179.919 96.3c-3.068 3.3-5.227 6.488-6.973 8.619-1.81 2.193-6.271 4.85-4.085 7.364 1.843 2.243 9.513-1.943 15.463-6.386 5.882-4.442 15.064-8.437 10.623-13.396-2.323-2.513-7.835-1.907-9.978-0.52-1.655 1.044-2.593 1.684-5.05 4.319z"/>\r
+   <path fill="#ffcc07" d="m180.055 96.454c-3.02 3.222-5.14 6.347-6.859 8.428-1.78 2.138-6.166 4.754-4.04 7.194 1.793 2.177 9.302-1.942 15.131-6.303 5.762-4.359 14.748-8.299 10.427-13.11-2.261-2.437-7.648-1.817-9.747-0.456-1.619 1.025-2.522 1.698-4.912 4.247z"/>\r
+   <path fill="#ffcd0a" d="m180.191 96.607c-2.97 3.143-5.052 6.207-6.745 8.237-1.749 2.082-6.063 4.659-3.994 7.023 1.743 2.111 9.09-1.941 14.798-6.219 5.644-4.276 14.433-8.162 10.231-12.824-2.199-2.361-7.463-1.727-9.518-0.392-1.581 1.008-2.45 1.713-4.772 4.175z"/>\r
+   <path fill="#ffcd0c" d="m180.327 96.761c-2.92 3.065-4.965 6.066-6.631 8.047-1.718 2.027-5.957 4.564-3.949 6.853 1.693 2.044 8.878-1.94 14.466-6.136 5.524-4.194 14.116-8.024 10.034-12.538-2.137-2.286-7.275-1.636-9.285-0.328-1.546 0.988-2.38 1.726-4.635 4.102z"/>\r
+   <path fill="#ffcd0f" d="m180.464 96.914c-2.871 2.987-4.879 5.926-6.518 7.857-1.688 1.971-5.854 4.468-3.903 6.683 1.643 1.978 8.666-1.94 14.133-6.053 5.404-4.111 13.801-7.887 9.839-12.251-2.075-2.21-7.091-1.546-9.056-0.264-1.509 0.969-2.308 1.738-4.495 4.028z"/>\r
+   <path fill="#ffcd11" d="m180.6 97.067c-2.821 2.909-4.792 5.786-6.404 7.667-1.657 1.916-5.748 4.373-3.858 6.512 1.593 1.912 8.455-1.938 13.802-5.969 5.284-4.028 13.484-7.75 9.641-11.966-2.012-2.134-6.902-1.456-8.823-0.199-1.474 0.951-2.238 1.752-4.358 3.955z"/>\r
+   <path fill="#ffce14" d="m180.736 97.221c-2.771 2.83-4.705 5.645-6.29 7.476-1.626 1.86-5.644 4.278-3.813 6.342 1.542 1.845 8.244-1.938 13.47-5.886 5.166-3.945 13.169-7.612 9.444-11.68-1.949-2.059-6.716-1.365-8.592-0.135-1.437 0.933-2.166 1.766-4.219 3.883z"/>\r
+   <path fill="#ffce16" d="m180.872 97.375c-2.722 2.752-4.617 5.504-6.176 7.286-1.595 1.805-5.539 4.182-3.767 6.172 1.49 1.779 8.031-1.937 13.136-5.803 5.046-3.862 12.853-7.475 9.249-11.394-1.889-1.983-6.53-1.274-8.362-0.071-1.4 0.914-2.095 1.779-4.08 3.81z"/>\r
+   <path fill="#ffce19" d="m181.009 97.528c-2.673 2.674-4.53 5.364-6.063 7.095-1.564 1.749-5.435 4.087-3.722 6.001 1.44 1.713 7.82-1.936 12.804-5.719 4.927-3.78 12.537-7.338 9.052-11.108-1.825-1.907-6.343-1.185-8.13-0.007-1.364 0.896-2.024 1.793-3.941 3.738z"/>\r
+   <path fill="#ffce1c" d="m181.145 97.682c-2.623 2.595-4.444 5.225-5.949 6.904-1.534 1.693-5.33 3.992-3.676 5.831 1.39 1.646 7.608-1.935 12.471-5.636 4.808-3.697 12.221-7.2 8.856-10.822-1.764-1.832-6.157-1.094-7.9 0.057-1.327 0.878-1.952 1.807-3.802 3.666z"/>\r
+   <path fill="#ffcf1e" d="m181.281 97.835c-2.573 2.517-4.357 5.084-5.835 6.714-1.503 1.638-5.226 3.896-3.631 5.661 1.34 1.58 7.396-1.935 12.139-5.553 4.689-3.614 11.905-7.063 8.659-10.536-1.701-1.756-5.97-1.004-7.668 0.121-1.291 0.86-1.881 1.821-3.664 3.593z"/>\r
+   <path fill="#ffcf21" d="m181.417 97.988c-2.522 2.439-4.27 4.944-5.721 6.524-1.472 1.582-5.121 3.801-3.586 5.491 1.29 1.513 7.186-1.934 11.807-5.47 4.569-3.531 11.589-6.926 8.463-10.25-1.639-1.68-5.783-0.914-7.438 0.186-1.254 0.84-1.809 1.834-3.525 3.519z"/>\r
+   <path fill="#ffcf23" d="m181.554 98.142c-2.476 2.361-4.185 4.803-5.608 6.333-1.441 1.527-5.017 3.706-3.54 5.32 1.24 1.447 6.974-1.933 11.474-5.386 4.45-3.448 11.273-6.788 8.268-9.964-1.577-1.605-5.599-0.823-7.207 0.25-1.22 0.822-1.74 1.848-3.387 3.447z"/>\r
+   <path fill="#ffcf26" d="m181.69 98.295c-2.425 2.283-4.098 4.663-5.494 6.143-1.411 1.471-4.912 3.61-3.495 5.15 1.19 1.381 6.763-1.932 11.142-5.303 4.331-3.366 10.957-6.65 8.07-9.679-1.514-1.529-5.411-0.732-6.976 0.313-1.182 0.805-1.667 1.863-3.247 3.376z"/>\r
+   <path fill="#ffd028" d="m181.826 98.449c-2.375 2.204-4.009 4.522-5.38 5.952-1.38 1.416-4.808 3.515-3.449 4.98 1.14 1.314 6.551-1.932 10.81-5.22 4.211-3.283 10.641-6.513 7.874-9.393-1.452-1.454-5.226-0.642-6.745 0.378-1.147 0.786-1.597 1.876-3.11 3.303z"/>\r
+   <path fill="#ffd02b" d="m181.962 98.602c-2.324 2.127-3.922 4.382-5.266 5.762-1.349 1.36-4.703 3.42-3.404 4.809 1.089 1.248 6.34-1.93 10.478-5.136 4.092-3.2 10.325-6.376 7.677-9.106-1.389-1.378-5.038-0.552-6.513 0.441-1.111 0.768-1.526 1.89-2.972 3.23z"/>\r
+   <path fill="#ffd02d" d="m182.099 98.756c-2.276 2.048-3.836 4.241-5.153 5.571-1.318 1.305-4.599 3.324-3.359 4.639 1.039 1.182 6.128-1.93 10.146-5.053 3.973-3.117 10.009-6.238 7.48-8.82-1.328-1.303-4.852-0.462-6.282 0.506-1.074 0.748-1.454 1.903-2.832 3.157z"/>\r
+   <path fill="#ffd030" d="m182.235 98.909c-2.228 1.97-3.749 4.101-5.039 5.381-1.288 1.249-4.494 3.229-3.313 4.469 0.988 1.115 5.916-1.929 9.813-4.97 3.853-3.034 9.693-6.101 7.285-8.535-1.267-1.227-4.666-0.371-6.052 0.57-1.038 0.731-1.384 1.918-2.694 3.085z"/>\r
+   <path fill="#ffd133" d="m182.371 99.063c-2.177 1.892-3.662 3.96-4.925 5.19-1.257 1.193-4.39 3.133-3.268 4.298 0.938 1.049 5.704-1.928 9.479-4.886 3.734-2.952 9.377-5.963 7.088-8.249-1.203-1.151-4.479-0.281-5.821 0.634-0.999 0.713-1.31 1.931-2.553 3.013z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fff" d="m186.414 168.569c0.864-2.808 28.872-9.432 33.48-7.272 4.536 2.16 26.279 33.768 22.392 35.496-3.888 1.657-12.24-10.512-24.408-16.128s-32.328-9.216-31.464-12.096z"/>\r
+   <path fill="#f9f9f9" d="m187.239 168.626c0.848-2.761 28.145-9.076 32.69-6.997 4.476 2.079 25.768 32.897 21.943 34.591-3.824 1.625-11.965-10.346-23.94-15.874-11.976-5.527-31.541-8.89-30.693-11.72z"/>\r
+   <path fill="#f4f4f4" d="m188.063 168.683c0.832-2.714 27.418-8.72 31.899-6.722 4.417 1.998 25.259 32.026 21.497 33.685-3.76 1.595-11.689-10.18-23.474-15.619-11.782-5.438-30.754-8.565-29.922-11.344z"/>\r
+   <path fill="#efefef" d="m188.888 168.74c0.814-2.668 26.69-8.364 31.109-6.447 4.357 1.917 24.746 31.155 21.049 32.779-3.695 1.563-11.416-10.014-23.007-15.364-11.59-5.349-29.967-8.239-29.151-10.968z"/>\r
+   <path fill="#eaeaea" d="m189.712 168.797c0.801-2.621 25.964-8.009 30.32-6.173 4.299 1.837 24.235 30.285 20.603 31.874-3.633 1.532-11.142-9.847-22.54-15.109-11.4-5.261-29.182-7.914-28.383-10.592z"/>\r
+   <path fill="#e5e5e5" d="m190.537 168.853c0.783-2.573 25.236-7.652 29.53-5.897 4.239 1.756 23.723 29.414 20.155 30.968-3.569 1.501-10.867-9.681-22.074-14.854-11.206-5.172-28.395-7.589-27.611-10.217z"/>\r
+   <path fill="#e0e0e0" d="m191.361 168.91c0.768-2.527 24.51-7.296 28.74-5.622 4.18 1.675 23.212 28.543 19.708 30.063-3.505 1.469-10.593-9.516-21.607-14.6-11.014-5.083-27.608-7.263-26.841-9.841z"/>\r
+   <path fill="#dbdbdb" d="m192.186 168.967c0.751-2.48 23.781-6.941 27.95-5.347 4.119 1.593 22.7 27.671 19.26 29.157-3.441 1.438-10.318-9.349-21.141-14.345-10.821-4.994-26.821-6.938-26.069-9.465z"/>\r
+   <path fill="#d6d6d6" d="m193.01 169.024c0.735-2.433 23.057-6.585 27.16-5.073 4.062 1.513 22.19 26.801 18.813 28.252-3.377 1.407-10.043-9.183-20.673-14.09-10.629-4.906-26.035-6.612-25.3-9.089z"/>\r
+   <path fill="#d1d1d1" d="m193.835 169.081c0.72-2.387 22.328-6.229 26.37-4.798 4.001 1.432 21.678 25.93 18.365 27.346-3.313 1.376-9.768-9.017-20.206-13.835-10.437-4.817-25.248-6.287-24.529-8.713z"/>\r
+   <path fill="#ccc" d="m194.659 169.137c0.703-2.339 21.603-5.873 25.58-4.521 3.942 1.351 21.167 25.059 17.918 26.44-3.249 1.345-9.493-8.851-19.739-13.58-10.245-4.729-24.462-5.963-23.759-8.339z"/>\r
+   <path fill="#c6c6c6" d="m195.484 169.194c0.687-2.292 20.874-5.517 24.79-4.247 3.882 1.27 20.655 24.188 17.47 25.535-3.185 1.314-9.219-8.685-19.271-13.326-10.054-4.639-23.676-5.636-22.989-7.962z"/>\r
+   <path fill="#c1c1c1" d="m196.308 169.251c0.671-2.246 20.147-5.161 24-3.973 3.822 1.19 20.145 23.318 17.022 24.63-3.121 1.283-8.943-8.519-18.805-13.071-9.859-4.551-22.888-5.311-22.217-7.586z"/>\r
+   <path fill="#bcbcbc" d="m197.133 169.308c0.654-2.199 19.421-4.805 23.21-3.698 3.764 1.109 19.634 22.447 16.575 23.724-3.057 1.252-8.669-8.353-18.338-12.816-9.668-4.462-22.102-4.985-21.447-7.21z"/>\r
+   <path fill="#b7b7b7" d="m197.957 169.365c0.64-2.152 18.693-4.45 22.42-3.423 3.705 1.027 19.122 21.575 16.129 22.818-2.993 1.221-8.395-8.186-17.872-12.561-9.476-4.373-21.315-4.66-20.677-6.834z"/>\r
+   <path fill="#b2b2b2" d="m198.782 169.421c0.622-2.105 17.966-4.093 21.63-3.147 3.646 0.946 18.61 20.704 15.681 21.912-2.93 1.19-8.12-8.02-17.404-12.306-9.284-4.284-20.53-4.335-19.907-6.459z"/>\r
+   <path fill="#adadad" d="m199.606 169.478c0.606-2.058 17.239-3.737 20.84-2.873 3.586 0.866 18.099 19.834 15.234 21.008-2.866 1.158-7.847-7.855-16.938-12.052-9.091-4.196-19.742-4.009-19.136-6.083z"/>\r
+   <path fill="#a8a8a8" d="m200.431 169.535c0.59-2.011 16.512-3.382 20.05-2.598 3.525 0.785 17.588 18.963 14.786 20.102-2.803 1.127-7.571-7.688-16.472-11.797-8.898-4.107-18.955-3.684-18.364-5.707z"/>\r
+   <path fill="#a3a3a3" d="m201.255 169.592c0.574-1.965 15.785-3.026 19.261-2.323 3.467 0.704 17.076 18.092 14.339 19.196-2.738 1.096-7.296-7.522-16.004-11.542-8.707-4.018-18.17-3.358-17.596-5.331z"/>\r
+   <path fill="#9e9e9e" d="m202.08 169.649c0.559-1.918 15.059-2.67 18.47-2.048 3.407 0.623 16.565 17.221 13.892 18.29-2.674 1.065-7.022-7.356-15.537-11.287-8.515-3.929-17.383-3.033-16.825-4.955z"/>\r
+   <path fill="#999" d="m202.904 169.705c0.542-1.871 14.331-2.314 17.68-1.773 3.349 0.542 16.055 16.35 13.444 17.385-2.61 1.034-6.747-7.19-15.07-11.032-8.322-3.841-16.596-2.708-16.054-4.58z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fff" d="m151.134 211.625c2.881 0.144 0.145 16.271 0.145 32.903s2.231 22.464 0.144 24.552-5.688-5.399-5.688-22.031c-0.001-16.632 2.519-35.568 5.399-35.424z"/>\r
+   <path fill="#f9f9f9" d="m151.105 212.016c2.783 0.162 0.109 16.052 0.097 32.419-0.012 16.366 2.188 22.208 0.164 24.237-2.02 2.029-5.561-5.383-5.546-21.752 0.012-16.367 2.502-35.065 5.285-34.904z"/>\r
+   <path fill="#f4f4f4" d="m151.075 212.407c2.687 0.18 0.076 15.832 0.051 31.934-0.023 16.102 2.143 21.951 0.185 23.924-1.953 1.968-5.435-5.367-5.405-21.473 0.024-16.103 2.484-34.564 5.169-34.385z"/>\r
+   <path fill="#efefef" d="m151.046 212.797c2.588 0.197 0.041 15.613 0.004 31.449-0.036 15.836 2.098 21.694 0.204 23.609-1.886 1.907-5.308-5.352-5.263-21.195 0.037-15.835 2.467-34.058 5.055-33.863z"/>\r
+   <path fill="#eaeaea" d="m151.017 213.189c2.49 0.214 0.007 15.392-0.043 30.962-0.05 15.571 2.052 21.439 0.224 23.297-1.818 1.848-5.181-5.334-5.122-20.916 0.049-15.571 2.45-33.557 4.941-33.343z"/>\r
+   <path fill="#e5e5e5" d="m150.987 213.581c2.394 0.23-0.027 15.17-0.089 30.477s2.007 21.182 0.244 22.982c-1.751 1.787-5.055-5.32-4.98-20.638 0.061-15.305 2.431-33.053 4.825-32.821z"/>\r
+   <path fill="#e0e0e0" d="m150.958 213.971c2.297 0.248-0.062 14.951-0.136 29.99-0.074 15.041 1.962 20.927 0.264 22.668-1.683 1.728-4.928-5.301-4.839-20.356 0.074-15.04 2.414-32.551 4.711-32.302z"/>\r
+   <path fill="#dbdbdb" d="m150.928 214.362c2.199 0.266-0.096 14.73-0.182 29.506-0.087 14.775 1.915 20.67 0.282 22.354-1.615 1.667-4.8-5.286-4.696-20.078 0.087-14.776 2.397-32.048 4.596-31.782z"/>\r
+   <path fill="#d6d6d6" d="m150.899 214.752c2.102 0.283-0.13 14.511-0.229 29.021-0.099 14.511 1.87 20.413 0.303 22.04-1.549 1.607-4.674-5.27-4.556-19.799 0.1-14.51 2.38-31.545 4.482-31.262z"/>\r
+   <path fill="#d1d1d1" d="m150.87 215.144c2.005 0.301-0.165 14.29-0.274 28.535-0.112 14.245 1.824 20.155 0.321 21.725-1.479 1.548-4.547-5.252-4.413-19.519 0.11-14.245 2.361-31.043 4.366-30.741z"/>\r
+   <path fill="#ccc" d="m150.84 215.536c1.908 0.317-0.197 14.069-0.32 28.049-0.124 13.979 1.779 19.899 0.342 21.412-1.413 1.486-4.42-5.238-4.272-19.242 0.122-13.979 2.343-30.54 4.25-30.219z"/>\r
+   <path fill="#c6c6c6" d="m150.811 215.926c1.811 0.334-0.233 13.85-0.368 27.564-0.136 13.713 1.735 19.643 0.362 21.096-1.346 1.428-4.293-5.219-4.131-18.961 0.136-13.712 2.327-30.035 4.137-29.699z"/>\r
+   <path fill="#c1c1c1" d="m150.781 216.317c1.714 0.354-0.267 13.629-0.414 27.078s1.69 19.387 0.382 20.783c-1.277 1.367-4.166-5.203-3.989-18.682 0.148-13.449 2.308-29.533 4.021-29.179z"/>\r
+   <path fill="#bcbcbc" d="m150.752 216.708c1.616 0.371-0.301 13.41-0.461 26.594-0.161 13.184 1.646 19.13 0.402 20.469-1.211 1.307-4.04-5.188-3.847-18.402 0.16-13.185 2.29-29.033 3.906-28.661z"/>\r
+   <path fill="#b7b7b7" d="m150.723 217.099c1.519 0.387-0.336 13.188-0.509 26.106-0.173 12.92 1.601 18.875 0.423 20.156-1.144 1.246-3.913-5.171-3.706-18.123 0.172-12.919 2.273-28.529 3.792-28.139z"/>\r
+   <path fill="#b2b2b2" d="m150.693 217.491c1.422 0.404-0.37 12.969-0.554 25.621-0.186 12.653 1.555 18.617 0.441 19.842-1.076 1.187-3.786-5.156-3.563-17.846 0.184-12.652 2.255-28.024 3.676-27.617z"/>\r
+   <path fill="#adadad" d="m150.664 217.881c1.325 0.422-0.404 12.748-0.601 25.136-0.198 12.388 1.51 18.36 0.462 19.528-1.008 1.125-3.66-5.139-3.423-17.566 0.197-12.389 2.238-27.521 3.562-27.098z"/>\r
+   <path fill="#a8a8a8" d="m150.634 218.272c1.229 0.439-0.438 12.527-0.646 24.65-0.21 12.123 1.464 18.104 0.48 19.213-0.939 1.066-3.531-5.121-3.279-17.285 0.208-12.123 2.219-27.019 3.445-26.578z"/>\r
+   <path fill="#a3a3a3" d="m150.605 218.663c1.13 0.457-0.474 12.309-0.694 24.166-0.222 11.857 1.419 17.848 0.501 18.899-0.873 1.006-3.405-5.106-3.139-17.009 0.222-11.855 2.202-26.515 3.332-26.056z"/>\r
+   <path fill="#9e9e9e" d="m150.576 219.054c1.033 0.474-0.507 12.088-0.741 23.68-0.234 11.593 1.374 17.591 0.521 18.585-0.806 0.946-3.279-5.089-2.997-16.729 0.233-11.591 2.184-26.011 3.217-25.536z"/>\r
+   <path fill="#999" d="m150.546 219.444c0.937 0.492-0.541 11.868-0.787 23.195-0.246 11.326 1.329 17.335 0.541 18.271-0.737 0.885-3.151-5.074-2.855-16.449 0.245-11.328 2.166-25.509 3.101-25.017z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fff" d="m157.434 167.161c1.735 0.192 12.437-2.218 12.822-1.254 0.386 0.772-6.651 2.893-8.966 5.303-0.771 0.771-2.796 2.603-4.049 2.41-0.964-0.096-1.543-2.121-2.989-3.664-3.471-3.47-5.688-3.181-5.013-4.531 0.579-1.06 5.207 1.446 8.195 1.736z"/>\r
+   <path fill="#fbfbfb" d="m157.479 167.201c1.7 0.188 12.176-2.171 12.554-1.227 0.377 0.755-6.512 2.832-8.778 5.191-0.755 0.755-2.736 2.549-3.964 2.36-0.942-0.094-1.51-2.077-2.926-3.587-3.398-3.397-5.568-3.115-4.907-4.436 0.565-1.038 5.096 1.415 8.021 1.699z"/>\r
+   <path fill="#f8f8f8" d="m157.525 167.241c1.663 0.184 11.914-2.124 12.283-1.201 0.369 0.739-6.372 2.771-8.589 5.08-0.738 0.739-2.679 2.494-3.879 2.309-0.924-0.092-1.479-2.032-2.863-3.51-3.325-3.324-5.449-3.048-4.803-4.341 0.555-1.015 4.988 1.385 7.851 1.663z"/>\r
+   <path fill="#f5f5f5" d="m157.57 167.281c1.626 0.18 11.652-2.078 12.014-1.175 0.361 0.723-6.231 2.711-8.4 4.969-0.723 0.722-2.619 2.439-3.793 2.258-0.903-0.09-1.446-1.987-2.802-3.433-3.252-3.251-5.329-2.981-4.695-4.245 0.54-0.993 4.876 1.354 7.676 1.626z"/>\r
+   <path fill="#f2f2f2" d="m157.615 167.321c1.59 0.176 11.391-2.031 11.745-1.148 0.352 0.706-6.093 2.649-8.212 4.856-0.707 0.707-2.562 2.385-3.709 2.208-0.883-0.088-1.413-1.943-2.738-3.356-3.179-3.178-5.209-2.914-4.591-4.15 0.529-0.971 4.768 1.324 7.505 1.59z"/>\r
+   <path fill="#efefef" d="m157.66 167.361c1.554 0.172 11.13-1.985 11.475-1.122 0.346 0.69-5.952 2.589-8.022 4.745-0.69 0.69-2.503 2.33-3.624 2.157-0.863-0.086-1.381-1.898-2.675-3.279-3.106-3.105-5.09-2.847-4.486-4.055 0.517-0.948 4.658 1.294 7.332 1.554z"/>\r
+   <path fill="#ebebeb" d="m157.705 167.401c1.518 0.168 10.868-1.938 11.206-1.096 0.336 0.674-5.813 2.528-7.835 4.634-0.674 0.674-2.444 2.275-3.539 2.106-0.842-0.084-1.348-1.853-2.612-3.202-3.032-3.032-4.97-2.78-4.38-3.959 0.505-0.926 4.549 1.263 7.16 1.517z"/>\r
+   <path fill="#e8e8e8" d="m157.751 167.441c1.48 0.164 10.606-1.892 10.936-1.069 0.329 0.657-5.673 2.467-7.646 4.522-0.658 0.657-2.385 2.22-3.453 2.055-0.822-0.082-1.315-1.809-2.549-3.124-2.96-2.96-4.851-2.714-4.275-3.865 0.491-0.904 4.438 1.233 6.987 1.481z"/>\r
+   <path fill="#e5e5e5" d="m157.796 167.481c1.444 0.16 10.346-1.845 10.666-1.043 0.32 0.641-5.532 2.406-7.458 4.41-0.641 0.642-2.325 2.166-3.367 2.005-0.803-0.08-1.284-1.764-2.486-3.047-2.887-2.887-4.732-2.647-4.17-3.769 0.48-0.882 4.329 1.202 6.815 1.444z"/>\r
+   <path fill="#e2e2e2" d="m157.841 167.521c1.407 0.156 10.083-1.799 10.397-1.017 0.312 0.625-5.394 2.346-7.271 4.299-0.625 0.625-2.267 2.111-3.282 1.954-0.782-0.078-1.251-1.719-2.423-2.97-2.814-2.814-4.612-2.58-4.065-3.674 0.469-0.859 4.221 1.172 6.644 1.408z"/>\r
+   <path fill="#dfdfdf" d="m157.886 167.56c1.37 0.152 9.821-1.751 10.127-0.99 0.304 0.609-5.254 2.285-7.081 4.188-0.609 0.609-2.208 2.056-3.198 1.903-0.761-0.076-1.218-1.675-2.36-2.893-2.741-2.741-4.492-2.513-3.959-3.579 0.456-0.837 4.111 1.142 6.471 1.371z"/>\r
+   <path fill="#dbdbdb" d="m157.931 167.6c1.335 0.148 9.561-1.704 9.857-0.963 0.296 0.592-5.114 2.223-6.893 4.076-0.593 0.593-2.149 2.001-3.113 1.853-0.741-0.074-1.186-1.631-2.297-2.817-2.668-2.667-4.373-2.446-3.854-3.483 0.445-0.815 4.003 1.111 6.3 1.334z"/>\r
+   <path fill="#d8d8d8" d="m157.977 167.64c1.298 0.144 9.299-1.658 9.587-0.937 0.288 0.576-4.974 2.163-6.704 3.964-0.576 0.577-2.091 1.947-3.027 1.803-0.721-0.072-1.153-1.586-2.234-2.74-2.596-2.594-4.253-2.379-3.748-3.388 0.431-0.792 3.891 1.081 6.126 1.298z"/>\r
+   <path fill="#d5d5d5" d="m158.022 167.68c1.261 0.14 9.037-1.611 9.317-0.911 0.28 0.56-4.834 2.102-6.516 3.853-0.56 0.561-2.032 1.892-2.942 1.752-0.7-0.07-1.12-1.541-2.172-2.663-2.521-2.521-4.133-2.312-3.643-3.292 0.421-0.77 3.784 1.05 5.956 1.261z"/>\r
+   <path fill="#d2d2d2" d="m158.067 167.72c1.225 0.136 8.775-1.564 9.049-0.884 0.271 0.543-4.695 2.041-6.327 3.741-0.545 0.544-1.974 1.837-2.857 1.701-0.682-0.068-1.09-1.497-2.109-2.585-2.449-2.449-4.014-2.246-3.538-3.198 0.407-0.748 3.673 1.02 5.782 1.225z"/>\r
+   <path fill="#cfcfcf" d="m158.112 167.76c1.188 0.132 8.515-1.518 8.779-0.858 0.264 0.527-4.555 1.98-6.139 3.63-0.527 0.528-1.915 1.782-2.772 1.65-0.66-0.066-1.057-1.452-2.046-2.508-2.376-2.376-3.895-2.179-3.433-3.103 0.397-0.725 3.565 0.99 5.611 1.189z"/>\r
+   <path fill="#ccc" d="m158.157 167.8c1.152 0.128 8.253-1.472 8.51-0.832 0.255 0.511-4.415 1.92-5.95 3.518-0.512 0.512-1.855 1.728-2.688 1.6-0.64-0.064-1.023-1.407-1.983-2.431-2.303-2.303-3.773-2.112-3.326-3.007 0.383-0.703 3.454 0.959 5.437 1.152z"/>\r
+   <path fill="#c8c8c8" d="m158.203 167.84c1.115 0.124 7.991-1.425 8.239-0.805 0.248 0.494-4.274 1.858-5.761 3.406-0.496 0.496-1.798 1.673-2.603 1.549-0.62-0.063-0.992-1.363-1.921-2.354-2.229-2.229-3.655-2.045-3.221-2.912 0.372-0.681 3.346 0.929 5.267 1.116z"/>\r
+   <path fill="#c5c5c5" d="m158.248 167.88c1.079 0.12 7.73-1.379 7.97-0.779 0.239 0.478-4.135 1.798-5.572 3.295-0.479 0.479-1.739 1.618-2.518 1.498-0.6-0.06-0.959-1.318-1.857-2.277-2.157-2.157-3.535-1.978-3.116-2.816 0.359-0.659 3.235 0.898 5.093 1.079z"/>\r
+   <path fill="#c2c2c2" d="m158.293 167.92c1.042 0.116 7.469-1.332 7.701-0.753 0.231 0.462-3.995 1.737-5.385 3.184-0.463 0.463-1.68 1.563-2.432 1.447-0.579-0.058-0.927-1.273-1.796-2.2-2.084-2.084-3.415-1.911-3.01-2.721 0.348-0.636 3.127 0.868 4.922 1.043z"/>\r
+   <path fill="#bfbfbf" d="m158.338 167.959c1.007 0.112 7.207-1.285 7.432-0.726 0.223 0.446-3.855 1.676-5.196 3.072-0.447 0.447-1.621 1.509-2.347 1.397-0.56-0.056-0.895-1.229-1.732-2.123-2.011-2.011-3.296-1.844-2.905-2.626 0.334-0.614 3.016 0.838 4.748 1.006z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m194.253 11.922c-1.222 2.631-3.812 23.214-0.248 20.892 3.594-2.341 13.57-5.312 19.886-7.013 7.003-1.886-17.188-19.463-19.638-13.879z"/>\r
+   <path fill="#060606" d="m194.485 12.307c-1.21 2.594-3.704 22.255-0.234 20.007 3.491-2.262 13.077-5.1 19.039-6.782 6.59-1.905-16.436-18.609-18.805-13.225z"/>\r
+   <path fill="#0c0c0c" d="m194.717 12.691c-1.198 2.557-3.595 21.296-0.221 19.124 3.391-2.184 12.586-4.888 18.194-6.551 6.177-1.924-15.684-17.757-17.973-12.573z"/>\r
+   <path fill="#131313" d="m194.949 13.076c-1.187 2.52-3.487 20.337-0.207 18.239 3.288-2.105 12.093-4.676 17.348-6.321 5.763-1.941-14.933-16.903-17.141-11.918z"/>\r
+   <path fill="#191919" d="m195.181 13.46c-1.177 2.483-3.379 19.378-0.193 17.355 3.187-2.027 11.6-4.464 16.502-6.09 5.349-1.959-14.182-16.05-16.309-11.265z"/>\r
+   <path fill="#1f1f1f" d="m195.413 13.845c-1.164 2.446-3.27 18.419-0.18 16.471 3.086-1.949 11.107-4.252 15.657-5.859 4.935-1.978-13.43-15.198-15.477-10.612z"/>\r
+   <path fill="#262626" d="m195.645 14.229c-1.153 2.409-3.162 17.46-0.166 15.586 2.983-1.87 10.616-4.04 14.811-5.628 4.521-1.995-12.679-14.344-14.645-9.958z"/>\r
+   <path fill="#2c2c2c" d="m195.878 14.614c-1.142 2.372-3.055 16.501-0.152 14.702 2.882-1.792 10.123-3.828 13.965-5.398 4.107-2.013-11.929-13.49-13.813-9.304z"/>\r
+   <path fill="#333" d="m196.11 14.999c-1.131 2.335-2.946 15.542-0.14 13.817 2.78-1.713 9.631-3.616 13.119-5.167 3.695-2.031-11.175-12.637-12.979-8.65z"/>\r
+   <path fill="#393939" d="m196.342 15.383c-1.118 2.299-2.838 14.583-0.126 12.934 2.68-1.636 9.139-3.404 12.274-4.937 3.28-2.049-10.425-11.784-12.148-7.997z"/>\r
+   <path fill="#3f3f3f" d="m196.574 15.768c-1.108 2.261-2.729 13.624-0.112 12.049 2.577-1.557 8.646-3.192 11.429-4.706 2.865-2.068-9.675-10.931-11.317-7.343z"/>\r
+   <path fill="#464646" d="m196.806 16.152c-1.097 2.225-2.622 12.665-0.1 11.165 2.477-1.479 8.154-2.98 10.583-4.475 2.453-2.086-8.922-10.078-10.483-6.69z"/>\r
+   <path fill="#4c4c4c" d="m197.038 16.537c-1.085 2.188-2.513 11.706-0.085 10.28 2.374-1.4 7.661-2.768 9.737-4.244 2.039-2.104-8.171-9.225-9.652-6.036z"/>\r
+   <path fill="#525252" d="m197.27 16.921c-1.073 2.151-2.405 10.747-0.071 9.396 2.272-1.322 7.168-2.556 8.891-4.013 1.625-2.122-7.42-8.371-8.82-5.383z"/>\r
+   <path fill="#595959" d="m197.502 17.306c-1.062 2.113-2.297 9.788-0.058 8.512 2.172-1.244 6.677-2.344 8.046-3.783 1.211-2.14-6.669-7.518-7.988-4.729z"/>\r
+   <path fill="#5f5f5f" d="m197.734 17.69c-1.05 2.077-2.188 8.829-0.044 7.627 2.069-1.165 6.184-2.132 7.2-3.552 0.797-2.157-5.917-6.664-7.156-4.075z"/>\r
+   <path fill="#666" d="m197.966 18.075c-1.038 2.04-2.079 7.87-0.029 6.743 1.968-1.087 5.69-1.92 6.354-3.321 0.382-2.176-5.167-5.812-6.325-3.422z"/>\r
+   <path fill="#6c6c6c" d="m198.198 18.459c-1.027 2.003-1.972 6.911-0.017 5.859 1.866-1.008 5.198-1.708 5.509-3.09-0.03-2.194-4.415-4.959-5.492-2.769z"/>\r
+   <path fill="#727272" d="m198.43 18.844c-1.017 1.966-1.863 5.952-0.003 4.975 1.765-0.93 4.706-1.496 4.662-2.86-0.443-2.212-3.662-4.106-4.659-2.115z"/>\r
+   <path fill="#797979" d="m198.662 19.228c-1.004 1.929-1.755 4.993 0.011 4.09 1.663-0.852 4.215-1.284 3.817-2.629-0.858-2.23-2.912-3.251-3.828-1.461z"/>\r
+   <path fill="#7f7f7f" d="m198.894 19.612c-0.993 1.892-1.647 4.034 0.023 3.206 1.563-0.773 3.723-1.072 2.973-2.398-1.272-2.248-2.161-2.399-2.996-0.808z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m143.502 46.386c-0.72 2.16 8.712 5.112 10.801 6.984 2.808 2.52 3.023 7.488 6.336 5.472 2.159-1.296 0.504-4.176-3.456-8.568-5.833-6.481-13.033-5.689-13.681-3.888z"/>\r
+   <path fill="#050505" d="m143.991 46.582c-0.716 2.073 8.275 4.9 10.336 6.741 2.745 2.457 2.961 7.249 6.146 5.313 2.094-1.254 0.449-4.072-3.343-8.28-5.574-6.203-12.491-5.505-13.139-3.774z"/>\r
+   <path fill="#0a0a0a" d="m144.479 46.779c-0.71 1.987 7.839 4.688 9.873 6.498 2.682 2.394 2.897 7.009 5.956 5.154 2.028-1.212 0.395-3.968-3.228-7.993-5.319-5.926-11.953-5.321-12.601-3.659z"/>\r
+   <path fill="#0f0f0f" d="m144.967 46.976c-0.704 1.9 7.403 4.476 9.41 6.254 2.62 2.33 2.835 6.77 5.766 4.995 1.964-1.171 0.342-3.864-3.112-7.706-5.064-5.647-11.415-5.137-12.064-3.543z"/>\r
+   <path fill="#141414" d="m145.456 47.172c-0.701 1.813 6.966 4.263 8.946 6.011 2.557 2.266 2.772 6.53 5.575 4.835 1.897-1.129 0.287-3.76-2.998-7.418-4.807-5.369-10.874-4.952-11.523-3.428z"/>\r
+   <path fill="#191919" d="m145.944 47.369c-0.696 1.726 6.53 4.051 8.483 5.768 2.493 2.203 2.71 6.291 5.385 4.676 1.833-1.087 0.231-3.656-2.884-7.13-4.551-5.093-10.335-4.769-10.984-3.314z"/>\r
+   <path fill="#1e1e1e" d="m146.433 47.565c-0.692 1.64 6.093 3.839 8.019 5.525 2.431 2.14 2.647 6.052 5.194 4.517 1.768-1.046 0.179-3.552-2.77-6.843-4.293-4.814-9.794-4.585-10.443-3.199z"/>\r
+   <path fill="#232323" d="m146.921 47.762c-0.686 1.553 5.657 3.627 7.558 5.282 2.367 2.076 2.583 5.813 5.003 4.357 1.702-1.003 0.124-3.448-2.654-6.555-4.04-4.537-9.257-4.401-9.907-3.084z"/>\r
+   <path fill="#282828" d="m147.409 47.959c-0.681 1.466 5.221 3.415 7.094 5.039 2.305 2.013 2.521 5.573 4.813 4.198 1.637-0.962 0.07-3.344-2.54-6.268-3.782-4.26-8.717-4.218-9.367-2.969z"/>\r
+   <path fill="#2d2d2d" d="m147.898 48.156c-0.677 1.379 4.784 3.203 6.63 4.795 2.242 1.949 2.457 5.333 4.622 4.039 1.572-0.92 0.016-3.24-2.425-5.98-3.526-3.983-8.177-4.034-8.827-2.854z"/>\r
+   <path fill="#333" d="m148.386 48.353c-0.673 1.292 4.348 2.99 6.167 4.552 2.179 1.886 2.394 5.095 4.432 3.88 1.506-0.878-0.038-3.136-2.312-5.693-3.268-3.705-7.636-3.85-8.287-2.739z"/>\r
+   <path fill="#383838" d="m148.875 48.549c-0.668 1.206 3.911 2.778 5.703 4.309 2.116 1.823 2.331 4.855 4.242 3.721 1.439-0.836-0.093-3.032-2.197-5.405-3.013-3.428-7.098-3.667-7.748-2.625z"/>\r
+   <path fill="#3d3d3d" d="m149.363 48.746c-0.662 1.119 3.475 2.566 5.24 4.065 2.053 1.759 2.268 4.616 4.052 3.562 1.375-0.795-0.147-2.928-2.082-5.118-2.757-3.15-6.559-3.483-7.21-2.509z"/>\r
+   <path fill="#424242" d="m149.851 48.942c-0.657 1.032 3.039 2.354 4.776 3.823 1.99 1.696 2.205 4.376 3.861 3.402 1.31-0.753-0.201-2.824-1.967-4.831-2.5-2.871-6.018-3.298-6.67-2.394z"/>\r
+   <path fill="#474747" d="m150.34 49.139c-0.652 0.946 2.603 2.142 4.313 3.58 1.927 1.632 2.143 4.137 3.671 3.243 1.244-0.712-0.256-2.72-1.853-4.543-2.245-2.595-5.48-3.115-6.131-2.28z"/>\r
+   <path fill="#4c4c4c" d="m150.828 49.336c-0.647 0.859 2.166 1.93 3.851 3.336 1.863 1.569 2.079 3.898 3.48 3.084 1.179-0.67-0.31-2.616-1.739-4.255-1.988-2.317-4.94-2.932-5.592-2.165z"/>\r
+   <path fill="#515151" d="m151.317 49.533c-0.645 0.772 1.729 1.718 3.386 3.093 1.802 1.505 2.018 3.658 3.29 2.925 1.114-0.628-0.364-2.512-1.624-3.968-1.732-2.04-4.4-2.748-5.052-2.05z"/>\r
+   <path fill="#565656" d="m151.805 49.729c-0.639 0.685 1.293 1.505 2.923 2.85 1.738 1.442 1.954 3.419 3.1 2.766 1.048-0.586-0.418-2.408-1.509-3.681-1.476-1.762-3.862-2.563-4.514-1.935z"/>\r
+   <path fill="#5b5b5b" d="m152.293 49.926c-0.633 0.598 0.857 1.293 2.46 2.606 1.677 1.379 1.892 3.18 2.91 2.606 0.983-0.544-0.473-2.304-1.395-3.393-1.22-1.483-3.322-2.379-3.975-1.819z"/>\r
+   <path fill="#606060" d="m152.782 50.123c-0.629 0.512 0.42 1.081 1.996 2.363 1.613 1.315 1.828 2.94 2.719 2.447 0.918-0.502-0.525-2.2-1.28-3.105-0.963-1.207-2.782-2.196-3.435-1.705z"/>\r
+   <path fill="#666" d="m153.27 50.319c-0.624 0.425-0.017 0.869 1.533 2.12 1.55 1.252 1.765 2.701 2.528 2.288 0.853-0.461-0.581-2.096-1.166-2.818-0.706-0.929-2.242-2.012-2.895-1.59z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m193.47 45.594c-0.072 1.08 2.951 1.728 4.896 2.448 1.944 0.648 5.76 3.24 7.56 5.256 1.801 1.944 5.688 7.704 6.553 6.192 0.863-1.368-2.017-5.328-2.809-6.984s-3.239-5.256-7.128-6.48c-3.384-1.008-9-1.297-9.072-0.432z"/>\r
+   <path fill="#060606" d="m193.779 45.67c-0.071 1.05 2.869 1.685 4.758 2.387 1.891 0.633 5.598 3.161 7.345 5.122 1.747 1.893 5.535 7.493 6.376 6.027 0.84-1.328-1.936-5.173-2.738-6.795-0.8-1.622-3.175-5.09-6.952-6.301-3.282-0.995-8.718-1.28-8.789-0.44z"/>\r
+   <path fill="#0c0c0c" d="m194.088 45.747c-0.07 1.021 2.785 1.641 4.62 2.327 1.836 0.618 5.436 3.081 7.131 4.988 1.692 1.842 5.382 7.282 6.198 5.862 0.814-1.288-1.855-5.019-2.67-6.607-0.808-1.587-3.11-4.925-6.776-6.122-3.178-0.983-8.433-1.264-8.503-0.448z"/>\r
+   <path fill="#131313" d="m194.397 45.824c-0.071 0.991 2.702 1.598 4.481 2.267 1.782 0.603 5.272 3.001 6.916 4.854 1.64 1.791 5.229 7.071 6.022 5.697 0.788-1.248-1.776-4.865-2.603-6.418-0.815-1.554-3.044-4.759-6.599-5.942-3.073-0.973-8.148-1.251-8.217-0.458z"/>\r
+   <path fill="#191919" d="m194.706 45.9c-0.069 0.961 2.618 1.555 4.345 2.206 1.728 0.588 5.109 2.922 6.7 4.721 1.586 1.74 5.075 6.86 5.846 5.531 0.764-1.207-1.696-4.711-2.532-6.23-0.824-1.519-2.979-4.593-6.424-5.763-2.972-0.959-7.866-1.234-7.935-0.465z"/>\r
+   <path fill="#1f1f1f" d="m195.015 45.977c-0.07 0.931 2.534 1.511 4.207 2.146 1.672 0.573 4.945 2.843 6.485 4.586 1.531 1.689 4.921 6.649 5.668 5.367 0.738-1.167-1.616-4.557-2.464-6.042-0.832-1.485-2.914-4.428-6.247-5.583-2.868-0.948-7.581-1.219-7.649-0.474z"/>\r
+   <path fill="#262626" d="m195.324 46.054c-0.069 0.901 2.451 1.468 4.069 2.085 1.618 0.557 4.784 2.763 6.271 4.453 1.479 1.638 4.769 6.438 5.491 5.201 0.714-1.127-1.536-4.402-2.396-5.854-0.839-1.451-2.848-4.263-6.07-5.404-2.765-0.934-7.298-1.202-7.365-0.481z"/>\r
+   <path fill="#2c2c2c" d="m195.632 46.13c-0.067 0.872 2.369 1.424 3.933 2.025 1.563 0.542 4.621 2.684 6.056 4.318 1.424 1.587 4.615 6.228 5.315 5.036 0.688-1.086-1.456-4.248-2.326-5.665-0.848-1.416-2.783-4.097-5.896-5.224-2.662-0.923-7.015-1.187-7.082-0.49z"/>\r
+   <path fill="#333" d="m195.941 46.207c-0.068 0.842 2.285 1.381 3.794 1.964 1.51 0.527 4.458 2.605 5.842 4.185 1.37 1.536 4.461 6.016 5.138 4.871 0.662-1.046-1.377-4.093-2.258-5.476-0.855-1.382-2.718-3.932-5.718-5.045-2.56-0.911-6.732-1.172-6.798-0.499z"/>\r
+   <path fill="#393939" d="m196.25 46.284c-0.066 0.813 2.202 1.338 3.656 1.904 1.456 0.512 4.296 2.525 5.627 4.051 1.317 1.485 4.308 5.805 4.961 4.706 0.638-1.006-1.296-3.939-2.188-5.288-0.863-1.348-2.652-3.766-5.542-4.866-2.457-0.899-6.449-1.157-6.514-0.507z"/>\r
+   <path fill="#3f3f3f" d="m196.559 46.36c-0.067 0.783 2.118 1.295 3.518 1.844 1.402 0.497 4.133 2.446 5.412 3.917 1.263 1.434 4.155 5.594 4.785 4.541 0.612-0.966-1.217-3.785-2.12-5.1-0.872-1.313-2.587-3.6-5.366-4.687-2.353-0.886-6.165-1.141-6.229-0.515z"/>\r
+   <path fill="#464646" d="m196.868 46.437c-0.065 0.753 2.035 1.251 3.38 1.783 1.349 0.482 3.972 2.367 5.197 3.783 1.21 1.383 4.002 5.383 4.608 4.375 0.588-0.926-1.137-3.63-2.052-4.911-0.879-1.279-2.521-3.435-5.189-4.507-2.25-0.874-5.881-1.125-5.944-0.523z"/>\r
+   <path fill="#4c4c4c" d="m197.177 46.514c-0.066 0.723 1.95 1.208 3.241 1.723 1.293 0.467 3.809 2.287 4.983 3.649 1.155 1.332 3.848 5.172 4.431 4.21 0.563-0.885-1.057-3.476-1.982-4.723-0.888-1.245-2.456-3.269-5.014-4.328-2.146-0.862-5.597-1.109-5.659-0.531z"/>\r
+   <path fill="#525252" d="m197.486 46.591c-0.066 0.693 1.868 1.164 3.104 1.662 1.239 0.452 3.646 2.208 4.769 3.515 1.102 1.281 3.695 4.961 4.254 4.045 0.537-0.845-0.976-3.321-1.913-4.534-0.896-1.21-2.391-3.103-4.838-4.148-2.044-0.851-5.315-1.095-5.376-0.54z"/>\r
+   <path fill="#595959" d="m197.795 46.667c-0.064 0.664 1.784 1.121 2.968 1.602 1.184 0.437 3.481 2.128 4.552 3.381 1.049 1.23 3.542 4.75 4.078 3.88 0.512-0.805-0.897-3.167-1.846-4.346-0.902-1.176-2.325-2.938-4.66-3.969-1.942-0.838-5.031-1.078-5.092-0.548z"/>\r
+   <path fill="#5f5f5f" d="m198.104 46.744c-0.065 0.634 1.701 1.078 2.829 1.541 1.13 0.421 3.318 2.049 4.338 3.248 0.994 1.179 3.388 4.539 3.899 3.715 0.487-0.765-0.815-3.013-1.775-4.157-0.911-1.142-2.261-2.772-4.485-3.79-1.837-0.826-4.746-1.064-4.806-0.557z"/>\r
+   <path fill="#666" d="m198.413 46.821c-0.063 0.604 1.617 1.034 2.691 1.481 1.076 0.406 3.157 1.969 4.123 3.113 0.94 1.128 3.234 4.328 3.724 3.55 0.462-0.725-0.737-2.858-1.707-3.969-0.919-1.108-2.195-2.606-4.309-3.61-1.734-0.814-4.463-1.049-4.522-0.565z"/>\r
+   <path fill="#6c6c6c" d="m198.721 46.897c-0.063 0.574 1.534 0.991 2.554 1.42 1.021 0.391 2.994 1.89 3.908 2.979 0.887 1.077 3.082 4.117 3.548 3.384 0.436-0.685-0.657-2.704-1.64-3.78-0.927-1.074-2.13-2.44-4.132-3.431-1.631-0.8-4.179-1.031-4.238-0.572z"/>\r
+   <path fill="#727272" d="m199.03 46.974c-0.063 0.544 1.451 0.948 2.416 1.36 0.967 0.376 2.831 1.811 3.694 2.846 0.833 1.026 2.928 3.906 3.369 3.219 0.411-0.644-0.576-2.549-1.569-3.592-0.936-1.04-2.064-2.275-3.956-3.251-1.528-0.79-3.896-1.017-3.954-0.582z"/>\r
+   <path fill="#797979" d="m199.339 47.051c-0.062 0.515 1.368 0.904 2.278 1.299 0.913 0.361 2.669 1.731 3.479 2.712 0.779 0.975 2.774 3.695 3.193 3.054 0.386-0.604-0.497-2.396-1.501-3.403-0.942-1.005-1.999-2.11-3.78-3.072-1.424-0.778-3.612-1.002-3.669-0.59z"/>\r
+   <path fill="#7f7f7f" d="m199.648 47.127c-0.063 0.485 1.284 0.861 2.14 1.239 0.859 0.346 2.506 1.652 3.265 2.578 0.726 0.924 2.621 3.484 3.017 2.889 0.361-0.564-0.417-2.241-1.432-3.215-0.951-0.971-1.935-1.944-3.604-2.893-1.323-0.765-3.33-0.986-3.386-0.598z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#995900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.017 11.592-31.104 19.152-13.968 9.576-18.792 13.824-23.328 18.359-7.056 7.057-13.752 9.432-24.48 9.432s-15.552-2.231-18.863-5.184c-3.313-2.88-6.984-10.225-6.624-21.168 0.288-10.872 3.744-20.809 5.399-37.729 0.721-7.271 0.648-16.271 0.648-24.264 0-10.08 0.144-18.648 2.304-19.943 3.889-2.448 4.752-2.592 9.36-2.592 4.607 0 6.696 0.287 8.208 1.799 1.439 1.44 0.864 4.752 0.359 9.433-0.432 4.681 1.801 6.192 4.032 8.136 2.232 1.872 4.248 4.248 11.305 4.824 7.056 0.504 9.647-0.648 12.96-2.736 3.312-2.088 7.991-5.832 9.72-7.992 1.656-2.088 5.76-9.287 6.552-9.287 0.719 0 5.472-1.656 8.136 2.232z"/>\r
+   <path fill="#9e5e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.12 11.556-31.26 19.008-13.885 9.371-18.903 13.54-23.521 17.902-6.912 6.74-13.414 9.084-23.915 9.019-10.411-0.047-15.116-2.181-18.414-5.118-3.297-2.867-6.931-9.966-6.613-20.578 0.205-10.851 3.701-20.683 5.256-37.279 0.666-7.379 0.407-16.303 0.335-24.375-0.076-10.068-0.072-18.627 2.084-19.922 3.889-2.444 4.752-2.592 9.36-2.592 4.607 0 6.7 0.291 8.208 1.799 1.491 1.492 0.767 4.887 0.205 9.408-0.63 4.658 1.458 6.486 3.795 8.607 2.34 2.059 4.489 4.471 11.534 5.021 7.232 0.482 10.015-0.832 13.362-3.106 3.303-2.207 7.773-5.903 9.513-8.168 1.641-2.132 5.727-9.386 6.519-9.386 0.719 0 5.472-1.656 8.136 2.232z"/>\r
+   <path fill="#a36400" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.226 11.52-31.414 18.863-13.803 9.166-19.016 13.256-23.717 17.447-6.768 6.422-13.075 8.733-23.35 8.604-10.094-0.094-14.682-2.131-17.964-5.055-3.283-2.852-6.876-9.705-6.603-19.987 0.122-10.828 3.657-20.556 5.112-36.828 0.612-7.487 0.165-16.336 0.021-24.487-0.15-10.058-0.287-18.605 1.865-19.9 3.889-2.44 4.752-2.592 9.36-2.592 4.607 0 6.703 0.295 8.208 1.799 1.541 1.541 0.67 5.02 0.051 9.383-0.828 4.637 1.116 6.781 3.556 9.078 2.448 2.248 4.731 4.695 11.766 5.221 7.409 0.461 10.383-1.016 13.767-3.477 3.29-2.326 7.552-5.977 9.302-8.346 1.627-2.175 5.695-9.482 6.487-9.482 0.72-0.001 5.473-1.657 8.137 2.231z"/>\r
+   <path fill="#a86a00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.329 11.484-31.568 18.72-13.721 8.961-19.127 12.972-23.911 16.989-6.624 6.105-12.737 8.384-22.785 8.189-9.777-0.141-14.245-2.08-17.514-4.99-3.27-2.836-6.822-9.445-6.591-19.396 0.038-10.807 3.613-20.43 4.968-36.378 0.558-7.597-0.076-16.368-0.292-24.599-0.228-10.047-0.504-18.584 1.645-19.879 3.889-2.438 4.752-2.592 9.36-2.592 4.607 0 6.707 0.299 8.208 1.799 1.591 1.593 0.573 5.152-0.104 9.357-1.025 4.615 0.774 7.077 3.319 9.551 2.556 2.434 4.972 4.918 11.995 5.418 7.585 0.439 10.75-1.199 14.17-3.849 3.279-2.444 7.333-6.048 9.093-8.521 1.613-2.219 5.663-9.58 6.455-9.58 0.719 0.001 5.472-1.655 8.136 2.233z"/>\r
+   <path fill="#ad7000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.434 11.447-31.724 18.576-13.637 8.756-19.238 12.687-24.106 16.531-6.479 5.789-12.397 8.035-22.219 7.776-9.461-0.188-13.809-2.03-17.063-4.925-3.254-2.823-6.769-9.188-6.581-18.807-0.043-10.785 3.571-20.305 4.824-35.928 0.504-7.705-0.316-16.402-0.604-24.711-0.303-10.037-0.72-18.563 1.425-19.857 3.889-2.434 4.752-2.592 9.36-2.592 4.607 0 6.711 0.303 8.208 1.799 1.642 1.643 0.475 5.285-0.259 9.332-1.225 4.594 0.432 7.373 3.082 10.022 2.664 2.621 5.212 5.142 12.225 5.616 7.762 0.418 11.117-1.383 14.573-4.219 3.269-2.563 7.113-6.121 8.885-8.698 1.598-2.261 5.63-9.677 6.422-9.677 0.719 0.002 5.472-1.654 8.136 2.234z"/>\r
+   <path fill="#b27500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.538 11.412-31.879 18.432-13.554 8.551-19.35 12.402-24.3 16.074-6.336 5.473-12.06 7.686-21.654 7.361-9.144-0.233-13.374-1.979-16.613-4.859-3.24-2.809-6.714-8.928-6.57-18.216-0.126-10.765 3.528-20.179 4.68-35.478 0.45-7.813-0.558-16.435-0.918-24.822-0.378-10.026-0.936-18.541 1.206-19.836 3.889-2.43 4.752-2.592 9.36-2.592 4.607 0 6.714 0.305 8.208 1.799 1.691 1.693 0.378 5.418-0.414 9.307-1.422 4.572 0.09 7.668 2.844 10.494 2.772 2.808 5.454 5.363 12.456 5.814 7.938 0.396 11.484-1.566 14.977-4.591 3.258-2.682 6.894-6.192 8.676-8.874 1.584-2.304 5.598-9.773 6.39-9.773 0.718 0 5.471-1.656 8.135 2.232z"/>\r
+   <path fill="#b77b00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.643 11.376-32.033 18.288-13.472 8.345-19.461 12.118-24.494 15.616-6.192 5.156-11.723 7.338-21.089 6.949-8.827-0.281-12.938-1.93-16.164-4.795-3.226-2.795-6.66-8.67-6.56-17.627-0.209-10.742 3.485-20.052 4.536-35.027 0.396-7.92-0.799-16.467-1.23-24.934-0.454-10.015-1.152-18.52 0.985-19.814 3.889-2.426 4.752-2.592 9.36-2.592 4.607 0 6.718 0.31 8.208 1.799 1.743 1.744 0.281 5.553-0.569 9.281-1.62 4.551-0.252 7.963 2.607 10.967 2.88 2.994 5.694 5.586 12.686 6.012 8.115 0.373 11.852-1.75 15.379-4.961 3.248-2.801 6.676-6.264 8.469-9.051 1.568-2.348 5.564-9.871 6.356-9.871 0.72 0 5.473-1.656 8.137 2.232z"/>\r
+   <path fill="#bc8100" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.747 11.34-32.188 18.145-13.389 8.139-19.574 11.834-24.689 15.159-6.048 4.839-11.383 6.988-20.523 6.534-8.51-0.328-12.503-1.879-15.714-4.73-3.211-2.779-6.606-8.41-6.549-17.035-0.292-10.721 3.441-19.926 4.393-34.578 0.342-8.028-1.041-16.498-1.545-25.045-0.529-10.004-1.368-18.498 0.767-19.793 3.889-2.422 4.752-2.592 9.36-2.592 4.607 0 6.721 0.313 8.208 1.799 1.793 1.793 0.184 5.686-0.723 9.256-1.818 4.529-0.595 8.259 2.367 11.438 2.988 3.184 5.938 5.811 12.917 6.211 8.291 0.352 12.22-1.934 15.783-5.332 3.236-2.92 6.454-6.336 8.258-9.227 1.556-2.391 5.533-9.969 6.325-9.969 0.72-0.001 5.473-1.657 8.137 2.231z"/>\r
+   <path fill="#c18700" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.852 11.304-32.343 18-13.306 7.936-19.685 11.549-24.883 14.703-5.904 4.521-11.045 6.638-19.959 6.119-8.193-0.375-12.067-1.828-15.264-4.666-3.197-2.764-6.553-8.149-6.537-16.444-0.375-10.699 3.397-19.8 4.248-34.128 0.288-8.137-1.282-16.531-1.858-25.156-0.604-9.994-1.584-18.477 0.547-19.771 3.889-2.42 4.752-2.592 9.36-2.592 4.607 0 6.725 0.316 8.208 1.799 1.843 1.845 0.087 5.818-0.878 9.231-2.017 4.507-0.937 8.554 2.131 11.909 3.096 3.369 6.178 6.033 13.146 6.408 8.468 0.33 12.587-2.117 16.187-5.703 3.225-3.038 6.235-6.408 8.049-9.402 1.541-2.436 5.501-10.066 6.293-10.066 0.72-0.001 5.473-1.657 8.137 2.231z"/>\r
+   <path fill="#c68c00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.955 11.268-32.498 17.855-13.223 7.73-19.796 11.266-25.077 14.246-5.761 4.204-10.706 6.289-19.394 5.707-7.877-0.423-11.631-1.779-14.813-4.602-3.183-2.751-6.498-7.891-6.527-15.855-0.457-10.677 3.355-19.674 4.104-33.678 0.234-8.244-1.521-16.563-2.17-25.268-0.681-9.983-1.8-18.455 0.327-19.75 3.889-2.416 4.752-2.592 9.36-2.592 4.607 0 6.729 0.32 8.208 1.799 1.894 1.895-0.011 5.951-1.033 9.207-2.214 4.484-1.278 8.848 1.895 12.379 3.203 3.558 6.418 6.258 13.377 6.607 8.644 0.309 12.952-2.301 16.589-6.074 3.215-3.156 6.016-6.479 7.841-9.58 1.526-2.477 5.468-10.162 6.26-10.162 0.718 0.001 5.471-1.655 8.135 2.233z"/>\r
+   <path fill="#cc9200" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.061 11.232-32.652 17.712-13.141 7.524-19.908 10.979-25.272 13.788-5.616 3.888-10.368 5.939-18.828 5.292-7.56-0.468-11.195-1.728-14.363-4.536-3.168-2.736-6.444-7.632-6.517-15.264-0.54-10.656 3.313-19.549 3.96-33.229 0.181-8.352-1.764-16.596-2.483-25.38-0.757-9.972-2.017-18.433 0.107-19.728 3.889-2.412 4.752-2.592 9.36-2.592 4.607 0 6.731 0.323 8.208 1.799 1.944 1.945-0.108 6.084-1.188 9.181-2.412 4.464-1.62 9.144 1.656 12.853 3.313 3.744 6.66 6.479 13.608 6.803 8.819 0.289 13.319-2.483 16.991-6.443 3.204-3.275 5.797-6.553 7.633-9.756 1.512-2.52 5.436-10.26 6.228-10.26 0.719 0 5.472-1.656 8.136 2.232z"/>\r
+   <path fill="#d19800" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.164 11.195-32.808 17.568-13.057 7.318-20.019 10.695-25.466 13.33-5.473 3.571-10.03 5.592-18.263 4.879-7.243-0.516-10.761-1.678-13.914-4.472-3.153-2.722-6.391-7.372-6.506-14.674-0.623-10.634 3.27-19.422 3.816-32.778 0.126-8.459-2.005-16.627-2.797-25.49-0.832-9.961-2.232-18.412-0.112-19.707 3.889-2.408 4.752-2.592 9.36-2.592 4.607 0 6.736 0.328 8.208 1.799 1.995 1.996-0.205 6.219-1.343 9.156-2.61 4.442-1.962 9.438 1.419 13.323 3.42 3.931 6.9 6.703 13.838 7.002 8.997 0.267 13.687-2.668 17.395-6.815 3.194-3.395 5.577-6.623 7.424-9.932 1.497-2.564 5.403-10.357 6.195-10.357 0.721 0 5.474-1.656 8.138 2.232z"/>\r
+   <path fill="#d69e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.27 11.16-32.962 17.424-12.975 7.114-20.132 10.412-25.661 12.874-5.327 3.254-9.69 5.242-17.697 4.464-6.927-0.563-10.325-1.627-13.464-4.406-3.14-2.707-6.337-7.113-6.494-14.084-0.706-10.611 3.225-19.295 3.672-32.328 0.072-8.567-2.247-16.66-3.111-25.603-0.907-9.95-2.448-18.39-0.331-19.685 3.889-2.404 4.752-2.592 9.36-2.592 4.607 0 6.739 0.332 8.208 1.799 2.045 2.045-0.302 6.352-1.497 9.131-2.808 4.421-2.304 9.734 1.18 13.795 3.528 4.119 7.144 6.927 14.069 7.199 9.173 0.246 14.055-2.851 17.799-7.185 3.182-3.514 5.356-6.696 7.214-10.108 1.483-2.607 5.371-10.455 6.163-10.455 0.719 0 5.472-1.656 8.136 2.232z"/>\r
+   <path fill="#dba300" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.373 11.124-33.116 17.279-12.893 6.91-20.243 10.127-25.855 12.418-5.184 2.937-9.353 4.892-17.133 4.05-6.609-0.609-9.889-1.577-13.014-4.343-3.125-2.692-6.282-6.854-6.483-13.492-0.789-10.592 3.182-19.17 3.528-31.879 0.018-8.676-2.488-16.692-3.425-25.713-0.982-9.94-2.664-18.369-0.551-19.664 3.889-2.401 4.752-2.592 9.36-2.592 4.607 0 6.743 0.334 8.208 1.799 2.095 2.097-0.399 6.484-1.652 9.105-3.006 4.398-2.646 10.029 0.943 14.268 3.636 4.305 7.384 7.148 14.299 7.397 9.349 0.224 14.422-3.034 18.202-7.558 3.171-3.631 5.137-6.768 7.005-10.284 1.469-2.649 5.339-10.552 6.131-10.552 0.72 0.001 5.473-1.655 8.137 2.233z"/>\r
+   <path fill="#e0a900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.478 11.088-33.271 17.136-12.81 6.704-20.354 9.843-26.05 11.96-5.04 2.62-9.015 4.543-16.567 3.637-6.293-0.656-9.453-1.527-12.563-4.277-3.11-2.68-6.229-6.596-6.474-12.903-0.871-10.569 3.141-19.044 3.384-31.428-0.035-8.784-2.728-16.726-3.735-25.826-1.06-9.929-2.88-18.347-0.771-19.642 3.889-2.397 4.752-2.592 9.36-2.592 4.607 0 6.747 0.338 8.208 1.799 2.146 2.146-0.497 6.617-1.808 9.08-3.203 4.377-2.987 10.324 0.706 14.738 3.744 4.493 7.624 7.373 14.529 7.596 9.526 0.203 14.789-3.217 18.605-7.926 3.161-3.752 4.918-6.841 6.797-10.463 1.454-2.693 5.306-10.648 6.098-10.648 0.719-0.001 5.472-1.657 8.136 2.231z"/>\r
+   <path fill="#e5af00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.582 11.052-33.427 16.992-12.726 6.498-20.466 9.558-26.244 11.502-4.896 2.304-8.676 4.193-16.002 3.222-5.976-0.702-9.018-1.476-12.114-4.212-3.096-2.664-6.174-6.336-6.462-12.313-0.953-10.547 3.097-18.918 3.24-30.978-0.09-8.892-2.97-16.758-4.05-25.938-1.134-9.918-3.096-18.324-0.99-19.619 3.889-2.395 4.752-2.592 9.36-2.592 4.607 0 6.75 0.342 8.208 1.799 2.196 2.197-0.594 6.75-1.962 9.055-3.402 4.355-3.33 10.619 0.468 15.21 3.852 4.681 7.866 7.597 14.76 7.794 9.702 0.18 15.156-3.402 19.008-8.298 3.15-3.87 4.698-6.912 6.589-10.638 1.439-2.736 5.273-10.746 6.065-10.746 0.72 0 5.473-1.656 8.137 2.232z"/>\r
+   <path fill="#eab500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.687 11.016-33.582 16.848-12.643 6.293-20.576 9.274-26.438 11.045-4.752 1.987-8.338 3.846-15.438 2.809-5.658-0.75-8.582-1.426-11.664-4.147-3.08-2.649-6.119-6.077-6.45-11.722-1.037-10.526 3.053-18.792 3.096-30.528-0.144-9-3.211-16.79-4.363-26.049-1.21-9.907-3.312-18.304-1.21-19.599 3.889-2.391 4.752-2.592 9.36-2.592 4.607 0 6.754 0.346 8.208 1.799 2.247 2.248-0.691 6.885-2.117 9.029-3.6 4.336-3.672 10.916 0.231 15.682 3.96 4.867 8.106 7.82 14.989 7.992 9.879 0.158 15.523-3.586 19.411-8.668 3.141-3.99 4.479-6.984 6.38-10.814 1.426-2.78 5.241-10.844 6.033-10.844 0.721-0.001 5.474-1.657 8.138 2.231z"/>\r
+   <path fill="#efba00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.791 10.98-33.735 16.703-12.562 6.089-20.69 8.99-26.633 10.589-4.608 1.67-7.999 3.496-14.872 2.394-5.343-0.796-8.147-1.375-11.215-4.082-3.066-2.636-6.065-5.818-6.439-11.132-1.12-10.504 3.009-18.666 2.952-30.077-0.198-9.109-3.453-16.822-4.677-26.162-1.285-9.896-3.528-18.281-1.43-19.576 3.889-2.387 4.752-2.592 9.36-2.592 4.607 0 6.757 0.35 8.208 1.799 2.297 2.297-0.788 7.018-2.271 9.004-3.798 4.314-4.014 11.211-0.008 16.154 4.068 5.055 8.35 8.043 15.221 8.189 10.056 0.137 15.892-3.77 19.815-9.039 3.128-4.107 4.258-7.057 6.17-10.99 1.411-2.824 5.209-10.941 6.001-10.941 0.72-0.001 5.473-1.657 8.137 2.231z"/>\r
+   <path fill="#f4c000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.896 10.943-33.891 16.561-12.478 5.883-20.801 8.704-26.827 10.131-4.464 1.353-7.661 3.146-14.307 1.979-5.025-0.843-7.711-1.325-10.765-4.019-3.053-2.621-6.012-5.558-6.429-10.541-1.203-10.482 2.966-18.539 2.809-29.627-0.253-9.217-3.694-16.855-4.99-26.272-1.361-9.886-3.744-18.261-1.649-19.556 3.889-2.383 4.752-2.592 9.36-2.592 4.607 0 6.761 0.353 8.208 1.799 2.347 2.349-0.885 7.15-2.426 8.979-3.996 4.291-4.356 11.505-0.245 16.625 4.176 5.241 8.59 8.265 15.451 8.388 10.23 0.115 16.258-3.953 20.218-9.41 3.117-4.227 4.039-7.129 5.961-11.168 1.396-2.865 5.177-11.037 5.969-11.037 0.72 0 5.473-1.656 8.137 2.232z"/>\r
+   <path fill="#f9c600" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.999 10.908-34.046 16.416-12.395 5.678-20.912 8.421-27.021 9.674-4.32 1.036-7.322 2.797-13.741 1.566-4.709-0.891-7.275-1.275-10.314-3.953-3.037-2.607-5.958-5.299-6.419-9.951-1.284-10.461 2.925-18.414 2.664-29.178-0.306-9.324-3.934-16.887-5.302-26.385-1.437-9.875-3.96-18.238-1.869-19.533 3.889-2.379 4.752-2.592 9.36-2.592 4.607 0 6.765 0.356 8.208 1.799 2.397 2.398-0.983 7.283-2.581 8.955-4.194 4.269-4.698 11.799-0.482 17.096 4.284 5.429 8.83 8.488 15.682 8.586 10.407 0.094 16.625-4.137 20.621-9.781 3.106-4.345 3.819-7.199 5.753-11.344 1.382-2.909 5.144-11.135 5.936-11.135 0.718 0 5.471-1.656 8.135 2.232z"/>\r
+   <path fill="#fc0" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-22.104 10.872-34.2 16.271-12.313 5.473-21.024 8.137-27.217 9.217-4.176 0.72-6.983 2.447-13.176 1.151-4.392-0.937-6.84-1.224-9.864-3.888-3.023-2.592-5.903-5.04-6.407-9.359-1.368-10.441 2.88-18.289 2.52-28.729-0.36-9.432-4.176-16.92-5.616-26.496-1.512-9.864-4.176-18.217-2.088-19.512 3.889-2.377 4.752-2.592 9.36-2.592 4.607 0 6.768 0.359 8.208 1.799 2.448 2.449-1.08 7.416-2.736 8.929-4.392 4.248-5.04 12.096-0.72 17.567 4.392 5.617 9.072 8.713 15.912 8.785 10.584 0.071 16.992-4.32 21.023-10.152 3.097-4.465 3.601-7.272 5.544-11.521 1.368-2.952 5.112-11.231 5.904-11.231 0.72 0.001 5.473-1.655 8.137 2.233z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m236.263 275.762c-0.709-0.258-3.932-15.209-2.191-16.239 3.351-1.997 4.253-2.319 8.377-2.319s6.057 0.322 7.346 1.61c2.126 2.127-1.159 6.702-2.448 7.991-3.738 3.673-10.375 9.215-11.084 8.957z"/>\r
+   <path fill="#ffcc02" d="m236.492 275.286c-0.77-0.326-4.102-14.719-2.368-15.742 3.344-1.992 4.278-2.211 8.322-2.211 4.124 0 5.976 0.269 7.282 1.602 2.105 2.136-1.119 6.572-2.398 7.852-3.727 3.663-10.081 8.811-10.838 8.499z"/>\r
+   <path fill="#ffcc05" d="m236.721 274.809c-0.832-0.393-4.273-14.229-2.547-15.247 3.339-1.983 4.306-2.101 8.269-2.101 4.124 0 5.896 0.213 7.217 1.592 2.087 2.146-1.076 6.443-2.346 7.714-3.718 3.653-9.788 8.409-10.593 8.042z"/>\r
+   <path fill="#ffcc07" d="m236.949 274.333c-0.892-0.461-4.443-13.74-2.722-14.75 3.331-1.979 4.33-1.992 8.213-1.992 4.124 0 5.814 0.158 7.151 1.582 2.068 2.156-1.033 6.316-2.294 7.574-3.707 3.644-9.494 8.007-10.348 7.586z"/>\r
+   <path fill="#ffcd0a" d="m237.178 273.855c-0.954-0.528-4.614-13.249-2.9-14.254 3.326-1.972 4.355-1.882 8.158-1.882 4.124 0 5.734 0.104 7.089 1.572 2.048 2.166-0.993 6.187-2.243 7.437-3.699 3.634-9.202 7.605-10.104 7.127z"/>\r
+   <path fill="#ffcd0c" d="m237.407 273.377c-1.015-0.596-4.785-12.758-3.077-13.758 3.319-1.965 4.382-1.771 8.104-1.771 4.124 0 5.653 0.049 7.023 1.563 2.029 2.176-0.951 6.057-2.19 7.299-3.69 3.623-8.91 7.201-9.86 6.667z"/>\r
+   <path fill="#ffcd0f" d="m237.636 272.901c-1.077-0.662-4.956-12.27-3.256-13.261 3.313-1.959 4.408-1.663 8.05-1.663 4.124 0 5.573-0.006 6.959 1.553 2.01 2.186-0.908 5.93-2.14 7.159-3.679 3.614-8.615 6.8-9.613 6.212z"/>\r
+   <path fill="#ffcd11" d="m237.864 272.424c-1.137-0.731-5.126-11.779-3.431-12.766 3.306-1.951 4.433-1.553 7.994-1.553 4.123 0 5.492-0.061 6.895 1.543 1.991 2.193-0.867 5.801-2.089 7.021-3.669 3.606-8.321 6.397-9.369 5.755z"/>\r
+   <path fill="#ffce14" d="m238.093 271.948c-1.197-0.799-5.297-11.289-3.607-12.27 3.299-1.946 4.459-1.443 7.938-1.443 4.124 0 5.412-0.115 6.83 1.533 1.973 2.204-0.824 5.671-2.037 6.883-3.659 3.596-8.028 5.993-9.124 5.297z"/>\r
+   <path fill="#ffce16" d="m238.322 271.471c-1.26-0.867-5.468-10.801-3.786-11.773 3.293-1.939 4.485-1.334 7.884-1.334 4.124 0 5.332-0.171 6.767 1.524 1.953 2.213-0.783 5.542-1.985 6.743-3.651 3.586-7.736 5.591-8.88 4.84z"/>\r
+   <path fill="#ffce19" d="m238.551 270.995c-1.32-0.935-5.639-10.312-3.963-11.277 3.286-1.934 4.511-1.225 7.829-1.225 4.124 0 5.252-0.226 6.702 1.514 1.934 2.224-0.741 5.414-1.934 6.605-3.64 3.576-7.442 5.187-8.634 4.383z"/>\r
+   <path fill="#ffce1c" d="m238.779 270.517c-1.382-1.002-5.809-9.821-4.14-10.781 3.279-1.926 4.535-1.114 7.774-1.114 4.124 0 5.171-0.279 6.637 1.504 1.914 2.233-0.698 5.285-1.882 6.467-3.63 3.566-7.148 4.784-8.389 3.924z"/>\r
+   <path fill="#ffcf1e" d="m239.008 270.04c-1.442-1.068-5.979-9.33-4.316-10.283 3.272-1.922 4.562-1.006 7.72-1.006 4.124 0 5.09-0.334 6.572 1.494 1.895 2.244-0.657 5.156-1.83 6.328-3.622 3.556-6.857 4.383-8.146 3.467z"/>\r
+   <path fill="#ffcf21" d="m239.237 269.563c-1.505-1.137-6.151-8.841-4.495-9.788 3.267-1.914 4.588-0.896 7.666-0.896 4.124 0 5.009-0.389 6.508 1.486 1.875 2.252-0.616 5.025-1.778 6.188-3.613 3.548-6.564 3.981-7.901 3.01z"/>\r
+   <path fill="#ffcf23" d="m239.466 269.086c-1.565-1.205-6.321-8.352-4.672-9.293 3.262-1.906 4.613-0.785 7.61-0.785 4.124 0 4.93-0.444 6.444 1.476 1.855 2.261-0.573 4.897-1.728 6.052-3.601 3.537-6.269 3.575-7.654 2.55z"/>\r
+   <path fill="#ffcf26" d="m239.694 268.61c-1.627-1.273-6.492-7.861-4.849-8.796 3.255-1.901 4.64-0.677 7.556-0.677 4.124 0 4.849-0.499 6.379 1.466 1.837 2.271-0.531 4.769-1.675 5.912-3.593 3.528-5.977 3.174-7.411 2.095z"/>\r
+   <path fill="#ffd028" d="m239.923 268.133c-1.688-1.34-6.663-7.373-5.025-8.301 3.248-1.895 4.665-0.566 7.501-0.566 4.124 0 4.768-0.555 6.314 1.456 1.817 2.28-0.489 4.64-1.624 5.774-3.583 3.519-5.684 2.771-7.166 1.637z"/>\r
+   <path fill="#ffd02b" d="m240.152 267.657c-1.749-1.408-6.834-6.883-5.203-7.805 3.241-1.889 4.69-0.457 7.446-0.457 4.124 0 4.687-0.609 6.25 1.447 1.798 2.289-0.448 4.51-1.573 5.635-3.572 3.509-5.39 2.367-6.92 1.18z"/>\r
+   <path fill="#ffd02d" d="m240.381 267.178c-1.811-1.475-7.005-6.391-5.381-7.307 3.235-1.881 4.717-0.348 7.393-0.348 4.124 0 4.606-0.664 6.185 1.438 1.779 2.299-0.405 4.381-1.521 5.496-3.564 3.501-5.098 1.965-6.676 0.721z"/>\r
+   <path fill="#ffd030" d="m240.609 266.702c-1.871-1.543-7.175-5.902-5.557-6.811 3.228-1.875 4.741-0.238 7.336-0.238 4.124 0 4.526-0.719 6.122 1.428 1.759 2.31-0.364 4.252-1.471 5.357-3.552 3.49-4.803 1.562-6.43 0.264z"/>\r
+   <path fill="#ffd133" d="m240.838 266.225c-1.933-1.611-7.346-5.413-5.734-6.314 3.222-1.869 4.768-0.129 7.281-0.129 4.124 0 4.446-0.773 6.058 1.418 1.74 2.318-0.322 4.123-1.418 5.219-3.545 3.48-4.512 1.16-6.187-0.194z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m302.769 263.374c3.742 5.461-0.062 12.76 2.638 17.117-6.809-6.258-9.938-8.834-19.324 0.367 2.577-3.742 3.129-6.257 4.725-9.814 1.104-2.455 4.354-9.57 5.029-9.57 0.613-0.001 4.724-1.35 6.932 1.9z"/>\r
+   <path fill="#ffcc02" d="m302.73 263.413c3.655 5.334 0.035 12.601 2.578 16.723-6.668-6.098-9.729-8.666-18.908 0.322 2.421-3.527 3.025-6.094 4.605-9.592 1.122-2.462 4.243-9.302 4.951-9.311 0.628-0.008 4.617-1.318 6.774 1.858z"/>\r
+   <path fill="#ffcc05" d="m302.691 263.45c3.568 5.209 0.132 12.441 2.517 16.332-6.526-5.938-9.519-8.5-18.492 0.277 2.268-3.314 2.924-5.934 4.488-9.372 1.141-2.468 4.132-9.032 4.873-9.052 0.641-0.013 4.508-1.284 6.614 1.815z"/>\r
+   <path fill="#ffcc07" d="m302.652 263.487c3.48 5.086 0.229 12.282 2.457 15.939-6.386-5.777-9.311-8.332-18.076 0.232 2.111-3.1 2.819-5.771 4.369-9.15 1.158-2.475 4.021-8.762 4.795-8.791 0.655-0.019 4.399-1.254 6.455 1.77z"/>\r
+   <path fill="#ffcd0a" d="m302.614 263.524c3.393 4.96 0.323 12.123 2.396 15.549-6.245-5.617-9.102-8.164-17.66 0.188 1.955-2.887 2.716-5.611 4.251-8.93 1.176-2.481 3.91-8.494 4.716-8.533 0.67-0.027 4.291-1.219 6.297 1.726z"/>\r
+   <path fill="#ffcd0c" d="m302.575 263.562c3.306 4.835 0.419 11.964 2.335 15.155-6.104-5.457-8.891-7.996-17.244 0.143 1.8-2.673 2.613-5.449 4.133-8.707 1.194-2.488 3.8-8.225 4.638-8.273 0.684-0.036 4.182-1.189 6.138 1.682z"/>\r
+   <path fill="#ffcd0f" d="m302.536 263.599c3.219 4.71 0.517 11.805 2.275 14.765-5.963-5.299-8.683-7.83-16.828 0.098 1.644-2.461 2.51-5.289 4.015-8.486 1.212-2.496 3.688-7.956 4.559-8.016 0.698-0.04 4.075-1.155 5.979 1.639z"/>\r
+   <path fill="#ffcd11" d="m302.497 263.637c3.131 4.585 0.612 11.645 2.216 14.371-5.822-5.137-8.474-7.661-16.413 0.053 1.489-2.245 2.406-5.125 3.896-8.264 1.229-2.504 3.576-7.688 4.479-7.756 0.714-0.046 3.968-1.123 5.822 1.596z"/>\r
+   <path fill="#ffce14" d="m302.458 263.674c3.044 4.459 0.708 11.486 2.154 13.979-5.681-4.978-8.263-7.493-15.996 0.009 1.334-2.033 2.303-4.965 3.779-8.043 1.247-2.511 3.464-7.418 4.4-7.498 0.728-0.052 3.859-1.089 5.663 1.553z"/>\r
+   <path fill="#ffce16" d="m302.42 263.711c2.956 4.336 0.804 11.328 2.094 13.588-5.54-4.817-8.055-7.326-15.58-0.036 1.178-1.819 2.199-4.804 3.659-7.822 1.267-2.517 3.354-7.149 4.323-7.237 0.741-0.061 3.75-1.058 5.504 1.507z"/>\r
+   <path fill="#ffce19" d="m302.381 263.749c2.868 4.211 0.9 11.168 2.033 13.196-5.398-4.657-7.845-7.159-15.164-0.081 1.022-1.605 2.097-4.642 3.542-7.601 1.283-2.524 3.241-6.88 4.244-6.979 0.755-0.067 3.642-1.026 5.345 1.465z"/>\r
+   <path fill="#ffce1c" d="m302.342 263.788c2.78 4.084 0.997 11.008 1.973 12.803-5.258-4.498-7.635-6.991-14.748-0.127 0.867-1.391 1.994-4.479 3.424-7.379 1.302-2.531 3.13-6.61 4.166-6.719 0.768-0.074 3.532-0.992 5.185 1.422z"/>\r
+   <path fill="#ffcf1e" d="m302.302 263.825c2.693 3.959 1.093 10.85 1.913 12.411-5.117-4.338-7.427-6.825-14.333-0.172 0.713-1.177 1.891-4.317 3.307-7.157 1.318-2.537 3.018-6.342 4.086-6.461 0.784-0.08 3.426-0.959 5.027 1.379z"/>\r
+   <path fill="#ffcf21" d="m302.263 263.862c2.606 3.834 1.188 10.689 1.853 12.02-4.976-4.178-7.217-6.657-13.916-0.217 0.556-0.963 1.786-4.156 3.188-6.936 1.337-2.545 2.906-6.072 4.008-6.202 0.797-0.086 3.318-0.927 4.867 1.335z"/>\r
+   <path fill="#ffcf23" d="m302.225 263.899c2.519 3.71 1.285 10.531 1.791 11.628-4.835-4.019-7.008-6.489-13.5-0.262 0.4-0.75 1.684-3.994 3.068-6.714 1.356-2.553 2.797-5.805 3.931-5.943 0.813-0.093 3.209-0.895 4.71 1.291z"/>\r
+   <path fill="#ffcf26" d="m302.186 263.937c2.431 3.584 1.381 10.371 1.73 11.235-4.693-3.857-6.798-6.322-13.084-0.307 0.245-0.535 1.58-3.832 2.951-6.492 1.373-2.56 2.686-5.535 3.852-5.685 0.828-0.1 3.101-0.861 4.551 1.249z"/>\r
+   <path fill="#ffd028" d="m302.147 263.974c2.344 3.46 1.477 10.213 1.671 10.845-4.553-3.699-6.589-6.156-12.668-0.354 0.089-0.321 1.477-3.67 2.832-6.271 1.392-2.565 2.574-5.267 3.772-5.425 0.842-0.104 2.994-0.828 4.393 1.205z"/>\r
+   <path fill="#ffd02b" d="m302.108 264.012c2.257 3.334 1.573 10.053 1.61 10.451-4.412-3.537-6.38-5.987-12.253-0.396-0.064-0.109 1.374-3.51 2.716-6.05 1.408-2.573 2.462-4.997 3.693-5.166 0.856-0.112 2.886-0.796 4.234 1.161z"/>\r
+   <path fill="#ffd02d" d="m302.069 264.049c2.17 3.209 1.67 9.894 1.55 10.061-4.271-3.379-6.17-5.82-11.836-0.441-0.221 0.104 1.271-3.35 2.596-5.83 1.428-2.58 2.352-4.728 3.615-4.906 0.87-0.12 2.777-0.765 4.075 1.116z"/>\r
+   <path fill="#ffd030" d="m302.03 264.086c2.082 3.084 1.767 9.736 1.49 9.668-4.131-3.219-5.961-5.652-11.42-0.486-0.377 0.318 1.167-3.188 2.478-5.607 1.445-2.586 2.239-4.459 3.536-4.647 0.884-0.127 2.669-0.732 3.916 1.072z"/>\r
+   <path fill="#ffd133" d="m301.991 264.124c1.995 2.959 1.862 9.576 1.43 9.277-3.989-3.059-5.752-5.486-11.005-0.531-0.532 0.531 1.064-3.027 2.36-5.387 1.463-2.594 2.128-4.189 3.458-4.389 0.899-0.133 2.561-0.699 3.757 1.03z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m305.862 283.481c5.977 7.848 17.064 16.271 21.024 18.576 2.88 1.656 7.056 3.6 6.983 8.783-0.144 5.904-3.168 7.561-4.823 9.217-3.313 3.313-22.177 10.943-34.2 16.271-12.24 5.4-21.097 8.209-27.217 9.217-4.104 0.647-7.056 2.375-13.176 1.151-4.32-0.864-6.912-1.296-9.864-3.888-2.951-2.52-5.976-5.184-6.407-9.359-1.225-10.369 3.672-16.921 8.424-25.921 3.888-7.2 11.735-8.64 16.632-7.991 17.568 2.375 16.416-8.641 21.24-13.465 4.464-4.463 17.208-8.064 21.384-2.591z"/>\r
+   <path fill="#ffcc02" d="m305.81 283.553c5.962 7.83 17.024 16.234 20.975 18.533 2.873 1.652 7.039 3.592 6.969 8.764-0.145 5.891-3.161 7.542-4.813 9.195-3.304 3.304-22.34 10.992-34.24 16.088-12.259 5.176-20.647 7.873-26.802 8.959-4.077 0.684-7.156 2.394-13.258 1.177-4.304-0.854-6.767-1.231-9.707-3.812-2.939-2.51-5.756-4.961-6.185-9.117-1.211-10.34 3.365-16.657 8.044-25.65 3.89-7.375 11.791-8.434 16.665-7.777 17.514 2.414 16.206-8.959 21.02-13.772 4.452-4.454 17.166-8.047 21.332-2.588z"/>\r
+   <path fill="#ffcc05" d="m305.76 283.627c5.946 7.812 16.982 16.195 20.925 18.488 2.866 1.648 7.022 3.584 6.951 8.743-0.144 5.876-3.153 7.524-4.801 9.173-3.298 3.297-22.506 11.043-34.28 15.907-12.279 4.949-20.201 7.538-26.389 8.699-4.051 0.721-7.256 2.413-13.341 1.202-4.286-0.846-6.619-1.168-9.55-3.733-2.924-2.501-5.536-4.741-5.959-8.877-1.198-10.312 3.058-16.394 7.664-25.379 3.89-7.552 11.845-8.229 16.698-7.563 17.458 2.453 15.995-9.279 20.797-14.08 4.443-4.443 17.127-8.026 21.285-2.58z"/>\r
+   <path fill="#ffcc07" d="m305.707 283.702c5.935 7.791 16.943 16.156 20.876 18.444 2.859 1.644 7.007 3.574 6.935 8.722-0.144 5.862-3.146 7.508-4.79 9.151-3.288 3.289-22.668 11.093-34.319 15.726-12.298 4.723-19.753 7.202-25.974 8.44-4.024 0.756-7.357 2.431-13.423 1.226-4.27-0.836-6.473-1.101-9.394-3.654-2.911-2.492-5.317-4.52-5.735-8.635-1.185-10.285 2.75-16.133 7.284-25.109 3.892-7.727 11.9-8.023 16.731-7.35 17.402 2.494 15.785-9.599 20.575-14.389 4.433-4.432 17.087-8.007 21.234-2.572z"/>\r
+   <path fill="#ffcd0a" d="m305.655 283.774c5.92 7.773 16.904 16.119 20.826 18.4 2.854 1.642 6.99 3.566 6.919 8.703-0.143 5.848-3.138 7.488-4.779 9.129-3.28 3.281-22.832 11.143-34.358 15.543-12.317 4.498-19.307 6.867-25.561 8.182-3.997 0.793-7.457 2.45-13.506 1.251-4.252-0.828-6.325-1.036-9.236-3.577-2.896-2.482-5.096-4.298-5.51-8.393-1.172-10.258 2.443-15.869 6.904-24.84 3.892-7.901 11.955-7.818 16.763-7.135 17.349 2.532 15.576-9.918 20.355-14.697 4.422-4.422 17.046-7.987 21.183-2.566z"/>\r
+   <path fill="#ffcd0c" d="m305.603 283.847c5.906 7.756 16.864 16.081 20.777 18.358 2.846 1.635 6.973 3.557 6.901 8.68-0.142 5.835-3.131 7.472-4.767 9.107-3.273 3.273-22.997 11.193-34.399 15.361-12.337 4.273-18.858 6.533-25.146 7.924-3.971 0.829-7.557 2.469-13.588 1.276-4.234-0.82-6.179-0.972-9.078-3.5-2.884-2.474-4.878-4.076-5.287-8.152-1.158-10.229 2.137-15.606 6.523-24.569 3.895-8.076 12.01-7.611 16.797-6.92 17.293 2.571 15.366-10.236 20.134-15.004 4.412-4.411 17.006-7.969 21.133-2.561z"/>\r
+   <path fill="#ffcd0f" d="m305.552 283.92c5.892 7.736 16.824 16.043 20.728 18.313 2.839 1.634 6.957 3.55 6.886 8.66-0.142 5.821-3.124 7.454-4.756 9.086-3.266 3.267-23.161 11.243-34.438 15.179-12.356 4.047-18.411 6.198-24.733 7.666-3.943 0.865-7.656 2.486-13.67 1.301-4.218-0.812-6.032-0.908-8.922-3.422-2.869-2.465-4.656-3.855-5.063-7.91-1.145-10.203 1.83-15.344 6.145-24.299 3.895-8.252 12.064-7.408 16.83-6.707 17.237 2.61 15.154-10.557 19.912-15.313 4.399-4.399 16.963-7.949 21.081-2.554z"/>\r
+   <path fill="#ffcd11" d="m305.501 283.993c5.877 7.719 16.782 16.004 20.678 18.271 2.833 1.628 6.939 3.54 6.869 8.639-0.143 5.807-3.116 7.436-4.745 9.064-3.257 3.258-23.324 11.293-34.479 14.996-12.375 3.822-17.963 5.863-24.319 7.408-3.917 0.9-7.757 2.504-13.752 1.324-4.2-0.802-5.886-0.842-8.765-3.344-2.856-2.454-4.438-3.633-4.838-7.669-1.132-10.173 1.521-15.081 5.764-24.029 3.896-8.426 12.119-7.2 16.863-6.491 17.183 2.649 14.945-10.875 19.689-15.621 4.391-4.389 16.926-7.93 21.035-2.548z"/>\r
+   <path fill="#ffce14" d="m305.448 284.066c5.863 7.701 16.743 15.966 20.629 18.228 2.826 1.625 6.924 3.531 6.853 8.619-0.142 5.793-3.108 7.418-4.733 9.043-3.25 3.25-23.489 11.342-34.518 14.813-12.396 3.598-17.517 5.529-23.905 7.148-3.891 0.938-7.857 2.524-13.834 1.351-4.185-0.793-5.74-0.776-8.609-3.267-2.841-2.444-4.217-3.412-4.613-7.426-1.118-10.146 1.216-14.818 5.385-23.76 3.896-8.602 12.174-6.996 16.896-6.277 17.128 2.688 14.735-11.195 19.468-15.929 4.378-4.38 16.883-7.911 20.981-2.543z"/>\r
+   <path fill="#ffce16" d="m305.396 284.139c5.85 7.682 16.703 15.928 20.579 18.184 2.82 1.62 6.907 3.523 6.837 8.598-0.141 5.779-3.101 7.4-4.722 9.021-3.242 3.242-23.653 11.393-34.559 14.631-12.414 3.372-17.068 5.194-23.491 6.891-3.862 0.975-7.957 2.543-13.917 1.375-4.167-0.783-5.592-0.713-8.451-3.188-2.827-2.437-3.997-3.19-4.389-7.187-1.105-10.117 0.908-14.555 5.004-23.487 3.898-8.776 12.229-6.79 16.928-6.063 17.074 2.728 14.525-11.515 19.248-16.236 4.37-4.371 16.845-7.894 20.933-2.539z"/>\r
+   <path fill="#ffce19" d="m305.344 284.211c5.836 7.664 16.663 15.891 20.529 18.141 2.813 1.617 6.892 3.516 6.82 8.578-0.14 5.765-3.093 7.382-4.71 8.999-3.235 3.233-23.817 11.442-34.598 14.448-12.434 3.146-16.621 4.859-23.077 6.633-3.837 1.01-8.058 2.561-13.999 1.4-4.15-0.775-5.446-0.648-8.295-3.111-2.814-2.426-3.777-2.969-4.164-6.944-1.094-10.09 0.601-14.293 4.624-23.22 3.898-8.951 12.282-6.584 16.961-5.848 17.019 2.767 14.314-11.834 19.025-16.545 4.361-4.359 16.806-7.872 20.884-2.531z"/>\r
+   <path fill="#ffce1c" d="m305.292 284.286c5.822 7.646 16.623 15.852 20.481 18.096 2.806 1.613 6.874 3.507 6.804 8.558-0.141 5.751-3.086 7.364-4.699 8.978-3.227 3.227-23.981 11.492-34.638 14.267-12.453 2.921-16.173 4.524-22.663 6.374-3.81 1.046-8.158 2.578-14.082 1.424-4.133-0.766-5.299-0.583-8.137-3.033-2.801-2.416-3.558-2.748-3.94-6.703-1.08-10.062 0.293-14.029 4.244-22.947 3.9-9.127 12.338-6.379 16.994-5.635 16.964 2.805 14.105-12.152 18.805-16.853 4.348-4.351 16.763-7.856 20.831-2.526z"/>\r
+   <path fill="#ffcf1e" d="m305.241 284.358c5.808 7.627 16.582 15.814 20.432 18.053 2.799 1.609 6.856 3.498 6.787 8.536-0.141 5.738-3.079 7.347-4.688 8.957-3.219 3.218-24.145 11.541-34.677 14.084-12.473 2.695-15.727 4.188-22.25 6.115-3.783 1.083-8.258 2.599-14.163 1.448-4.116-0.756-5.153-0.518-7.981-2.954-2.786-2.408-3.337-2.526-3.716-6.462-1.066-10.034-0.013-13.766 3.864-22.678 3.901-9.303 12.393-6.172 17.027-5.42 16.908 2.844 13.896-12.473 18.583-17.16 4.338-4.337 16.723-7.835 20.782-2.519z"/>\r
+   <path fill="#ffcf21" d="m305.189 284.431c5.793 7.608 16.542 15.776 20.382 18.009 2.792 1.605 6.84 3.49 6.771 8.516-0.14 5.725-3.071 7.33-4.677 8.936-3.211 3.211-24.309 11.591-34.717 13.902-12.491 2.47-15.278 3.854-21.836 5.856-3.756 1.119-8.357 2.616-14.246 1.474-4.099-0.748-5.006-0.453-7.823-2.877-2.772-2.398-3.118-2.306-3.492-6.22-1.053-10.007-0.319-13.505 3.484-22.407 3.903-9.479 12.448-5.969 17.062-5.207 16.853 2.883 13.684-12.791 18.36-17.469 4.328-4.328 16.683-7.819 20.732-2.513z"/>\r
+   <path fill="#ffcf23" d="m305.137 284.504c5.778 7.59 16.503 15.736 20.332 17.965 2.786 1.602 6.825 3.482 6.755 8.496-0.139 5.709-3.064 7.311-4.665 8.912-3.204 3.203-24.474 11.642-34.759 13.721-12.51 2.244-14.829 3.52-21.421 5.598-3.729 1.155-8.457 2.635-14.327 1.499-4.082-0.739-4.86-0.389-7.667-2.8-2.76-2.389-2.897-2.083-3.268-5.979-1.04-9.979-0.627-13.24 3.104-22.138 3.903-9.653 12.503-5.762 17.093-4.991 16.799 2.922 13.475-13.111 18.141-17.777 4.318-4.316 16.643-7.799 20.682-2.506z"/>\r
+   <path fill="#ffcf26" d="m305.086 284.579c5.765 7.57 16.463 15.697 20.282 17.92 2.779 1.599 6.809 3.474 6.738 8.476-0.139 5.696-3.056 7.293-4.654 8.892-3.194 3.194-24.637 11.69-34.797 13.536-12.529 2.021-14.382 3.185-21.007 5.341-3.703 1.191-8.559 2.652-14.411 1.523-4.065-0.73-4.713-0.324-7.509-2.723-2.745-2.379-2.679-1.861-3.043-5.735-1.027-9.952-0.936-12.979 2.724-21.868 3.905-9.828 12.557-5.557 17.126-4.777 16.744 2.961 13.265-13.431 17.919-18.084 4.307-4.309 16.602-7.783 20.632-2.501z"/>\r
+   <path fill="#ffd028" d="m305.033 284.651c5.752 7.553 16.423 15.66 20.234 17.878 2.771 1.593 6.791 3.464 6.722 8.454-0.139 5.682-3.049 7.275-4.643 8.869-3.188 3.188-24.801 11.74-34.838 13.355-12.548 1.793-13.935 2.85-20.593 5.082-3.676 1.228-8.658 2.67-14.493 1.547-4.048-0.721-4.565-0.258-7.353-2.644-2.731-2.37-2.457-1.64-2.818-5.495-1.014-9.923-1.242-12.716 2.345-21.597 3.905-10.004 12.611-5.351 17.158-4.563 16.689 3 13.055-13.75 17.698-18.393 4.297-4.295 16.562-7.761 20.581-2.493z"/>\r
+   <path fill="#ffd02b" d="m304.982 284.724c5.737 7.534 16.382 15.622 20.184 17.834 2.766 1.59 6.774 3.456 6.705 8.433-0.138 5.67-3.041 7.26-4.631 8.85-3.18 3.179-24.966 11.789-34.877 13.172-12.568 1.568-13.487 2.515-20.179 4.824-3.65 1.263-8.759 2.688-14.575 1.572-4.031-0.713-4.42-0.195-7.196-2.566-2.718-2.361-2.238-1.42-2.594-5.254-1.001-9.896-1.549-12.453 1.964-21.328 3.907-10.178 12.666-5.145 17.192-4.348 16.634 3.039 12.844-14.068 17.476-18.701 4.285-4.286 16.521-7.743 20.531-2.488z"/>\r
+   <path fill="#ffd02d" d="m304.93 284.797c5.723 7.516 16.342 15.584 20.135 17.789 2.758 1.588 6.758 3.449 6.688 8.414-0.138 5.654-3.034 7.24-4.619 8.826-3.173 3.172-25.13 11.84-34.918 12.99-12.587 1.344-13.039 2.18-19.766 4.564-3.622 1.301-8.856 2.709-14.657 1.599-4.014-0.704-4.272-0.13-7.039-2.489-2.702-2.352-2.018-1.197-2.369-5.012-0.987-9.868-1.855-12.189 1.584-21.057 3.908-10.354 12.722-4.94 17.226-4.135 16.578 3.078 12.634-14.389 17.254-19.009 4.275-4.273 16.481-7.721 20.481-2.48z"/>\r
+   <path fill="#ffd030" d="m304.879 284.87c5.709 7.498 16.302 15.547 20.085 17.748 2.752 1.582 6.741 3.438 6.673 8.391-0.139 5.642-3.027 7.224-4.609 8.806-3.164 3.164-25.293 11.89-34.956 12.808-12.606 1.119-12.592 1.844-19.352 4.308-3.596 1.336-8.958 2.726-14.739 1.622-3.997-0.695-4.127-0.065-6.882-2.411-2.69-2.343-1.799-0.976-2.146-4.771-0.974-9.84-2.163-11.928 1.204-20.787 3.91-10.529 12.777-4.734 17.258-3.92 16.524 3.117 12.424-14.707 17.034-19.316 4.263-4.267 16.439-7.706 20.43-2.478z"/>\r
+   <path fill="#ffd133" d="m304.826 284.943c5.695 7.479 16.263 15.509 20.036 17.703 2.745 1.579 6.726 3.431 6.656 8.372-0.137 5.627-3.02 7.205-4.597 8.783-3.157 3.156-25.458 11.939-34.997 12.625-12.626 0.893-12.145 1.51-18.938 4.049-3.569 1.373-9.058 2.745-14.822 1.646-3.979-0.686-3.979 0-6.725-2.332-2.676-2.334-1.578-0.756-1.921-4.529-0.961-9.813-2.471-11.665 0.824-20.516 3.91-10.705 12.83-4.529 17.29-3.707 16.47 3.156 12.215-15.027 16.813-19.625 4.255-4.253 16.401-7.684 20.381-2.469z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#995900" d="m52.494 273.618c-6.479 4.68-22.896 4.248-27.072 9.719-4.104 5.473 0.145 13.393 0.072 28.08 0 6.265-1.08 11.017-1.8 14.832-1.008 4.824-1.656 8.209 0.36 11.664 3.672 6.121 9.575 7.633 43.344 14.688 18.072 3.744 35.136 13.464 46.584 14.399 11.448 0.865 13.896-2.951 20.88-9.144 6.912-6.192 9.144-4.248 8.928-17.856-0.216-13.535-8.928-17.567-18.792-33.191s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.208 13.248-14.688 17.929z"/>\r
+   <path fill="#9e5e00" d="m52.598 273.905c-6.397 4.702-22.475 3.788-27.062 9.512-4.154 5.414 0.228 13.276 0.098 27.955-0.025 6.23-1.152 10.881-1.937 14.877-1.037 4.871-1.678 8.201 0.349 11.619 3.787 6.162 9.695 7.123 43.456 14.168 18.061 3.737 34.541 13.307 46.343 14.112 11.186 0.792 13.564-2.829 20.463-8.96 6.896-6.195 9.024-4.277 8.858-17.406-0.075-13.521-8.305-17.349-18.169-32.973s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.153 13.479-14.583 18.216z"/>\r
+   <path fill="#a36400" d="m52.703 274.193c-6.314 4.724-22.054 3.327-27.051 9.304-4.204 5.356 0.31 13.16 0.123 27.828-0.051 6.198-1.225 10.748-2.074 14.924-1.065 4.918-1.699 8.194 0.339 11.571 3.902 6.206 9.813 6.617 43.567 13.651 18.05 3.73 33.948 13.146 46.101 13.824 10.923 0.72 13.234-2.707 20.045-8.777 6.885-6.199 8.907-4.305 8.792-16.956 0.064-13.507-7.683-17.129-17.547-32.753s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.1 13.709-14.479 18.504z"/>\r
+   <path fill="#a86a00" d="m52.807 274.481c-6.231 4.745-21.633 2.866-27.04 9.094-4.255 5.299 0.393 13.047 0.148 27.702-0.076 6.167-1.297 10.616-2.211 14.972-1.095 4.965-1.721 8.188 0.328 11.524 4.018 6.25 9.932 6.108 43.679 13.134 18.039 3.721 33.354 12.988 45.86 13.535 10.659 0.648 12.902-2.585 19.627-8.593 6.869-6.203 8.788-4.335 8.723-16.507 0.205-13.492-7.06-16.909-16.924-32.533s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.045 13.94-14.374 18.792z"/>\r
+   <path fill="#ad7000" d="m52.912 274.769c-6.149 4.767-21.211 2.405-27.029 8.885-4.306 5.242 0.476 12.931 0.173 27.576-0.101 6.136-1.368 10.483-2.347 15.019-1.123 5.012-1.742 8.181 0.316 11.478 4.133 6.293 10.052 5.603 43.791 12.614 18.028 3.716 32.76 12.83 45.619 13.248 10.396 0.576 12.57-2.463 19.21-8.409 6.854-6.206 8.668-4.363 8.653-16.056 0.347-13.479-6.437-16.69-16.301-32.314s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.991 14.169-14.269 19.079z"/>\r
+   <path fill="#b27500" d="m53.016 275.057c-6.066 4.787-20.79 1.943-27.019 8.676-4.355 5.184 0.559 12.816 0.198 27.45-0.126 6.103-1.44 10.351-2.484 15.065-1.151 5.059-1.764 8.172 0.307 11.431 4.248 6.336 10.17 5.094 43.901 12.096 18.019 3.708 32.166 12.672 45.378 12.96 10.135 0.504 12.24-2.34 18.792-8.227 6.841-6.209 8.551-4.391 8.586-15.605 0.486-13.464-5.813-16.47-15.678-32.094s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.937 14.399-14.165 19.368z"/>\r
+   <path fill="#b77b00" d="m53.121 275.344c-5.983 4.811-20.369 1.484-27.008 8.469-4.406 5.126 0.641 12.7 0.224 27.324-0.151 6.068-1.512 10.216-2.621 15.111-1.181 5.105-1.785 8.166 0.295 11.385 4.363 6.379 10.289 4.586 44.014 11.576 18.008 3.701 31.572 12.515 45.137 12.672 9.872 0.433 11.909-2.217 18.375-8.041 6.825-6.215 8.431-4.422 8.518-15.156 0.627-13.45-5.191-16.251-15.056-31.875s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.884 14.631-14.062 19.655z"/>\r
+   <path fill="#bc8100" d="m53.225 275.633c-5.9 4.832-19.948 1.023-26.997 8.259-4.457 5.069 0.724 12.585 0.249 27.198-0.177 6.037-1.584 10.082-2.758 15.158-1.21 5.152-1.808 8.158 0.284 11.338 4.479 6.422 10.407 4.078 44.125 11.059 17.997 3.693 30.979 12.355 44.896 12.384 9.608 0.36 11.578-2.095 17.957-7.858 6.812-6.217 8.313-4.449 8.45-14.707 0.766-13.435-4.569-16.03-14.434-31.654s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.829 14.859-13.956 19.943z"/>\r
+   <path fill="#c18700" d="m53.329 275.92c-5.817 4.854-19.526 0.563-26.985 8.051-4.507 5.011 0.807 12.47 0.273 27.072-0.201 6.004-1.655 9.949-2.894 15.205-1.239 5.199-1.829 8.151 0.273 11.291 4.594 6.465 10.526 3.57 44.236 10.541 17.985 3.686 30.384 12.196 44.655 12.096 9.345 0.287 11.245-1.973 17.539-7.676 6.797-6.221 8.193-4.479 8.381-14.256 0.906-13.42-3.946-15.812-13.811-31.436s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.774 15.094-13.851 20.232z"/>\r
+   <path fill="#c68c00" d="m53.433 276.209c-5.734 4.875-19.104 0.101-26.975 7.84-4.558 4.955 0.89 12.355 0.299 26.947-0.227 5.973-1.728 9.816-3.031 15.252-1.267 5.246-1.851 8.145 0.263 11.244 4.709 6.508 10.646 3.063 44.349 10.022 17.975 3.679 29.79 12.038 44.413 11.808 9.083 0.217 10.915-1.851 17.122-7.492 6.782-6.224 8.074-4.506 8.313-13.806 1.048-13.405-3.323-15.592-13.188-31.216s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.722 15.322-13.749 20.521z"/>\r
+   <path fill="#cc9200" d="m53.538 276.497c-5.651 4.896-18.684-0.359-26.964 7.633-4.607 4.896 0.972 12.24 0.324 26.82-0.252 5.939-1.8 9.684-3.168 15.299-1.296 5.293-1.872 8.137 0.252 11.196 4.824 6.552 10.764 2.556 44.46 9.505 17.964 3.672 29.196 11.879 44.172 11.52 8.82 0.144 10.584-1.729 16.704-7.309 6.768-6.228 7.956-4.535 8.244-13.355 1.188-13.393-2.7-15.372-12.564-30.996s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.668 15.551-13.644 20.807z"/>\r
+   <path fill="#d19800" d="m53.642 276.786c-5.569 4.918-18.263-0.82-26.953 7.424-4.658 4.838 1.055 12.123 0.35 26.693-0.277 5.907-1.872 9.551-3.305 15.346-1.325 5.34-1.894 8.129 0.241 11.15 4.938 6.596 10.883 2.048 44.571 8.984 17.953 3.666 28.602 11.723 43.931 11.232 8.558 0.072 10.253-1.605 16.287-7.123 6.753-6.232 7.837-4.566 8.175-12.906 1.329-13.379-2.077-15.153-11.941-30.777s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.614 15.783-13.54 21.097z"/>\r
+   <path fill="#d69e00" d="m53.747 277.073c-5.486 4.94-17.842-1.281-26.942 7.215-4.709 4.781 1.138 12.01 0.374 26.568-0.302 5.875-1.943 9.417-3.441 15.393-1.354 5.387-1.915 8.123 0.23 11.104 5.055 6.639 11.002 1.541 44.684 8.467 17.942 3.658 28.008 11.563 43.688 10.944 8.296 0 9.923-1.483 15.869-6.941 6.74-6.235 7.72-4.593 8.108-12.456 1.468-13.363-1.455-14.933-11.319-30.557s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.56 16.012-13.435 21.383z"/>\r
+   <path fill="#dba300" d="m53.851 277.361c-5.403 4.962-17.421-1.741-26.932 7.007-4.759 4.723 1.221 11.893 0.399 26.441-0.327 5.843-2.016 9.283-3.578 15.439-1.383 5.434-1.937 8.115 0.22 11.057 5.169 6.682 11.12 1.033 44.795 7.949 17.932 3.649 27.414 11.404 43.448 10.656 8.031-0.072 9.59-1.361 15.451-6.758 6.725-6.238 7.6-4.623 8.039-12.006 1.609-13.35-0.832-14.714-10.696-30.338s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.504 16.245-13.33 21.673z"/>\r
+   <path fill="#e0a900" d="m53.956 277.649c-5.321 4.982-16.999-2.203-26.921 6.797-4.81 4.666 1.303 11.779 0.425 26.316-0.353 5.811-2.088 9.15-3.715 15.486-1.411 5.48-1.959 8.108 0.208 11.01 5.285 6.725 11.239 0.525 44.907 7.431 17.92 3.644 26.819 11.246 43.207 10.368 7.769-0.145 9.259-1.239 15.034-6.574 6.71-6.242 7.479-4.65 7.97-11.557 1.75-13.334-0.209-14.493-10.073-30.117s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.452 16.474-13.226 21.96z"/>\r
+   <path fill="#e5af00" d="m54.06 277.937c-5.238 5.004-16.578-2.664-26.91 6.588-4.86 4.608 1.386 11.664 0.45 26.19-0.378 5.777-2.16 9.018-3.853 15.533-1.439 5.526-1.979 8.101 0.198 10.963 5.4 6.768 11.358 0.018 45.018 6.912 17.91 3.635 26.227 11.088 42.967 10.08 7.506-0.217 8.928-1.117 14.615-6.391 6.696-6.246 7.362-4.68 7.902-11.105 1.89-13.32 0.414-14.274-9.45-29.898s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.397 16.704-13.121 22.248z"/>\r
+   <path fill="#eab500" d="m54.165 278.225c-5.155 5.025-16.157-3.124-26.899 6.38-4.91 4.55 1.469 11.548 0.476 26.063-0.403 5.746-2.232 8.885-3.989 15.58-1.469 5.573-2.002 8.094 0.188 10.916 5.515 6.812 11.477-0.49 45.129 6.394 17.899 3.629 25.633 10.93 42.725 9.792 7.243-0.288 8.598-0.993 14.199-6.206 6.681-6.25 7.243-4.709 7.833-10.656 2.031-13.306 1.037-14.055-8.827-29.679s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.346 16.935-13.019 22.536z"/>\r
+   <path fill="#efba00" d="m54.269 278.513c-5.073 5.048-15.736-3.585-26.889 6.171-4.961 4.492 1.552 11.434 0.5 25.938-0.428 5.713-2.304 8.752-4.125 15.627-1.498 5.621-2.023 8.086 0.176 10.869 5.631 6.854 11.596-0.996 45.241 5.875 17.889 3.623 25.038 10.771 42.483 9.504 6.981-0.359 8.266-0.871 13.781-6.022 6.668-6.253 7.125-4.737 7.766-10.206 2.17-13.291 1.659-13.835-8.205-29.459s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.289 17.164-12.912 22.823z"/>\r
+   <path fill="#f4c000" d="m54.374 278.801c-4.99 5.068-15.314-4.047-26.878 5.962-5.012 4.435 1.634 11.317 0.525 25.812-0.453 5.682-2.376 8.618-4.263 15.674-1.526 5.668-2.045 8.08 0.166 10.822 5.745 6.898 11.714-1.505 45.353 5.357 17.878 3.613 24.444 10.613 42.243 9.216 6.717-0.433 7.934-0.749 13.362-5.839 6.653-6.258 7.007-4.768 7.697-9.756 2.312-13.277 2.282-13.616-7.582-29.24s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.235 17.395-12.807 23.112z"/>\r
+   <path fill="#f9c600" d="m54.477 279.088c-4.906 5.092-14.893-4.506-26.866 5.754-5.062 4.377 1.717 11.203 0.551 25.686-0.479 5.648-2.448 8.485-4.399 15.721-1.555 5.715-2.066 8.072 0.155 10.775 5.86 6.941 11.833-2.012 45.464 4.839 17.867 3.607 23.851 10.454 42.001 8.929 6.455-0.504 7.604-0.627 12.946-5.656 6.638-6.26 6.886-4.795 7.628-9.307 2.452-13.262 2.905-13.396-6.959-29.02s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.182 17.626-12.705 23.399z"/>\r
+   <path fill="#fc0" d="m54.582 279.377c-4.823 5.111-14.472-4.969-26.855 5.543-5.112 4.32 1.8 11.088 0.576 25.561-0.504 5.616-2.521 8.352-4.536 15.768-1.584 5.76-2.088 8.064 0.144 10.729 5.977 6.984 11.952-2.52 45.576 4.32 17.856 3.6 23.256 10.295 41.76 8.64 6.192-0.576 7.272-0.504 12.528-5.472 6.624-6.264 6.768-4.824 7.56-8.856 2.592-13.248 3.528-13.176-6.336-28.8s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.129 17.855-12.601 23.687z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m57.701 285.002c-4.278 4.539-18.28-1.36-24.892 3.631-4.732 3.5 2.398 7.908 1.426 20.873-0.389 4.926-3.824 5.834-2.398 12.64 1.103 5.121 2.27 4.991 4.214 7.325 5.315 6.223 4.084 1.686 34.355 7.777 16.011 3.242 20.938 9.271 37.596 7.779 5.575-0.518 6.612-0.453 11.279-4.926 5.964-5.575 2.917-4.408 3.565-7.973 2.269-11.863 0.453-13.938-8.428-28.004-8.88-14.066-8.102-14.844-13.936-24.113-5.834-9.141-13.872-25.799-20.549-25.93-5.25-0.129-8.297 2.723-11.603 6.094-3.305 3.372-5.768 19.643-10.629 24.827z"/>\r
+   <path fill="#ffcc02" d="m57.995 285.094c-4.461 4.701-18.604-1.196-25.06 3.705-4.701 3.514 2.578 8.05 1.608 20.68-0.4 4.896-3.733 5.877-2.458 12.634 0.986 5.093 2.357 4.938 4.334 7.201 5.686 6.131 4.673 1.826 34.119 7.743 15.918 3.211 20.815 9.215 37.372 7.732 5.541-0.513 6.479-0.463 11.155-4.849 5.865-5.407 2.858-4.287 3.412-8.058 2.066-11.787 0.442-13.981-8.188-27.649-8.83-13.983-8.143-14.698-13.941-23.913-5.8-9.085-13.701-25.805-20.338-25.934-5.219-0.129-8.248 2.705-11.533 6.057-3.287 3.352-5.644 19.505-10.482 24.651z"/>\r
+   <path fill="#ffcc05" d="m58.289 285.185c-4.644 4.866-18.93-1.031-25.229 3.78-4.669 3.527 2.759 8.191 1.792 20.488-0.413 4.866-3.642 5.918-2.519 12.625 0.872 5.066 2.447 4.887 4.455 7.078 6.057 6.04 5.263 1.969 33.883 7.709 15.825 3.18 20.693 9.159 37.148 7.686 5.508-0.506 6.345-0.471 11.03-4.77 5.768-5.24 2.803-4.168 3.26-8.142 1.865-11.716 0.432-14.027-7.949-27.298-8.78-13.899-8.183-14.553-13.948-23.713-5.764-9.03-13.529-25.811-20.126-25.938-5.188-0.129-8.198 2.688-11.465 6.021-3.266 3.331-5.517 19.368-10.332 24.474z"/>\r
+   <path fill="#ffcc07" d="m58.584 285.276c-4.827 5.03-19.255-0.865-25.397 3.855-4.639 3.541 2.938 8.332 1.975 20.295-0.425 4.838-3.551 5.961-2.578 12.619 0.757 5.039 2.536 4.834 4.575 6.955 6.428 5.949 5.852 2.108 33.646 7.674 15.733 3.147 20.571 9.103 36.925 7.639 5.475-0.501 6.211-0.48 10.905-4.693 5.67-5.072 2.745-4.045 3.107-8.224 1.663-11.642 0.42-14.073-7.711-26.946-8.73-13.814-8.223-14.406-13.952-23.511-5.729-8.976-13.358-25.817-19.916-25.944-5.156-0.127-8.148 2.674-11.396 5.984s-5.391 19.229-10.183 24.297z"/>\r
+   <path fill="#ffcd0a" d="m58.878 285.368c-5.01 5.193-19.579-0.701-25.565 3.93-4.607 3.555 3.117 8.475 2.157 20.102-0.437 4.809-3.459 6.004-2.639 12.613 0.643 5.011 2.626 4.781 4.695 6.83 6.799 5.857 6.442 2.25 33.411 7.64 15.641 3.118 20.45 9.048 36.701 7.593 5.44-0.494 6.076-0.488 10.781-4.615 5.57-4.904 2.688-3.926 2.954-8.308 1.462-11.569 0.409-14.118-7.472-26.593-8.68-13.732-8.263-14.262-13.958-23.311-5.695-8.922-13.188-25.824-19.705-25.951-5.125-0.127-8.1 2.658-11.326 5.949-3.227 3.289-5.266 19.091-10.034 24.121z"/>\r
+   <path fill="#ffcd0c" d="m59.173 285.458c-5.193 5.358-19.905-0.535-25.734 4.008-4.577 3.566 3.297 8.613 2.34 19.908-0.449 4.778-3.368 6.045-2.698 12.605 0.526 4.982 2.715 4.729 4.815 6.707 7.17 5.766 7.031 2.391 33.175 7.604 15.549 3.088 20.328 8.994 36.477 7.547 5.408-0.488 5.943-0.498 10.657-4.537 5.472-4.737 2.63-3.805 2.802-8.393 1.261-11.494 0.398-14.162-7.232-26.24-8.63-13.647-8.304-14.117-13.964-23.109-5.66-8.867-13.017-25.829-19.494-25.956-5.094-0.126-8.05 2.642-11.257 5.912-3.21 3.27-5.142 18.955-9.887 23.944z"/>\r
+   <path fill="#ffcd0f" d="m59.467 285.547c-5.376 5.523-20.229-0.369-25.903 4.084-4.545 3.58 3.478 8.756 2.523 19.715-0.461 4.75-3.277 6.088-2.758 12.599 0.411 4.955 2.804 4.677 4.936 6.584 7.541 5.675 7.621 2.532 32.938 7.569 15.456 3.056 20.206 8.938 36.253 7.5 5.375-0.482 5.811-0.506 10.533-4.459 5.374-4.57 2.572-3.686 2.649-8.477 1.058-11.42 0.387-14.209-6.995-25.888-8.58-13.563-8.344-13.972-13.969-22.909-5.626-8.813-12.846-25.834-19.283-25.961-5.063-0.125-8 2.625-11.188 5.877-3.188 3.251-5.015 18.818-9.736 23.766z"/>\r
+   <path fill="#ffcd11" d="m59.76 285.639c-5.559 5.688-20.555-0.205-26.071 4.158-4.515 3.594 3.657 8.896 2.706 19.521-0.473 4.721-3.186 6.131-2.818 12.594 0.297 4.926 2.894 4.623 5.057 6.459 7.911 5.584 8.21 2.674 32.703 7.535 15.362 3.025 20.084 8.883 36.027 7.453 5.342-0.477 5.677-0.515 10.409-4.381 5.275-4.402 2.516-3.564 2.497-8.561 0.855-11.348 0.375-14.254-6.756-25.535-8.53-13.479-8.385-13.825-13.976-22.709-5.59-8.758-12.673-25.842-19.071-25.965-5.031-0.125-7.951 2.608-11.119 5.838-3.168 3.232-4.888 18.684-9.588 23.593z"/>\r
+   <path fill="#ffce14" d="m60.055 285.73c-5.742 5.851-20.88-0.04-26.24 4.233-4.483 3.607 3.837 9.039 2.889 19.33-0.485 4.69-3.095 6.172-2.878 12.584 0.182 4.9 2.982 4.572 5.177 6.338 8.282 5.492 8.8 2.814 32.467 7.498 15.271 2.996 19.962 8.828 35.804 7.408 5.309-0.472 5.543-0.523 10.285-4.304 5.177-4.235 2.458-3.444 2.344-8.644 0.654-11.273 0.364-14.299-6.518-25.184-8.479-13.395-8.425-13.679-13.98-22.507-5.556-8.704-12.502-25.849-18.86-25.972-5-0.123-7.901 2.593-11.05 5.803s-4.765 18.547-9.44 23.417z"/>\r
+   <path fill="#ffce16" d="m60.349 285.821c-5.925 6.016-21.205 0.125-26.408 4.309-4.453 3.621 4.017 9.18 3.07 19.137-0.496 4.662-3.002 6.215-2.938 12.579 0.066 4.872 3.072 4.518 5.298 6.213 8.653 5.401 9.389 2.956 32.23 7.464 15.178 2.964 19.84 8.771 35.58 7.361 5.275-0.465 5.409-0.532 10.159-4.225 5.079-4.068 2.401-3.324 2.192-8.729 0.452-11.2 0.354-14.346-6.279-24.831-8.429-13.312-8.464-13.534-13.985-22.306-5.521-8.65-12.331-25.854-18.649-25.978-4.969-0.123-7.853 2.577-10.98 5.767-3.129 3.19-4.637 18.409-9.29 23.239z"/>\r
+   <path fill="#ffce19" d="m60.643 285.911c-6.107 6.18-21.529 0.291-26.577 4.385-4.421 3.635 4.197 9.322 3.254 18.945-0.508 4.631-2.911 6.256-2.997 12.571-0.049 4.845 3.161 4.465 5.418 6.089 9.023 5.309 9.979 3.098 31.994 7.43 15.085 2.934 19.718 8.717 35.355 7.314 5.242-0.459 5.276-0.541 10.036-4.148 4.98-3.899 2.344-3.203 2.039-8.811 0.25-11.127 0.342-14.391-6.04-24.479-8.38-13.228-8.505-13.389-13.991-22.105-5.486-8.596-12.16-25.859-18.438-25.982-4.938-0.123-7.803 2.561-10.911 5.73-3.109 3.17-4.513 18.272-9.142 23.061z"/>\r
+   <path fill="#ffce1c" d="m60.938 286.002c-6.291 6.344-21.855 0.455-26.746 4.459-4.391 3.648 4.377 9.463 3.437 18.752-0.521 4.603-2.82 6.299-3.058 12.564-0.163 4.817 3.251 4.413 5.539 5.965 9.395 5.219 10.567 3.24 31.758 7.396 14.993 2.903 19.597 8.661 35.132 7.269 5.209-0.453 5.143-0.55 9.912-4.07 4.882-3.732 2.286-3.082 1.887-8.895 0.048-11.053 0.329-14.436-5.802-24.126-8.33-13.144-8.545-13.243-13.997-21.905-5.451-8.541-11.988-25.865-18.228-25.988-4.906-0.121-7.753 2.545-10.843 5.695-3.088 3.149-4.385 18.132-8.991 22.884z"/>\r
+   <path fill="#ffcf1e" d="m61.232 286.092c-6.473 6.51-22.18 0.621-26.914 4.535-4.359 3.662 4.557 9.604 3.619 18.559-0.532 4.574-2.729 6.342-3.117 12.559-0.278 4.789 3.34 4.36 5.659 5.842 9.766 5.127 11.157 3.381 31.521 7.359 14.9 2.872 19.475 8.607 34.908 7.223 5.176-0.447 5.008-0.559 9.787-3.992 4.784-3.565 2.229-2.963 1.735-8.979-0.155-10.98 0.317-14.482-5.564-23.773-8.279-13.061-8.585-13.098-14.002-21.705-5.416-8.485-11.817-25.871-18.017-25.992-4.875-0.121-7.704 2.527-10.773 5.658-3.068 3.128-4.26 17.995-8.842 22.706z"/>\r
+   <path fill="#ffcf21" d="m61.526 286.184c-6.655 6.673-22.505 0.785-27.082 4.611-4.328 3.674 4.736 9.744 3.802 18.365-0.544 4.543-2.638 6.383-3.178 12.551-0.394 4.761 3.43 4.308 5.78 5.718 10.136 5.036 11.746 3.522 31.285 7.325 14.808 2.841 19.353 8.551 34.685 7.176 5.142-0.441 4.875-0.567 9.663-3.914 4.685-3.398 2.171-2.842 1.582-9.063-0.357-10.906 0.307-14.527-5.325-23.422-8.23-12.976-8.625-12.951-14.008-21.503-5.382-8.432-11.646-25.878-17.806-25.999-4.844-0.119-7.654 2.512-10.704 5.622-3.049 3.109-4.134 17.859-8.694 22.533z"/>\r
+   <path fill="#ffcf23" d="m61.821 286.275c-6.839 6.837-22.83 0.95-27.251 4.687-4.298 3.688 4.916 9.886 3.984 18.172-0.557 4.515-2.546 6.426-3.237 12.545-0.509 4.732 3.519 4.255 5.9 5.594 10.507 4.945 12.336 3.663 31.05 7.29 14.715 2.812 19.23 8.496 34.46 7.129 5.108-0.435 4.74-0.575 9.538-3.835 4.587-3.23 2.113-2.723 1.43-9.146-0.559-10.834 0.296-14.572-5.086-23.069-8.18-12.892-8.666-12.806-14.014-21.302-5.347-8.377-11.476-25.885-17.595-26.004-4.813-0.119-7.605 2.496-10.635 5.584-3.029 3.088-4.008 17.722-8.544 22.355z"/>\r
+   <path fill="#ffcf26" d="m62.115 286.366c-7.021 7.002-23.154 1.115-27.42 4.762-4.266 3.701 5.096 10.027 4.168 17.979-0.568 4.486-2.455 6.469-3.297 12.538-0.624 4.706 3.607 4.203 6.021 5.472 10.878 4.852 12.925 3.803 30.813 7.254 14.622 2.78 19.108 8.441 34.236 7.084 5.075-0.43 4.606-0.584 9.413-3.759 4.489-3.063 2.058-2.601 1.277-9.229-0.761-10.76 0.284-14.618-4.848-22.717-8.129-12.809-8.706-12.66-14.019-21.102-5.313-8.322-11.304-25.891-17.384-26.01-4.781-0.118-7.556 2.48-10.566 5.55-3.008 3.068-3.881 17.584-8.394 22.178z"/>\r
+   <path fill="#ffd028" d="m62.409 286.456c-7.204 7.166-23.479 1.281-27.588 4.838-4.235 3.715 5.275 10.168 4.351 17.787-0.58 4.455-2.364 6.51-3.357 12.53-0.738 4.679 3.697 4.149 6.142 5.347 11.249 4.763 13.515 3.946 30.577 7.221 14.529 2.748 18.986 8.386 34.012 7.037 5.043-0.424 4.474-0.594 9.289-3.68 4.392-2.897 2-2.481 1.125-9.314-0.963-10.686 0.273-14.664-4.608-22.364-8.079-12.726-8.746-12.517-14.024-20.901-5.277-8.269-11.133-25.896-17.173-26.015-4.75-0.116-7.506 2.464-10.497 5.513-2.992 3.047-3.759 17.447-8.249 22.001z"/>\r
+   <path fill="#ffd02b" d="m62.704 286.547c-7.388 7.33-23.805 1.445-27.757 4.912-4.204 3.729 5.455 10.311 4.533 17.594-0.593 4.427-2.272 6.553-3.417 12.523-0.854 4.651 3.786 4.098 6.262 5.225 11.619 4.671 14.104 4.087 30.341 7.185 14.438 2.72 18.864 8.33 33.787 6.991 5.01-0.418 4.341-0.604 9.166-3.604 4.292-2.729 1.942-2.359 0.972-9.396-1.163-10.613 0.263-14.709-4.369-22.012-8.03-12.641-8.787-12.371-14.03-20.7-5.243-8.214-10.962-25.903-16.962-26.021-4.719-0.117-7.457 2.447-10.428 5.477-2.972 3.029-3.632 17.313-8.098 21.826z"/>\r
+   <path fill="#ffd02d" d="m62.998 286.638c-7.57 7.493-24.13 1.61-27.925 4.987-4.174 3.742 5.635 10.451 4.716 17.4-0.604 4.398-2.182 6.596-3.478 12.518-0.969 4.623 3.875 4.045 6.382 5.101 11.991 4.579 14.694 4.228 30.105 7.149 14.345 2.688 18.743 8.275 33.563 6.944 4.977-0.411 4.207-0.61 9.042-3.524 4.193-2.562 1.884-2.239 0.819-9.481-1.366-10.538 0.251-14.754-4.133-21.659-7.979-12.557-8.825-12.224-14.034-20.498-5.208-8.16-10.791-25.91-16.751-26.027-4.688-0.114-7.407 2.433-10.358 5.441-2.951 3.01-3.505 17.174-7.948 21.649z"/>\r
+   <path fill="#ffd030" d="m63.292 286.729c-7.753 7.658-24.454 1.775-28.094 5.063-4.142 3.756 5.815 10.594 4.899 17.209-0.616 4.367-2.09 6.638-3.537 12.51-1.084 4.596 3.964 3.992 6.502 4.977 12.362 4.488 15.283 4.369 29.869 7.115 14.252 2.656 18.621 8.22 33.34 6.898 4.943-0.406 4.073-0.621 8.917-3.447 4.095-2.395 1.828-2.119 0.667-9.565-1.568-10.465 0.239-14.8-3.894-21.307-7.929-12.474-8.866-12.078-14.04-20.298-5.173-8.105-10.619-25.916-16.54-26.031-4.656-0.115-7.357 2.415-10.289 5.404-2.932 2.988-3.38 17.036-7.8 21.472z"/>\r
+   <path fill="#ffd133" d="m63.587 286.82c-7.937 7.822-24.78 1.94-28.263 5.138-4.111 3.77 5.995 10.734 5.081 17.016-0.627 4.339-1.998 6.68-3.597 12.504-1.199 4.568 4.054 3.939 6.623 4.854 12.732 4.396 15.873 4.51 29.633 7.08 14.16 2.625 18.499 8.164 33.116 6.852 4.909-0.4 3.939-0.629 8.793-3.369 3.997-2.227 1.77-1.999 0.514-9.648-1.771-10.393 0.228-14.846-3.654-20.955-7.88-12.39-8.907-11.934-14.046-20.098-5.139-8.051-10.448-25.922-16.329-26.037-4.625-0.113-7.309 2.398-10.221 5.368s-3.254 16.897-7.65 21.295z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m88.782 218.681c-0.936 2.088-1.728 20.017 2.952 27 4.68 6.911 3.312 10.872-1.872 5.616-5.4-5.112-8.928-12.816-9-18.145 0-3.096 2.376-15.84 3.313-17.208 1.007-1.44 5.327 1.153 4.607 2.737z"/>\r
+   <path fill="#030303" d="m88.692 219.032c-0.903 2.34-1.656 19.698 3.01 26.668 4.665 6.901 3.186 10.49-1.84 5.356-5.23-4.997-8.607-12.47-8.741-17.787-0.043-3.114 2.236-15.419 3.133-16.791 0.961-1.394 5.126 0.989 4.438 2.554z"/>\r
+   <path fill="#070707" d="m88.602 219.379c-0.871 2.593-1.584 19.383 3.067 26.338 4.65 6.891 3.06 10.109-1.808 5.098-5.062-4.882-8.287-12.125-8.481-17.432-0.087-3.131 2.095-14.998 2.952-16.373 0.915-1.345 4.926 0.828 4.27 2.369z"/>\r
+   <path fill="#0b0b0b" d="m88.512 219.729c-0.839 2.844-1.513 19.066 3.124 26.006 4.638 6.881 2.935 9.729-1.774 4.84-4.893-4.768-7.967-11.779-8.223-17.076-0.129-3.149 1.955-14.576 2.772-15.955 0.868-1.299 4.724 0.665 4.101 2.185z"/>\r
+   <path fill="#0f0f0f" d="m88.422 220.079c-0.806 3.096-1.439 18.748 3.183 25.674 4.623 6.869 2.809 9.347-1.742 4.58-4.724-4.651-7.646-11.434-7.963-16.719-0.173-3.168 1.814-14.154 2.592-15.537 0.819-1.252 4.52 0.504 3.93 2.002z"/>\r
+   <path fill="#131313" d="m88.332 220.426c-0.773 3.349-1.368 18.433 3.24 25.345 4.608 6.858 2.682 8.964-1.71 4.319-4.554-4.535-7.326-11.088-7.704-16.361-0.216-3.186 1.674-13.734 2.412-15.12 0.774-1.206 4.32 0.343 3.762 1.817z"/>\r
+   <path fill="#161616" d="m88.242 220.777c-0.741 3.601-1.296 18.115 3.298 25.013 4.594 6.848 2.556 8.582-1.678 4.061-4.385-4.421-7.006-10.742-7.444-16.006-0.26-3.203 1.533-13.313 2.231-14.702 0.728-1.16 4.118 0.18 3.593 1.634z"/>\r
+   <path fill="#1a1a1a" d="m88.152 221.125c-0.709 3.853-1.224 17.799 3.355 24.682 4.579 6.837 2.43 8.201-1.646 3.802-4.216-4.306-6.686-10.397-7.186-15.649-0.303-3.221 1.394-12.892 2.052-14.285 0.682-1.112 3.918 0.018 3.425 1.45z"/>\r
+   <path fill="#1e1e1e" d="m88.062 221.475c-0.677 4.104-1.152 17.482 3.413 24.35 4.564 6.826 2.304 7.82-1.613 3.543-4.046-4.191-6.365-10.051-6.927-15.293-0.345-3.24 1.253-12.47 1.872-13.867 0.634-1.066 3.716-0.144 3.255 1.267z"/>\r
+   <path fill="#222" d="m87.972 221.825c-0.645 4.355-1.08 17.164 3.47 24.018 4.551 6.816 2.179 7.439-1.58 3.285-3.877-4.076-6.044-9.707-6.667-14.938-0.389-3.258 1.112-12.049 1.691-13.449 0.587-1.019 3.514-0.306 3.086 1.084z"/>\r
+   <path fill="#262626" d="m87.883 222.172c-0.612 4.609-1.009 16.849 3.527 23.688 4.536 6.804 2.052 7.056-1.548 3.024-3.708-3.961-5.724-9.36-6.408-14.58-0.432-3.276 0.973-11.629 1.513-13.032 0.54-0.971 3.311-0.467 2.916 0.9z"/>\r
+   <path fill="#2a2a2a" d="m87.792 222.523c-0.579 4.86-0.936 16.531 3.586 23.356 4.521 6.793 1.926 6.675-1.516 2.765-3.539-3.845-5.403-9.015-6.148-14.224-0.476-3.293 0.831-11.207 1.332-12.614 0.493-0.925 3.11-0.63 2.746 0.717z"/>\r
+   <path fill="#2d2d2d" d="m87.702 222.872c-0.547 5.112-0.864 16.215 3.644 23.025 4.507 6.783 1.8 6.293-1.483 2.506-3.369-3.73-5.083-8.669-5.89-13.867-0.519-3.312 0.691-10.785 1.152-12.197 0.446-0.878 2.908-0.792 2.577 0.533z"/>\r
+   <path fill="#313131" d="m87.612 223.221c-0.515 5.363-0.792 15.898 3.701 22.693 4.492 6.772 1.674 5.912-1.451 2.248-3.2-3.615-4.763-8.324-5.63-13.512-0.563-3.33 0.551-10.363 0.972-11.779 0.399-0.831 2.707-0.953 2.408 0.35z"/>\r
+   <path fill="#353535" d="m87.522 223.57c-0.482 5.616-0.72 15.581 3.758 22.363 4.479 6.761 1.549 5.53-1.418 1.987-3.031-3.5-4.442-7.978-5.371-13.154-0.604-3.348 0.41-9.943 0.792-11.361 0.352-0.785 2.506-1.115 2.239 0.165z"/>\r
+   <path fill="#393939" d="m87.432 223.918c-0.45 5.869-0.648 15.265 3.815 22.033 4.464 6.75 1.422 5.147-1.386 1.728-2.862-3.384-4.122-7.632-5.112-12.798-0.647-3.366 0.271-9.522 0.612-10.944 0.307-0.737 2.305-1.278 2.071-0.019z"/>\r
+   <path fill="#3d3d3d" d="m87.343 224.269c-0.418 6.12-0.576 14.946 3.873 21.7 4.45 6.74 1.296 4.767-1.354 1.469-2.692-3.27-3.802-7.286-4.853-12.441-0.691-3.383 0.129-9.101 0.432-10.527 0.26-0.691 2.103-1.44 1.902-0.201z"/>\r
+   <path fill="#414141" d="m87.252 224.618c-0.385 6.373-0.504 14.631 3.932 21.369 4.436 6.729 1.17 4.385-1.321 1.211-2.523-3.154-3.481-6.941-4.594-12.086-0.734-3.402-0.011-8.68 0.252-10.109 0.212-0.644 1.901-1.602 1.731-0.385z"/>\r
+   <path fill="#444" d="m87.162 224.967c-0.353 6.623-0.432 14.314 3.989 21.037 4.421 6.719 1.044 4.004-1.289 0.951-2.354-3.039-3.161-6.595-4.334-11.729-0.778-3.42-0.151-8.258 0.071-9.691 0.166-0.597 1.7-1.763 1.563-0.568z"/>\r
+   <path fill="#484848" d="m87.072 225.316c-0.32 6.876-0.36 13.997 4.047 20.707 4.406 6.707 0.918 3.622-1.257 0.692-2.186-2.924-2.841-6.25-4.075-11.373-0.82-3.438-0.292-7.838-0.108-9.273 0.119-0.551 1.498-1.926 1.393-0.753z"/>\r
+   <path fill="#4c4c4c" d="m86.982 225.665c-0.288 7.129-0.288 13.68 4.104 20.377 4.393 6.695 0.792 3.24-1.224 0.432s-2.52-5.904-3.816-11.016c-0.863-3.457-0.432-7.416-0.287-8.856 0.071-0.505 1.295-2.089 1.223-0.937z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m88.782 218.681c4.32-9.433 6.696-19.584 12.888-29.448 6.12-9.792 3.672-13.608-0.863-8.64-4.536 4.968-9.504 15.48-9.504 15.48s-5.832 9.216-7.128 19.872c-0.217 1.8 3.887 4.248 4.607 2.736z"/>\r
+   <path fill="#020202" d="m88.968 218.071c4.279-9.5 6.615-19.246 12.586-28.802 5.901-9.488 3.608-13.279-0.764-8.472-4.403 4.847-9.302 15.236-9.368 15.381 0 0-5.637 8.993-6.877 19.239-0.209 1.771 3.72 4.145 4.423 2.654z"/>\r
+   <path fill="#050505" d="m89.152 217.459c4.239-9.566 6.535-18.908 12.284-28.155 5.683-9.183 3.547-12.95-0.663-8.303-4.27 4.725-9.099 14.991-9.231 15.282 0 0-5.442 8.766-6.627 18.605-0.201 1.741 3.554 4.042 4.237 2.571z"/>\r
+   <path fill="#070707" d="m89.338 216.849c4.199-9.634 6.454-18.572 11.981-27.51 5.465-8.878 3.484-12.621-0.563-8.135-4.137 4.605-8.896 14.748-9.096 15.184 0 0-5.247 8.542-6.376 17.972-0.192 1.713 3.387 3.937 4.054 2.489z"/>\r
+   <path fill="#0a0a0a" d="m89.522 216.239c4.159-9.701 6.375-18.234 11.68-26.865 5.247-8.573 3.422-12.292-0.461-7.966-4.005 4.483-8.693 14.503-8.96 15.085 0 0-5.053 8.317-6.126 17.337-0.186 1.684 3.219 3.837 3.867 2.409z"/>\r
+   <path fill="#0c0c0c" d="m89.708 215.627c4.118-9.769 6.294-17.897 11.376-26.218 5.029-8.268 3.36-11.962-0.359-7.797-3.871 4.361-8.49 14.259-8.823 14.985 0 0-4.858 8.093-5.876 16.706-0.179 1.653 3.051 3.731 3.682 2.324z"/>\r
+   <path fill="#0f0f0f" d="m89.893 215.017c4.077-9.836 6.213-17.56 11.073-25.573 4.812-7.963 3.298-11.633-0.259-7.629-3.738 4.241-8.288 14.015-8.688 14.887 0 0-4.663 7.868-5.625 16.072-0.169 1.624 2.886 3.628 3.499 2.243z"/>\r
+   <path fill="#111" d="m90.078 214.407c4.037-9.904 6.133-17.224 10.772-24.928 4.593-7.658 3.234-11.304-0.159-7.46-3.605 4.119-8.085 13.771-8.551 14.788 0 0-4.47 7.645-5.375 15.439-0.162 1.594 2.718 3.524 3.313 2.161z"/>\r
+   <path fill="#141414" d="m90.263 213.795c3.997-9.971 6.052-16.885 10.47-24.281 4.374-7.353 3.172-10.975-0.059-7.291-3.472 3.998-7.882 13.526-8.415 14.689 0 0-4.273 7.418-5.124 14.805-0.154 1.565 2.551 3.421 3.128 2.078z"/>\r
+   <path fill="#161616" d="m90.449 213.184c3.956-10.037 5.972-16.548 10.167-23.635 4.156-7.048 3.11-10.645 0.043-7.123-3.34 3.877-7.68 13.283-8.279 14.591 0 0-4.08 7.194-4.874 14.172-0.147 1.535 2.383 3.317 2.943 1.995z"/>\r
+   <path fill="#191919" d="m90.634 212.573c3.916-10.105 5.892-16.209 9.865-22.989 3.938-6.743 3.047-10.316 0.144-6.954-3.207 3.755-7.477 13.038-8.143 14.491 0 0-3.886 6.969-4.624 13.54-0.139 1.506 2.217 3.213 2.758 1.912z"/>\r
+   <path fill="#1c1c1c" d="m90.819 211.963c3.875-10.174 5.811-15.874 9.563-22.344 3.721-6.438 2.984-9.987 0.244-6.785-3.073 3.634-7.274 12.793-8.007 14.392 0 0-3.69 6.745-4.373 12.905-0.131 1.477 2.049 3.112 2.573 1.832z"/>\r
+   <path fill="#1e1e1e" d="m91.004 211.352c3.836-10.24 5.73-15.536 9.262-21.698 3.501-6.133 2.922-9.658 0.344-6.617-2.94 3.513-7.071 12.55-7.87 14.293 0 0-3.496 6.521-4.123 12.272-0.124 1.447 1.881 3.009 2.387 1.75z"/>\r
+   <path fill="#212121" d="m91.189 210.741c3.795-10.307 5.649-15.198 8.958-21.052 3.284-5.828 2.859-9.328 0.445-6.448-2.808 3.392-6.868 12.305-7.734 14.195 0 0-3.301 6.295-3.872 11.639-0.115 1.418 1.715 2.904 2.203 1.666z"/>\r
+   <path fill="#232323" d="m91.375 210.129c3.754-10.373 5.569-14.86 8.655-20.405 3.066-5.523 2.797-8.999 0.547-6.279-2.675 3.27-6.666 12.061-7.599 14.097 0 0-3.106 6.07-3.622 11.004-0.107 1.388 1.548 2.801 2.019 1.583z"/>\r
+   <path fill="#262626" d="m91.559 209.519c3.714-10.44 5.489-14.523 8.354-19.76 2.847-5.218 2.735-8.67 0.647-6.111-2.542 3.149-6.463 11.817-7.462 13.997 0 0-2.912 5.848-3.372 10.373-0.099 1.357 1.381 2.697 1.833 1.501z"/>\r
+   <path fill="#282828" d="m91.745 208.909c3.674-10.509 5.408-14.187 8.051-19.115 2.629-4.913 2.672-8.341 0.748-5.942-2.409 3.028-6.261 11.573-7.326 13.898 0 0-2.717 5.621-3.121 9.738-0.092 1.33 1.213 2.595 1.648 1.421z"/>\r
+   <path fill="#2b2b2b" d="m91.929 208.297c3.634-10.575 5.328-13.848 7.75-18.468 2.41-4.608 2.609-8.011 0.848-5.773-2.275 2.906-6.058 11.328-7.189 13.799 0 0-2.522 5.397-2.871 9.106-0.084 1.299 1.046 2.491 1.462 1.336z"/>\r
+   <path fill="#2d2d2d" d="m92.115 207.687c3.593-10.643 5.247-13.512 7.447-17.823 2.191-4.303 2.547-7.682 0.949-5.605-2.144 2.786-5.855 11.085-7.055 13.701 0 0-2.327 5.172-2.62 8.473-0.076 1.269 0.881 2.386 1.279 1.254z"/>\r
+   <path fill="#303030" d="m92.301 207.077c3.552-10.71 5.167-13.175 7.145-17.178 1.974-3.998 2.484-7.353 1.05-5.436-2.011 2.664-5.652 10.84-6.918 13.602 0 0-2.133 4.947-2.37 7.839-0.07 1.24 0.712 2.283 1.093 1.173z"/>\r
+   <path fill="#333" d="m92.485 206.465c3.513-10.778 5.087-12.837 6.843-16.531s2.422-7.024 1.15-5.268c-1.877 2.543-5.449 10.596-6.781 13.502 0 0-1.938 4.724-2.12 7.207-0.061 1.211 0.545 2.18 0.908 1.09z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m273.03 225.592c2.088-5.903 1.872-20.951-3.456-30.671-1.872-3.528-3.672-7.632-4.752-7.848-1.152-0.216-3.24 2.088-3.024 2.448 0.288 0.576 10.009 14.256 7.992 32.832-0.144 1.513 2.736 4.608 3.24 3.239z"/>\r
+   <path fill="#030303" d="m272.936 224.831c2.025-5.719 1.753-20.379-3.344-29.663-1.815-3.407-3.535-7.374-4.595-7.59-1.122-0.214-3.125 2.022-2.925 2.367 0.258 0.562 9.605 13.778 7.729 31.753-0.129 1.487 2.647 4.456 3.135 3.133z"/>\r
+   <path fill="#070707" d="m272.841 224.068c1.967-5.532 1.637-19.808-3.228-28.654-1.762-3.286-3.401-7.115-4.44-7.332-1.091-0.211-3.009 1.956-2.824 2.287 0.227 0.548 9.201 13.299 7.466 30.672-0.118 1.463 2.555 4.305 3.026 3.027z"/>\r
+   <path fill="#0b0b0b" d="m272.747 223.305c1.904-5.348 1.518-19.235-3.115-27.645-1.706-3.165-3.265-6.856-4.282-7.073-1.062-0.21-2.896 1.889-2.727 2.206 0.197 0.534 8.799 12.821 7.203 29.592-0.103 1.44 2.466 4.153 2.921 2.92z"/>\r
+   <path fill="#0f0f0f" d="m272.652 222.542c1.843-5.162 1.398-18.662-3.001-26.635-1.65-3.044-3.13-6.598-4.127-6.815-1.03-0.207-2.779 1.823-2.626 2.126 0.167 0.52 8.396 12.341 6.94 28.511-0.09 1.416 2.376 4.001 2.814 2.813z"/>\r
+   <path fill="#131313" d="m272.558 221.779c1.78-4.976 1.279-18.09-2.889-25.626-1.595-2.923-2.994-6.34-3.97-6.557-1-0.205-2.664 1.756-2.527 2.045 0.137 0.506 7.993 11.861 6.679 27.432-0.078 1.392 2.285 3.849 2.707 2.706z"/>\r
+   <path fill="#161616" d="m272.463 221.016c1.721-4.79 1.163-17.518-2.773-24.617-1.539-2.802-2.858-6.081-3.814-6.299-0.969-0.203-2.548 1.691-2.427 1.965 0.106 0.492 7.59 11.383 6.415 26.352-0.065 1.369 2.194 3.697 2.599 2.599z"/>\r
+   <path fill="#1a1a1a" d="m272.369 220.254c1.659-4.605 1.044-16.946-2.66-23.609-1.483-2.681-2.723-5.822-3.658-6.04-0.938-0.201-2.434 1.624-2.326 1.884 0.074 0.478 7.185 10.904 6.15 25.271-0.051 1.344 2.106 3.546 2.494 2.494z"/>\r
+   <path fill="#1e1e1e" d="m272.274 219.491c1.598-4.42 0.926-16.373-2.546-22.6-1.43-2.56-2.587-5.564-3.501-5.782-0.908-0.198-2.319 1.558-2.229 1.804 0.044 0.464 6.782 10.425 5.889 24.19-0.037 1.321 2.016 3.396 2.387 2.388z"/>\r
+   <path fill="#222" d="m272.18 218.728c1.535-4.233 0.807-15.802-2.434-21.59-1.373-2.439-2.452-5.306-3.345-5.524-0.877-0.197-2.203 1.491-2.128 1.723 0.014 0.45 6.379 9.947 5.625 23.111-0.023 1.297 1.927 3.242 2.282 2.28z"/>\r
+   <path fill="#262626" d="m272.085 217.965c1.476-4.049 0.69-15.229-2.318-20.582-1.317-2.317-2.316-5.046-3.188-5.265-0.847-0.194-2.088 1.425-2.029 1.642-0.016 0.436 5.977 9.468 5.362 22.032-0.011 1.272 1.835 3.089 2.173 2.173z"/>\r
+   <path fill="#2a2a2a" d="m271.991 217.202c1.413-3.861 0.571-14.656-2.206-19.572-1.262-2.196-2.18-4.788-3.032-5.007-0.815-0.191-1.973 1.36-1.929 1.562-0.047 0.422 5.573 8.988 5.099 20.951 0.003 1.247 1.746 2.939 2.068 2.066z"/>\r
+   <path fill="#2d2d2d" d="m271.896 216.439c1.353-3.677 0.453-14.084-2.091-18.563-1.207-2.076-2.045-4.529-2.876-4.749-0.786-0.19-1.858 1.293-1.83 1.481-0.077 0.408 5.17 8.51 4.836 19.87 0.017 1.226 1.656 2.789 1.961 1.961z"/>\r
+   <path fill="#313131" d="m271.802 215.676c1.29-3.491 0.334-13.512-1.979-17.553-1.151-1.956-1.909-4.272-2.72-4.493-0.755-0.187-1.742 1.227-1.73 1.401-0.106 0.394 4.768 8.031 4.573 18.791 0.031 1.202 1.567 2.637 1.856 1.854z"/>\r
+   <path fill="#353535" d="m271.707 214.915c1.23-3.307 0.217-12.94-1.864-16.545-1.096-1.834-1.773-4.014-2.563-4.234-0.725-0.185-1.627 1.16-1.631 1.32-0.138 0.38 4.364 7.552 4.311 17.71 0.042 1.176 1.475 2.485 1.747 1.749z"/>\r
+   <path fill="#393939" d="m271.613 214.151c1.168-3.119 0.098-12.367-1.751-15.535-1.04-1.714-1.638-3.755-2.407-3.976-0.693-0.183-1.512 1.094-1.531 1.24-0.168 0.366 3.962 7.074 4.049 16.63 0.055 1.153 1.384 2.332 1.64 1.641z"/>\r
+   <path fill="#3d3d3d" d="m271.518 213.388c1.106-2.935-0.021-11.796-1.638-14.527-0.983-1.592-1.502-3.496-2.25-3.716-0.664-0.181-1.396 1.028-1.432 1.159-0.198 0.352 3.558 6.594 3.785 15.549 0.07 1.13 1.296 2.183 1.535 1.535z"/>\r
+   <path fill="#414141" d="m271.424 212.625c1.047-2.75-0.139-11.223-1.522-13.518-0.93-1.471-1.367-3.238-2.094-3.459-0.635-0.178-1.282 0.962-1.333 1.079-0.229 0.338 3.153 6.114 3.521 14.47 0.083 1.106 1.205 2.03 1.428 1.428z"/>\r
+   <path fill="#444" d="m271.329 211.862c0.985-2.563-0.256-10.65-1.409-12.508-0.874-1.35-1.23-2.979-1.938-3.2-0.604-0.177-1.166 0.895-1.233 0.998-0.259 0.324 2.751 5.636 3.259 13.39 0.096 1.082 1.115 1.876 1.321 1.32z"/>\r
+   <path fill="#484848" d="m271.235 211.099c0.923-2.377-0.375-10.077-1.296-11.499-0.818-1.229-1.097-2.72-1.781-2.942-0.573-0.174-1.052 0.829-1.134 0.918-0.289 0.309 2.348 5.156 2.996 12.309 0.11 1.058 1.025 1.726 1.215 1.214z"/>\r
+   <path fill="#4c4c4c" d="m271.14 210.336c0.861-2.192-0.493-9.506-1.183-10.49-0.763-1.107-0.96-2.463-1.625-2.684-0.542-0.172-0.936 0.762-1.034 0.836-0.319 0.297 1.945 4.68 2.733 11.229 0.124 1.035 0.936 1.576 1.109 1.109z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m264.822 187.073c-10.224-13.968-23.472-18.504-22.104-14.112 0 0 10.152 5.76 19.08 16.56 1.728 2.088 4.608-0.288 3.024-2.448z"/>\r
+   <path fill="#030303" d="m264.372 186.687c-9.924-13.495-22.894-17.912-21.539-13.7 0.018 0.012 9.901 5.614 18.609 16.071 1.678 2.016 4.467-0.285 2.93-2.371z"/>\r
+   <path fill="#070707" d="m263.922 186.3c-9.624-13.022-22.316-17.319-20.975-13.287 0.036 0.023 9.652 5.467 18.139 15.582 1.628 1.943 4.325-0.283 2.836-2.295z"/>\r
+   <path fill="#0b0b0b" d="m263.472 185.913c-9.324-12.549-21.739-16.726-20.41-12.874 0.053 0.034 9.4 5.32 17.668 15.093 1.578 1.871 4.183-0.28 2.742-2.219z"/>\r
+   <path fill="#0f0f0f" d="m263.022 185.527c-9.024-12.077-21.162-16.134-19.847-12.462 0.071 0.045 9.151 5.174 17.198 14.604 1.529 1.798 4.043-0.278 2.649-2.142z"/>\r
+   <path fill="#131313" d="m262.571 185.14c-8.723-11.603-20.583-15.541-19.28-12.049 0.088 0.056 8.901 5.027 16.728 14.114 1.477 1.726 3.899-0.275 2.552-2.065z"/>\r
+   <path fill="#161616" d="m262.121 184.753c-8.423-11.13-20.006-14.948-18.716-11.636 0.106 0.067 8.651 4.88 16.257 13.625 1.428 1.654 3.759-0.272 2.459-1.989z"/>\r
+   <path fill="#1a1a1a" d="m261.671 184.367c-8.124-10.658-19.428-14.356-18.15-11.224 0.124 0.078 8.399 4.734 15.785 13.136 1.378 1.581 3.617-0.27 2.365-1.912z"/>\r
+   <path fill="#1e1e1e" d="m261.221 183.98c-7.824-10.185-18.851-13.763-17.588-10.811 0.143 0.089 8.151 4.587 15.315 12.647 1.33 1.508 3.477-0.267 2.273-1.836z"/>\r
+   <path fill="#222" d="m260.771 183.593c-7.524-9.711-18.273-13.17-17.022-10.398 0.159 0.1 7.9 4.44 14.844 12.158 1.279 1.436 3.335-0.265 2.178-1.76z"/>\r
+   <path fill="#262626" d="m260.321 183.206c-7.224-9.238-17.695-12.578-16.458-9.985 0.177 0.111 7.65 4.293 14.374 11.668 1.229 1.364 3.193-0.262 2.084-1.683z"/>\r
+   <path fill="#2a2a2a" d="m259.871 182.82c-6.924-8.766-17.118-11.986-15.893-9.573 0.193 0.122 7.398 4.147 13.902 11.179 1.18 1.291 3.053-0.259 1.991-1.606z"/>\r
+   <path fill="#2d2d2d" d="m259.42 182.433c-6.623-8.293-16.539-11.393-15.328-9.16 0.214 0.133 7.15 4 13.434 10.69 1.128 1.219 2.909-0.257 1.894-1.53z"/>\r
+   <path fill="#313131" d="m258.97 182.046c-6.323-7.819-15.963-10.8-14.764-8.747 0.23 0.144 6.899 3.853 12.962 10.201 1.08 1.146 2.769-0.254 1.802-1.454z"/>\r
+   <path fill="#353535" d="m258.52 181.66c-6.023-7.347-15.384-10.208-14.199-8.335 0.248 0.155 6.649 3.707 12.492 9.712 1.028 1.073 2.627-0.252 1.707-1.377z"/>\r
+   <path fill="#393939" d="m258.07 181.273c-5.723-6.874-14.807-9.615-13.634-7.922 0.265 0.166 6.398 3.56 12.021 9.222 0.978 1.002 2.485-0.249 1.613-1.3z"/>\r
+   <path fill="#3d3d3d" d="m257.62 180.886c-5.423-6.401-14.229-9.021-13.07-7.509 0.283 0.177 6.149 3.413 11.552 8.733 0.927 0.929 2.343-0.246 1.518-1.224z"/>\r
+   <path fill="#414141" d="m257.17 180.5c-5.124-5.928-13.65-8.43-12.505-7.097 0.301 0.188 5.898 3.267 11.079 8.244 0.879 0.856 2.203-0.244 1.426-1.147z"/>\r
+   <path fill="#444" d="m256.719 180.113c-4.823-5.455-13.073-7.837-11.94-6.684 0.319 0.199 5.649 3.12 10.609 7.755 0.829 0.784 2.061-0.241 1.331-1.071z"/>\r
+   <path fill="#484848" d="m256.269 179.726c-4.523-4.982-12.495-7.244-11.375-6.271 0.336 0.21 5.397 2.973 10.138 7.266 0.779 0.711 1.92-0.239 1.237-0.995z"/>\r
+   <path fill="#4c4c4c" d="m255.819 179.339c-4.223-4.509-11.918-6.652-10.812-5.859 0.354 0.222 5.148 2.827 9.668 6.777 0.73 0.639 1.779-0.236 1.144-0.918z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m273.03 225.592c0.144 6.265-5.76 22.248-7.992 21.673-2.52-0.576 0.504-5.257 2.809-13.177 0.936-3.312 1.655-11.447 1.943-11.735 0.936-0.936 3.24 1.728 3.24 3.239z"/>\r
+   <path fill="#050505" d="m272.846 226.116c0.103 6.082-5.638 21.594-7.797 21.018-2.422-0.567 0.548-5.146 2.814-12.928 0.899-3.178 1.595-10.947 1.887-11.25 0.914-0.927 3.147 1.527 3.096 3.16z"/>\r
+   <path fill="#0a0a0a" d="m272.662 226.637c0.063 5.902-5.514 20.939-7.601 20.363-2.323-0.558 0.592-5.035 2.82-12.681 0.861-3.041 1.534-10.446 1.83-10.761 0.89-0.917 3.054 1.327 2.951 3.079z"/>\r
+   <path fill="#0f0f0f" d="m272.478 227.159c0.021 5.721-5.392 20.284-7.405 19.711-2.224-0.55 0.635-4.927 2.827-12.434 0.824-2.907 1.473-9.945 1.773-10.273 0.866-0.911 2.959 1.125 2.805 2.996z"/>\r
+   <path fill="#141414" d="m272.294 227.68c-0.02 5.539-5.268 19.63-7.21 19.057-2.125-0.541 0.68-4.816 2.835-12.186 0.786-2.771 1.412-9.445 1.717-9.786 0.84-0.901 2.863 0.924 2.658 2.915z"/>\r
+   <path fill="#191919" d="m272.11 228.202c-0.063 5.359-5.146 18.977-7.014 18.403-2.027-0.532 0.722-4.706 2.841-11.938 0.748-2.637 1.351-8.944 1.659-9.299 0.818-0.893 2.77 0.722 2.514 2.834z"/>\r
+   <path fill="#1e1e1e" d="m271.926 228.723c-0.103 5.179-5.021 18.322-6.818 17.75-1.928-0.523 0.766-4.596 2.848-11.691 0.711-2.5 1.29-8.443 1.603-8.811 0.792-0.885 2.674 0.522 2.367 2.752z"/>\r
+   <path fill="#232323" d="m271.742 229.245c-0.144 4.998-4.9 17.668-6.623 17.096-1.83-0.514 0.811-4.485 2.854-11.442 0.673-2.366 1.229-7.944 1.545-8.325 0.771-0.876 2.583 0.32 2.224 2.671z"/>\r
+   <path fill="#282828" d="m271.558 229.766c-0.186 4.816-4.777 17.013-6.428 16.443-1.731-0.506 0.854-4.377 2.86-11.196 0.636-2.231 1.168-7.443 1.488-7.837 0.749-0.866 2.49 0.119 2.08 2.59z"/>\r
+   <path fill="#2d2d2d" d="m271.374 230.288c-0.226 4.637-4.653 16.359-6.231 15.789-1.632-0.496 0.896-4.266 2.866-10.947 0.6-2.098 1.107-6.943 1.433-7.351 0.722-0.859 2.393-0.081 1.932 2.509z"/>\r
+   <path fill="#333" d="m271.19 230.809c-0.268 4.456-4.531 15.705-6.036 15.136-1.534-0.489 0.94-4.155 2.873-10.7 0.561-1.961 1.046-6.443 1.375-6.863 0.7-0.848 2.3-0.282 1.788 2.427z"/>\r
+   <path fill="#383838" d="m271.006 231.331c-0.308 4.275-4.407 15.051-5.841 14.482-1.435-0.48 0.984-4.046 2.88-10.453 0.524-1.826 0.985-5.941 1.318-6.375 0.676-0.84 2.206-0.483 1.643 2.346z"/>\r
+   <path fill="#3d3d3d" d="m270.822 231.853c-0.35 4.093-4.285 14.396-5.645 13.828-1.338-0.472 1.027-3.937 2.886-10.206 0.485-1.691 0.924-5.441 1.261-5.887 0.653-0.832 2.113-0.684 1.498 2.265z"/>\r
+   <path fill="#424242" d="m270.638 232.374c-0.392 3.914-4.162 13.742-5.45 13.176-1.238-0.463 1.072-3.826 2.893-9.959 0.449-1.555 0.863-4.94 1.204-5.399 0.629-0.824 2.019-0.886 1.353 2.182z"/>\r
+   <path fill="#474747" d="m270.454 232.896c-0.432 3.731-4.039 13.087-5.254 12.521-1.14-0.453 1.115-3.715 2.9-9.711 0.411-1.42 0.802-4.439 1.146-4.912 0.606-0.815 1.925-1.086 1.208 2.102z"/>\r
+   <path fill="#4c4c4c" d="m270.27 233.417c-0.474 3.553-3.916 12.434-5.06 11.869-1.041-0.445 1.159-3.606 2.907-9.463 0.373-1.287 0.741-3.941 1.089-4.427 0.583-0.806 1.832-1.287 1.064 2.021z"/>\r
+   <path fill="#515151" d="m270.086 233.939c-0.514 3.37-3.793 11.778-4.862 11.214-0.942-0.436 1.201-3.496 2.913-9.216 0.336-1.151 0.68-3.438 1.032-3.938 0.558-0.797 1.736-1.489 0.917 1.94z"/>\r
+   <path fill="#565656" d="m269.902 234.461c-0.555 3.188-3.671 11.123-4.667 10.56-0.844-0.429 1.246-3.386 2.919-8.968 0.298-1.016 0.619-2.939 0.976-3.451 0.535-0.788 1.643-1.689 0.772 1.859z"/>\r
+   <path fill="#5b5b5b" d="m269.718 234.982c-0.597 3.009-3.548 10.47-4.472 9.907-0.745-0.42 1.29-3.275 2.926-8.721 0.262-0.881 0.559-2.438 0.919-2.963 0.511-0.781 1.549-1.89 0.627 1.777z"/>\r
+   <path fill="#606060" d="m269.534 235.504c-0.638 2.828-3.425 9.814-4.276 9.252-0.646-0.409 1.333-3.166 2.933-8.473 0.224-0.746 0.497-1.938 0.862-2.476 0.487-0.769 1.454-2.09 0.481 1.697z"/>\r
+   <path fill="#666" d="m269.35 236.025c-0.68 2.647-3.303 9.161-4.081 8.599-0.548-0.4 1.377-3.056 2.938-8.225 0.187-0.611 0.437-1.438 0.806-1.988 0.464-0.763 1.361-2.293 0.337 1.614z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m251.07 187.865c-1.537 1.622-2.903 9.991 0.938 12.893 3.844 2.818 10.59-2.391 10.59-5.379-0.086-6.746-9.991-9.222-11.528-7.514z"/>\r
+   <path fill="#010101" d="m251.207 188.006c-1.559 1.611-2.876 9.823 0.857 12.667 3.731 2.764 10.349-2.273 10.384-5.279-0.047-6.576-9.681-9.083-11.241-7.388z"/>\r
+   <path fill="#030303" d="m251.344 188.146c-1.582 1.601-2.85 9.653 0.774 12.438 3.62 2.709 10.109-2.154 10.178-5.177-0.007-6.404-9.37-8.943-10.952-7.261z"/>\r
+   <path fill="#050505" d="m251.481 188.287c-1.604 1.589-2.823 9.484 0.691 12.211 3.511 2.653 9.869-2.037 9.975-5.078 0.031-6.232-9.061-8.802-10.666-7.133z"/>\r
+   <path fill="#070707" d="m251.617 188.427c-1.626 1.579-2.795 9.316 0.611 11.984 3.397 2.6 9.629-1.918 9.768-4.976 0.071-6.062-8.751-8.664-10.379-7.008z"/>\r
+   <path fill="#090909" d="m251.754 188.567c-1.648 1.568-2.768 9.146 0.529 11.758 3.287 2.543 9.389-1.802 9.563-4.875 0.109-5.892-8.441-8.525-10.092-6.883z"/>\r
+   <path fill="#0b0b0b" d="m251.891 188.708c-1.671 1.557-2.741 8.978 0.445 11.529 3.177 2.489 9.15-1.683 9.358-4.774 0.15-5.72-8.13-8.385-9.803-6.755z"/>\r
+   <path fill="#0d0d0d" d="m252.028 188.848c-1.694 1.546-2.715 8.809 0.364 11.302 3.064 2.435 8.908-1.565 9.152-4.673 0.189-5.549-7.82-8.245-9.516-6.629z"/>\r
+   <path fill="#0f0f0f" d="m252.165 188.989c-1.716 1.535-2.688 8.64 0.282 11.074 2.953 2.38 8.669-1.447 8.948-4.572 0.226-5.378-7.512-8.106-9.23-6.502z"/>\r
+   <path fill="#111" d="m252.301 189.129c-1.737 1.524-2.659 8.471 0.2 10.847 2.844 2.325 8.431-1.33 8.743-4.471 0.266-5.207-7.201-7.966-8.943-6.376z"/>\r
+   <path fill="#131313" d="m252.438 189.269c-1.76 1.514-2.633 8.304 0.118 10.619 2.73 2.271 8.189-1.212 8.538-4.369 0.305-5.036-6.892-7.827-8.656-6.25z"/>\r
+   <path fill="#151515" d="m252.575 189.41c-1.783 1.503-2.606 8.133 0.036 10.391 2.62 2.216 7.949-1.094 8.332-4.268 0.344-4.865-6.581-7.687-8.368-6.123z"/>\r
+   <path fill="#161616" d="m252.712 189.55c-1.805 1.492-2.58 7.965-0.046 10.164 2.508 2.162 7.709-0.975 8.127-4.167 0.383-4.694-6.272-7.548-8.081-5.997z"/>\r
+   <path fill="#181818" d="m252.849 189.691c-1.828 1.481-2.554 7.796-0.129 9.937 2.397 2.105 7.47-0.857 7.922-4.066 0.423-4.524-5.961-7.409-7.793-5.871z"/>\r
+   <path fill="#1a1a1a" d="m252.985 189.831c-1.85 1.47-2.525 7.626-0.21 9.708 2.286 2.053 7.229-0.74 7.717-3.964 0.461-4.352-5.652-7.269-7.507-5.744z"/>\r
+   <path fill="#1c1c1c" d="m253.122 189.971c-1.872 1.46-2.499 7.459-0.292 9.482 2.175 1.996 6.989-0.623 7.511-3.865 0.501-4.18-5.341-7.128-7.219-5.617z"/>\r
+   <path fill="#1e1e1e" d="m253.259 190.112c-1.895 1.448-2.472 7.289-0.375 9.254 2.064 1.942 6.75-0.504 7.308-3.763 0.539-4.01-5.033-6.99-6.933-5.491z"/>\r
+   <path fill="#202020" d="m253.396 190.252c-1.917 1.438-2.445 7.122-0.457 9.027 1.953 1.888 6.51-0.386 7.102-3.662 0.578-3.839-4.722-6.85-6.645-5.365z"/>\r
+   <path fill="#222" d="m253.533 190.393c-1.939 1.426-2.418 6.951-0.539 8.799 1.841 1.832 6.271-0.268 6.896-3.561 0.618-3.668-4.412-6.711-6.357-5.238z"/>\r
+   <path fill="#242424" d="m253.669 190.533c-1.961 1.416-2.391 6.783-0.621 8.572 1.731 1.776 6.03-0.149 6.692-3.46 0.657-3.497-4.102-6.571-6.071-5.112z"/>\r
+   <path fill="#262626" d="m253.806 190.673c-1.984 1.405-2.364 6.615-0.703 8.344 1.619 1.724 5.79-0.032 6.485-3.358 0.697-3.326-3.791-6.432-5.782-4.986z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m250.71 256.698c1.513 1.512 2.809-2.232 4.32-3.457 1.512-1.224 3.96-3.888 8.856-3.888s4.535-0.144 4.319-2.017c-0.144-1.799-1.584-1.655-5.903-1.008-4.32 0.576-7.2 2.809-8.929 4.824-1.654 1.945-3.527 4.681-2.663 5.546z"/>\r
+   <path fill="#050505" d="m251.043 256.331c1.459 1.449 2.703-2.121 4.205-3.308 1.501-1.187 3.931-3.731 8.64-3.731 4.71-0.002 4.415-0.129 4.209-1.94-0.139-1.743-1.543-1.593-5.749-0.979-4.207 0.543-7.029 2.703-8.712 4.648-1.616 1.877-3.438 4.474-2.593 5.31z"/>\r
+   <path fill="#0a0a0a" d="m251.376 255.961c1.406 1.389 2.6-2.008 4.089-3.156 1.491-1.148 3.901-3.576 8.425-3.577 4.521-0.001 4.293-0.11 4.096-1.862-0.132-1.688-1.501-1.531-5.594-0.951-4.093 0.51-6.857 2.596-8.495 4.471-1.575 1.812-3.348 4.271-2.521 5.075z"/>\r
+   <path fill="#0f0f0f" d="m251.709 255.594c1.354 1.326 2.494-1.895 3.975-3.008 1.479-1.111 3.871-3.42 8.207-3.422s4.171-0.094 3.984-1.785c-0.126-1.631-1.46-1.467-5.438-0.924-3.979 0.479-6.687 2.492-8.28 4.297-1.533 1.747-3.257 4.066-2.448 4.842z"/>\r
+   <path fill="#141414" d="m252.042 255.226c1.302 1.265 2.39-1.783 3.858-2.856 1.47-1.076 3.842-3.266 7.991-3.268s4.05-0.077 3.873-1.709c-0.119-1.575-1.419-1.404-5.284-0.895-3.865 0.444-6.515 2.385-8.063 4.121-1.49 1.678-3.165 3.861-2.375 4.607z"/>\r
+   <path fill="#191919" d="m252.374 254.859c1.249 1.202 2.285-1.671 3.744-2.708 1.458-1.037 3.813-3.109 7.774-3.111 3.963-0.004 3.929-0.061 3.761-1.633-0.113-1.519-1.377-1.341-5.128-0.867-3.751 0.414-6.344 2.279-7.847 3.945-1.449 1.613-3.075 3.656-2.304 4.374z"/>\r
+   <path fill="#1e1e1e" d="m252.707 254.491c1.196 1.141 2.182-1.559 3.628-2.558 1.448-1 3.783-2.954 7.56-2.957 3.775-0.003 3.806-0.043 3.648-1.556-0.106-1.461-1.336-1.277-4.974-0.838-3.637 0.379-6.172 2.174-7.63 3.77-1.408 1.546-2.984 3.451-2.232 4.139z"/>\r
+   <path fill="#232323" d="m253.04 254.124c1.144 1.078 2.076-1.447 3.514-2.41 1.437-0.961 3.753-2.797 7.342-2.799 3.589-0.004 3.685-0.027 3.537-1.48-0.101-1.405-1.294-1.215-4.818-0.811-3.524 0.349-6.001 2.068-7.415 3.594-1.367 1.48-2.894 3.245-2.16 3.906z"/>\r
+   <path fill="#282828" d="m253.373 253.754c1.09 1.018 1.972-1.334 3.398-2.258 1.426-0.926 3.723-2.642 7.125-2.646 3.402-0.005 3.563-0.011 3.426-1.403-0.095-1.349-1.253-1.15-4.664-0.781-3.409 0.314-5.829 1.961-7.198 3.418-1.325 1.415-2.803 3.041-2.087 3.67z"/>\r
+   <path fill="#2d2d2d" d="m253.706 253.388c1.038 0.954 1.866-1.222 3.282-2.11 1.416-0.887 3.694-2.486 6.909-2.49 3.217-0.004 3.441 0.008 3.313-1.326-0.088-1.293-1.212-1.088-4.508-0.754-3.296 0.283-5.658 1.857-6.981 3.244-1.284 1.345-2.712 2.836-2.015 3.436z"/>\r
+   <path fill="#333" d="m254.039 253.02c0.985 0.893 1.762-1.109 3.167-1.96s3.664-2.33 6.693-2.335c3.029-0.006 3.32 0.023 3.202-1.249-0.082-1.237-1.171-1.024-4.354-0.726-3.182 0.25-5.485 1.75-6.765 3.066-1.243 1.282-2.622 2.634-1.943 3.204z"/>\r
+   <path fill="#383838" d="m254.372 252.652c0.933 0.831 1.657-0.998 3.051-1.81 1.396-0.813 3.636-2.174 6.478-2.18 2.843-0.006 3.199 0.039 3.09-1.172-0.076-1.181-1.129-0.963-4.198-0.697-3.068 0.217-5.314 1.644-6.55 2.891-1.202 1.214-2.531 2.427-1.871 2.968z"/>\r
+   <path fill="#3d3d3d" d="m254.704 252.284c0.88 0.771 1.553-0.885 2.938-1.66 1.383-0.775 3.604-2.019 6.26-2.024 2.656-0.007 3.078 0.058 2.979-1.095-0.069-1.125-1.088-0.899-4.044-0.67-2.954 0.185-5.144 1.539-6.333 2.715-1.16 1.148-2.441 2.222-1.8 2.734z"/>\r
+   <path fill="#424242" d="m255.037 251.917c0.827 0.707 1.448-0.773 2.821-1.51 1.373-0.738 3.576-1.863 6.044-1.871 2.47-0.007 2.956 0.074 2.867-1.018-0.063-1.068-1.046-0.836-3.889-0.641-2.841 0.151-4.973 1.433-6.116 2.539-1.119 1.083-2.35 2.018-1.727 2.501z"/>\r
+   <path fill="#474747" d="m255.37 251.549c0.774 0.645 1.344-0.661 2.706-1.362 1.362-0.7 3.545-1.706 5.828-1.713 2.283-0.009 2.834 0.09 2.754-0.942-0.057-1.012-1.005-0.773-3.733-0.613-2.727 0.119-4.801 1.328-5.899 2.365-1.078 1.013-2.26 1.81-1.656 2.265z"/>\r
+   <path fill="#4c4c4c" d="m255.703 251.181c0.721 0.584 1.239-0.55 2.59-1.212 1.353-0.663 3.517-1.551 5.612-1.559 2.096-0.009 2.713 0.107 2.643-0.865-0.051-0.955-0.964-0.709-3.577-0.584-2.613 0.086-4.631 1.222-5.686 2.188-1.035 0.949-2.168 1.607-1.582 2.032z"/>\r
+   <path fill="#515151" d="m256.036 250.813c0.669 0.521 1.134-0.436 2.476-1.063 1.341-0.625 3.485-1.395 5.395-1.402 1.91-0.01 2.591 0.124 2.531-0.789-0.044-0.898-0.922-0.646-3.423-0.557-2.499 0.055-4.458 1.117-5.469 2.014-0.994 0.882-2.077 1.402-1.51 1.797z"/>\r
+   <path fill="#565656" d="m256.369 250.446c0.616 0.459 1.029-0.324 2.36-0.912 1.33-0.589 3.456-1.24 5.178-1.248 1.723-0.01 2.47 0.141 2.42-0.713-0.039-0.842-0.881-0.582-3.268-0.527-2.387 0.021-4.287 1.01-5.252 1.836-0.953 0.816-1.987 1.199-1.438 1.564z"/>\r
+   <path fill="#5b5b5b" d="m256.701 250.079c0.564 0.397 0.926-0.213 2.245-0.764s3.427-1.084 4.963-1.093c1.536-0.011 2.348 0.157 2.307-0.636-0.031-0.785-0.839-0.52-3.112-0.5-2.271-0.01-4.116 0.906-5.035 1.662-0.913 0.751-1.898 0.993-1.368 1.331z"/>\r
+   <path fill="#606060" d="m257.034 249.709c0.511 0.336 0.821-0.1 2.13-0.612 1.309-0.515 3.397-0.929 4.746-0.938 1.351-0.01 2.227 0.176 2.196-0.558-0.026-0.729-0.799-0.457-2.958-0.472-2.158-0.043-3.945 0.799-4.82 1.486-0.87 0.682-1.805 0.788-1.294 1.094z"/>\r
+   <path fill="#666" d="m257.367 249.342c0.458 0.273 0.716 0.012 2.014-0.465 1.299-0.476 3.368-0.771 4.53-0.781 1.163-0.012 2.105 0.191 2.084-0.482-0.02-0.673-0.757-0.393-2.803-0.443-2.044-0.076-3.773 0.693-4.604 1.311-0.828 0.616-1.714 0.582-1.221 0.86z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m270.222 247.265c0 2.304 4.68 3.096 9.144 3.743 4.392 0.648 7.92 1.513 8.136 6.121 0.216 4.535-0.936 7.775 1.08 7.416 4.32-0.793 5.904-5.473 5.832-7.633 0-2.16-3.168-6.047-8.855-8.207-4.177-1.584-7.2-2.305-10.872-2.449-4.897-0.214-4.465 1.009-4.465 1.009z"/>\r
+   <path fill="#030303" d="m270.348 247.304c0.012 2.239 4.643 2.97 9.049 3.639 4.352 0.675 7.75 1.511 8.11 6.002 0.345 4.415-0.854 7.515 1.136 7.188 4.145-0.739 5.688-5.2 5.607-7.332-0.015-2.151-3.118-5.91-8.733-8.038-4.129-1.563-7.11-2.298-10.74-2.452-4.754-0.217-4.438 0.952-4.429 0.993z"/>\r
+   <path fill="#070707" d="m270.474 247.342c0.023 2.174 4.605 2.845 8.953 3.533 4.312 0.701 7.58 1.508 8.087 5.885 0.471 4.295-0.771 7.252 1.189 6.963 3.97-0.689 5.472-4.93 5.384-7.033-0.028-2.145-3.068-5.773-8.61-7.87-4.082-1.543-7.022-2.291-10.609-2.456-4.612-0.218-4.412 0.896-4.394 0.978z"/>\r
+   <path fill="#0b0b0b" d="m270.6 247.379c0.035 2.109 4.568 2.721 8.857 3.431 4.271 0.728 7.411 1.506 8.063 5.767 0.599 4.174-0.689 6.988 1.245 6.735 3.795-0.638 5.257-4.66 5.159-6.733-0.044-2.137-3.019-5.636-8.488-7.701-4.035-1.522-6.933-2.285-10.478-2.459-4.469-0.219-4.384 0.837-4.358 0.96z"/>\r
+   <path fill="#0f0f0f" d="m270.726 247.418c0.047 2.043 4.531 2.595 8.762 3.324 4.232 0.754 7.242 1.504 8.039 5.649 0.725 4.052-0.608 6.728 1.299 6.509 3.621-0.586 5.041-4.389 4.937-6.436-0.06-2.127-2.971-5.496-8.367-7.53-3.988-1.502-6.842-2.278-10.346-2.464-4.328-0.22-4.359 0.784-4.324 0.948z"/>\r
+   <path fill="#131313" d="m270.852 247.458c0.059 1.978 4.495 2.469 8.667 3.219 4.19 0.781 7.071 1.502 8.014 5.531 0.854 3.932-0.526 6.465 1.354 6.283 3.445-0.535 4.824-4.119 4.712-6.137-0.074-2.119-2.92-5.359-8.245-7.361-3.941-1.482-6.753-2.271-10.213-2.469-4.186-0.221-4.333 0.726-4.289 0.934z"/>\r
+   <path fill="#161616" d="m270.978 247.495c0.07 1.914 4.458 2.344 8.57 3.115 4.151 0.807 6.903 1.5 7.99 5.413 0.98 3.812-0.443 6.202 1.409 6.056 3.271-0.482 4.609-3.848 4.488-5.836-0.088-2.111-2.871-5.222-8.123-7.193-3.894-1.461-6.663-2.264-10.081-2.471-4.043-0.223-4.306 0.67-4.253 0.916z"/>\r
+   <path fill="#1a1a1a" d="m271.104 247.534c0.082 1.848 4.422 2.219 8.476 3.01 4.111 0.832 6.734 1.498 7.965 5.295 1.108 3.69-0.36 5.94 1.464 5.83 3.097-0.433 4.394-3.578 4.265-5.537-0.104-2.104-2.821-5.084-8-7.023-3.848-1.441-6.575-2.26-9.949-2.477-3.905-0.223-4.283 0.613-4.221 0.902z"/>\r
+   <path fill="#1e1e1e" d="m271.23 247.573c0.094 1.781 4.385 2.092 8.381 2.904 4.07 0.859 6.563 1.495 7.939 5.178 1.236 3.568-0.278 5.678 1.52 5.602 2.921-0.381 4.177-3.305 4.04-5.237-0.118-2.097-2.771-4.946-7.878-6.854-3.8-1.42-6.485-2.252-9.817-2.479-3.762-0.226-4.256 0.556-4.185 0.886z"/>\r
+   <path fill="#222" d="m271.356 247.61c0.105 1.717 4.348 1.969 8.285 2.801 4.029 0.885 6.395 1.493 7.916 5.059 1.362 3.449-0.197 5.416 1.573 5.377 2.746-0.329 3.962-3.036 3.816-4.939-0.133-2.087-2.722-4.808-7.756-6.684-3.753-1.4-6.396-2.247-9.686-2.484-3.618-0.227-4.227 0.499-4.148 0.87z"/>\r
+   <path fill="#262626" d="m271.482 247.648c0.118 1.651 4.311 1.843 8.189 2.694 3.99 0.914 6.226 1.492 7.892 4.943 1.491 3.328-0.115 5.152 1.629 5.149 2.571-0.278 3.746-2.765 3.592-4.64-0.146-2.08-2.672-4.672-7.634-6.516-3.705-1.38-6.306-2.24-9.553-2.488-3.478-0.225-4.203 0.446-4.115 0.858z"/>\r
+   <path fill="#2a2a2a" d="m271.608 247.687c0.129 1.587 4.273 1.716 8.094 2.59 3.95 0.938 6.056 1.489 7.867 4.825 1.618 3.206-0.033 4.891 1.684 4.922 2.396-0.227 3.53-2.494 3.368-4.34-0.162-2.072-2.623-4.534-7.512-6.348-3.658-1.358-6.216-2.232-9.421-2.492-3.336-0.226-4.177 0.39-4.08 0.843z"/>\r
+   <path fill="#2d2d2d" d="m271.734 247.725c0.141 1.521 4.237 1.591 7.999 2.484 3.909 0.967 5.886 1.488 7.842 4.707 1.746 3.086 0.05 4.629 1.739 4.697 2.221-0.176 3.313-2.225 3.144-4.041-0.177-2.064-2.572-4.396-7.389-6.178-3.612-1.339-6.128-2.227-9.29-2.497-3.194-0.227-4.151 0.334-4.045 0.828z"/>\r
+   <path fill="#313131" d="m271.86 247.763c0.153 1.456 4.2 1.466 7.903 2.381 3.869 0.991 5.717 1.485 7.817 4.589 1.873 2.965 0.132 4.365 1.794 4.469 2.046-0.123 3.099-1.953 2.92-3.742-0.191-2.055-2.523-4.258-7.267-6.008-3.565-1.318-6.038-2.22-9.158-2.5-3.051-0.229-4.124 0.276-4.009 0.811z"/>\r
+   <path fill="#353535" d="m271.986 247.801c0.165 1.392 4.163 1.341 7.808 2.275 3.829 1.018 5.547 1.483 7.794 4.473 2 2.843 0.213 4.103 1.848 4.242 1.873-0.074 2.883-1.683 2.696-3.443-0.206-2.047-2.474-4.12-7.145-5.838-3.517-1.299-5.948-2.215-9.026-2.506-2.91-0.229-4.099 0.221-3.975 0.797z"/>\r
+   <path fill="#393939" d="m272.112 247.84c0.176 1.326 4.126 1.215 7.712 2.17 3.789 1.045 5.378 1.482 7.771 4.354 2.127 2.723 0.295 3.842 1.901 4.016 1.698-0.021 2.667-1.412 2.474-3.144-0.222-2.038-2.426-3.981-7.023-5.669-3.47-1.277-5.859-2.208-8.894-2.509-2.769-0.231-4.074 0.164-3.941 0.782z"/>\r
+   <path fill="#3d3d3d" d="m272.238 247.877c0.188 1.262 4.089 1.09 7.617 2.066 3.749 1.071 5.208 1.479 7.745 4.236 2.255 2.602 0.377 3.578 1.957 3.789 1.522 0.029 2.451-1.141 2.249-2.844-0.236-2.033-2.375-3.846-6.901-5.5-3.423-1.258-5.769-2.203-8.762-2.514-2.626-0.231-4.046 0.109-3.905 0.767z"/>\r
+   <path fill="#414141" d="m272.364 247.917c0.2 1.195 4.052 0.965 7.522 1.961 3.708 1.098 5.037 1.477 7.72 4.119 2.383 2.479 0.46 3.315 2.012 3.562 1.348 0.081 2.236-0.87 2.025-2.545-0.251-2.022-2.325-3.707-6.778-5.331-3.377-1.237-5.681-2.195-8.631-2.518-2.485-0.233-4.02 0.05-3.87 0.752z"/>\r
+   <path fill="#444" d="m272.49 247.956c0.212 1.129 4.015 0.838 7.426 1.855 3.668 1.124 4.869 1.475 7.696 4 2.51 2.359 0.542 3.055 2.067 3.336 1.173 0.133 2.02-0.6 1.801-2.246-0.266-2.016-2.276-3.568-6.656-5.16-3.329-1.218-5.591-2.189-8.499-2.521-2.343-0.235-3.994-0.007-3.835 0.736z"/>\r
+   <path fill="#484848" d="m272.616 247.993c0.223 1.065 3.979 0.715 7.331 1.752 3.628 1.15 4.699 1.473 7.671 3.883 2.638 2.238 0.624 2.791 2.122 3.108 0.998 0.185 1.804-0.329 1.577-1.946-0.28-2.008-2.227-3.432-6.534-4.992-3.282-1.196-5.501-2.182-8.367-2.525-2.201-0.235-3.968-0.064-3.8 0.72z"/>\r
+   <path fill="#4c4c4c" d="m272.742 248.032c0.235 1 3.941 0.588 7.235 1.645 3.588 1.178 4.529 1.472 7.646 3.766 2.766 2.118 0.706 2.529 2.177 2.883 0.823 0.235 1.589-0.059 1.354-1.648-0.295-1.998-2.177-3.293-6.412-4.822-3.235-1.176-5.412-2.176-8.235-2.529-2.059-0.239-3.942-0.119-3.765 0.705z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#4c4c4c" d="m287.565 252.854c1.646 1 1.353 2.059 2.412 2.766 0.528 0.352 1.412 0.352 0.882-1-0.706-1.588-1.294-2.472-4.941-3.943-2.353-0.941-1.882 0.059 1.647 2.177z"/>\r
+   <path fill="#505050" d="m287.609 252.868c1.605 0.975 1.32 2.008 2.353 2.696 0.517 0.343 1.377 0.343 0.86-0.976-0.689-1.549-1.262-2.41-4.82-3.846-2.295-0.917-1.836 0.059 1.607 2.126z"/>\r
+   <path fill="#545454" d="m287.652 252.879c1.567 0.951 1.287 1.957 2.294 2.629 0.503 0.334 1.343 0.334 0.839-0.951-0.671-1.51-1.23-2.35-4.699-3.749-2.238-0.893-1.79 0.058 1.566 2.071z"/>\r
+   <path fill="#575757" d="m287.696 252.891c1.526 0.926 1.254 1.908 2.235 2.563 0.489 0.325 1.308 0.325 0.816-0.928-0.653-1.471-1.199-2.289-4.578-3.652-2.179-0.872-1.743 0.055 1.527 2.017z"/>\r
+   <path fill="#5b5b5b" d="m287.74 252.903c1.485 0.902 1.22 1.857 2.175 2.494 0.479 0.318 1.274 0.318 0.796-0.902-0.637-1.432-1.167-2.229-4.457-3.556-2.122-0.849-1.697 0.054 1.486 1.964z"/>\r
+   <path fill="#5f5f5f" d="m287.783 252.915c1.446 0.879 1.188 1.808 2.117 2.426 0.464 0.31 1.239 0.31 0.773-0.877-0.619-1.394-1.136-2.168-4.336-3.459-2.064-0.826-1.65 0.052 1.446 1.91z"/>\r
+   <path fill="#636363" d="m287.827 252.926c1.405 0.854 1.154 1.758 2.057 2.359 0.452 0.301 1.205 0.301 0.754-0.853-0.603-1.354-1.104-2.108-4.216-3.363-2.007-0.801-1.605 0.053 1.405 1.857z"/>\r
+   <path fill="#676767" d="m287.871 252.94c1.364 0.828 1.121 1.705 1.998 2.29 0.438 0.292 1.17 0.292 0.731-0.828-0.585-1.315-1.072-2.047-4.095-3.267-1.948-0.779-1.558 0.05 1.366 1.805z"/>\r
+   <path fill="#6b6b6b" d="m287.914 252.952c1.325 0.805 1.088 1.655 1.94 2.223 0.425 0.283 1.135 0.283 0.709-0.803-0.568-1.277-1.041-1.988-3.974-3.17-1.891-0.757-1.512 0.047 1.325 1.75z"/>\r
+   <path fill="#6e6e6e" d="m287.958 252.963c1.284 0.779 1.056 1.605 1.88 2.156 0.413 0.274 1.102 0.274 0.688-0.779-0.551-1.238-1.009-1.926-3.853-3.073-1.833-0.733-1.466 0.046 1.285 1.696z"/>\r
+   <path fill="#727272" d="m288.002 252.976c1.243 0.755 1.021 1.554 1.821 2.087 0.399 0.266 1.066 0.266 0.666-0.755-0.533-1.199-0.977-1.865-3.731-2.976-1.776-0.71-1.421 0.045 1.244 1.644z"/>\r
+   <path fill="#767676" d="m288.045 252.989c1.203 0.73 0.989 1.504 1.763 2.02 0.387 0.257 1.031 0.257 0.645-0.731-0.516-1.159-0.946-1.805-3.61-2.879-1.72-0.688-1.376 0.042 1.202 1.59z"/>\r
+   <path fill="#7a7a7a" d="m288.089 253c1.163 0.705 0.955 1.453 1.703 1.951 0.373 0.25 0.997 0.25 0.623-0.705-0.499-1.121-0.914-1.744-3.489-2.783-1.661-0.664-1.329 0.041 1.163 1.537z"/>\r
+   <path fill="#7e7e7e" d="m288.133 253.012c1.122 0.682 0.923 1.404 1.644 1.885 0.361 0.24 0.962 0.24 0.602-0.682-0.481-1.082-0.882-1.684-3.367-2.687-1.605-0.64-1.285 0.041 1.121 1.484z"/>\r
+   <path fill="#828282" d="m288.176 253.025c1.082 0.657 0.89 1.353 1.586 1.815 0.348 0.232 0.927 0.232 0.578-0.656-0.463-1.043-0.85-1.623-3.245-2.59-1.547-0.618-1.237 0.039 1.081 1.431z"/>\r
+   <path fill="#858585" d="m288.22 253.038c1.042 0.631 0.855 1.301 1.524 1.748 0.335 0.223 0.894 0.223 0.559-0.633-0.446-1.005-0.818-1.563-3.125-2.492-1.488-0.596-1.19 0.037 1.042 1.377z"/>\r
+   <path fill="#898989" d="m288.264 253.049c1.001 0.607 0.821 1.252 1.466 1.681 0.322 0.214 0.857 0.214 0.536-0.608-0.43-0.965-0.786-1.502-3.004-2.396-1.43-0.573-1.144 0.034 1.002 1.323z"/>\r
+   <path fill="#8d8d8d" d="m288.307 253.061c0.961 0.584 0.79 1.201 1.407 1.613 0.309 0.205 0.823 0.205 0.515-0.584-0.412-0.926-0.755-1.441-2.883-2.299-1.373-0.548-1.098 0.034 0.961 1.27z"/>\r
+   <path fill="#919191" d="m288.351 253.073c0.921 0.559 0.756 1.151 1.348 1.547 0.296 0.196 0.789 0.196 0.493-0.56-0.395-0.888-0.723-1.381-2.762-2.204-1.315-0.525-1.052 0.033 0.921 1.217z"/>\r
+   <path fill="#959595" d="m288.395 253.084c0.88 0.535 0.723 1.102 1.289 1.479 0.282 0.189 0.754 0.189 0.471-0.534-0.377-0.849-0.691-1.321-2.641-2.106-1.257-0.505-1.006 0.031 0.881 1.161z"/>\r
+   <path fill="#999" d="m288.438 253.097c0.84 0.51 0.689 1.05 1.229 1.409 0.271 0.181 0.721 0.181 0.45-0.51-0.36-0.81-0.66-1.26-2.52-2.01-1.199-0.48-0.959 0.031 0.841 1.111z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path d="m222.275 107.427c-0.738 0.902 0.574 8.365 5.412 13.285 4.839 4.838 7.791 4.838 9.759 2.706 3.771-4.018 0.738-7.791-1.558-10.415-2.297-2.624-5.248-1.722-7.955-4.346-2.706-2.624-4.592-2.46-5.658-1.23z"/>\r
+   <path fill="#050505" d="m222.345 107.494c-0.732 0.895 0.569 8.3 5.369 13.182 4.803 4.801 7.731 4.801 9.685 2.685 3.742-3.987 0.731-7.73-1.546-10.334-2.278-2.604-5.208-1.709-7.894-4.312-2.684-2.604-4.556-2.441-5.614-1.221z"/>\r
+   <path fill="#0a0a0a" d="m222.416 107.561c-0.727 0.888 0.565 8.235 5.328 13.079 4.763 4.763 7.67 4.763 9.607 2.664 3.713-3.956 0.727-7.67-1.534-10.253-2.26-2.584-5.166-1.696-7.831-4.279-2.664-2.583-4.521-2.422-5.57-1.211z"/>\r
+   <path fill="#0f0f0f" d="m222.486 107.628c-0.721 0.881 0.561 8.17 5.286 12.976 4.726 4.725 7.608 4.725 9.532 2.642 3.684-3.924 0.72-7.609-1.522-10.172-2.243-2.563-5.126-1.682-7.77-4.244-2.643-2.563-4.485-2.403-5.526-1.202z"/>\r
+   <path fill="#141414" d="m222.556 107.695c-0.716 0.874 0.557 8.105 5.243 12.872 4.689 4.688 7.55 4.688 9.456 2.622 3.655-3.893 0.716-7.549-1.51-10.091-2.224-2.543-5.085-1.669-7.707-4.211-2.621-2.543-4.449-2.384-5.482-1.192z"/>\r
+   <path fill="#191919" d="m222.627 107.762c-0.71 0.867 0.552 8.04 5.202 12.769 4.65 4.65 7.488 4.65 9.379 2.601 3.626-3.862 0.71-7.489-1.497-10.011s-5.044-1.655-7.646-4.177-4.414-2.364-5.438-1.182z"/>\r
+   <path fill="#1e1e1e" d="m222.697 107.829c-0.704 0.86 0.547 7.975 5.16 12.666 4.613 4.612 7.428 4.612 9.304 2.579 3.596-3.83 0.703-7.427-1.486-9.929-2.188-2.502-5.003-1.642-7.584-4.143-2.579-2.502-4.378-2.346-5.394-1.173z"/>\r
+   <path fill="#232323" d="m222.767 107.896c-0.697 0.853 0.543 7.91 5.117 12.562 4.576 4.575 7.367 4.575 9.229 2.559 3.567-3.8 0.698-7.367-1.473-9.848-2.171-2.482-4.963-1.629-7.522-4.11s-4.343-2.326-5.351-1.163z"/>\r
+   <path fill="#282828" d="m222.838 107.963c-0.691 0.846 0.538 7.845 5.076 12.459 4.537 4.537 7.307 4.537 9.152 2.538 3.537-3.769 0.691-7.307-1.461-9.768-2.154-2.461-4.922-1.615-7.461-4.076-2.538-2.461-4.307-2.307-5.306-1.153z"/>\r
+   <path fill="#2d2d2d" d="m222.908 108.03c-0.686 0.839 0.534 7.78 5.034 12.355 4.5 4.499 7.246 4.499 9.076 2.516 3.509-3.737 0.686-7.246-1.449-9.686-2.135-2.441-4.881-1.602-7.399-4.042-2.516-2.44-4.271-2.287-5.262-1.143z"/>\r
+   <path fill="#333" d="m222.978 108.096c-0.681 0.832 0.529 7.715 4.992 12.253 4.463 4.462 7.186 4.462 9.001 2.496 3.479-3.706 0.68-7.186-1.438-9.605-2.118-2.42-4.841-1.588-7.337-4.008s-4.235-2.27-5.218-1.136z"/>\r
+   <path fill="#383838" d="m223.048 108.163c-0.674 0.825 0.526 7.65 4.95 12.15 4.425 4.425 7.125 4.425 8.925 2.475 3.45-3.675 0.676-7.125-1.425-9.525-2.099-2.4-4.8-1.575-7.274-3.975-2.475-2.399-4.201-2.25-5.176-1.125z"/>\r
+   <path fill="#3d3d3d" d="m223.119 108.23c-0.669 0.818 0.521 7.585 4.908 12.047 4.387 4.387 7.063 4.387 8.849 2.453 3.42-3.643 0.669-7.064-1.413-9.443-2.082-2.38-4.759-1.562-7.214-3.941-2.453-2.38-4.164-2.231-5.13-1.116z"/>\r
+   <path fill="#424242" d="m223.189 108.297c-0.663 0.811 0.516 7.52 4.866 11.944 4.35 4.349 7.004 4.349 8.772 2.432 3.392-3.612 0.663-7.004-1.4-9.363-2.064-2.359-4.719-1.548-7.151-3.907-2.433-2.359-4.129-2.212-5.087-1.106z"/>\r
+   <path fill="#474747" d="m223.259 108.364c-0.656 0.804 0.513 7.455 4.824 11.84 4.313 4.312 6.944 4.312 8.697 2.412 3.362-3.582 0.658-6.944-1.388-9.282-2.046-2.339-4.679-1.535-7.09-3.874-2.411-2.338-4.093-2.192-5.043-1.096z"/>\r
+   <path fill="#4c4c4c" d="m223.33 108.431c-0.651 0.797 0.507 7.39 4.782 11.737 4.274 4.274 6.882 4.274 8.621 2.39 3.332-3.55 0.651-6.883-1.377-9.201s-4.636-1.521-7.028-3.839c-2.39-2.318-4.057-2.174-4.998-1.087z"/>\r
+   <path fill="#515151" d="m223.4 108.498c-0.646 0.79 0.503 7.325 4.74 11.634 4.236 4.236 6.821 4.236 8.545 2.369 3.304-3.519 0.646-6.822-1.364-9.12s-4.596-1.508-6.966-3.806c-2.369-2.298-4.022-2.154-4.955-1.077z"/>\r
+   <path fill="#565656" d="m223.47 108.565c-0.641 0.783 0.499 7.26 4.697 11.53 4.199 4.199 6.763 4.199 8.471 2.349 3.273-3.488 0.64-6.762-1.353-9.039-1.993-2.278-4.556-1.495-6.905-3.773-2.347-2.277-3.985-2.135-4.91-1.067z"/>\r
+   <path fill="#5b5b5b" d="m223.541 108.632c-0.635 0.776 0.493 7.195 4.656 11.427 4.161 4.161 6.701 4.161 8.393 2.327 3.245-3.456 0.636-6.701-1.34-8.958-1.975-2.257-4.514-1.48-6.843-3.738-2.327-2.257-3.95-2.116-4.866-1.058z"/>\r
+   <path fill="#606060" d="m223.611 108.699c-0.629 0.769 0.489 7.13 4.614 11.324 4.124 4.123 6.64 4.123 8.317 2.306 3.215-3.425 0.628-6.641-1.328-8.877-1.957-2.237-4.474-1.468-6.78-3.705-2.306-2.236-3.915-2.097-4.823-1.048z"/>\r
+   <path fill="#666" d="m223.681 108.765c-0.623 0.762 0.484 7.065 4.571 11.221 4.086 4.086 6.58 4.086 8.242 2.285 3.187-3.394 0.623-6.58-1.315-8.796-1.939-2.217-4.434-1.455-6.72-3.671-2.284-2.216-3.878-2.078-4.778-1.039z"/>\r
+  </g>\r
+  <g transform="translate(-12.4048,10.0005)">\r
+   <path fill="#fc0" d="m137.79 109.277c1.978 1.366 2.031 1.607 4.948 3.514 4.64 3.768 12.885 4.616 16.922 4.75 9.233 1.467 25.738-7.161 32.273-11.111 3.291-2.463 9.38-7.551 11.659-7.637 1.405 1.485-0.66 1.792-3.587 3.775-3.906 2.779-7.25 5.156-13.172 8.515-6.338 3.316-16.078 8.794-28.548 8.054-6.542-0.959-6.566-1.024-10.606-3.086-2.4-1.732-7.901-4.608-9.889-6.774z"/>\r
+   <linearGradient id="al" x1="129.342" gradientUnits="userSpaceOnUse" x2="195.598" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.305" y2="259.305">\r
+    <stop stop-color="#FAC700" offset="0"/>\r
+    <stop stop-color="#F7C400" offset=".415"/>\r
+    <stop stop-color="#F7C400" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#al)" d="m137.742 109.259c1.926 1.274 2.165 1.643 5.083 3.554 4.616 3.734 12.716 4.616 16.796 4.763 9.365 1.452 26.05-7.294 32.356-11.159 3.357-2.506 9.344-7.498 11.595-7.604 1.365 1.472-0.728 1.768-3.688 3.814-3.889 2.753-7.119 5.065-12.972 8.383-6.29 3.291-16.078 8.795-28.536 8.104-6.561-0.945-6.851-1.07-10.758-3.079-2.468-1.755-7.876-4.587-9.876-6.776z"/>\r
+   <linearGradient id="am" x1="129.293" gradientUnits="userSpaceOnUse" x2="195.554" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.311" y2="259.311">\r
+    <stop stop-color="#F6C200" offset="0"/>\r
+    <stop stop-color="#EFBC00" offset=".415"/>\r
+    <stop stop-color="#EFBC00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#am)" d="m137.693 109.24c1.876 1.183 2.3 1.68 5.218 3.595 4.593 3.7 12.548 4.616 16.67 4.776 9.498 1.437 26.364-7.428 32.44-11.207 3.425-2.55 9.308-7.444 11.528-7.57 1.326 1.457-0.795 1.743-3.788 3.854-3.87 2.725-6.99 4.973-12.771 8.25-6.243 3.266-16.078 8.796-28.525 8.154-6.579-0.931-7.134-1.117-10.908-3.073-2.536-1.779-7.852-4.567-9.864-6.779z"/>\r
+   <linearGradient id="an" x1="129.245" gradientUnits="userSpaceOnUse" x2="195.51" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.317" y2="259.317">\r
+    <stop stop-color="#F1BD00" offset="0"/>\r
+    <stop stop-color="#E8B500" offset=".415"/>\r
+    <stop stop-color="#E8B500" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#an)" d="m137.645 109.222c1.825 1.091 2.434 1.715 5.352 3.635 4.569 3.665 12.38 4.615 16.544 4.789 9.631 1.422 26.677-7.562 32.524-11.255 3.491-2.594 9.271-7.392 11.463-7.538 1.287 1.442-0.861 1.718-3.889 3.893-3.853 2.699-6.86 4.882-12.57 8.119-6.195 3.241-16.078 8.797-28.513 8.203-6.6-0.916-7.418-1.163-11.061-3.066-2.603-1.801-7.826-4.546-9.85-6.78z"/>\r
+   <linearGradient id="ao" x1="129.196" gradientUnits="userSpaceOnUse" x2="195.465" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.322" y2="259.322">\r
+    <stop stop-color="#EDB800" offset="0"/>\r
+    <stop stop-color="#E0AD00" offset=".415"/>\r
+    <stop stop-color="#E0AD00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ao)" d="m137.596 109.203c1.774 1 2.568 1.752 5.487 3.676 4.545 3.631 12.211 4.615 16.418 4.801 9.764 1.408 26.989-7.695 32.608-11.302 3.557-2.637 9.236-7.338 11.396-7.505 1.247 1.427-0.928 1.693-3.99 3.932-3.833 2.672-6.729 4.791-12.369 7.986-6.148 3.217-16.078 8.799-28.501 8.254-6.619-0.902-7.702-1.21-11.21-3.059-2.672-1.825-7.803-4.525-9.839-6.783z"/>\r
+   <linearGradient id="ap" x1="129.148" gradientUnits="userSpaceOnUse" x2="195.422" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.327" y2="259.327">\r
+    <stop stop-color="#E9B300" offset="0"/>\r
+    <stop stop-color="#D8A500" offset=".415"/>\r
+    <stop stop-color="#D8A500" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ap)" d="m137.548 109.184c1.724 0.909 2.703 1.788 5.622 3.717 4.522 3.597 12.043 4.615 16.292 4.814 9.896 1.393 27.303-7.829 32.692-11.35 3.624-2.681 9.2-7.286 11.331-7.472 1.208 1.412-0.995 1.668-4.092 3.972-3.814 2.644-6.6 4.698-12.168 7.853-6.101 3.192-16.077 8.8-28.489 8.303-6.638-0.887-7.986-1.256-11.361-3.052-2.741-1.848-7.779-4.504-9.827-6.785z"/>\r
+   <linearGradient id="aq" x1="129.099" gradientUnits="userSpaceOnUse" x2="195.379" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.332" y2="259.332">\r
+    <stop stop-color="#E4AE00" offset="0"/>\r
+    <stop stop-color="#D19E00" offset=".415"/>\r
+    <stop stop-color="#D19E00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#aq)" d="m137.499 109.166c1.673 0.817 2.838 1.824 5.757 3.757 4.499 3.562 11.875 4.614 16.166 4.827 10.029 1.378 27.615-7.963 32.776-11.398 3.691-2.725 9.164-7.232 11.265-7.439 1.169 1.397-1.061 1.644-4.191 4.01-3.796 2.618-6.469 4.608-11.968 7.722-6.053 3.167-16.077 8.801-28.478 8.353-6.657-0.873-8.27-1.303-11.512-3.046-2.809-1.87-7.755-4.483-9.815-6.786z"/>\r
+   <linearGradient id="ar" x1="129.051" gradientUnits="userSpaceOnUse" x2="195.338" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.336" y2="259.336">\r
+    <stop stop-color="#E0A900" offset="0"/>\r
+    <stop stop-color="#C99600" offset=".415"/>\r
+    <stop stop-color="#C99600" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ar)" d="m137.451 109.147c1.622 0.726 2.972 1.86 5.892 3.798 4.475 3.528 11.705 4.614 16.04 4.84 10.161 1.362 27.929-8.097 32.859-11.447 3.757-2.767 9.128-7.178 11.2-7.405 1.13 1.382-1.128 1.619-4.294 4.049-3.777 2.592-6.339 4.517-11.767 7.589-6.005 3.143-16.077 8.803-28.466 8.404-6.676-0.859-8.553-1.35-11.663-3.039-2.876-1.894-7.729-4.462-9.801-6.789z"/>\r
+   <linearGradient id="w" x1="129.003" gradientUnits="userSpaceOnUse" x2="195.296" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.34" y2="259.34">\r
+    <stop stop-color="#DCA400" offset="0"/>\r
+    <stop stop-color="#C18E00" offset=".415"/>\r
+    <stop stop-color="#C18E00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#w)" d="m137.403 109.129c1.571 0.634 3.105 1.896 6.026 3.838 4.45 3.494 11.536 4.614 15.913 4.852 10.295 1.348 28.241-8.23 32.943-11.494 3.824-2.811 9.092-7.125 11.134-7.373 1.092 1.367-1.194 1.594-4.394 4.088-3.759 2.565-6.209 4.425-11.566 7.457-5.957 3.118-16.077 8.804-28.454 8.453-6.694-0.844-8.837-1.396-11.813-3.032-2.945-1.916-7.706-4.44-9.789-6.789z"/>\r
+   <linearGradient id="x" x1="128.954" gradientUnits="userSpaceOnUse" x2="195.255" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.343" y2="259.343">\r
+    <stop stop-color="#D79F00" offset="0"/>\r
+    <stop stop-color="#BA8700" offset=".415"/>\r
+    <stop stop-color="#BA8700" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#x)" d="m137.354 109.11c1.521 0.543 3.241 1.932 6.161 3.879 4.428 3.459 11.368 4.613 15.788 4.865 10.427 1.333 28.554-8.364 33.026-11.542 3.892-2.855 9.057-7.073 11.068-7.339 1.052 1.353-1.261 1.569-4.495 4.127-3.74 2.538-6.078 4.334-11.365 7.325-5.91 3.093-16.077 8.805-28.441 8.503-6.716-0.83-9.121-1.443-11.966-3.026-3.012-1.939-7.68-4.42-9.776-6.792z"/>\r
+   <linearGradient id="y" x1="128.906" gradientUnits="userSpaceOnUse" x2="195.216" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.348" y2="259.348">\r
+    <stop stop-color="#D39B00" offset="0"/>\r
+    <stop stop-color="#B27F00" offset=".415"/>\r
+    <stop stop-color="#B27F00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#y)" d="m137.306 109.091c1.47 0.451 3.375 1.969 6.296 3.919 4.403 3.426 11.2 4.614 15.662 4.879 10.559 1.318 28.865-8.498 33.109-11.59 3.958-2.899 9.021-7.02 11.003-7.306 1.013 1.337-1.328 1.544-4.596 4.167-3.722 2.511-5.949 4.242-11.165 7.192-5.862 3.068-16.077 8.807-28.43 8.553-6.734-0.816-9.405-1.489-12.116-3.019-3.08-1.963-7.656-4.4-9.763-6.795z"/>\r
+   <linearGradient id="z" x1="128.857" gradientUnits="userSpaceOnUse" x2="195.176" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.35" y2="259.35">\r
+    <stop stop-color="#CF9600" offset="0"/>\r
+    <stop stop-color="#a70" offset=".415"/>\r
+    <stop stop-color="#a70" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#z)" d="m137.257 109.073c1.421 0.359 3.511 2.005 6.432 3.959 4.38 3.392 11.032 4.614 15.536 4.892 10.691 1.303 29.179-8.631 33.193-11.638 4.024-2.942 8.984-6.967 10.938-7.274 0.973 1.323-1.396 1.521-4.697 4.206-3.703 2.484-5.818 4.151-10.964 7.06-5.814 3.043-16.077 8.808-28.418 8.603-6.753-0.802-9.689-1.535-12.268-3.012-3.149-1.986-7.632-4.378-9.752-6.796z"/>\r
+   <linearGradient id="aa" x1="128.809" gradientUnits="userSpaceOnUse" x2="195.137" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.354" y2="259.354">\r
+    <stop stop-color="#CA9100" offset="0"/>\r
+    <stop stop-color="#A37000" offset=".415"/>\r
+    <stop stop-color="#A37000" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#aa)" d="m137.209 109.054c1.368 0.268 3.645 2.041 6.565 4 4.356 3.357 10.864 4.613 15.41 4.904 10.824 1.289 29.493-8.764 33.277-11.685 4.092-2.986 8.948-6.914 10.871-7.241 0.935 1.308-1.461 1.496-4.797 4.245-3.685 2.457-5.688 4.06-10.763 6.928-5.768 3.018-16.077 8.809-28.407 8.653-6.771-0.788-9.972-1.582-12.418-3.006-3.216-2.008-7.607-4.357-9.738-6.798z"/>\r
+   <linearGradient id="ab" x1="128.76" gradientUnits="userSpaceOnUse" x2="195.099" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.356" y2="259.356">\r
+    <stop stop-color="#C68C00" offset="0"/>\r
+    <stop stop-color="#9B6800" offset=".415"/>\r
+    <stop stop-color="#9B6800" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ab)" d="m137.16 109.036c1.318 0.176 3.779 2.077 6.701 4.04 4.333 3.323 10.695 4.613 15.284 4.917 10.957 1.274 29.805-8.898 33.36-11.733 4.158-3.03 8.912-6.86 10.807-7.208 0.894 1.292-1.528 1.471-4.899 4.284-3.666 2.43-5.558 3.968-10.562 6.796-5.72 2.993-16.077 8.81-28.396 8.702-6.791-0.773-10.256-1.628-12.568-2.999-3.285-2.031-7.583-4.336-9.727-6.799z"/>\r
+   <linearGradient id="ac" x1="128.712" gradientUnits="userSpaceOnUse" x2="195.062" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.358" y2="259.358">\r
+    <stop stop-color="#C28700" offset="0"/>\r
+    <stop stop-color="#936000" offset=".415"/>\r
+    <stop stop-color="#936000" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ac)" d="m137.112 109.017c1.267 0.085 3.912 2.113 6.835 4.081 4.31 3.289 10.527 4.613 15.158 4.93 11.09 1.258 30.118-9.032 33.445-11.782 4.225-3.072 8.877-6.807 10.739-7.174 0.855 1.278-1.595 1.446-5 4.323-3.647 2.404-5.427 3.877-10.36 6.663-5.673 2.969-16.077 8.812-28.384 8.753-6.811-0.759-10.54-1.675-12.719-2.992-3.353-2.055-7.559-4.315-9.714-6.802z"/>\r
+   <linearGradient id="ad" x1="128.663" gradientUnits="userSpaceOnUse" x2="195.025" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.36" y2="259.36">\r
+    <stop stop-color="#BD8200" offset="0"/>\r
+    <stop stop-color="#8C5900" offset=".415"/>\r
+    <stop stop-color="#8C5900" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ad)" d="m137.063 108.998c1.217-0.006 4.047 2.15 6.97 4.122 4.286 3.254 10.359 4.612 15.032 4.943 11.223 1.243 30.431-9.166 33.53-11.83 4.289-3.116 8.84-6.753 10.673-7.141 0.815 1.263-1.661 1.421-5.101 4.362-3.63 2.377-5.298 3.785-10.161 6.531-5.624 2.944-16.075 8.813-28.37 8.802-6.83-0.744-10.824-1.721-12.87-2.985-3.422-2.077-7.535-4.294-9.703-6.804z"/>\r
+   <linearGradient id="ae" x1="128.615" gradientUnits="userSpaceOnUse" x2="194.989" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.362" y2="259.362">\r
+    <stop stop-color="#B97D00" offset="0"/>\r
+    <stop stop-color="#845100" offset=".415"/>\r
+    <stop stop-color="#845100" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ae)" d="m137.015 108.98c1.166-0.098 4.181 2.185 7.104 4.162 4.262 3.22 10.19 4.612 14.906 4.955 11.354 1.229 30.743-9.299 33.613-11.877 4.356-3.16 8.804-6.7 10.607-7.108 0.776 1.248-1.728 1.397-5.202 4.401-3.61 2.35-5.167 3.694-9.96 6.399-5.576 2.919-16.076 8.814-28.358 8.852-6.85-0.73-11.108-1.768-13.021-2.979-3.489-2.1-7.51-4.273-9.689-6.805z"/>\r
+   <linearGradient id="af" x1="128.567" gradientUnits="userSpaceOnUse" x2="194.954" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.364" y2="259.364">\r
+    <stop stop-color="#B57800" offset="0"/>\r
+    <stop stop-color="#7C4900" offset=".415"/>\r
+    <stop stop-color="#7C4900" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#af)" d="m136.967 108.961c1.115-0.189 4.315 2.222 7.239 4.203 4.239 3.186 10.021 4.612 14.78 4.968 11.488 1.214 31.057-9.433 33.697-11.925 4.424-3.203 8.768-6.647 10.542-7.075 0.736 1.233-1.795 1.372-5.303 4.44-3.593 2.323-5.038 3.603-9.759 6.266-5.529 2.895-16.077 8.816-28.348 8.903-6.868-0.716-11.392-1.815-13.172-2.972-3.557-2.124-7.485-4.252-9.676-6.808z"/>\r
+   <linearGradient id="ah" x1="128.518" gradientUnits="userSpaceOnUse" x2="194.918" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.366" y2="259.366">\r
+    <stop stop-color="#B07300" offset="0"/>\r
+    <stop stop-color="#754200" offset=".415"/>\r
+    <stop stop-color="#754200" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ah)" d="m136.918 108.943c1.064-0.281 4.45 2.257 7.374 4.243 4.216 3.151 9.854 4.611 14.654 4.981 11.621 1.199 31.37-9.567 33.781-11.973 4.49-3.247 8.731-6.594 10.476-7.042 0.698 1.218-1.861 1.347-5.403 4.479-3.573 2.296-4.906 3.511-9.558 6.134-5.48 2.87-16.076 8.817-28.336 8.952-6.887-0.701-11.675-1.861-13.323-2.965-3.626-2.146-7.462-4.231-9.665-6.809z"/>\r
+   <linearGradient id="ai" x1="128.47" gradientUnits="userSpaceOnUse" x2="194.886" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.367" y2="259.367">\r
+    <stop stop-color="#AC6E00" offset="0"/>\r
+    <stop stop-color="#6D3A00" offset=".415"/>\r
+    <stop stop-color="#6D3A00" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#ai)" d="m136.87 108.924c1.013-0.372 4.584 2.294 7.509 4.284 4.191 3.117 9.685 4.611 14.528 4.994 11.753 1.184 31.682-9.701 33.864-12.021 4.557-3.291 8.695-6.542 10.411-7.009 0.657 1.203-1.929 1.322-5.504 4.518-3.557 2.269-4.777 3.42-9.358 6.002-5.434 2.845-16.076 8.818-28.324 9.002-6.907-0.687-11.959-1.908-13.474-2.959-3.694-2.169-7.437-4.21-9.652-6.811z"/>\r
+   <linearGradient id="aj" x1="128.421" gradientUnits="userSpaceOnUse" x2="194.85" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.369" y2="259.369">\r
+    <stop stop-color="#A86A00" offset="0"/>\r
+    <stop stop-color="#663200" offset=".415"/>\r
+    <stop stop-color="#663200" offset="1"/>\r
+   </linearGradient>\r
+   <path fill="url(#aj)" d="m136.821 108.905c0.963-0.464 4.719 2.33 7.644 4.324 4.168 3.083 9.517 4.611 14.402 5.007 11.886 1.169 31.995-9.834 33.948-12.069 4.624-3.334 8.66-6.487 10.345-6.976 0.619 1.188-1.995 1.298-5.604 4.558-3.537 2.242-4.647 3.328-9.157 5.869-5.386 2.82-16.076 8.82-28.313 9.052-6.926-0.673-12.243-1.954-13.625-2.952-3.762-2.192-7.413-4.189-9.64-6.813z"/>\r
+  </g>\r
+ </g>\r
+</svg>\r
index 8ea9c68..bf7fb21 100644 (file)
@@ -7,5 +7,5 @@ $result = array( 'xmp-exif' =>
                'GPSLatitude' => 88.51805555,
                'GPSLongitude' => -21.12356945,
                'GPSVersionID' => '2.2.0.0'
-        )
+       )
 );
index 686ab93..7f9a023 100644 (file)
@@ -5,7 +5,11 @@
  */
 class ArticleTablesTest extends MediaWikiLangTestCase {
 
-       function testbug14404() {
+       /**
+        * @covers Title::getTemplateLinksFrom
+        * @covers Title::getLinksFrom
+        */
+       public function testbug14404() {
                global $wgContLang, $wgLanguageCode, $wgLang;
 
                $title = Title::newFromText( 'Bug 14404' );
@@ -20,7 +24,7 @@ class ArticleTablesTest extends MediaWikiLangTestCase {
                $templates1 = $title->getTemplateLinksFrom();
 
                $wgLang = Language::factory( 'de' );
-               $page->mPreparedEdit = false; // In order to force the rerendering of the same wikitext
+               $page = WikiPage::factory( $title ); // In order to force the rerendering of the same wikitext
 
                // We need an edit, a purge is not enough to regenerate the tables
                $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', EDIT_UPDATE, false, $user );
index 867c4f0..84f900f 100644 (file)
@@ -25,28 +25,37 @@ class ArticleTest extends MediaWikiTestCase {
                $this->article = null;
        }
 
-       function testImplementsGetMagic() {
+       /**
+        * @covers Article::__get
+        */
+       public function testImplementsGetMagic() {
                $this->assertEquals( false, $this->article->mLatest, "Article __get magic" );
        }
 
        /**
         * @depends testImplementsGetMagic
+        * @covers Article::__set
         */
-       function testImplementsSetMagic() {
+       public function testImplementsSetMagic() {
                $this->article->mLatest = 2;
                $this->assertEquals( 2, $this->article->mLatest, "Article __set magic" );
        }
 
        /**
         * @depends testImplementsSetMagic
+        * @covers Article::__call
         */
-       function testImplementsCallMagic() {
+       public function testImplementsCallMagic() {
                $this->article->mLatest = 33;
                $this->article->mDataLoaded = true;
                $this->assertEquals( 33, $this->article->getLatest(), "Article __call magic" );
        }
 
-       function testGetOrSetOnNewProperty() {
+       /**
+        * @covers Article::__get
+        * @covers Article::__set
+        */
+       public function testGetOrSetOnNewProperty() {
                $this->article->ext_someNewProperty = 12;
                $this->assertEquals( 12, $this->article->ext_someNewProperty,
                        "Article get/set magic on new field" );
@@ -58,8 +67,13 @@ class ArticleTest extends MediaWikiTestCase {
 
        /**
         * Checks for the existence of the backwards compatibility static functions (forwarders to WikiPage class)
+        * @covers Article::selectFields
+        * @covers Article::onArticleCreate
+        * @covers Article::onArticleDelete
+        * @covers Article::onArticleEdit
+        * @covers Article::getAutosummary
         */
-       function testStaticFunctions() {
+       public function testStaticFunctions() {
                $this->hideDeprecated( 'Article::getAutosummary' );
                $this->hideDeprecated( 'WikiPage::getAutosummary' );
                $this->hideDeprecated( 'CategoryPage::getAutosummary' ); // Inherited from Article
@@ -75,18 +89,4 @@ class ArticleTest extends MediaWikiTestCase {
                $this->assertTrue( is_string( CategoryPage::getAutosummary( '', '', 0 ) ),
                        "Article static functions" );
        }
-
-       function testWikiPageFactory() {
-               $title = Title::makeTitle( NS_FILE, 'Someimage.png' );
-               $page = WikiPage::factory( $title );
-               $this->assertEquals( 'WikiFilePage', get_class( $page ) );
-
-               $title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
-               $page = WikiPage::factory( $title );
-               $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
-
-               $title = Title::makeTitle( NS_MAIN, 'SomePage' );
-               $page = WikiPage::factory( $title );
-               $this->assertEquals( 'WikiPage', get_class( $page ) );
-       }
 }
index 32fc2c5..f0049fe 100644 (file)
@@ -6,7 +6,9 @@
  */
 class BlockTest extends MediaWikiLangTestCase {
 
-       private $block, $madeAt;
+       /** @var Block */
+       private $block;
+       private $madeAt;
 
        /* variable used to save up the blockID we insert in this test suite */
        private $blockId;
@@ -66,18 +68,24 @@ class BlockTest extends MediaWikiLangTestCase {
                }
        }
 
-       function testInitializerFunctionsReturnCorrectBlock() {
-               // $this->dumpBlocks();
-
+       /**
+        * @covers Block::newFromTarget
+        */
+       public function testINewFromTargetReturnsCorrectBlock() {
                $this->assertTrue( $this->block->equals( Block::newFromTarget( 'UTBlockee' ) ), "newFromTarget() returns the same block as the one that was made" );
+       }
 
+       /**
+        * @covers Block::newFromID
+        */
+       public function testINewFromIDReturnsCorrectBlock() {
                $this->assertTrue( $this->block->equals( Block::newFromID( $this->blockId ) ), "newFromID() returns the same block as the one that was made" );
        }
 
        /**
         * per bug 26425
         */
-       function testBug26425BlockTimestampDefaultsToTime() {
+       public function testBug26425BlockTimestampDefaultsToTime() {
                // delta to stop one-off errors when things happen to go over a second mark.
                $delta = abs( $this->madeAt - $this->block->mTimestamp );
                $this->assertLessThan( 2, $delta, "If no timestamp is specified, the block is recorded as time()" );
@@ -90,8 +98,9 @@ class BlockTest extends MediaWikiLangTestCase {
         * This stopped working with r84475 and friends: regression being fixed for bug 29116.
         *
         * @dataProvider provideBug29116Data
+        * @covers Block::load
         */
-       function testBug29116LoadWithEmptyIp( $vagueTarget ) {
+       public function testBug29116LoadWithEmptyIp( $vagueTarget ) {
                $this->hideDeprecated( 'Block::load' );
 
                $uid = User::idFromName( 'UTBlockee' );
@@ -110,8 +119,9 @@ class BlockTest extends MediaWikiLangTestCase {
         * had. Regression bug 29116.
         *
         * @dataProvider provideBug29116Data
+        * @covers Block::newFromTarget
         */
-       function testBug29116NewFromTargetWithEmptyIp( $vagueTarget ) {
+       public function testBug29116NewFromTargetWithEmptyIp( $vagueTarget ) {
                $block = Block::newFromTarget( 'UTBlockee', $vagueTarget );
                $this->assertTrue( $this->block->equals( $block ), "newFromTarget() returns the same block as the one that was made when given empty vagueTarget param " . var_export( $vagueTarget, true ) );
        }
@@ -124,7 +134,10 @@ class BlockTest extends MediaWikiLangTestCase {
                );
        }
 
-       function testBlockedUserCanNotCreateAccount() {
+       /**
+        * @covers Block::prevents
+        */
+       public function testBlockedUserCanNotCreateAccount() {
                $username = 'BlockedUserToCreateAccountWith';
                $u = User::newFromName( $username );
                $u->setPassword( 'NotRandomPass' );
@@ -184,7 +197,10 @@ class BlockTest extends MediaWikiLangTestCase {
                );
        }
 
-       function testCrappyCrossWikiBlocks() {
+       /**
+        * @covers Block::insert
+        */
+       public function testCrappyCrossWikiBlocks() {
                // Delete the last round's block if it's still there
                $oldBlock = Block::newFromTarget( 'UserOnForeignWiki' );
                if ( $oldBlock ) {
@@ -343,8 +359,10 @@ class BlockTest extends MediaWikiLangTestCase {
 
        /**
         * @dataProvider providerXff
+        * @covers Block::getBlocksForIPList
+        * @covers Block::chooseBlock
         */
-       function testBlocksOnXff( $xff, $exCount, $exResult ) {
+       public function testBlocksOnXff( $xff, $exCount, $exResult ) {
                $list = array_map( 'trim', explode( ',', $xff ) );
                $xffblocks = Block::getBlocksForIPList( $list, true );
                $this->assertEquals( $exCount, count( $xffblocks ), 'Number of blocks for ' . $xff );
diff --git a/tests/phpunit/includes/CdbTest.php b/tests/phpunit/includes/CdbTest.php
deleted file mode 100644 (file)
index e3d9da7..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-/**
- * Test the CDB reader/writer
- */
-class CdbTest extends MediaWikiTestCase {
-
-       protected function setUp() {
-               parent::setUp();
-               if ( !CdbReader::haveExtension() ) {
-                       $this->markTestSkipped( 'Native CDB support is not available' );
-               }
-       }
-
-       /**
-        * @group medium
-        */
-       public function testCdb() {
-               $dir = wfTempDir();
-               if ( !is_writable( $dir ) ) {
-                       $this->markTestSkipped( "Temp dir isn't writable" );
-               }
-
-               $phpcdbfile = $this->getNewTempFile();
-               $dbacdbfile = $this->getNewTempFile();
-
-               $w1 = new CdbWriter_PHP( $phpcdbfile );
-               $w2 = new CdbWriter_DBA( $dbacdbfile );
-
-               $data = array();
-               for ( $i = 0; $i < 1000; $i++ ) {
-                       $key = $this->randomString();
-                       $value = $this->randomString();
-                       $w1->set( $key, $value );
-                       $w2->set( $key, $value );
-
-                       if ( !isset( $data[$key] ) ) {
-                               $data[$key] = $value;
-                       }
-               }
-
-               $w1->close();
-               $w2->close();
-
-               $this->assertEquals(
-                       md5_file( $phpcdbfile ),
-                       md5_file( $dbacdbfile ),
-                       'same hash'
-               );
-
-               $r1 = new CdbReader_PHP( $phpcdbfile );
-               $r2 = new CdbReader_DBA( $dbacdbfile );
-
-               foreach ( $data as $key => $value ) {
-                       if ( $key === '' ) {
-                               // Known bug
-                               continue;
-                       }
-                       $v1 = $r1->get( $key );
-                       $v2 = $r2->get( $key );
-
-                       $v1 = $v1 === false ? '(not found)' : $v1;
-                       $v2 = $v2 === false ? '(not found)' : $v2;
-
-                       # cdbAssert( 'Mismatch', $key, $v1, $v2 );
-                       $this->cdbAssert( "PHP error", $key, $v1, $value );
-                       $this->cdbAssert( "DBA error", $key, $v2, $value );
-               }
-       }
-
-       private function randomString() {
-               $len = mt_rand( 0, 10 );
-               $s = '';
-               for ( $j = 0; $j < $len; $j++ ) {
-                       $s .= chr( mt_rand( 0, 255 ) );
-               }
-
-               return $s;
-       }
-
-       private function cdbAssert( $msg, $key, $v1, $v2 ) {
-               $this->assertEquals(
-                       $v2,
-                       $v1,
-                       $msg . ', k=' . bin2hex( $key )
-               );
-       }
-}
index f1004fb..c6a7169 100644 (file)
@@ -1,4 +1,12 @@
 <?php
+
+/**
+ * Class CollationTest
+ * @covers Collation
+ * @covers IcuCollation
+ * @covers IdentityCollation
+ * @covers UppercaseCollation
+ */
 class CollationTest extends MediaWikiLangTestCase {
        protected function setUp() {
                parent::setUp();
@@ -20,7 +28,7 @@ class CollationTest extends MediaWikiLangTestCase {
         *
         * @dataProvider prefixDataProvider
         */
-       function testIsPrefix( $lang, $base, $extended ) {
+       public function testIsPrefix( $lang, $base, $extended ) {
                $cp = Collator::create( $lang );
                $cp->setStrength( Collator::PRIMARY );
                $baseBin = $cp->getSortKey( $base );
@@ -30,7 +38,7 @@ class CollationTest extends MediaWikiLangTestCase {
                $this->assertStringStartsWith( $baseBin, $extendedBin, "$base is not a prefix of $extended" );
        }
 
-       function prefixDataProvider() {
+       public static function prefixDataProvider() {
                return array(
                        array( 'en', 'A', 'AA' ),
                        array( 'en', 'A', 'AAA' ),
@@ -53,7 +61,7 @@ class CollationTest extends MediaWikiLangTestCase {
         *
         * @dataProvider notPrefixDataProvider
         */
-       function testNotIsPrefix( $lang, $base, $extended ) {
+       public function testNotIsPrefix( $lang, $base, $extended ) {
                $cp = Collator::create( $lang );
                $cp->setStrength( Collator::PRIMARY );
                $baseBin = $cp->getSortKey( $base );
@@ -63,7 +71,7 @@ class CollationTest extends MediaWikiLangTestCase {
                $this->assertStringStartsNotWith( $baseBin, $extendedBin, "$base is a prefix of $extended" );
        }
 
-       function notPrefixDataProvider() {
+       public static function notPrefixDataProvider() {
                return array(
                        array( 'en', 'A', 'B' ),
                        array( 'en', 'AC', 'ABC' ),
@@ -81,7 +89,7 @@ class CollationTest extends MediaWikiLangTestCase {
         *
         * @dataProvider firstLetterProvider
         */
-       function testGetFirstLetter( $collation, $string, $firstLetter ) {
+       public function testGetFirstLetter( $collation, $string, $firstLetter ) {
                $col = Collation::factory( $collation );
                $this->assertEquals( $firstLetter, $col->getFirstLetter( $string ) );
        }
index d927b7a..0b04c6e 100644 (file)
@@ -1,7 +1,10 @@
 <?php
 
 class DiffHistoryBlobTest extends MediaWikiTestCase {
+
        protected function setUp() {
+               parent::setUp();
+
                if ( !extension_loaded( 'xdiff' ) ) {
                        $this->markTestSkipped( 'The xdiff extension is not available' );
 
@@ -17,14 +20,14 @@ class DiffHistoryBlobTest extends MediaWikiTestCase {
 
                        return;
                }
-               parent::setUp();
        }
 
        /**
         * Test for DiffHistoryBlob::xdiffAdler32()
         * @dataProvider provideXdiffAdler32
+        * @covers DiffHistoryBlob::xdiffAdler32
         */
-       function testXdiffAdler32( $input ) {
+       public function testXdiffAdler32( $input ) {
                $xdiffHash = substr( xdiff_string_rabdiff( $input, '' ), 0, 4 );
                $dhb = new DiffHistoryBlob;
                $myHash = $dhb->xdiffAdler32( $input );
index 76ef782..0dee6b0 100644 (file)
@@ -13,8 +13,9 @@ class EditPageTest extends MediaWikiLangTestCase {
 
        /**
         * @dataProvider provideExtractSectionTitle
+        * @covers EditPage::extractSectionTitle
         */
-       function testExtractSectionTitle( $section, $title ) {
+       public function testExtractSectionTitle( $section, $title ) {
                $extracted = EditPage::extractSectionTitle( $section );
                $this->assertEquals( $title, $extracted );
        }
@@ -59,7 +60,7 @@ class EditPageTest extends MediaWikiLangTestCase {
         * wrapper around assertEquals() which calls rrtrim() to normalize the
         * expected and actual texts.
         */
-       function assertEditedTextEquals( $expected, $actual, $msg = '' ) {
+       protected function assertEditedTextEquals( $expected, $actual, $msg = '' ) {
                return $this->assertEquals( rtrim( $expected ), rtrim( $actual ), $msg );
        }
 
@@ -172,6 +173,10 @@ class EditPageTest extends MediaWikiLangTestCase {
                return $page;
        }
 
+       /**
+        * @todo split into a dataprovider and test method
+        * @covers EditPage
+        */
        public function testCreatePage() {
                $this->assertEdit(
                        'EditPageTest_testCreatePage',
@@ -197,7 +202,6 @@ class EditPageTest extends MediaWikiLangTestCase {
                        "expected article not being created if empty"
                );
 
-
                $this->assertEdit(
                        'MediaWiki:January',
                        null,
@@ -338,6 +342,7 @@ hello
 
        /**
         * @dataProvider provideSectionEdit
+        * @covers EditPage
         */
        public function testSectionEdit( $base, $section, $text, $summary, $expected ) {
                $edit = array(
@@ -432,6 +437,7 @@ hello
 
        /**
         * @dataProvider provideAutoMerge
+        * @covers EditPage
         */
        public function testAutoMerge( $baseUser, $text, $adamsEdit, $bertasEdit,
                $expectedCode, $expectedText, $message = null
diff --git a/tests/phpunit/includes/ExceptionTest.php b/tests/phpunit/includes/ExceptionTest.php
new file mode 100644 (file)
index 0000000..e2a3711
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Tests for includes/Exception.php.
+ *
+ * @author Antoine Musso
+ * @copyright Copyright © 2013, Antoine Musso
+ * @copyright Copyright © 2013, Wikimedia Foundation Inc.
+ * @file
+ */
+
+class ExceptionTest extends MediaWikiTestCase {
+
+       /**
+        * @expectedException MWException
+        */
+       function testMwexceptionThrowing() {
+               throw new MWException();
+       }
+
+       /**
+        * Verify the exception classes are JSON serializabe.
+        *
+        * @covers MWExceptionHandler::jsonSerializeException
+        * @dataProvider provideExceptionClasses
+        */
+       function testJsonSerializeExceptions( $exception_class ) {
+               $json = MWExceptionHandler::jsonSerializeException(
+                       new $exception_class()
+               );
+               $this->assertNotEquals( false, $json,
+                       "The $exception_class exception should be JSON serializable, got false." );
+       }
+
+       function provideExceptionClasses() {
+               return array(
+                       array( 'Exception' ),
+                       array( 'MWException' ),
+               );
+       }
+
+       /**
+        * Lame JSON schema validation.
+        *
+        * @covers MWExceptionHandler::jsonSerializeException
+        *
+        * @param $expectedKeyType String Type expected as returned by gettype()
+        * @param $exClass String An exception class (ie: Exception, MWException)
+        * @param $key String Name of the key to validate in the serialized JSON
+        * @dataProvider provideJsonSerializedKeys
+        */
+       function testJsonserializeexceptionKeys( $expectedKeyType, $exClass, $key ) {
+
+               # Make sure we log a backtrace:
+               $this->setMwGlobals( array( 'wgLogExceptionBacktrace' => true ) );
+
+               $json = json_decode(
+                       MWExceptionHandler::jsonSerializeException( new $exClass())
+               );
+               $this->assertObjectHasAttribute( $key, $json,
+                       "JSON serialized exception is missing key '$key'"
+               );
+               $this->assertInternalType( $expectedKeyType, $json->$key,
+                       "JSON serialized key '$key' has type " . gettype( $json->$key )
+                       . " (expected: $expectedKeyType)."
+               );
+       }
+
+       /**
+        * Returns test cases: exception class, key name, gettype()
+        */
+       function provideJsonSerializedKeys() {
+               $testCases = array();
+               foreach ( array( 'Exception', 'MWException' ) as $exClass ) {
+                       $exTests = array(
+                               array( 'string',  $exClass,  'id' ),
+                               array( 'string',  $exClass,  'file' ),
+                               array( 'integer', $exClass,  'line' ),
+                               array( 'string',  $exClass,  'message' ),
+                               array( 'null',    $exClass,  'url' ),
+                               # Backtrace only enabled with wgLogExceptionBacktrace = true
+                               array( 'array',   $exClass,  'backtrace' ),
+                       );
+                       $testCases = array_merge( $testCases, $exTests );
+               }
+               return $testCases;
+       }
+
+       /**
+        * Given wgLogExceptionBacktrace is true
+        * then serialized exception SHOULD have a backtrace
+        *
+        * @covers MWExceptionHandler::jsonSerializeException
+        */
+       function testJsonserializeexceptionBacktracingEnabled() {
+               $this->setMwGlobals( array( 'wgLogExceptionBacktrace' => true ) );
+               $json = json_decode(
+                       MWExceptionHandler::jsonSerializeException( new Exception() )
+               );
+               $this->assertObjectHasAttribute( 'backtrace', $json );
+       }
+
+       /**
+        * Given wgLogExceptionBacktrace is false
+        * then serialized exception SHOULD NOT have a backtrace
+        *
+        * @covers MWExceptionHandler::jsonSerializeException
+        */
+       function testJsonserializeexceptionBacktracingDisabled() {
+               $this->setMwGlobals( array( 'wgLogExceptionBacktrace' => false ) );
+               $json = json_decode(
+                       MWExceptionHandler::jsonSerializeException( new Exception() )
+               );
+               $this->assertObjectNotHasAttribute( 'backtrace', $json );
+
+       }
+
+}
index 99544e7..ba155a4 100644 (file)
@@ -5,7 +5,10 @@
 
 class ExternalStoreTest extends MediaWikiTestCase {
 
-       function testExternalFetchFromURL() {
+       /**
+        * @covers ExternalStore::fetchFromURL
+        */
+       public function testExternalFetchFromURL() {
                $this->setMwGlobals( 'wgExternalStores', false );
 
                $this->assertFalse(
index 07215c1..dc19154 100644 (file)
@@ -5,6 +5,11 @@
  */
 class ExtraParserTest extends MediaWikiTestCase {
 
+       /** @var ParserOptions */
+       protected $options;
+       /** @var Parser */
+       protected $parser;
+
        protected function setUp() {
                parent::setUp();
 
@@ -26,8 +31,11 @@ class ExtraParserTest extends MediaWikiTestCase {
                MagicWord::clearCache();
        }
 
-       // Bug 8689 - Long numeric lines kill the parser
-       function testBug8689() {
+       /**
+        * Bug 8689 - Long numeric lines kill the parser
+        * @covers Parser::parse
+        */
+       public function testBug8689() {
                global $wgUser;
                $longLine = '1.' . str_repeat( '1234567890', 100000 ) . "\n";
 
@@ -37,14 +45,20 @@ class ExtraParserTest extends MediaWikiTestCase {
                        $this->parser->parse( $longLine, $t, $options )->getText() );
        }
 
-       /* Test the parser entry points */
-       function testParse() {
+       /**
+        * Test the parser entry points
+        * @covers Parser::parse
+        */
+       public function testParse() {
                $title = Title::newFromText( __FUNCTION__ );
                $parserOutput = $this->parser->parse( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
                $this->assertEquals( "<p>Test\nContent of <i>Template:Foo</i>\nContent of <i>Template:Bar</i>\n</p>", $parserOutput->getText() );
        }
 
-       function testPreSaveTransform() {
+       /**
+        * @covers Parser::preSaveTransform
+        */
+       public function testPreSaveTransform() {
                global $wgUser;
                $title = Title::newFromText( __FUNCTION__ );
                $outputText = $this->parser->preSaveTransform( "Test\r\n{{subst:Foo}}\n{{Bar}}", $title, $wgUser, $this->options );
@@ -52,7 +66,10 @@ class ExtraParserTest extends MediaWikiTestCase {
                $this->assertEquals( "Test\nContent of ''Template:Foo''\n{{Bar}}", $outputText );
        }
 
-       function testPreprocess() {
+       /**
+        * @covers Parser::preprocess
+        */
+       public function testPreprocess() {
                $title = Title::newFromText( __FUNCTION__ );
                $outputText = $this->parser->preprocess( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options );
 
@@ -61,8 +78,9 @@ class ExtraParserTest extends MediaWikiTestCase {
 
        /**
         * cleanSig() makes all templates substs and removes tildes
+        * @covers Parser::cleanSig
         */
-       function testCleanSig() {
+       public function testCleanSig() {
                $title = Title::newFromText( __FUNCTION__ );
                $outputText = $this->parser->cleanSig( "{{Foo}} ~~~~" );
 
@@ -71,8 +89,9 @@ class ExtraParserTest extends MediaWikiTestCase {
 
        /**
         * cleanSig() should do nothing if disabled
+        * @covers Parser::cleanSig
         */
-       function testCleanSigDisabled() {
+       public function testCleanSigDisabled() {
                $this->setMwGlobals( 'wgCleanSignatures', false );
 
                $title = Title::newFromText( __FUNCTION__ );
@@ -84,8 +103,9 @@ class ExtraParserTest extends MediaWikiTestCase {
        /**
         * cleanSigInSig() just removes tildes
         * @dataProvider provideStringsForCleanSigInSig
+        * @covers Parser::cleanSigInSig
         */
-       function testCleanSigInSig( $in, $out ) {
+       public function testCleanSigInSig( $in, $out ) {
                $this->assertEquals( Parser::cleanSigInSig( $in ), $out );
        }
 
@@ -97,7 +117,10 @@ class ExtraParserTest extends MediaWikiTestCase {
                );
        }
 
-       function testGetSection() {
+       /**
+        * @covers Parser::getSection
+        */
+       public function testGetSection() {
                $outputText2 = $this->parser->getSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 2 );
                $outputText1 = $this->parser->getSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 1 );
 
@@ -105,7 +128,10 @@ class ExtraParserTest extends MediaWikiTestCase {
                $this->assertEquals( "== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2", $outputText1 );
        }
 
-       function testReplaceSection() {
+       /**
+        * @covers Parser::replaceSection
+        */
+       public function testReplaceSection() {
                $outputText = $this->parser->replaceSection( "Section 0\n== Heading 1 ==\nSection 1\n=== Heading 2 ===\nSection 2\n== Heading 3 ==\nSection 3\n", 1, "New section 1" );
 
                $this->assertEquals( "Section 0\nNew section 1\n\n== Heading 3 ==\nSection 3", $outputText );
@@ -113,8 +139,9 @@ class ExtraParserTest extends MediaWikiTestCase {
 
        /**
         * Templates and comments are not affected, but noinclude/onlyinclude is.
+        * @covers Parser::getPreloadText
         */
-       function testGetPreloadText() {
+       public function testGetPreloadText() {
                $title = Title::newFromText( __FUNCTION__ );
                $outputText = $this->parser->getPreloadText( "{{Foo}}<noinclude> censored</noinclude> information <!-- is very secret -->", $title, $this->options );
 
@@ -133,8 +160,9 @@ class ExtraParserTest extends MediaWikiTestCase {
 
        /**
         * @group Database
+        * @covers Parser::parse
         */
-       function testTrackingCategory() {
+       public function testTrackingCategory() {
                $title = Title::newFromText( __FUNCTION__ );
                $catName = wfMessage( 'broken-file-category' )->inContentLanguage()->text();
                $cat = Title::makeTitleSafe( NS_CATEGORY, $catName );
@@ -146,8 +174,9 @@ class ExtraParserTest extends MediaWikiTestCase {
 
        /**
         * @group Database
+        * @covers Parser::parse
         */
-       function testTrackingCategorySpecial() {
+       public function testTrackingCategorySpecial() {
                // Special pages shouldn't have tracking cats.
                $title = SpecialPage::getTitleFor( 'Contributions' );
                $parserOutput = $this->parser->parse( "[[file:nonexistent]]", $title, $this->options );
diff --git a/tests/phpunit/includes/FallbackTest.php b/tests/phpunit/includes/FallbackTest.php
new file mode 100644 (file)
index 0000000..910b766
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @covers Fallback
+ */
+class FallbackTest extends MediaWikiTestCase {
+
+       public function testFallbackMbstringFunctions() {
+
+               if ( !extension_loaded( 'mbstring' ) ) {
+                       $this->markTestSkipped( "The mb_string functions must be installed to test the fallback functions" );
+               }
+
+               $sampleUTF = "Östergötland_coat_of_arms.png";
+
+               //mb_substr
+               $substr_params = array(
+                       array( 0, 0 ),
+                       array( 5, -4 ),
+                       array( 33 ),
+                       array( 100, -5 ),
+                       array( -8, 10 ),
+                       array( 1, 1 ),
+                       array( 2, -1 )
+               );
+
+               foreach ( $substr_params as $param_set ) {
+                       $old_param_set = $param_set;
+                       array_unshift( $param_set, $sampleUTF );
+
+                       $this->assertEquals(
+                               call_user_func_array( 'mb_substr', $param_set ),
+                               call_user_func_array( 'Fallback::mb_substr', $param_set ),
+                               'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
+                       );
+               }
+
+               //mb_strlen
+               $this->assertEquals(
+                       mb_strlen( $sampleUTF ),
+                       Fallback::mb_strlen( $sampleUTF ),
+                       'Fallback mb_strlen'
+               );
+
+               //mb_str(r?)pos
+               $strpos_params = array(
+                       //array( 'ter' ),
+                       //array( 'Ö' ),
+                       //array( 'Ö', 3 ),
+                       //array( 'oat_', 100 ),
+                       //array( 'c', -10 ),
+                       //Broken for now
+               );
+
+               foreach ( $strpos_params as $param_set ) {
+                       $old_param_set = $param_set;
+                       array_unshift( $param_set, $sampleUTF );
+
+                       $this->assertEquals(
+                               call_user_func_array( 'mb_strpos', $param_set ),
+                               call_user_func_array( 'Fallback::mb_strpos', $param_set ),
+                               'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
+                       );
+
+                       $this->assertEquals(
+                               call_user_func_array( 'mb_strrpos', $param_set ),
+                               call_user_func_array( 'Fallback::mb_strrpos', $param_set ),
+                               'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
+                       );
+               }
+       }
+}
index dfb0f13..3246410 100644 (file)
@@ -2,7 +2,11 @@
 
 class FauxRequestTest extends MediaWikiTestCase {
 
-       function testGetSetHeader() {
+       /**
+        * @covers FauxRequest::setHeader
+        * @covers FauxRequest::getHeader
+        */
+       public function testGetSetHeader() {
                $value = 'test/test';
 
                $request = new FauxRequest();
index 977c22b..7f41cfd 100644 (file)
  */
 
 class FauxResponseTest extends MediaWikiTestCase {
-       var $response;
+       /** @var FauxResponse */
+       protected $response;
 
        protected function setUp() {
                parent::setUp();
                $this->response = new FauxResponse;
        }
 
-       function testCookie() {
+       /**
+        * @covers FauxResponse::getcookie
+        * @covers FauxResponse::setcookie
+        */
+       public function testCookie() {
                $this->assertEquals( null, $this->response->getcookie( 'key' ), 'Non-existing cookie' );
                $this->response->setcookie( 'key', 'val' );
                $this->assertEquals( 'val', $this->response->getcookie( 'key' ), 'Existing cookie' );
        }
 
-       function testHeader() {
+       /**
+        * @covers FauxResponse::getheader
+        * @covers FauxResponse::header
+        */
+       public function testHeader() {
                $this->assertEquals( null, $this->response->getheader( 'Location' ), 'Non-existing header' );
 
                $this->response->header( 'Location: http://localhost/' );
@@ -52,7 +61,10 @@ class FauxResponseTest extends MediaWikiTestCase {
                $this->assertEquals( 'http://localhost/', $this->response->getheader( 'LOCATION' ), 'Get header case insensitive' );
        }
 
-       function testResponseCode() {
+       /**
+        * @covers FauxResponse::getStatusCode
+        */
+       public function testResponseCode() {
                $this->response->header( 'HTTP/1.1 200' );
                $this->assertEquals( 200, $this->response->getStatusCode(), 'Header with no message' );
 
index fb2304d..1531b56 100644 (file)
@@ -35,7 +35,6 @@ class FormOptionsInitializationTest extends MediaWikiTestCase {
         */
        protected $object;
 
-
        /**
         * A new fresh and empty FormOptions object to test initialization
         * with.
@@ -45,6 +44,9 @@ class FormOptionsInitializationTest extends MediaWikiTestCase {
                $this->object = new FormOptionsExposed();
        }
 
+       /**
+        * @covers FormOptionsExposed::add
+        */
        public function testAddStringOption() {
                $this->object->add( 'foo', 'string value' );
                $this->assertEquals(
@@ -60,6 +62,9 @@ class FormOptionsInitializationTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers FormOptionsExposed::add
+        */
        public function testAddIntegers() {
                $this->object->add( 'one', 1 );
                $this->object->add( 'negone', -1 );
index 0a13cfe..665fa39 100644 (file)
@@ -34,6 +34,7 @@ class FormOptionsTest extends MediaWikiTestCase {
                $this->object->add( 'string1', 'string one' );
                $this->object->add( 'string2', 'string two' );
                $this->object->add( 'integer', 0 );
+               $this->object->add( 'float', 0.0 );
                $this->object->add( 'intnull', 0, FormOptions::INTNULL );
        }
 
@@ -45,6 +46,9 @@ class FormOptionsTest extends MediaWikiTestCase {
        private function assertGuessInt( $data ) {
                $this->guess( FormOptions::INT, $data );
        }
+       private function assertGuessFloat( $data ) {
+               $this->guess( FormOptions::FLOAT, $data );
+       }
        private function assertGuessString( $data ) {
                $this->guess( FormOptions::STRING, $data );
        }
@@ -60,6 +64,7 @@ class FormOptionsTest extends MediaWikiTestCase {
 
        /**
         * Reuse helpers above assertGuessBoolean assertGuessInt assertGuessString
+        * @covers FormOptions::guessType
         */
        public function testGuessTypeDetection() {
                $this->assertGuessBoolean( true );
@@ -70,20 +75,27 @@ class FormOptionsTest extends MediaWikiTestCase {
                $this->assertGuessInt( 5 );
                $this->assertGuessInt( 0x0F );
 
+               $this->assertGuessFloat( 0.0 );
+               $this->assertGuessFloat( 1.5 );
+               $this->assertGuessFloat( 1e3 );
+
                $this->assertGuessString( 'true' );
                $this->assertGuessString( 'false' );
                $this->assertGuessString( '5' );
                $this->assertGuessString( '0' );
+               $this->assertGuessString( '1.5' );
        }
 
        /**
         * @expectedException MWException
+        * @covers FormOptions::guessType
         */
        public function testGuessTypeOnArrayThrowException() {
                $this->object->guessType( array( 'foo' ) );
        }
        /**
         * @expectedException MWException
+        * @covers FormOptions::guessType
         */
        public function testGuessTypeOnNullThrowException() {
                $this->object->guessType( null );
index 244b100..f67f696 100644 (file)
@@ -29,7 +29,10 @@ class GlobalTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
-       /** @dataProvider provideForWfArrayDiff2 */
+       /**
+        * @dataProvider provideForWfArrayDiff2
+        * @covers ::wfArrayDiff2
+        */
        public function testWfArrayDiff2( $a, $b, $expected ) {
                $this->assertEquals(
                        wfArrayDiff2( $a, $b ), $expected
@@ -53,25 +56,37 @@ class GlobalTest extends MediaWikiTestCase {
                );
        }
 
-       function testRandom() {
+       /**
+        * @covers ::wfRandom
+        */
+       public function testRandom() {
                # This could hypothetically fail, but it shouldn't ;)
                $this->assertFalse(
                        wfRandom() == wfRandom() );
        }
 
-       function testUrlencode() {
+       /**
+        * @covers ::wfUrlencode
+        */
+       public function testUrlencode() {
                $this->assertEquals(
                        "%E7%89%B9%E5%88%A5:Contributions/Foobar",
                        wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
        }
 
-       function testExpandIRI() {
+       /**
+        * @covers ::wfExpandIRI
+        */
+       public function testExpandIRI() {
                $this->assertEquals(
                        "https://te.wikibooks.org/wiki/ఉబుంటు_వాడుకరి_మార్గదర్శని",
                        wfExpandIRI( "https://te.wikibooks.org/wiki/%E0%B0%89%E0%B0%AC%E0%B1%81%E0%B0%82%E0%B0%9F%E0%B1%81_%E0%B0%B5%E0%B0%BE%E0%B0%A1%E0%B1%81%E0%B0%95%E0%B0%B0%E0%B0%BF_%E0%B0%AE%E0%B0%BE%E0%B0%B0%E0%B1%8D%E0%B0%97%E0%B0%A6%E0%B0%B0%E0%B1%8D%E0%B0%B6%E0%B0%A8%E0%B0%BF" ) );
        }
 
-       function testReadOnlyEmpty() {
+       /**
+        * @covers ::wfReadOnly
+        */
+       public function testReadOnlyEmpty() {
                global $wgReadOnly;
                $wgReadOnly = null;
 
@@ -79,7 +94,10 @@ class GlobalTest extends MediaWikiTestCase {
                $this->assertFalse( wfReadOnly() );
        }
 
-       function testReadOnlySet() {
+       /**
+        * @covers ::wfReadOnly
+        */
+       public function testReadOnlySet() {
                global $wgReadOnly, $wgReadOnlyFile;
 
                $f = fopen( $wgReadOnlyFile, "wt" );
@@ -97,12 +115,6 @@ class GlobalTest extends MediaWikiTestCase {
                $this->assertFalse( wfReadOnly() );
        }
 
-       function testQuotedPrintable() {
-               $this->assertEquals(
-                       "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
-                       UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
-       }
-
        public static function provideArrayToCGI() {
                return array(
                        array( array(), '' ), // empty
@@ -123,13 +135,16 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideArrayToCGI
+        * @covers ::wfArrayToCgi
         */
-       function testArrayToCGI( $array, $result ) {
+       public function testArrayToCGI( $array, $result ) {
                $this->assertEquals( $result, wfArrayToCgi( $array ) );
        }
 
-
-       function testArrayToCGI2() {
+       /**
+        * @covers ::wfArrayToCgi
+        */
+       public function testArrayToCGI2() {
                $this->assertEquals(
                        "baz=bar&foo=bar",
                        wfArrayToCgi(
@@ -154,8 +169,9 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideCgiToArray
+        * @covers ::wfCgiToArray
         */
-       function testCgiToArray( $cgi, $result ) {
+       public function testCgiToArray( $cgi, $result ) {
                $this->assertEquals( $result, wfCgiToArray( $cgi ) );
        }
 
@@ -174,12 +190,16 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideCgiRoundTrip
+        * @covers ::wfArrayToCgi
         */
-       function testCgiRoundTrip( $cgi ) {
+       public function testCgiRoundTrip( $cgi ) {
                $this->assertEquals( $cgi, wfArrayToCgi( wfCgiToArray( $cgi ) ) );
        }
 
-       function testMimeTypeMatch() {
+       /**
+        * @covers ::mimeTypeMatch
+        */
+       public function testMimeTypeMatch() {
                $this->assertEquals(
                        'text/html',
                        mimeTypeMatch( 'text/html',
@@ -201,7 +221,10 @@ class GlobalTest extends MediaWikiTestCase {
                                        'image/svg+xml' => 0.5 ) ) );
        }
 
-       function testNegotiateType() {
+       /**
+        * @covers ::wfNegotiateType
+        */
+       public function testNegotiateType() {
                $this->assertEquals(
                        'text/html',
                        wfNegotiateType(
@@ -242,73 +265,11 @@ class GlobalTest extends MediaWikiTestCase {
                                array( 'application/xhtml+xml' => 1.0 ) ) );
        }
 
-       function testFallbackMbstringFunctions() {
-
-               if ( !extension_loaded( 'mbstring' ) ) {
-                       $this->markTestSkipped( "The mb_string functions must be installed to test the fallback functions" );
-               }
-
-               $sampleUTF = "Östergötland_coat_of_arms.png";
-
-               //mb_substr
-               $substr_params = array(
-                       array( 0, 0 ),
-                       array( 5, -4 ),
-                       array( 33 ),
-                       array( 100, -5 ),
-                       array( -8, 10 ),
-                       array( 1, 1 ),
-                       array( 2, -1 )
-               );
-
-               foreach ( $substr_params as $param_set ) {
-                       $old_param_set = $param_set;
-                       array_unshift( $param_set, $sampleUTF );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_substr', $param_set ),
-                               call_user_func_array( 'Fallback::mb_substr', $param_set ),
-                               'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
-                       );
-               }
-
-               //mb_strlen
-               $this->assertEquals(
-                       mb_strlen( $sampleUTF ),
-                       Fallback::mb_strlen( $sampleUTF ),
-                       'Fallback mb_strlen'
-               );
-
-               //mb_str(r?)pos
-               $strpos_params = array(
-                       //array( 'ter' ),
-                       //array( 'Ö' ),
-                       //array( 'Ö', 3 ),
-                       //array( 'oat_', 100 ),
-                       //array( 'c', -10 ),
-                       //Broken for now
-               );
-
-               foreach ( $strpos_params as $param_set ) {
-                       $old_param_set = $param_set;
-                       array_unshift( $param_set, $sampleUTF );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_strpos', $param_set ),
-                               call_user_func_array( 'Fallback::mb_strpos', $param_set ),
-                               'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
-                       );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_strrpos', $param_set ),
-                               call_user_func_array( 'Fallback::mb_strrpos', $param_set ),
-                               'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
-                       );
-               }
-       }
-
-
-       function testDebugFunctionTest() {
+       /**
+        * @covers ::wfDebug
+        * @covers ::wfDebugMem
+        */
+       public function testDebugFunctionTest() {
 
                global $wgDebugLogFile, $wgDebugTimestamps;
 
@@ -331,18 +292,21 @@ class GlobalTest extends MediaWikiTestCase {
                unlink( $wgDebugLogFile );
 
                wfDebugMem();
-               $this->assertGreaterThan( 5000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
+               $this->assertGreaterThan( 1000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
                unlink( $wgDebugLogFile );
 
                wfDebugMem( true );
-               $this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
+               $this->assertGreaterThan( 1000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
                unlink( $wgDebugLogFile );
 
                $wgDebugLogFile = $old_log_file;
                $wgDebugTimestamps = $old_wgDebugTimestamps;
        }
 
-       function testClientAcceptsGzipTest() {
+       /**
+        * @covers ::wfClientAcceptsGzip
+        */
+       public function testClientAcceptsGzipTest() {
 
                $settings = array(
                        'gzip' => true,
@@ -373,7 +337,10 @@ class GlobalTest extends MediaWikiTestCase {
                }
        }
 
-       function testSwapVarsTest() {
+       /**
+        * @covers ::swap
+        */
+       public function testSwapVarsTest() {
                $var1 = 1;
                $var2 = 2;
 
@@ -386,7 +353,10 @@ class GlobalTest extends MediaWikiTestCase {
                $this->assertEquals( $var2, 1, 'var2 is swapped' );
        }
 
-       function testWfPercentTest() {
+       /**
+        * @covers ::wfPercent
+        */
+       public function testWfPercentTest() {
 
                $pcts = array(
                        array( 6 / 7, '0.86%', 2, false ),
@@ -414,6 +384,7 @@ class GlobalTest extends MediaWikiTestCase {
        /**
         * test @see wfShorthandToInteger()
         * @dataProvider provideShorthand
+        * @covers ::wfShorthandToInteger
         */
        public function testWfShorthandToInteger( $shorthand, $expected ) {
                $this->assertEquals( $expected,
@@ -474,6 +445,7 @@ class GlobalTest extends MediaWikiTestCase {
         *
         * @dataProvider provideMerge()
         * @group medium
+        * @covers ::wfMerge
         */
        public function testMerge( $old, $mine, $yours, $expectedMergeResult, $expectedText ) {
                $this->checkHasDiff3();
@@ -549,8 +521,9 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideMakeUrlIndexes()
+        * @covers ::wfMakeUrlIndexes
         */
-       function testMakeUrlIndexes( $url, $expected ) {
+       public function testMakeUrlIndexes( $url, $expected ) {
                $index = wfMakeUrlIndexes( $url );
                $this->assertEquals( $expected, $index, "wfMakeUrlIndexes(\"$url\")" );
        }
@@ -606,8 +579,9 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideWfMatchesDomainList
+        * @covers ::wfMatchesDomainList
         */
-       function testWfMatchesDomainList( $url, $domains, $expected, $description ) {
+       public function testWfMatchesDomainList( $url, $domains, $expected, $description ) {
                $actual = wfMatchesDomainList( $url, $domains );
                $this->assertEquals( $expected, $actual, $description );
        }
@@ -630,7 +604,10 @@ class GlobalTest extends MediaWikiTestCase {
                return $a;
        }
 
-       function testWfMkdirParents() {
+       /**
+        * @covers ::wfMkdirParents
+        */
+       public function testWfMkdirParents() {
                // Should not return true if file exists instead of directory
                $fname = $this->getNewTempFile();
                wfSuppressWarnings();
@@ -641,8 +618,9 @@ class GlobalTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideWfShellMaintenanceCmdList
+        * @covers ::wfShellMaintenanceCmd
         */
-       function testWfShellMaintenanceCmd( $script, $parameters, $options, $expected, $description ) {
+       public function testWfShellMaintenanceCmd( $script, $parameters, $options, $expected, $description ) {
                if ( wfIsWindows() ) {
                        // Approximation that's good enough for our purposes just now
                        $expected = str_replace( "'", '"', $expected );
@@ -669,5 +647,5 @@ class GlobalTest extends MediaWikiTestCase {
                                "Called eval.php --help --test with wrapper and php option" ),
                );
        }
-       /* TODO: many more! */
+       /* @TODO many more! */
 }
index 8bd0849..cf891e7 100644 (file)
@@ -6,8 +6,9 @@
 class GlobalWithDBTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideWfIsBadImageList
+        * @covers ::wfIsBadImage
         */
-       function testWfIsBadImage( $name, $title, $blacklist, $expected, $desc ) {
+       public function testWfIsBadImage( $name, $title, $blacklist, $expected, $desc ) {
                $this->assertEquals( $expected, wfIsBadImage( $name, $title, $blacklist ), $desc );
        }
 
index 4184d15..9bb7487 100644 (file)
@@ -1,9 +1,11 @@
 <?php
 /**
- * Tests for wfAssembleUrl()
+ * @covers ::wfAssembleUrl
  */
 class WfAssembleUrlTest extends MediaWikiTestCase {
-       /** @dataProvider provideURLParts */
+       /**
+        * @dataProvider provideURLParts
+        */
        public function testWfAssembleUrl( $parts, $output ) {
                $partsDump = print_r( $parts, true );
                $this->assertEquals(
index baf9cee..a01c0d4 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Tests for wfBCP47()
+ * @covers ::wfBCP47
  */
 class WfBCP47Test extends MediaWikiTestCase {
        /**
@@ -13,7 +13,7 @@ class WfBCP47Test extends MediaWikiTestCase {
         * @see http://tools.ietf.org/html/bcp47
         * @dataProvider provideLanguageCodes()
         */
-       function testBCP47( $code, $expected ) {
+       public function testBCP47( $code, $expected ) {
                $code = strtolower( $code );
                $this->assertEquals( $expected, wfBCP47( $code ),
                        "Applying BCP47 standard to lower case '$code'"
index c60f223..7da804e 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Tests for wfBaseConvert()
+ * @covers ::wfBaseConvert
  */
 class WfBaseConvertTest extends MediaWikiTestCase {
        public static function provideSingleDigitConversions() {
index 3c4fa20..8c54804 100644 (file)
@@ -1,12 +1,12 @@
 <?php
 /**
- * Tests for wfBaseName()
+ * @covers ::wfBaseName
  */
 class WfBaseNameTest extends MediaWikiTestCase {
        /**
         * @dataProvider providePaths
         */
-       function testBaseName( $fullpath, $basename ) {
+       public function testBaseName( $fullpath, $basename ) {
                $this->assertEquals( $basename, wfBaseName( $fullpath ),
                        "wfBaseName('$fullpath') => '$basename'" );
        }
index 5b622c1..b06f3d2 100644 (file)
@@ -1,23 +1,19 @@
 <?php
 /**
- * Tests for wfExpandUrl()
+ * @covers ::wfExpandUrl
  */
 class WfExpandUrlTest extends MediaWikiTestCase {
-       /** @dataProvider provideExpandableUrls */
+       /**
+        * @dataProvider provideExpandableUrls
+        */
        public function testWfExpandUrl( $fullUrl, $shortUrl, $defaultProto, $server, $canServer, $httpsMode, $message ) {
-               // Fake $wgServer and $wgCanonicalServer
+               // Fake $wgServer, $wgCanonicalServer and $wgRequest->getProtocol()
                $this->setMwGlobals( array(
                        'wgServer' => $server,
                        'wgCanonicalServer' => $canServer,
+                       'wgRequest' => new FauxRequest( array(), false, null, $httpsMode ? 'https' : 'http' )
                ) );
 
-               // Fake $_SERVER['HTTPS'] if needed
-               if ( $httpsMode ) {
-                       $_SERVER['HTTPS'] = 'on';
-               } else {
-                       unset( $_SERVER['HTTPS'] );
-               }
-
                $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl, $defaultProto ), $message );
        }
 
index 3521d18..6229624 100644 (file)
@@ -1,8 +1,11 @@
 <?php
 
+/**
+ * @covers ::wfGetCaller
+ */
 class WfGetCallerTest extends MediaWikiTestCase {
 
-       function testZero() {
+       public function testZero() {
                $this->assertEquals( __METHOD__, wfGetCaller( 1 ) );
        }
 
@@ -10,7 +13,7 @@ class WfGetCallerTest extends MediaWikiTestCase {
                return wfGetCaller();
        }
 
-       function testOne() {
+       public function testOne() {
                $this->assertEquals( 'WfGetCallerTest::testOne', self::callerOne() );
        }
 
@@ -22,11 +25,11 @@ class WfGetCallerTest extends MediaWikiTestCase {
                return wfGetCaller( $level );
        }
 
-       function testTwo() {
+       public function testTwo() {
                $this->assertEquals( 'WfGetCallerTest::testTwo', self::intermediateFunction() );
        }
 
-       function testN() {
+       public function testN() {
                $this->assertEquals( 'WfGetCallerTest::testN', self::intermediateFunction( 2, 0 ) );
                $this->assertEquals( 'WfGetCallerTest::intermediateFunction', self::intermediateFunction( 1, 0 ) );
 
index 841a1b1..5032dc1 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- * Tests for wfParseUrl()
- *
  * Copyright © 2013 Alexandre Emsenhuber
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,6 +20,9 @@
  * @file
  */
 
+/**
+ * @covers ::wfParseUrl
+ */
 class WfParseUrlTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
@@ -31,7 +32,9 @@ class WfParseUrlTest extends MediaWikiTestCase {
                ) );
        }
 
-       /** @dataProvider provideURLs */
+       /**
+        * @dataProvider provideURLs
+        */
        public function testWfParseUrl( $url, $parts ) {
                $partsDump = var_export( $parts, true );
                $this->assertEquals(
index 67861ee..238a2c9 100644 (file)
@@ -1,9 +1,11 @@
 <?php
 /**
- * Tests for wfRemoveDotSegments()
+ *@covers ::wfRemoveDotSegments
  */
 class WfRemoveDotSegmentsTest extends MediaWikiTestCase {
-       /** @dataProvider providePaths */
+       /**
+        * @dataProvider providePaths
+        */
        public function testWfRemoveDotSegments( $inputPath, $outputPath ) {
                $this->assertEquals(
                        $outputPath,
index 604f901..aadec87 100644 (file)
@@ -1,10 +1,13 @@
 <?php
 
+/**
+ * @covers ::wfShorthandToInteger
+ */
 class WfShorthandToIntegerTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideABunchOfShorthands
         */
-       function testWfShorthandToInteger( $input, $output, $description ) {
+       public function testWfShorthandToInteger( $input, $output, $description ) {
                $this->assertEquals(
                        wfShorthandToInteger( $input ),
                        $output,
index 32bb49d..5998f18 100644 (file)
@@ -1,12 +1,12 @@
 <?php
 /*
- * Tests for wfTimestamp()
+ * @covers ::wfTimestamp
  */
 class WfTimestampTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideNormalTimestamps
         */
-       function testNormalTimestamps( $input, $format, $output, $desc ) {
+       public function testNormalTimestamps( $input, $format, $output, $desc ) {
                $this->assertEquals( $output, wfTimestamp( $format, $input ), $desc );
        }
 
@@ -57,7 +57,7 @@ class WfTimestampTest extends MediaWikiTestCase {
         * See r74778 and bug 25451
         * @dataProvider provideOldTimestamps
         */
-       function testOldTimestamps( $input, $format, $output, $desc ) {
+       public function testOldTimestamps( $input, $format, $output, $desc ) {
                $this->assertEquals( $output, wfTimestamp( $format, $input ), $desc );
        }
 
@@ -96,7 +96,7 @@ class WfTimestampTest extends MediaWikiTestCase {
         * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
         * @dataProvider provideHttpDates
         */
-       function testHttpDate( $input, $output, $desc ) {
+       public function testHttpDate( $input, $output, $desc ) {
                $this->assertEquals( $output, wfTimestamp( TS_MW, $input ), $desc );
        }
 
@@ -114,7 +114,7 @@ class WfTimestampTest extends MediaWikiTestCase {
         * There are a number of assumptions in our codebase where wfTimestamp()
         * should give the current date but it is not given a 0 there. See r71751 CR
         */
-       function testTimestampParameter() {
+       public function testTimestampParameter() {
                $now = wfTimestamp( TS_UNIX );
                // We check that wfTimestamp doesn't return false (error) and use a LessThan assert
                // for the cases where the test is run in a second boundary.
index 77685d5..ce6c82c 100644 (file)
@@ -1,18 +1,21 @@
 <?php
 /**
- * Tests for wfUrlencode()
- *
  * The function only need a string parameter and might react to IIS7.0
+ * @covers ::wfUrlencode
  */
 class WfUrlencodeTest extends MediaWikiTestCase {
        #### TESTS ##############################################################
 
-       /** @dataProvider provideURLS */
+       /**
+        * @dataProvider provideURLS
+        */
        public function testEncodingUrlWith( $input, $expected ) {
                $this->verifyEncodingFor( 'Apache', $input, $expected );
        }
 
-       /** @dataProvider provideURLS */
+       /**
+        * @dataProvider provideURLS
+        */
        public function testEncodingUrlWithMicrosoftIis7( $input, $expected ) {
                $this->verifyEncodingFor( 'Microsoft-IIS/7', $input, $expected );
        }
index 5bbafd3..39c3959 100644 (file)
@@ -1,7 +1,8 @@
 <?php
 
 /**
- * Unit tests for the HTMLCheckMatrix form field
+ * Unit tests for the HTMLCheckMatrix + HTMLFormField
+ * @todo the tests for the two classes could be split up
  */
 class HtmlCheckMatrixTest extends MediaWikiTestCase {
        static private $defaultOptions = array(
@@ -10,6 +11,9 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
                'fieldname' => 'test',
        );
 
+       /**
+        * @covers HTMLCheckMatrix::__construct
+        */
        public function testPlainInstantiation() {
                try {
                        $form = new HTMLCheckMatrix( array() );
@@ -21,11 +25,17 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
                $this->fail( 'Expected MWException indicating missing parameters but none was thrown.' );
        }
 
+       /**
+        * @covers HTMLCheckMatrix::__construct
+        */
        public function testInstantiationWithMinimumRequiredParameters() {
                $form = new HTMLCheckMatrix( self::$defaultOptions );
                $this->assertTrue( true ); // form instantiation must throw exception on failure
        }
 
+       /**
+        * @covers HTMLFormField::validate
+        */
        public function testValidateCallsUserDefinedValidationCallback() {
                $called = false;
                $field = new HTMLCheckMatrix( self::$defaultOptions + array(
@@ -38,6 +48,9 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
                $this->assertTrue( $called );
        }
 
+       /**
+        * @covers HTMLFormField::validate
+        */
        public function testValidateRequiresArrayInput() {
                $field = new HTMLCheckMatrix( self::$defaultOptions );
                $this->assertEquals( false, $this->validate( $field, null ) );
@@ -47,11 +60,17 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
                $this->assertEquals( true, $this->validate( $field, array() ) );
        }
 
+       /**
+        * @covers HTMLFormField::validate
+        */
        public function testValidateAllowsOnlyKnownTags() {
                $field = new HTMLCheckMatrix( self::$defaultOptions );
                $this->assertInternalType( 'string', $this->validate( $field, array( 'foo' ) ) );
        }
 
+       /**
+        * @covers HTMLFormField::validate
+        */
        public function testValidateAcceptsPartialTagList() {
                $field = new HTMLCheckMatrix( self::$defaultOptions );
                $this->assertTrue( $this->validate( $field, array() ) );
@@ -65,6 +84,7 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
         * foreach ( $field->filterDataForSubmit( $data ) as $k => $v ) {
         *     $user->setOption( $k, $v );
         * }
+        * @covers HTMLFormField::filterDataForSubmit
         */
        public function testValuesForcedOnRemainOn() {
                $field = new HTMLCheckMatrix( self::$defaultOptions + array(
@@ -79,6 +99,9 @@ class HtmlCheckMatrixTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $field->filterDataForSubmit( array() ) );
        }
 
+       /**
+        * @covers HTMLFormField::filterDataForSubmit
+        */
        public function testValuesForcedOffRemainOff() {
                $field = new HTMLCheckMatrix( self::$defaultOptions + array(
                        'force-options-off' => array( 'c1-r2', 'c2-r2' ),
diff --git a/tests/phpunit/includes/HashRingTest.php b/tests/phpunit/includes/HashRingTest.php
deleted file mode 100644 (file)
index bc4e499..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @group HashRing
- */
-class HashRingTest extends MediaWikiTestCase {
-       function testHashRing() {
-               $ring = new HashRing( array( 's1' => 1, 's2' => 1, 's3' => 2, 's4' => 2, 's5' => 2, 's6' => 3 ) );
-
-               $locations = array();
-               for ( $i = 0; $i < 20; $i++ ) {
-                       $locations[ "hello$i"] = $ring->getLocation( "hello$i" );
-               }
-               $expectedLocations = array(
-                       "hello0" => "s5",
-                       "hello1" => "s6",
-                       "hello2" => "s2",
-                       "hello3" => "s5",
-                       "hello4" => "s6",
-                       "hello5" => "s4",
-                       "hello6" => "s5",
-                       "hello7" => "s4",
-                       "hello8" => "s5",
-                       "hello9" => "s5",
-                       "hello10" => "s3",
-                       "hello11" => "s6",
-                       "hello12" => "s1",
-                       "hello13" => "s3",
-                       "hello14" => "s3",
-                       "hello15" => "s5",
-                       "hello16" => "s4",
-                       "hello17" => "s6",
-                       "hello18" => "s6",
-                       "hello19" => "s3"
-               );
-
-               $this->assertEquals( $expectedLocations, $locations, 'Items placed at proper locations' );
-
-               $locations = array();
-               for ( $i = 0; $i < 5; $i++ ) {
-                       $locations[ "hello$i"] = $ring->getLocations( "hello$i", 2 );
-               }
-
-               $expectedLocations = array(
-                       "hello0" => array( "s5", "s6" ),
-                       "hello1" => array( "s6", "s4" ),
-                       "hello2" => array( "s2", "s1" ),
-                       "hello3" => array( "s5", "s6" ),
-                       "hello4" => array( "s6", "s4" ),
-               );
-               $this->assertEquals( $expectedLocations, $locations, 'Items placed at proper locations' );
-       }
-}
index 81dd487..87af6c1 100644 (file)
@@ -35,6 +35,7 @@ class HooksTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideHooks
+        * @covers ::wfRunHooks
         */
        public function testOldStyleHooks( $msg, array $hook, $expectedFoo, $expectedBar ) {
                global $wgHooks;
@@ -49,6 +50,8 @@ class HooksTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideHooks
+        * @covers Hooks::register
+        * @covers Hooks::run
         */
        public function testNewStyleHooks( $msg, $hook, $expectedFoo, $expectedBar ) {
                $foo = $bar = 'original';
@@ -60,6 +63,12 @@ class HooksTest extends MediaWikiTestCase {
                $this->assertSame( $expectedBar, $bar, $msg );
        }
 
+       /**
+        * @covers Hooks::isRegistered
+        * @covers Hooks::register
+        * @covers Hooks::getHandlers
+        * @covers Hooks::run
+        */
        public function testNewStyleHookInteraction() {
                global $wgHooks;
 
@@ -82,12 +91,16 @@ class HooksTest extends MediaWikiTestCase {
 
        /**
         * @expectedException MWException
+        * @covers Hooks::run
         */
        public function testUncallableFunction() {
                Hooks::register( 'MediaWikiHooksTest001', 'ThisFunctionDoesntExist' );
                Hooks::run( 'MediaWikiHooksTest001', array() );
        }
 
+       /**
+        * @covers Hooks::run
+        */
        public function testFalseReturn() {
                Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
                        return false;
@@ -104,6 +117,7 @@ class HooksTest extends MediaWikiTestCase {
 
        /**
         * @expectedException FatalError
+        * @covers Hooks::run
         */
        public function testFatalError() {
                Hooks::register( 'MediaWikiHooksTest001', function () {
index a37df74..7ef0b60 100644 (file)
@@ -6,6 +6,7 @@
 class HtmlFormatterTest extends MediaWikiTestCase {
        /**
         * @dataProvider getHtmlData
+        * @covers HtmlFormatter::getText
         */
        public function testTransform( $input, $expected, $callback = false ) {
                $input = self::normalize( $input );
index ecfe418..21372a0 100644 (file)
@@ -41,6 +41,9 @@ class HtmlTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers Html::element
+        */
        public function testElementBasics() {
                $this->assertEquals(
                        '<img>',
@@ -89,11 +92,15 @@ class HtmlTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider dataXmlMimeType
+        * @covers Html::isXmlMimeType
         */
        public function testXmlMimeType( $mimetype, $isXmlMimeType ) {
                $this->assertEquals( $isXmlMimeType, Html::isXmlMimeType( $mimetype ) );
        }
 
+       /**
+        * @covers HTML::expandAttributes
+        */
        public function testExpandAttributesSkipsNullAndFalse() {
 
                ### EMPTY ########
@@ -111,6 +118,9 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers HTML::expandAttributes
+        */
        public function testExpandAttributesForBooleans() {
                $this->assertEquals(
                        '',
@@ -146,6 +156,7 @@ class HtmlTest extends MediaWikiTestCase {
        /**
         * Test for Html::expandAttributes()
         * Please note it output a string prefixed with a space!
+        * @covers Html::expandAttributes
         */
        public function testExpandAttributesVariousExpansions() {
                ### NOT EMPTY ####
@@ -198,6 +209,7 @@ class HtmlTest extends MediaWikiTestCase {
         * Html::expandAttributes has special features for HTML
         * attributes that use space separated lists and also
         * allows arrays to be used as values.
+        * @covers Html::expandAttributes
         */
        public function testExpandAttributesListValueAttributes() {
                ### STRING VALUES
@@ -249,8 +261,9 @@ class HtmlTest extends MediaWikiTestCase {
        /**
         * Test feature added by r96188, let pass attributes values as
         * a PHP array. Restricted to class,rel, accesskey.
+        * @covers Html::expandAttributes
         */
-       function testExpandAttributesSpaceSeparatedAttributesWithBoolean() {
+       public function testExpandAttributesSpaceSeparatedAttributesWithBoolean() {
                $this->assertEquals(
                        ' class="booltrue one"',
                        Html::expandAttributes( array( 'class' => array(
@@ -273,8 +286,9 @@ class HtmlTest extends MediaWikiTestCase {
         * The later will take precedence.
         *
         * Feature added by r96188
+        * @covers Html::expandAttributes
         */
-       function testValueIsAuthoritativeInSpaceSeparatedAttributesArrays() {
+       public function testValueIsAuthoritativeInSpaceSeparatedAttributesArrays() {
                $this->assertEquals(
                        ' class=""',
                        Html::expandAttributes( array( 'class' => array(
@@ -285,7 +299,10 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
-       function testNamespaceSelector() {
+       /**
+        * @covers Html::namespaceSelector
+        */
+       public function testNamespaceSelector() {
                $this->assertEquals(
                        '<select id=namespace name=namespace>' . "\n" .
                                '<option value=0>(Main)</option>' . "\n" .
@@ -364,7 +381,7 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
-       function testCanFilterOutNamespaces() {
+       public function testCanFilterOutNamespaces() {
                $this->assertEquals(
                        '<select id=namespace name=namespace>' . "\n" .
                                '<option value=2>User</option>' . "\n" .
@@ -386,7 +403,7 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
-       function testCanDisableANamespaces() {
+       public function testCanDisableANamespaces() {
                $this->assertEquals(
                        '<select id=namespace name=namespace>' . "\n" .
                                '<option disabled value=0>(Main)</option>' . "\n" .
@@ -415,8 +432,9 @@ class HtmlTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideHtml5InputTypes
+        * @covers Html::element
         */
-       function testHtmlElementAcceptsNewHtml5TypesInHtml5Mode( $HTML5InputType ) {
+       public function testHtmlElementAcceptsNewHtml5TypesInHtml5Mode( $HTML5InputType ) {
                $this->assertEquals(
                        '<input type=' . $HTML5InputType . '>',
                        Html::element( 'input', array( 'type' => $HTML5InputType ) ),
@@ -457,7 +475,7 @@ class HtmlTest extends MediaWikiTestCase {
         * @covers Html::dropDefaults
         * @dataProvider provideElementsWithAttributesHavingDefaultValues
         */
-       function testDropDefaults( $expected, $element, $attribs, $message = '' ) {
+       public function testDropDefaults( $expected, $element, $attribs, $message = '' ) {
                $this->assertEquals( $expected, Html::element( $element, $attribs ), $message );
        }
 
@@ -617,6 +635,9 @@ class HtmlTest extends MediaWikiTestCase {
                return $ret;
        }
 
+       /**
+        * @covers Html::expandAttributes
+        */
        public function testFormValidationBlacklist() {
                $this->assertEmpty(
                        Html::expandAttributes( array( 'min' => 1, 'max' => 100, 'pattern' => 'abc', 'required' => true, 'step' => 2 ) ),
index 6e0aa88..11d8ed6 100644 (file)
@@ -53,7 +53,7 @@ class HttpTest extends MediaWikiTestCase {
         * @dataProvider provideURI
         * @covers Http::isValidURI
         */
-       function testIsValidUri( $expect, $URI, $message = '' ) {
+       public function testIsValidUri( $expect, $URI, $message = '' ) {
                $this->assertEquals(
                        $expect,
                        (bool)Http::isValidURI( $URI ),
diff --git a/tests/phpunit/includes/IPTest.php b/tests/phpunit/includes/IPTest.php
deleted file mode 100644 (file)
index 22bf0c0..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-<?php
-/**
- * Tests for IP validity functions.
- *
- * Ported from /t/inc/IP.t by avar.
- *
- * @group IP
- * @todo Test methods in this call should be split into a method and a
- * dataprovider.
- */
-
-class IPTest extends MediaWikiTestCase {
-       /**
-        *  not sure it should be tested with boolean false. hashar 20100924
-        * @covers IP::isIPAddress
-        */
-       public function testisIPAddress() {
-               $this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' );
-               $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' );
-               $this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' );
-               $this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' );
-               $this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' );
-               $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' );
-               $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::' ), 'IPv6 with a double :: occurrence, last at end' );
-               $this->assertFalse( IP::isIPAddress( '::2001:0DB8::5:1' ), 'IPv6 with a double :: occurrence, firt at beginning' );
-               $this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' );
-               $this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' );
-               $this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' );
-               $this->assertFalse( IP::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' );
-
-               $this->assertTrue( IP::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' );
-               $this->assertTrue( IP::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' );
-               $this->assertTrue( IP::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) );
-               $this->assertTrue( IP::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' );
-               $this->assertTrue( IP::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' );
-
-               $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac',
-                       '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' );
-               foreach ( $validIPs as $ip ) {
-                       $this->assertTrue( IP::isIPAddress( $ip ), "$ip is a valid IP address" );
-               }
-       }
-
-       /**
-        * @covers IP::isIPv6
-        */
-       public function testisIPv6() {
-               $this->assertFalse( IP::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' );
-               $this->assertFalse( IP::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
-               $this->assertFalse( IP::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' );
-               $this->assertFalse( IP::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' );
-
-               $this->assertTrue( IP::isIPv6( 'fc:100::' ) );
-               $this->assertTrue( IP::isIPv6( 'fc:100:a::' ) );
-               $this->assertTrue( IP::isIPv6( 'fc:100:a:d::' ) );
-               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1::' ) );
-               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e::' ) );
-               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac::' ) );
-
-               $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
-               $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' );
-
-               $this->assertFalse( IP::isIPv6( ':::' ) );
-               $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
-
-               $this->assertTrue( IP::isIPv6( '::' ), 'IPv6 zero address' );
-               $this->assertTrue( IP::isIPv6( '::0' ) );
-               $this->assertTrue( IP::isIPv6( '::fc' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100:a' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100:a:d' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e' ) );
-               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e:ac' ) );
-
-               $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
-               $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
-
-               $this->assertFalse( IP::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' );
-               $this->assertFalse( IP::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' );
-               $this->assertFalse( IP::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' );
-
-               $this->assertTrue( IP::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' );
-               $this->assertTrue( IP::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
-               $this->assertTrue( IP::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) );
-               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
-               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
-               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
-               $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
-               $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
-               $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
-
-               $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
-               $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
-
-               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
-       }
-
-       /**
-        * @covers IP::isIPv4
-        */
-       public function testisIPv4() {
-               $this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' );
-               $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' );
-               $this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' );
-               $this->assertFalse( IP::isIPv4( 'abc' ) );
-               $this->assertFalse( IP::isIPv4( ':' ) );
-               $this->assertFalse( IP::isIPv4( '124.24.52' ), 'IPv4 not enough quads' );
-               $this->assertFalse( IP::isIPv4( '24.324.52.13' ), 'IPv4 out of range' );
-               $this->assertFalse( IP::isIPv4( '.24.52.13' ), 'IPv4 starts with period' );
-
-               $this->assertTrue( IP::isIPv4( '124.24.52.13' ) );
-               $this->assertTrue( IP::isIPv4( '1.24.52.13' ) );
-               $this->assertTrue( IP::isIPv4( '74.24.52.13/20', 'IPv4 range' ) );
-       }
-
-       /**
-        * @covers IP::isValid
-        */
-       public function testValidIPs() {
-               foreach ( range( 0, 255 ) as $i ) {
-                       $a = sprintf( "%03d", $i );
-                       $b = sprintf( "%02d", $i );
-                       $c = sprintf( "%01d", $i );
-                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
-                               $ip = "$f.$f.$f.$f";
-                               $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv4 address" );
-                       }
-               }
-               foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) {
-                       $a = sprintf( "%04x", $i );
-                       $b = sprintf( "%03x", $i );
-                       $c = sprintf( "%02x", $i );
-                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
-                               $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
-                               $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv6 address" );
-                       }
-               }
-               // test with some abbreviations
-               $this->assertFalse( IP::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' );
-               $this->assertFalse( IP::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
-               $this->assertFalse( IP::isValid( 'fc:300' ), 'IPv6 with only 2 words' );
-               $this->assertFalse( IP::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' );
-
-               $this->assertTrue( IP::isValid( 'fc:100::' ) );
-               $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e::' ) );
-               $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e:ac::' ) );
-
-               $this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
-               $this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
-               $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
-               $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
-               $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
-               $this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
-               $this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
-
-               $this->assertFalse( IP::isValid( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
-               $this->assertFalse( IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' );
-       }
-
-       /**
-        * @covers IP::isValid
-        */
-       public function testInvalidIPs() {
-               // Out of range...
-               foreach ( range( 256, 999 ) as $i ) {
-                       $a = sprintf( "%03d", $i );
-                       $b = sprintf( "%02d", $i );
-                       $c = sprintf( "%01d", $i );
-                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
-                               $ip = "$f.$f.$f.$f";
-                               $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv4 address" );
-                       }
-               }
-               foreach ( range( 'g', 'z' ) as $i ) {
-                       $a = sprintf( "%04s", $i );
-                       $b = sprintf( "%03s", $i );
-                       $c = sprintf( "%02s", $i );
-                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
-                               $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
-                               $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv6 address" );
-                       }
-               }
-               // Have CIDR
-               $ipCIDRs = array(
-                       '212.35.31.121/32',
-                       '212.35.31.121/18',
-                       '212.35.31.121/24',
-                       '::ff:d:321:5/96',
-                       'ff::d3:321:5/116',
-                       'c:ff:12:1:ea:d:321:5/120',
-               );
-               foreach ( $ipCIDRs as $i ) {
-                       $this->assertFalse( IP::isValid( $i ),
-                               "$i is an invalid IP address because it is a block" );
-               }
-               // Incomplete/garbage
-               $invalid = array(
-                       'www.xn--var-xla.net',
-                       '216.17.184.G',
-                       '216.17.184.1.',
-                       '216.17.184',
-                       '216.17.184.',
-                       '256.17.184.1'
-               );
-               foreach ( $invalid as $i ) {
-                       $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" );
-               }
-       }
-
-       /**
-        * @covers IP::isValidBlock
-        */
-       public function testValidBlocks() {
-               $valid = array(
-                       '116.17.184.5/32',
-                       '0.17.184.5/30',
-                       '16.17.184.1/24',
-                       '30.242.52.14/1',
-                       '10.232.52.13/8',
-                       '30.242.52.14/0',
-                       '::e:f:2001/96',
-                       '::c:f:2001/128',
-                       '::10:f:2001/70',
-                       '::fe:f:2001/1',
-                       '::6d:f:2001/8',
-                       '::fe:f:2001/0',
-               );
-               foreach ( $valid as $i ) {
-                       $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" );
-               }
-       }
-
-       /**
-        * @covers IP::isValidBlock
-        */
-       public function testInvalidBlocks() {
-               $invalid = array(
-                       '116.17.184.5/33',
-                       '0.17.184.5/130',
-                       '16.17.184.1/-1',
-                       '10.232.52.13/*',
-                       '7.232.52.13/ab',
-                       '11.232.52.13/',
-                       '::e:f:2001/129',
-                       '::c:f:2001/228',
-                       '::10:f:2001/-1',
-                       '::6d:f:2001/*',
-                       '::86:f:2001/ab',
-                       '::23:f:2001/',
-               );
-               foreach ( $invalid as $i ) {
-                       $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" );
-               }
-       }
-
-       /**
-        * Improve IP::sanitizeIP() code coverage
-        * @todo Most probably incomplete
-        */
-       public function testSanitizeIP() {
-               $this->assertNull( IP::sanitizeIP( '' ) );
-               $this->assertNull( IP::sanitizeIP( ' ' ) );
-       }
-
-       /**
-        * @covers IP::toUnsigned
-        * @dataProvider provideToUnsigned
-        */
-       public function testToUnsigned( $expected, $input ) {
-               $result = IP::toUnsigned( $input );
-               $this->assertTrue( $result === false || is_string( $result ) || is_int( $result ) );
-               $this->assertEquals( $expected, $result );
-       }
-
-       /**
-        * Provider for IP::testToUnsigned()
-        */
-       public static function provideToUnsigned() {
-               return array(
-                       array( 1, '0.0.0.1' ),
-                       array( 16909060, '1.2.3.4' ),
-                       array( 2130706433, '127.0.0.1' ),
-                       array( '2147483648', '128.0.0.0' ),
-                       array( '3735931646', '222.173.202.254' ),
-                       array( pow( 2, 32 ) - 1, '255.255.255.255' ),
-                       array( false, 'IN.VA.LI.D' ),
-                       array( 1, '::1' ),
-                       array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
-                       array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ),
-                       array( false, 'IN:VA::LI:D' ),
-                       array( false, ':::1' )
-               );
-       }
-
-       /**
-        * @covers IP::toHex
-        * @dataProvider provideToHex
-        */
-       public function testToHex( $expected, $input ) {
-               $result = IP::toHex( $input );
-               $this->assertTrue( $result === false || is_string( $result ) );
-               $this->assertEquals( $expected, $result );
-       }
-
-       /**
-        * Provider for IP::testToHex()
-        */
-       public static function provideToHex() {
-               return array(
-                       array( '00000001', '0.0.0.1' ),
-                       array( '01020304', '1.2.3.4' ),
-                       array( '7F000001', '127.0.0.1' ),
-                       array( '80000000', '128.0.0.0' ),
-                       array( 'DEADCAFE', '222.173.202.254' ),
-                       array( 'FFFFFFFF', '255.255.255.255' ),
-                       array( false, 'IN.VA.LI.D' ),
-                       array( 'v6-00000000000000000000000000000001', '::1' ),
-                       array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
-                       array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
-                       array( false, 'IN:VA::LI:D' ),
-                       array( false, ':::1' )
-               );
-       }
-
-       /**
-        * @covers IP::isPublic
-        */
-       public function testPrivateIPs() {
-               $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' );
-               foreach ( $private as $p ) {
-                       $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" );
-               }
-               $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' );
-               foreach ( $public as $p ) {
-                       $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" );
-               }
-       }
-
-       // Private wrapper used to test CIDR Parsing.
-       private function assertFalseCIDR( $CIDR, $msg = '' ) {
-               $ff = array( false, false );
-               $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg );
-       }
-
-       // Private wrapper to test network shifting using only dot notation
-       private function assertNet( $expected, $CIDR ) {
-               $parse = IP::parseCIDR( $CIDR );
-               $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
-       }
-
-       /**
-        * @covers IP::hexToQuad
-        */
-       public function testHexToQuad() {
-               $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) );
-               $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) );
-               $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) );
-               $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) );
-               // hex not left-padded...
-               $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) );
-               $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) );
-               $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) );
-               $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) );
-       }
-
-       /**
-        * @covers IP::hexToOctet
-        */
-       public function testHexToOctet() {
-               $this->assertEquals( '0:0:0:0:0:0:0:1',
-                       IP::hexToOctet( '00000000000000000000000000000001' ) );
-               $this->assertEquals( '0:0:0:0:0:0:FF:3',
-                       IP::hexToOctet( '00000000000000000000000000FF0003' ) );
-               $this->assertEquals( '0:0:0:0:0:0:FF00:6',
-                       IP::hexToOctet( '000000000000000000000000FF000006' ) );
-               $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF',
-                       IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) );
-               $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
-                       IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
-               // hex not left-padded...
-               $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) );
-               $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) );
-               $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) );
-               $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) );
-               $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) );
-               $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) );
-       }
-
-       /**
-        * IP::parseCIDR() returns an array containing a signed IP address
-        * representing the network mask and the bit mask.
-        * @covers IP::parseCIDR
-        */
-       function testCIDRParsing() {
-               $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
-               $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
-
-               // Verify if statement
-               $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
-               $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
-               $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
-               $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
-
-               // Check internal logic
-               # 0 mask always result in array(0,0)
-               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) );
-               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) );
-               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) );
-
-               // @todo FIXME: Add more tests.
-
-               # This part test network shifting
-               $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
-               $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
-               $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
-               $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
-               $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
-               $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
-               $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
-               $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
-               $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
-       }
-
-       /**
-        * @covers IP::canonicalize
-        */
-       public function testIPCanonicalizeOnValidIp() {
-               $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ),
-                       'Canonicalization of a valid IP returns it unchanged' );
-       }
-
-       /**
-        * @covers IP::canonicalize
-        */
-       public function testIPCanonicalizeMappedAddress() {
-               $this->assertEquals(
-                       '192.0.2.152',
-                       IP::canonicalize( '::ffff:192.0.2.152' )
-               );
-               $this->assertEquals(
-                       '192.0.2.152',
-                       IP::canonicalize( '::192.0.2.152' )
-               );
-       }
-
-       /**
-        * Issues there are most probably from IP::toHex() or IP::parseRange()
-        * @covers IP::isInRange
-        * @dataProvider provideIPsAndRanges
-        */
-       public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
-               $this->assertEquals(
-                       $expected,
-                       IP::isInRange( $addr, $range ),
-                       $message
-               );
-       }
-
-       /** Provider for testIPIsInRange() */
-       public static function provideIPsAndRanges() {
-               # Format: (expected boolean, address, range, optional message)
-               return array(
-                       # IPv4
-                       array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
-                       array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
-                       array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
-
-                       array( false, '0.0.0.0', '192.0.2.0/24' ),
-                       array( false, '255.255.255', '192.0.2.0/24' ),
-
-                       # IPv6
-                       array( false, '::1', '2001:DB8::/32' ),
-                       array( false, '::', '2001:DB8::/32' ),
-                       array( false, 'FE80::1', '2001:DB8::/32' ),
-
-                       array( true, '2001:DB8::', '2001:DB8::/32' ),
-                       array( true, '2001:0DB8::', '2001:DB8::/32' ),
-                       array( true, '2001:DB8::1', '2001:DB8::/32' ),
-                       array( true, '2001:0DB8::1', '2001:DB8::/32' ),
-                       array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
-                               '2001:DB8::/32' ),
-
-                       array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
-               );
-       }
-
-       /**
-        * Test for IP::splitHostAndPort().
-        * @dataProvider provideSplitHostAndPort
-        */
-       function testSplitHostAndPort( $expected, $input, $description ) {
-               $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description );
-       }
-
-       /**
-        * Provider for IP::splitHostAndPort()
-        */
-       public static function provideSplitHostAndPort() {
-               return array(
-                       array( false, '[', 'Unclosed square bracket' ),
-                       array( false, '[::', 'Unclosed square bracket 2' ),
-                       array( array( '::', false ), '::', 'Bare IPv6 0' ),
-                       array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
-                       array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
-                       array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
-                       array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
-                       array( false, '::x', 'Double colon but no IPv6' ),
-                       array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
-                       array( false, 'x:x', 'Hostname and invalid port' ),
-                       array( array( 'x', false ), 'x', 'Plain hostname' )
-               );
-       }
-
-       /**
-        * Test for IP::combineHostAndPort()
-        * @dataProvider provideCombineHostAndPort
-        */
-       function testCombineHostAndPort( $expected, $input, $description ) {
-               list( $host, $port, $defaultPort ) = $input;
-               $this->assertEquals(
-                       $expected,
-                       IP::combineHostAndPort( $host, $port, $defaultPort ),
-                       $description );
-       }
-
-       /**
-        * Provider for IP::combineHostAndPort()
-        */
-       public static function provideCombineHostAndPort() {
-               return array(
-                       array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
-                       array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
-                       array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
-                       array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
-               );
-       }
-
-       /**
-        * Test for IP::sanitizeRange()
-        * @dataProvider provideIPCIDRs
-        */
-       function testSanitizeRange( $input, $expected, $description ) {
-               $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
-       }
-
-       /**
-        * Provider for IP::testSanitizeRange()
-        */
-       public static function provideIPCIDRs() {
-               return array(
-                       array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
-                       array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
-                       array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
-                       array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
-                       array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
-                       array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
-                       array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
-                       array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
-               );
-       }
-
-       /**
-        * Test for IP::prettifyIP()
-        * @dataProvider provideIPsToPrettify
-        */
-       function testPrettifyIP( $ip, $prettified ) {
-               $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" );
-       }
-
-       /**
-        * Provider for IP::testPrettifyIP()
-        */
-       public static function provideIPsToPrettify() {
-               return array(
-                       array( '0:0:0:0:0:0:0:0', '::' ),
-                       array( '0:0:0::0:0:0', '::' ),
-                       array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
-                       array( '0:0::f', '::f' ),
-                       array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
-                       array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
-                       array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
-                       array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
-                       array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
-                       array( '0:0:0:0:0:0:0:0/16', '::/16' ),
-                       array( '0:0:0::0:0:0/64', '::/64' ),
-                       array( '0:0::f/52', '::f/52' ),
-                       array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
-                       array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
-                       array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
-                       array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
-                       array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),
-               );
-       }
-}
index 070a680..d4ccca9 100644 (file)
@@ -1,7 +1,9 @@
 <?php
 
 class LanguageConverterTest extends MediaWikiLangTestCase {
+       /** @var LanguageToTest */
        protected $lang = null;
+       /** @var TestConverter */
        protected $lc = null;
 
        protected function setUp() {
@@ -30,39 +32,61 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                parent::tearDown();
        }
 
-       function testGetPreferredVariantDefaults() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantDefaults() {
                $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantHeaders() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaders() {
                global $wgRequest;
                $wgRequest->setHeader( 'Accept-Language', 'tg-latn' );
 
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantHeaderWeight() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderWeight() {
                global $wgRequest;
                $wgRequest->setHeader( 'Accept-Language', 'tg;q=1' );
 
                $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantHeaderWeight2() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderWeight2() {
                global $wgRequest;
                $wgRequest->setHeader( 'Accept-Language', 'tg-latn;q=1' );
 
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantHeaderMulti() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderMulti() {
                global $wgRequest;
                $wgRequest->setHeader( 'Accept-Language', 'en, tg-latn;q=1' );
 
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantUserOption() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantUserOption() {
                global $wgUser;
 
                $wgUser = new User;
@@ -75,7 +99,11 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantUserOptionForForeignLanguage() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getUserVariant
+        */
+       public function testGetPreferredVariantUserOptionForForeignLanguage() {
                global $wgContLang, $wgUser;
 
                $wgContLang = Language::factory( 'en' );
@@ -89,7 +117,12 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantHeaderUserVsUrl() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getUserVariant
+        * @covers LanguageConverter::getURLVariant
+        */
+       public function testGetPreferredVariantHeaderUserVsUrl() {
                global $wgContLang, $wgRequest, $wgUser;
 
                $wgContLang = Language::factory( 'tg-latn' );
@@ -103,15 +136,21 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
        }
 
-
-       function testGetPreferredVariantDefaultLanguageVariant() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantDefaultLanguageVariant() {
                global $wgDefaultLanguageVariant;
 
                $wgDefaultLanguageVariant = 'tg-latn';
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       function testGetPreferredVariantDefaultLanguageVsUrlVariant() {
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getURLVariant
+        */
+       public function testGetPreferredVariantDefaultLanguageVsUrlVariant() {
                global $wgDefaultLanguageVariant, $wgRequest, $wgContLang;
 
                $wgContLang = Language::factory( 'tg-latn' );
index 212b3b3..63b2c39 100644 (file)
@@ -1,8 +1,11 @@
 <?php
 
+/**
+ * @covers Licenses
+ */
 class LicensesTest extends MediaWikiTestCase {
 
-       function testLicenses() {
+       public function testLicenses() {
                $str = "
 * Free licenses:
 ** GFDL|Debian disagrees
diff --git a/tests/phpunit/includes/LinkFilterTest.php b/tests/phpunit/includes/LinkFilterTest.php
new file mode 100644 (file)
index 0000000..41207b7
--- /dev/null
@@ -0,0 +1,274 @@
+<?php
+
+/**
+ * @group Database
+ */
+class LinkFilterTest extends MediaWikiLangTestCase {
+
+       protected function setUp() {
+
+               parent::setUp();
+
+               $this->setMwGlobals( 'wgUrlProtocols', array(
+                       'http://',
+                       'https://',
+                       'ftp://',
+                       'irc://',
+                       'ircs://',
+                       'gopher://',
+                       'telnet://',
+                       'nntp://',
+                       'worldwind://',
+                       'mailto:',
+                       'news:',
+                       'svn://',
+                       'git://',
+                       'mms://',
+                       '//',
+               ) );
+
+       }
+
+       /**
+        * createRegexFromLike($like)
+        *
+        * Takes an array as created by LinkFilter::makeLikeArray() and creates a regex from it
+        *
+        * @param Array $like Array as created by LinkFilter::makeLikeArray()
+        * @return string Regex
+        */
+       function createRegexFromLIKE( $like ) {
+
+               $regex = '!^';
+
+               foreach ( $like as $item ) {
+
+                       if ( $item instanceof LikeMatch ) {
+                               if ( $item->toString() == '%' ) {
+                                       $regex .= '.*';
+                               } elseif ( $item->toString() == '_' ) {
+                                       $regex .= '.';
+                               }
+                       } else {
+                               $regex .= preg_quote( $item, '!' );
+                       }
+
+               }
+
+               $regex .= '$!';
+
+               return $regex;
+
+       }
+
+       /**
+        * provideValidPatterns()
+        *
+        * @return array
+        */
+       public static function provideValidPatterns() {
+
+               return array(
+                       // Protocol, Search pattern, URL which matches the pattern
+                       array( 'http://', '*.test.com', 'http://www.test.com' ),
+                       array( 'http://', 'test.com:8080/dir/file', 'http://name:pass@test.com:8080/dir/file' ),
+                       array( 'https://', '*.com', 'https://s.s.test..com:88/dir/file?a=1&b=2' ),
+                       array( 'https://', '*.com', 'https://name:pass@secure.com/index.html' ),
+                       array( 'http://', 'name:pass@test.com', 'http://test.com' ),
+                       array( 'http://', 'test.com', 'http://name:pass@test.com' ),
+                       array( 'http://', '*.test.com', 'http://a.b.c.test.com/dir/dir/file?a=6'),
+                       array( null, 'http://*.test.com', 'http://www.test.com' ),
+                       array( 'mailto:', 'name@mail.test123.com', 'mailto:name@mail.test123.com' ),
+                       array( '',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg'
+                       ),
+                       array( '', 'http://name:pass@*.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg' ),
+                       array( '', 'http://name:wrongpass@*.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg' ),
+                       array( 'http://', 'name:pass@*.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg' ),
+                       array( '', 'http://name:pass@www.test.com:12345',
+                               'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg' ),
+                       array( 'ftp://', 'user:pass@ftp.test.com:1233/home/user/file;type=efw',
+                               'ftp://user:pass@ftp.test.com:1233/home/user/file;type=efw' ),
+                       array( null, 'ftp://otheruser:otherpass@ftp.test.com:1233/home/user/file;type=',
+                               'ftp://user:pass@ftp.test.com:1233/home/user/file;type=efw' ),
+                       array( null, 'ftp://@ftp.test.com:1233/home/user/file;type=',
+                               'ftp://user:pass@ftp.test.com:1233/home/user/file;type=efw' ),
+                       array( null, 'ftp://ftp.test.com/',
+                               'ftp://user:pass@ftp.test.com/home/user/file;type=efw' ),
+                       array( null, 'ftp://ftp.test.com/',
+                               'ftp://user:pass@ftp.test.com/home/user/file;type=efw' ),
+                       array( null, 'ftp://*.test.com:222/',
+                               'ftp://user:pass@ftp.test.com:222/home' ),
+                       array( 'irc://', '*.myserver:6667/', 'irc://test.myserver:6667/' ),
+                       array( 'irc://', 'name:pass@*.myserver/', 'irc://test.myserver:6667/' ),
+                       array( 'irc://', 'name:pass@*.myserver/', 'irc://other:@test.myserver:6667/' ),
+                       array( '', 'irc://test/name,string,abc?msg=t', 'irc://test/name,string,abc?msg=test' ),
+                       array( '', 'https://gerrit.wikimedia.org/r/#/q/status:open,n,z',
+                               'https://gerrit.wikimedia.org/r/#/q/status:open,n,z' ),
+                       array( '', 'https://gerrit.wikimedia.org',
+                               'https://gerrit.wikimedia.org/r/#/q/status:open,n,z' ),
+                       array( 'mailto:', '*.test.com', 'mailto:name@pop3.test.com' ),
+                       array( 'mailto:', 'test.com', 'mailto:name@test.com' ),
+                       array( 'news:', 'test.1234afc@news.test.com', 'news:test.1234afc@news.test.com' ),
+                       array( 'news:', '*.test.com', 'news:test.1234afc@news.test.com' ),
+                       array( '', 'news:4df8kh$iagfewewf(at)newsbf02aaa.news.aol.com',
+                               'news:4df8kh$iagfewewf(at)newsbf02aaa.news.aol.com' ),
+                       array( '', 'news:*.aol.com',
+                               'news:4df8kh$iagfewewf(at)newsbf02aaa.news.aol.com' ),
+                       array( '', 'git://github.com/prwef/abc-def.git', 'git://github.com/prwef/abc-def.git' ),
+                       array( 'git://', 'github.com/', 'git://github.com/prwef/abc-def.git' ),
+                       array( 'git://', '*.github.com/', 'git://a.b.c.d.e.f.github.com/prwef/abc-def.git' ),
+                       array( '', 'gopher://*.test.com/', 'gopher://gopher.test.com/0/v2/vstat'),
+                       array( 'telnet://', '*.test.com', 'telnet://shell.test.com/~home/'),
+
+                       //
+                       // The following only work in PHP >= 5.3.7, due to a bug in parse_url which eats
+                       // the path from the url (https://bugs.php.net/bug.php?id=54180)
+                       //
+                       // array( '', 'http://test.com', 'http://test.com/index?arg=1' ),
+                       // array( 'http://', '*.test.com', 'http://www.test.com/index?arg=1' ),
+                       // array( '' ,
+                       //    'http://xx23124:__ffdfdef__@www.test.com:12345/dir' ,
+                       //    'http://name:pass@www.test.com:12345/dir/dir/file.xyz.php#__se__?arg1=_&arg2[]=4rtg'
+                       // ),
+                       //
+
+                       //
+                       // Tests for false positives
+                       //
+                       array( 'http://', 'test.com', 'http://www.test.com', false ),
+                       array( 'http://', 'www1.test.com', 'http://www.test.com', false ),
+                       array( 'http://', '*.test.com', 'http://www.test.t.com', false ),
+                       array( '', 'http://test.com:8080', 'http://www.test.com:8080', false ),
+                       array( '', 'https://test.com', 'http://test.com', false ),
+                       array( '', 'http://test.com', 'https://test.com', false ),
+                       array( 'http://', 'http://test.com', 'http://test.com', false ),
+                       array( null, 'http://www.test.com', 'http://www.test.com:80', false ),
+                       array( null, 'http://www.test.com:80', 'http://www.test.com', false ),
+                       array( null, 'http://*.test.com:80', 'http://www.test.com', false ),
+                       array( '', 'https://gerrit.wikimedia.org/r/#/XXX/status:open,n,z',
+                               'https://gerrit.wikimedia.org/r/#/q/status:open,n,z', false ),
+                       array( '', 'https://*.wikimedia.org/r/#/q/status:open,n,z',
+                               'https://gerrit.wikimedia.org/r/#/XXX/status:open,n,z', false ),
+                       array( 'mailto:', '@test.com', '@abc.test.com', false ),
+                       array( 'mailto:', 'mail@test.com', 'mail2@test.com', false ),
+                       array( '', 'mailto:mail@test.com', 'mail2@test.com', false ),
+                       array( '', 'mailto:@test.com', '@abc.test.com', false ),
+                       array( 'ftp://', '*.co', 'ftp://www.co.uk', false ),
+                       array( 'ftp://', '*.co', 'ftp://www.co.m', false ),
+                       array( 'ftp://', '*.co/dir/', 'ftp://www.co/dir2/', false ),
+                       array( 'ftp://', 'www.co/dir/', 'ftp://www.co/dir2/', false ),
+                       array( 'ftp://', 'test.com/dir/', 'ftp://test.com/', false ),
+                       array( '', 'http://test.com:8080/dir/', 'http://test.com:808/dir/', false ),
+                       array( '', 'http://test.com/dir/index.html', 'http://test.com/dir/index.php', false ),
+
+                       //
+                       // These are false positives too and ideally shouldn't match, but that
+                       // would require using regexes and RLIKE instead of LIKE
+                       //
+                       // array( null, 'http://*.test.com', 'http://www.test.com:80', false ),
+                       // array( '', 'https://*.wikimedia.org/r/#/q/status:open,n,z',
+                       //      'https://gerrit.wikimedia.org/XXX/r/#/q/status:open,n,z', false ),
+               );
+
+       }
+
+       /**
+        * testMakeLikeArrayWithValidPatterns()
+        *
+        * Tests whether the LIKE clause produced by LinkFilter::makeLikeArray($pattern, $protocol)
+        * will find one of the URL indexes produced by wfMakeUrlIndexes($url)
+        *
+        * @dataProvider provideValidPatterns
+        *
+        * @param String $protocol Protocol, e.g. 'http://' or 'mailto:'
+        * @param String $pattern Search pattern to feed to LinkFilter::makeLikeArray
+        * @param String $url URL to feed to wfMakeUrlIndexes
+        * @param bool $shouldBeFound Should the URL be found? (defaults true)
+        */
+       function testMakeLikeArrayWithValidPatterns( $protocol, $pattern, $url, $shouldBeFound = true ) {
+
+               $indexes = wfMakeUrlIndexes( $url );
+               $likeArray = LinkFilter::makeLikeArray( $pattern, $protocol );
+
+               $this->assertTrue( $likeArray !== false,
+                       "LinkFilter::makeLikeArray('$pattern', '$protocol') returned false on a valid pattern"
+               );
+
+               $regex = $this->createRegexFromLIKE( $likeArray );
+               $debugmsg = "Regex: '" . $regex . "'\n";
+               $debugmsg .= count( $indexes ) . " index(es) created by wfMakeUrlIndexes():\n";
+
+               $matches = 0;
+
+               foreach ( $indexes as $index ) {
+                       $matches += preg_match( $regex, $index );
+                       $debugmsg .= "\t'$index'\n";
+               }
+
+               if ( $shouldBeFound ) {
+                       $this->assertTrue(
+                               $matches > 0,
+                               "Search pattern '$protocol$pattern' does not find url '$url' \n$debugmsg"
+                       );
+               } else {
+                       $this->assertFalse(
+                               $matches > 0,
+                               "Search pattern '$protocol$pattern' should not find url '$url' \n$debugmsg"
+                       );
+               }
+
+       }
+
+       /**
+        * provideInvalidPatterns()
+        *
+        * @return array
+        */
+       public static function provideInvalidPatterns() {
+
+               return array(
+                       array( '' ),
+                       array( '*' ),
+                       array( 'http://*' ),
+                       array( 'http://*/' ),
+                       array( 'http://*/dir/file' ),
+                       array( 'test.*.com' ),
+                       array( 'http://test.*.com' ),
+                       array( 'test.*.com' ),
+                       array( 'http://*.test.*' ),
+                       array( 'http://*test.com' ),
+                       array( 'https://*' ),
+                       array( '*://test.com'),
+                       array( 'mailto:name:pass@t*est.com' ),
+                       array( 'http://*:888/'),
+                       array( '*http://'),
+                       array( 'test.com/*/index' ),
+                       array( 'test.com/dir/index?arg=*' ),
+               );
+
+       }
+
+       /**
+        * testMakeLikeArrayWithInvalidPatterns()
+        *
+        * Tests whether LinkFilter::makeLikeArray($pattern) will reject invalid search patterns
+        *
+        * @dataProvider provideInvalidPatterns
+        *
+        * @param $pattern string: Invalid search pattern
+        */
+       function testMakeLikeArrayWithInvalidPatterns( $pattern ) {
+
+               $this->assertFalse(
+                       LinkFilter::makeLikeArray( $pattern ),
+                       "'$pattern' is not a valid pattern and should be rejected"
+               );
+
+       }
+
+}
index ec4d98e..b605f08 100644 (file)
@@ -6,7 +6,7 @@ class LinkerTest extends MediaWikiLangTestCase {
         * @dataProvider provideCasesForUserLink
         * @covers Linker::userLink
         */
-       function testUserLink( $expected, $userId, $userName, $altUserName = false, $msg = '' ) {
+       public function testUserLink( $expected, $userId, $userName, $altUserName = false, $msg = '' ) {
                $this->setMwGlobals( array(
                        'wgArticlePath' => '/wiki/$1',
                        'wgWellFormedXml' => true,
index 5ade250..b37ff2e 100644 (file)
@@ -52,6 +52,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                return array( $t, $po );
        }
 
+       /**
+        * @covers LinksUpdate::addLink
+        */
        public function testUpdate_pagelinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -86,6 +89,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ), $update->getRemovedLinks() );
        }
 
+       /**
+        * @covers LinksUpdate::addExternalLink
+        */
        public function testUpdate_externallinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -96,6 +102,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::addCategory
+        */
        public function testUpdate_categorylinks() {
                $this->setMwGlobals( 'wgCategoryCollation', 'uppercase' );
 
@@ -108,6 +117,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::addInterwikiLink
+        */
        public function testUpdate_iwlinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -119,6 +131,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::addTemplate
+        */
        public function testUpdate_templatelinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -129,6 +144,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::addImage
+        */
        public function testUpdate_imagelinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -139,6 +157,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::addLanguageLink
+        */
        public function testUpdate_langlinks() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
@@ -149,6 +170,9 @@ class LinksUpdateTest extends MediaWikiTestCase {
                ) );
        }
 
+       /**
+        * @covers LinksUpdate::setProperty
+        */
        public function testUpdate_page_props() {
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
index d6f0d2e..694f4ae 100644 (file)
@@ -3,6 +3,7 @@
 /**
  * These tests should work regardless of $wgCapitalLinks
  * @group Database
+ * @todo Split tests into providers and test methods
  */
 
 class LocalFileTest extends MediaWikiTestCase {
@@ -35,72 +36,105 @@ class LocalFileTest extends MediaWikiTestCase {
                $this->file_lc = $this->repo_lc->newFile( 'test!' );
        }
 
-       function testGetHashPath() {
+       /**
+        * @covers File::getHashPath
+        */
+       public function testGetHashPath() {
                $this->assertEquals( '', $this->file_hl0->getHashPath() );
                $this->assertEquals( 'a/a2/', $this->file_hl2->getHashPath() );
                $this->assertEquals( 'c/c4/', $this->file_lc->getHashPath() );
        }
 
-       function testGetRel() {
+       /**
+        * @covers File::getRel
+        */
+       public function testGetRel() {
                $this->assertEquals( 'Test!', $this->file_hl0->getRel() );
                $this->assertEquals( 'a/a2/Test!', $this->file_hl2->getRel() );
                $this->assertEquals( 'c/c4/test!', $this->file_lc->getRel() );
        }
 
-       function testGetUrlRel() {
+       /**
+        * @covers File::getUrlRel
+        */
+       public function testGetUrlRel() {
                $this->assertEquals( 'Test%21', $this->file_hl0->getUrlRel() );
                $this->assertEquals( 'a/a2/Test%21', $this->file_hl2->getUrlRel() );
                $this->assertEquals( 'c/c4/test%21', $this->file_lc->getUrlRel() );
        }
 
-       function testGetArchivePath() {
+       /**
+        * @covers File::getArchivePath
+        */
+       public function testGetArchivePath() {
                $this->assertEquals( 'mwstore://local-backend/test-public/archive', $this->file_hl0->getArchivePath() );
                $this->assertEquals( 'mwstore://local-backend/test-public/archive/a/a2', $this->file_hl2->getArchivePath() );
                $this->assertEquals( 'mwstore://local-backend/test-public/archive/!', $this->file_hl0->getArchivePath( '!' ) );
                $this->assertEquals( 'mwstore://local-backend/test-public/archive/a/a2/!', $this->file_hl2->getArchivePath( '!' ) );
        }
 
-       function testGetThumbPath() {
+       /**
+        * @covers File::getThumbPath
+        */
+       public function testGetThumbPath() {
                $this->assertEquals( 'mwstore://local-backend/test-thumb/Test!', $this->file_hl0->getThumbPath() );
                $this->assertEquals( 'mwstore://local-backend/test-thumb/a/a2/Test!', $this->file_hl2->getThumbPath() );
                $this->assertEquals( 'mwstore://local-backend/test-thumb/Test!/x', $this->file_hl0->getThumbPath( 'x' ) );
                $this->assertEquals( 'mwstore://local-backend/test-thumb/a/a2/Test!/x', $this->file_hl2->getThumbPath( 'x' ) );
        }
 
-       function testGetArchiveUrl() {
+       /**
+        * @covers File::getArchiveUrl
+        */
+       public function testGetArchiveUrl() {
                $this->assertEquals( '/testurl/archive', $this->file_hl0->getArchiveUrl() );
                $this->assertEquals( '/testurl/archive/a/a2', $this->file_hl2->getArchiveUrl() );
                $this->assertEquals( '/testurl/archive/%21', $this->file_hl0->getArchiveUrl( '!' ) );
                $this->assertEquals( '/testurl/archive/a/a2/%21', $this->file_hl2->getArchiveUrl( '!' ) );
        }
 
-       function testGetThumbUrl() {
+       /**
+        * @covers File::getThumbUrl
+        */
+       public function testGetThumbUrl() {
                $this->assertEquals( '/testurl/thumb/Test%21', $this->file_hl0->getThumbUrl() );
                $this->assertEquals( '/testurl/thumb/a/a2/Test%21', $this->file_hl2->getThumbUrl() );
                $this->assertEquals( '/testurl/thumb/Test%21/x', $this->file_hl0->getThumbUrl( 'x' ) );
                $this->assertEquals( '/testurl/thumb/a/a2/Test%21/x', $this->file_hl2->getThumbUrl( 'x' ) );
        }
 
-       function testGetArchiveVirtualUrl() {
+       /**
+        * @covers File::getArchiveVirtualUrl
+        */
+       public function testGetArchiveVirtualUrl() {
                $this->assertEquals( 'mwrepo://test/public/archive', $this->file_hl0->getArchiveVirtualUrl() );
                $this->assertEquals( 'mwrepo://test/public/archive/a/a2', $this->file_hl2->getArchiveVirtualUrl() );
                $this->assertEquals( 'mwrepo://test/public/archive/%21', $this->file_hl0->getArchiveVirtualUrl( '!' ) );
                $this->assertEquals( 'mwrepo://test/public/archive/a/a2/%21', $this->file_hl2->getArchiveVirtualUrl( '!' ) );
        }
 
-       function testGetThumbVirtualUrl() {
+       /**
+        * @covers File::getThumbVirtualUrl
+        */
+       public function testGetThumbVirtualUrl() {
                $this->assertEquals( 'mwrepo://test/thumb/Test%21', $this->file_hl0->getThumbVirtualUrl() );
                $this->assertEquals( 'mwrepo://test/thumb/a/a2/Test%21', $this->file_hl2->getThumbVirtualUrl() );
                $this->assertEquals( 'mwrepo://test/thumb/Test%21/%21', $this->file_hl0->getThumbVirtualUrl( '!' ) );
                $this->assertEquals( 'mwrepo://test/thumb/a/a2/Test%21/%21', $this->file_hl2->getThumbVirtualUrl( '!' ) );
        }
 
-       function testGetUrl() {
+       /**
+        * @covers File::getUrl
+        */
+       public function testGetUrl() {
                $this->assertEquals( '/testurl/Test%21', $this->file_hl0->getUrl() );
                $this->assertEquals( '/testurl/a/a2/Test%21', $this->file_hl2->getUrl() );
        }
 
-       function testWfLocalFile() {
+       /**
+        * @covers ::wfLocalFile
+        */
+       public function testWfLocalFile() {
                $file = wfLocalFile( "File:Some_file_that_probably_doesn't exist.png" );
                $this->assertThat( $file, $this->isInstanceOf( 'LocalFile' ), 'wfLocalFile() returns LocalFile for valid Titles' );
        }
index b34847a..f98410a 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @covers LocalisationCache
+ */
 class LocalisationCacheTest extends MediaWikiTestCase {
        public function testPuralRulesFallback() {
                $cache = Language::getLocalisationCache();
diff --git a/tests/phpunit/includes/MWExceptionHandlerTest.php b/tests/phpunit/includes/MWExceptionHandlerTest.php
new file mode 100644 (file)
index 0000000..dd76e3b
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Tests for includes/Exception.php.
+ *
+ * @author Antoine Musso
+ * @copyright Copyright © 2013, Antoine Musso
+ * @copyright Copyright © 2013, Wikimedia Foundation Inc.
+ * @file
+ */
+
+class MWExceptionHandlerTest extends MediaWikiTestCase {
+
+       /**
+        * @covers MWExceptionHandler::getRedactedTrace
+        */
+       function testGetRedactedTrace() {
+               $refvar = 'value';
+               try {
+                       $array = array( 'a', 'b' );
+                       $object = new StdClass();
+                       self::helperThrowAnException( $array, $object, $refvar );
+               } catch ( Exception $e ) {
+               }
+
+               # Make sure our strack trace contains an array and an object passed to
+               # some function in the stacktrace. Else, we can not assert the trace
+               # redaction achieved its job.
+               $trace = $e->getTrace();
+               $hasObject = false;
+               $hasArray = false;
+               foreach ( $trace as $frame ) {
+                       if ( ! isset( $frame['args'] ) ) {
+                               continue;
+                       }
+                       foreach ( $frame['args'] as $arg ) {
+                               $hasObject = $hasObject || is_object( $arg );
+                               $hasArray = $hasArray || is_array( $arg );
+                       }
+
+                       if ( $hasObject && $hasArray ) {
+                               break;
+                       }
+               }
+               $this->assertTrue( $hasObject,
+                       "The stacktrace must have a function having an object has parameter" );
+               $this->assertTrue( $hasArray,
+                       "The stacktrace must have a function having an array has parameter" );
+
+               # Now we redact the trace.. and make sure no function arguments are
+               # arrays or objects.
+               $redacted = MWExceptionHandler::getRedactedTrace( $e );
+
+               foreach ( $redacted as $frame ) {
+                       if ( ! isset( $frame['args'] ) ) {
+                               continue;
+                       }
+                       foreach ( $frame['args'] as $arg ) {
+                               $this->assertNotInternalType( 'array', $arg );
+                               $this->assertNotInternalType( 'object', $arg );
+                       }
+               }
+
+               $this->assertEquals( 'value', $refvar, 'Ensuring reference variable wasn\'t changed' );
+       }
+
+       /**
+        * Helper function for testExpandArgumentsInCall
+        *
+        * Pass it an object and an array, and something by reference :-)
+        *
+        * @throws Exception
+        */
+       protected static function helperThrowAnException( $a, $b, &$c ) {
+               throw new Exception();
+       }
+}
index a44f69e..f2a720e 100644 (file)
@@ -1,7 +1,10 @@
 <?php
 
+/**
+ * @covers MWFunction
+ */
 class MWFunctionTest extends MediaWikiTestCase {
-       function testNewObjFunction() {
+       public function testNewObjFunction() {
                $arg1 = 'Foo';
                $arg2 = 'Bar';
                $arg3 = array( 'Baz' );
index 10e9db6..b6fa139 100644 (file)
@@ -8,6 +8,8 @@
 /**
  * Test class for MWNamespace.
  * Generated by PHPUnit on 2011-02-20 at 21:01:55.
+ * @todo covers tags
+ * @FIXME this test file is a mess
  *
  */
 class MWNamespaceTest extends MediaWikiTestCase {
@@ -31,6 +33,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
 
        /**
         * @todo Write more texts, handle $wgAllowImageMoving setting
+        * @covers MWNamespace::isMovable
         */
        public function testIsMovable() {
                $this->assertFalse( MWNamespace::isMovable( NS_CATEGORY ) );
@@ -39,6 +42,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
 
        /**
         * Please make sure to change testIsTalk() if you change the assertions below
+        * @covers MWNamespace::isSubject
         */
        public function testIsSubject() {
                // Special namespaces
@@ -59,6 +63,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        /**
         * Reverse of testIsSubject().
         * Please update testIsSubject() if you change assertions below
+        * @covers MWNamespace::isTalk
         */
        public function testIsTalk() {
                // Special namespaces
@@ -77,6 +82,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
+        * @covers MWNamespace::getSubject
         */
        public function testGetSubject() {
                // Special namespaces are their own subjects
@@ -91,6 +97,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * Regular getTalk() calls
         * Namespaces without a talk page (NS_MEDIA, NS_SPECIAL) are tested in
         * the function testGetTalkExceptions()
+        * @covers MWNamespace::getTalk
         */
        public function testGetTalk() {
                $this->assertEquals( NS_TALK, MWNamespace::getTalk( NS_MAIN ) );
@@ -103,6 +110,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * Exceptions with getTalk()
         * NS_MEDIA does not have talk pages. MediaWiki raise an exception for them.
         * @expectedException MWException
+        * @covers MWNamespace::getTalk
         */
        public function testGetTalkExceptionsForNsMedia() {
                $this->assertNull( MWNamespace::getTalk( NS_MEDIA ) );
@@ -112,6 +120,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * Exceptions with getTalk()
         * NS_SPECIAL does not have talk pages. MediaWiki raise an exception for them.
         * @expectedException MWException
+        * @covers MWNamespace::getTalk
         */
        public function testGetTalkExceptionsForNsSpecial() {
                $this->assertNull( MWNamespace::getTalk( NS_SPECIAL ) );
@@ -121,6 +130,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * Regular getAssociated() calls
         * Namespaces without an associated page (NS_MEDIA, NS_SPECIAL) are tested in
         * the function testGetAssociatedExceptions()
+        * @covers MWNamespace::getAssociated
         */
        public function testGetAssociated() {
                $this->assertEquals( NS_TALK, MWNamespace::getAssociated( NS_MAIN ) );
@@ -132,6 +142,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        ### an exception for them.
        /**
         * @expectedException MWException
+        * @covers MWNamespace::getAssociated
         */
        public function testGetAssociatedExceptionsForNsMedia() {
                $this->assertNull( MWNamespace::getAssociated( NS_MEDIA ) );
@@ -139,6 +150,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
 
        /**
         * @expectedException MWException
+        * @covers MWNamespace::getAssociated
         */
        public function testGetAssociatedExceptionsForNsSpecial() {
                $this->assertNull( MWNamespace::getAssociated( NS_SPECIAL ) );
@@ -161,6 +173,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * Note if we add a namespace registration system with keys like 'MAIN'
         * we should add tests here for equivilance on things like 'MAIN' == 0
         * and 'MAIN' == NS_MAIN.
+        * @covers MWNamespace::equals
         */
        public function testEquals() {
                $this->assertTrue( MWNamespace::equals( NS_MAIN, NS_MAIN ) );
@@ -175,7 +188,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
-        * Test MWNamespace::subjectEquals
+        * @covers MWNamespace::subjectEquals
         */
        public function testSubjectEquals() {
                $this->assertSameSubject( NS_MAIN, NS_MAIN );
@@ -191,6 +204,9 @@ class MWNamespaceTest extends MediaWikiTestCase {
                $this->assertDifferentSubject( NS_SPECIAL, NS_MAIN );
        }
 
+       /**
+        * @covers MWNamespace::subjectEquals
+        */
        public function testSpecialAndMediaAreDifferentSubjects() {
                $this->assertDifferentSubject(
                        NS_MEDIA, NS_SPECIAL,
@@ -249,6 +265,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        */
 
        /**
+        * @covers MWNamespace::canTalk
         */
        public function testCanTalk() {
                $this->assertCanNotTalk( NS_MEDIA );
@@ -265,6 +282,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
+        * @covers MWNamespace::isContent
         */
        public function testIsContent() {
                // NS_MAIN is a content namespace per DefaultSettings.php
@@ -285,6 +303,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        /**
         * Similar to testIsContent() but alters the $wgContentNamespaces
         * global variable.
+        * @covers MWNamespace::isContent
         */
        public function testIsContentAdvanced() {
                global $wgContentNamespaces;
@@ -301,6 +320,9 @@ class MWNamespaceTest extends MediaWikiTestCase {
                $this->assertIsContent( NS_MAIN );
        }
 
+       /**
+        * @covers MWNamespace::isWatchable
+        */
        public function testIsWatchable() {
                // Specials namespaces are not watchable
                $this->assertIsNotWatchable( NS_MEDIA );
@@ -315,6 +337,9 @@ class MWNamespaceTest extends MediaWikiTestCase {
                $this->assertIsWatchable( 101 );
        }
 
+       /**
+        * @covers MWNamespace::hasSubpages
+        */
        public function testHasSubpages() {
                global $wgNamespacesWithSubpages;
 
@@ -338,6 +363,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
+        * @covers MWNamespace::getContentNamespaces
         */
        public function testGetContentNamespaces() {
                global $wgContentNamespaces;
@@ -388,6 +414,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
+        * @covers MWNamespace::getSubjectNamespaces
         */
        public function testGetSubjectNamespaces() {
                $subjectsNS = MWNamespace::getSubjectNamespaces();
@@ -403,6 +430,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        }
 
        /**
+        * @covers MWNamespace::getTalkNamespaces
         */
        public function testGetTalkNamespaces() {
                $talkNS = MWNamespace::getTalkNamespaces();
@@ -420,6 +448,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
        /**
         * Some namespaces are always capitalized per code definition
         * in MWNamespace::$alwaysCapitalizedNamespaces
+        * @covers MWNamespace::isCapitalized
         */
        public function testIsCapitalizedHardcodedAssertions() {
                // NS_MEDIA and NS_FILE are treated the same
@@ -451,6 +480,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         *
         * Global setting correctness is tested against the NS_PROJECT and
         * NS_PROJECT_TALK namespaces since they are not hardcoded nor specials
+        * @covers MWNamespace::isCapitalized
         */
        public function testIsCapitalizedWithWgCapitalLinks() {
                global $wgCapitalLinks;
@@ -475,6 +505,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         * testing the $wgCapitalLinkOverrides global.
         *
         * @todo split groups of assertions in autonomous testing functions
+        * @covers MWNamespace::isCapitalized
         */
        public function testIsCapitalizedWithWgCapitalLinkOverrides() {
                global $wgCapitalLinkOverrides;
@@ -507,6 +538,9 @@ class MWNamespaceTest extends MediaWikiTestCase {
                $this->assertIsCapitalized( NS_PROJECT );
        }
 
+       /**
+        * @covers MWNamespace::hasGenderDistinction
+        */
        public function testHasGenderDistinction() {
                // Namespaces with gender distinctions
                $this->assertTrue( MWNamespace::hasGenderDistinction( NS_USER ) );
@@ -519,6 +553,9 @@ class MWNamespaceTest extends MediaWikiTestCase {
                $this->assertFalse( MWNamespace::hasGenderDistinction( NS_TALK ) );
        }
 
+       /**
+        * @covers MWNamespace::isNonincludable
+        */
        public function testIsNonincludable() {
                global $wgNonincludableNamespaces;
 
index 1ba2d40..71ebd6a 100644 (file)
@@ -10,7 +10,10 @@ class MessageTest extends MediaWikiLangTestCase {
                ) );
        }
 
-       function testExists() {
+       /**
+        * @covers Message::exists
+        */
+       public function testExists() {
                $this->assertTrue( wfMessage( 'mainpage' )->exists() );
                $this->assertTrue( wfMessage( 'mainpage' )->params( array() )->exists() );
                $this->assertTrue( wfMessage( 'mainpage' )->rawParams( 'foo', 123 )->exists() );
@@ -19,7 +22,10 @@ class MessageTest extends MediaWikiLangTestCase {
                $this->assertFalse( wfMessage( 'i-dont-exist-evar' )->rawParams( 'foo', 123 )->exists() );
        }
 
-       function testKey() {
+       /**
+        * @covers Message::__construct
+        */
+       public function testKey() {
                $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
                $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->text() );
@@ -28,28 +34,42 @@ class MessageTest extends MediaWikiLangTestCase {
                $this->assertEquals( '&lt;i-dont-exist-evar&gt;', wfMessage( 'i-dont-exist-evar' )->escaped() );
        }
 
-       function testInLanguage() {
+       /**
+        * @covers Message::inLanguage
+        */
+       public function testInLanguage() {
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inLanguage( 'en' )->text() );
                $this->assertEquals( 'Заглавная страница', wfMessage( 'mainpage' )->inLanguage( 'ru' )->text() );
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inLanguage( Language::factory( 'en' ) )->text() );
                $this->assertEquals( 'Заглавная страница', wfMessage( 'mainpage' )->inLanguage( Language::factory( 'ru' ) )->text() );
        }
 
-       function testMessageParams() {
+       /**
+        * @covers Message::__construct
+        */
+       public function testMessageParams() {
                $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
                $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
                $this->assertEquals( 'You have foo (bar).', wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text() );
                $this->assertEquals( 'You have foo (bar).', wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text() );
        }
 
-       function testMessageParamSubstitution() {
+       /**
+        * @covers Message::__construct
+        * @covers Message::rawParams
+        */
+       public function testMessageParamSubstitution() {
                $this->assertEquals( '(Заглавная страница)', wfMessage( 'parentheses', 'Заглавная страница' )->plain() );
                $this->assertEquals( '(Заглавная страница $1)', wfMessage( 'parentheses', 'Заглавная страница $1' )->plain() );
                $this->assertEquals( '(Заглавная страница)', wfMessage( 'parentheses' )->rawParams( 'Заглавная страница' )->plain() );
                $this->assertEquals( '(Заглавная страница $1)', wfMessage( 'parentheses' )->rawParams( 'Заглавная страница $1' )->plain() );
        }
 
-       function testDeliciouslyManyParams() {
+       /**
+        * @covers Message::__construct
+        * @covers Message::params
+        */
+       public function testDeliciouslyManyParams() {
                $msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' );
                // One less than above has placeholders
                $params = array( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' );
@@ -59,8 +79,15 @@ class MessageTest extends MediaWikiLangTestCase {
        /**
         * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
         * @group Database
+        * @todo this should be split up into multiple test methods
+        * @covers Message::numParams
+        * @covers Message::durationParams
+        * @covers Message::expiryParams
+        * @covers Message::timeperiodParams
+        * @covers Message::sizeParams
+        * @covers Message::bitrateParams
         */
-       function testMessageParamTypes() {
+       public function testMessageParamTypes() {
                $lang = Language::factory( 'en' );
 
                $msg = new RawMessage( '$1' );
@@ -106,13 +133,19 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
-       function testInContentLanguageDisabled() {
+       /**
+        * @covers Message::inContentLanguage
+        */
+       public function testInContentLanguageDisabled() {
                $this->setMwGlobals( 'wgLang', Language::factory( 'fr' ) );
 
                $this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->inContentLanguage()->plain(), 'ForceUIMsg disabled' );
        }
 
-       function testInContentLanguageEnabled() {
+       /**
+        * @covers Message::inContentLanguage
+        */
+       public function testInContentLanguageEnabled() {
                $this->setMwGlobals( array(
                        'wgLang' => Language::factory( 'fr' ),
                        'wgForceUIMsgAsContentMsg' => array( 'mainpage' ),
@@ -123,8 +156,9 @@ class MessageTest extends MediaWikiLangTestCase {
 
        /**
         * @expectedException MWException
+        * @covers Message::inLanguage
         */
-       function testInLanguageThrows() {
+       public function testInLanguageThrows() {
                wfMessage( 'foo' )->inLanguage( 123 );
        }
 }
index 56bb0fc..385cee5 100644 (file)
@@ -6,6 +6,8 @@
  *
  * @group Output
  *
+ * @todo factor tests in this class into providers and test methods
+ *
  */
 class OutputPageTest extends MediaWikiTestCase {
        const SCREEN_MEDIA_QUERY = 'screen and (min-width: 982px)';
@@ -46,6 +48,7 @@ class OutputPageTest extends MediaWikiTestCase {
 
        /**
         * Tests print requests
+        * @covers OutputPage::transformCssMedia
         */
        public function testPrintRequests() {
                $this->assertTransformCssMediaCase( array(
@@ -79,6 +82,7 @@ class OutputPageTest extends MediaWikiTestCase {
 
        /**
         * Tests screen requests, without either query parameter set
+        * @covers OutputPage::transformCssMedia
         */
        public function testScreenRequests() {
                $this->assertTransformCssMediaCase( array(
@@ -114,6 +118,7 @@ class OutputPageTest extends MediaWikiTestCase {
 
        /**
         * Tests handheld behavior
+        * @covers OutputPage::transformCssMedia
         */
        public function testHandheld() {
                $this->assertTransformCssMediaCase( array(
index adfb215..e60dc54 100644 (file)
@@ -1,10 +1,10 @@
 <?php
+
 /**
  * Tests for the PathRouter parsing.
  *
- * @todo Add covers tags.
+ * @covers PathRouter
  */
-
 class PathRouterTest extends MediaWikiTestCase {
 
        /**
@@ -240,7 +240,6 @@ class PathRouterTest extends MediaWikiTestCase {
                $this->assertEquals( $matches, array( 'title' => "Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum." ) );
        }
 
-
        /**
         * Ensure that the php passed site of parameter values are not urldecoded
         */
index 3dec2da..5841bb6 100644 (file)
@@ -81,9 +81,9 @@ class PreferencesTest extends MediaWikiTestCase {
        protected function prefsFor( $user_key ) {
                $preferences = array();
                Preferences::profilePreferences(
-                       $this->prefUsers[$user_key]
-                       , $this->context
-                       $preferences
+                       $this->prefUsers[$user_key],
+                       $this->context,
+                       $preferences
                );
 
                return $preferences;
diff --git a/tests/phpunit/includes/RecentChangeTest.php b/tests/phpunit/includes/RecentChangeTest.php
deleted file mode 100644 (file)
index cfa3e77..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-<?php
-/**
- * @group Database
- */
-class RecentChangeTest extends MediaWikiTestCase {
-       protected $title;
-       protected $target;
-       protected $user;
-       protected $user_comment;
-       protected $context;
-
-       public function __construct() {
-               parent::__construct();
-
-               $this->title = Title::newFromText( 'SomeTitle' );
-               $this->target = Title::newFromText( 'TestTarget' );
-               $this->user = User::newFromName( 'UserName' );
-
-               $this->user_comment = '<User comment about action>';
-               $this->context = RequestContext::newExtraneousContext( $this->title );
-       }
-
-       /**
-        * The testIrcMsgForAction* tests are supposed to cover the hacky
-        * LogFormatter::getIRCActionText / bug 34508
-        *
-        * Third parties bots listen to those messages. They are clever enough
-        * to fetch the i18n messages from the wiki and then analyze the IRC feed
-        * to reverse engineer the $1, $2 messages.
-        * One thing bots can not detect is when MediaWiki change the meaning of
-        * a message like what happened when we deployed 1.19. $1 became the user
-        * performing the action which broke basically all bots around.
-        *
-        * Should cover the following log actions (which are most commonly used by bots):
-        * - block/block
-        * - block/unblock
-        * - delete/delete
-        * - delete/restore
-        * - newusers/create
-        * - newusers/create2
-        * - newusers/autocreate
-        * - move/move
-        * - move/move_redir
-        * - protect/protect
-        * - protect/modifyprotect
-        * - protect/unprotect
-        * - upload/upload
-        *
-        * As well as the following Auto Edit Summaries:
-        * - blank
-        * - replace
-        * - rollback
-        * - undo
-        */
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeBlock() {
-               $sep = $this->context->msg( 'colon-separator' )->text();
-
-               # block/block
-               $this->assertIRCComment(
-                       $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'block', 'block',
-                       array(),
-                       $this->user_comment
-               );
-               # block/unblock
-               $this->assertIRCComment(
-                       $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'block', 'unblock',
-                       array(),
-                       $this->user_comment
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeDelete() {
-               $sep = $this->context->msg( 'colon-separator' )->text();
-
-               # delete/delete
-               $this->assertIRCComment(
-                       $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'delete', 'delete',
-                       array(),
-                       $this->user_comment
-               );
-
-               # delete/restore
-               $this->assertIRCComment(
-                       $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'delete', 'restore',
-                       array(),
-                       $this->user_comment
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeNewusers() {
-               $this->assertIRCComment(
-                       'New user account',
-                       'newusers', 'newusers',
-                       array()
-               );
-               $this->assertIRCComment(
-                       'New user account',
-                       'newusers', 'create',
-                       array()
-               );
-               $this->assertIRCComment(
-                       'created new account SomeTitle',
-                       'newusers', 'create2',
-                       array()
-               );
-               $this->assertIRCComment(
-                       'Account created automatically',
-                       'newusers', 'autocreate',
-                       array()
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeMove() {
-               $move_params = array(
-                       '4::target' => $this->target->getPrefixedText(),
-                       '5::noredir' => 0,
-               );
-               $sep = $this->context->msg( 'colon-separator' )->text();
-
-               # move/move
-               $this->assertIRCComment(
-                       $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
-                       'move', 'move',
-                       $move_params,
-                       $this->user_comment
-               );
-
-               # move/move_redir
-               $this->assertIRCComment(
-                       $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
-                       'move', 'move_redir',
-                       $move_params,
-                       $this->user_comment
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypePatrol() {
-               # patrol/patrol
-               $this->assertIRCComment(
-                       $this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(),
-                       'patrol', 'patrol',
-                       array(
-                               '4::curid' => '777',
-                               '5::previd' => '666',
-                               '6::auto' => 0,
-                       )
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeProtect() {
-               $protectParams = array(
-                       '[edit=sysop] (indefinite) ‎[move=sysop] (indefinite)'
-               );
-               $sep = $this->context->msg( 'colon-separator' )->text();
-
-               # protect/protect
-               $this->assertIRCComment(
-                       $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
-                       'protect', 'protect',
-                       $protectParams,
-                       $this->user_comment
-               );
-
-               # protect/unprotect
-               $this->assertIRCComment(
-                       $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'protect', 'unprotect',
-                       array(),
-                       $this->user_comment
-               );
-
-               # protect/modify
-               $this->assertIRCComment(
-                       $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
-                       'protect', 'modify',
-                       $protectParams,
-                       $this->user_comment
-               );
-       }
-
-       /**
-        * @covers LogFormatter::getIRCActionText
-        */
-       public function testIrcMsgForLogTypeUpload() {
-               $sep = $this->context->msg( 'colon-separator' )->text();
-
-               # upload/upload
-               $this->assertIRCComment(
-                       $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'upload', 'upload',
-                       array(),
-                       $this->user_comment
-               );
-
-               # upload/overwrite
-               $this->assertIRCComment(
-                       $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
-                       'upload', 'overwrite',
-                       array(),
-                       $this->user_comment
-               );
-       }
-
-       /**
-        * @todo Emulate these edits somehow and extract
-        * raw edit summary from RecentChange object
-        * --
-        */
-       /*
-       public function testIrcMsgForBlankingAES() {
-               // $this->context->msg( 'autosumm-blank', .. );
-       }
-
-       public function testIrcMsgForReplaceAES() {
-               // $this->context->msg( 'autosumm-replace', .. );
-       }
-
-       public function testIrcMsgForRollbackAES() {
-               // $this->context->msg( 'revertpage', .. );
-       }
-
-       public function testIrcMsgForUndoAES() {
-               // $this->context->msg( 'undo-summary', .. );
-       }
-       */
-
-       /**
-        * @param $expected String Expected IRC text without colors codes
-        * @param $type String Log type (move, delete, suppress, patrol ...)
-        * @param $action String A log type action
-        * @param $params
-        * @param $comment String (optional) A comment for the log action
-        * @param $msg String (optional) A message for PHPUnit :-)
-        */
-       protected function assertIRCComment( $expected, $type, $action, $params, $comment = null, $msg = '' ) {
-
-               $logEntry = new ManualLogEntry( $type, $action );
-               $logEntry->setPerformer( $this->user );
-               $logEntry->setTarget( $this->title );
-               if ( $comment !== null ) {
-                       $logEntry->setComment( $comment );
-               }
-               $logEntry->setParameters( $params );
-
-               $formatter = LogFormatter::newFromEntry( $logEntry );
-               $formatter->setContext( $this->context );
-
-               // Apply the same transformation as done in IRCColourfulRCFeedFormatter::getLine for rc_comment
-               $ircRcComment = IRCColourfulRCFeedFormatter::cleanupForIRC( $formatter->getIRCActionComment() );
-
-               $this->assertEquals(
-                       $expected,
-                       $ircRcComment,
-                       $msg
-               );
-       }
-}
diff --git a/tests/phpunit/includes/ResourceLoaderModuleTest.php b/tests/phpunit/includes/ResourceLoaderModuleTest.php
new file mode 100644 (file)
index 0000000..4643319
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+
+class ResourceLoaderModuleTest extends MediaWikiTestCase {
+
+       protected static function getResourceLoaderContext() {
+               $resourceLoader = new ResourceLoader();
+               $request = new FauxRequest( array(
+                               'debug' => 'false',
+                               'lang' => 'en',
+                               'modules' => 'startup',
+                               'only' => 'scripts',
+                               'skin' => 'vector',
+               ) );
+               return new ResourceLoaderContext( $resourceLoader, $request );
+       }
+
+       /**
+        * @covers ResourceLoaderModule::getDefinitionSummary
+        * @covers ResourceLoaderFileModule::getDefinitionSummary
+        */
+       public function testDefinitionSummary() {
+               $context = self::getResourceLoaderContext();
+
+               $baseParams = array(
+                       'scripts' => array( 'foo.js', 'bar.js' ),
+                       'dependencies' => array( 'jquery', 'mediawiki' ),
+                       'messages' => array( 'hello', 'world' ),
+               );
+
+               $module = new ResourceLoaderFileModule( $baseParams );
+
+               $jsonSummary = json_encode( $module->getDefinitionSummary( $context ) );
+
+               // Exactly the same
+               $module = new ResourceLoaderFileModule( $baseParams );
+
+               $this->assertEquals(
+                       $jsonSummary,
+                       json_encode( $module->getDefinitionSummary( $context ) ),
+                       'Instance is insignificant'
+               );
+
+               // Re-order dependencies
+               $module = new ResourceLoaderFileModule( array(
+                       'dependencies' => array( 'mediawiki', 'jquery' ),
+               ) + $baseParams );
+
+               $this->assertEquals(
+                       $jsonSummary,
+                       json_encode( $module->getDefinitionSummary( $context ) ),
+                       'Order of dependencies is insignificant'
+               );
+
+               // Re-order messages
+               $module = new ResourceLoaderFileModule( array(
+                       'messages' => array( 'world', 'hello' ),
+               ) + $baseParams );
+
+               $this->assertEquals(
+                       $jsonSummary,
+                       json_encode( $module->getDefinitionSummary( $context ) ),
+                       'Order of messages is insignificant'
+               );
+
+               // Re-order scripts
+               $module = new ResourceLoaderFileModule( array(
+                       'scripts' => array( 'bar.js', 'foo.js' ),
+               ) + $baseParams );
+
+               $this->assertNotEquals(
+                       $jsonSummary,
+                       json_encode( $module->getDefinitionSummary( $context ) ),
+                       'Order of scripts is significant'
+               );
+
+               // Subclass
+               $module = new ResourceLoaderFileModuleTestModule( $baseParams );
+
+               $this->assertNotEquals(
+                       $jsonSummary,
+                       json_encode( $module->getDefinitionSummary( $context ) ),
+                       'Class is significant'
+               );
+       }
+}
+
+class ResourceLoaderFileModuleTestModule extends ResourceLoaderFileModule {}
index e17c7b0..7e275a5 100644 (file)
@@ -56,7 +56,7 @@ class RevisionStorageTest extends MediaWikiTestCase {
                }
        }
 
-       public function tearDown() {
+       protected function tearDown() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
 
                parent::tearDown();
@@ -170,7 +170,6 @@ class RevisionStorageTest extends MediaWikiTestCase {
                $this->assertRevEquals( $orig, $rev );
        }
 
-
        /**
         * @covers Revision::newFromArchiveRow
         */
index 4e83e35..f830e36 100644 (file)
@@ -57,7 +57,6 @@ class RevisionTest_ContentHandlerUseDB extends RevisionStorageTest {
                }
        }
 
-
        /**
         * @covers Revision::getContentFormat
         */
index b5819ff..fc23919 100644 (file)
@@ -325,7 +325,6 @@ class RevisionTest extends MediaWikiTestCase {
                $this->assertEquals( $expectedText, $rev->getRawText( $audience ) );
        }
 
-
        public function dataGetSize() {
                return array(
                        array( "hello world.", CONTENT_MODEL_WIKITEXT, 12 ),
@@ -428,7 +427,6 @@ class RevisionTest extends MediaWikiTestCase {
                $this->assertEquals( "bar", $content->getText() ); // clones should be independent
        }
 
-
        /**
         * Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
         *
index 8a88191..8516a4c 100644 (file)
@@ -33,7 +33,7 @@ class TestSample extends MediaWikiLangTestCase {
         * "Agile Documentation" at
         * http://www.phpunit.de/manual/3.4/en/other-uses-for-tests.html
         */
-       function testTitleObjectStringConversion() {
+       public function testTitleObjectStringConversion() {
                $title = Title::newFromText( "text" );
                $this->assertInstanceOf( 'Title', $title, "Title creation" );
                $this->assertEquals( "Text", $title, "Automatic string conversion" );
@@ -98,7 +98,7 @@ class TestSample extends MediaWikiLangTestCase {
         * @expectedException MWException object
         * See http://www.phpunit.de/manual/3.4/en/appendixes.annotations.html#appendixes.annotations.expectedException
         */
-       function testTitleObjectFromObject() {
+       public function testTitleObjectFromObject() {
                $title = Title::newFromText( Title::newFromText( "test" ) );
                $this->assertEquals( "Test", $title->isLocal() );
        }
index 81246d3..97abf80 100644 (file)
@@ -235,7 +235,7 @@ class SanitizerTest extends MediaWikiTestCase {
                        array( 'align="left"', 'tr' ),
                        array( 'align="center"', 'div' ),
                        array( 'align="left"', 'h1' ),
-                       array( 'align="left"', 'span' ),
+                       array( 'align="left"', 'p' ),
                );
        }
 
diff --git a/tests/phpunit/includes/SpecialPageTest.php b/tests/phpunit/includes/SpecialPageTest.php
new file mode 100644 (file)
index 0000000..65057a5
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @covers SpecialPage
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class SpecialPageTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgScript' => '/index.php',
+                       'wgContLang' => Language::factory( 'en' )
+               ) );
+       }
+
+       /**
+        * @dataProvider getTitleForProvider
+        */
+       public function testGetTitleFor( $expectedName, $name ) {
+               $title = SpecialPage::getTitleFor( $name );
+               $expected = Title::makeTitle( NS_SPECIAL, $expectedName );
+               $this->assertEquals( $expected, $title );
+       }
+
+       public function getTitleForProvider() {
+               return array(
+                       array( 'UserLogin', 'Userlogin' )
+               );
+       }
+
+       /**
+        * @expectedException PHPUnit_Framework_Error_Notice
+        */
+       public function testInvalidGetTitleFor() {
+               $title = SpecialPage::getTitleFor( 'cat' );
+               $expected = Title::makeTitle( NS_SPECIAL, 'Cat' );
+               $this->assertEquals( $expected, $title );
+       }
+
+       /**
+        * @expectedException PHPUnit_Framework_Error_Notice
+        * @dataProvider getTitleForWithWarningProvider
+        */
+       public function testGetTitleForWithWarning( $expected, $name ) {
+               $title = SpecialPage::getTitleFor( $name );
+               $this->assertEquals( $expected, $title );
+       }
+
+       public function getTitleForWithWarningProvider() {
+               return array(
+                       array( Title::makeTitle( NS_SPECIAL, 'UserLogin' ), 'UserLogin' )
+               );
+       }
+
+       /**
+        * @dataProvider requireLoginAnonProvider
+        */
+       public function testRequireLoginAnon( $expected, $reason, $title ) {
+               $specialPage = new SpecialPage( 'Watchlist', 'viewmywatchlist' );
+
+               $user = User::newFromId( 0 );
+               $specialPage->getContext()->setUser( $user );
+               $specialPage->getContext()->setLanguage( Language::factory( 'en' ) );
+
+               $this->setExpectedException( 'UserNotLoggedIn', $expected );
+
+               if ( $reason === 'blank' && $title === 'blank' ) {
+                       $specialPage->requireLogin();
+               } else {
+                       $specialPage->requireLogin( $reason, $title );
+               }
+       }
+
+       public function requireLoginAnonProvider() {
+               $lang = 'en';
+
+               $msg = wfMessage( 'loginreqlink' )->inLanguage( $lang )->escaped();
+               $loginLink = '<a href="/index.php?title=Special:UserLogin&amp;returnto=Special%3AWatchlist"'
+                       . ' title="Special:UserLogin">' . $msg . '</a>';
+
+               $expected1 = wfMessage( 'exception-nologin-text-manual' )
+                       ->params( $loginLink )->inLanguage( $lang )->text();
+
+               $expected2 = wfMessage( 'about' )->inLanguage( $lang )->text();
+
+               return array(
+                       array( $expected1, null, null ),
+                       array( $expected2, 'about', null ),
+                       array( $expected2, wfMessage( 'about' ), null ),
+                       array( $expected2, 'about', 'about' ),
+                       array( $expected2, 'about', wfMessage( 'about' ) ),
+                       array( $expected1, 'blank', 'blank' )
+               );
+       }
+
+       public function testRequireLoginNotAnon() {
+               $specialPage = new SpecialPage( 'Watchlist', 'viewmywatchlist' );
+
+               $user = User::newFromId( 0 );
+               $user->setId( 1 );
+               $specialPage->getContext()->setUser( $user );
+
+               $specialPage->requireLogin();
+
+               // no exception thrown, logged in use can access special page
+               $this->assertTrue( true );
+       }
+
+}
diff --git a/tests/phpunit/includes/StatusTest.php b/tests/phpunit/includes/StatusTest.php
new file mode 100644 (file)
index 0000000..30a554e
--- /dev/null
@@ -0,0 +1,475 @@
+<?php
+
+/**
+ * @author Adam Shorland
+ */
+class StatusTest extends MediaWikiLangTestCase {
+
+       public function testCanConstruct() {
+               new Status();
+               $this->assertTrue( true );
+       }
+
+       /**
+        * @dataProvider provideValues
+        * @covers Status::newGood
+        */
+       public function testNewGood( $value = null ) {
+               $status = Status::newGood( $value );
+               $this->assertTrue( $status->isGood() );
+               $this->assertTrue( $status->isOK() );
+               $this->assertEquals( $value, $status->getValue() );
+       }
+
+       public static function provideValues() {
+               return array(
+                       array(),
+                       array( 'foo' ),
+                       array( array( 'foo' => 'bar' ) ),
+                       array( new Exception() ),
+                       array( 1234 ),
+               );
+       }
+
+       /**
+        * @covers Status::newFatal
+        */
+       public function testNewFatalWithMessage() {
+               $message = $this->getMockBuilder( 'Message' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+
+               $status = Status::newFatal( $message );
+               $this->assertFalse( $status->isGood() );
+               $this->assertFalse( $status->isOK() );
+               $this->assertEquals( $message, $status->getMessage() );
+       }
+
+       /**
+        * @covers Status::newFatal
+        */
+       public function testNewFatalWithString() {
+               $message = 'foo';
+               $status = Status::newFatal( $message );
+               $this->assertFalse( $status->isGood() );
+               $this->assertFalse( $status->isOK() );
+               $this->assertEquals( $message, $status->getMessage()->getKey() );
+       }
+
+       /**
+        * @dataProvider provideSetResult
+        * @covers Status::setResult
+        */
+       public function testSetResult( $ok, $value = null ) {
+               $status = new Status();
+               $status->setResult( $ok, $value );
+               $this->assertEquals( $ok, $status->isOK() );
+               $this->assertEquals( $value, $status->getValue() );
+       }
+
+       public static function provideSetResult() {
+               return array(
+                       array( true ),
+                       array( false ),
+                       array( true, 'value' ),
+                       array( false, 'value' ),
+               );
+       }
+
+       /**
+        * @dataProvider provideIsOk
+        * @covers Status::isOk
+        */
+       public function testIsOk( $ok ) {
+               $status = new Status();
+               $status->ok = $ok;
+               $this->assertEquals( $ok, $status->isOK() );
+       }
+
+       public static function provideIsOk() {
+               return array(
+                       array( true ),
+                       array( false ),
+               );
+       }
+
+       /**
+        * @covers Status::getValue
+        */
+       public function testGetValue() {
+               $status = new Status();
+               $status->value = 'foobar';
+               $this->assertEquals( 'foobar', $status->getValue() );
+       }
+
+       /**
+        * @dataProvider provideIsGood
+        * @covers Status::isGood
+        */
+       public function testIsGood( $ok, $errors, $expected ) {
+               $status = new Status();
+               $status->ok = $ok;
+               $status->errors = $errors;
+               $this->assertEquals( $expected, $status->isGood() );
+       }
+
+       public static function provideIsGood() {
+               return array(
+                       array( true, array(), true ),
+                       array( true, array( 'foo' ), false ),
+                       array( false, array(), false ),
+                       array( false, array( 'foo' ), false ),
+               );
+       }
+
+       /**
+        * @dataProvider provideMockMessageDetails
+        * @covers Status::warning
+        * @covers Status::getWarningsArray
+        * @covers Status::getStatusArray
+        */
+       public function testWarningWithMessage( $mockDetails ) {
+               $status = new Status();
+               $messages = $this->getMockMessages( $mockDetails );
+
+               foreach ( $messages as $message ) {
+                       $status->warning( $message );
+               }
+               $warnings = $status->getWarningsArray();
+
+               $this->assertEquals( count( $messages ), count( $warnings ) );
+               foreach ( $messages as $key => $message ) {
+                       $expectedArray = array_merge( array( $message->getKey() ), $message->getParams() );
+                       $this->assertEquals( $warnings[$key], $expectedArray );
+               }
+       }
+
+       /**
+        * @dataProvider provideMockMessageDetails
+        * @covers Status::error
+        * @covers Status::getErrorsArray
+        * @covers Status::getStatusArray
+        */
+       public function testErrorWithMessage( $mockDetails ) {
+               $status = new Status();
+               $messages = $this->getMockMessages( $mockDetails );
+
+               foreach ( $messages as $message ) {
+                       $status->error( $message );
+               }
+               $errors = $status->getErrorsArray();
+
+               $this->assertEquals( count( $messages ), count( $errors ) );
+               foreach ( $messages as $key => $message ) {
+                       $expectedArray = array_merge( array( $message->getKey() ), $message->getParams() );
+                       $this->assertEquals( $errors[$key], $expectedArray );
+               }
+       }
+
+       protected function getMockMessage( $key = 'key', $params = array() ) {
+               $message = $this->getMockBuilder( 'Message' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $message->expects( $this->atLeastOnce() )
+                       ->method( 'getKey' )
+                       ->will( $this->returnValue( $key ) );
+               $message->expects( $this->atLeastOnce() )
+                       ->method( 'getParams' )
+                       ->will( $this->returnValue( $params ) );
+               return $message;
+       }
+
+       /**
+        * @param array $messageDetails eg. array( 'KEY' => array(/PARAMS/) )
+        * @return Message[]
+        */
+       protected function getMockMessages( $messageDetails ) {
+               $messages = array();
+               foreach ( $messageDetails as $key => $paramsArray ) {
+                       $messages[] = $this->getMockMessage( $key, $paramsArray );
+               }
+               return $messages;
+       }
+
+       public static function provideMockMessageDetails() {
+               return array(
+                       array( array( 'key1' => array( 'foo' => 'bar' ) ) ),
+                       array( array( 'key1' => array( 'foo' => 'bar' ), 'key2' => array( 'foo2' => 'bar2' ) ) ),
+               );
+       }
+
+       /**
+        * @covers Status::merge
+        * @todo test merge with $overwriteValue true
+        */
+       public function testMerge() {
+               $status1 = new Status();
+               $status2 = new Status();
+               $message1 = $this->getMockMessage( 'warn1' );
+               $message2 = $this->getMockMessage( 'error2' );
+               $status1->warning( $message1 );
+               $status2->error( $message2 );
+
+               $status1->merge( $status2 );
+               $this->assertEquals( 2, count( $status1->getWarningsArray() ) + count( $status1->getErrorsArray() ) );
+       }
+
+       /**
+        * @covers Status::hasMessage
+        */
+       public function testHasMessage() {
+               $status = new Status();
+               $status->fatal( 'bad' );
+               $this->assertTrue( $status->hasMessage( 'bad' ) );
+               $this->assertFalse( $status->hasMessage( 'good' ) );
+       }
+
+       /**
+        * @dataProvider provideCleanParams
+        * @covers Status::cleanParams
+        */
+       public function testCleanParams( $cleanCallback, $params, $expected ) {
+               $method = new ReflectionMethod( 'Status', 'cleanParams' );
+               $method->setAccessible( true );
+               $status = new Status();
+               $status->cleanCallback = $cleanCallback;
+
+               $this->assertEquals( $expected, $method->invoke( $status, $params ) );
+       }
+
+       /**
+        * @todo test cleanParams with a callback
+        */
+       public static function provideCleanParams() {
+               return array(
+                       array( false, array( 'foo' => 'bar' ), array( 'foo' => 'bar' ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetWikiTextAndHtml
+        * @covers Status::getWikiText
+        * @todo test long and short context messages generated through this method
+        *       this can not really be done now due to use of wfMessage()->plain()
+        *       It is possible to mock such methods but only if namespaces are used
+        */
+       public function testGetWikiText( Status $status, $expected ) {
+               $this->assertEquals( $expected, $status->getWikiText() );
+       }
+
+       /**
+        * @dataProvider provideGetWikiTextAndHtml
+        * @covers Status::getHtml
+        * @todo test long and short context messages generated through this method
+        *       this can not really be done now due to use of $this->getWikiText using wfMessage()->plain()
+        *       It is possible to mock such methods but only if namespaces are used
+        */
+       public function testGetHtml( Status $status, $expected ) {
+               $this->assertEquals( $expected, $status->getHTML() );
+       }
+
+       /**
+        * @return array of arrays with values;
+        *    0 => status object
+        *    1 => expected string (with no context)
+        */
+       public static function provideGetWikiTextAndHtml() {
+               $testCases = array();
+
+               $testCases[ 'GoodStatus' ] = array(
+                       new Status(),
+                       "Internal error: Status::getWikiText called for a good result, this is incorrect\n",
+               );
+
+               $status = new Status();
+               $status->ok = false;
+               $testCases[ 'GoodButNoError' ] = array(
+                       $status,
+                       "Internal error: Status::getWikiText: Invalid result object: no error text but not OK\n",
+               );
+
+               $status = new Status();
+               $status->warning( 'fooBar!' );
+               $testCases[ '1StringWarning' ] = array(
+                       $status,
+                       "<fooBar!>",
+               );
+
+               $status = new Status();
+               $status->warning( 'fooBar!' );
+               $status->warning( 'fooBar2!' );
+               $testCases[ '2StringWarnings' ] = array(
+                       $status,
+                       "* <fooBar!>\n* <fooBar2!>\n",
+               );
+
+               $status = new Status();
+               $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
+               $testCases[ '1MessageWarning' ] = array(
+                       $status,
+                       "<fooBar!>",
+               );
+
+               $status = new Status();
+               $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
+               $status->warning( new Message( 'fooBar2!' ) );
+               $testCases[ '2MessageWarnings' ] = array(
+                       $status,
+                       "* <fooBar!>\n* <fooBar2!>\n",
+               );
+
+               return $testCases;
+       }
+
+       /**
+        * @dataProvider provideGetMessage
+        * @covers Status::getMessage
+        * @todo test long and short context messages generated through this method
+        */
+       public function testGetMessage( Status $status, $expectedParams = array(), $expectedKey ) {
+               $message = $status->getMessage();
+               $this->assertInstanceOf( 'Message', $message );
+               $this->assertEquals( $expectedParams, $message->getParams() );
+               $this->assertEquals( $expectedKey, $message->getKey() );
+       }
+
+       /**
+        * @return array of arrays with values;
+        *    0 => status object
+        *    1 => expected Message Params (with no context)
+        */
+       public static function provideGetMessage() {
+               $testCases = array();
+
+               $testCases[ 'GoodStatus' ] = array(
+                       new Status(),
+                       array( "Status::getMessage called for a good result, this is incorrect\n" ),
+                       'internalerror_info'
+               );
+
+               $status = new Status();
+               $status->ok = false;
+               $testCases[ 'GoodButNoError' ] = array(
+                       $status,
+                       array( "Status::getMessage: Invalid result object: no error text but not OK\n" ),
+                       'internalerror_info'
+               );
+
+               $status = new Status();
+               $status->warning( 'fooBar!' );
+               $testCases[ '1StringWarning' ] = array(
+                       $status,
+                       array(),
+                       "fooBar!"
+               );
+
+               //NOTE: this seems to return a string instead of a Message object...
+//             $status = new Status();
+//             $status->warning( 'fooBar!' );
+//             $status->warning( 'fooBar2!' );
+//             $testCases[ '2StringWarnings' ] = array(
+//                     $status,
+//                     array(),
+//                     ''
+//             );
+
+               $status = new Status();
+               $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
+               $testCases[ '1MessageWarning' ] = array(
+                       $status,
+                       array( 'foo', 'bar' ),
+                       "fooBar!",
+               );
+
+               //NOTE: this seems to return a string instead of a Message object...
+//             $status = new Status();
+//             $status->warning( new Message( 'fooBar!', array( 'foo', 'bar' ) ) );
+//             $status->warning( new Message( 'fooBar2!' ) );
+//             $testCases[ '2MessageWarnings' ] = array(
+//                     $status,
+//                     array(),
+//                     "",
+//             );
+
+               return $testCases;
+       }
+
+       /**
+        * @covers Status::replaceMessage
+        */
+       public function testReplaceMessage() {
+               $status = new Status();
+               $message = new Message( 'key1', array( 'foo1', 'bar1' ) );
+               $status->error( $message );
+               $newMessage = new Message( 'key2', array( 'foo2', 'bar2' ) );
+
+               $status->replaceMessage( $message, $newMessage );
+
+               $this->assertEquals( $newMessage, $status->errors[0]['message'] );
+       }
+
+       /**
+        * @covers Status::getErrorMessage
+        */
+       public function testGetErrorMessage() {
+               $method = new ReflectionMethod( 'Status', 'getErrorMessage' );
+               $method->setAccessible( true );
+               $status = new Status();
+               $key = 'foo';
+               $params = array( 'bar' );
+
+               /** @var Message $message */
+               $message = $method->invoke( $status, array_merge( array( $key ), $params ) );
+               $this->assertInstanceOf( 'Message', $message );
+               $this->assertEquals( $key, $message->getKey() );
+               $this->assertEquals( $params, $message->getParams() );
+       }
+
+       /**
+        * @covers Status::getErrorMessageArray
+        */
+       public function testGetErrorMessageArray() {
+               $method = new ReflectionMethod( 'Status', 'getErrorMessageArray' );
+               $method->setAccessible( true );
+               $status = new Status();
+               $key = 'foo';
+               $params = array( 'bar' );
+
+               /** @var Message[] $messageArray */
+               $messageArray = $method->invoke(
+                       $status,
+                       array(
+                               array_merge( array( $key ), $params ),
+                               array_merge( array( $key ), $params )
+                       )
+               );
+
+               $this->assertInternalType( 'array', $messageArray );
+               $this->assertCount( 2, $messageArray );
+               foreach ( $messageArray as $message ) {
+                       $this->assertInstanceOf( 'Message', $message );
+                       $this->assertEquals( $key, $message->getKey() );
+                       $this->assertEquals( $params, $message->getParams() );
+               }
+       }
+
+       /**
+        * @covers Status::getErrorsByType
+        */
+       public function testGetErrorsByType() {
+               $status = new Status();
+               $warning = new Message( 'warning111' );
+               $error = new Message( 'error111' );
+               $status->warning( $warning );
+               $status->error( $error );
+
+               $warnings = $status->getErrorsByType( 'warning' );
+               $errors = $status->getErrorsByType( 'error' );
+
+               $this->assertCount( 1, $warnings );
+               $this->assertCount( 1, $errors );
+               $this->assertEquals( $warning, $warnings[0]['message'] );
+               $this->assertEquals( $error, $errors[0]['message'] );
+       }
+
+}
diff --git a/tests/phpunit/includes/StringUtilsTest.php b/tests/phpunit/includes/StringUtilsTest.php
deleted file mode 100644 (file)
index b222812..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-
-class StringUtilsTest extends MediaWikiTestCase {
-
-       /**
-        * This tests StringUtils::isUtf8 whenever we have the mbstring extension
-        * loaded.
-        *
-        * @covers StringUtils::isUtf8
-        * @dataProvider provideStringsForIsUtf8Check
-        */
-       function testIsUtf8WithMbstring( $expected, $string ) {
-               if ( !function_exists( 'mb_check_encoding' ) ) {
-                       $this->markTestSkipped( 'Test requires the mbstring PHP extension' );
-               }
-               $this->assertEquals( $expected,
-                       StringUtils::isUtf8( $string ),
-                       'Testing string "' . $this->escaped( $string ) . '" with mb_check_encoding'
-               );
-       }
-
-       /**
-        * This tests StringUtils::isUtf8 making sure we use the pure PHP
-        * implementation used as a fallback when mb_check_encoding() is
-        * not available.
-        *
-        * @covers StringUtils::isUtf8
-        * @dataProvider provideStringsForIsUtf8Check
-        */
-       function testIsUtf8WithPhpFallbackImplementation( $expected, $string ) {
-               $this->assertEquals( $expected,
-                       StringUtils::isUtf8( $string, /** disable mbstring: */true ),
-                       'Testing string "' . $this->escaped( $string ) . '" with pure PHP implementation'
-               );
-       }
-
-       /**
-        * Print high range characters as an hexadecimal
-        */
-       function escaped( $string ) {
-               $escaped = '';
-               $length = strlen( $string );
-               for ( $i = 0; $i < $length; $i++ ) {
-                       $char = $string[$i];
-                       $val = ord( $char );
-                       if ( $val > 127 ) {
-                               $escaped .= '\x' . dechex( $val );
-                       } else {
-                               $escaped .= $char;
-                       }
-               }
-
-               return $escaped;
-       }
-
-       /**
-        * See also "UTF-8 decoder capability and stress test" by
-        * Markus Kuhn:
-        * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
-        */
-       public static function provideStringsForIsUtf8Check() {
-               // Expected return values for StringUtils::isUtf8()
-               $PASS = true;
-               $FAIL = false;
-
-               return array(
-                       'some ASCII' => array( $PASS, 'Some ASCII' ),
-                       'euro sign' => array( $PASS, "Euro sign €" ),
-
-                       'first possible sequence 1 byte' => array( $PASS, "\x00" ),
-                       'first possible sequence 2 bytes' => array( $PASS, "\xc2\x80" ),
-                       'first possible sequence 3 bytes' => array( $PASS, "\xe0\xa0\x80" ),
-                       'first possible sequence 4 bytes' => array( $PASS, "\xf0\x90\x80\x80" ),
-                       'first possible sequence 5 bytes' => array( $FAIL, "\xf8\x88\x80\x80\x80" ),
-                       'first possible sequence 6 bytes' => array( $FAIL, "\xfc\x84\x80\x80\x80\x80" ),
-
-                       'last possible sequence 1 byte' => array( $PASS, "\x7f" ),
-                       'last possible sequence 2 bytes' => array( $PASS, "\xdf\xbf" ),
-                       'last possible sequence 3 bytes' => array( $PASS, "\xef\xbf\xbf" ),
-                       'last possible sequence 4 bytes (U+1FFFFF)' => array( $FAIL, "\xf7\xbf\xbf\xbf" ),
-                       'last possible sequence 5 bytes' => array( $FAIL, "\xfb\xbf\xbf\xbf\xbf" ),
-                       'last possible sequence 6 bytes' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf\xbf" ),
-
-                       'boundary 1' => array( $PASS, "\xed\x9f\xbf" ),
-                       'boundary 2' => array( $PASS, "\xee\x80\x80" ),
-                       'boundary 3' => array( $PASS, "\xef\xbf\xbd" ),
-                       'boundary 4' => array( $PASS, "\xf2\x80\x80\x80" ),
-                       'boundary 5 (U+FFFFF)' => array( $PASS, "\xf3\xbf\xbf\xbf" ),
-                       'boundary 6 (U+100000)' => array( $PASS, "\xf4\x80\x80\x80" ),
-                       'boundary 7 (U+10FFFF)' => array( $PASS, "\xf4\x8f\xbf\xbf" ),
-                       'boundary 8 (U+110000)' => array( $FAIL, "\xf4\x90\x80\x80" ),
-
-                       'malformed 1' => array( $FAIL, "\x80" ),
-                       'malformed 2' => array( $FAIL, "\xbf" ),
-                       'malformed 3' => array( $FAIL, "\x80\xbf" ),
-                       'malformed 4' => array( $FAIL, "\x80\xbf\x80" ),
-                       'malformed 5' => array( $FAIL, "\x80\xbf\x80\xbf" ),
-                       'malformed 6' => array( $FAIL, "\x80\xbf\x80\xbf\x80" ),
-                       'malformed 7' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf" ),
-                       'malformed 8' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf\x80" ),
-
-                       'last byte missing 1' => array( $FAIL, "\xc0" ),
-                       'last byte missing 2' => array( $FAIL, "\xe0\x80" ),
-                       'last byte missing 3' => array( $FAIL, "\xf0\x80\x80" ),
-                       'last byte missing 4' => array( $FAIL, "\xf8\x80\x80\x80" ),
-                       'last byte missing 5' => array( $FAIL, "\xfc\x80\x80\x80\x80" ),
-                       'last byte missing 6' => array( $FAIL, "\xdf" ),
-                       'last byte missing 7' => array( $FAIL, "\xef\xbf" ),
-                       'last byte missing 8' => array( $FAIL, "\xf7\xbf\xbf" ),
-                       'last byte missing 9' => array( $FAIL, "\xfb\xbf\xbf\xbf" ),
-                       'last byte missing 10' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf" ),
-
-                       'extra continuation byte 1' => array( $FAIL, "e\xaf" ),
-                       'extra continuation byte 2' => array( $FAIL, "\xc3\x89\xaf" ),
-                       'extra continuation byte 3' => array( $FAIL, "\xef\xbc\xa5\xaf" ),
-                       'extra continuation byte 4' => array( $FAIL, "\xf0\x9d\x99\xb4\xaf" ),
-
-                       'impossible bytes 1' => array( $FAIL, "\xfe" ),
-                       'impossible bytes 2' => array( $FAIL, "\xff" ),
-                       'impossible bytes 3' => array( $FAIL, "\xfe\xfe\xff\xff" ),
-
-                       'overlong sequences 1' => array( $FAIL, "\xc0\xaf" ),
-                       'overlong sequences 2' => array( $FAIL, "\xc1\xaf" ),
-                       'overlong sequences 3' => array( $FAIL, "\xe0\x80\xaf" ),
-                       'overlong sequences 4' => array( $FAIL, "\xf0\x80\x80\xaf" ),
-                       'overlong sequences 5' => array( $FAIL, "\xf8\x80\x80\x80\xaf" ),
-                       'overlong sequences 6' => array( $FAIL, "\xfc\x80\x80\x80\x80\xaf" ),
-
-                       'maximum overlong sequences 1' => array( $FAIL, "\xc1\xbf" ),
-                       'maximum overlong sequences 2' => array( $FAIL, "\xe0\x9f\xbf" ),
-                       'maximum overlong sequences 3' => array( $FAIL, "\xf0\x8f\xbf\xbf" ),
-                       'maximum overlong sequences 4' => array( $FAIL, "\xf8\x87\xbf\xbf" ),
-                       'maximum overlong sequences 5' => array( $FAIL, "\xfc\x83\xbf\xbf\xbf\xbf" ),
-
-                       'surrogates 1 (U+D799)' => array( $PASS, "\xed\x9f\xbf" ),
-                       'surrogates 2 (U+E000)' => array( $PASS, "\xee\x80\x80" ),
-                       'surrogates 3 (U+D800)' => array( $FAIL, "\xed\xa0\x80" ),
-                       'surrogates 4 (U+DBFF)' => array( $FAIL, "\xed\xaf\xbf" ),
-                       'surrogates 5 (U+DC00)' => array( $FAIL, "\xed\xb0\x80" ),
-                       'surrogates 6 (U+DFFF)' => array( $FAIL, "\xed\xbf\xbf" ),
-                       'surrogates 7 (U+D800 U+DC00)' => array( $FAIL, "\xed\xa0\x80\xed\xb0\x80" ),
-
-                       'noncharacters 1' => array( $PASS, "\xef\xbf\xbe" ),
-                       'noncharacters 2' => array( $PASS, "\xef\xbf\xbf" ),
-               );
-       }
-}
index 906aebd..b0d1726 100644 (file)
@@ -10,12 +10,12 @@ class TemplateCategoriesTest extends MediaWikiLangTestCase {
        /**
         * @covers Title::getParentCategories
         */
-       function testTemplateCategories() {
-               $title = Title::newFromText( "Categorized from template" );
-               $page = WikiPage::factory( $title );
+       public function testTemplateCategories() {
                $user = new User();
-               $user->mRights = array( 'createpage', 'edit', 'purge' );
+               $user->mRights = array( 'createpage', 'edit', 'purge', 'delete' );
 
+               $title = Title::newFromText( "Categorized from template" );
+               $page = WikiPage::factory( $title );
                $page->doEditContent(
                        new WikitextContent( '{{Categorising template}}' ),
                        'Create a page with a template',
@@ -25,12 +25,13 @@ class TemplateCategoriesTest extends MediaWikiLangTestCase {
                );
 
                $this->assertEquals(
-                       array()
-                       , $title->getParentCategories()
+                       array(),
+                       $title->getParentCategories(),
+                       'Verify that the category doesn\'t contain the page before the template is created'
                );
 
+               // Create template
                $template = WikiPage::factory( Title::newFromText( 'Template:Categorising template' ) );
-
                $template->doEditContent(
                        new WikitextContent( '[[Category:Solved bugs]]' ),
                        'Add a category through a template',
@@ -45,9 +46,51 @@ class TemplateCategoriesTest extends MediaWikiLangTestCase {
                $jobs->loadParamsAndArgs( null, array( 'quiet' => true ), null );
                $jobs->execute();
 
+               // Make sure page is in the category
                $this->assertEquals(
-                       array( 'Category:Solved_bugs' => $title->getPrefixedText() )
-                       , $title->getParentCategories()
+                       array( 'Category:Solved_bugs' => $title->getPrefixedText() ),
+                       $title->getParentCategories(),
+                       'Verify that the page is in the category after the template is created'
+               );
+
+               // Edit the template
+               $template->doEditContent(
+                       new WikitextContent( '[[Category:Solved bugs 2]]' ),
+                       'Change the category added by the template',
+                       0,
+                       false,
+                       $user
                );
+
+               // Run the job queue
+               JobQueueGroup::destroySingletons();
+               $jobs = new RunJobs;
+               $jobs->loadParamsAndArgs( null, array( 'quiet' => true ), null );
+               $jobs->execute();
+
+               // Make sure page is in the right category
+               $this->assertEquals(
+                       array( 'Category:Solved_bugs_2' => $title->getPrefixedText() ),
+                       $title->getParentCategories(),
+                       'Verify that the page is in the right category after the template is edited'
+               );
+
+               // Now delete the template
+               $error = '';
+               $template->doDeleteArticleReal( 'Delete the template', false, 0, true, $error, $user );
+
+               // Run the job queue
+               JobQueueGroup::destroySingletons();
+               $jobs = new RunJobs;
+               $jobs->loadParamsAndArgs( null, array( 'quiet' => true ), null );
+               $jobs->execute();
+
+               // Make sure the page is no longer in the category
+               $this->assertEquals(
+                       array(),
+                       $title->getParentCategories(),
+                       'Verify that the page is no longer in the category after template deletion'
+               );
+
        }
 }
index 3079d73..55a17ac 100644 (file)
@@ -9,7 +9,7 @@
  */
 class TitleMethodsTest extends MediaWikiTestCase {
 
-       public function setUp() {
+       protected function setUp() {
                global $wgContLang;
 
                parent::setUp();
@@ -33,7 +33,7 @@ class TitleMethodsTest extends MediaWikiTestCase {
                $wgContLang->resetNamespaces(); # reset namespace cache
        }
 
-       public function tearDown() {
+       protected function tearDown() {
                global $wgContLang;
 
                parent::tearDown();
index f15c177..c7cbc7b 100644 (file)
@@ -2,7 +2,9 @@
 
 /**
  * @group Database
- * @todo covers tags
+ *
+ * @covers Title::getUserPermissionsErrors
+ * @covers Title::getUserPermissionsErrorsInternal
  */
 class TitlePermissionTest extends MediaWikiLangTestCase {
 
@@ -45,7 +47,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                date_default_timezone_set( $localZone );
 
                $this->title = Title::makeTitle( NS_MAIN, "Main Page" );
-               if ( !isset( $this->userUser ) || !( $this->userUser instanceOf User ) ) {
+               if ( !isset( $this->userUser ) || !( $this->userUser instanceof User ) ) {
                        $this->userUser = User::newFromName( $this->userName );
 
                        if ( !$this->userUser->getID() ) {
diff --git a/tests/phpunit/includes/UIDGeneratorTest.php b/tests/phpunit/includes/UIDGeneratorTest.php
deleted file mode 100644 (file)
index 8f78ae5..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-
-class UIDGeneratorTest extends MediaWikiTestCase {
-
-       /**
-        * @dataProvider provider_testTimestampedUID
-        * @covers UIDGenerator::newTimestampedUID128
-        * @covers UIDGenerator::newTimestampedUID88
-        */
-       public function testTimestampedUID( $method, $digitlen, $bits, $tbits, $hostbits ) {
-               $id = call_user_func( array( 'UIDGenerator', $method ) );
-               $this->assertEquals( true, ctype_digit( $id ), "UID made of digit characters" );
-               $this->assertLessThanOrEqual( $digitlen, strlen( $id ),
-                       "UID has the right number of digits" );
-               $this->assertLessThanOrEqual( $bits, strlen( wfBaseConvert( $id, 10, 2 ) ),
-                       "UID has the right number of bits" );
-
-               $ids = array();
-               for ( $i = 0; $i < 300; $i++ ) {
-                       $ids[] = call_user_func( array( 'UIDGenerator', $method ) );
-               }
-
-               $lastId = array_shift( $ids );
-               if ( $hostbits ) {
-                       $lastHost = substr( wfBaseConvert( $lastId, 10, 2, $bits ), -$hostbits );
-               }
-
-               $this->assertArrayEquals( array_unique( $ids ), $ids, "All generated IDs are unique." );
-
-               foreach ( $ids as $id ) {
-                       $id_bin = wfBaseConvert( $id, 10, 2 );
-                       $lastId_bin = wfBaseConvert( $lastId, 10, 2 );
-
-                       $this->assertGreaterThanOrEqual(
-                               substr( $id_bin, 0, $tbits ),
-                               substr( $lastId_bin, 0, $tbits ),
-                               "New ID timestamp ($id_bin) >= prior one ($lastId_bin)." );
-
-                       if ( $hostbits ) {
-                               $this->assertEquals(
-                                       substr( $id_bin, 0, -$hostbits ),
-                                       substr( $lastId_bin, 0, -$hostbits ),
-                                       "Host ID of ($id_bin) is same as prior one ($lastId_bin)." );
-                       }
-
-                       $lastId = $id;
-               }
-       }
-
-       /**
-        * array( method, length, bits, hostbits )
-        * NOTE: When adding a new method name here please update the covers tags for the tests!
-        */
-       public static function provider_testTimestampedUID() {
-               return array(
-                       array( 'newTimestampedUID128', 39, 128, 46, 48 ),
-                       array( 'newTimestampedUID128', 39, 128, 46, 48 ),
-                       array( 'newTimestampedUID88', 27, 88, 46, 32 ),
-               );
-       }
-
-       /**
-        * @covers UIDGenerator::newUUIDv4
-        */
-       public function testUUIDv4() {
-               for ( $i = 0; $i < 100; $i++ ) {
-                       $id = UIDGenerator::newUUIDv4();
-                       $this->assertEquals( true,
-                               preg_match( '!^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$!', $id ),
-                               "UID $id has the right format" );
-               }
-       }
-
-       /**
-        * @covers UIDGenerator::newRawUUIDv4
-        */
-       public function testRawUUIDv4() {
-               for ( $i = 0; $i < 100; $i++ ) {
-                       $id = UIDGenerator::newRawUUIDv4();
-                       $this->assertEquals( true,
-                               preg_match( '!^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$!', $id ),
-                               "UID $id has the right format" );
-               }
-       }
-
-       /**
-        * @covers UIDGenerator::newRawUUIDv4
-        */
-       public function testRawUUIDv4QuickRand() {
-               for ( $i = 0; $i < 100; $i++ ) {
-                       $id = UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND );
-                       $this->assertEquals( true,
-                               preg_match( '!^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$!', $id ),
-                               "UID $id has the right format" );
-               }
-       }
-
-}
diff --git a/tests/phpunit/includes/UserMailerTest.php b/tests/phpunit/includes/UserMailerTest.php
new file mode 100644 (file)
index 0000000..dca8aeb
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+class UserMailerTest extends MediaWikiLangTestCase {
+
+       /**
+        * @covers UserMailer::quotedPrintable
+        */
+       public function testQuotedPrintable() {
+               $this->assertEquals(
+                       "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
+                       UserMailer::quotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
+       }
+
+}
index a600188..06ed1fd 100644 (file)
@@ -22,7 +22,7 @@ class WebRequestTest extends MediaWikiTestCase {
         * @dataProvider provideDetectServer
         * @covers WebRequest::detectServer
         */
-       function testDetectServer( $expected, $input, $description ) {
+       public function testDetectServer( $expected, $input, $description ) {
                $_SERVER = $input;
                $result = WebRequest::detectServer();
                $this->assertEquals( $expected, $result, $description );
@@ -106,7 +106,7 @@ class WebRequestTest extends MediaWikiTestCase {
         * @dataProvider provideGetIP
         * @covers WebRequest::getIP
         */
-       function testGetIP( $expected, $input, $squid, $xffList, $private, $description ) {
+       public function testGetIP( $expected, $input, $squid, $xffList, $private, $description ) {
                $_SERVER = $input;
                $this->setMwGlobals( array(
                        'wgSquidServersNoPurge' => $squid,
@@ -269,6 +269,28 @@ class WebRequestTest extends MediaWikiTestCase {
                                false,
                                'With X-Forwaded-For and private IP and hook (disallowed)'
                        ),
+                       array(
+                               '12.0.0.1',
+                               array(
+                                       'REMOTE_ADDR' => 'abcd:0001:002:03:4:555:6666:7777',
+                                       'HTTP_X_FORWARDED_FOR' => '12.0.0.1, abcd:0001:002:03:4:555:6666:7777',
+                               ),
+                               array( 'ABCD:1:2:3::/64' ),
+                               array(),
+                               false,
+                               'IPv6 CIDR'
+                       ),
+                       array(
+                               '12.0.0.3',
+                               array(
+                                       'REMOTE_ADDR' => '12.0.0.1',
+                                       'HTTP_X_FORWARDED_FOR' => '12.0.0.3, 12.0.0.2'
+                               ),
+                               array( '12.0.0.0/24' ),
+                               array(),
+                               false,
+                               'IPv4 CIDR'
+                       ),
                );
        }
 
@@ -276,7 +298,15 @@ class WebRequestTest extends MediaWikiTestCase {
         * @expectedException MWException
         * @covers WebRequest::getIP
         */
-       function testGetIpLackOfRemoteAddrThrowAnException() {
+       public function testGetIpLackOfRemoteAddrThrowAnException() {
+               // ensure that local install state doesn't interfere with test
+               $this->setMwGlobals( array(
+                       'wgSquidServersNoPurge' => array(),
+                       'wgSquidServers' => array(),
+                       'wgUsePrivateIPs' => false,
+                       'wgHooks' => array(),
+               ) );
+
                $request = new WebRequest();
                # Next call throw an exception about lacking an IP
                $request->getIP();
@@ -302,7 +332,7 @@ class WebRequestTest extends MediaWikiTestCase {
         * @dataProvider provideLanguageData
         * @covers WebRequest::getAcceptLang
         */
-       function testAcceptLang( $acceptLanguageHeader, $expectedLanguages, $description ) {
+       public function testAcceptLang( $acceptLanguageHeader, $expectedLanguages, $description ) {
                $_SERVER = array( 'HTTP_ACCEPT_LANGUAGE' => $acceptLanguageHeader );
                $request = new WebRequest();
                $this->assertSame( $request->getAcceptLang(), $expectedLanguages, $description );
index e0d786b..796adf3 100644 (file)
@@ -576,7 +576,6 @@ class WikiPageTest extends MediaWikiLangTestCase {
                );
        }
 
-
        /**
         * @dataProvider provideIsCountable
         * @covers WikiPage::isCountable
@@ -678,7 +677,6 @@ just a test
 more stuff
 ";
 
-
        public function dataReplaceSection() {
                //NOTE: assume the Help namespace to contain wikitext
                return array(
@@ -1071,4 +1069,21 @@ more stuff
 
                $this->assertEquals( $expected, $text );
        }
+
+       /**
+        * @covers WikiPage::factory
+        */
+       public function testWikiPageFactory() {
+               $title = Title::makeTitle( NS_FILE, 'Someimage.png' );
+               $page = WikiPage::factory( $title );
+               $this->assertEquals( 'WikiFilePage', get_class( $page ) );
+
+               $title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
+               $page = WikiPage::factory( $title );
+               $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
+
+               $title = Title::makeTitle( NS_MAIN, 'SomePage' );
+               $page = WikiPage::factory( $title );
+               $this->assertEquals( 'WikiPage', get_class( $page ) );
+       }
 }
index 161468e..907ce79 100644 (file)
@@ -14,7 +14,7 @@ class XmlJs extends MediaWikiTestCase {
                $this->assertEquals( $value, $obj->value );
        }
 
-       public function provideConstruction(){
+       public function provideConstruction() {
                return array(
                        array( null ),
                        array( '' ),
index a0b33ee..8205029 100644 (file)
@@ -57,7 +57,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::element
         */
-       function testElementOpen() {
+       public function testElementOpen() {
                $this->assertEquals(
                        '<element>',
                        Xml::element( 'element', null, null ),
@@ -68,7 +68,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::element
         */
-       function testElementEmpty() {
+       public function testElementEmpty() {
                $this->assertEquals(
                        '<element />',
                        Xml::element( 'element', null, '' ),
@@ -79,7 +79,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::input
         */
-       function testElementInputCanHaveAValueOfZero() {
+       public function testElementInputCanHaveAValueOfZero() {
                $this->assertEquals(
                        '<input name="name" value="0" />',
                        Xml::input( 'name', false, 0 ),
@@ -90,7 +90,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::element
         */
-       function testElementEscaping() {
+       public function testElementEscaping() {
                $this->assertEquals(
                        '<element>hello &lt;there&gt; you &amp; you</element>',
                        Xml::element( 'element', null, 'hello <there> you & you' ),
@@ -110,7 +110,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::element
         */
-       function testElementAttributes() {
+       public function testElementAttributes() {
                $this->assertEquals(
                        '<element key="value" <>="&lt;&gt;">',
                        Xml::element( 'element', array( 'key' => 'value', '<>' => '<>' ), null ),
@@ -121,7 +121,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::openElement
         */
-       function testOpenElement() {
+       public function testOpenElement() {
                $this->assertEquals(
                        '<element k="v">',
                        Xml::openElement( 'element', array( 'k' => 'v' ) ),
@@ -132,7 +132,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::closeElement
         */
-       function testCloseElement() {
+       public function testCloseElement() {
                $this->assertEquals( '</element>', Xml::closeElement( 'element' ), 'closeElement() shortcut' );
        }
 
@@ -222,7 +222,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::textarea
         */
-       function testTextareaNoContent() {
+       public function testTextareaNoContent() {
                $this->assertEquals(
                        '<textarea name="name" id="name" cols="40" rows="5"></textarea>',
                        Xml::textarea( 'name', '' ),
@@ -233,7 +233,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::textarea
         */
-       function testTextareaAttribs() {
+       public function testTextareaAttribs() {
                $this->assertEquals(
                        '<textarea name="name" id="name" cols="20" rows="10">&lt;txt&gt;</textarea>',
                        Xml::textarea( 'name', '<txt>', 20, 10 ),
@@ -244,7 +244,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::label
         */
-       function testLabelCreation() {
+       public function testLabelCreation() {
                $this->assertEquals(
                        '<label for="id">name</label>',
                        Xml::label( 'name', 'id' ),
@@ -255,7 +255,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::label
         */
-       function testLabelAttributeCanOnlyBeClassOrTitle() {
+       public function testLabelAttributeCanOnlyBeClassOrTitle() {
                $this->assertEquals(
                        '<label for="id">name</label>',
                        Xml::label( 'name', 'id', array( 'generated' => true ) ),
@@ -287,7 +287,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::languageSelector
         */
-       function testLanguageSelector() {
+       public function testLanguageSelector() {
                $select = Xml::languageSelector( 'en', true, null,
                        array( 'id' => 'testlang' ), wfMessage( 'yourlanguage' ) );
                $this->assertEquals(
@@ -299,7 +299,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::escapeJsString
         */
-       function testEscapeJsStringSpecialChars() {
+       public function testEscapeJsStringSpecialChars() {
                $this->assertEquals(
                        '\\\\\r\n',
                        Xml::escapeJsString( "\\\r\n" ),
@@ -310,7 +310,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarBoolean() {
+       public function testEncodeJsVarBoolean() {
                $this->assertEquals(
                        'true',
                        Xml::encodeJsVar( true ),
@@ -321,7 +321,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarNull() {
+       public function testEncodeJsVarNull() {
                $this->assertEquals(
                        'null',
                        Xml::encodeJsVar( null ),
@@ -332,7 +332,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarArray() {
+       public function testEncodeJsVarArray() {
                $this->assertEquals(
                        '["a",1]',
                        Xml::encodeJsVar( array( 'a', 1 ) ),
@@ -348,7 +348,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarObject() {
+       public function testEncodeJsVarObject() {
                $this->assertEquals(
                        '{"a":"a","b":1}',
                        Xml::encodeJsVar( (object)array( 'a' => 'a', 'b' => 1 ) ),
@@ -359,7 +359,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarInt() {
+       public function testEncodeJsVarInt() {
                $this->assertEquals(
                        '123456',
                        Xml::encodeJsVar( 123456 ),
@@ -370,7 +370,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarFloat() {
+       public function testEncodeJsVarFloat() {
                $this->assertEquals(
                        '1.23456',
                        Xml::encodeJsVar( 1.23456 ),
@@ -381,7 +381,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarIntString() {
+       public function testEncodeJsVarIntString() {
                $this->assertEquals(
                        '"123456"',
                        Xml::encodeJsVar( '123456' ),
@@ -392,7 +392,7 @@ class XmlTest extends MediaWikiTestCase {
        /**
         * @covers Xml::encodeJsVar
         */
-       function testEncodeJsVarFloatString() {
+       public function testEncodeJsVarFloatString() {
                $this->assertEquals(
                        '"1.23456"',
                        Xml::encodeJsVar( '1.23456' ),
diff --git a/tests/phpunit/includes/ZipDirectoryReaderTest.php b/tests/phpunit/includes/ZipDirectoryReaderTest.php
deleted file mode 100644 (file)
index 7f436cd..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-/**
- * @covers ZipDirectoryReader
- * NOTE: this test is more like an integration test than a unit test
- */
-class ZipDirectoryReaderTest extends MediaWikiTestCase {
-       protected $zipDir;
-       protected $entries;
-
-       protected function setUp() {
-               parent::setUp();
-               $this->zipDir = __DIR__ . '/../data/zip';
-       }
-
-       function zipCallback( $entry ) {
-               $this->entries[] = $entry;
-       }
-
-       function readZipAssertError( $file, $error, $assertMessage ) {
-               $this->entries = array();
-               $status = ZipDirectoryReader::read( "{$this->zipDir}/$file", array( $this, 'zipCallback' ) );
-               $this->assertTrue( $status->hasMessage( $error ), $assertMessage );
-       }
-
-       function readZipAssertSuccess( $file, $assertMessage ) {
-               $this->entries = array();
-               $status = ZipDirectoryReader::read( "{$this->zipDir}/$file", array( $this, 'zipCallback' ) );
-               $this->assertTrue( $status->isOK(), $assertMessage );
-       }
-
-       function testEmpty() {
-               $this->readZipAssertSuccess( 'empty.zip', 'Empty zip' );
-       }
-
-       function testMultiDisk0() {
-               $this->readZipAssertError( 'split.zip', 'zip-unsupported',
-                       'Split zip error' );
-       }
-
-       function testNoSignature() {
-               $this->readZipAssertError( 'nosig.zip', 'zip-wrong-format',
-                       'No signature should give "wrong format" error' );
-       }
-
-       function testSimple() {
-               $this->readZipAssertSuccess( 'class.zip', 'Simple ZIP' );
-               $this->assertEquals( $this->entries, array( array(
-                       'name' => 'Class.class',
-                       'mtime' => '20010115000000',
-                       'size' => 1,
-               ) ) );
-       }
-
-       function testBadCentralEntrySignature() {
-               $this->readZipAssertError( 'wrong-central-entry-sig.zip', 'zip-bad',
-                       'Bad central entry error' );
-       }
-
-       function testTrailingBytes() {
-               $this->readZipAssertError( 'trail.zip', 'zip-bad',
-                       'Trailing bytes error' );
-       }
-
-       function testWrongCDStart() {
-               $this->readZipAssertError( 'wrong-cd-start-disk.zip', 'zip-unsupported',
-                       'Wrong CD start disk error' );
-       }
-
-
-       function testCentralDirectoryGap() {
-               $this->readZipAssertError( 'cd-gap.zip', 'zip-bad',
-                       'CD gap error' );
-       }
-
-       function testCentralDirectoryTruncated() {
-               $this->readZipAssertError( 'cd-truncated.zip', 'zip-bad',
-                       'CD truncated error (should hit unpack() overrun)' );
-       }
-
-       function testLooksLikeZip64() {
-               $this->readZipAssertError( 'looks-like-zip64.zip', 'zip-unsupported',
-                       'A file which looks like ZIP64 but isn\'t, should give error' );
-       }
-}
diff --git a/tests/phpunit/includes/api/ApiAccountCreationTest.php b/tests/phpunit/includes/api/ApiAccountCreationTest.php
deleted file mode 100644 (file)
index 50638ca..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-/**
- * @group Database
- * @group API
- * @group medium
- */
-class ApiCreateAccountTest extends ApiTestCase {
-       function setUp() {
-               parent::setUp();
-               LoginForm::setCreateaccountToken();
-               $this->setMwGlobals( array( 'wgEnableEmail' => true ) );
-       }
-
-       /**
-        * Test the account creation API with a valid request. Also
-        * make sure the new account can log in and is valid.
-        *
-        * This test does multiple API requests so it might end up being
-        * a bit slow. Raise the default timeout.
-        * @group medium
-        */
-       function testValid() {
-               global $wgServer;
-
-               if ( !isset( $wgServer ) ) {
-                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
-               }
-
-               $password = User::randomPassword();
-
-               $ret = $this->doApiRequest( array(
-                       'action' => 'createaccount',
-                       'name' => 'Apitestnew',
-                       'password' => $password,
-                       'email' => 'test@domain.test',
-                       'realname' => 'Test Name'
-               ) );
-
-               $result = $ret[0];
-               $this->assertNotInternalType( 'bool', $result );
-               $this->assertNotInternalType( 'null', $result['createaccount'] );
-
-               // Should first ask for token.
-               $a = $result['createaccount'];
-               $this->assertEquals( 'needtoken', $a['result'] );
-               $token = $a['token'];
-
-               // Finally create the account
-               $ret = $this->doApiRequest(
-                       array(
-                               'action' => 'createaccount',
-                               'name' => 'Apitestnew',
-                               'password' => $password,
-                               'token' => $token,
-                               'email' => 'test@domain.test',
-                               'realname' => 'Test Name'
-                       ),
-                       $ret[2]
-               );
-
-               $result = $ret[0];
-               $this->assertNotInternalType( 'bool', $result );
-               $this->assertEquals( 'success', $result['createaccount']['result'] );
-
-               // Try logging in with the new user.
-               $ret = $this->doApiRequest( array(
-                       'action' => 'login',
-                       'lgname' => 'Apitestnew',
-                       'lgpassword' => $password,
-               ) );
-
-               $result = $ret[0];
-               $this->assertNotInternalType( 'bool', $result );
-               $this->assertNotInternalType( 'null', $result['login'] );
-
-               $a = $result['login']['result'];
-               $this->assertEquals( 'NeedToken', $a );
-               $token = $result['login']['token'];
-
-               $ret = $this->doApiRequest(
-                       array(
-                               'action' => 'login',
-                               'lgtoken' => $token,
-                               'lgname' => 'Apitestnew',
-                               'lgpassword' => $password,
-                       ),
-                       $ret[2]
-               );
-
-               $result = $ret[0];
-
-               $this->assertNotInternalType( 'bool', $result );
-               $a = $result['login']['result'];
-
-               $this->assertEquals( 'Success', $a );
-
-               // log out to destroy the session
-               $ret = $this->doApiRequest(
-                       array(
-                               'action' => 'logout',
-                       ),
-                       $ret[2]
-               );
-               $this->assertEquals( array(), $ret[0] );
-       }
-
-       /**
-        * Make sure requests with no names are invalid.
-        * @expectedException UsageException
-        */
-       function testNoName() {
-               $this->doApiRequest( array(
-                       'action' => 'createaccount',
-                       'token' => LoginForm::getCreateaccountToken(),
-                       'password' => 'password',
-               ) );
-       }
-
-       /**
-        * Make sure requests with no password are invalid.
-        * @expectedException UsageException
-        */
-       function testNoPassword() {
-               $this->doApiRequest( array(
-                       'action' => 'createaccount',
-                       'name' => 'testName',
-                       'token' => LoginForm::getCreateaccountToken(),
-               ) );
-       }
-
-       /**
-        * Make sure requests with existing users are invalid.
-        * @expectedException UsageException
-        */
-       function testExistingUser() {
-               $this->doApiRequest( array(
-                       'action' => 'createaccount',
-                       'name' => 'Apitestsysop',
-                       'token' => LoginForm::getCreateaccountToken(),
-                       'password' => 'password',
-                       'email' => 'test@domain.test',
-               ) );
-       }
-
-       /**
-        * Make sure requests with invalid emails are invalid.
-        * @expectedException UsageException
-        */
-       function testInvalidEmail() {
-               $this->doApiRequest( array(
-                       'action' => 'createaccount',
-                       'name' => 'Test User',
-                       'token' => LoginForm::getCreateaccountToken(),
-                       'password' => 'password',
-                       'email' => 'invalid',
-               ) );
-       }
-}
diff --git a/tests/phpunit/includes/api/ApiBaseTest.php b/tests/phpunit/includes/api/ApiBaseTest.php
new file mode 100644 (file)
index 0000000..bfb75ef
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ */
+class ApiBaseTest extends ApiTestCase {
+
+       /**
+        * @covers ApiBase::requireOnlyOneParameter
+        */
+       public function testRequireOnlyOneParameterDefault() {
+               $mock = new MockApi();
+               $mock->requireOnlyOneParameter(
+                       array( "filename" => "foo.txt", "enablechunks" => false ),
+                       "filename", "enablechunks"
+               );
+               $this->assertTrue( true );
+       }
+
+       /**
+        * @expectedException UsageException
+        * @covers ApiBase::requireOnlyOneParameter
+        */
+       public function testRequireOnlyOneParameterZero() {
+               $mock = new MockApi();
+               $mock->requireOnlyOneParameter(
+                       array( "filename" => "foo.txt","enablechunks" => 0 ),
+                       "filename", "enablechunks"
+               );
+       }
+
+       /**
+        * @expectedException UsageException
+        * @covers ApiBase::requireOnlyOneParameter
+        */
+       public function testRequireOnlyOneParameterTrue() {
+               $mock = new MockApi();
+               $mock->requireOnlyOneParameter(
+                       array( "filename" => "foo.txt", "enablechunks" => true ),
+                       "filename", "enablechunks"
+               );
+       }
+
+}
index d0eb18a..d98eec6 100644 (file)
@@ -4,6 +4,8 @@
  * @group API
  * @group Database
  * @group medium
+ *
+ * @covers ApiBlock
  */
 class ApiBlockTest extends ApiTestCase {
        protected function setUp() {
@@ -11,7 +13,7 @@ class ApiBlockTest extends ApiTestCase {
                $this->doLogin();
        }
 
-       function getTokens() {
+       protected function getTokens() {
                return $this->getTokenList( self::$users['sysop'] );
        }
 
@@ -34,7 +36,7 @@ class ApiBlockTest extends ApiTestCase {
         * Which made the Block/Unblock API to actually verify the token
         * previously always considered valid (bug 34212).
         */
-       function testMakeNormalBlock() {
+       public function testMakeNormalBlock() {
                $tokens = $this->getTokens();
 
                $user = User::newFromName( 'UTApiBlockee' );
@@ -63,17 +65,13 @@ class ApiBlockTest extends ApiTestCase {
        }
 
        /**
-        * Attempting to block without a token should give a UsageException with
-        * error message:
-        *   "The token parameter must be set"
-        *
-        * @dataProvider provideBlockUnblockAction
         * @expectedException UsageException
+        * @expectedExceptionMessage The token parameter must be set
         */
-       function testBlockingActionWithNoToken( $action ) {
+       public function testBlockingActionWithNoToken( ) {
                $this->doApiRequest(
                        array(
-                               'action' => $action,
+                               'action' => 'block',
                                'user' => 'UTApiBlockee',
                                'reason' => 'Some reason',
                        ),
@@ -82,14 +80,4 @@ class ApiBlockTest extends ApiTestCase {
                        self::$users['sysop']->user
                );
        }
-
-       /**
-        * Just provide the 'block' and 'unblock' action to test both API calls
-        */
-       public static function provideBlockUnblockAction() {
-               return array(
-                       array( 'block' ),
-                       array( 'unblock' ),
-               );
-       }
 }
diff --git a/tests/phpunit/includes/api/ApiCreateAccountTest.php b/tests/phpunit/includes/api/ApiCreateAccountTest.php
new file mode 100644 (file)
index 0000000..a723245
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * @group Database
+ * @group API
+ * @group medium
+ *
+ * @covers ApiCreateAccount
+ */
+class ApiCreateAccountTest extends ApiTestCase {
+       protected function setUp() {
+               parent::setUp();
+               LoginForm::setCreateaccountToken();
+               $this->setMwGlobals( array( 'wgEnableEmail' => true ) );
+       }
+
+       /**
+        * Test the account creation API with a valid request. Also
+        * make sure the new account can log in and is valid.
+        *
+        * This test does multiple API requests so it might end up being
+        * a bit slow. Raise the default timeout.
+        * @group medium
+        */
+       public function testValid() {
+               global $wgServer;
+
+               if ( !isset( $wgServer ) ) {
+                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
+               }
+
+               $password = User::randomPassword();
+
+               $ret = $this->doApiRequest( array(
+                       'action' => 'createaccount',
+                       'name' => 'Apitestnew',
+                       'password' => $password,
+                       'email' => 'test@domain.test',
+                       'realname' => 'Test Name'
+               ) );
+
+               $result = $ret[0];
+               $this->assertNotInternalType( 'bool', $result );
+               $this->assertNotInternalType( 'null', $result['createaccount'] );
+
+               // Should first ask for token.
+               $a = $result['createaccount'];
+               $this->assertEquals( 'needtoken', $a['result'] );
+               $token = $a['token'];
+
+               // Finally create the account
+               $ret = $this->doApiRequest(
+                       array(
+                               'action' => 'createaccount',
+                               'name' => 'Apitestnew',
+                               'password' => $password,
+                               'token' => $token,
+                               'email' => 'test@domain.test',
+                               'realname' => 'Test Name'
+                       ),
+                       $ret[2]
+               );
+
+               $result = $ret[0];
+               $this->assertNotInternalType( 'bool', $result );
+               $this->assertEquals( 'success', $result['createaccount']['result'] );
+
+               // Try logging in with the new user.
+               $ret = $this->doApiRequest( array(
+                       'action' => 'login',
+                       'lgname' => 'Apitestnew',
+                       'lgpassword' => $password,
+               ) );
+
+               $result = $ret[0];
+               $this->assertNotInternalType( 'bool', $result );
+               $this->assertNotInternalType( 'null', $result['login'] );
+
+               $a = $result['login']['result'];
+               $this->assertEquals( 'NeedToken', $a );
+               $token = $result['login']['token'];
+
+               $ret = $this->doApiRequest(
+                       array(
+                               'action' => 'login',
+                               'lgtoken' => $token,
+                               'lgname' => 'Apitestnew',
+                               'lgpassword' => $password,
+                       ),
+                       $ret[2]
+               );
+
+               $result = $ret[0];
+
+               $this->assertNotInternalType( 'bool', $result );
+               $a = $result['login']['result'];
+
+               $this->assertEquals( 'Success', $a );
+
+               // log out to destroy the session
+               $ret = $this->doApiRequest(
+                       array(
+                               'action' => 'logout',
+                       ),
+                       $ret[2]
+               );
+               $this->assertEquals( array(), $ret[0] );
+       }
+
+       /**
+        * Make sure requests with no names are invalid.
+        * @expectedException UsageException
+        */
+       public function testNoName() {
+               $this->doApiRequest( array(
+                       'action' => 'createaccount',
+                       'token' => LoginForm::getCreateaccountToken(),
+                       'password' => 'password',
+               ) );
+       }
+
+       /**
+        * Make sure requests with no password are invalid.
+        * @expectedException UsageException
+        */
+       public function testNoPassword() {
+               $this->doApiRequest( array(
+                       'action' => 'createaccount',
+                       'name' => 'testName',
+                       'token' => LoginForm::getCreateaccountToken(),
+               ) );
+       }
+
+       /**
+        * Make sure requests with existing users are invalid.
+        * @expectedException UsageException
+        */
+       public function testExistingUser() {
+               $this->doApiRequest( array(
+                       'action' => 'createaccount',
+                       'name' => 'Apitestsysop',
+                       'token' => LoginForm::getCreateaccountToken(),
+                       'password' => 'password',
+                       'email' => 'test@domain.test',
+               ) );
+       }
+
+       /**
+        * Make sure requests with invalid emails are invalid.
+        * @expectedException UsageException
+        */
+       public function testInvalidEmail() {
+               $this->doApiRequest( array(
+                       'action' => 'createaccount',
+                       'name' => 'Test User',
+                       'token' => LoginForm::getCreateaccountToken(),
+                       'password' => 'password',
+                       'email' => 'invalid',
+               ) );
+       }
+}
index 3926e85..0a6607e 100644 (file)
@@ -8,10 +8,12 @@
  * @group API
  * @group Database
  * @group medium
+ *
+ * @covers ApiEditPage
  */
 class ApiEditPageTest extends ApiTestCase {
 
-       public function setUp() {
+       protected function setUp() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
 
                parent::setUp();
@@ -28,7 +30,7 @@ class ApiEditPageTest extends ApiTestCase {
                $this->doLogin();
        }
 
-       public function tearDown() {
+       protected function tearDown() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
 
                unset( $wgExtraNamespaces[12312] );
@@ -43,7 +45,7 @@ class ApiEditPageTest extends ApiTestCase {
                parent::tearDown();
        }
 
-       function testEdit() {
+       public function testEdit() {
                $name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
 
                // -- test new page --------------------------------------------
@@ -97,7 +99,7 @@ class ApiEditPageTest extends ApiTestCase {
                );
        }
 
-       function testNonTextEdit() {
+       public function testNonTextEdit() {
                $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
                $data = serialize( 'some bla bla text' );
 
@@ -124,6 +126,9 @@ class ApiEditPageTest extends ApiTestCase {
                $this->assertEquals( $data, $page->getContent()->serialize() );
        }
 
+       /**
+        * @return array
+        */
        public static function provideEditAppend() {
                return array(
                        array( #0: append
@@ -150,7 +155,7 @@ class ApiEditPageTest extends ApiTestCase {
        /**
         * @dataProvider provideEditAppend
         */
-       function testEditAppend( $text, $op, $append, $expected ) {
+       public function testEditAppend( $text, $op, $append, $expected ) {
                static $count = 0;
                $count++;
 
@@ -196,7 +201,7 @@ class ApiEditPageTest extends ApiTestCase {
        /**
         * Test editing of sections
         */
-       function testEditSection() {
+       public function testEditSection() {
                $name = 'Help:ApiEditPageTest_testEditSection';
                $page = WikiPage::factory( Title::newFromText( $name ) );
                $text = "==section 1==\ncontent 1\n==section 2==\ncontent2";
@@ -210,7 +215,7 @@ class ApiEditPageTest extends ApiTestCase {
                        'text' => "==section 1==\nnew content 1",
                ) );
                $this->assertEquals( 'Success', $re['edit']['result'] );
-               $newtext = WikiPage::factory( Title::newFromText( $name) )->getContent( Revision::RAW )->getNativeData();
+               $newtext = WikiPage::factory( Title::newFromText( $name ) )->getContent( Revision::RAW )->getNativeData();
                $this->assertEquals( $newtext, "==section 1==\nnew content 1\n\n==section 2==\ncontent2" );
 
                // Test that we raise a 'nosuchsection' error
@@ -233,7 +238,7 @@ class ApiEditPageTest extends ApiTestCase {
         * page that doesn't exist (bug 52830) and one that
         * does exist
         */
-       function testEditNewSection() {
+       public function testEditNewSection() {
                $name = 'Help:ApiEditPageTest_testEditNewSection';
 
                // Test on a page that does not already exist
@@ -266,7 +271,7 @@ class ApiEditPageTest extends ApiTestCase {
                $this->assertEquals( $text, "== header ==\n\ntest\n\n== header ==\n\ntest" );
        }
 
-       function testEditConflict() {
+       public function testEditConflict() {
                static $count = 0;
                $count++;
 
@@ -302,7 +307,7 @@ class ApiEditPageTest extends ApiTestCase {
                }
        }
 
-       function testEditConflict_redirect() {
+       public function testEditConflict_redirect() {
                static $count = 0;
                $count++;
 
@@ -358,7 +363,7 @@ class ApiEditPageTest extends ApiTestCase {
                }
        }
 
-       function testEditConflict_bug41990() {
+       public function testEditConflict_bug41990() {
                static $count = 0;
                $count++;
 
@@ -405,6 +410,10 @@ class ApiEditPageTest extends ApiTestCase {
                        "no edit conflict expected here" );
        }
 
+       /**
+        * @param WikiPage $page
+        * @param string|int $timestamp
+        */
        protected function forceRevisionDate( WikiPage $page, $timestamp ) {
                $dbw = wfGetDB( DB_MASTER );
 
diff --git a/tests/phpunit/includes/api/ApiLoginTest.php b/tests/phpunit/includes/api/ApiLoginTest.php
new file mode 100644 (file)
index 0000000..f1199e0
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ *
+ * @covers ApiLogin
+ */
+class ApiLoginTest extends ApiTestCase {
+
+       /**
+        * Test result of attempted login with an empty username
+        */
+       public function testApiLoginNoName() {
+               $data = $this->doApiRequest( array( 'action' => 'login',
+                       'lgname' => '', 'lgpassword' => self::$users['sysop']->password,
+               ) );
+               $this->assertEquals( 'NoName', $data[0]['login']['result'] );
+       }
+
+       public function testApiLoginBadPass() {
+               global $wgServer;
+
+               $user = self::$users['sysop'];
+               $user->user->logOut();
+
+               if ( !isset( $wgServer ) ) {
+                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
+               }
+               $ret = $this->doApiRequest( array(
+                       "action" => "login",
+                       "lgname" => $user->username,
+                       "lgpassword" => "bad",
+               ) );
+
+               $result = $ret[0];
+
+               $this->assertNotInternalType( "bool", $result );
+               $a = $result["login"]["result"];
+               $this->assertEquals( "NeedToken", $a );
+
+               $token = $result["login"]["token"];
+
+               $ret = $this->doApiRequest(
+                       array(
+                               "action" => "login",
+                               "lgtoken" => $token,
+                               "lgname" => $user->username,
+                               "lgpassword" => "badnowayinhell",
+                       ),
+                       $ret[2]
+               );
+
+               $result = $ret[0];
+
+               $this->assertNotInternalType( "bool", $result );
+               $a = $result["login"]["result"];
+
+               $this->assertEquals( "WrongPass", $a );
+       }
+
+       public function testApiLoginGoodPass() {
+               global $wgServer;
+
+               if ( !isset( $wgServer ) ) {
+                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
+               }
+
+               $user = self::$users['sysop'];
+               $user->user->logOut();
+
+               $ret = $this->doApiRequest( array(
+                               "action" => "login",
+                               "lgname" => $user->username,
+                               "lgpassword" => $user->password,
+                       )
+               );
+
+               $result = $ret[0];
+               $this->assertNotInternalType( "bool", $result );
+               $this->assertNotInternalType( "null", $result["login"] );
+
+               $a = $result["login"]["result"];
+               $this->assertEquals( "NeedToken", $a );
+               $token = $result["login"]["token"];
+
+               $ret = $this->doApiRequest(
+                       array(
+                               "action" => "login",
+                               "lgtoken" => $token,
+                               "lgname" => $user->username,
+                               "lgpassword" => $user->password,
+                       ),
+                       $ret[2]
+               );
+
+               $result = $ret[0];
+
+               $this->assertNotInternalType( "bool", $result );
+               $a = $result["login"]["result"];
+
+               $this->assertEquals( "Success", $a );
+       }
+
+       /**
+        * @group Broken
+        */
+       public function testApiLoginGotCookie() {
+               $this->markTestIncomplete( "The server can't do external HTTP requests, and the internal one won't give cookies" );
+
+               global $wgServer, $wgScriptPath;
+
+               if ( !isset( $wgServer ) ) {
+                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
+               }
+               $user = self::$users['sysop'];
+
+               $req = MWHttpRequest::factory( self::$apiUrl . "?action=login&format=xml",
+                       array( "method" => "POST",
+                               "postData" => array(
+                                       "lgname" => $user->username,
+                                       "lgpassword" => $user->password
+                               )
+                       )
+               );
+               $req->execute();
+
+               libxml_use_internal_errors( true );
+               $sxe = simplexml_load_string( $req->getContent() );
+               $this->assertNotInternalType( "bool", $sxe );
+               $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
+               $this->assertNotInternalType( "null", $sxe->login[0] );
+
+               $a = $sxe->login[0]->attributes()->result[0];
+               $this->assertEquals( ' result="NeedToken"', $a->asXML() );
+               $token = (string)$sxe->login[0]->attributes()->token;
+
+               $req->setData( array(
+                       "lgtoken" => $token,
+                       "lgname" => $user->username,
+                       "lgpassword" => $user->password ) );
+               $req->execute();
+
+               $cj = $req->getCookieJar();
+               $serverName = parse_url( $wgServer, PHP_URL_HOST );
+               $this->assertNotEquals( false, $serverName );
+               $serializedCookie = $cj->serializeToHttpRequest( $wgScriptPath, $serverName );
+               $this->assertNotEquals( '', $serializedCookie );
+               $this->assertRegexp( '/_session=[^;]*; .*UserID=[0-9]*; .*UserName=' . $user->userName . '; .*Token=/', $serializedCookie );
+       }
+
+       public function testRunLogin() {
+               $sysopUser = self::$users['sysop'];
+               $data = $this->doApiRequest( array(
+                       'action' => 'login',
+                       'lgname' => $sysopUser->username,
+                       'lgpassword' => $sysopUser->password ) );
+
+               $this->assertArrayHasKey( "login", $data[0] );
+               $this->assertArrayHasKey( "result", $data[0]['login'] );
+               $this->assertEquals( "NeedToken", $data[0]['login']['result'] );
+               $token = $data[0]['login']['token'];
+
+               $data = $this->doApiRequest( array(
+                       'action' => 'login',
+                       "lgtoken" => $token,
+                       "lgname" => $sysopUser->username,
+                       "lgpassword" => $sysopUser->password ), $data[2] );
+
+               $this->assertArrayHasKey( "login", $data[0] );
+               $this->assertArrayHasKey( "result", $data[0]['login'] );
+               $this->assertEquals( "Success", $data[0]['login']['result'] );
+               $this->assertArrayHasKey( 'lgtoken', $data[0]['login'] );
+       }
+
+}
diff --git a/tests/phpunit/includes/api/ApiMainTest.php b/tests/phpunit/includes/api/ApiMainTest.php
new file mode 100644 (file)
index 0000000..4ed5aa9
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ *
+ * @covers ApiMain
+ */
+class ApiMainTest extends ApiTestCase {
+
+       /**
+        * Test that the API will accept a FauxRequest and execute. The help action
+        * (default) throws a UsageException. Just validate we're getting proper XML
+        *
+        * @expectedException UsageException
+        */
+       public function testApi() {
+               $api = new ApiMain(
+                       new FauxRequest( array( 'action' => 'help', 'format' => 'xml' ) )
+               );
+               $api->execute();
+               $api->getPrinter()->setBufferResult( true );
+               $api->printResult( false );
+               $resp = $api->getPrinter()->getBuffer();
+
+               libxml_use_internal_errors( true );
+               $sxe = simplexml_load_string( $resp );
+               $this->assertNotInternalType( "bool", $sxe );
+               $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
+       }
+
+}
index ad1e73a..6659414 100644 (file)
@@ -4,10 +4,18 @@
  * @group API
  * @group Database
  * @group medium
+ *
+ * @covers ApiOptions
  */
 class ApiOptionsTest extends MediaWikiLangTestCase {
 
-       private $mTested, $mUserMock, $mContext, $mSession;
+       /** @var PHPUnit_Framework_MockObject_MockObject */
+       private $mUserMock;
+       /** @var ApiOptions */
+       private $mTested;
+       private $mSession;
+       /** @var DerivativeContext */
+       private $mContext;
 
        private $mOldGetPreferencesHooks = false;
 
@@ -91,6 +99,12 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
                return true;
        }
 
+       /**
+        * @param IContextSource $context
+        * @param array|null $options
+        *
+        * @return array
+        */
        public function getOptionKinds( IContextSource $context, $options = null ) {
                // Match with above.
                $kinds = array(
index b408875..d303d4b 100644 (file)
@@ -4,6 +4,8 @@
  * @group API
  * @group Database
  * @group medium
+ *
+ * @covers ApiParse
  */
 class ApiParseTest extends ApiTestCase {
 
@@ -12,7 +14,7 @@ class ApiParseTest extends ApiTestCase {
                $this->doLogin();
        }
 
-       function testParseNonexistentPage() {
+       public function testParseNonexistentPage() {
                $somePage = mt_rand();
 
                try {
index 881eb3f..d25a4c1 100644 (file)
@@ -4,6 +4,8 @@
  * @group API
  * @group Database
  * @group medium
+ *
+ * @covers ApiPurge
  */
 class ApiPurgeTest extends ApiTestCase {
 
@@ -15,7 +17,7 @@ class ApiPurgeTest extends ApiTestCase {
        /**
         * @group Broken
         */
-       function testPurgeMainPage() {
+       public function testPurgeMainPage() {
                if ( !Title::newFromText( 'UTPage' )->exists() ) {
                        $this->markTestIncomplete( "The article [[UTPage]] does not exist" );
                }
diff --git a/tests/phpunit/includes/api/ApiTest.php b/tests/phpunit/includes/api/ApiTest.php
deleted file mode 100644 (file)
index 5106be5..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-<?php
-
-/**
- * @group API
- * @group Database
- * @group medium
- */
-class ApiTest extends ApiTestCase {
-
-       function testRequireOnlyOneParameterDefault() {
-               $mock = new MockApi();
-
-               $this->assertEquals(
-                       null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
-                       "enablechunks" => false ), "filename", "enablechunks" ) );
-       }
-
-       /**
-        * @expectedException UsageException
-        */
-       function testRequireOnlyOneParameterZero() {
-               $mock = new MockApi();
-
-               $this->assertEquals(
-                       null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
-                       "enablechunks" => 0 ), "filename", "enablechunks" ) );
-       }
-
-       /**
-        * @expectedException UsageException
-        */
-       function testRequireOnlyOneParameterTrue() {
-               $mock = new MockApi();
-
-               $this->assertEquals(
-                       null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
-                       "enablechunks" => true ), "filename", "enablechunks" ) );
-       }
-
-       /**
-        * Test that the API will accept a FauxRequest and execute. The help action
-        * (default) throws a UsageException. Just validate we're getting proper XML
-        *
-        * @expectedException UsageException
-        */
-       function testApi() {
-               $api = new ApiMain(
-                       new FauxRequest( array( 'action' => 'help', 'format' => 'xml' ) )
-               );
-               $api->execute();
-               $api->getPrinter()->setBufferResult( true );
-               $api->printResult( false );
-               $resp = $api->getPrinter()->getBuffer();
-
-               libxml_use_internal_errors( true );
-               $sxe = simplexml_load_string( $resp );
-               $this->assertNotInternalType( "bool", $sxe );
-               $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
-       }
-
-       /**
-        * Test result of attempted login with an empty username
-        */
-       function testApiLoginNoName() {
-               $data = $this->doApiRequest( array( 'action' => 'login',
-                       'lgname' => '', 'lgpassword' => self::$users['sysop']->password,
-               ) );
-               $this->assertEquals( 'NoName', $data[0]['login']['result'] );
-       }
-
-       function testApiLoginBadPass() {
-               global $wgServer;
-
-               $user = self::$users['sysop'];
-               $user->user->logOut();
-
-               if ( !isset( $wgServer ) ) {
-                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
-               }
-               $ret = $this->doApiRequest( array(
-                       "action" => "login",
-                       "lgname" => $user->username,
-                       "lgpassword" => "bad",
-               ) );
-
-               $result = $ret[0];
-
-               $this->assertNotInternalType( "bool", $result );
-               $a = $result["login"]["result"];
-               $this->assertEquals( "NeedToken", $a );
-
-               $token = $result["login"]["token"];
-
-               $ret = $this->doApiRequest(
-                       array(
-                               "action" => "login",
-                               "lgtoken" => $token,
-                               "lgname" => $user->username,
-                               "lgpassword" => "badnowayinhell",
-                       ),
-                       $ret[2]
-               );
-
-               $result = $ret[0];
-
-               $this->assertNotInternalType( "bool", $result );
-               $a = $result["login"]["result"];
-
-               $this->assertEquals( "WrongPass", $a );
-       }
-
-       function testApiLoginGoodPass() {
-               global $wgServer;
-
-               if ( !isset( $wgServer ) ) {
-                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
-               }
-
-               $user = self::$users['sysop'];
-               $user->user->logOut();
-
-               $ret = $this->doApiRequest( array(
-                               "action" => "login",
-                               "lgname" => $user->username,
-                               "lgpassword" => $user->password,
-                       )
-               );
-
-               $result = $ret[0];
-               $this->assertNotInternalType( "bool", $result );
-               $this->assertNotInternalType( "null", $result["login"] );
-
-               $a = $result["login"]["result"];
-               $this->assertEquals( "NeedToken", $a );
-               $token = $result["login"]["token"];
-
-               $ret = $this->doApiRequest(
-                       array(
-                               "action" => "login",
-                               "lgtoken" => $token,
-                               "lgname" => $user->username,
-                               "lgpassword" => $user->password,
-                       ),
-                       $ret[2]
-               );
-
-               $result = $ret[0];
-
-               $this->assertNotInternalType( "bool", $result );
-               $a = $result["login"]["result"];
-
-               $this->assertEquals( "Success", $a );
-       }
-
-       /**
-        * @group Broken
-        */
-       function testApiGotCookie() {
-               $this->markTestIncomplete( "The server can't do external HTTP requests, and the internal one won't give cookies" );
-
-               global $wgServer, $wgScriptPath;
-
-               if ( !isset( $wgServer ) ) {
-                       $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
-               }
-               $user = self::$users['sysop'];
-
-               $req = MWHttpRequest::factory( self::$apiUrl . "?action=login&format=xml",
-                       array( "method" => "POST",
-                               "postData" => array(
-                                       "lgname" => $user->username,
-                                       "lgpassword" => $user->password
-                               )
-                       )
-               );
-               $req->execute();
-
-               libxml_use_internal_errors( true );
-               $sxe = simplexml_load_string( $req->getContent() );
-               $this->assertNotInternalType( "bool", $sxe );
-               $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
-               $this->assertNotInternalType( "null", $sxe->login[0] );
-
-               $a = $sxe->login[0]->attributes()->result[0];
-               $this->assertEquals( ' result="NeedToken"', $a->asXML() );
-               $token = (string)$sxe->login[0]->attributes()->token;
-
-               $req->setData( array(
-                       "lgtoken" => $token,
-                       "lgname" => $user->username,
-                       "lgpassword" => $user->password ) );
-               $req->execute();
-
-               $cj = $req->getCookieJar();
-               $serverName = parse_url( $wgServer, PHP_URL_HOST );
-               $this->assertNotEquals( false, $serverName );
-               $serializedCookie = $cj->serializeToHttpRequest( $wgScriptPath, $serverName );
-               $this->assertNotEquals( '', $serializedCookie );
-               $this->assertRegexp( '/_session=[^;]*; .*UserID=[0-9]*; .*UserName=' . $user->userName . '; .*Token=/', $serializedCookie );
-
-               return $cj;
-       }
-
-       function testRunLogin() {
-               $sysopUser = self::$users['sysop'];
-               $data = $this->doApiRequest( array(
-                       'action' => 'login',
-                       'lgname' => $sysopUser->username,
-                       'lgpassword' => $sysopUser->password ) );
-
-               $this->assertArrayHasKey( "login", $data[0] );
-               $this->assertArrayHasKey( "result", $data[0]['login'] );
-               $this->assertEquals( "NeedToken", $data[0]['login']['result'] );
-               $token = $data[0]['login']['token'];
-
-               $data = $this->doApiRequest( array(
-                       'action' => 'login',
-                       "lgtoken" => $token,
-                       "lgname" => $sysopUser->username,
-                       "lgpassword" => $sysopUser->password ), $data[2] );
-
-               $this->assertArrayHasKey( "login", $data[0] );
-               $this->assertArrayHasKey( "result", $data[0]['login'] );
-               $this->assertEquals( "Success", $data[0]['login']['result'] );
-               $this->assertArrayHasKey( 'lgtoken', $data[0]['login'] );
-
-               return $data;
-       }
-
-       function testGettingToken() {
-               foreach ( self::$users as $user ) {
-                       $this->runTokenTest( $user );
-               }
-       }
-
-       function runTokenTest( $user ) {
-               $tokens = $this->getTokenList( $user );
-
-               $rights = $user->user->getRights();
-
-               $this->assertArrayHasKey( 'edittoken', $tokens );
-               $this->assertArrayHasKey( 'movetoken', $tokens );
-
-               if ( isset( $rights['delete'] ) ) {
-                       $this->assertArrayHasKey( 'deletetoken', $tokens );
-               }
-
-               if ( isset( $rights['block'] ) ) {
-                       $this->assertArrayHasKey( 'blocktoken', $tokens );
-                       $this->assertArrayHasKey( 'unblocktoken', $tokens );
-               }
-
-               if ( isset( $rights['protect'] ) ) {
-                       $this->assertArrayHasKey( 'protecttoken', $tokens );
-               }
-
-               return $tokens;
-       }
-}
index 94ef9c6..ad297dd 100644 (file)
@@ -117,7 +117,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
         * @param $params Array: key-value API params
         * @param $session Array|null: session array
         * @param $user User|null A User object for the context
-        * @return result of the API call
+        * @return mixed result of the API call
         * @throws Exception in case wsToken is not set in the session
         */
        protected function doApiRequestWithToken( array $params, array $session = null, User $user = null ) {
@@ -188,66 +188,3 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                );
        }
 }
-
-class UserWrapper {
-       public $userName;
-       public $password;
-       public $user;
-
-       public function __construct( $userName, $password, $group = '' ) {
-               $this->userName = $userName;
-               $this->password = $password;
-
-               $this->user = User::newFromName( $this->userName );
-               if ( !$this->user->getID() ) {
-                       $this->user = User::createNew( $this->userName, array(
-                               "email" => "test@example.com",
-                               "real_name" => "Test User" ) );
-               }
-               $this->user->setPassword( $this->password );
-
-               if ( $group !== '' ) {
-                       $this->user->addGroup( $group );
-               }
-               $this->user->saveSettings();
-       }
-}
-
-class MockApi extends ApiBase {
-       public function execute() {
-       }
-
-       public function getVersion() {
-       }
-
-       public function __construct() {
-       }
-
-       public function getAllowedParams() {
-               return array(
-                       'filename' => null,
-                       'enablechunks' => false,
-                       'sessionkey' => null,
-               );
-       }
-}
-
-class ApiTestContext extends RequestContext {
-
-       /**
-        * Returns a DerivativeContext with the request variables in place
-        *
-        * @param $request WebRequest request object including parameters and session
-        * @param $user User or null
-        * @return DerivativeContext
-        */
-       public function newTestContext( WebRequest $request, User $user = null ) {
-               $context = new DerivativeContext( $this );
-               $context->setRequest( $request );
-               if ( $user !== null ) {
-                       $context->setUser( $user );
-               }
-
-               return $context;
-       }
-}
index 7e18b6e..42f02fa 100644 (file)
@@ -29,7 +29,10 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
 
        /**
         * Helper function -- remove files and associated articles by Title
-        * @param $title Title: title to be removed
+        *
+        * @param Title $title title to be removed
+        *
+        * @return bool
         */
        public function deleteFileByTitle( $title ) {
                if ( $title->exists() ) {
@@ -53,7 +56,10 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
 
        /**
         * Helper function -- remove files and associated articles with a particular filename
-        * @param $fileName String: filename to be removed
+        *
+        * @param string $fileName filename to be removed
+        *
+        * @return bool
         */
        public function deleteFileByFileName( $fileName ) {
                return $this->deleteFileByTitle( Title::newFromText( $fileName, NS_FILE ) );
@@ -61,7 +67,10 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
 
        /**
         * Helper function -- given a file on the filesystem, find matching content in the db (and associated articles) and remove them.
-        * @param $filePath String: path to file on the filesystem
+        *
+        * @param string $filePath path to file on the filesystem
+        *
+        * @return bool
         */
        public function deleteFileByContent( $filePath ) {
                $hash = FSFile::getSha1Base36FromPath( $filePath );
@@ -77,10 +86,14 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
        /**
         * Fake an upload by dumping the file into temp space, and adding info to $_FILES.
         * (This is what PHP would normally do).
-        * @param $fieldName String: name this would have in the upload form
-        * @param $fileName String: name to title this
-        * @param $type String: mime type
-        * @param $filePath String: path where to find file contents
+        *
+        * @param string $fieldName name this would have in the upload form
+        * @param string $fileName name to title this
+        * @param string $type mime type
+        * @param string $filePath path where to find file contents
+        *
+        * @throws Exception
+        * @return bool
         */
        function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) {
                $tmpName = tempnam( wfTempDir(), "" );
diff --git a/tests/phpunit/includes/api/ApiTestContext.php b/tests/phpunit/includes/api/ApiTestContext.php
new file mode 100644 (file)
index 0000000..80d7ea6
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+class ApiTestContext extends RequestContext {
+
+       /**
+        * Returns a DerivativeContext with the request variables in place
+        *
+        * @param $request WebRequest request object including parameters and session
+        * @param $user User or null
+        * @return DerivativeContext
+        */
+       public function newTestContext( WebRequest $request, User $user = null ) {
+               $context = new DerivativeContext( $this );
+               $context->setRequest( $request );
+               if ( $user !== null ) {
+                       $context->setUser( $user );
+               }
+
+               return $context;
+       }
+}
diff --git a/tests/phpunit/includes/api/ApiTokensTest.php b/tests/phpunit/includes/api/ApiTokensTest.php
new file mode 100644 (file)
index 0000000..fbe9789
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ *
+ * @covers ApiTokens
+ */
+class ApiTokensTest extends ApiTestCase {
+
+       public function testGettingToken() {
+               foreach ( self::$users as $user ) {
+                       $this->runTokenTest( $user );
+               }
+       }
+
+       protected function runTokenTest( $user ) {
+               $tokens = $this->getTokenList( $user );
+
+               $rights = $user->user->getRights();
+
+               $this->assertArrayHasKey( 'edittoken', $tokens );
+               $this->assertArrayHasKey( 'movetoken', $tokens );
+
+               if ( isset( $rights['delete'] ) ) {
+                       $this->assertArrayHasKey( 'deletetoken', $tokens );
+               }
+
+               if ( isset( $rights['block'] ) ) {
+                       $this->assertArrayHasKey( 'blocktoken', $tokens );
+                       $this->assertArrayHasKey( 'unblocktoken', $tokens );
+               }
+
+               if ( isset( $rights['protect'] ) ) {
+                       $this->assertArrayHasKey( 'protecttoken', $tokens );
+               }
+       }
+
+}
diff --git a/tests/phpunit/includes/api/ApiUnblockTest.php b/tests/phpunit/includes/api/ApiUnblockTest.php
new file mode 100644 (file)
index 0000000..2c2370a
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ *
+ * @covers ApiUnblock
+ */
+class ApiUnblockTest extends ApiTestCase {
+       protected function setUp() {
+               parent::setUp();
+               $this->doLogin();
+       }
+
+       /**
+        * @expectedException UsageException
+        */
+       public function testWithNoToken( ) {
+               $this->doApiRequest(
+                       array(
+                               'action' => 'unblock',
+                               'user' => 'UTApiBlockee',
+                               'reason' => 'Some reason',
+                       ),
+                       null,
+                       false,
+                       self::$users['sysop']->user
+               );
+       }
+}
index ae3a5e9..ba7fb25 100644 (file)
@@ -3,6 +3,7 @@
 /**
  * @group API
  * @group Database
+ * @group medium
  */
 
 /**
@@ -31,7 +32,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
         * Testing login
         * XXX this is a funny way of getting session context
         */
-       function testLogin() {
+       public function testLogin() {
                $user = self::$users['uploader'];
 
                $params = array(
@@ -95,7 +96,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertTrue( $exception, "Got exception" );
        }
 
-
        /**
         * @depends testLogin
         */
@@ -110,6 +110,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        $this->markTestIncomplete( $e->getMessage() );
                }
 
+               /** @var array $filePaths */
                $filePath = $filePaths[0];
                $fileSize = filesize( $filePath );
                $fileName = basename( $filePath );
@@ -147,7 +148,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
                unlink( $filePath );
        }
 
-
        /**
         * @depends testLogin
         */
@@ -185,7 +185,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
                unlink( $filePath );
        }
 
-
        /**
         * @depends testLogin
         */
@@ -201,6 +200,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                }
 
                // we'll reuse this filename
+               /** @var array $filePaths */
                $fileName = basename( $filePaths[0] );
 
                // clear any other files with the same name
@@ -257,7 +257,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
                unlink( $filePaths[1] );
        }
 
-
        /**
         * @depends testLogin
         */
@@ -272,6 +271,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        $this->markTestIncomplete( $e->getMessage() );
                }
 
+               /** @var array $filePaths */
                $fileNames[0] = basename( $filePaths[0] );
                $fileNames[1] = "SameContentAs" . $fileNames[0];
 
@@ -356,6 +356,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                        $this->markTestIncomplete( $e->getMessage() );
                }
 
+               /** @var array $filePaths */
                $filePath = $filePaths[0];
                $fileSize = filesize( $filePath );
                $fileName = basename( $filePath );
index 8253989..028ea9f 100644 (file)
@@ -18,7 +18,7 @@ class ApiWatchTest extends ApiTestCase {
 
        /**
         */
-       function testWatchEdit() {
+       public function testWatchEdit() {
                $tokens = $this->getTokens();
 
                $data = $this->doApiRequest( array(
@@ -37,7 +37,7 @@ class ApiWatchTest extends ApiTestCase {
        /**
         * @depends testWatchEdit
         */
-       function testWatchClear() {
+       public function testWatchClear() {
                $tokens = $this->getTokens();
 
                $data = $this->doApiRequest( array(
@@ -67,7 +67,7 @@ class ApiWatchTest extends ApiTestCase {
 
        /**
         */
-       function testWatchProtect() {
+       public function testWatchProtect() {
                $tokens = $this->getTokens();
 
                $data = $this->doApiRequest( array(
@@ -85,7 +85,7 @@ class ApiWatchTest extends ApiTestCase {
 
        /**
         */
-       function testGetRollbackToken() {
+       public function testGetRollbackToken() {
                $this->getTokens();
 
                if ( !Title::newFromText( 'Help:UTPage' )->exists() ) {
@@ -121,7 +121,7 @@ class ApiWatchTest extends ApiTestCase {
         *
         * @depends testGetRollbackToken
         */
-       function testWatchRollback( $data ) {
+       public function testWatchRollback( $data ) {
                $keys = array_keys( $data[0]['query']['pages'] );
                $key = array_pop( $keys );
                $pageinfo = $data[0]['query']['pages'][$key];
diff --git a/tests/phpunit/includes/api/MockApi.php b/tests/phpunit/includes/api/MockApi.php
new file mode 100644 (file)
index 0000000..d94aa2c
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+class MockApi extends ApiBase {
+       public function execute() {
+       }
+
+       public function getVersion() {
+       }
+
+       public function __construct() {
+       }
+
+       public function getAllowedParams() {
+               return array(
+                       'filename' => null,
+                       'enablechunks' => false,
+                       'sessionkey' => null,
+               );
+       }
+}
index d9be85e..a1fc2c2 100644 (file)
@@ -6,6 +6,7 @@
  * @group API
  */
 class PrefixUniquenessTest extends MediaWikiTestCase {
+
        public function testPrefixes() {
                $main = new ApiMain( new FauxRequest() );
                $query = new ApiQuery( $main, 'foo', 'bar' );
@@ -13,6 +14,7 @@ class PrefixUniquenessTest extends MediaWikiTestCase {
                $prefixes = array();
 
                foreach ( $modules as $name => $class ) {
+                       /** @var ApiMain $module */
                        $module = new $class( $main, $name );
                        $prefix = $module->getModulePrefix();
                        if ( isset( $prefixes[$prefix] ) ) {
index 59756b2..1d534ee 100644 (file)
@@ -66,7 +66,6 @@ class RandomImageGenerator {
                )
        );
 
-
        public function __construct( $options = array() ) {
                foreach ( array( 'dictionaryFile', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'shapesToDraw' ) as $property ) {
                        if ( isset( $options[$property] ) ) {
@@ -112,10 +111,13 @@ class RandomImageGenerator {
                return $filenames;
        }
 
-
        /**
         * Figure out how we write images. This is a factor of both format and the local system
-        * @param $format (a typical extension like 'svg', 'jpg', etc.)
+        *
+        * @param string $format (a typical extension like 'svg', 'jpg', etc.)
+        *
+        * @throws Exception
+        * @return string
         */
        function getImageWriteMethod( $format ) {
                global $wgUseImageMagick, $wgImageMagickConvertCommand;
@@ -159,7 +161,6 @@ class RandomImageGenerator {
                return $filenames;
        }
 
-
        /**
         * Generate data representing an image of random size (within limits),
         * consisting of randomly colored and sized upward pointing triangles against a random background color
@@ -222,9 +223,12 @@ class RandomImageGenerator {
        /**
         * Based on image specification, write a very simple SVG file to disk.
         * Ignores the background spec because transparency is cool. :)
-        * @param $spec: spec describing background and shapes to draw
-        * @param $format: file format to write (which is obviously always svg here)
-        * @param $filename: filename to write to
+        *
+        * @param array $spec spec describing background and shapes to draw
+        * @param string $format file format to write (which is obviously always svg here)
+        * @param string $filename filename to write to
+        *
+        * @throws Exception
         */
        public function writeSvg( $spec, $format, $filename ) {
                $svg = new SimpleXmlElement( '<svg/>' );
@@ -250,9 +254,9 @@ class RandomImageGenerator {
 
        /**
         * Based on an image specification, write such an image to disk, using Imagick PHP extension
-        * @param $spec: spec describing background and circles to draw
-        * @param $format: file format to write
-        * @param $filename: filename to write to
+        * @param array $spec spec describing background and circles to draw
+        * @param string $format file format to write
+        * @param string $filename filename to write to
         */
        public function writeImageWithApi( $spec, $format, $filename ) {
                // this is a hack because I can't get setImageOrientation() to work. See below.
@@ -307,7 +311,7 @@ class RandomImageGenerator {
         * This is used when simulating a rotated image capture with Exif orientation
         * @param $spec Object returned by getImageSpec
         * @param $matrix 2x2 transformation matrix
-        * @return transformed Spec
+        * @return array transformed Spec
         */
        private static function rotateImageSpec( &$spec, $matrix ) {
                $tSpec = array();
@@ -355,7 +359,6 @@ class RandomImageGenerator {
                );
        }
 
-
        /**
         * Based on an image specification, write such an image to disk, using the command line ImageMagick program ('convert').
         *
@@ -365,9 +368,12 @@ class RandomImageGenerator {
         *   -draw 'fill rgb(99,123,231) circle 59,39 56,57' \
         *   -draw 'fill rgb(240,12,32)  circle 50,21 50,3'  filename.png
         *
-        * @param $spec: spec describing background and shapes to draw
-        * @param $format: file format to write (unused by this method but kept so it has the same signature as writeImageWithApi)
-        * @param $filename: filename to write to
+        * @param array $spec spec describing background and shapes to draw
+        * @param string $format file format to write (unused by this method but kept so it has the same signature as
+        * writeImageWithApi)
+        * @param string $filename filename to write to
+        *
+        * @return bool
         */
        public function writeImageWithCommandLine( $spec, $format, $filename ) {
                global $wgImageMagickConvertCommand;
@@ -392,7 +398,7 @@ class RandomImageGenerator {
        /**
         * Generate a string of random colors for ImageMagick or SVG, like "rgb(12, 37, 98)"
         *
-        * @return {String}
+        * @return string
         */
        public function getRandomColor() {
                $components = array();
@@ -426,8 +432,10 @@ class RandomImageGenerator {
         *
         * Will throw exception if the file could not be read or if it had fewer lines than requested.
         *
-        * @param $number_desired Integer: number of lines desired
-        * @return Array: of exactly n elements, drawn randomly from lines the file
+        * @param int $number_desired number of lines desired
+        *
+        * @throws Exception
+        * @return array of exactly n elements, drawn randomly from lines the file
         */
        private function getRandomLines( $number_desired ) {
                $filepath = $this->dictionaryFile;
diff --git a/tests/phpunit/includes/api/UserWrapper.php b/tests/phpunit/includes/api/UserWrapper.php
new file mode 100644 (file)
index 0000000..f8da0ff
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+
+class UserWrapper {
+       public $userName;
+       public $password;
+       public $user;
+
+       public function __construct( $userName, $password, $group = '' ) {
+               $this->userName = $userName;
+               $this->password = $password;
+
+               $this->user = User::newFromName( $this->userName );
+               if ( !$this->user->getID() ) {
+                       $this->user = User::createNew( $this->userName, array(
+                               "email" => "test@example.com",
+                               "real_name" => "Test User" ) );
+               }
+               $this->user->setPassword( $this->password );
+
+               if ( $group !== '' ) {
+                       $this->user->addGroup( $group );
+               }
+               $this->user->saveSettings();
+       }
+}
diff --git a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
new file mode 100644 (file)
index 0000000..c71faec
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ * @covers ApiFormatJson
+ */
+class ApiFormatJsonTest extends ApiFormatTestBase {
+
+       public function testValidSyntax( ) {
+               $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+
+               $this->assertInternalType( 'array', json_decode( $data, true ) );
+               $this->assertGreaterThan( 0, count( (array)$data ) );
+       }
+}
index 802a0e1..759dfc7 100644 (file)
@@ -4,11 +4,11 @@
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiFormatPhp
  */
 class ApiFormatPhpTest extends ApiFormatTestBase {
 
-       function testValidPhpSyntax() {
-
+       public function testValidyntax( ) {
                $data = $this->apiRequest( 'php', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
 
                $this->assertInternalType( 'array', unserialize( $data ) );
index 153f2cf..24d8cb8 100644 (file)
@@ -1,9 +1,18 @@
 <?php
 
 abstract class ApiFormatTestBase extends ApiTestCase {
+
+       /**
+        * @param string $format
+        * @param array $params
+        * @param $data
+        *
+        * @return string
+        */
        protected function apiRequest( $format, $params, $data = null ) {
                $data = parent::doApiRequest( $params, $data, true );
 
+               /** @var ApiMain $module */
                $module = $data[3];
 
                $printer = $module->createPrinterByName( $format );
@@ -19,4 +28,5 @@ abstract class ApiFormatTestBase extends ApiTestCase {
 
                return $out;
        }
+
 }
diff --git a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
new file mode 100644 (file)
index 0000000..d075f54
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @group medium
+ * @covers ApiFormatWddx
+ */
+class ApiFormatWddxTest extends ApiFormatTestBase {
+
+       /**
+        * @requires function wddx_deserialize
+        */
+       public function testValidSyntax( ) {
+               $data = $this->apiRequest( 'wddx', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+
+               $this->assertInternalType( 'array', wddx_deserialize( $data ) );
+               $this->assertGreaterThan( 0, count( (array)$data ) );
+       }
+}
index 1a2aa83..9c5b3ca 100644 (file)
@@ -1,6 +1,5 @@
 <?php
 /**
- *
  *
  * Created on Feb 6, 2013
  *
 
 require_once 'ApiQueryTestBase.php';
 
-/** These tests validate basic functionality of the api query module
+/**
+ * These tests validate basic functionality of the api query module
  *
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiQuery
  */
 class ApiQueryBasicTest extends ApiQueryTestBase {
+       protected $exceptionFromAddDBData;
+
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
         * @see MediaWikiTestCase::addDBData()
@@ -128,6 +131,7 @@ class ApiQueryBasicTest extends ApiQueryTestBase {
                ) )
        );
 
+       // Although this appears to have no use it is used by testLists()
        private static $allcategories = array(
                array( 'list' => 'allcategories', 'acprefix' => 'AQBT-' ),
                array( 'allcategories' => array(
@@ -234,6 +238,7 @@ class ApiQueryBasicTest extends ApiQueryTestBase {
                $this->check( self::$alllinks );
                $this->check( self::$alltransclusions );
                // This test is temporarily disabled until a sqlite bug is fixed
+               // Confirmed still broken 15-nov-2013
                // $this->check( self::$allcategories );
                $this->check( self::$backlinks );
                $this->check( self::$embeddedin );
@@ -365,29 +370,30 @@ class ApiQueryBasicTest extends ApiQueryTestBase {
 
        /**
         * Recursively compare arrays, ignoring mismatches in numeric key and pageids.
-        * @param $expected array expected values
-        * @param $result array returned values
+        *
+        * @param $expectedArray array expected values
+        * @param $resultArray array returned values
         */
-       private function assertQueryResults( $expected, $result ) {
-               reset( $expected );
-               reset( $result );
+       private function assertQueryResults( $expectedArray, $resultArray ) {
+               reset( $expectedArray );
+               reset( $resultArray );
                while ( true ) {
-                       $e = each( $expected );
-                       $r = each( $result );
+                       $expectedValue = each( $expectedArray );
+                       $resultValue = each( $resultArray );
                        // If either of the arrays is shorter, abort. If both are done, success.
-                       $this->assertEquals( (bool)$e, (bool)$r );
-                       if ( !$e ) {
+                       $this->assertEquals( (bool)$expectedValue, (bool)$resultValue );
+                       if ( !$expectedValue ) {
                                break; // done
                        }
                        // continue only if keys are identical or both keys are numeric
-                       $this->assertTrue( $e['key'] === $r['key'] || ( is_numeric( $e['key'] ) && is_numeric( $r['key'] ) ) );
+                       $this->assertTrue( $expectedValue['key'] === $resultValue['key'] || ( is_numeric( $expectedValue['key'] ) && is_numeric( $resultValue['key'] ) ) );
                        // don't compare pageids
-                       if ( $e['key'] !== 'pageid' ) {
+                       if ( $expectedValue['key'] !== 'pageid' ) {
                                // If values are arrays, compare recursively, otherwise compare with ===
-                               if ( is_array( $e['value'] ) && is_array( $r['value'] ) ) {
-                                       $this->assertQueryResults( $e['value'], $r['value'] );
+                               if ( is_array( $expectedValue['value'] ) && is_array( $resultValue['value'] ) ) {
+                                       $this->assertQueryResults( $expectedValue['value'], $resultValue['value'] );
                                } else {
-                                       $this->assertEquals( $e['value'], $r['value'] );
+                                       $this->assertEquals( $expectedValue['value'], $resultValue['value'] );
                                }
                        }
                }
index 4d5ddba..347cd6f 100644 (file)
@@ -24,8 +24,11 @@ require_once 'ApiQueryContinueTestBase.php';
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiQuery
  */
 class ApiQueryContinue2Test extends ApiQueryContinueTestBase {
+       protected $exceptionFromAddDBData;
+
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
         * @see MediaWikiTestCase::addDBData()
index f494e9c..0379790 100644 (file)
@@ -28,8 +28,11 @@ require_once 'ApiQueryContinueTestBase.php';
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiQuery
  */
 class ApiQueryContinueTest extends ApiQueryContinueTestBase {
+       protected $exceptionFromAddDBData;
+
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
         * @see MediaWikiTestCase::addDBData()
index fbb1e64..e7203c9 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * Created on Jan 1, 2013
  *
  * Copyright © 2013 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
@@ -112,6 +110,9 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
                } while ( true );
        }
 
+       /**
+        * @param array $data
+        */
        private function printResult( $data ) {
                $q = $data['query'];
                $print = array();
@@ -151,7 +152,8 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
        private static function GetItems( $q, $moduleName, $name, &$print ) {
                if ( isset( $q[$moduleName] ) ) {
                        $print[] = "*$name/[" . implode( ',',
-                               array_map( function ( $v ) {
+                               array_map(
+                                       function ( $v ) {
                                                return $v['title'];
                                        },
                                        $q[$moduleName] ) ) . ']';
index 7f5fe91..74ceff9 100644 (file)
@@ -4,13 +4,14 @@
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiQueryRevisions
  */
 class ApiQueryRevisionsTest extends ApiTestCase {
 
        /**
         * @group medium
         */
-       function testContentComesWithContentModelAndFormat() {
+       public function testContentComesWithContentModelAndFormat() {
                $pageName = 'Help:' . __METHOD__;
                $title = Title::newFromText( $pageName );
                $page = WikiPage::factory( $title );
index bc01ec2..2ec5fe3 100644 (file)
@@ -4,6 +4,7 @@
  * @group API
  * @group Database
  * @group medium
+ * @covers ApiQuery
  */
 class ApiQueryTest extends ApiTestCase {
 
@@ -12,7 +13,7 @@ class ApiQueryTest extends ApiTestCase {
                $this->doLogin();
        }
 
-       function testTitlesGetNormalized() {
+       public function testTitlesGetNormalized() {
 
                global $wgMetaNamespace;
 
@@ -43,7 +44,7 @@ class ApiQueryTest extends ApiTestCase {
                );
        }
 
-       function testTitlesAreRejectedIfInvalid() {
+       public function testTitlesAreRejectedIfInvalid() {
                $title = false;
                while ( !$title || Title::newFromText( $title )->exists() ) {
                        $title = md5( mt_rand( 0, 10000 ) + rand( 0, 999000 ) );
index 8ee8ea9..9cfab41 100644 (file)
@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * Created on Feb 10, 2013
  *
  * Copyright © 2013 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
index 2ac2942..ce2db5d 100644 (file)
@@ -48,7 +48,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         * @dataProvider provideUserGenders
         * @covers GenderCache::getGenderOf
         */
-       function testUserName( $username, $expectedGender ) {
+       public function testUserName( $username, $expectedGender ) {
                $genderCache = GenderCache::singleton();
                $gender = $genderCache->getGenderOf( $username );
                $this->assertEquals( $gender, $expectedGender, "GenderCache normal" );
@@ -60,7 +60,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         * @dataProvider provideUserGenders
         * @covers GenderCache::getGenderOf
         */
-       function testUserObjects( $username, $expectedGender ) {
+       public function testUserObjects( $username, $expectedGender ) {
                $genderCache = GenderCache::singleton();
                $user = User::newFromName( $username );
                $gender = $genderCache->getGenderOf( $user );
@@ -86,7 +86,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
         * @dataProvider provideStripSubpages
         * @covers GenderCache::getGenderOf
         */
-       function testStripSubpages( $pageWithSubpage, $expectedGender ) {
+       public function testStripSubpages( $pageWithSubpage, $expectedGender ) {
                $genderCache = GenderCache::singleton();
                $gender = $genderCache->getGenderOf( $pageWithSubpage );
                $this->assertEquals( $gender, $expectedGender, "GenderCache must strip of subpages" );
index 3559f15..803acf7 100644 (file)
@@ -84,7 +84,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
         *
         * @dataProvider provideMessagesForFallback
         */
-       function testMessageFallbacks( $message, $lang, $expectedContent ) {
+       public function testMessageFallbacks( $message, $lang, $expectedContent ) {
                $result = MessageCache::singleton()->get( $message, true, $lang );
                $this->assertEquals( $expectedContent, $result, "Message fallback failed." );
        }
@@ -112,7 +112,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
         *
         * @dataProvider provideMessagesForFullKeys
         */
-       function testFullKeyBehaviour( $message, $lang, $expectedContent ) {
+       public function testFullKeyBehaviour( $message, $lang, $expectedContent ) {
                $result = MessageCache::singleton()->get( $message, true, $lang, true );
                $this->assertEquals( $expectedContent, $result, "Full key message fallback failed." );
        }
index 1c81ea7..d3793d8 100644 (file)
@@ -59,7 +59,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
        /**
         * Highlight diff between assertEquals and assertNotSame
         */
-       function testPhpUnitArrayEquality() {
+       public function testPhpUnitArrayEquality() {
                $one = array( 'A' => 1, 'B' => 2 );
                $two = array( 'B' => 2, 'A' => 1 );
                $this->assertEquals( $one, $two ); // ==
@@ -70,7 +70,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
         * @dataProvider provideInvalidConstructorArg
         * @expectedException MWException
         */
-       function testConstructorGivenInvalidValue( $maxSize ) {
+       public function testConstructorGivenInvalidValue( $maxSize ) {
                new ProcessCacheLRUTestable( $maxSize );
        }
 
@@ -88,7 +88,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
                );
        }
 
-       function testAddAndGetAKey() {
+       public function testAddAndGetAKey() {
                $oneCache = new ProcessCacheLRUTestable( 1 );
                $this->assertCacheEmpty( $oneCache );
 
@@ -99,7 +99,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
                $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
        }
 
-       function testDeleteOldKey() {
+       public function testDeleteOldKey() {
                $oneCache = new ProcessCacheLRUTestable( 1 );
                $this->assertCacheEmpty( $oneCache );
 
@@ -117,7 +117,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
         * @param $cacheMaxEntries Maximum entry the created cache will hold
         * @param $entryToFill Number of entries to insert in the created cache.
         */
-       function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
+       public function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
                $cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
                $this->fillCache( $cache, $entryToFill );
 
@@ -145,7 +145,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
         * Create a cache with only one remaining entry then update
         * the first inserted entry. Should bump it to the top.
         */
-       function testReplaceExistingKeyShouldBumpEntryToTop() {
+       public function testReplaceExistingKeyShouldBumpEntryToTop() {
                $maxEntries = 3;
 
                $cache = new ProcessCacheLRUTestable( $maxEntries );
@@ -164,7 +164,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
                );
        }
 
-       function testRecentlyAccessedKeyStickIn() {
+       public function testRecentlyAccessedKeyStickIn() {
                $cache = new ProcessCacheLRUTestable( 2 );
                $cache->set( 'first', 'prop1', 'value1' );
                $cache->set( 'second', 'prop2', 'value2' );
@@ -183,7 +183,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
         * Given a cache having 1,2,3 as key, updating 2 should bump 2 to
         * the top of the queue with the new value: 1,3,2* (* = updated).
         */
-       function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
+       public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
                $maxEntries = 3;
 
                $cache = new ProcessCacheLRUTestable( $maxEntries );
@@ -204,7 +204,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
                );
        }
 
-       function testBumpExistingKeyToTop() {
+       public function testBumpExistingKeyToTop() {
                $cache = new ProcessCacheLRUTestable( 3 );
                $this->fillCache( $cache, 3 );
 
diff --git a/tests/phpunit/includes/changes/RecentChangeTest.php b/tests/phpunit/includes/changes/RecentChangeTest.php
new file mode 100644 (file)
index 0000000..cfa3e77
--- /dev/null
@@ -0,0 +1,280 @@
+<?php
+/**
+ * @group Database
+ */
+class RecentChangeTest extends MediaWikiTestCase {
+       protected $title;
+       protected $target;
+       protected $user;
+       protected $user_comment;
+       protected $context;
+
+       public function __construct() {
+               parent::__construct();
+
+               $this->title = Title::newFromText( 'SomeTitle' );
+               $this->target = Title::newFromText( 'TestTarget' );
+               $this->user = User::newFromName( 'UserName' );
+
+               $this->user_comment = '<User comment about action>';
+               $this->context = RequestContext::newExtraneousContext( $this->title );
+       }
+
+       /**
+        * The testIrcMsgForAction* tests are supposed to cover the hacky
+        * LogFormatter::getIRCActionText / bug 34508
+        *
+        * Third parties bots listen to those messages. They are clever enough
+        * to fetch the i18n messages from the wiki and then analyze the IRC feed
+        * to reverse engineer the $1, $2 messages.
+        * One thing bots can not detect is when MediaWiki change the meaning of
+        * a message like what happened when we deployed 1.19. $1 became the user
+        * performing the action which broke basically all bots around.
+        *
+        * Should cover the following log actions (which are most commonly used by bots):
+        * - block/block
+        * - block/unblock
+        * - delete/delete
+        * - delete/restore
+        * - newusers/create
+        * - newusers/create2
+        * - newusers/autocreate
+        * - move/move
+        * - move/move_redir
+        * - protect/protect
+        * - protect/modifyprotect
+        * - protect/unprotect
+        * - upload/upload
+        *
+        * As well as the following Auto Edit Summaries:
+        * - blank
+        * - replace
+        * - rollback
+        * - undo
+        */
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeBlock() {
+               $sep = $this->context->msg( 'colon-separator' )->text();
+
+               # block/block
+               $this->assertIRCComment(
+                       $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'block', 'block',
+                       array(),
+                       $this->user_comment
+               );
+               # block/unblock
+               $this->assertIRCComment(
+                       $this->context->msg( 'unblocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'block', 'unblock',
+                       array(),
+                       $this->user_comment
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeDelete() {
+               $sep = $this->context->msg( 'colon-separator' )->text();
+
+               # delete/delete
+               $this->assertIRCComment(
+                       $this->context->msg( 'deletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'delete', 'delete',
+                       array(),
+                       $this->user_comment
+               );
+
+               # delete/restore
+               $this->assertIRCComment(
+                       $this->context->msg( 'undeletedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'delete', 'restore',
+                       array(),
+                       $this->user_comment
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeNewusers() {
+               $this->assertIRCComment(
+                       'New user account',
+                       'newusers', 'newusers',
+                       array()
+               );
+               $this->assertIRCComment(
+                       'New user account',
+                       'newusers', 'create',
+                       array()
+               );
+               $this->assertIRCComment(
+                       'created new account SomeTitle',
+                       'newusers', 'create2',
+                       array()
+               );
+               $this->assertIRCComment(
+                       'Account created automatically',
+                       'newusers', 'autocreate',
+                       array()
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeMove() {
+               $move_params = array(
+                       '4::target' => $this->target->getPrefixedText(),
+                       '5::noredir' => 0,
+               );
+               $sep = $this->context->msg( 'colon-separator' )->text();
+
+               # move/move
+               $this->assertIRCComment(
+                       $this->context->msg( '1movedto2', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
+                       'move', 'move',
+                       $move_params,
+                       $this->user_comment
+               );
+
+               # move/move_redir
+               $this->assertIRCComment(
+                       $this->context->msg( '1movedto2_redir', 'SomeTitle', 'TestTarget' )->plain() . $sep . $this->user_comment,
+                       'move', 'move_redir',
+                       $move_params,
+                       $this->user_comment
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypePatrol() {
+               # patrol/patrol
+               $this->assertIRCComment(
+                       $this->context->msg( 'patrol-log-line', 'revision 777', '[[SomeTitle]]', '' )->plain(),
+                       'patrol', 'patrol',
+                       array(
+                               '4::curid' => '777',
+                               '5::previd' => '666',
+                               '6::auto' => 0,
+                       )
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeProtect() {
+               $protectParams = array(
+                       '[edit=sysop] (indefinite) ‎[move=sysop] (indefinite)'
+               );
+               $sep = $this->context->msg( 'colon-separator' )->text();
+
+               # protect/protect
+               $this->assertIRCComment(
+                       $this->context->msg( 'protectedarticle', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
+                       'protect', 'protect',
+                       $protectParams,
+                       $this->user_comment
+               );
+
+               # protect/unprotect
+               $this->assertIRCComment(
+                       $this->context->msg( 'unprotectedarticle', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'protect', 'unprotect',
+                       array(),
+                       $this->user_comment
+               );
+
+               # protect/modify
+               $this->assertIRCComment(
+                       $this->context->msg( 'modifiedarticleprotection', 'SomeTitle ' . $protectParams[0] )->plain() . $sep . $this->user_comment,
+                       'protect', 'modify',
+                       $protectParams,
+                       $this->user_comment
+               );
+       }
+
+       /**
+        * @covers LogFormatter::getIRCActionText
+        */
+       public function testIrcMsgForLogTypeUpload() {
+               $sep = $this->context->msg( 'colon-separator' )->text();
+
+               # upload/upload
+               $this->assertIRCComment(
+                       $this->context->msg( 'uploadedimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'upload', 'upload',
+                       array(),
+                       $this->user_comment
+               );
+
+               # upload/overwrite
+               $this->assertIRCComment(
+                       $this->context->msg( 'overwroteimage', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+                       'upload', 'overwrite',
+                       array(),
+                       $this->user_comment
+               );
+       }
+
+       /**
+        * @todo Emulate these edits somehow and extract
+        * raw edit summary from RecentChange object
+        * --
+        */
+       /*
+       public function testIrcMsgForBlankingAES() {
+               // $this->context->msg( 'autosumm-blank', .. );
+       }
+
+       public function testIrcMsgForReplaceAES() {
+               // $this->context->msg( 'autosumm-replace', .. );
+       }
+
+       public function testIrcMsgForRollbackAES() {
+               // $this->context->msg( 'revertpage', .. );
+       }
+
+       public function testIrcMsgForUndoAES() {
+               // $this->context->msg( 'undo-summary', .. );
+       }
+       */
+
+       /**
+        * @param $expected String Expected IRC text without colors codes
+        * @param $type String Log type (move, delete, suppress, patrol ...)
+        * @param $action String A log type action
+        * @param $params
+        * @param $comment String (optional) A comment for the log action
+        * @param $msg String (optional) A message for PHPUnit :-)
+        */
+       protected function assertIRCComment( $expected, $type, $action, $params, $comment = null, $msg = '' ) {
+
+               $logEntry = new ManualLogEntry( $type, $action );
+               $logEntry->setPerformer( $this->user );
+               $logEntry->setTarget( $this->title );
+               if ( $comment !== null ) {
+                       $logEntry->setComment( $comment );
+               }
+               $logEntry->setParameters( $params );
+
+               $formatter = LogFormatter::newFromEntry( $logEntry );
+               $formatter->setContext( $this->context );
+
+               // Apply the same transformation as done in IRCColourfulRCFeedFormatter::getLine for rc_comment
+               $ircRcComment = IRCColourfulRCFeedFormatter::cleanupForIRC( $formatter->getIRCActionComment() );
+
+               $this->assertEquals(
+                       $expected,
+                       $ircRcComment,
+                       $msg
+               );
+       }
+}
index aedf594..d1c214a 100644 (file)
@@ -10,7 +10,7 @@
  */
 class ContentHandlerTest extends MediaWikiTestCase {
 
-       public function setUp() {
+       protected function setUp() {
                global $wgContLang;
                parent::setUp();
 
@@ -38,7 +38,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
                $wgContLang->resetNamespaces();
        }
 
-       public function tearDown() {
+       protected function tearDown() {
                global $wgContLang;
 
                // Reset namespace cache
index 75a7278..73b975b 100644 (file)
@@ -10,7 +10,7 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
         */
        var $handler;
 
-       public function setUp() {
+       protected function setUp() {
                parent::setUp();
 
                $this->handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
@@ -79,6 +79,8 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
                global $wgContLang;
                $wgContLang->resetNamespaces();
 
+               MagicWord::clearCache();
+
                if ( is_string( $title ) ) {
                        $title = Title::newFromText( $title );
                }
index 9f20073..1d133f3 100644 (file)
@@ -245,26 +245,6 @@ just a test"
                );
        }
 
-       /**
-        * @todo Test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo Test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
        public static function dataIsCountable() {
                return array(
                        array( '',
index 7d7a2bd..16dac94 100644 (file)
  */
 class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
        // From DatabaseBase
+       function __construct() {}
        protected function closeConnection() {}
        protected function doQuery( $sql ) {}
 
        // From DatabaseMysql
        protected function mysqlConnect( $realServer ) {}
+       protected function mysqlSetCharset( $charset ) {}
        protected function mysqlFreeResult( $res ) {}
        protected function mysqlFetchObject( $res ) {}
        protected function mysqlFetchArray( $res ) {}
@@ -60,13 +62,12 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase {
         * @dataProvider provideDiapers
         * @covers DatabaseMysqlBase::addIdentifierQuotes
         */
-       function testAddIdentifierQuotes( $expected, $in ) {
+       public function testAddIdentifierQuotes( $expected, $in ) {
                $db = new FakeDatabaseMysqlBase();
                $quoted = $db->addIdentifierQuotes( $in );
-               $this->assertEquals($expected, $quoted);
+               $this->assertEquals( $expected, $quoted );
        }
 
-
        /**
         * Feeds testAddIdentifierQuotes
         *
@@ -119,8 +120,91 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase {
                );
        }
 
-       private static function createUnicodeString($str) {
+       private static function createUnicodeString( $str ) {
                return json_decode( '"' . $str . '"' );
        }
 
+       function getMockForViews() {
+               $db = $this->getMockBuilder( 'DatabaseMysql' )
+                       ->disableOriginalConstructor()
+                       ->setMethods( array( 'fetchRow', 'query' ) )
+                       ->getMock();
+
+               $db->expects( $this->any() )
+                       ->method( 'query' )
+                       ->with( $this->anything() )
+                       ->will(
+                               $this->returnValue( null )
+                       );
+
+               $db->expects( $this->any() )
+                       ->method( 'fetchRow' )
+                       ->with( $this->anything() )
+                       ->will( $this->onConsecutiveCalls(
+                               array( 'Tables_in_' => 'view1' ),
+                               array( 'Tables_in_' => 'view2' ),
+                               array( 'Tables_in_' => 'myview' ),
+                               false  # no more rows
+                       ));
+               return $db;
+       }
+       /**
+        * @covers DatabaseMysqlBase::listViews
+        */
+       function testListviews() {
+               $db = $this->getMockForViews();
+
+               // The first call populate an internal cache of views
+               $this->assertEquals( array( 'view1', 'view2', 'myview' ),
+                       $db->listViews() );
+               $this->assertEquals( array( 'view1', 'view2', 'myview' ),
+                       $db->listViews() );
+
+               // Prefix filtering
+               $this->assertEquals( array( 'view1', 'view2' ),
+                       $db->listViews( 'view' ) );
+               $this->assertEquals( array( 'myview' ),
+                       $db->listViews( 'my' ) );
+               $this->assertEquals( array(),
+                       $db->listViews( 'UNUSED_PREFIX' ) );
+               $this->assertEquals( array( 'view1', 'view2', 'myview' ),
+                       $db->listViews( '' ) );
+       }
+
+       /**
+        * @covers DatabaseMysqlBase::isView
+        * @dataProvider provideViewExistanceChecks
+        */
+       function testIsView( $isView, $viewName ) {
+               $db = $this->getMockForViews();
+
+               switch ( $isView ) {
+                       case true:
+                               $this->assertTrue( $db->isView( $viewName ),
+                                       "$viewName should be considered a view" );
+                       break;
+
+                       case false:
+                               $this->assertFalse( $db->isView( $viewName ),
+                                       "$viewName has not been defined as a view" );
+                       break;
+               }
+
+       }
+
+       function provideViewExistanceChecks() {
+               return array(
+                       // format: whether it is a view, view name
+                       array( true, 'view1' ),
+                       array( true, 'view2' ),
+                       array( true, 'myview' ),
+
+                       array( false, 'user' ),
+
+                       array( false, 'view10' ),
+                       array( false, 'my' ),
+                       array( false, 'OH_MY_GOD' ),  # they killed kenny!
+               );
+       }
+
 }
index 726d63a..bdd567e 100644 (file)
@@ -27,7 +27,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideSelect
         * @covers DatabaseBase::select
         */
-       function testSelect( $sql, $sqlText ) {
+       public function testSelect( $sql, $sqlText ) {
                $this->database->select(
                        $sql['tables'],
                        $sql['fields'],
@@ -129,7 +129,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideUpdate
         * @covers DatabaseBase::update
         */
-       function testUpdate( $sql, $sqlText ) {
+       public function testUpdate( $sql, $sqlText ) {
                $this->database->update(
                        $sql['table'],
                        $sql['values'],
@@ -181,7 +181,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideDelete
         * @covers DatabaseBase::delete
         */
-       function testDelete( $sql, $sqlText ) {
+       public function testDelete( $sql, $sqlText ) {
                $this->database->delete(
                        $sql['table'],
                        $sql['conds'],
@@ -214,7 +214,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideUpsert
         * @covers DatabaseBase::upsert
         */
-       function testUpsert( $sql, $sqlText ) {
+       public function testUpsert( $sql, $sqlText ) {
                $this->database->upsert(
                        $sql['table'],
                        $sql['rows'],
@@ -250,7 +250,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideDeleteJoin
         * @covers DatabaseBase::deleteJoin
         */
-       function testDeleteJoin( $sql, $sqlText ) {
+       public function testDeleteJoin( $sql, $sqlText ) {
                $this->database->deleteJoin(
                        $sql['delTable'],
                        $sql['joinTable'],
@@ -297,7 +297,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideInsert
         * @covers DatabaseBase::insert
         */
-       function testInsert( $sql, $sqlText ) {
+       public function testInsert( $sql, $sqlText ) {
                $this->database->insert(
                        $sql['table'],
                        $sql['rows'],
@@ -350,7 +350,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideInsertSelect
         * @covers DatabaseBase::insertSelect
         */
-       function testInsertSelect( $sql, $sqlText ) {
+       public function testInsertSelect( $sql, $sqlText ) {
                $this->database->insertSelect(
                        $sql['destTable'],
                        $sql['srcTable'],
@@ -413,7 +413,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideReplace
         * @covers DatabaseBase::replace
         */
-       function testReplace( $sql, $sqlText ) {
+       public function testReplace( $sql, $sqlText ) {
                $this->database->replace(
                        $sql['table'],
                        $sql['uniqueIndexes'],
@@ -528,7 +528,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideNativeReplace
         * @covers DatabaseBase::nativeReplace
         */
-       function testNativeReplace( $sql, $sqlText ) {
+       public function testNativeReplace( $sql, $sqlText ) {
                $this->database->nativeReplace(
                        $sql['table'],
                        $sql['rows'],
@@ -555,7 +555,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideConditional
         * @covers DatabaseBase::conditional
         */
-       function testConditional( $sql, $sqlText ) {
+       public function testConditional( $sql, $sqlText ) {
                $this->assertEquals( trim( $this->database->conditional(
                        $sql['conds'],
                        $sql['true'],
@@ -596,7 +596,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideBuildConcat
         * @covers DatabaseBase::buildConcat
         */
-       function testBuildConcat( $stringList, $sqlText ) {
+       public function testBuildConcat( $stringList, $sqlText ) {
                $this->assertEquals( trim( $this->database->buildConcat(
                        $stringList
                ) ), $sqlText );
@@ -619,7 +619,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideBuildLike
         * @covers DatabaseBase::buildLike
         */
-       function testBuildLike( $array, $sqlText ) {
+       public function testBuildLike( $array, $sqlText ) {
                $this->assertEquals( trim( $this->database->buildLike(
                        $array
                ) ), $sqlText );
@@ -650,7 +650,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
         * @dataProvider provideUnionQueries
         * @covers DatabaseBase::unionQueries
         */
-       function testUnionQueries( $sql, $sqlText ) {
+       public function testUnionQueries( $sql, $sqlText ) {
                $this->assertEquals( trim( $this->database->unionQueries(
                        $sql['sqls'],
                        $sql['all']
@@ -686,7 +686,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        /**
         * @covers DatabaseBase::commit
         */
-       function testTransactionCommit() {
+       public function testTransactionCommit() {
                $this->database->begin( __METHOD__ );
                $this->database->commit( __METHOD__ );
                $this->assertLastSql( 'BEGIN; COMMIT' );
@@ -695,7 +695,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        /**
         * @covers DatabaseBase::rollback
         */
-       function testTransactionRollback() {
+       public function testTransactionRollback() {
                $this->database->begin( __METHOD__ );
                $this->database->rollback( __METHOD__ );
                $this->assertLastSql( 'BEGIN; ROLLBACK' );
@@ -704,7 +704,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        /**
         * @covers DatabaseBase::dropTable
         */
-       function testDropTable() {
+       public function testDropTable() {
                $this->database->setExistingTables( array( 'table' ) );
                $this->database->dropTable( 'table', __METHOD__ );
                $this->assertLastSql( 'DROP TABLE table' );
@@ -713,7 +713,7 @@ class DatabaseSQLTest extends MediaWikiTestCase {
        /**
         * @covers DatabaseBase::dropTable
         */
-       function testDropNonExistingTable() {
+       public function testDropNonExistingTable() {
                $this->assertFalse(
                        $this->database->dropTable( 'non_existing', __METHOD__ )
                );
index f151fb2..65726eb 100644 (file)
@@ -149,6 +149,14 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
                $this->assertEquals( "ALTER TABLE foo ADD COLUMN foo_bar INTEGER DEFAULT 42",
                        $this->replaceVars( "ALTER TABLE foo\nADD COLUMN foo_bar int(10) unsigned DEFAULT 42" )
                );
+
+               $this->assertEquals( "DROP INDEX foo",
+                       $this->replaceVars( "DROP INDEX /*i*/foo ON /*_*/bar" )
+               );
+
+               $this->assertEquals( "DROP INDEX foo -- dropping index",
+                       $this->replaceVars( "DROP INDEX /*i*/foo ON /*_*/bar -- dropping index" )
+               );
        }
 
        /**
@@ -411,7 +419,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
                return $indexes;
        }
 
-       function testCaseInsensitiveLike() {
+       public function testCaseInsensitiveLike() {
                // TODO: Test this for all databases
                $db = new DatabaseSqliteStandalone( ':memory:' );
                $res = $db->query( 'SELECT "a" LIKE "A" AS a' );
index 5e8e7a4..35a8e4c 100644 (file)
@@ -26,7 +26,7 @@ class DatabaseTest extends MediaWikiTestCase {
        /**
         * @covers DatabaseBase::dropTable
         */
-       function testAddQuotesNull() {
+       public function testAddQuotesNull() {
                $check = "NULL";
                if ( $this->db->getType() === 'sqlite' || $this->db->getType() === 'oracle' ) {
                        $check = "''";
@@ -34,7 +34,7 @@ class DatabaseTest extends MediaWikiTestCase {
                $this->assertEquals( $check, $this->db->addQuotes( null ) );
        }
 
-       function testAddQuotesInt() {
+       public function testAddQuotesInt() {
                # returning just "1234" should be ok too, though...
                # maybe
                $this->assertEquals(
@@ -42,20 +42,20 @@ class DatabaseTest extends MediaWikiTestCase {
                        $this->db->addQuotes( 1234 ) );
        }
 
-       function testAddQuotesFloat() {
+       public function testAddQuotesFloat() {
                # returning just "1234.5678" would be ok too, though
                $this->assertEquals(
                        "'1234.5678'",
                        $this->db->addQuotes( 1234.5678 ) );
        }
 
-       function testAddQuotesString() {
+       public function testAddQuotesString() {
                $this->assertEquals(
                        "'string'",
                        $this->db->addQuotes( 'string' ) );
        }
 
-       function testAddQuotesStringQuote() {
+       public function testAddQuotesStringQuote() {
                $check = "'string''s cause trouble'";
                if ( $this->db->getType() === 'mysql' ) {
                        $check = "'string\'s cause trouble'";
@@ -109,27 +109,27 @@ class DatabaseTest extends MediaWikiTestCase {
                }
 
                if ( $this->db->getType() === 'oracle' ) {
-                       return strtoupper($database . $quote . $prefix . $table);
+                       return strtoupper( $database . $quote . $prefix . $table );
                } else {
                        return $database . $quote . $prefix . $table . $quote;
                }
        }
 
-       function testTableNameLocal() {
+       public function testTableNameLocal() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename' ),
                        $this->db->tableName( 'tablename' )
                );
        }
 
-       function testTableNameRawLocal() {
+       public function testTableNameRawLocal() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename', null, null, 'raw' ),
                        $this->db->tableName( 'tablename', 'raw' )
                );
        }
 
-       function testTableNameShared() {
+       public function testTableNameShared() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename', 'sharedatabase', 'sh_' ),
                        $this->getSharedTableName( 'tablename', 'sharedatabase', 'sh_' )
@@ -141,7 +141,7 @@ class DatabaseTest extends MediaWikiTestCase {
                );
        }
 
-       function testTableNameRawShared() {
+       public function testTableNameRawShared() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename', 'sharedatabase', 'sh_', 'raw' ),
                        $this->getSharedTableName( 'tablename', 'sharedatabase', 'sh_', 'raw' )
@@ -153,21 +153,21 @@ class DatabaseTest extends MediaWikiTestCase {
                );
        }
 
-       function testTableNameForeign() {
+       public function testTableNameForeign() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename', 'databasename', '' ),
                        $this->db->tableName( 'databasename.tablename' )
                );
        }
 
-       function testTableNameRawForeign() {
+       public function testTableNameRawForeign() {
                $this->assertEquals(
                        $this->prefixAndQuote( 'tablename', 'databasename', '', 'raw' ),
                        $this->db->tableName( 'databasename.tablename', 'raw' )
                );
        }
 
-       function testFillPreparedEmpty() {
+       public function testFillPreparedEmpty() {
                $sql = $this->db->fillPrepared(
                        'SELECT * FROM interwiki', array() );
                $this->assertEquals(
@@ -175,7 +175,7 @@ class DatabaseTest extends MediaWikiTestCase {
                        $sql );
        }
 
-       function testFillPreparedQuestion() {
+       public function testFillPreparedQuestion() {
                $sql = $this->db->fillPrepared(
                        'SELECT * FROM cur WHERE cur_namespace=? AND cur_title=?',
                        array( 4, "Snicker's_paradox" ) );
@@ -187,7 +187,7 @@ class DatabaseTest extends MediaWikiTestCase {
                $this->assertEquals( $check, $sql );
        }
 
-       function testFillPreparedBang() {
+       public function testFillPreparedBang() {
                $sql = $this->db->fillPrepared(
                        'SELECT user_id FROM ! WHERE user_name=?',
                        array( '"user"', "Slash's Dot" ) );
@@ -199,7 +199,7 @@ class DatabaseTest extends MediaWikiTestCase {
                $this->assertEquals( $check, $sql );
        }
 
-       function testFillPreparedRaw() {
+       public function testFillPreparedRaw() {
                $sql = $this->db->fillPrepared(
                        "SELECT * FROM cur WHERE cur_title='This_\\&_that,_WTF\\?\\!'",
                        array( '"user"', "Slash's Dot" ) );
@@ -208,7 +208,7 @@ class DatabaseTest extends MediaWikiTestCase {
                        $sql );
        }
 
-       function testStoredFunctions() {
+       public function testStoredFunctions() {
                if ( !in_array( wfGetDB( DB_MASTER )->getType(), array( 'mysql', 'postgres' ) ) ) {
                        $this->markTestSkipped( 'MySQL or Postgres required' );
                }
@@ -226,7 +226,7 @@ class DatabaseTest extends MediaWikiTestCase {
                );
        }
 
-       function testUnknownTableCorruptsResults() {
+       public function testUnknownTableCorruptsResults() {
                $res = $this->db->select( 'page', '*', array( 'page_id' => 1 ) );
                $this->assertFalse( $this->db->tableExists( 'foobarbaz' ) );
                $this->assertInternalType( 'int', $res->numRows() );
index e583d1b..7171ee5 100644 (file)
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
  * @author Daniel Kinzler
  */
+
+/**
+ * @covers PageORMTableForTesting
+ */
 class ORMTableTest extends MediaWikiTestCase {
 
        /**
index f65642b..c9459c9 100644 (file)
@@ -40,6 +40,9 @@
  */
 require_once __DIR__ . "/ORMRowTest.php";
 
+/**
+ * @covers TestORMRow
+ */
 class TestORMRowTest extends ORMRowTest {
 
        /**
index 9026cb9..91399be 100644 (file)
@@ -2,7 +2,6 @@
 
 class MWDebugTest extends MediaWikiTestCase {
 
-
        protected function setUp() {
                parent::setUp();
                // Make sure MWDebug class is enabled
@@ -21,7 +20,10 @@ class MWDebugTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
-       function testAddLog() {
+       /**
+        * @covers MWDebug::log
+        */
+       public function testAddLog() {
                MWDebug::log( 'logging a string' );
                $this->assertEquals(
                        array( array(
@@ -33,7 +35,10 @@ class MWDebugTest extends MediaWikiTestCase {
                );
        }
 
-       function testAddWarning() {
+       /**
+        * @covers MWDebug::warning
+        */
+       public function testAddWarning() {
                MWDebug::warning( 'Warning message' );
                $this->assertEquals(
                        array( array(
@@ -45,7 +50,10 @@ class MWDebugTest extends MediaWikiTestCase {
                );
        }
 
-       function testAvoidDuplicateDeprecations() {
+       /**
+        * @covers MWDebug::deprecated
+        */
+       public function testAvoidDuplicateDeprecations() {
                MWDebug::deprecated( 'wfOldFunction', '1.0', 'component' );
                MWDebug::deprecated( 'wfOldFunction', '1.0', 'component' );
 
@@ -56,7 +64,10 @@ class MWDebugTest extends MediaWikiTestCase {
                );
        }
 
-       function testAvoidNonConsecutivesDuplicateDeprecations() {
+       /**
+        * @covers MWDebug::deprecated
+        */
+       public function testAvoidNonConsecutivesDuplicateDeprecations() {
                MWDebug::deprecated( 'wfOldFunction', '1.0', 'component' );
                MWDebug::warning( 'some warning' );
                MWDebug::log( 'we could have logged something too' );
diff --git a/tests/phpunit/includes/diff/DifferenceEngineTest.php b/tests/phpunit/includes/diff/DifferenceEngineTest.php
new file mode 100644 (file)
index 0000000..f95eb5e
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @covers DifferenceEngine
+ *
+ * @todo tests for the rest of DifferenceEngine!
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class DifferenceEngineTest extends MediaWikiTestCase {
+
+       protected $context;
+
+       private static $revisions;
+
+       protected function setUp() {
+               parent::setUp();
+
+               $title = $this->getTitle();
+
+               $this->context = new RequestContext();
+               $this->context->setTitle( $title );
+
+               if ( !self::$revisions ) {
+                       self::$revisions = $this->doEdits();
+               }
+       }
+
+       /**
+        * @return Title
+        */
+       protected function getTitle() {
+               $namespace = $this->getDefaultWikitextNS();
+               return Title::newFromText( 'Kitten', $namespace );
+       }
+
+       /**
+        * @return int[] revision ids
+        */
+       protected function doEdits() {
+               $title = $this->getTitle();
+               $page = WikiPage::factory( $title );
+
+               $strings = array( "it is a kitten", "two kittens", "three kittens", "four kittens" );
+               $revisions = array();
+
+               foreach ( $strings as $string ) {
+                       $content = ContentHandler::makeContent( $string, $title );
+                       $page->doEditContent( $content, 'edit page' );
+                       $revisions[] = $page->getLatest();
+               }
+
+               return $revisions;
+       }
+
+       public function testMapDiffPrevNext() {
+               $cases = $this->getMapDiffPrevNextCases();
+
+               foreach ( $cases as $case ) {
+                       list( $expected, $old, $new, $message ) = $case;
+
+                       $diffEngine = new DifferenceEngine( $this->context, $old, $new, 2, true, false );
+                       $diffMap = $diffEngine->mapDiffPrevNext( $old, $new );
+                       $this->assertEquals( $expected, $diffMap, $message );
+               }
+       }
+
+       private function getMapDiffPrevNextCases() {
+               $revs = self::$revisions;
+
+               return array(
+                       array( array( $revs[1], $revs[2] ), $revs[2], 'prev', 'diff=prev' ),
+                       array( array( $revs[2], $revs[3] ), $revs[2], 'next', 'diff=next' ),
+                       array( array( $revs[1], $revs[3] ), $revs[1], $revs[3], 'diff=' . $revs[3] )
+               );
+       }
+
+       public function testLoadRevisionData() {
+               $cases = $this->getLoadRevisionDataCases();
+
+               foreach ( $cases as $case ) {
+                       list( $expectedOld, $expectedNew, $old, $new, $message ) = $case;
+
+                       $diffEngine = new DifferenceEngine( $this->context, $old, $new, 2, true, false );
+                       $diffEngine->loadRevisionData();
+
+                       $this->assertEquals( $diffEngine->getOldid(), $expectedOld, $message );
+                       $this->assertEquals( $diffEngine->getNewid(), $expectedNew, $message );
+               }
+       }
+
+       private function getLoadRevisionDataCases() {
+               $revs = self::$revisions;
+
+               return array(
+                       array( $revs[2], $revs[3], $revs[3], 'prev', 'diff=prev' ),
+                       array( $revs[2], $revs[3], $revs[2], 'next', 'diff=next' ),
+                       array( $revs[1], $revs[3], $revs[1], $revs[3], 'diff=' . $revs[3] ),
+                       array( $revs[1], $revs[3], $revs[1], 0, 'diff=0' )
+               );
+       }
+
+       public function testGetOldid() {
+               $revs = self::$revisions;
+
+               $diffEngine = new DifferenceEngine( $this->context, $revs[1], $revs[2], 2, true, false );
+               $this->assertEquals( $revs[1], $diffEngine->getOldid(), 'diff get old id' );
+       }
+
+       public function testGetNewid() {
+               $revs = self::$revisions;
+
+               $diffEngine = new DifferenceEngine( $this->context, $revs[1], $revs[2], 2, true, false );
+               $this->assertEquals( $revs[2], $diffEngine->getNewid(), 'diff get new id' );
+       }
+
+}
index b760e26..e3a7556 100644 (file)
@@ -6,7 +6,7 @@ class FileRepoTest extends MediaWikiTestCase {
         * @expectedException MWException
         * @covers FileRepo::__construct
         */
-       function testFileRepoConstructionOptionCanNotBeNull() {
+       public function testFileRepoConstructionOptionCanNotBeNull() {
                new FileRepo();
        }
 
@@ -14,7 +14,7 @@ class FileRepoTest extends MediaWikiTestCase {
         * @expectedException MWException
         * @covers FileRepo::__construct
         */
-       function testFileRepoConstructionOptionCanNotBeAnEmptyArray() {
+       public function testFileRepoConstructionOptionCanNotBeAnEmptyArray() {
                new FileRepo( array() );
        }
 
@@ -22,7 +22,7 @@ class FileRepoTest extends MediaWikiTestCase {
         * @expectedException MWException
         * @covers FileRepo::__construct
         */
-       function testFileRepoConstructionOptionNeedNameKey() {
+       public function testFileRepoConstructionOptionNeedNameKey() {
                new FileRepo( array(
                        'backend' => 'foobar'
                ) );
@@ -32,7 +32,7 @@ class FileRepoTest extends MediaWikiTestCase {
         * @expectedException MWException
         * @covers FileRepo::__construct
         */
-       function testFileRepoConstructionOptionNeedBackendKey() {
+       public function testFileRepoConstructionOptionNeedBackendKey() {
                new FileRepo( array(
                        'name' => 'foobar'
                ) );
@@ -41,7 +41,7 @@ class FileRepoTest extends MediaWikiTestCase {
        /**
         * @covers FileRepo::__construct
         */
-       function testFileRepoConstructionWithRequiredOptions() {
+       public function testFileRepoConstructionWithRequiredOptions() {
                $f = new FileRepo( array(
                        'name' => 'FileRepoTestRepository',
                        'backend' => new FSFileBackend( array(
index ea87ede..0e5f267 100644 (file)
@@ -9,7 +9,7 @@ class InstallDocFormatterTest extends MediaWikiTestCase {
         * @covers InstallDocFormatter::format
         * @dataProvider provideDocFormattingTests
         */
-       function testFormat( $expected, $unformattedText, $message = '' ) {
+       public function testFormat( $expected, $unformattedText, $message = '' ) {
                $this->assertEquals(
                        $expected,
                        InstallDocFormatter::format( $unformattedText ),
index 592500d..66e6559 100644 (file)
@@ -13,7 +13,7 @@ class OracleInstallerTest extends MediaWikiTestCase {
         * @dataProvider provideOracleConnectStrings
         * @covers OracleInstaller::checkConnectStringFormat
         */
-       function testCheckConnectStringFormat( $expected, $connectString, $msg = '' ) {
+       public function testCheckConnectStringFormat( $expected, $connectString, $msg = '' ) {
                $validity = $expected ? 'should be valid' : 'should NOT be valid';
                $msg = "'$connectString' ($msg) $validity.";
                $this->assertEquals( $expected,
index 6990153..3319490 100644 (file)
@@ -70,21 +70,33 @@ class JobQueueTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provider_queueLists
+        * @covers JobQueue::getWiki
         */
-       function testProperties( $queue, $recycles, $desc ) {
+       public function testGetWiki( $queue, $recycles, $desc ) {
                $queue = $this->$queue;
                if ( !$queue ) {
                        $this->markTestSkipped( $desc );
                }
-
                $this->assertEquals( wfWikiID(), $queue->getWiki(), "Proper wiki ID ($desc)" );
+       }
+
+       /**
+        * @dataProvider provider_queueLists
+        * @covers JobQueue::getType
+        */
+       public function testGetType( $queue, $recycles, $desc ) {
+               $queue = $this->$queue;
+               if ( !$queue ) {
+                       $this->markTestSkipped( $desc );
+               }
                $this->assertEquals( 'null', $queue->getType(), "Proper job type ($desc)" );
        }
 
        /**
         * @dataProvider provider_queueLists
+        * @covers JobQueue
         */
-       function testBasicOperations( $queue, $recycles, $desc ) {
+       public function testBasicOperations( $queue, $recycles, $desc ) {
                $queue = $this->$queue;
                if ( !$queue ) {
                        $this->markTestSkipped( $desc );
@@ -157,8 +169,9 @@ class JobQueueTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provider_queueLists
+        * @covers JobQueue
         */
-       function testBasicDeduplication( $queue, $recycles, $desc ) {
+       public function testBasicDeduplication( $queue, $recycles, $desc ) {
                $queue = $this->$queue;
                if ( !$queue ) {
                        $this->markTestSkipped( $desc );
@@ -214,8 +227,9 @@ class JobQueueTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provider_queueLists
+        * @covers JobQueue
         */
-       function testRootDeduplication( $queue, $recycles, $desc ) {
+       public function testRootDeduplication( $queue, $recycles, $desc ) {
                $queue = $this->$queue;
                if ( !$queue ) {
                        $this->markTestSkipped( $desc );
@@ -267,8 +281,9 @@ class JobQueueTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provider_fifoQueueLists
+        * @covers JobQueue
         */
-       function testJobOrder( $queue, $recycles, $desc ) {
+       public function testJobOrder( $queue, $recycles, $desc ) {
                $queue = $this->$queue;
                if ( !$queue ) {
                        $this->markTestSkipped( $desc );
diff --git a/tests/phpunit/includes/jobqueue/RefreshLinksPartitionTest.php b/tests/phpunit/includes/jobqueue/RefreshLinksPartitionTest.php
new file mode 100644 (file)
index 0000000..531a954
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @group JobQueue
+ * @group medium
+ * @group Database
+ */
+class RefreshLinksPartitionTest extends MediaWikiTestCase {
+       function __construct( $name = null, array $data = array(), $dataName = '' ) {
+               parent::__construct( $name, $data, $dataName );
+
+               $this->tablesUsed[] = 'page';
+               $this->tablesUsed[] = 'revision';
+               $this->tablesUsed[] = 'pagelinks';
+       }
+
+       /**
+        * @dataProvider provider_backlinks
+        */
+       public function testRefreshLinks( $ns, $dbKey, $pages ) {
+               $title = Title::makeTitle( $ns, $dbKey );
+
+               $dbw = wfGetDB( DB_MASTER );
+
+               $rows = array();
+               foreach ( $pages as $page ) {
+                       list( $bns, $bdbkey ) = $page;
+                       $bpage = WikiPage::factory( Title::makeTitle( $bns, $bdbkey ) );
+                       $content = ContentHandler::makeContent( "[[{$title->getPrefixedText()}]]", $bpage->getTitle() );
+                       $bpage->doEditContent( $content, "test" );
+               }
+
+               $title->getBacklinkCache()->clear();
+               $this->assertEquals( 20, $title->getBacklinkCache()->getNumLinks( 'pagelinks' ), 'Correct number of backlinks' );
+
+               $job = new RefreshLinksJob( $title, array( 'recursive' => true, 'table' => 'pagelinks' )
+                       + Job::newRootJobParams( "refreshlinks:pagelinks:{$title->getPrefixedText()}" ) );
+               $extraParams = $job->getRootJobParams();
+               $jobs = BacklinkJobUtils::partitionBacklinkJob( $job, 9, 1, array( 'params' => $extraParams ) );
+
+               $this->assertEquals( 10, count( $jobs ), 'Correct number of sub-jobs' );
+               $this->assertEquals( $pages[0], current( $jobs[0]->params['pages'] ),
+                       'First job is leaf job with proper title' );
+               $this->assertEquals( $pages[8], current( $jobs[8]->params['pages'] ),
+                       'Last leaf job is leaf job with proper title' );
+               $this->assertEquals( true, isset( $jobs[9]->params['recursive'] ),
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( true, $jobs[9]->params['recursive'],
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( true, is_array( $jobs[9]->params['range'] ),
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( $title->getPrefixedText(), $jobs[0]->getTitle()->getPrefixedText(),
+                       'Base job title retainend in leaf job' );
+               $this->assertEquals( $title->getPrefixedText(), $jobs[9]->getTitle()->getPrefixedText(),
+                       'Base job title retainend recursive sub-job' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs[0]->params['rootJobSignature'],
+                       'Leaf job has root params' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs[9]->params['rootJobSignature'],
+                       'Recursive sub-job has root params' );
+
+               $jobs2 = BacklinkJobUtils::partitionBacklinkJob( $jobs[9], 9, 1, array( 'params' => $extraParams ) );
+
+               $this->assertEquals( 10, count( $jobs2 ), 'Correct number of sub-jobs' );
+               $this->assertEquals( $pages[9], current( $jobs2[0]->params['pages'] ),
+                       'First job is leaf job with proper title' );
+               $this->assertEquals( $pages[17], current( $jobs2[8]->params['pages'] ),
+                       'Last leaf job is leaf job with proper title' );
+               $this->assertEquals( true, isset( $jobs2[9]->params['recursive'] ),
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( true, $jobs2[9]->params['recursive'],
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( true, is_array( $jobs2[9]->params['range'] ),
+                       'Last job is recursive sub-job' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs2[0]->params['rootJobSignature'],
+                       'Leaf job has root params' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs2[9]->params['rootJobSignature'],
+                       'Recursive sub-job has root params' );
+
+               $jobs3 = BacklinkJobUtils::partitionBacklinkJob( $jobs2[9], 9, 1, array( 'params' => $extraParams ) );
+
+               $this->assertEquals( 2, count( $jobs3 ), 'Correct number of sub-jobs' );
+               $this->assertEquals( $pages[18], current( $jobs3[0]->params['pages'] ),
+                       'First job is leaf job with proper title' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs3[0]->params['rootJobSignature'],
+                       'Leaf job has root params' );
+               $this->assertEquals( $pages[19], current( $jobs3[1]->params['pages'] ),
+                       'Last job is leaf job with proper title' );
+               $this->assertEquals( $extraParams['rootJobSignature'], $jobs3[1]->params['rootJobSignature'],
+                       'Last leaf job has root params' );
+       }
+
+       public static function provider_backlinks() {
+               $pages = array();
+               for ( $i = 0; $i < 20; ++$i ) {
+                       $pages[] = array( 0, "Page-$i" );
+               }
+               return array(
+                       array( 10, 'Bang', $pages )
+               );
+       }
+}
index eb024ab..8359f0d 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @covers FormatJson
+ */
 class FormatJsonTest extends MediaWikiTestCase {
 
        public function testEncoderPrettyPrinting() {
@@ -12,28 +15,30 @@ class FormatJsonTest extends MediaWikiTestCase {
                                        123,
                                        456,
                                ),
+                               // Nested json works without problems
                                '"7":["8",{"9":"10"}]',
+                               // Whitespace clean up doesn't touch strings that look alike
+                               "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}",
                        ),
                );
 
                // 4 space indent, no trailing whitespace, no trailing linefeed
                $json = '{
-    "emptyObject": {
-    },
-    "emptyArray": [
-    ],
+    "emptyObject": {},
+    "emptyArray": [],
     "string": "foobar\\\\",
     "filledArray": [
         [
             123,
             456
         ],
-        "\"7\":[\"8\",{\"9\":\"10\"}]"
+        "\"7\":[\"8\",{\"9\":\"10\"}]",
+        "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}"
     ]
 }';
 
                $json = str_replace( "\r", '', $json ); // Windows compat
-               $this->assertSame( $json, str_replace("\n\n", "\n", FormatJson::encode( $obj, true ) ));
+               $this->assertSame( $json, FormatJson::encode( $obj, true ) );
        }
 
        public static function provideEncodeDefault() {
index e9901ce..5bbc3a5 100644 (file)
@@ -20,8 +20,9 @@ class CSSMinTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideMinifyCases
+        * @covers CSSMin::minify
         */
-       function testMinify( $code, $expectedOutput ) {
+       public function testMinify( $code, $expectedOutput ) {
                $minified = CSSMin::minify( $code );
 
                $this->assertEquals( $expectedOutput, $minified, 'Minified output should be in the form expected.' );
@@ -68,9 +69,12 @@ class CSSMinTest extends MediaWikiTestCase {
        }
 
        /**
+        * This tests funky parameters to CSSMin::remap. testRemapRemapping tests the basic functionality.
+        *
         * @dataProvider provideRemapCases
+        * @covers CSSMin::remap
         */
-       function testRemap( $message, $params, $expectedOutput ) {
+       public function testRemap( $message, $params, $expectedOutput ) {
                $remapped = call_user_func_array( 'CSSMin::remap', $params );
 
                $messageAdd = " Case: $message";
@@ -109,13 +113,122 @@ class CSSMinTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * This tests basic functionality of CSSMin::remap. testRemapRemapping tests funky parameters.
+        *
+        * @dataProvider provideRemapRemappingCases
+        * @covers CSSMin::remap
+        */
+       public function testRemapRemapping( $message, $input, $expectedOutput ) {
+               $localPath = __DIR__ . '/../../data/cssmin/';
+               $remotePath = 'http://localhost/w/';
+
+               $realOutput = CSSMin::remap( $input, $localPath, $remotePath );
+
+               $this->assertEquals(
+                       $expectedOutput,
+                       preg_replace( '/\d+-\d+-\d+T\d+:\d+:\d+Z/', 'timestamp', $realOutput ),
+                       "CSSMin::remap: $message"
+               );
+       }
+
+       public static function provideRemapRemappingCases() {
+               // red.gif and green.gif are one-pixel 35-byte GIFs.
+               // large.png is a 35K PNG that should be non-embeddable.
+               // Full paths start with http://localhost/w/.
+               // Timestamps in output are replaced with 'timestamp'.
+
+               // data: URIs for red.gif and green.gif
+               $red   = 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=';
+               $green = 'data:image/gif;base64,R0lGODlhAQABAIAAAACAADAAACwAAAAAAQABAAACAkQBADs=';
+
+               return array(
+                       array(
+                               'Regular file',
+                               'foo { background: url(red.gif); }',
+                               'foo { background: url(http://localhost/w/red.gif?timestamp); }',
+                       ),
+                       array(
+                               'Remote URL',
+                               'foo { background: url(http://example.org/w/foo.png); }',
+                               'foo { background: url(http://example.org/w/foo.png); }',
+                       ),
+                       array(
+                               'Embedded file',
+                               'foo { /* @embed */ background: url(red.gif); }',
+                               "foo { background: url($red); background: url(http://localhost/w/red.gif?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Can not embed remote URLs',
+                               'foo { /* @embed */ background: url(http://example.org/w/foo.png); }',
+                               'foo { background: url(http://example.org/w/foo.png); }',
+                       ),
+                       array(
+                               'Embedded file (inline @embed)',
+                               'foo { background: /* @embed */ url(red.gif); }',
+                               "foo { background: url($red); background: url(http://localhost/w/red.gif?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Can not embed large files',
+                               'foo { /* @embed */ background: url(large.png); }',
+                               "foo { background: url(http://localhost/w/large.png?timestamp); }",
+                       ),
+                       array(
+                               'Two regular files in one rule',
+                               'foo { background: url(red.gif), url(green.gif); }',
+                               'foo { background: url(http://localhost/w/red.gif?timestamp), url(http://localhost/w/green.gif?timestamp); }',
+                       ),
+                       array(
+                               'Two embedded files in one rule',
+                               'foo { /* @embed */ background: url(red.gif), url(green.gif); }',
+                               "foo { background: url($red), url($green); background: url(http://localhost/w/red.gif?timestamp), url(http://localhost/w/green.gif?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Two embedded files in one rule (inline @embed)',
+                               'foo { background: /* @embed */ url(red.gif), /* @embed */ url(green.gif); }',
+                               "foo { background: url($red), url($green); background: url(http://localhost/w/red.gif?timestamp), url(http://localhost/w/green.gif?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Two embedded files in one rule (inline @embed), one too large',
+                               'foo { background: /* @embed */ url(red.gif), /* @embed */ url(large.png); }',
+                               "foo { background: url($red), url(http://localhost/w/large.png?timestamp); background: url(http://localhost/w/red.gif?timestamp), url(http://localhost/w/large.png?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Practical example with some noise',
+                               'foo { /* @embed */ background: #f9f9f9 url(red.gif) 0 0 no-repeat; }',
+                               "foo { background: #f9f9f9 url($red) 0 0 no-repeat; background: #f9f9f9 url(http://localhost/w/red.gif?timestamp) 0 0 no-repeat!ie; }",
+                       ),
+                       array(
+                               'Does not mess with other properties',
+                               'foo { color: red; background: url(red.gif); font-size: small; }',
+                               'foo { color: red; background: url(http://localhost/w/red.gif?timestamp); font-size: small; }',
+                       ),
+                       array(
+                               'Spacing and miscellanea not changed (1)',
+                               'foo {   background:    url(red.gif);  }',
+                               'foo {   background:    url(http://localhost/w/red.gif?timestamp);  }',
+                       ),
+                       array(
+                               'Spacing and miscellanea not changed (2)',
+                               'foo {background:url(red.gif)}',
+                               'foo {background:url(http://localhost/w/red.gif?timestamp)}',
+                       ),
+                       array(
+                               'Spaces within url() parentheses are ignored',
+                               'foo { background: url( red.gif ); }',
+                               'foo { background: url(http://localhost/w/red.gif?timestamp); }',
+                       ),
+               );
+       }
+
        /**
         * Seperated because they are currently broken (bug 35492)
         *
         * @group Broken
         * @dataProvider provideStringCases
+        * @covers CSSMin::remap
         */
-       function testMinifyWithCSSStringValues( $code, $expectedOutput ) {
+       public function testMinifyWithCSSStringValues( $code, $expectedOutput ) {
                $this->testMinifyOutput( $code, $expectedOutput );
        }
 
index 7436c43..e2ec474 100644 (file)
@@ -83,6 +83,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param array $elements
+        *
+        * @covers GenericArrayObject::__construct
         */
        public function testConstructor( array $elements ) {
                $arrayObject = $this->getNew( $elements );
@@ -96,6 +98,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param array $elements
+        *
+        * @covers GenericArrayObject::isEmpty
         */
        public function testIsEmpty( array $elements ) {
                $arrayObject = $this->getNew( $elements );
@@ -109,6 +113,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param GenericArrayObject $list
+        *
+        * @covers GenericArrayObject::offsetUnset
         */
        public function testUnset( GenericArrayObject $list ) {
                if ( $list->isEmpty() ) {
@@ -134,6 +140,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param array $elements
+        *
+        * @covers GenericArrayObject::append
         */
        public function testAppend( array $elements ) {
                $list = $this->getNew();
@@ -163,6 +171,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param callback $function
+        *
+        * @covers GenericArrayObject::getObjectType
         */
        protected function checkTypeChecks( $function ) {
                $excption = null;
@@ -194,6 +204,8 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.20
         *
         * @param array $elements
+        *
+        * @covers GenericArrayObject::offsetSet
         */
        public function testOffsetSet( array $elements ) {
                if ( $elements === array() ) {
@@ -247,6 +259,10 @@ abstract class GenericArrayObjectTest extends MediaWikiTestCase {
         * @since 1.21
         *
         * @param GenericArrayObject $list
+        *
+        * @covers GenericArrayObject::getSerializationData
+        * @covers GenericArrayObject::serialize
+        * @covers GenericArrayObject::unserialize
         */
        public function testSerialization( GenericArrayObject $list ) {
                $serialization = serialize( $list );
index d04dd7d..b707123 100644 (file)
@@ -2,9 +2,14 @@
 
 /**
  * Tests for IEUrlExtension::findIE6Extension
+ * @todo tests below for findIE6Extension should be split into...
+ *    ...a dataprovider and test method.
  */
 class IEUrlExtensionTest extends MediaWikiTestCase {
-       function testSimple() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testSimple() {
                $this->assertEquals(
                        'y',
                        IEUrlExtension::findIE6Extension( 'x.y' ),
@@ -12,7 +17,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testSimpleNoExt() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testSimpleNoExt() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( 'x' ),
@@ -20,7 +28,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testEmpty() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testEmpty() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( '' ),
@@ -28,7 +39,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testQuestionMark() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testQuestionMark() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( '?' ),
@@ -36,7 +50,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testExtQuestionMark() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testExtQuestionMark() {
                $this->assertEquals(
                        'x',
                        IEUrlExtension::findIE6Extension( '.x?' ),
@@ -44,7 +61,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testQuestionMarkExt() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testQuestionMarkExt() {
                $this->assertEquals(
                        'x',
                        IEUrlExtension::findIE6Extension( '?.x' ),
@@ -52,7 +72,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testInvalidChar() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testInvalidChar() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( '.x*' ),
@@ -60,7 +83,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testInvalidCharThenExtension() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testInvalidCharThenExtension() {
                $this->assertEquals(
                        'x',
                        IEUrlExtension::findIE6Extension( '*.x' ),
@@ -68,7 +94,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testMultipleQuestionMarks() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testMultipleQuestionMarks() {
                $this->assertEquals(
                        'c',
                        IEUrlExtension::findIE6Extension( 'a?b?.c?.d?e?f' ),
@@ -76,7 +105,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testExeException() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testExeException() {
                $this->assertEquals(
                        'd',
                        IEUrlExtension::findIE6Extension( 'a?b?.exe?.d?.e' ),
@@ -84,7 +116,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testExeException2() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testExeException2() {
                $this->assertEquals(
                        'exe',
                        IEUrlExtension::findIE6Extension( 'a?b?.exe' ),
@@ -92,7 +127,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testHash() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testHash() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( 'a#b.c' ),
@@ -100,7 +138,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testHash2() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testHash2() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( 'a?#b.c' ),
@@ -108,7 +149,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testDotAtEnd() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testDotAtEnd() {
                $this->assertEquals(
                        '',
                        IEUrlExtension::findIE6Extension( '.' ),
@@ -116,7 +160,10 @@ class IEUrlExtensionTest extends MediaWikiTestCase {
                );
        }
 
-       function testTwoDots() {
+       /**
+        * @covers IEUrlExtension::findIE6Extension
+        */
+       public function testTwoDots() {
                $this->assertEquals(
                        'z',
                        IEUrlExtension::findIE6Extension( 'x.y.z' ),
index eb64a64..62ee45a 100644 (file)
@@ -118,8 +118,9 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideCases
+        * @covers JavaScriptMinifier::minify
         */
-       function testJavaScriptMinifierOutput( $code, $expectedOutput ) {
+       public function testJavaScriptMinifierOutput( $code, $expectedOutput ) {
                $minified = JavaScriptMinifier::minify( $code );
 
                // JSMin+'s parser will throw an exception if output is not valid JS.
@@ -152,8 +153,9 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideBug32548
+        * @covers JavaScriptMinifier::minify
         */
-       function testBug32548Exponent( $num ) {
+       public function testBug32548Exponent( $num ) {
                // Long line breaking was being incorrectly done between the base and
                // exponent part of a number, causing a syntax error. The line should
                // instead break at the start of the number.
old mode 100755 (executable)
new mode 100644 (file)
index e8ccf43..9650fb1
@@ -61,6 +61,9 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                return $logEntry;
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        */
        public function testNormalLogParams() {
                $entry = $this->newLogEntry( 'test', array() );
                $formatter = LogFormatter::newFromEntry( $entry );
@@ -99,6 +102,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $titleLink, $paramsWithoutTools[2]['raw'] );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeRaw() {
                $params = array( '4:raw:raw' => Linker::link( $this->title, null, array(), array() ) );
                $expected = Linker::link( $this->title, null, array(), array() );
@@ -112,6 +119,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeMsg() {
                $params = array( '4:msg:msg' => 'log-description-phpunit' );
                $expected = wfMessage( 'log-description-phpunit' )->text();
@@ -125,6 +136,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeMsgContent() {
                $params = array( '4:msg-content:msgContent' => 'log-description-phpunit' );
                $expected = wfMessage( 'log-description-phpunit' )->inContentLanguage()->text();
@@ -138,6 +153,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeNumber() {
                global $wgLang;
 
@@ -153,6 +172,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeUserLink() {
                $params = array( '4:user-link:userLink' => $this->user->getName() );
                $expected = Linker::userLink(
@@ -169,6 +192,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypeTitleLink() {
                $params = array( '4:title-link:titleLink' => $this->title->getText() );
                $expected = Linker::link( $this->title, null, array(), array() );
@@ -182,6 +209,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getActionText
+        */
        public function testLogParamsTypePlain() {
                $params = array( '4:plain:plain' => 'Some plain text' );
                $expected = 'Some plain text';
@@ -195,6 +226,10 @@ class LogFormatterTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $logParam );
        }
 
+       /**
+        * @covers LogFormatter::newFromEntry
+        * @covers LogFormatter::getComment
+        */
        public function testLogComment() {
                $entry = $this->newLogEntry( 'test', array() );
                $formatter = LogFormatter::newFromEntry( $entry );
index 43792c1..a0e63a8 100644 (file)
@@ -16,6 +16,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
         * Basically the file has IPTC and XMP metadata, the
         * IPTC should override the XMP, except for the multilingual
         * translation (to en) where XMP should win.
+        * @covers BitmapMetadataHandler::Jpeg
         */
        public function testMultilingualCascade() {
                if ( !extension_loaded( 'exif' ) ) {
@@ -48,6 +49,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
         *
         * There's more extensive tests of comment extraction in
         * JpegMetadataExtractorTests.php
+        * @covers BitmapMetadataHandler::Jpeg
         */
        public function testJpegComment() {
                $meta = BitmapMetadataHandler::Jpeg( $this->filePath .
@@ -60,6 +62,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
        /**
         * Make sure a bad iptc block doesn't stop the other metadata
         * from being extracted.
+        * @covers BitmapMetadataHandler::Jpeg
         */
        public function testBadIPTC() {
                $meta = BitmapMetadataHandler::Jpeg( $this->filePath .
@@ -67,6 +70,9 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
                $this->assertEquals( 'Created with GIMP', $meta['JPEGFileComment'][0] );
        }
 
+       /**
+        * @covers BitmapMetadataHandler::Jpeg
+        */
        public function testIPTCDates() {
                $meta = BitmapMetadataHandler::Jpeg( $this->filePath .
                        'iptc-timetest.jpg' );
@@ -78,6 +84,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
        /**
         * File has an invalid time (+ one valid but really weird time)
         * that shouldn't be included
+        * @covers BitmapMetadataHandler::Jpeg
         */
        public function testIPTCDatesInvalid() {
                $meta = BitmapMetadataHandler::Jpeg( $this->filePath .
@@ -91,6 +98,8 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
         * XMP data should take priority over iptc data
         * when hash has been updated, but not when
         * the hash is wrong.
+        * @covers BitmapMetadataHandler::addMetadata
+        * @covers BitmapMetadataHandler::getMetadataArray
         */
        public function testMerging() {
                $merger = new BitmapMetadataHandler();
@@ -114,6 +123,9 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
+       /**
+        * @covers BitmapMetadataHandler::png
+        */
        public function testPNGXMP() {
                if ( !extension_loaded( 'xml' ) ) {
                        $this->markTestSkipped( "This test needs the xml extension." );
@@ -134,6 +146,9 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $result );
        }
 
+       /**
+        * @covers BitmapMetadataHandler::png
+        */
        public function testPNGNative() {
                $handler = new BitmapMetadataHandler();
                $result = $handler->png( $this->filePath . 'Png-native-test.png' );
@@ -141,6 +156,9 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $result['metadata']['Identifier']['x-default'] );
        }
 
+       /**
+        * @covers BitmapMetadataHandler::getTiffByteOrder
+        */
        public function testTiffByteOrder() {
                $handler = new BitmapMetadataHandler();
                $res = $handler->getTiffByteOrder( $this->filePath . 'test.tiff' );
index c4706bf..9395b66 100644 (file)
@@ -13,8 +13,9 @@ class BitmapScalingTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideNormaliseParams
+        * @covers BitmapHandler::normaliseParams
         */
-       function testNormaliseParams( $fileDimensions, $expectedParams, $params, $msg ) {
+       public function testNormaliseParams( $fileDimensions, $expectedParams, $params, $msg ) {
                $file = new FakeDimensionFile( $fileDimensions );
                $handler = new BitmapHandler;
                $valid = $handler->normaliseParams( $file, $params );
@@ -102,7 +103,10 @@ class BitmapScalingTest extends MediaWikiTestCase {
                );
        }
 
-       function testTooBigImage() {
+       /**
+        * @covers BitmapHandler::doTransform
+        */
+       public function testTooBigImage() {
                $file = new FakeDimensionFile( array( 4000, 4000 ) );
                $handler = new BitmapHandler;
                $params = array( 'width' => '3700' ); // Still bigger than max size.
@@ -110,7 +114,10 @@ class BitmapScalingTest extends MediaWikiTestCase {
                        get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
        }
 
-       function testTooBigMustRenderImage() {
+       /**
+        * @covers BitmapHandler::doTransform
+        */
+       public function testTooBigMustRenderImage() {
                $file = new FakeDimensionFile( array( 4000, 4000 ) );
                $file->mustRender = true;
                $handler = new BitmapHandler;
@@ -119,36 +126,12 @@ class BitmapScalingTest extends MediaWikiTestCase {
                        get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
        }
 
-       function testImageArea() {
+       /**
+        * @covers BitmapHandler::getImageArea
+        */
+       public function testImageArea() {
                $file = new FakeDimensionFile( array( 7, 9 ) );
                $handler = new BitmapHandler;
                $this->assertEquals( 63, $handler->getImageArea( $file ) );
        }
 }
-
-class FakeDimensionFile extends File {
-       public $mustRender = false;
-
-       public function __construct( $dimensions ) {
-               parent::__construct( Title::makeTitle( NS_FILE, 'Test' ),
-                       new NullRepo( null ) );
-
-               $this->dimensions = $dimensions;
-       }
-
-       public function getWidth( $page = 1 ) {
-               return $this->dimensions[0];
-       }
-
-       public function getHeight( $page = 1 ) {
-               return $this->dimensions[1];
-       }
-
-       public function mustRender() {
-               return $this->mustRender;
-       }
-
-       public function getPath() {
-               return '';
-       }
-}
index 532182c..a2e0eb6 100644 (file)
@@ -2,6 +2,11 @@
 
 class ExifBitmapTest extends MediaWikiTestCase {
 
+       /**
+        * @var ExifBitmapHandler
+        */
+       protected $handler;
+
        protected function setUp() {
                parent::setUp();
                if ( !extension_loaded( 'exif' ) ) {
@@ -14,42 +19,62 @@ class ExifBitmapTest extends MediaWikiTestCase {
 
        }
 
+       /**
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testIsOldBroken() {
                $res = $this->handler->isMetadataValid( null, ExifBitmapHandler::OLD_BROKEN_FILE );
                $this->assertEquals( ExifBitmapHandler::METADATA_COMPATIBLE, $res );
        }
 
+       /**
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testIsBrokenFile() {
                $res = $this->handler->isMetadataValid( null, ExifBitmapHandler::BROKEN_FILE );
                $this->assertEquals( ExifBitmapHandler::METADATA_GOOD, $res );
        }
 
+       /**
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testIsInvalid() {
                $res = $this->handler->isMetadataValid( null, 'Something Invalid Here.' );
                $this->assertEquals( ExifBitmapHandler::METADATA_BAD, $res );
        }
 
+       /**
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testGoodMetadata() {
                $meta = 'a:16:{s:10:"ImageWidth";i:20;s:11:"ImageLength";i:20;s:13:"BitsPerSample";a:3:{i:0;i:8;i:1;i:8;i:2;i:8;}s:11:"Compression";i:5;s:25:"PhotometricInterpretation";i:2;s:16:"ImageDescription";s:17:"Created with GIMP";s:12:"StripOffsets";i:8;s:11:"Orientation";i:1;s:15:"SamplesPerPixel";i:3;s:12:"RowsPerStrip";i:64;s:15:"StripByteCounts";i:238;s:11:"XResolution";s:19:"1207959552/16777216";s:11:"YResolution";s:19:"1207959552/16777216";s:19:"PlanarConfiguration";i:1;s:14:"ResolutionUnit";i:2;s:22:"MEDIAWIKI_EXIF_VERSION";i:2;}';
                $res = $this->handler->isMetadataValid( null, $meta );
                $this->assertEquals( ExifBitmapHandler::METADATA_GOOD, $res );
        }
 
+       /**
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testIsOldGood() {
                $meta = 'a:16:{s:10:"ImageWidth";i:20;s:11:"ImageLength";i:20;s:13:"BitsPerSample";a:3:{i:0;i:8;i:1;i:8;i:2;i:8;}s:11:"Compression";i:5;s:25:"PhotometricInterpretation";i:2;s:16:"ImageDescription";s:17:"Created with GIMP";s:12:"StripOffsets";i:8;s:11:"Orientation";i:1;s:15:"SamplesPerPixel";i:3;s:12:"RowsPerStrip";i:64;s:15:"StripByteCounts";i:238;s:11:"XResolution";s:19:"1207959552/16777216";s:11:"YResolution";s:19:"1207959552/16777216";s:19:"PlanarConfiguration";i:1;s:14:"ResolutionUnit";i:2;s:22:"MEDIAWIKI_EXIF_VERSION";i:1;}';
                $res = $this->handler->isMetadataValid( null, $meta );
                $this->assertEquals( ExifBitmapHandler::METADATA_COMPATIBLE, $res );
        }
 
-       // Handle metadata from paged tiff handler (gotten via instant commons)
-       // gracefully.
+       /**
+        * Handle metadata from paged tiff handler (gotten via instant commons) gracefully.
+        * @covers ExifBitmapHandler::isMetadataValid
+        */
        public function testPagedTiffHandledGracefully() {
                $meta = 'a:6:{s:9:"page_data";a:1:{i:1;a:5:{s:5:"width";i:643;s:6:"height";i:448;s:5:"alpha";s:4:"true";s:4:"page";i:1;s:6:"pixels";i:288064;}}s:10:"page_count";i:1;s:10:"first_page";i:1;s:9:"last_page";i:1;s:4:"exif";a:9:{s:10:"ImageWidth";i:643;s:11:"ImageLength";i:448;s:11:"Compression";i:5;s:25:"PhotometricInterpretation";i:2;s:11:"Orientation";i:1;s:15:"SamplesPerPixel";i:4;s:12:"RowsPerStrip";i:50;s:19:"PlanarConfiguration";i:1;s:22:"MEDIAWIKI_EXIF_VERSION";i:1;}s:21:"TIFF_METADATA_VERSION";s:3:"1.4";}';
                $res = $this->handler->isMetadataValid( null, $meta );
                $this->assertEquals( ExifBitmapHandler::METADATA_BAD, $res );
        }
 
-       function testConvertMetadataLatest() {
+       /**
+        * @covers ExifBitmapHandler::convertMetadataVersion
+        */
+       public function testConvertMetadataLatest() {
                $metadata = array(
                        'foo' => array( 'First', 'Second', '_type' => 'ol' ),
                        'MEDIAWIKI_EXIF_VERSION' => 2
@@ -58,7 +83,10 @@ class ExifBitmapTest extends MediaWikiTestCase {
                $this->assertEquals( $metadata, $res );
        }
 
-       function testConvertMetadataToOld() {
+       /**
+        * @covers ExifBitmapHandler::convertMetadataVersion
+        */
+       public function testConvertMetadataToOld() {
                $metadata = array(
                        'foo' => array( 'First', 'Second', '_type' => 'ol' ),
                        'bar' => array( 'First', 'Second', '_type' => 'ul' ),
@@ -77,7 +105,10 @@ class ExifBitmapTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $res );
        }
 
-       function testConvertMetadataSoftware() {
+       /**
+        * @covers ExifBitmapHandler::convertMetadataVersion
+        */
+       public function testConvertMetadataSoftware() {
                $metadata = array(
                        'Software' => array( array( 'GIMP', '1.1' ) ),
                        'MEDIAWIKI_EXIF_VERSION' => 2,
@@ -90,7 +121,10 @@ class ExifBitmapTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $res );
        }
 
-       function testConvertMetadataSoftwareNormal() {
+       /**
+        * @covers ExifBitmapHandler::convertMetadataVersion
+        */
+       public function testConvertMetadataSoftwareNormal() {
                $metadata = array(
                        'Software' => array( "GIMP 1.2", "vim" ),
                        'MEDIAWIKI_EXIF_VERSION' => 2,
index c16de8b..f4f4154 100644 (file)
@@ -3,6 +3,8 @@
  * Tests related to auto rotation.
  *
  * @group medium
+ *
+ * @todo covers tags
  */
 class ExifRotationTest extends MediaWikiTestCase {
 
@@ -34,10 +36,9 @@ class ExifRotationTest extends MediaWikiTestCase {
        }
 
        /**
-        *
         * @dataProvider provideFiles
         */
-       function testMetadata( $name, $type, $info ) {
+       public function testMetadata( $name, $type, $info ) {
                if ( !BitmapHandler::canRotate() ) {
                        $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
                }
@@ -50,7 +51,7 @@ class ExifRotationTest extends MediaWikiTestCase {
         *
         * @dataProvider provideFiles
         */
-       function testRotationRendering( $name, $type, $info, $thumbs ) {
+       public function testRotationRendering( $name, $type, $info, $thumbs ) {
                if ( !BitmapHandler::canRotate() ) {
                        $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
                }
@@ -129,7 +130,7 @@ class ExifRotationTest extends MediaWikiTestCase {
         * Same as before, but with auto-rotation disabled.
         * @dataProvider provideFilesNoAutoRotate
         */
-       function testMetadataNoAutoRotate( $name, $type, $info ) {
+       public function testMetadataNoAutoRotate( $name, $type, $info ) {
                $this->setMwGlobals( 'wgEnableAutoRotation', false );
 
                $file = $this->dataFile( $name, $type );
@@ -141,7 +142,7 @@ class ExifRotationTest extends MediaWikiTestCase {
         *
         * @dataProvider provideFilesNoAutoRotate
         */
-       function testRotationRenderingNoAutoRotate( $name, $type, $info, $thumbs ) {
+       public function testRotationRenderingNoAutoRotate( $name, $type, $info, $thumbs ) {
                $this->setMwGlobals( 'wgEnableAutoRotation', false );
 
                foreach ( $thumbs as $size => $out ) {
@@ -209,14 +210,13 @@ class ExifRotationTest extends MediaWikiTestCase {
                );
        }
 
-
        const TEST_WIDTH = 100;
        const TEST_HEIGHT = 200;
 
        /**
         * @dataProvider provideBitmapExtractPreRotationDimensions
         */
-       function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
+       public function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
                $result = $this->handler->extractPreRotationDimensions( array(
                        'physicalWidth' => self::TEST_WIDTH,
                        'physicalHeight' => self::TEST_HEIGHT,
index b84ed56..667c078 100644 (file)
@@ -1,6 +1,13 @@
 <?php
+
+/**
+ * @covers Exif
+ */
 class ExifTest extends MediaWikiTestCase {
 
+       /** @var string */
+       protected $mediaPath;
+
        protected function setUp() {
                parent::setUp();
                if ( !extension_loaded( 'exif' ) ) {
@@ -9,8 +16,6 @@ class ExifTest extends MediaWikiTestCase {
 
                $this->mediaPath = __DIR__ . '/../../data/media/';
 
-
-
                $this->setMwGlobals( 'wgShowEXIF', true );
        }
 
diff --git a/tests/phpunit/includes/media/FakeDimensionFile.php b/tests/phpunit/includes/media/FakeDimensionFile.php
new file mode 100644 (file)
index 0000000..7bc785e
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+
+class FakeDimensionFile extends File {
+       public $mustRender = false;
+
+       public function __construct( $dimensions ) {
+               parent::__construct( Title::makeTitle( NS_FILE, 'Test' ),
+                       new NullRepo( null ) );
+
+               $this->dimensions = $dimensions;
+       }
+
+       public function getWidth( $page = 1 ) {
+               return $this->dimensions[0];
+       }
+
+       public function getHeight( $page = 1 ) {
+               return $this->dimensions[1];
+       }
+
+       public function mustRender() {
+               return $this->mustRender;
+       }
+
+       public function getPath() {
+               return '';
+       }
+}
index bee0906..a4f71db 100644 (file)
@@ -1,6 +1,12 @@
 <?php
+
 class FormatMetadataTest extends MediaWikiTestCase {
 
+       /** @var FSFileBackend */
+       protected $backend;
+       /** @var FSRepo */
+       protected $repo;
+
        protected function setUp() {
                parent::setUp();
 
@@ -22,6 +28,9 @@ class FormatMetadataTest extends MediaWikiTestCase {
                $this->setMwGlobals( 'wgShowEXIF', true );
        }
 
+       /**
+        * @covers File::formatMetadata
+        */
        public function testInvalidDate() {
                $file = $this->dataFile( 'broken_exif_date.jpg', 'image/jpeg' );
 
@@ -43,6 +52,39 @@ class FormatMetadataTest extends MediaWikiTestCase {
                        'File with invalid date metadata (bug 29471)' );
        }
 
+       /**
+        * @param $filename String
+        * @param $expected Integer Total image area
+        * @dataProvider provideFlattenArray
+        * @covers FormatMetadata::flattenArray
+        */
+       public function testFlattenArray( $vals, $type, $noHtml, $ctx, $expected ) {
+               $actual = FormatMetadata::flattenArray( $vals, $type, $noHtml, $ctx );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public static function provideFlattenArray() {
+               return array(
+                       array(
+                               array( 1, 2, 3 ), 'ul', false, false,
+                               "<ul><li>1</li>\n<li>2</li>\n<li>3</li></ul>",
+                       ),
+                       array(
+                               array( 1, 2, 3 ), 'ol', false, false,
+                               "<ol><li>1</li>\n<li>2</li>\n<li>3</li></ol>",
+                       ),
+                       array(
+                               array( 1, 2, 3 ), 'ul', true, false,
+                               "\n*1\n*2\n*3",
+                       ),
+                       array(
+                               array( 1, 2, 3 ), 'ol', true, false,
+                               "\n#1\n#2\n#3",
+                       ),
+                       // TODO: more test cases
+               );
+       }
+
        private function dataFile( $name, $type ) {
                return new UnregisteredLocalFile( false, $this->repo,
                        "mwstore://localtesting/data/$name", $type );
index 86cf346..9e3f924 100644 (file)
@@ -12,6 +12,7 @@ class GIFMetadataExtractorTest extends MediaWikiTestCase {
         * @param $filename String
         * @param $expected Array The extracted metadata.
         * @dataProvider provideGetMetadata
+        * @covers GIFMetadataExtractor::getMetadata
         */
        public function testGetMetadata( $filename, $expected ) {
                $actual = GIFMetadataExtractor::getMetadata( $this->mediaPath . $filename );
index 7ea6b7e..4350cbb 100644 (file)
@@ -1,6 +1,15 @@
 <?php
 class GIFHandlerTest extends MediaWikiTestCase {
 
+       /** @var FSFileBackend */
+       protected $backend;
+       /** @var GIFHandler */
+       protected $handler;
+       /** @var FSRepo */
+       protected $repo;
+       /** @var string */
+       protected $filePath;
+
        protected function setUp() {
                parent::setUp();
 
@@ -18,6 +27,9 @@ class GIFHandlerTest extends MediaWikiTestCase {
                $this->handler = new GIFHandler();
        }
 
+       /**
+        * @covers GIFHandler::getMetadata
+        */
        public function testInvalidFile() {
                $res = $this->handler->getMetadata( null, $this->filePath . '/README' );
                $this->assertEquals( GIFHandler::BROKEN_FILE, $res );
@@ -27,6 +39,7 @@ class GIFHandlerTest extends MediaWikiTestCase {
         * @param $filename String basename of the file to check
         * @param $expected boolean Expected result.
         * @dataProvider provideIsAnimated
+        * @covers GIFHandler::isAnimatedImage
         */
        public function testIsAnimanted( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/gif' );
@@ -45,6 +58,7 @@ class GIFHandlerTest extends MediaWikiTestCase {
         * @param $filename String
         * @param $expected Integer Total image area
         * @dataProvider provideGetImageArea
+        * @covers GIFHandler::getImageArea
         */
        public function testGetImageArea( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/gif' );
@@ -63,6 +77,7 @@ class GIFHandlerTest extends MediaWikiTestCase {
         * @param $metadata String Serialized metadata
         * @param $expected Integer One of the class constants of GIFHandler
         * @dataProvider provideIsMetadataValid
+        * @covers GIFHandler::isMetadataValid
         */
        public function testIsMetadataValid( $metadata, $expected ) {
                $actual = $this->handler->isMetadataValid( null, $metadata );
@@ -83,6 +98,7 @@ class GIFHandlerTest extends MediaWikiTestCase {
         * @param $filename String
         * @param $expected String Serialized array
         * @dataProvider provideGetMetadata
+        * @covers GIFHandler::getMetadata
         */
        public function testGetMetadata( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/gif' );
@@ -97,6 +113,42 @@ class GIFHandlerTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @param $filename String
+        * @param $expected String Serialized array
+        * @dataProvider provideGetIndependentMetaArray
+        * @covers GIFHandler::getCommonMetaArray
+        */
+       public function testGetIndependentMetaArray( $filename, $expected ) {
+               $file = $this->dataFile( $filename, 'image/gif' );
+               $actual = $this->handler->getCommonMetaArray( $file );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetIndependentMetaArray() {
+               return array(
+                       array( 'nonanimated.gif', array(
+                               'GIFFileComment' => array(
+                                       'GIF test file ⁕ Created with GIMP',
+                               ),
+                       ) ),
+                       array( 'animated-xmp.gif',
+                               array(
+                                       'Artist' => 'Bawolff',
+                                       'ImageDescription' => array(
+                                               'x-default' => 'A file to test GIF',
+                                               '_type' => 'lang',
+                                       ),
+                                       'SublocationDest' => 'The interwebs',
+                                       'GIFFileComment' =>
+                                       array(
+                                               'GIƒ·test·file',
+                                       ),
+                               )
+                       ),
+               );
+       }
+
        private function dataFile( $name, $type ) {
                return new UnregisteredLocalFile( false, $this->repo,
                        "mwstore://localtesting/data/$name", $type );
index 81a58dd..81c1d28 100644 (file)
@@ -1,11 +1,19 @@
 <?php
+
 class IPTCTest extends MediaWikiTestCase {
+
+       /**
+        * @covers IPTC::getCharset
+        */
        public function testRecognizeUtf8() {
                // utf-8 is the only one used in practise.
                $res = IPTC::getCharset( "\x1b%G" );
                $this->assertEquals( 'UTF-8', $res );
        }
 
+       /**
+        * @covers IPTC::Parse
+        */
        public function testIPTCParseNoCharset88591() {
                // basically IPTC for keyword with value of 0xBC which is 1/4 in iso-8859-1
                // This data doesn't specify a charset. We're supposed to guess
@@ -15,17 +23,22 @@ class IPTCTest extends MediaWikiTestCase {
                $this->assertEquals( array( '¼' ), $res['Keywords'] );
        }
 
-       /* This one contains a sequence that's valid iso 8859-1 but not valid utf8 */
-       /* \xC3 = Ã, \xB8 = ¸  */
+       /**
+        * @covers IPTC::Parse
+        */
        public function testIPTCParseNoCharset88591b() {
+               /* This one contains a sequence that's valid iso 8859-1 but not valid utf8 */
+               /* \xC3 = Ã, \xB8 = ¸  */
                $iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x09\x1c\x02\x19\x00\x04\xC3\xC3\xC3\xB8";
                $res = IPTC::Parse( $iptcData );
                $this->assertEquals( array( 'ÃÃø' ), $res['Keywords'] );
        }
 
-       /* Same as testIPTCParseNoCharset88591b, but forcing the charset to utf-8.
+       /**
+        * Same as testIPTCParseNoCharset88591b, but forcing the charset to utf-8.
         * What should happen is the first "\xC3\xC3" should be dropped as invalid,
         * leaving \xC3\xB8, which is ø
+        * @covers IPTC::Parse
         */
        public function testIPTCParseForcedUTFButInvalid() {
                $iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x11\x1c\x02\x19\x00\x04\xC3\xC3\xC3\xB8"
@@ -34,13 +47,19 @@ class IPTCTest extends MediaWikiTestCase {
                $this->assertEquals( array( 'ø' ), $res['Keywords'] );
        }
 
+       /**
+        * @covers IPTC::Parse
+        */
        public function testIPTCParseNoCharsetUTF8() {
                $iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x07\x1c\x02\x19\x00\x02¼";
                $res = IPTC::Parse( $iptcData );
                $this->assertEquals( array( '¼' ), $res['Keywords'] );
        }
 
-       // Testing something that has 2 values for keyword
+       /**
+        * Testing something that has 2 values for keyword
+        * @covers IPTC::Parse
+        */
        public function testIPTCParseMulti() {
                $iptcData = /* identifier */ "Photoshop 3.0\08BIM\4\4"
                        /* length */ . "\0\0\0\0\0\x0D"
@@ -50,6 +69,9 @@ class IPTCTest extends MediaWikiTestCase {
                $this->assertEquals( array( '¼', '¼½' ), $res['Keywords'] );
        }
 
+       /**
+        * @covers IPTC::Parse
+        */
        public function testIPTCParseUTF8() {
                // This has the magic "\x1c\x01\x5A\x00\x03\x1B\x25\x47" which marks content as UTF8.
                $iptcData = "Photoshop 3.0\08BIM\4\4\0\0\0\0\0\x0F\x1c\x02\x19\x00\x02¼\x1c\x01\x5A\x00\x03\x1B\x25\x47";
index cae7137..7ffde3b 100644 (file)
@@ -5,9 +5,13 @@
  * 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.
+ *
+ * @covers JpegMetadataExtractor
  */
 class JpegMetadataExtractorTest extends MediaWikiTestCase {
 
+       protected $filePath;
+
        protected function setUp() {
                parent::setUp();
 
@@ -18,7 +22,7 @@ class JpegMetadataExtractorTest extends MediaWikiTestCase {
         * We also use this test to test padding bytes don't
         * screw stuff up
         *
-        * @param $file filename
+        * @param string $file filename
         *
         * @dataProvider provideUtf8Comment
         */
@@ -76,7 +80,6 @@ class JpegMetadataExtractorTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $res['XMP'] );
        }
 
-
        public function testIPTCHashComparisionNoHash() {
                $segments = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-psir.jpg' );
                $res = JpegMetadataExtractor::doPSIR( $segments['PSIR'][0] );
index 7775c41..bff64bb 100644 (file)
@@ -1,6 +1,11 @@
 <?php
+/**
+ * @covers JpegHandler
+ */
 class JpegTest extends MediaWikiTestCase {
 
+       protected $filePath;
+
        protected function setUp() {
                parent::setUp();
                if ( !extension_loaded( 'exif' ) ) {
@@ -9,22 +14,59 @@ class JpegTest extends MediaWikiTestCase {
 
                $this->filePath = __DIR__ . '/../../data/media/';
 
-
                $this->setMwGlobals( 'wgShowEXIF', true );
+
+               $this->backend = new FSFileBackend( array(
+                       'name' => 'localtesting',
+                       'lockManager' => 'nullLockManager',
+                       'containerPaths' => array( 'data' => $this->filePath )
+               ) );
+               $this->repo = new FSRepo( array(
+                       'name' => 'temp',
+                       'url' => 'http://localhost/thumbtest',
+                       'backend' => $this->backend
+               ) );
+
+               $this->handler = new JpegHandler;
        }
 
        public function testInvalidFile() {
-               $jpeg = new JpegHandler;
-               $res = $jpeg->getMetadata( null, $this->filePath . 'README' );
+               $file = $this->dataFile( 'README', 'image/jpeg' );
+               $res = $this->handler->getMetadata( $file, $this->filePath . 'README' );
                $this->assertEquals( ExifBitmapHandler::BROKEN_FILE, $res );
        }
 
        public function testJpegMetadataExtraction() {
-               $h = new JpegHandler;
-               $res = $h->getMetadata( null, $this->filePath . 'test.jpg' );
+               $file = $this->dataFile( 'test.jpg', 'image/jpeg' );
+               $res = $this->handler->getMetadata( $file, $this->filePath . 'test.jpg' );
                $expected = 'a:7:{s:16:"ImageDescription";s:9:"Test file";s:11:"XResolution";s:4:"72/1";s:11:"YResolution";s:4:"72/1";s:14:"ResolutionUnit";i:2;s:16:"YCbCrPositioning";i:1;s:15:"JPEGFileComment";a:1:{i:0;s:17:"Created with GIMP";}s:22:"MEDIAWIKI_EXIF_VERSION";i:2;}';
 
                // Unserialize in case serialization format ever changes.
                $this->assertEquals( unserialize( $expected ), unserialize( $res ) );
        }
+
+       /**
+        * @covers JpegHandler::getCommonMetaArray
+        */
+       public function testGetIndependentMetaArray() {
+               $file = $this->dataFile( 'test.jpg', 'image/jpeg' );
+               $res = $this->handler->getCommonMetaArray( $file );
+               $expected = array(
+                       'ImageDescription' => 'Test file',
+                       'XResolution' => '72/1',
+                       'YResolution' => '72/1',
+                       'ResolutionUnit' => 2,
+                       'YCbCrPositioning' => 1,
+                       'JPEGFileComment' => array(
+                               'Created with GIMP',
+                       ),
+               );
+
+               $this->assertEquals( $res, $expected );
+       }
+
+       private function dataFile( $name, $type ) {
+               return new UnregisteredLocalFile( false, $this->repo,
+                       "mwstore://localtesting/data/$name", $type );
+       }
 }
index 4e4c649..c28898b 100644 (file)
@@ -1,7 +1,12 @@
 <?php
 
 class MediaHandlerTest extends MediaWikiTestCase {
-       function testFitBoxWidth() {
+
+       /**
+        * @covers MediaHandler::fitBoxWidth
+        * @todo split into a dataprovider and test method
+        */
+       public function testFitBoxWidth() {
                $vals = array(
                        array(
                                'width' => 50,
index 58d791f..84deb1b 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @covers PNGMetadataExtractor
+ */
 class PNGMetadataExtractorTest extends MediaWikiTestCase {
 
        protected function setUp() {
@@ -9,7 +13,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
        /**
         * Tests zTXt tag (compressed textual metadata)
         */
-       function testPngNativetZtxt() {
+       public function testPngNativetZtxt() {
                $this->checkPHPExtension( 'zlib' );
 
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
@@ -26,7 +30,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
        /**
         * Test tEXt tag (Uncompressed textual metadata)
         */
-       function testPngNativeText() {
+       public function testPngNativeText() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
                $expected = "Some long image desc";
@@ -43,7 +47,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
         * tEXt tags must be encoded iso-8859-1 (vs iTXt which are utf-8)
         * Make sure non-ascii characters get converted properly
         */
-       function testPngNativeTextNonAscii() {
+       public function testPngNativeTextNonAscii() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
 
@@ -65,7 +69,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
         * actual resolution of the image is (aka in dots per meter).
         */
        /*
-       function testPngPhysTag() {
+       public function testPngPhysTag() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
 
@@ -81,7 +85,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
        /**
         * Given a normal static PNG, check the animation metadata returned.
         */
-       function testStaticPngAnimationMetadata() {
+       public function testStaticPngAnimationMetadata() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
 
@@ -94,7 +98,7 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
         * Given an animated APNG image file
         * check it gets animated metadata right.
         */
-       function testApngAnimationMetadata() {
+       public function testApngAnimationMetadata() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Animated_PNG_example_bouncing_beach_ball.png' );
 
@@ -104,46 +108,45 @@ class PNGMetadataExtractorTest extends MediaWikiTestCase {
                $this->assertEquals( 1.5, $meta['duration'], '', 0.00001 );
        }
 
-       function testPngBitDepth8() {
+       public function testPngBitDepth8() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
 
                $this->assertEquals( 8, $meta['bitDepth'] );
        }
 
-       function testPngBitDepth1() {
+       public function testPngBitDepth1() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        '1bit-png.png' );
                $this->assertEquals( 1, $meta['bitDepth'] );
        }
 
-
-       function testPngIndexColour() {
+       public function testPngIndexColour() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'Png-native-test.png' );
 
                $this->assertEquals( 'index-coloured', $meta['colorType'] );
        }
 
-       function testPngRgbColour() {
+       public function testPngRgbColour() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'rgb-png.png' );
                $this->assertEquals( 'truecolour-alpha', $meta['colorType'] );
        }
 
-       function testPngRgbNoAlphaColour() {
+       public function testPngRgbNoAlphaColour() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'rgb-na-png.png' );
                $this->assertEquals( 'truecolour', $meta['colorType'] );
        }
 
-       function testPngGreyscaleColour() {
+       public function testPngGreyscaleColour() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'greyscale-png.png' );
                $this->assertEquals( 'greyscale-alpha', $meta['colorType'] );
        }
 
-       function testPngGreyscaleNoAlphaColour() {
+       public function testPngGreyscaleNoAlphaColour() {
                $meta = PNGMetadataExtractor::getMetadata( $this->filePath .
                        'greyscale-na-png.png' );
                $this->assertEquals( 'greyscale', $meta['colorType'] );
index 855780d..2cb7426 100644 (file)
@@ -1,6 +1,15 @@
 <?php
 class PNGHandlerTest extends MediaWikiTestCase {
 
+       /** @var PNGHandler */
+       protected $handler;
+       /** @var FSRepo */
+       protected $repo;
+       /** @var FSFileBackend */
+       protected $backend;
+       /** @var string */
+       protected $filePath;
+
        protected function setUp() {
                parent::setUp();
 
@@ -18,6 +27,9 @@ class PNGHandlerTest extends MediaWikiTestCase {
                $this->handler = new PNGHandler();
        }
 
+       /**
+        * @covers PNGHandler::getMetadata
+        */
        public function testInvalidFile() {
                $res = $this->handler->getMetadata( null, $this->filePath . '/README' );
                $this->assertEquals( PNGHandler::BROKEN_FILE, $res );
@@ -27,6 +39,7 @@ class PNGHandlerTest extends MediaWikiTestCase {
         * @param $filename String basename of the file to check
         * @param $expected boolean Expected result.
         * @dataProvider provideIsAnimated
+        * @covers PNGHandler::isAnimatedImage
         */
        public function testIsAnimanted( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/png' );
@@ -45,6 +58,7 @@ class PNGHandlerTest extends MediaWikiTestCase {
         * @param $filename String
         * @param $expected Integer Total image area
         * @dataProvider provideGetImageArea
+        * @covers PNGHandler::getImageArea
         */
        public function testGetImageArea( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/png' );
@@ -65,6 +79,7 @@ class PNGHandlerTest extends MediaWikiTestCase {
         * @param $metadata String Serialized metadata
         * @param $expected Integer One of the class constants of PNGHandler
         * @dataProvider provideIsMetadataValid
+        * @covers PNGHandler::isMetadataValid
         */
        public function testIsMetadataValid( $metadata, $expected ) {
                $actual = $this->handler->isMetadataValid( null, $metadata );
@@ -85,6 +100,7 @@ class PNGHandlerTest extends MediaWikiTestCase {
         * @param $filename String
         * @param $expected String Serialized array
         * @dataProvider provideGetMetadata
+        * @covers PNGHandler::getMetadata
         */
        public function testGetMetadata( $filename, $expected ) {
                $file = $this->dataFile( $filename, 'image/png' );
@@ -100,6 +116,29 @@ class PNGHandlerTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @param $filename String
+        * @param $expected Array Expected standard metadata
+        * @dataProvider provideGetIndependentMetaArray
+        * @covers PNGHandler::getCommonMetaArray
+        */
+       public function testGetIndependentMetaArray( $filename, $expected ) {
+               $file = $this->dataFile( $filename, 'image/png' );
+               $actual = $this->handler->getCommonMetaArray( $file );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public function provideGetIndependentMetaArray() {
+               return array(
+                       array( 'rgb-na-png.png', array() ),
+                       array( 'xmp.png',
+                               array(
+                                       'SerialNumber' => '123456789',
+                               )
+                       ),
+               );
+       }
+
        private function dataFile( $name, $type ) {
                return new UnregisteredLocalFile( false, $this->repo,
                        "mwstore://localtesting/data/$name", $type );
index 3bf9c59..d00a33d 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+/**
+ * @covers SVGMetadataExtractor
+ */
 class SVGMetadataExtractorTest extends MediaWikiTestCase {
 
        protected function setUp() {
@@ -10,14 +13,14 @@ class SVGMetadataExtractorTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideSvgFiles
         */
-       function testGetMetadata( $infile, $expected ) {
+       public function testGetMetadata( $infile, $expected ) {
                $this->assertMetadata( $infile, $expected );
        }
 
        /**
         * @dataProvider provideSvgFilesWithXMLMetadata
         */
-       function testGetXMLMetadata( $infile, $expected ) {
+       public function testGetXMLMetadata( $infile, $expected ) {
                $r = new XMLReader();
                if ( !method_exists( $r, 'readInnerXML' ) ) {
                        $this->markTestSkipped( 'XMLReader::readInnerXML() does not exist (libxml >2.6.20 needed).' );
@@ -80,6 +83,17 @@ class SVGMetadataExtractorTest extends MediaWikiTestCase {
                                        'originalWidth' => '385',
                                        'originalHeight' => '385.0004883',
                                )
+                       ),
+                       array(
+                               "$base/Tux.svg",
+                               array(
+                                       'width' => 512,
+                                       'height' => 594,
+                                       'originalWidth' => '100%',
+                                       'originalHeight' => '100%',
+                                       'title' => 'Tux',
+                                       'description' => 'For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg',
+                               )
                        )
                );
        }
diff --git a/tests/phpunit/includes/media/SVGTest.php b/tests/phpunit/includes/media/SVGTest.php
new file mode 100644 (file)
index 0000000..e0fae71
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+class SvgTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->filePath = __DIR__ . '/../../data/media/';
+
+               $this->setMwGlobals( 'wgShowEXIF', true );
+
+               $this->backend = new FSFileBackend( array(
+                       'name' => 'localtesting',
+                       'lockManager' => 'nullLockManager',
+                       'containerPaths' => array( 'data' => $this->filePath )
+               ) );
+               $this->repo = new FSRepo( array(
+                       'name' => 'temp',
+                       'url' => 'http://localhost/thumbtest',
+                       'backend' => $this->backend
+               ) );
+
+               $this->handler = new SvgHandler;
+       }
+
+       /**
+        * @param $filename String
+        * @param $expected Array The expected independent metadata
+        * @dataProvider providerGetIndependentMetaArray
+        * @covers SvgHandler::getCommonMetaArray
+        */
+       public function testGetIndependentMetaArray( $filename, $expected ) {
+               $file = $this->dataFile( $filename, 'image/svg+xml' );
+               $res = $this->handler->getCommonMetaArray( $file );
+
+               $this->assertEquals( $res, $expected );
+       }
+
+       public function providerGetIndependentMetaArray() {
+               return array(
+                       array( 'Tux.svg', array(
+                               'ObjectName' => 'Tux',
+                               'ImageDescription' => 'For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg',
+                       ) ),
+                       array( 'Wikimedia-logo.svg', array() )
+               );
+       }
+
+       private function dataFile( $name, $type ) {
+               return new UnregisteredLocalFile( false, $this->repo,
+                       "mwstore://localtesting/data/$name", $type );
+       }
+}
index 1ec34d5..8d74b98 100644 (file)
@@ -1,6 +1,11 @@
 <?php
 class TiffTest extends MediaWikiTestCase {
 
+       /** @var TiffHandler */
+       protected $handler;
+       /** @var string */
+       protected $filePath;
+
        protected function setUp() {
                parent::setUp();
                if ( !extension_loaded( 'exif' ) ) {
@@ -13,11 +18,17 @@ class TiffTest extends MediaWikiTestCase {
                $this->handler = new TiffHandler;
        }
 
+       /**
+        * @covers TiffHandler::getMetadata
+        */
        public function testInvalidFile() {
                $res = $this->handler->getMetadata( null, $this->filePath . 'README' );
                $this->assertEquals( ExifBitmapHandler::BROKEN_FILE, $res );
        }
 
+       /**
+        * @covers TiffHandler::getMetadata
+        */
        public function testTiffMetadataExtraction() {
                $res = $this->handler->getMetadata( null, $this->filePath . 'test.tiff' );
                $expected = 'a:16:{s:10:"ImageWidth";i:20;s:11:"ImageLength";i:20;s:13:"BitsPerSample";a:3:{i:0;i:8;i:1;i:8;i:2;i:8;}s:11:"Compression";i:5;s:25:"PhotometricInterpretation";i:2;s:16:"ImageDescription";s:17:"Created with GIMP";s:12:"StripOffsets";i:8;s:11:"Orientation";i:1;s:15:"SamplesPerPixel";i:3;s:12:"RowsPerStrip";i:64;s:15:"StripByteCounts";i:238;s:11:"XResolution";s:19:"1207959552/16777216";s:11:"YResolution";s:19:"1207959552/16777216";s:19:"PlanarConfiguration";i:1;s:14:"ResolutionUnit";i:2;s:22:"MEDIAWIKI_EXIF_VERSION";i:2;}';
index aa0cdd2..9ec5796 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+
+/**
+ * @todo covers tags
+ */
 class XMPTest extends MediaWikiTestCase {
 
        protected function setUp() {
@@ -15,7 +19,10 @@ class XMPTest extends MediaWikiTestCase {
         * @param $expected Array expected result of parsing the xmp.
         * @param $info String Short sentence on what's being tested.
         *
+        * @throws Exception
         * @dataProvider provideXMPParse
+        *
+        * @covers XMPReader::parse
         */
        public function testXMPParse( $xmp, $expected, $info ) {
                if ( !is_string( $xmp ) || !is_array( $expected ) ) {
@@ -74,8 +81,10 @@ class XMPTest extends MediaWikiTestCase {
         *
         * @todo This is based on what the standard says. Need to find a real
         * world example file to double check the support for this is right.
+        *
+        * @covers XMPReader::parseExtended
         */
-       function testExtendedXMP() {
+       public function testExtendedXMP() {
                $xmpPath = __DIR__ . '/../../data/xmp/';
                $standardXMP = file_get_contents( $xmpPath . 'xmpExt.xmp' );
                $extendedXMP = file_get_contents( $xmpPath . 'xmpExt2.xmp' );
@@ -104,8 +113,10 @@ class XMPTest extends MediaWikiTestCase {
        /**
         * This test has an extended XMP block with a wrong guid (md5sum)
         * and thus should only return the StandardXMP, not the ExtendedXMP.
+        *
+        * @covers XMPReader::parseExtended
         */
-       function testExtendedXMPWithWrongGUID() {
+       public function testExtendedXMPWithWrongGUID() {
                $xmpPath = __DIR__ . '/../../data/xmp/';
                $standardXMP = file_get_contents( $xmpPath . 'xmpExt.xmp' );
                $extendedXMP = file_get_contents( $xmpPath . 'xmpExt2.xmp' );
@@ -133,8 +144,10 @@ class XMPTest extends MediaWikiTestCase {
        /**
         * Have a high offset to simulate a missing packet,
         * which should cause it to ignore the ExtendedXMP packet.
+        *
+        * @covers XMPReader::parseExtended
         */
-       function testExtendedXMPMissingPacket() {
+       public function testExtendedXMPMissingPacket() {
                $xmpPath = __DIR__ . '/../../data/xmp/';
                $standardXMP = file_get_contents( $xmpPath . 'xmpExt.xmp' );
                $extendedXMP = file_get_contents( $xmpPath . 'xmpExt2.xmp' );
index 257c40a..96bf5e4 100644 (file)
@@ -3,8 +3,9 @@ class XMPValidateTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideDates
+        * @covers XMPValidate::validateDate
         */
-       function testValidateDate( $value, $expected ) {
+       public function testValidateDate( $value, $expected ) {
                // The method should modify $value.
                XMPValidate::validateDate( array(), $value, true );
                $this->assertEquals( $expected, $value );
index 68efd86..a495700 100644 (file)
  * @ingroup UtfNormal
  * @group Large
  *
+ * @todo covers tags, will be UtfNormal::cleanUp once the below is resolved
+ * @todo split me into test methods and providers per the below comment
+ *
  * We ignore code coverage for this test suite until they are rewritten
  * to use data providers (bug 46561).
  * @codeCoverageIgnore
  */
 class CleanUpTest extends MediaWikiTestCase {
        /** @todo document */
-       function testAscii() {
+       public function testAscii() {
                $text = 'This is plain ASCII text.';
                $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
        }
 
        /** @todo document */
-       function testNull() {
+       public function testNull() {
                $text = "a \x00 null";
                $expect = "a \xef\xbf\xbd null";
                $this->assertEquals(
@@ -52,13 +55,13 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testLatin() {
+       public function testLatin() {
                $text = "L'\xc3\xa9cole";
                $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
        }
 
        /** @todo document */
-       function testLatinNormal() {
+       public function testLatinNormal() {
                $text = "L'e\xcc\x81cole";
                $expect = "L'\xc3\xa9cole";
                $this->assertEquals( $expect, UtfNormal::cleanUp( $text ) );
@@ -105,7 +108,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testAllBytes() {
+       public function testAllBytes() {
                $this->doTestBytes( '', '' );
                $this->doTestBytes( 'x', '' );
                $this->doTestBytes( '', 'x' );
@@ -145,7 +148,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testDoubleBytes() {
+       public function testDoubleBytes() {
                $this->doTestDoubleBytes( '', '' );
                $this->doTestDoubleBytes( 'x', '' );
                $this->doTestDoubleBytes( '', 'x' );
@@ -198,7 +201,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testTripleBytes() {
+       public function testTripleBytes() {
                $this->doTestTripleBytes( '', '' );
                $this->doTestTripleBytes( 'x', '' );
                $this->doTestTripleBytes( '', 'x' );
@@ -276,7 +279,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testChunkRegression() {
+       public function testChunkRegression() {
                # Check for regression against a chunking bug
                $text = "\x46\x55\xb8" .
                        "\xdc\x96" .
@@ -299,7 +302,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testInterposeRegression() {
+       public function testInterposeRegression() {
                $text = "\x4e\x30" .
                        "\xb1" . # bad tail
                        "\x3a" .
@@ -334,7 +337,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testOverlongRegression() {
+       public function testOverlongRegression() {
                $text = "\x67" .
                        "\x1a" . # forbidden ascii
                        "\xea" . # bad head
@@ -359,7 +362,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testSurrogateRegression() {
+       public function testSurrogateRegression() {
                $text = "\xed\xb4\x96" . # surrogate 0xDD16
                        "\x83" . # bad tail
                        "\xb4" . # bad tail
@@ -374,7 +377,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testBomRegression() {
+       public function testBomRegression() {
                $text = "\xef\xbf\xbe" . # U+FFFE, illegal char
                        "\xb2" . # bad tail
                        "\xef" . # bad head
@@ -389,7 +392,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testForbiddenRegression() {
+       public function testForbiddenRegression() {
                $text = "\xef\xbf\xbf"; # U+FFFF, illegal char
                $expect = "\xef\xbf\xbd";
                $this->assertEquals(
@@ -398,7 +401,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       function testHangulRegression() {
+       public function testHangulRegression() {
                $text = "\xed\x9c\xaf" . # Hangul char
                        "\xe1\x87\x81"; # followed by another final jamo
                $expect = $text; # Should *not* change.
index e90c630..eac4de5 100644 (file)
@@ -631,6 +631,7 @@ class NewParserTest extends MediaWikiTestCase {
                        $out = $parser->getPreloadText( $input, $title, $options );
                } else {
                        $output = $parser->parse( $input, $title, $options, true, true, 1337 );
+                       $output->setTOCEnabled( !isset( $opts['notoc'] ) );
                        $out = $output->getText();
 
                        if ( isset( $opts['showtitle'] ) ) {
@@ -672,7 +673,7 @@ class NewParserTest extends MediaWikiTestCase {
         *
         * @group ParserFuzz
         */
-       function testFuzzTests() {
+       public function testFuzzTests() {
                global $wgParserTestFiles;
 
                $files = $wgParserTestFiles;
index 0d2e07e..8aee937 100644 (file)
@@ -233,7 +233,7 @@ class PreprocessorTest extends MediaWikiTestCase {
         * @dataProvider provideHeadings
         * @covers Preprocessor_DOM::preprocessToXml
         */
-       function testHeadings( $wikiText, $expectedXml ) {
+       public function testHeadings( $wikiText, $expectedXml ) {
                $this->assertEquals( $this->normalizeXml( $expectedXml ), $this->preprocessToXml( $wikiText ) );
        }
 }
index ed60079..259a9e2 100644 (file)
@@ -20,8 +20,9 @@ class TagHookTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideValidNames
+        * @covers Parser::setHook
         */
-       function testTagHooks( $tag ) {
+       public function testTagHooks( $tag ) {
                global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
 
@@ -35,8 +36,9 @@ class TagHookTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideBadNames
         * @expectedException MWException
+        * @covers Parser::setHook
         */
-       function testBadTagHooks( $tag ) {
+       public function testBadTagHooks( $tag ) {
                global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
 
@@ -47,8 +49,9 @@ class TagHookTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideValidNames
+        * @covers Parser::setFunctionTagHook
         */
-       function testFunctionTagHooks( $tag ) {
+       public function testFunctionTagHooks( $tag ) {
                global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
 
@@ -62,8 +65,9 @@ class TagHookTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideBadNames
         * @expectedException MWException
+        * @covers Parser::setFunctionTagHook
         */
-       function testBadFunctionTagHooks( $tag ) {
+       public function testBadFunctionTagHooks( $tag ) {
                global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
 
diff --git a/tests/phpunit/includes/parser/TidyTest.php b/tests/phpunit/includes/parser/TidyTest.php
new file mode 100644 (file)
index 0000000..12aac69
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @group Parser
+ */
+class TidyTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+               $check = MWTidy::tidy( '' );
+               if ( strpos( $check, '<!--' ) !== false ) {
+                       $this->markTestSkipped( 'Tidy not found' );
+               }
+       }
+
+       /**
+        * @dataProvider provideTestWrapping
+        */
+       public function testTidyWrapping( $expected, $text, $msg = '' ) {
+               $text = MWTidy::tidy( $text );
+               // We don't care about where Tidy wants to stick is <p>s
+               $text = trim( preg_replace( '#</?p>#', '', $text ) );
+               // Windows, we love you!
+               $text = str_replace( "\r", '', $text );
+               $this->assertEquals( $expected, $text, $msg );
+       }
+
+       public function provideTestWrapping() {
+               return array(
+                       array(
+                               '<mw:editsection page="foo" section="bar">foo</mw:editsection>',
+                               '<mw:editsection page="foo" section="bar">foo</mw:editsection>',
+                               '<mw:editsection> should survive tidy'
+                       ),
+                       array(
+                               '<editsection page="foo" section="bar">foo</editsection>',
+                               '<editsection page="foo" section="bar">foo</editsection>',
+                               '<editsection> should survive tidy'
+                       ),
+                       array( '<mw:toc>foo</mw:toc>', '<mw:toc>foo</mw:toc>', '<mw:toc> should survive tidy' ),
+                       array( "<link foo=\"bar\" />\nfoo", '<link foo="bar"/>foo', '<link> should survive tidy' ),
+                       array( "<meta foo=\"bar\" />\nfoo", '<meta foo="bar"/>foo', '<meta> should survive tidy' ),
+               );
+       }
+}
index 8957a2f..e460591 100644 (file)
@@ -3,9 +3,16 @@
 /**
  * @group Search
  * @group Database
+ *
+ * @covers SearchEngine<extended>
+ * @note Coverage will only ever show one of on of the Search* classes
  */
 class SearchEngineTest extends MediaWikiLangTestCase {
-       protected $search, $pageList;
+       /**
+        * @var SearchEngine
+        */
+       protected $search;
+       protected $pageList;
 
        /**
         * Checks for database type & version.
@@ -115,7 +122,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                return true;
        }
 
-       function testFullWidth() {
+       public function testFullWidth() {
                $this->assertEquals(
                        array( 'FullOneUp', 'FullTwoLow', 'HalfOneUp', 'HalfTwoLow' ),
                        $this->fetchIds( $this->search->searchText( 'AZ' ) ),
@@ -134,14 +141,14 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                        "Search for normalized from Full-width Lower" );
        }
 
-       function testTextSearch() {
+       public function testTextSearch() {
                $this->assertEquals(
                        array( 'Smithee' ),
                        $this->fetchIds( $this->search->searchText( 'smithee' ) ),
                        "Plain search failed" );
        }
 
-       function testTextPowerSearch() {
+       public function testTextPowerSearch() {
                $this->search->setNamespaces( array( 0, 1, 4 ) );
                $this->assertEquals(
                        array(
@@ -152,7 +159,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                        "Power search failed" );
        }
 
-       function testTitleSearch() {
+       public function testTitleSearch() {
                $this->assertEquals(
                        array(
                                'Alan Smithee',
@@ -162,7 +169,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                        "Title search failed" );
        }
 
-       function testTextTitlePowerSearch() {
+       public function testTextTitlePowerSearch() {
                $this->search->setNamespaces( array( 0, 1, 4 ) );
                $this->assertEquals(
                        array(
index e947c34..b913af8 100644 (file)
@@ -30,7 +30,10 @@ class SearchUpdateTest extends MediaWikiTestCase {
                return trim( SearchUpdate::updateText( $text ) );
        }
 
-       function testUpdateText() {
+       /**
+        * @covers SearchUpdate::updateText
+        */
+       public function testUpdateText() {
                $this->assertEquals(
                        'test',
                        $this->updateText( '<div>TeSt</div>' ),
@@ -62,7 +65,10 @@ EOT
                );
        }
 
-       function testBug32712() {
+       /**
+        * @covers SearchUpdate::updateText
+        */
+       public function testBug32712() {
                $text = "text „http://example.com“ text";
                $result = $this->updateText( $text );
                $processed = preg_replace( '/Q/u', 'Q', $result );
index 3b82e07..ba845eb 100644 (file)
@@ -15,6 +15,9 @@ if ( !defined( 'MEDIAWIKI' ) ) {
 global $IP;
 require_once "$IP/includes/QueryPage.php"; // Needed to populate $wgQueryPages
 
+/**
+ * @covers QueryPage<extended>
+ */
 class QueryAllSpecialPagesTest extends MediaWikiTestCase {
 
        /** List query pages that can not be tested automatically */
@@ -51,7 +54,7 @@ class QueryAllSpecialPagesTest extends MediaWikiTestCase {
         * Test SQL for each of our QueryPages objects
         * @group Database
         */
-       function testQuerypageSqlQuery() {
+       public function testQuerypageSqlQuery() {
                global $wgDBtype;
 
                foreach ( $this->queryPages as $page ) {
index c7a4828..8a92daf 100644 (file)
@@ -7,6 +7,9 @@
  *
  */
 
+/**
+ * @covers SpecialPreferences
+ */
 class SpecialPreferencesTest extends MediaWikiTestCase {
 
        /**
@@ -15,7 +18,7 @@ class SpecialPreferencesTest extends MediaWikiTestCase {
         *
         * Test specifications by Alexandre "ialex" Emsenhuber.
         */
-       function testBug41337() {
+       public function testBug41337() {
 
                // Set a low limit
                $this->setMwGlobals( 'wgMaxSigChars', 2 );
index 436eb2e..b1ba152 100644 (file)
@@ -6,6 +6,8 @@
  *
  * @author Antoine Musso
  * @group Database
+ *
+ * @covers SpecialRecentChanges
  */
 class SpecialRecentchangesTest extends MediaWikiTestCase {
 
index c737f05..4ccf5d7 100644 (file)
@@ -18,7 +18,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
         * @param $expectedProfile An expected search profile name
         * @param $expectedNs Array Expected namespaces
         */
-       function testProfileAndNamespaceLoading(
+       public function testProfileAndNamespaceLoading(
                $requested, $userOptions, $expectedProfile, $expectedNS,
                $message = 'Profile name and namespaces mismatches!'
        ) {
@@ -46,12 +46,12 @@ class SpecialSearchTest extends MediaWikiTestCase {
                        array( /** Expected: */
                                'ProfileName' => $expectedProfile,
                                'Namespaces' => $expectedNS,
-                       )
-                       array( /** Actual: */
+                       ),
+                       array( /** Actual: */
                                'ProfileName' => $search->getProfile(),
                                'Namespaces' => $search->getNamespaces(),
-                       )
-                       $message
+                       ),
+                       $message
                );
        }
 
@@ -112,7 +112,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
         * Verify we do not expand search term in <title> on search result page
         * https://gerrit.wikimedia.org/r/4841
         */
-       function testSearchTermIsNotExpanded() {
+       public function testSearchTermIsNotExpanded() {
 
                # Initialize [[Special::Search]]
                $search = new SpecialSearch();
index 982b46b..4f17601 100644 (file)
@@ -26,7 +26,6 @@ class UploadBaseTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
-
        /**
         * First checks the return code
         * of UploadBase::getTitle() and then the actual returned title
index a75fba6..397c100 100644 (file)
@@ -4,6 +4,8 @@
  * @group Broken
  * @group Upload
  * @group Database
+ *
+ * @covers UploadFromUrl
  */
 class UploadFromUrlTest extends ApiTestCase {
        protected function setUp() {
@@ -46,35 +48,6 @@ class UploadFromUrlTest extends ApiTestCase {
        }
 
        /**
-        * @todo Document why we test login, since the $wgUser hack used doesn't
-        * require login
-        */
-       public function testLogin() {
-               $data = $this->doApiRequest( array(
-                       'action' => 'login',
-                       'lgname' => $this->user->userName,
-                       'lgpassword' => $this->user->passWord ) );
-               $this->assertArrayHasKey( "login", $data[0] );
-               $this->assertArrayHasKey( "result", $data[0]['login'] );
-               $this->assertEquals( "NeedToken", $data[0]['login']['result'] );
-               $token = $data[0]['login']['token'];
-
-               $data = $this->doApiRequest( array(
-                       'action' => 'login',
-                       "lgtoken" => $token,
-                       'lgname' => $this->user->userName,
-                       'lgpassword' => $this->user->passWord ) );
-
-               $this->assertArrayHasKey( "login", $data[0] );
-               $this->assertArrayHasKey( "result", $data[0]['login'] );
-               $this->assertEquals( "Success", $data[0]['login']['result'] );
-               $this->assertArrayHasKey( 'lgtoken', $data[0]['login'] );
-
-               return $data;
-       }
-
-       /**
-        * @depends testLogin
         * @depends testClearQueue
         */
        public function testSetupUrlDownload( $data ) {
@@ -148,7 +121,6 @@ class UploadFromUrlTest extends ApiTestCase {
        }
 
        /**
-        * @depends testLogin
         * @depends testClearQueue
         */
        public function testAsyncUpload( $data ) {
@@ -167,7 +139,6 @@ class UploadFromUrlTest extends ApiTestCase {
        }
 
        /**
-        * @depends testLogin
         * @depends testClearQueue
         */
        public function testAsyncUploadWarning( $data ) {
@@ -197,7 +168,6 @@ class UploadFromUrlTest extends ApiTestCase {
        }
 
        /**
-        * @depends testLogin
         * @depends testClearQueue
         */
        public function testSyncDownload( $data ) {
@@ -329,9 +299,6 @@ class UploadFromUrlTest extends ApiTestCase {
                return $data;
        }
 
-       /**
-        *
-        */
        protected function deleteFile( $name ) {
                $t = Title::newFromText( $name, NS_FILE );
                $this->assertTrue( $t->exists(), "File '$name' exists" );
index 7a0fea4..1c89377 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 /**
  * @group Database
+ *
+ * @covers UploadStash
  */
 class UploadStashTest extends MediaWikiTestCase {
        /**
diff --git a/tests/phpunit/includes/utils/CdbTest.php b/tests/phpunit/includes/utils/CdbTest.php
new file mode 100644 (file)
index 0000000..487ee1f
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Test the CDB reader/writer
+ * @covers CdbWriterPHP
+ * @covers CdbWriterDBA
+ */
+class CdbTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+               if ( !CdbReader::haveExtension() ) {
+                       $this->markTestSkipped( 'Native CDB support is not available' );
+               }
+       }
+
+       /**
+        * @group medium
+        */
+       public function testCdb() {
+               $dir = wfTempDir();
+               if ( !is_writable( $dir ) ) {
+                       $this->markTestSkipped( "Temp dir isn't writable" );
+               }
+
+               $phpcdbfile = $this->getNewTempFile();
+               $dbacdbfile = $this->getNewTempFile();
+
+               $w1 = new CdbWriterPHP( $phpcdbfile );
+               $w2 = new CdbWriterDBA( $dbacdbfile );
+
+               $data = array();
+               for ( $i = 0; $i < 1000; $i++ ) {
+                       $key = $this->randomString();
+                       $value = $this->randomString();
+                       $w1->set( $key, $value );
+                       $w2->set( $key, $value );
+
+                       if ( !isset( $data[$key] ) ) {
+                               $data[$key] = $value;
+                       }
+               }
+
+               $w1->close();
+               $w2->close();
+
+               $this->assertEquals(
+                       md5_file( $phpcdbfile ),
+                       md5_file( $dbacdbfile ),
+                       'same hash'
+               );
+
+               $r1 = new CdbReaderPHP( $phpcdbfile );
+               $r2 = new CdbReaderDBA( $dbacdbfile );
+
+               foreach ( $data as $key => $value ) {
+                       if ( $key === '' ) {
+                               // Known bug
+                               continue;
+                       }
+                       $v1 = $r1->get( $key );
+                       $v2 = $r2->get( $key );
+
+                       $v1 = $v1 === false ? '(not found)' : $v1;
+                       $v2 = $v2 === false ? '(not found)' : $v2;
+
+                       # cdbAssert( 'Mismatch', $key, $v1, $v2 );
+                       $this->cdbAssert( "PHP error", $key, $v1, $value );
+                       $this->cdbAssert( "DBA error", $key, $v2, $value );
+               }
+       }
+
+       private function randomString() {
+               $len = mt_rand( 0, 10 );
+               $s = '';
+               for ( $j = 0; $j < $len; $j++ ) {
+                       $s .= chr( mt_rand( 0, 255 ) );
+               }
+
+               return $s;
+       }
+
+       private function cdbAssert( $msg, $key, $v1, $v2 ) {
+               $this->assertEquals(
+                       $v2,
+                       $v1,
+                       $msg . ', k=' . bin2hex( $key )
+               );
+       }
+}
diff --git a/tests/phpunit/includes/utils/HashRingTest.php b/tests/phpunit/includes/utils/HashRingTest.php
new file mode 100644 (file)
index 0000000..68dfea1
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @group HashRing
+ */
+class HashRingTest extends MediaWikiTestCase {
+       /**
+        * @covers HashRing
+        */
+       public function testHashRing() {
+               $ring = new HashRing( array( 's1' => 1, 's2' => 1, 's3' => 2, 's4' => 2, 's5' => 2, 's6' => 3 ) );
+
+               $locations = array();
+               for ( $i = 0; $i < 20; $i++ ) {
+                       $locations[ "hello$i"] = $ring->getLocation( "hello$i" );
+               }
+               $expectedLocations = array(
+                       "hello0" => "s5",
+                       "hello1" => "s6",
+                       "hello2" => "s2",
+                       "hello3" => "s5",
+                       "hello4" => "s6",
+                       "hello5" => "s4",
+                       "hello6" => "s5",
+                       "hello7" => "s4",
+                       "hello8" => "s5",
+                       "hello9" => "s5",
+                       "hello10" => "s3",
+                       "hello11" => "s6",
+                       "hello12" => "s1",
+                       "hello13" => "s3",
+                       "hello14" => "s3",
+                       "hello15" => "s5",
+                       "hello16" => "s4",
+                       "hello17" => "s6",
+                       "hello18" => "s6",
+                       "hello19" => "s3"
+               );
+
+               $this->assertEquals( $expectedLocations, $locations, 'Items placed at proper locations' );
+
+               $locations = array();
+               for ( $i = 0; $i < 5; $i++ ) {
+                       $locations[ "hello$i"] = $ring->getLocations( "hello$i", 2 );
+               }
+
+               $expectedLocations = array(
+                       "hello0" => array( "s5", "s6" ),
+                       "hello1" => array( "s6", "s4" ),
+                       "hello2" => array( "s2", "s1" ),
+                       "hello3" => array( "s5", "s6" ),
+                       "hello4" => array( "s6", "s4" ),
+               );
+               $this->assertEquals( $expectedLocations, $locations, 'Items placed at proper locations' );
+       }
+}
diff --git a/tests/phpunit/includes/utils/IPTest.php b/tests/phpunit/includes/utils/IPTest.php
new file mode 100644 (file)
index 0000000..24b077a
--- /dev/null
@@ -0,0 +1,610 @@
+<?php
+/**
+ * Tests for IP validity functions.
+ *
+ * Ported from /t/inc/IP.t by avar.
+ *
+ * @group IP
+ * @todo Test methods in this call should be split into a method and a
+ * dataprovider.
+ */
+
+class IPTest extends MediaWikiTestCase {
+       /**
+        *  not sure it should be tested with boolean false. hashar 20100924
+        * @covers IP::isIPAddress
+        */
+       public function testisIPAddress() {
+               $this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' );
+               $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' );
+               $this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' );
+               $this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' );
+               $this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' );
+               $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' );
+               $this->assertFalse(
+                       IP::isIPAddress( '2001:0DB8::A:1::' ),
+                       'IPv6 with a double :: occurrence, last at end'
+               );
+               $this->assertFalse(
+                       IP::isIPAddress( '::2001:0DB8::5:1' ),
+                       'IPv6 with a double :: occurrence, firt at beginning'
+               );
+               $this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' );
+               $this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' );
+               $this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' );
+               $this->assertFalse( IP::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' );
+
+               $this->assertTrue( IP::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' );
+               $this->assertTrue( IP::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' );
+               $this->assertTrue( IP::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) );
+               $this->assertTrue( IP::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' );
+               $this->assertTrue( IP::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' );
+
+               $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac',
+                       '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' );
+               foreach ( $validIPs as $ip ) {
+                       $this->assertTrue( IP::isIPAddress( $ip ), "$ip is a valid IP address" );
+               }
+       }
+
+       /**
+        * @covers IP::isIPv6
+        */
+       public function testisIPv6() {
+               $this->assertFalse( IP::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' );
+               $this->assertFalse( IP::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
+               $this->assertFalse( IP::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' );
+               $this->assertFalse( IP::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' );
+
+               $this->assertTrue( IP::isIPv6( 'fc:100::' ) );
+               $this->assertTrue( IP::isIPv6( 'fc:100:a::' ) );
+               $this->assertTrue( IP::isIPv6( 'fc:100:a:d::' ) );
+               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1::' ) );
+               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e::' ) );
+               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac::' ) );
+
+               $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
+               $this->assertFalse(
+                       IP::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ),
+                       'IPv6 with 9 words ending with "::"'
+               );
+
+               $this->assertFalse( IP::isIPv6( ':::' ) );
+               $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
+
+               $this->assertTrue( IP::isIPv6( '::' ), 'IPv6 zero address' );
+               $this->assertTrue( IP::isIPv6( '::0' ) );
+               $this->assertTrue( IP::isIPv6( '::fc' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100:a' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100:a:d' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e' ) );
+               $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e:ac' ) );
+
+               $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
+               $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
+
+               $this->assertFalse( IP::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' );
+               $this->assertFalse( IP::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' );
+               $this->assertFalse( IP::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' );
+
+               $this->assertTrue( IP::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' );
+               $this->assertTrue( IP::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
+               $this->assertTrue( IP::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) );
+               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
+               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
+               $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
+               $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
+               $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
+               $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
+
+               $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
+               $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
+
+               $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
+       }
+
+       /**
+        * @covers IP::isIPv4
+        */
+       public function testisIPv4() {
+               $this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' );
+               $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' );
+               $this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' );
+               $this->assertFalse( IP::isIPv4( 'abc' ) );
+               $this->assertFalse( IP::isIPv4( ':' ) );
+               $this->assertFalse( IP::isIPv4( '124.24.52' ), 'IPv4 not enough quads' );
+               $this->assertFalse( IP::isIPv4( '24.324.52.13' ), 'IPv4 out of range' );
+               $this->assertFalse( IP::isIPv4( '.24.52.13' ), 'IPv4 starts with period' );
+
+               $this->assertTrue( IP::isIPv4( '124.24.52.13' ) );
+               $this->assertTrue( IP::isIPv4( '1.24.52.13' ) );
+               $this->assertTrue( IP::isIPv4( '74.24.52.13/20', 'IPv4 range' ) );
+       }
+
+       /**
+        * @covers IP::isValid
+        */
+       public function testValidIPs() {
+               foreach ( range( 0, 255 ) as $i ) {
+                       $a = sprintf( "%03d", $i );
+                       $b = sprintf( "%02d", $i );
+                       $c = sprintf( "%01d", $i );
+                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
+                               $ip = "$f.$f.$f.$f";
+                               $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv4 address" );
+                       }
+               }
+               foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) {
+                       $a = sprintf( "%04x", $i );
+                       $b = sprintf( "%03x", $i );
+                       $c = sprintf( "%02x", $i );
+                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
+                               $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
+                               $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv6 address" );
+                       }
+               }
+               // test with some abbreviations
+               $this->assertFalse( IP::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' );
+               $this->assertFalse( IP::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
+               $this->assertFalse( IP::isValid( 'fc:300' ), 'IPv6 with only 2 words' );
+               $this->assertFalse( IP::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' );
+
+               $this->assertTrue( IP::isValid( 'fc:100::' ) );
+               $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e::' ) );
+               $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e:ac::' ) );
+
+               $this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
+               $this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
+               $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
+               $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
+               $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
+               $this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
+               $this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
+
+               $this->assertFalse(
+                       IP::isValid( 'fc:100:a:d:1:e:ac:0::' ),
+                       'IPv6 with 8 words ending with "::"'
+               );
+               $this->assertFalse(
+                       IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ),
+                       'IPv6 with 9 words ending with "::"'
+               );
+       }
+
+       /**
+        * @covers IP::isValid
+        */
+       public function testInvalidIPs() {
+               // Out of range...
+               foreach ( range( 256, 999 ) as $i ) {
+                       $a = sprintf( "%03d", $i );
+                       $b = sprintf( "%02d", $i );
+                       $c = sprintf( "%01d", $i );
+                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
+                               $ip = "$f.$f.$f.$f";
+                               $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv4 address" );
+                       }
+               }
+               foreach ( range( 'g', 'z' ) as $i ) {
+                       $a = sprintf( "%04s", $i );
+                       $b = sprintf( "%03s", $i );
+                       $c = sprintf( "%02s", $i );
+                       foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
+                               $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
+                               $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv6 address" );
+                       }
+               }
+               // Have CIDR
+               $ipCIDRs = array(
+                       '212.35.31.121/32',
+                       '212.35.31.121/18',
+                       '212.35.31.121/24',
+                       '::ff:d:321:5/96',
+                       'ff::d3:321:5/116',
+                       'c:ff:12:1:ea:d:321:5/120',
+               );
+               foreach ( $ipCIDRs as $i ) {
+                       $this->assertFalse( IP::isValid( $i ),
+                               "$i is an invalid IP address because it is a block" );
+               }
+               // Incomplete/garbage
+               $invalid = array(
+                       'www.xn--var-xla.net',
+                       '216.17.184.G',
+                       '216.17.184.1.',
+                       '216.17.184',
+                       '216.17.184.',
+                       '256.17.184.1'
+               );
+               foreach ( $invalid as $i ) {
+                       $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" );
+               }
+       }
+
+       /**
+        * @covers IP::isValidBlock
+        */
+       public function testValidBlocks() {
+               $valid = array(
+                       '116.17.184.5/32',
+                       '0.17.184.5/30',
+                       '16.17.184.1/24',
+                       '30.242.52.14/1',
+                       '10.232.52.13/8',
+                       '30.242.52.14/0',
+                       '::e:f:2001/96',
+                       '::c:f:2001/128',
+                       '::10:f:2001/70',
+                       '::fe:f:2001/1',
+                       '::6d:f:2001/8',
+                       '::fe:f:2001/0',
+               );
+               foreach ( $valid as $i ) {
+                       $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" );
+               }
+       }
+
+       /**
+        * @covers IP::isValidBlock
+        */
+       public function testInvalidBlocks() {
+               $invalid = array(
+                       '116.17.184.5/33',
+                       '0.17.184.5/130',
+                       '16.17.184.1/-1',
+                       '10.232.52.13/*',
+                       '7.232.52.13/ab',
+                       '11.232.52.13/',
+                       '::e:f:2001/129',
+                       '::c:f:2001/228',
+                       '::10:f:2001/-1',
+                       '::6d:f:2001/*',
+                       '::86:f:2001/ab',
+                       '::23:f:2001/',
+               );
+               foreach ( $invalid as $i ) {
+                       $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" );
+               }
+       }
+
+       /**
+        * Improve IP::sanitizeIP() code coverage
+        * @todo Most probably incomplete
+        */
+       public function testSanitizeIP() {
+               $this->assertNull( IP::sanitizeIP( '' ) );
+               $this->assertNull( IP::sanitizeIP( ' ' ) );
+       }
+
+       /**
+        * @covers IP::toUnsigned
+        * @dataProvider provideToUnsigned
+        */
+       public function testToUnsigned( $expected, $input ) {
+               $result = IP::toUnsigned( $input );
+               $this->assertTrue( $result === false || is_string( $result ) || is_int( $result ) );
+               $this->assertEquals( $expected, $result );
+       }
+
+       /**
+        * Provider for IP::testToUnsigned()
+        */
+       public static function provideToUnsigned() {
+               return array(
+                       array( 1, '0.0.0.1' ),
+                       array( 16909060, '1.2.3.4' ),
+                       array( 2130706433, '127.0.0.1' ),
+                       array( '2147483648', '128.0.0.0' ),
+                       array( '3735931646', '222.173.202.254' ),
+                       array( pow( 2, 32 ) - 1, '255.255.255.255' ),
+                       array( false, 'IN.VA.LI.D' ),
+                       array( 1, '::1' ),
+                       array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
+                       array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ),
+                       array( false, 'IN:VA::LI:D' ),
+                       array( false, ':::1' )
+               );
+       }
+
+       /**
+        * @covers IP::toHex
+        * @dataProvider provideToHex
+        */
+       public function testToHex( $expected, $input ) {
+               $result = IP::toHex( $input );
+               $this->assertTrue( $result === false || is_string( $result ) );
+               $this->assertEquals( $expected, $result );
+       }
+
+       /**
+        * Provider for IP::testToHex()
+        */
+       public static function provideToHex() {
+               return array(
+                       array( '00000001', '0.0.0.1' ),
+                       array( '01020304', '1.2.3.4' ),
+                       array( '7F000001', '127.0.0.1' ),
+                       array( '80000000', '128.0.0.0' ),
+                       array( 'DEADCAFE', '222.173.202.254' ),
+                       array( 'FFFFFFFF', '255.255.255.255' ),
+                       array( false, 'IN.VA.LI.D' ),
+                       array( 'v6-00000000000000000000000000000001', '::1' ),
+                       array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
+                       array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
+                       array( false, 'IN:VA::LI:D' ),
+                       array( false, ':::1' )
+               );
+       }
+
+       /**
+        * @covers IP::isPublic
+        */
+       public function testPrivateIPs() {
+               $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' );
+               foreach ( $private as $p ) {
+                       $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" );
+               }
+               $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' );
+               foreach ( $public as $p ) {
+                       $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" );
+               }
+       }
+
+       // Private wrapper used to test CIDR Parsing.
+       private function assertFalseCIDR( $CIDR, $msg = '' ) {
+               $ff = array( false, false );
+               $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg );
+       }
+
+       // Private wrapper to test network shifting using only dot notation
+       private function assertNet( $expected, $CIDR ) {
+               $parse = IP::parseCIDR( $CIDR );
+               $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
+       }
+
+       /**
+        * @covers IP::hexToQuad
+        */
+       public function testHexToQuad() {
+               $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) );
+               $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) );
+               $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) );
+               $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) );
+               // hex not left-padded...
+               $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) );
+               $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) );
+               $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) );
+               $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) );
+       }
+
+       /**
+        * @covers IP::hexToOctet
+        */
+       public function testHexToOctet() {
+               $this->assertEquals( '0:0:0:0:0:0:0:1',
+                       IP::hexToOctet( '00000000000000000000000000000001' ) );
+               $this->assertEquals( '0:0:0:0:0:0:FF:3',
+                       IP::hexToOctet( '00000000000000000000000000FF0003' ) );
+               $this->assertEquals( '0:0:0:0:0:0:FF00:6',
+                       IP::hexToOctet( '000000000000000000000000FF000006' ) );
+               $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF',
+                       IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) );
+               $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
+                       IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
+               // hex not left-padded...
+               $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) );
+               $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) );
+               $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) );
+               $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) );
+               $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) );
+               $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) );
+       }
+
+       /**
+        * IP::parseCIDR() returns an array containing a signed IP address
+        * representing the network mask and the bit mask.
+        * @covers IP::parseCIDR
+        */
+       public function testCIDRParsing() {
+               $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
+               $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
+
+               // Verify if statement
+               $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
+               $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
+               $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
+               $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
+
+               // Check internal logic
+               # 0 mask always result in array(0,0)
+               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) );
+               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) );
+               $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) );
+
+               // @todo FIXME: Add more tests.
+
+               # This part test network shifting
+               $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
+               $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
+               $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
+               $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
+               $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
+               $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
+               $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
+               $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
+               $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
+       }
+
+       /**
+        * @covers IP::canonicalize
+        */
+       public function testIPCanonicalizeOnValidIp() {
+               $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ),
+                       'Canonicalization of a valid IP returns it unchanged' );
+       }
+
+       /**
+        * @covers IP::canonicalize
+        */
+       public function testIPCanonicalizeMappedAddress() {
+               $this->assertEquals(
+                       '192.0.2.152',
+                       IP::canonicalize( '::ffff:192.0.2.152' )
+               );
+               $this->assertEquals(
+                       '192.0.2.152',
+                       IP::canonicalize( '::192.0.2.152' )
+               );
+       }
+
+       /**
+        * Issues there are most probably from IP::toHex() or IP::parseRange()
+        * @covers IP::isInRange
+        * @dataProvider provideIPsAndRanges
+        */
+       public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
+               $this->assertEquals(
+                       $expected,
+                       IP::isInRange( $addr, $range ),
+                       $message
+               );
+       }
+
+       /** Provider for testIPIsInRange() */
+       public static function provideIPsAndRanges() {
+               # Format: (expected boolean, address, range, optional message)
+               return array(
+                       # IPv4
+                       array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
+                       array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
+                       array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
+
+                       array( false, '0.0.0.0', '192.0.2.0/24' ),
+                       array( false, '255.255.255', '192.0.2.0/24' ),
+
+                       # IPv6
+                       array( false, '::1', '2001:DB8::/32' ),
+                       array( false, '::', '2001:DB8::/32' ),
+                       array( false, 'FE80::1', '2001:DB8::/32' ),
+
+                       array( true, '2001:DB8::', '2001:DB8::/32' ),
+                       array( true, '2001:0DB8::', '2001:DB8::/32' ),
+                       array( true, '2001:DB8::1', '2001:DB8::/32' ),
+                       array( true, '2001:0DB8::1', '2001:DB8::/32' ),
+                       array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
+                               '2001:DB8::/32' ),
+
+                       array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
+               );
+       }
+
+       /**
+        * Test for IP::splitHostAndPort().
+        * @dataProvider provideSplitHostAndPort
+        */
+       public function testSplitHostAndPort( $expected, $input, $description ) {
+               $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description );
+       }
+
+       /**
+        * Provider for IP::splitHostAndPort()
+        */
+       public static function provideSplitHostAndPort() {
+               return array(
+                       array( false, '[', 'Unclosed square bracket' ),
+                       array( false, '[::', 'Unclosed square bracket 2' ),
+                       array( array( '::', false ), '::', 'Bare IPv6 0' ),
+                       array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
+                       array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
+                       array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
+                       array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
+                       array( false, '::x', 'Double colon but no IPv6' ),
+                       array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
+                       array( false, 'x:x', 'Hostname and invalid port' ),
+                       array( array( 'x', false ), 'x', 'Plain hostname' )
+               );
+       }
+
+       /**
+        * Test for IP::combineHostAndPort()
+        * @dataProvider provideCombineHostAndPort
+        */
+       public function testCombineHostAndPort( $expected, $input, $description ) {
+               list( $host, $port, $defaultPort ) = $input;
+               $this->assertEquals(
+                       $expected,
+                       IP::combineHostAndPort( $host, $port, $defaultPort ),
+                       $description );
+       }
+
+       /**
+        * Provider for IP::combineHostAndPort()
+        */
+       public static function provideCombineHostAndPort() {
+               return array(
+                       array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
+                       array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
+                       array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
+                       array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
+               );
+       }
+
+       /**
+        * Test for IP::sanitizeRange()
+        * @dataProvider provideIPCIDRs
+        */
+       public function testSanitizeRange( $input, $expected, $description ) {
+               $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
+       }
+
+       /**
+        * Provider for IP::testSanitizeRange()
+        */
+       public static function provideIPCIDRs() {
+               return array(
+                       array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
+                       array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
+                       array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
+                       array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
+                       array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
+                       array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
+                       array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
+                       array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
+               );
+       }
+
+       /**
+        * Test for IP::prettifyIP()
+        * @dataProvider provideIPsToPrettify
+        */
+       public function testPrettifyIP( $ip, $prettified ) {
+               $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" );
+       }
+
+       /**
+        * Provider for IP::testPrettifyIP()
+        */
+       public static function provideIPsToPrettify() {
+               return array(
+                       array( '0:0:0:0:0:0:0:0', '::' ),
+                       array( '0:0:0::0:0:0', '::' ),
+                       array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
+                       array( '0:0::f', '::f' ),
+                       array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
+                       array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
+                       array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
+                       array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
+                       array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
+                       array( '0:0:0:0:0:0:0:0/16', '::/16' ),
+                       array( '0:0:0::0:0:0/64', '::/64' ),
+                       array( '0:0::f/52', '::f/52' ),
+                       array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
+                       array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
+                       array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
+                       array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
+                       array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),
+               );
+       }
+}
diff --git a/tests/phpunit/includes/utils/StringUtilsTest.php b/tests/phpunit/includes/utils/StringUtilsTest.php
new file mode 100644 (file)
index 0000000..89759e5
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+
+class StringUtilsTest extends MediaWikiTestCase {
+
+       /**
+        * This tests StringUtils::isUtf8 whenever we have the mbstring extension
+        * loaded.
+        *
+        * @covers StringUtils::isUtf8
+        * @dataProvider provideStringsForIsUtf8Check
+        */
+       public function testIsUtf8WithMbstring( $expected, $string ) {
+               if ( !function_exists( 'mb_check_encoding' ) ) {
+                       $this->markTestSkipped( 'Test requires the mbstring PHP extension' );
+               }
+               $this->assertEquals( $expected,
+                       StringUtils::isUtf8( $string ),
+                       'Testing string "' . $this->escaped( $string ) . '" with mb_check_encoding'
+               );
+       }
+
+       /**
+        * This tests StringUtils::isUtf8 making sure we use the pure PHP
+        * implementation used as a fallback when mb_check_encoding() is
+        * not available.
+        *
+        * @covers StringUtils::isUtf8
+        * @dataProvider provideStringsForIsUtf8Check
+        */
+       public function testIsUtf8WithPhpFallbackImplementation( $expected, $string ) {
+               $this->assertEquals( $expected,
+                       StringUtils::isUtf8( $string, /** disable mbstring: */true ),
+                       'Testing string "' . $this->escaped( $string ) . '" with pure PHP implementation'
+               );
+       }
+
+       /**
+        * Print high range characters as an hexadecimal
+        */
+       function escaped( $string ) {
+               $escaped = '';
+               $length = strlen( $string );
+               for ( $i = 0; $i < $length; $i++ ) {
+                       $char = $string[$i];
+                       $val = ord( $char );
+                       if ( $val > 127 ) {
+                               $escaped .= '\x' . dechex( $val );
+                       } else {
+                               $escaped .= $char;
+                       }
+               }
+
+               return $escaped;
+       }
+
+       /**
+        * See also "UTF-8 decoder capability and stress test" by
+        * Markus Kuhn:
+        * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+        */
+       public static function provideStringsForIsUtf8Check() {
+               // Expected return values for StringUtils::isUtf8()
+               $PASS = true;
+               $FAIL = false;
+
+               return array(
+                       'some ASCII' => array( $PASS, 'Some ASCII' ),
+                       'euro sign' => array( $PASS, "Euro sign €" ),
+
+                       'first possible sequence 1 byte' => array( $PASS, "\x00" ),
+                       'first possible sequence 2 bytes' => array( $PASS, "\xc2\x80" ),
+                       'first possible sequence 3 bytes' => array( $PASS, "\xe0\xa0\x80" ),
+                       'first possible sequence 4 bytes' => array( $PASS, "\xf0\x90\x80\x80" ),
+                       'first possible sequence 5 bytes' => array( $FAIL, "\xf8\x88\x80\x80\x80" ),
+                       'first possible sequence 6 bytes' => array( $FAIL, "\xfc\x84\x80\x80\x80\x80" ),
+
+                       'last possible sequence 1 byte' => array( $PASS, "\x7f" ),
+                       'last possible sequence 2 bytes' => array( $PASS, "\xdf\xbf" ),
+                       'last possible sequence 3 bytes' => array( $PASS, "\xef\xbf\xbf" ),
+                       'last possible sequence 4 bytes (U+1FFFFF)' => array( $FAIL, "\xf7\xbf\xbf\xbf" ),
+                       'last possible sequence 5 bytes' => array( $FAIL, "\xfb\xbf\xbf\xbf\xbf" ),
+                       'last possible sequence 6 bytes' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf\xbf" ),
+
+                       'boundary 1' => array( $PASS, "\xed\x9f\xbf" ),
+                       'boundary 2' => array( $PASS, "\xee\x80\x80" ),
+                       'boundary 3' => array( $PASS, "\xef\xbf\xbd" ),
+                       'boundary 4' => array( $PASS, "\xf2\x80\x80\x80" ),
+                       'boundary 5 (U+FFFFF)' => array( $PASS, "\xf3\xbf\xbf\xbf" ),
+                       'boundary 6 (U+100000)' => array( $PASS, "\xf4\x80\x80\x80" ),
+                       'boundary 7 (U+10FFFF)' => array( $PASS, "\xf4\x8f\xbf\xbf" ),
+                       'boundary 8 (U+110000)' => array( $FAIL, "\xf4\x90\x80\x80" ),
+
+                       'malformed 1' => array( $FAIL, "\x80" ),
+                       'malformed 2' => array( $FAIL, "\xbf" ),
+                       'malformed 3' => array( $FAIL, "\x80\xbf" ),
+                       'malformed 4' => array( $FAIL, "\x80\xbf\x80" ),
+                       'malformed 5' => array( $FAIL, "\x80\xbf\x80\xbf" ),
+                       'malformed 6' => array( $FAIL, "\x80\xbf\x80\xbf\x80" ),
+                       'malformed 7' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf" ),
+                       'malformed 8' => array( $FAIL, "\x80\xbf\x80\xbf\x80\xbf\x80" ),
+
+                       'last byte missing 1' => array( $FAIL, "\xc0" ),
+                       'last byte missing 2' => array( $FAIL, "\xe0\x80" ),
+                       'last byte missing 3' => array( $FAIL, "\xf0\x80\x80" ),
+                       'last byte missing 4' => array( $FAIL, "\xf8\x80\x80\x80" ),
+                       'last byte missing 5' => array( $FAIL, "\xfc\x80\x80\x80\x80" ),
+                       'last byte missing 6' => array( $FAIL, "\xdf" ),
+                       'last byte missing 7' => array( $FAIL, "\xef\xbf" ),
+                       'last byte missing 8' => array( $FAIL, "\xf7\xbf\xbf" ),
+                       'last byte missing 9' => array( $FAIL, "\xfb\xbf\xbf\xbf" ),
+                       'last byte missing 10' => array( $FAIL, "\xfd\xbf\xbf\xbf\xbf" ),
+
+                       'extra continuation byte 1' => array( $FAIL, "e\xaf" ),
+                       'extra continuation byte 2' => array( $FAIL, "\xc3\x89\xaf" ),
+                       'extra continuation byte 3' => array( $FAIL, "\xef\xbc\xa5\xaf" ),
+                       'extra continuation byte 4' => array( $FAIL, "\xf0\x9d\x99\xb4\xaf" ),
+
+                       'impossible bytes 1' => array( $FAIL, "\xfe" ),
+                       'impossible bytes 2' => array( $FAIL, "\xff" ),
+                       'impossible bytes 3' => array( $FAIL, "\xfe\xfe\xff\xff" ),
+
+                       'overlong sequences 1' => array( $FAIL, "\xc0\xaf" ),
+                       'overlong sequences 2' => array( $FAIL, "\xc1\xaf" ),
+                       'overlong sequences 3' => array( $FAIL, "\xe0\x80\xaf" ),
+                       'overlong sequences 4' => array( $FAIL, "\xf0\x80\x80\xaf" ),
+                       'overlong sequences 5' => array( $FAIL, "\xf8\x80\x80\x80\xaf" ),
+                       'overlong sequences 6' => array( $FAIL, "\xfc\x80\x80\x80\x80\xaf" ),
+
+                       'maximum overlong sequences 1' => array( $FAIL, "\xc1\xbf" ),
+                       'maximum overlong sequences 2' => array( $FAIL, "\xe0\x9f\xbf" ),
+                       'maximum overlong sequences 3' => array( $FAIL, "\xf0\x8f\xbf\xbf" ),
+                       'maximum overlong sequences 4' => array( $FAIL, "\xf8\x87\xbf\xbf" ),
+                       'maximum overlong sequences 5' => array( $FAIL, "\xfc\x83\xbf\xbf\xbf\xbf" ),
+
+                       'surrogates 1 (U+D799)' => array( $PASS, "\xed\x9f\xbf" ),
+                       'surrogates 2 (U+E000)' => array( $PASS, "\xee\x80\x80" ),
+                       'surrogates 3 (U+D800)' => array( $FAIL, "\xed\xa0\x80" ),
+                       'surrogates 4 (U+DBFF)' => array( $FAIL, "\xed\xaf\xbf" ),
+                       'surrogates 5 (U+DC00)' => array( $FAIL, "\xed\xb0\x80" ),
+                       'surrogates 6 (U+DFFF)' => array( $FAIL, "\xed\xbf\xbf" ),
+                       'surrogates 7 (U+D800 U+DC00)' => array( $FAIL, "\xed\xa0\x80\xed\xb0\x80" ),
+
+                       'noncharacters 1' => array( $PASS, "\xef\xbf\xbe" ),
+                       'noncharacters 2' => array( $PASS, "\xef\xbf\xbf" ),
+               );
+       }
+}
diff --git a/tests/phpunit/includes/utils/UIDGeneratorTest.php b/tests/phpunit/includes/utils/UIDGeneratorTest.php
new file mode 100644 (file)
index 0000000..8f78ae5
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+
+class UIDGeneratorTest extends MediaWikiTestCase {
+
+       /**
+        * @dataProvider provider_testTimestampedUID
+        * @covers UIDGenerator::newTimestampedUID128
+        * @covers UIDGenerator::newTimestampedUID88
+        */
+       public function testTimestampedUID( $method, $digitlen, $bits, $tbits, $hostbits ) {
+               $id = call_user_func( array( 'UIDGenerator', $method ) );
+               $this->assertEquals( true, ctype_digit( $id ), "UID made of digit characters" );
+               $this->assertLessThanOrEqual( $digitlen, strlen( $id ),
+                       "UID has the right number of digits" );
+               $this->assertLessThanOrEqual( $bits, strlen( wfBaseConvert( $id, 10, 2 ) ),
+                       "UID has the right number of bits" );
+
+               $ids = array();
+               for ( $i = 0; $i < 300; $i++ ) {
+                       $ids[] = call_user_func( array( 'UIDGenerator', $method ) );
+               }
+
+               $lastId = array_shift( $ids );
+               if ( $hostbits ) {
+                       $lastHost = substr( wfBaseConvert( $lastId, 10, 2, $bits ), -$hostbits );
+               }
+
+               $this->assertArrayEquals( array_unique( $ids ), $ids, "All generated IDs are unique." );
+
+               foreach ( $ids as $id ) {
+                       $id_bin = wfBaseConvert( $id, 10, 2 );
+                       $lastId_bin = wfBaseConvert( $lastId, 10, 2 );
+
+                       $this->assertGreaterThanOrEqual(
+                               substr( $id_bin, 0, $tbits ),
+                               substr( $lastId_bin, 0, $tbits ),
+                               "New ID timestamp ($id_bin) >= prior one ($lastId_bin)." );
+
+                       if ( $hostbits ) {
+                               $this->assertEquals(
+                                       substr( $id_bin, 0, -$hostbits ),
+                                       substr( $lastId_bin, 0, -$hostbits ),
+                                       "Host ID of ($id_bin) is same as prior one ($lastId_bin)." );
+                       }
+
+                       $lastId = $id;
+               }
+       }
+
+       /**
+        * array( method, length, bits, hostbits )
+        * NOTE: When adding a new method name here please update the covers tags for the tests!
+        */
+       public static function provider_testTimestampedUID() {
+               return array(
+                       array( 'newTimestampedUID128', 39, 128, 46, 48 ),
+                       array( 'newTimestampedUID128', 39, 128, 46, 48 ),
+                       array( 'newTimestampedUID88', 27, 88, 46, 32 ),
+               );
+       }
+
+       /**
+        * @covers UIDGenerator::newUUIDv4
+        */
+       public function testUUIDv4() {
+               for ( $i = 0; $i < 100; $i++ ) {
+                       $id = UIDGenerator::newUUIDv4();
+                       $this->assertEquals( true,
+                               preg_match( '!^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$!', $id ),
+                               "UID $id has the right format" );
+               }
+       }
+
+       /**
+        * @covers UIDGenerator::newRawUUIDv4
+        */
+       public function testRawUUIDv4() {
+               for ( $i = 0; $i < 100; $i++ ) {
+                       $id = UIDGenerator::newRawUUIDv4();
+                       $this->assertEquals( true,
+                               preg_match( '!^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$!', $id ),
+                               "UID $id has the right format" );
+               }
+       }
+
+       /**
+        * @covers UIDGenerator::newRawUUIDv4
+        */
+       public function testRawUUIDv4QuickRand() {
+               for ( $i = 0; $i < 100; $i++ ) {
+                       $id = UIDGenerator::newRawUUIDv4( UIDGenerator::QUICK_RAND );
+                       $this->assertEquals( true,
+                               preg_match( '!^[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}$!', $id ),
+                               "UID $id has the right format" );
+               }
+       }
+
+}
diff --git a/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php b/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php
new file mode 100644 (file)
index 0000000..34ffb53
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @covers ZipDirectoryReader
+ * NOTE: this test is more like an integration test than a unit test
+ */
+class ZipDirectoryReaderTest extends MediaWikiTestCase {
+       protected $zipDir;
+       protected $entries;
+
+       protected function setUp() {
+               parent::setUp();
+               $this->zipDir = __DIR__ . '/../../data/zip';
+       }
+
+       function zipCallback( $entry ) {
+               $this->entries[] = $entry;
+       }
+
+       function readZipAssertError( $file, $error, $assertMessage ) {
+               $this->entries = array();
+               $status = ZipDirectoryReader::read( "{$this->zipDir}/$file", array( $this, 'zipCallback' ) );
+               $this->assertTrue( $status->hasMessage( $error ), $assertMessage );
+       }
+
+       function readZipAssertSuccess( $file, $assertMessage ) {
+               $this->entries = array();
+               $status = ZipDirectoryReader::read( "{$this->zipDir}/$file", array( $this, 'zipCallback' ) );
+               $this->assertTrue( $status->isOK(), $assertMessage );
+       }
+
+       public function testEmpty() {
+               $this->readZipAssertSuccess( 'empty.zip', 'Empty zip' );
+       }
+
+       public function testMultiDisk0() {
+               $this->readZipAssertError( 'split.zip', 'zip-unsupported',
+                       'Split zip error' );
+       }
+
+       public function testNoSignature() {
+               $this->readZipAssertError( 'nosig.zip', 'zip-wrong-format',
+                       'No signature should give "wrong format" error' );
+       }
+
+       public function testSimple() {
+               $this->readZipAssertSuccess( 'class.zip', 'Simple ZIP' );
+               $this->assertEquals( $this->entries, array( array(
+                       'name' => 'Class.class',
+                       'mtime' => '20010115000000',
+                       'size' => 1,
+               ) ) );
+       }
+
+       public function testBadCentralEntrySignature() {
+               $this->readZipAssertError( 'wrong-central-entry-sig.zip', 'zip-bad',
+                       'Bad central entry error' );
+       }
+
+       public function testTrailingBytes() {
+               $this->readZipAssertError( 'trail.zip', 'zip-bad',
+                       'Trailing bytes error' );
+       }
+
+       public function testWrongCDStart() {
+               $this->readZipAssertError( 'wrong-cd-start-disk.zip', 'zip-unsupported',
+                       'Wrong CD start disk error' );
+       }
+
+       public function testCentralDirectoryGap() {
+               $this->readZipAssertError( 'cd-gap.zip', 'zip-bad',
+                       'CD gap error' );
+       }
+
+       public function testCentralDirectoryTruncated() {
+               $this->readZipAssertError( 'cd-truncated.zip', 'zip-bad',
+                       'CD truncated error (should hit unpack() overrun)' );
+       }
+
+       public function testLooksLikeZip64() {
+               $this->readZipAssertError( 'looks-like-zip64.zip', 'zip-unsupported',
+                       'A file which looks like ZIP64 but isn\'t, should give error' );
+       }
+}
index d5822f4..97a17ec 100644 (file)
@@ -79,12 +79,13 @@ class LanguageBe_taraskTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
+               $forms = array( 'one', 'other', '0=one' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
        public static function providePluralTwoForms() {
                return array(
+                       array( 'one', 0 ),
                        array( 'one', 1 ),
                        array( 'other', 11 ),
                        array( 'other', 91 ),
index e938be7..56f8490 100644 (file)
@@ -17,6 +17,17 @@ class LanguageRuTest extends LanguageClassesTestCase {
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
+       /**
+        * Test explicit plural forms - n=FormN forms
+        * @covers Language::convertPlural
+        */
+       public function testExplicitPlural() {
+               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
+               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
+               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
+               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
+       }
+
        /**
         * @dataProvider providePlural
         * @covers Language::getPluralRuleType
index ab4d4ab..f551248 100644 (file)
@@ -225,7 +225,6 @@ class LanguageSrTest extends LanguageClassesTestCase {
                $this->assertConverted( $text, 'sr-ec', $msg );
        }
 
-
        /** Wrapper for converter::convertTo() method*/
        protected function convertTo( $text, $variant ) {
                return $this->getLang()
index 78929e2..e958fde 100644 (file)
@@ -241,6 +241,26 @@ class LanguageTest extends LanguageClassesTestCase {
                        $this->getLang()->truncate( "123456789", -5, 'XXXXXXXXXXXXXXX' ),
                        'truncate suffix, large ellipsis'
                );
+               $this->assertEquals(
+                       "123XXX",
+                       $this->getLang()->truncate( "123                ", 9, 'XXX' ),
+                       'truncate prefix, with spaces'
+               );
+               $this->assertEquals(
+                       "12345XXX",
+                       $this->getLang()->truncate( "12345            8", 11, 'XXX' ),
+                       'truncate prefix, with spaces and non-space ending'
+               );
+               $this->assertEquals(
+                       "XXX234",
+                       $this->getLang()->truncate( "1              234", -8, 'XXX' ),
+                       'truncate suffix, with spaces'
+               );
+               $this->assertEquals(
+                       "12345XXX",
+                       $this->getLang()->truncate( "1234567890", 5, 'XXX', false ),
+                       'truncate without adjustment'
+               );
        }
 
        /**
@@ -1114,7 +1134,6 @@ class LanguageTest extends LanguageClassesTestCase {
                );
        }
 
-
        /**
         * @dataProvider provideFormatDuration
         * @covers Language::formatDuration
@@ -1467,13 +1486,14 @@ class LanguageTest extends LanguageClassesTestCase {
 
        public static function provideCommafyData() {
                return array(
-                       array( 1, '1' ),
+                       array( -1, '-1' ),
                        array( 10, '10' ),
                        array( 100, '100' ),
                        array( 1000, '1,000' ),
                        array( 10000, '10,000' ),
                        array( 100000, '100,000' ),
                        array( 1000000, '1,000,000' ),
+                       array( -1.0001, '-1.0001' ),
                        array( 1.0001, '1.0001' ),
                        array( 10.0001, '10.0001' ),
                        array( 100.0001, '100.0001' ),
@@ -1481,6 +1501,8 @@ class LanguageTest extends LanguageClassesTestCase {
                        array( 10000.0001, '10,000.0001' ),
                        array( 100000.0001, '100,000.0001' ),
                        array( 1000000.0001, '1,000,000.0001' ),
+                       array( '200000000000000000000', '200,000,000,000,000,000,000' ),
+                       array( '-200000000000000000000', '-200,000,000,000,000,000,000' ),
                );
        }
 
index 8fc2795..2c9905f 100644 (file)
@@ -16,6 +16,8 @@ class LanguageTrTest extends LanguageClassesTestCase {
         *  - Emperyan
         * @see http://en.wikipedia.org/wiki/Dotted_and_dotless_I
         * @dataProvider provideDottedAndDotlessI
+        * @covers Language::ucfirst
+        * @covers Language::lcfirst
         */
        public function testDottedAndDotlessI( $func, $input, $inputCase, $expected ) {
                if ( $func == 'ucfirst' ) {
index 0783fcf..1d81bc5 100644 (file)
@@ -17,6 +17,17 @@ class LanguageUkTest extends LanguageClassesTestCase {
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
+       /**
+        * Test explicit plural forms - n=FormN forms
+        * @covers Language::convertPlural
+        */
+       public function testExplicitPlural() {
+               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
+               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
+               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
+               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
+       }
+
        /**
         * @dataProvider providePlural
         * @covers Language::getPluralRuleType
index 13f57c1..8cd3a6a 100644 (file)
@@ -105,7 +105,6 @@ class LanguageUzTest extends LanguageClassesTestCase {
                $this->assertConverted( $text, 'uz-cyrl', $msg );
        }
 
-
        /** Wrapper for converter::convertTo() method*/
        protected function convertTo( $text, $variant ) {
                return $this->getLang()->mConverter->convertTo( $text, $variant );
index 3bf7414..6abd09f 100644 (file)
@@ -4,6 +4,9 @@
  * @file
  */
 
+/**
+ * @covers CLDRPluralRuleEvaluator
+ */
 class CLDRPluralRuleEvaluatorTest extends MediaWikiTestCase {
        /**
         * @dataProvider validTestCases
@@ -23,7 +26,7 @@ class CLDRPluralRuleEvaluatorTest extends MediaWikiTestCase {
 
        function validTestCases() {
                $tests = array(
-                       # expected, number, rule, comment
+                       # expected, rule, number, comment
                        array( 0, 'n is 1', 1, 'integer number and is' ),
                        array( 0, 'n is 1', "1", 'string integer number and is' ),
                        array( 0, 'n is 1', 1.0, 'float number and is' ),
index 83d8c71..6950fa3 100644 (file)
@@ -48,7 +48,6 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
                throw new MWException( "Could not determine revision id (" . $status->getWikiText() . ")" );
        }
 
-
        /**
         * gunzips the given file and stores the result in the original file name
         *
@@ -110,7 +109,6 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
                }
        }
 
-
        /**
         * Step the current XML reader until node end of given name is found.
         *
@@ -230,7 +228,6 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
                }
        }
 
-
        /**
         * Asserts that the xml reader is at an element of given tag that contains a given text,
         * and skips over the element.
index 318ce0d..2a5bd5f 100644 (file)
@@ -111,7 +111,6 @@ class MaintenanceFixup extends Maintenance {
                $this->testCase = $testCase;
        }
 
-
        // --- Making protected functions visible for test
 
        public function output( $out, $channel = null ) {
@@ -122,7 +121,6 @@ class MaintenanceFixup extends Maintenance {
                return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() );
        }
 
-
        // --- Requirements for getting instance of abstract class
 
        public function execute() {
@@ -130,9 +128,11 @@ class MaintenanceFixup extends Maintenance {
        }
 }
 
+/**
+ * @covers Maintenance
+ */
 class MaintenanceTest extends MediaWikiTestCase {
 
-
        /**
         * The main Maintenance instance that is used for testing.
         *
@@ -140,7 +140,6 @@ class MaintenanceTest extends MediaWikiTestCase {
         */
        private $m;
 
-
        protected function setUp() {
                parent::setUp();
                $this->m = new MaintenanceFixup( $this );
@@ -154,7 +153,6 @@ class MaintenanceTest extends MediaWikiTestCase {
                parent::tearDown();
        }
 
-
        /**
         * asserts the output before and after simulating shutdown
         *
@@ -179,7 +177,6 @@ class MaintenanceTest extends MediaWikiTestCase {
                $this->expectOutputString( $postShutdownOutput );
        }
 
-
        // Although the following tests do not seem to be too consistent (compare for
        // example the newlines within the test.*StringString tests, or the
        // test.*Intermittent.* tests), the objective of these tests is not to describe
index bc2d737..adf026c 100644 (file)
@@ -6,6 +6,7 @@ require_once __DIR__ . "/../../../maintenance/backupPrefetch.inc";
  * Tests for BaseDump
  *
  * @group Dump
+ * @covers BaseDump
  */
 class BaseDumpTest extends MediaWikiTestCase {
 
@@ -136,7 +137,6 @@ class BaseDumpTest extends MediaWikiTestCase {
                $this->assertPrefetchEquals( "BackupDumperTestP2Text1", 2, 2 );
        }
 
-
        /**
         * Constructs a temporary file that can be used for prefetching
         *
index 653a114..8a297b1 100644 (file)
@@ -7,6 +7,7 @@ require_once __DIR__ . "/../../../maintenance/backupTextPass.inc";
  *
  * @group Database
  * @group Dump
+ * @covers TextPassDumper
  */
 class TextPassDumperTest extends DumpTestCase {
 
@@ -417,7 +418,6 @@ class TextPassDumperTest extends DumpTestCase {
                $this->checkpointHelper( "gzip" );
        }
 
-
        /**
         * Creates a stub file that is used for testing the text pass of dumps
         *
index 98d8165..5640b8d 100644 (file)
@@ -4,10 +4,10 @@
  *
  * @group Database
  * @group Dump
+ * @covers BackupDumper
  */
 class BackupDumperLoggerTest extends DumpTestCase {
 
-
        // We'll add several log entries and users for this test. The following
        // variables hold the corresponding ids.
        private $userId1, $userId2;
@@ -84,7 +84,6 @@ class BackupDumperLoggerTest extends DumpTestCase {
                }
        }
 
-
        /**
         * asserts that the xml reader is at the beginning of a log entry and skips over
         * it while analyzing it.
index 99bd270..6963601 100644 (file)
@@ -4,6 +4,7 @@
  *
  * @group Database
  * @group Dump
+ * @covers BackupDumper
  */
 class BackupDumperPageTest extends DumpTestCase {
 
@@ -271,7 +272,6 @@ class BackupDumperPageTest extends DumpTestCase {
                $this->assertDumpEnd();
        }
 
-
        function testXmlDumpsBackupUseCase() {
                // xmldumps-backup typically performs a single dump that that writes
                // out three files
index e8df199..dd80840 100644 (file)
@@ -25,7 +25,6 @@ class SemiMockedFetchText extends FetchText {
         */
        private $mockInvocations = array( 'getStdin' => 0 );
 
-
        /**
         * Data for the fake stdin
         *
@@ -70,6 +69,7 @@ class SemiMockedFetchText extends FetchText {
  *
  * @group Database
  * @group Dump
+ * @covers FetchText
  */
 class FetchTextTest extends MediaWikiTestCase {
 
@@ -81,7 +81,6 @@ class FetchTextTest extends MediaWikiTestCase {
        private $textId4;
        private $textId5;
 
-
        /**
         * @var Exception|null As the current MediaWikiTestCase::run is not
         * robust enough to recover from thrown exceptions directly, we cannot
@@ -118,7 +117,6 @@ class FetchTextTest extends MediaWikiTestCase {
                throw new MWException( "Could not determine text id" );
        }
 
-
        function addDBData() {
                $this->tablesUsed[] = 'page';
                $this->tablesUsed[] = 'revision';
@@ -144,7 +142,6 @@ class FetchTextTest extends MediaWikiTestCase {
                }
        }
 
-
        protected function setUp() {
                parent::setUp();
 
@@ -156,7 +153,6 @@ class FetchTextTest extends MediaWikiTestCase {
                $this->fetchText = new SemiMockedFetchText();
        }
 
-
        /**
         * Helper to relate FetchText's input and output
         */
@@ -169,7 +165,6 @@ class FetchTextTest extends MediaWikiTestCase {
                $this->expectOutputString( $expectedOutput );
        }
 
-
        // Instead of the following functions, a data provider would be great.
        // However, as data providers are evaluated /before/ addDBData, a data
        // provider would not know the required ids.
index 2c84886..bb678af 100644 (file)
@@ -6,6 +6,7 @@ require_once __DIR__ . "/../../../maintenance/getSlaveServer.php";
  * Tests for getSlaveServer
  *
  * @group Database
+ * @covers GetSlaveServer
  */
 class GetSlaveServerTest extends MediaWikiTestCase {
 
index 742b41e..38cacf9 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Fake handler for images.
+ * Fake handler for Bitmap images.
  *
  * 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
@@ -25,68 +25,8 @@ class MockBitmapHandler extends BitmapHandler {
        function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
                return MockImageHandler::doFakeTransform( $this, $image, $dstPath, $dstUrl, $params, $flags );
        }
+
        function doClientImage( $image, $scalerParams ) {
                        return $this->getClientScalingThumbnailImage( $image, $scalerParams );
        }
 }
-class MockSvgHandler extends SvgHandler {
-       function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
-               return MockImageHandler::doFakeTransform( $this, $image, $dstPath, $dstUrl, $params, $flags );
-       }
-}
-/**
- * Mock handler for images.
- *
- * This is really intended for unit testing.
- *
- * @ingroup Media
- */
-class MockImageHandler {
-
-       /**
-        * Override BitmapHandler::doTransform() making sure we do not generate
-        * a thumbnail at all. That is merely returning a ThumbnailImage that
-        * will be consumed by the unit test.  There is no need to create a real
-        * thumbnail on the filesystem.
-        */
-       static function doFakeTransform( $that, $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
-               # Example of what we receive:
-               # $image: LocalFile
-               # $dstPath: /tmp/transform_7d0a7a2f1a09-1.jpg
-               # $dstUrl : http://example.com/images/thumb/0/09/Bad.jpg/320px-Bad.jpg
-               # $params:  width: 320,  descriptionUrl http://trunk.dev/wiki/File:Bad.jpg
-
-               $that->normaliseParams( $image, $params );
-
-               $scalerParams = array(
-                       # The size to which the image will be resized
-                       'physicalWidth' => $params['physicalWidth'],
-                       'physicalHeight' => $params['physicalHeight'],
-                       'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
-                       # The size of the image on the page
-                       'clientWidth' => $params['width'],
-                       'clientHeight' => $params['height'],
-                       # Comment as will be added to the EXIF of the thumbnail
-                       'comment' => isset( $params['descriptionUrl'] ) ?
-                       "File source: {$params['descriptionUrl']}" : '',
-                       # Properties of the original image
-                       'srcWidth' => $image->getWidth(),
-                       'srcHeight' => $image->getHeight(),
-                       'mimeType' => $image->getMimeType(),
-                       'dstPath' => $dstPath,
-                       'dstUrl' => $dstUrl,
-               );
-
-               # In some cases, we do not bother generating a thumbnail.
-               if ( !$image->mustRender() &&
-                       $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
-                       && $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
-               ) {
-                       wfDebug( __METHOD__ . ": returning unscaled image\n" );
-                       // getClientScalingThumbnailImage is protected
-                       return $that->doClientImage( $image, $scalerParams );
-               }
-
-               return new ThumbnailImage( $image, $dstUrl, false, $params );
-       }
-}
diff --git a/tests/phpunit/mocks/media/MockImageHandler.php b/tests/phpunit/mocks/media/MockImageHandler.php
new file mode 100644 (file)
index 0000000..b2f7fac
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Fake handler for images.
+ *
+ * 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 Media
+ */
+
+/**
+ * Mock handler for images.
+ *
+ * This is really intended for unit testing.
+ *
+ * @ingroup Media
+ */
+class MockImageHandler {
+
+       /**
+        * Override BitmapHandler::doTransform() making sure we do not generate
+        * a thumbnail at all. That is merely returning a ThumbnailImage that
+        * will be consumed by the unit test.  There is no need to create a real
+        * thumbnail on the filesystem.
+        */
+       static function doFakeTransform( $that, $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
+               # Example of what we receive:
+               # $image: LocalFile
+               # $dstPath: /tmp/transform_7d0a7a2f1a09-1.jpg
+               # $dstUrl : http://example.com/images/thumb/0/09/Bad.jpg/320px-Bad.jpg
+               # $params:  width: 320,  descriptionUrl http://trunk.dev/wiki/File:Bad.jpg
+
+               $that->normaliseParams( $image, $params );
+
+               $scalerParams = array(
+                       # The size to which the image will be resized
+                       'physicalWidth' => $params['physicalWidth'],
+                       'physicalHeight' => $params['physicalHeight'],
+                       'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
+                       # The size of the image on the page
+                       'clientWidth' => $params['width'],
+                       'clientHeight' => $params['height'],
+                       # Comment as will be added to the EXIF of the thumbnail
+                       'comment' => isset( $params['descriptionUrl'] ) ?
+                                       "File source: {$params['descriptionUrl']}" : '',
+                       # Properties of the original image
+                       'srcWidth' => $image->getWidth(),
+                       'srcHeight' => $image->getHeight(),
+                       'mimeType' => $image->getMimeType(),
+                       'dstPath' => $dstPath,
+                       'dstUrl' => $dstUrl,
+               );
+
+               # In some cases, we do not bother generating a thumbnail.
+               if ( !$image->mustRender() &&
+                       $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
+                       && $scalerParams['physicalHeight'] == $scalerParams['srcHeight']
+               ) {
+                       wfDebug( __METHOD__ . ": returning unscaled image\n" );
+                       // getClientScalingThumbnailImage is protected
+                       return $that->doClientImage( $image, $scalerParams );
+               }
+
+               return new ThumbnailImage( $image, $dstUrl, false, $params );
+       }
+}
diff --git a/tests/phpunit/mocks/media/MockSvgHandler.php b/tests/phpunit/mocks/media/MockSvgHandler.php
new file mode 100644 (file)
index 0000000..21520c4
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Fake handler for SVG images.
+ *
+ * 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 Media
+ */
+
+class MockSvgHandler extends SvgHandler {
+       function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
+               return MockImageHandler::doFakeTransform( $this, $image, $dstPath, $dstUrl, $params, $flags );
+       }
+}
index 1d65e52..401b8a8 100755 (executable)
@@ -49,7 +49,7 @@ class PHPUnitMaintClass extends Maintenance {
                // Assume UTC for testing purposes
                $wgLocaltimezone = 'UTC';
 
-               $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+               $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
 
                // Bug 44192 Do not attempt to send a real e-mail
                Hooks::clear( 'AlternateUserMailer' );
index 850d39c..7d33a59 100644 (file)
@@ -5,7 +5,10 @@
  */
 class SideBarTest extends MediaWikiLangTestCase {
 
-       /** A skin template, reinitialized before each test */
+       /**
+        * A skin template, reinitialized before each test
+        * @var SkinTemplate
+        */
        private $skin;
        /** Local cache for sidebar messages */
        private $messages;
@@ -36,16 +39,12 @@ class SideBarTest extends MediaWikiLangTestCase {
                $this->skin->getContext()->setLanguage( Language::factory( 'en' ) );
        }
 
-       protected function tearDown() {
-               parent::tearDown();
-               $this->skin = null;
-       }
-
        /**
         * Internal helper to test the sidebar
         * @param $expected
         * @param $text
         * @param $message (Default: '')
+        * @todo this assert method to should be converted to a test using a dataprovider..
         */
        private function assertSideBar( $expected, $text, $message = '' ) {
                $bar = array();
@@ -53,7 +52,10 @@ class SideBarTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $bar, $message );
        }
 
-       function testSidebarWithOnlyTwoTitles() {
+       /**
+        * @covers SkinTemplate::addToSidebarPlain
+        */
+       public function testSidebarWithOnlyTwoTitles() {
                $this->assertSideBar(
                        array(
                                'Title1' => array(),
@@ -65,7 +67,10 @@ class SideBarTest extends MediaWikiLangTestCase {
                );
        }
 
-       function testExpandMessages() {
+       /**
+        * @covers SkinTemplate::addToSidebarPlain
+        */
+       public function testExpandMessages() {
                $this->assertSidebar(
                        array( 'Title' => array(
                                array(
@@ -81,7 +86,15 @@ class SideBarTest extends MediaWikiLangTestCase {
                );
        }
 
-       function testExternalUrlsRequireADescription() {
+       /**
+        * @covers SkinTemplate::addToSidebarPlain
+        */
+       public function testExternalUrlsRequireADescription() {
+               $this->setMwGlobals( array(
+                       'wgNoFollowLinks' => true,
+                       'wgNoFollowDomainExceptions' => array(),
+                       'wgNoFollowNsExceptions' => array(),
+               ) );
                $this->assertSidebar(
                        array( 'Title' => array(
                                # ** http://www.mediawiki.org/| Home
@@ -105,8 +118,9 @@ class SideBarTest extends MediaWikiLangTestCase {
        /**
         * bug 33321 - Make sure there's a | after transforming.
         * @group Database
+        * @covers SkinTemplate::addToSidebarPlain
         */
-       function testTrickyPipe() {
+       public function testTrickyPipe() {
                $this->assertSidebar(
                        array( 'Title' => array(
                                # The first 2 are skipped
@@ -135,7 +149,6 @@ class SideBarTest extends MediaWikiLangTestCase {
                );
        }
 
-
        #### Attributes for external links ##########################
        private function getAttribs() {
                # Sidebar text we will use everytime
@@ -151,9 +164,11 @@ class SideBarTest extends MediaWikiLangTestCase {
        /**
         * Simple test to verify our helper assertAttribs() is functional
         */
-       function testTestAttributesAssertionHelper() {
+       public function testTestAttributesAssertionHelper() {
                $this->setMwGlobals( array(
                        'wgNoFollowLinks' => true,
+                       'wgNoFollowDomainExceptions' => array(),
+                       'wgNoFollowNsExceptions' => array(),
                        'wgExternalLinkTarget' => false,
                ) );
                $attribs = $this->getAttribs();
@@ -167,7 +182,7 @@ class SideBarTest extends MediaWikiLangTestCase {
        /**
         * Test $wgNoFollowLinks in sidebar
         */
-       function testRespectWgnofollowlinks() {
+       public function testRespectWgnofollowlinks() {
                $this->setMwGlobals( 'wgNoFollowLinks', false );
 
                $attribs = $this->getAttribs();
@@ -180,7 +195,7 @@ class SideBarTest extends MediaWikiLangTestCase {
         * Test $wgExternaLinkTarget in sidebar
         * @dataProvider dataRespectExternallinktarget
         */
-       function testRespectExternallinktarget( $externalLinkTarget ) {
+       public function testRespectExternallinktarget( $externalLinkTarget ) {
                $this->setMwGlobals( 'wgExternalLinkTarget', $externalLinkTarget );
 
                $attribs = $this->getAttribs();
@@ -188,7 +203,7 @@ class SideBarTest extends MediaWikiLangTestCase {
                $this->assertEquals( $attribs['target'], $externalLinkTarget );
        }
 
-       function dataRespectExternallinktarget() {
+       public static function dataRespectExternallinktarget() {
                return array(
                        array( '_blank' ),
                        array( '_self' ),
index 205ea36..d8b90d5 100644 (file)
@@ -1,5 +1,25 @@
 <?php
+
 class AutoLoaderTest extends MediaWikiTestCase {
+       protected function setUp() {
+               global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+
+               parent::setUp();
+
+               // Fancy dance to trigger a rebuild of AutoLoader::$autoloadLocalClassesLower
+               $this->testLocalClasses = array(
+                       'TestAutoloadedLocalClass' => __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php',
+                       'TestAutoloadedCamlClass' => __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php',
+                       'TestAutoloadedSerializedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php',
+               );
+               $this->setMwGlobals( 'wgAutoloadLocalClasses', $this->testLocalClasses + $wgAutoloadLocalClasses );
+               AutoLoader::resetAutoloadLocalClassesLower();
+
+               $this->testExtensionClasses = array(
+                       'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php',
+               );
+               $this->setMwGlobals( 'wgAutoloadClasses', $this->testExtensionClasses + $wgAutoloadClasses );
+       }
 
        /**
         * Assert that there were no classes loaded that are not registered with the AutoLoader.
@@ -53,4 +73,23 @@ class AutoLoaderTest extends MediaWikiTestCase {
                        'actual' => $actual,
                );
        }
+
+       function testCoreClass() {
+               $this->assertTrue( class_exists( 'TestAutoloadedLocalClass' ) );
+       }
+
+       function testExtensionClass() {
+               $this->assertTrue( class_exists( 'TestAutoloadedClass' ) );
+       }
+
+       function testWrongCaseClass() {
+               $this->assertTrue( class_exists( 'testautoLoadedcamlCLASS' ) );
+       }
+
+       function testWrongCaseSerializedClass() {
+               $dummyCereal = 'O:29:"testautoloadedserializedclass":0:{}';
+               $uncerealized = unserialize( $dummyCereal );
+               $this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class,
+                       "unserialize() can load classes case-insensitively." );
+       }
 }
index fe823fa..cce1b7e 100644 (file)
@@ -26,27 +26,98 @@ class ResourcesTest extends MediaWikiTestCase {
        }
 
        /**
-        * This ask the ResouceLoader for all registered files from modules
-        * created by ResourceLoaderFileModule (or one of its descendants).
-        *
-        *
-        * Since the raw data is stored in protected properties, we have to
-        * overrride this through ReflectionObject methods.
+        * @dataProvider provideMediaStylesheets
         */
-       public static function provideResourceFiles() {
+       public function testStyleMedia( $moduleName, $media, $filename, $css ) {
+               $cssText = CSSMin::minify( $css->cssText );
+
+               $this->assertTrue( strpos( $cssText, '@media' ) === false, 'Stylesheets should not both specify "media" and contain @media' );
+       }
+
+       /**
+        * Get all registered modules from ResouceLoader.
+        */
+       protected static function getAllModules() {
                global $wgEnableJavaScriptTest;
 
                // Test existance of test suite files as well
                // (can't use setUp or setMwGlobals because providers are static)
-               $live_wgEnableJavaScriptTest = $wgEnableJavaScriptTest;
+               $org_wgEnableJavaScriptTest = $wgEnableJavaScriptTest;
                $wgEnableJavaScriptTest = true;
 
-               // Array with arguments for the test function
-               $cases = array();
-
                // Initialize ResourceLoader
                $rl = new ResourceLoader();
 
+               $modules = array();
+
+               foreach ( $rl->getModuleNames() as $moduleName ) {
+                       $modules[$moduleName] = $rl->getModule( $moduleName );
+               }
+
+               // Restore settings
+               $wgEnableJavaScriptTest = $org_wgEnableJavaScriptTest;
+
+               return array(
+                       'modules' => $modules,
+                       'resourceloader' => $rl,
+                       'context' => new ResourceLoaderContext( $rl, new FauxRequest() )
+               );
+       }
+
+       /**
+        * Get all stylesheet files from modules that are an instance of
+        * ResourceLoaderFileModule (or one of its subclasses).
+        */
+       public static function provideMediaStylesheets() {
+               $data = self::getAllModules();
+               $cases = array();
+
+               foreach ( $data['modules'] as $moduleName => $module ) {
+                       if ( !$module instanceof ResourceLoaderFileModule ) {
+                               continue;
+                       }
+
+                       $reflectedModule = new ReflectionObject( $module );
+
+                       $getStyleFiles = $reflectedModule->getMethod( 'getStyleFiles' );
+                       $getStyleFiles->setAccessible( true );
+
+                       $readStyleFile = $reflectedModule->getMethod( 'readStyleFile' );
+                       $readStyleFile->setAccessible( true );
+
+                       $styleFiles = $getStyleFiles->invoke( $module, $data['context'] );
+
+                       $flip = $module->getFlip( $data['context'] );
+
+                       foreach ( $styleFiles as $media => $files ) {
+                               if ( $media && $media !== 'all' ) {
+                                       foreach ( $files as $file ) {
+                                               $cases[] = array(
+                                                       $moduleName,
+                                                       $media,
+                                                       $file,
+                                                       // XXX: Wrapped in an object to keep it out of PHPUnit output
+                                                       (object) array( 'cssText' => $readStyleFile->invoke( $module, $file, $flip ) ),
+                                               );
+                                       }
+                               }
+                       }
+               }
+
+               return $cases;
+       }
+
+       /**
+        * Get all resource files from modules that are an instance of
+        * ResourceLoaderFileModule (or one of its subclasses).
+        *
+        * Since the raw data is stored in protected properties, we have to
+        * overrride this through ReflectionObject methods.
+        */
+       public static function provideResourceFiles() {
+               $data = self::getAllModules();
+               $cases = array();
+
                // See also ResourceLoaderFileModule::__construct
                $filePathProps = array(
                        // Lists of file paths
@@ -65,8 +136,7 @@ class ResourcesTest extends MediaWikiTestCase {
                        ),
                );
 
-               foreach ( $rl->getModuleNames() as $moduleName ) {
-                       $module = $rl->getModule( $moduleName );
+               foreach ( $data['modules'] as $moduleName => $module ) {
                        if ( !$module instanceof ResourceLoaderFileModule ) {
                                continue;
                        }
@@ -117,15 +187,12 @@ class ResourcesTest extends MediaWikiTestCase {
                        foreach ( $files as $file ) {
                                $cases[] = array(
                                        $method->invoke( $module, $file ),
-                                       $module->getName(),
+                                       $moduleName,
                                        $file,
                                );
                        }
                }
 
-               // Restore settings
-               $wgEnableJavaScriptTest = $live_wgEnableJavaScriptTest;
-
                return $cases;
        }
 }
index c874375..01fedc8 100644 (file)
@@ -19,6 +19,7 @@ return array(
                        'tests/qunit/suites/resources/jquery/jquery.localize.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js',
+                       'tests/qunit/suites/resources/jquery/jquery.placeholder.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.textSelection.test.js',
@@ -49,6 +50,7 @@ return array(
                        'jquery.localize',
                        'jquery.makeCollapsible',
                        'jquery.mwExtension',
+                       'jquery.placeholder',
                        'jquery.tabIndex',
                        'jquery.tablesorter',
                        'jquery.textSelection',
index 6da56ed..3c508d4 100644 (file)
                $toggle.trigger( 'click' );
        } );
 
+       function tableWithCaptionTest( $collapsible, assert ) {
+               var $caption, $headerRow, $contentRow, $toggle;
+
+               $caption = $collapsible.find( 'caption' );
+               $headerRow = $collapsible.find( 'tr:first' );
+               $contentRow = $collapsible.find( 'tr:last' );
+
+               $toggle = $caption.find( '.mw-collapsible-toggle' );
+               assert.equal( $toggle.length, 1, 'toggle is added to the end of the caption' );
+
+               assert.assertTrue( $caption.is( ':visible' ), 'caption is visible' );
+               assert.assertTrue( $headerRow.is( ':visible' ), 'headerRow is visible' );
+               assert.assertTrue( $contentRow.is( ':visible' ), 'contentRow is visible' );
+
+               $collapsible.on( 'afterCollapse.mw-collapsible', function () {
+                       assert.assertTrue( $caption.is( ':visible' ), 'after collapsing: caption is still visible' );
+                       assert.assertTrue( $headerRow.is( ':hidden' ), 'after collapsing: headerRow is hidden' );
+                       assert.assertTrue( $contentRow.is( ':hidden' ), 'after collapsing: contentRow is hidden' );
+
+                       $collapsible.on( 'afterExpand.mw-collapsible', function () {
+                               assert.assertTrue( $caption.is( ':visible' ), 'after expanding: caption is still visible' );
+                               assert.assertTrue( $headerRow.is( ':visible' ), 'after expanding: headerRow is visible' );
+                               assert.assertTrue( $contentRow.is( ':visible' ), 'after expanding: contentRow is visible' );
+                               QUnit.start();
+                       } );
+
+                       $toggle.trigger( 'click' );
+               } );
+
+               $toggle.trigger( 'click' );
+       }
+
+       QUnit.asyncTest( 'basic operation (<table> with caption)', 10, function ( assert ) {
+               tableWithCaptionTest( prepareCollapsible(
+                       '<table class="mw-collapsible">' +
+                               '<caption>' + loremIpsum + '</caption>' +
+                               '<tr><th>' + loremIpsum + '</th><th>' + loremIpsum + '</th></tr>' +
+                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                       '</table>'
+               ), assert );
+       } );
+
+       QUnit.asyncTest( 'basic operation (<table> with caption and <thead>)', 10, function ( assert ) {
+               tableWithCaptionTest( prepareCollapsible(
+                       '<table class="mw-collapsible">' +
+                               '<caption>' + loremIpsum + '</caption>' +
+                               '<thead><tr><th>' + loremIpsum + '</th><th>' + loremIpsum + '</th></tr></thead>' +
+                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                       '</table>'
+               ), assert );
+       } );
+
        function listTest( listType, assert ) {
                var $collapsible, $toggleItem, $contentItem, $toggle;
                $collapsible = prepareCollapsible(
diff --git a/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js b/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
new file mode 100644 (file)
index 0000000..ca0ea67
--- /dev/null
@@ -0,0 +1,145 @@
+(function($) {
+
+       QUnit.module('jquery.placeholder', QUnit.newMwEnvironment());
+
+       QUnit.test('caches results of feature tests', 2, function(assert) {
+               assert.strictEqual(typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input');
+               assert.strictEqual(typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea');
+       });
+
+       if ($.fn.placeholder.input && $.fn.placeholder.textarea) {
+               return;
+       }
+
+       var html = '<form>' +
+                       '<input id="input-type-search" type="search" placeholder="Search this site...">' +
+                       '<input id="input-type-text" type="text" placeholder="e.g. John Doe">' +
+                       '<input id="input-type-email" type="email" placeholder="e.g. address@example.ext">' +
+                       '<input id="input-type-url" type="url" placeholder="e.g. http://mathiasbynens.be/">' +
+                       '<input id="input-type-tel" type="tel" placeholder="e.g. +32 472 77 69 88">' +
+                       '<input id="input-type-password" type="password" placeholder="e.g. hunter2">' +
+                       '<textarea id="textarea" name="message" placeholder="Your message goes here"></textarea>' +
+               '</form>',
+       testElement = function($el, assert) {
+
+               var el = $el[0],
+                       placeholder = el.getAttribute('placeholder');
+
+               assert.strictEqual($el.placeholder(), $el, 'should be chainable');
+
+               assert.strictEqual(el.value, placeholder, 'should set `placeholder` text as `value`');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok($el.hasClass('placeholder'), 'should have `placeholder` class');
+
+               // test on focus
+               $el.focus();
+               assert.strictEqual(el.value, '', '`value` should be the empty string on focus');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok(!$el.hasClass('placeholder'), 'should not have `placeholder` class on focus');
+
+               // and unfocus (blur) again
+               $el.blur();
+
+               assert.strictEqual(el.value, placeholder, 'should set `placeholder` text as `value`');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok($el.hasClass('placeholder'), 'should have `placeholder` class');
+
+               // change the value
+               $el.val('lorem ipsum');
+               assert.strictEqual($el.prop('value'), 'lorem ipsum', '`$el.val(string)` should change the `value` property');
+               assert.strictEqual(el.value, 'lorem ipsum', '`$el.val(string)` should change the `value` attribute');
+               assert.ok(!$el.hasClass('placeholder'), '`$el.val(string)` should remove `placeholder` class');
+
+               // and clear it again
+               $el.val('');
+               assert.strictEqual($el.prop('value'), '', '`$el.val("")` should change the `value` property');
+               assert.strictEqual(el.value, placeholder, '`$el.val("")` should change the `value` attribute');
+               assert.ok($el.hasClass('placeholder'), '`$el.val("")` should re-enable `placeholder` class');
+
+               // make sure the placeholder property works as expected.
+               assert.strictEqual($el.prop('placeholder'), placeholder, '$el.prop(`placeholder`) should return the placeholder value');
+               $el.placeholder('new placeholder');
+               assert.strictEqual(el.getAttribute('placeholder'), 'new placeholder', '$el.placeholder(<string>) should set the placeholder value');
+               assert.strictEqual(el.value, 'new placeholder', '$el.placeholder(<string>) should update the displayed placeholder value');
+               $el.placeholder(placeholder);
+       };
+
+       QUnit.test('emulates placeholder for <input type=text>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#input-type-text'), assert);
+       });
+
+       QUnit.test('emulates placeholder for <input type=search>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#input-type-search'), assert);
+       });
+
+       QUnit.test('emulates placeholder for <input type=email>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#input-type-email'), assert);
+       });
+
+       QUnit.test('emulates placeholder for <input type=url>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#input-type-url'), assert);
+       });
+
+       QUnit.test('emulates placeholder for <input type=tel>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#input-type-tel'), assert);
+       });
+
+       QUnit.test('emulates placeholder for <input type=password>', 13, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+
+               var selector = '#input-type-password',
+                       $el = $(selector),
+                       el = $el[0],
+                       placeholder = el.getAttribute('placeholder');
+
+               assert.strictEqual($el.placeholder(), $el, 'should be chainable');
+
+               // Re-select the element, as it gets replaced by another one in some browsers
+               $el = $(selector);
+               el = $el[0];
+
+               assert.strictEqual(el.value, placeholder, 'should set `placeholder` text as `value`');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok($el.hasClass('placeholder'), 'should have `placeholder` class');
+
+               // test on focus
+               $el.focus();
+
+               // Re-select the element, as it gets replaced by another one in some browsers
+               $el = $(selector);
+               el = $el[0];
+
+               assert.strictEqual(el.value, '', '`value` should be the empty string on focus');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok(!$el.hasClass('placeholder'), 'should not have `placeholder` class on focus');
+
+               // and unfocus (blur) again
+               $el.blur();
+
+               // Re-select the element, as it gets replaced by another one in some browsers
+               $el = $(selector);
+               el = $el[0];
+
+               assert.strictEqual(el.value, placeholder, 'should set `placeholder` text as `value`');
+               assert.strictEqual($el.prop('value'), '', 'propHooks works properly');
+               assert.strictEqual($el.val(), '', 'valHooks works properly');
+               assert.ok($el.hasClass('placeholder'), 'should have `placeholder` class');
+
+       });
+
+       QUnit.test('emulates placeholder for <textarea></textarea>', 22, function(assert) {
+               $('<div>').html(html).appendTo($('#qunit-fixture'));
+               testElement($('#textarea'), assert);
+       });
+
+}(jQuery));
index ba15fba..cb0bf69 100644 (file)
 
        } );
 
-       QUnit.test( 'getUrl', 2, function ( assert ) {
+       QUnit.test( 'getUrl', 3, function ( assert ) {
                var title;
 
                // Config
                mw.config.set( 'wgArticlePath', '/wiki/$1' );
 
                title = new mw.Title( 'Foobar' );
-               assert.equal( title.getUrl(), '/wiki/Foobar', 'Basic functionally, toString passing to wikiGetlink' );
+               assert.equal( title.getUrl(), '/wiki/Foobar', 'Basic functionality, getUrl uses mw.util.getUrl' );
+               assert.equal( title.getUrl({ action: 'edit' }), '/wiki/Foobar?action=edit', 'Basic functionality, \'params\' parameter' );
 
                title = new mw.Title( 'John Doe', 3 );
                assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' );
        } );
 
-       QUnit.test( 'newFromImg', 28, function ( assert ) {
+       QUnit.test( 'newFromImg', 40, function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
+                               {
+                                       url: '//upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Princess_Alexandra_of_Denmark_%28later_Queen_Alexandra%2C_wife_of_Edward_VII%29_with_her_two_eldest_sons%2C_Prince_Albert_Victor_%28Eddy%29_and_George_Frederick_Ernest_Albert_%28later_George_V%29.jpg/939px-thumbnail.jpg',
+                                       typeOfUrl: 'Hashed thumb with shortened path',
+                                       nameText: 'Princess Alexandra of Denmark (later Queen Alexandra, wife of Edward VII) with her two eldest sons, Prince Albert Victor (Eddy) and George Frederick Ernest Albert (later George V)',
+                                       prefixedText: 'File:Princess Alexandra of Denmark (later Queen Alexandra, wife of Edward VII) with her two eldest sons, Prince Albert Victor (Eddy) and George Frederick Ernest Albert (later George V).jpg'
+                               },
                                {
                                        url: '/wiki/images/thumb/9/91/Anticlockwise_heliotrope%27s.jpg/99px-Anticlockwise_heliotrope%27s.jpg',
                                        typeOfUrl: 'Normal hashed directory thumbnail',
                                        prefixedText: 'File:Anticlockwise heliotrope\'s.jpg'
                                },
 
+                               {
+                                       url: '/wiki/images/thumb/8/80/Wikipedia-logo-v2.svg/langde-150px-Wikipedia-logo-v2.svg.png',
+                                       typeOfUrl: 'Normal hashed directory thumbnail with complex thumbnail parameters',
+                                       nameText: 'Wikipedia-logo-v2',
+                                       prefixedText: 'File:Wikipedia-logo-v2.svg'
+                               },
+
                                {
                                        url: '//upload.wikimedia.org/wikipedia/commons/thumb/8/80/Wikipedia-logo-v2.svg/150px-Wikipedia-logo-v2.svg.png',
                                        typeOfUrl: 'Commons thumbnail',
                                        prefixedText: 'File:Wikipedia-logo-v2.svg'
                                },
 
+                               {
+                                       url: '/wikipedia/commons/thumb/Wikipedia-logo-v2.svg/langde-150px-Wikipedia-logo-v2.svg.png',
+                                       typeOfUrl: 'Commons unhashed thumbnail with complex thumbnail parameters',
+                                       nameText: 'Wikipedia-logo-v2',
+                                       prefixedText: 'File:Wikipedia-logo-v2.svg'
+                               },
+
                                {
                                        url: '/wiki/images/Anticlockwise_heliotrope%27s.jpg',
                                        typeOfUrl: 'Unhashed local file',
index e0e823d..90cd546 100644 (file)
@@ -554,7 +554,7 @@ QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
                                return;
                        }
                        mw.messages.set(test.message );
-                       mw.config.set( 'wgUserLanguage', test.lang ) ;
+                       mw.config.set( 'wgUserLanguage', test.lang );
                        var parser = new mw.jqueryMsg.parser( { language: langClass } );
                        assert.equal(
                                parser.parse( test.integer ? 'formatnum-msg-int' : 'formatnum-msg',
@@ -585,7 +585,7 @@ QUnit.test( 'HTML', 26, function ( assert ) {
 
        assert.htmlEqual(
                formatParse( 'jquerymsg-italics-with-link' ),
-               'An <i>italicized <a title="link" href="' + mw.html.escape( mw.util.wikiGetlink( 'link' ) ) + '">wiki-link</i>',
+               'An <i>italicized <a title="link" href="' + mw.html.escape( mw.util.getUrl( 'link' ) ) + '">wiki-link</i>',
                'Italics with link inside in parse mode'
        );
 
@@ -625,7 +625,7 @@ QUnit.test( 'HTML', 26, function ( assert ) {
        mw.messages.set( 'jquerymsg-script-link-msg', '<script>[[Foo|bar]]</script>' );
        assert.htmlEqual(
                formatParse( 'jquerymsg-script-link-msg' ),
-               '&lt;script&gt;<a title="Foo" href="' + mw.html.escape( mw.util.wikiGetlink( 'Foo' ) ) + '">bar</a>&lt;/script&gt;',
+               '&lt;script&gt;<a title="Foo" href="' + mw.html.escape( mw.util.getUrl( 'Foo' ) ) + '">bar</a>&lt;/script&gt;',
                'Script tag text is escaped because that element is not allowed, but link inside is still HTML'
        );
 
index 502b55b..594ae25 100644 (file)
@@ -43,7 +43,7 @@
                assert.strictEqual( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
        } );
 
-       QUnit.test( 'mw.Map', 27, function ( assert ) {
+       QUnit.test( 'mw.Map', 28, function ( assert ) {
                var arry, conf, funky, globalConf, nummy, someValues;
 
                conf = new mw.Map();
                        'lorem': 'ipsum'
                }, 'Map.get returns multiple values correctly as an object' );
 
+               assert.deepEqual( conf, new mw.Map( conf.values ), 'new mw.Map maps over existing values-bearing object' );
+
                assert.deepEqual( conf.get( ['foo', 'notExist'] ), {
                        'foo': 'bar',
                        'notExist': null
                );
                assert.htmlEqual(
                        mw.message( 'mediawiki-italics-with-link' ).parse(),
-                       'An <i>italicized <a title="link" href="' + mw.util.wikiGetlink( 'link' ) + '">wiki-link</i>',
+                       'An <i>italicized <a title="link" href="' + mw.util.getUrl( 'link' ) + '">wiki-link</i>',
                        'Italics with link inside in parse mode'
                );
 
index 96be3d1..f422bc1 100644 (file)
                } );
        } );
 
-       QUnit.asyncTest( 'getRights', 1, function ( assert ) {
+       QUnit.test( 'getRights', 2, function ( assert ) {
+               QUnit.stop();
+               QUnit.stop();
+
                mw.user.getRights( function ( rights ) {
                        assert.equal( $.type( rights ), 'array', 'Callback gets an array' );
                        QUnit.start();
                } );
+
+               mw.user.getRights().done( function ( rights ) {
+                       assert.equal( $.type( rights ), 'array', 'Using promise interface instead of callback' );
+                       QUnit.start();
+               } );
        } );
 }( mediaWiki, jQuery ) );
index 08adb93..9216f0a 100644 (file)
                assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
        } );
 
-       QUnit.test( 'wikiGetlink', 4, function ( assert ) {
+       QUnit.test( 'getUrl', 4, function ( assert ) {
                // Not part of startUp module
                mw.config.set( 'wgArticlePath', '/wiki/$1' );
                mw.config.set( 'wgPageName', 'Foobar' );
 
-               var href = mw.util.wikiGetlink( 'Sandbox' );
+               var href = mw.util.getUrl( 'Sandbox' );
                assert.equal( href, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
 
-               href = mw.util.wikiGetlink( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
+               href = mw.util.getUrl( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
                assert.equal( href, '/wiki/Foo:Sandbox_%3F_5%2B5%3D10_%21_%28test%29/subpage',
                        'Advanced title; Get link for "Foo:Sandbox ? 5+5=10 ! (test)/subpage"' );
 
-               href = mw.util.wikiGetlink();
+               href = mw.util.getUrl();
                assert.equal( href, '/wiki/Foobar', 'Default title; Get link for current page ("Foobar")' );
 
-               href = mw.util.wikiGetlink( 'Sandbox', { action: 'edit' } );
+               href = mw.util.getUrl( 'Sandbox', { action: 'edit' } );
                assert.equal( href, '/wiki/Sandbox?action=edit',
                        'Simple title with query string; Get link for "Sandbox" with action=edit' );
        } );
         * Previously, test elements where invisible to the selector since only
         * one element can have a given id.
         */
-       QUnit.test( 'addPortletLink', 11, function ( assert ) {
-               var pTestTb, pCustom, vectorTabs, tbRL, cuQuux, $cuQuux, tbMW, $tbMW, tbRLDM, caFoo, addedAfter;
+       QUnit.test( 'addPortletLink', 13, function ( assert ) {
+               var pTestTb, pCustom, vectorTabs, tbRL, cuQuux, $cuQuux, tbMW, $tbMW, tbRLDM, caFoo,
+                       addedAfter, tbRLDMnonexistentid, tbRLDMemptyjquery;
 
                pTestTb = '\
                <div class="portlet" id="p-test-tb">\
 
                addedAfter = mw.util.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL ) );
                assert.strictEqual( $( addedAfter ).next()[0], tbRL, 'Link is in the correct position (by passing a jQuery object as nextnode)' );
+
+               // test case - nonexistent id as next node
+               tbRLDMnonexistentid = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
+                       'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
+
+               assert.equal( tbRLDMnonexistentid, $( '#p-test-tb li:last' )[0], 'Nonexistent id as nextnode adds the portlet at end' );
+
+               // test case - empty jquery object as next node
+               tbRLDMemptyjquery = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
+                       'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
+
+               assert.equal( tbRLDMemptyjquery, $( '#p-test-tb li:last' )[0], 'Empty jquery as nextnode adds the portlet at end' );
        } );
 
        QUnit.test( 'jsMessage', 1, function ( assert ) {
index 88e5885..f4433f4 100644 (file)
@@ -527,7 +527,6 @@ class TestFileIterator implements Iterator {
                return false;
        }
 
-
        /**
         * Clear section name and its data
         */
index 913adc1..ad5239e 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -107,6 +107,15 @@ function wfStreamThumb( array $params ) {
 
        $fileName = isset( $params['f'] ) ? $params['f'] : '';
 
+       // Backwards compatibility parameters
+       if ( isset( $params['w'] ) ) {
+               $params['width'] = $params['w'];
+               unset( $params['w'] );
+       }
+       if ( isset( $params['p'] ) ) {
+               $params['page'] = $params['p'];
+       }
+
        // Is this a thumb of an archived file?
        $isOld = ( isset( $params['archived'] ) && $params['archived'] );
        unset( $params['archived'] ); // handlers don't care
@@ -171,7 +180,6 @@ function wfStreamThumb( array $params ) {
                return;
        }
 
-
        // Check the source file storage path
        if ( !$img->exists() ) {
                $redirectedLocation = false;
@@ -235,18 +243,9 @@ function wfStreamThumb( array $params ) {
                }
        }
 
-       // Backwards compatibility parameters
-       if ( isset( $params['w'] ) ) {
-               $params['width'] = $params['w'];
-               unset( $params['w'] );
-       }
-       if ( isset( $params['p'] ) ) {
-               $params['page'] = $params['p'];
-       }
        unset( $params['r'] ); // ignore 'r' because we unconditionally pass File::RENDER
        unset( $params['f'] ); // We're done with 'f' parameter.
 
-
        // Get the normalized thumbnail name from the parameters...
        try {
                $thumbName = $img->thumbName( $params );